Skip to content

Commit 1ab4a85

Browse files
committed
Add an example for extending the parser.
1 parent ddf0471 commit 1ab4a85

File tree

5 files changed

+50
-6
lines changed

5 files changed

+50
-6
lines changed

‎docs/css3.rst‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ can be used to serialize a selector back to an Unicode string.
1616
... 'div.error, #root > section:first-letter{color: red }')
1717
>>> selector_string = stylesheet.rules[0].selector.as_css()
1818
>>> selector_string
19-
u'div.error, #root > section:first-letter'
19+
'div.error, #root > section:first-letter'
2020

2121
This string can be parsed by cssselect_. The parsed objects have information
2222
about pseudo-elements and selector specificity.
@@ -28,15 +28,15 @@ about pseudo-elements and selector specificity.
2828
>>> [s.specificity() for s in selectors]
2929
[(0, 1, 1), (1, 0, 2)]
3030
>>> [s.pseudo_element for s in selectors]
31-
[None, u'first-letter']
31+
[None, 'first-letter']
3232

3333
These objects can in turn be translated to XPath expressions. Note that
3434
the translation ignores pseudo-elements, you have to account for them
3535
somehow or reject selectors with pseudo-elements.
3636

3737
>>> xpath = cssselect.HTMLTranslator().selector_to_xpath(selectors[1])
3838
>>> xpath
39-
u"descendant-or-self::*[@id = 'root']/section"
39+
"descendant-or-self::*[@id = 'root']/section"
4040

4141
Finally, the XPath expressions can be used with lxml_ to find the matching
4242
elements.

‎docs/extending.rst‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,48 @@ and send a pull request: see :ref:`hacking`.
1717

1818
.. currentmodule:: tinycss.css21
1919

20+
Example: star hack
21+
------------------
22+
23+
.. _star hack: https://en.wikipedia.org/wiki/CSS_filter#Star_hack
24+
25+
The `star hack`_ uses invalid declarations that are only parsed by some
26+
versions of Internet Explorer. By default, tinycss ignores invalid
27+
declarations and logs an error.
28+
29+
>>> from tinycss.css21 import CSS21Parser
30+
>>> css ='#elem{width: [W3C Model Width]; *width: [BorderBox Model]}'
31+
>>> stylesheet = CSS21Parser().parse_stylesheet(css)
32+
>>> stylesheet.errors
33+
[ParseError('Parse error at 1:35, expected a property name, got DELIM',)]
34+
>>> [decl.name for decl in stylesheet.rules[0].declarations]
35+
['width']
36+
37+
If for example a minifier based on tinycss wants to support the star hack,
38+
it can by extending the parser::
39+
40+
>>> class CSSStarHackParser(CSS21Parser):
41+
... def parse_declaration(self, tokens):
42+
... has_star_hack = (tokens[0].type == 'DELIM' and tokens[0].value == '*')
43+
... if has_star_hack:
44+
... tokens = tokens[1:]
45+
... declaration = super(CSSStarHackParser, self).parse_declaration(tokens)
46+
... declaration.has_star_hack = has_star_hack
47+
... return declaration
48+
...
49+
>>> stylesheet = CSSStarHackParser().parse_stylesheet(css)
50+
>>> stylesheet.errors
51+
[]
52+
>>> [(d.name, d.has_star_hack) for d in stylesheet.rules[0].declarations]
53+
[('width', False), ('width', True)]
54+
55+
This class extends the :meth:`~CSS21Parser.parse_declaration` method.
56+
It removes any ``*`` delimeter :class:`~.token_data.Token` at the start of
57+
a declaration, and adds a ``has_star_hack`` boolean attribute on parsed
58+
:class:`Declaration` objects: ``True`` if a ``*`` was removed, ``False`` for
59+
“normal” declarations.
60+
61+
2062
Parser methods
2163
--------------
2264

‎docs/parsing.rst‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ and parse a stylesheet:
1717
... p.error{color: red } @lorem-ipsum;
1818
... @page tables{size: landscape }''')
1919
>>> stylesheet.rules
20-
[<ImportRule 1:1 foo.css>, <RuleSet at 2:5 p.error>, <PageRule 3:5 (u'tables', None)>]
20+
[<ImportRule 1:1 foo.css>, <RuleSet at 2:5 p.error>, <PageRule 3:5 ('tables', None)>]
2121
>>> stylesheet.errors
22-
[ParseError(u'Parse error at 2:29, unknown at-rule in stylesheet context: @lorem-ipsum',)]
22+
[ParseError('Parse error at 2:29, unknown at-rule in stylesheet context: @lorem-ipsum',)]
2323

2424
You’ll get a :class:`~tinycss.css21.Stylesheet` object which contains
2525
all the parsed content as well as a list of encountered errors.

‎tinycss/css21.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ def __init__(self, name, value, priority, line, column):
180180
def__repr__(self):
181181
priority=' !'+self.priorityifself.priorityelse''
182182
return ('<{0.__class__.__name__}{0.line}:{0.column}'
183-
'{0.name}:{0.value.as_css}{1}>'.format(self, priority))
183+
'{0.name}:{1}{2}>'.format(
184+
self, self.value.as_css(), priority))
184185

185186

186187
classPageRule(object):

‎tox.ini‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ commands = py.test --pyargs tinycss []
1010
setenv = TINYCSS_SKIP_SPEEDUPS_TESTS=1
1111

1212
[testenv:sphinx-doctests]
13+
basepython = python3
1314
deps =
1415
Sphinx
1516
cssselect

0 commit comments

Comments
(0)