|
101 | 101 | CSS_ESCAPES = fr'(?:\\(?:[a-f0-9]{{1,6}}{WS}?|[^\r\n\f]|$))'
|
102 | 102 | CSS_STRING_ESCAPES = fr'(?:\\(?:[a-f0-9]{{1,6}}{WS}?|[^\r\n\f]|$|{NEWLINE}))'
|
103 | 103 | # CSS Identifier
|
104 |
| -IDENTIFIER = r''' |
105 |
| -(?:(?:-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{esc})+|--) |
106 |
| -(?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{esc})*) |
107 |
| -'''.format(esc=CSS_ESCAPES) |
| 104 | +IDENTIFIER = fr''' |
| 105 | +(?:(?:-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})+|--) |
| 106 | +(?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*) |
| 107 | +''' |
108 | 108 | # `nth` content
|
109 |
| -NTH = r'(?:[-+])?(?:[0-9]+n?|n)(?:(?<=n){ws}*(?:[-+]){ws}*(?:[0-9]+))?'.format(ws=WSC) |
| 109 | +NTH = fr'(?:[-+])?(?:[0-9]+n?|n)(?:(?<=n){WSC}*(?:[-+]){WSC}*(?:[0-9]+))?' |
110 | 110 | # Value: quoted string or identifier
|
111 |
| -VALUE = r''' |
112 |
| -(?:"(?:\\(?:.|{nl})|[^\\"\r\n\f]+)*?"|'(?:\\(?:.|{nl})|[^\\'\r\n\f]+)*?'|{ident}+) |
113 |
| -'''.format(nl=NEWLINE, ident=IDENTIFIER) |
| 111 | +VALUE = fr'''(?:"(?:\\(?:.|{NEWLINE})|[^\\"\r\n\f]+)*?"|'(?:\\(?:.|{NEWLINE})|[^\\'\r\n\f]+)*?'|{IDENTIFIER}+)''' |
114 | 112 | # Attribute value comparison. `!=` is handled special as it is non-standard.
|
115 |
| -ATTR = r''' |
116 |
| -(?:{ws}*(?P<cmp>[!~^|*$]?=){ws}*(?P<value>{value})(?:{ws}*(?P<case>[is]))?)?{ws}*\] |
117 |
| -'''.format(ws=WSC, value=VALUE) |
| 113 | +ATTR = fr'(?:{WSC}*(?P<cmp>[!~^|*$]?=){WSC}*(?P<value>{VALUE})(?:{WSC}*(?P<case>[is]))?)?{WSC}*\]' |
118 | 114 |
|
119 | 115 | # Selector patterns
|
120 | 116 | # IDs (`#id`)
|
121 | 117 | PAT_ID = fr'\#{IDENTIFIER}'
|
122 | 118 | # Classes (`.class`)
|
123 | 119 | PAT_CLASS = fr'\.{IDENTIFIER}'
|
124 | 120 | # Prefix:Tag (`prefix|tag`)
|
125 |
| -PAT_TAG = r'(?P<tag_ns>(?:{ident}|\*)?\|)?(?P<tag_name>{ident}|\*)'.format(ident=IDENTIFIER) |
| 121 | +PAT_TAG = fr'(?P<tag_ns>(?:{IDENTIFIER}|\*)?\|)?(?P<tag_name>{IDENTIFIER}|\*)' |
126 | 122 | # Attributes (`[attr]`, `[attr=value]`, etc.)
|
127 |
| -PAT_ATTR = r''' |
128 |
| -\[{ws}*(?P<attr_ns>(?:{ident}|\*)?\|)?(?P<attr_name>{ident}){attr} |
129 |
| -'''.format(ws=WSC, ident=IDENTIFIER, attr=ATTR) |
| 123 | +PAT_ATTR = fr'\[{WSC}*(?P<attr_ns>(?:{IDENTIFIER}|\*)?\|)?(?P<attr_name>{IDENTIFIER}){ATTR}' |
130 | 124 | # Pseudo class (`:pseudo-class`, `:pseudo-class(`)
|
131 | 125 | PAT_PSEUDO_CLASS = fr'(?P<name>:{IDENTIFIER})(?P<open>\({WSC}*)?'
|
132 | 126 | # Pseudo class special patterns. Matches `:pseudo-class(` for special case pseudo classes.
|
|
140 | 134 | # At rule (`@page`, etc.) (not supported)
|
141 | 135 | PAT_AT_RULE = fr'@P{IDENTIFIER}'
|
142 | 136 | # Pseudo class `nth-child` (`:nth-child(an+b [of S]?)`, `:first-child`, etc.)
|
143 |
| -PAT_PSEUDO_NTH_CHILD = r''' |
144 |
| -(?P<pseudo_nth_child>{name} |
145 |
| -(?P<nth_child>{nth}|even|odd))(?:{wsc}*\)|(?P<of>{comments}*{ws}{wsc}*of{comments}*{ws}{wsc}*)) |
146 |
| -'''.format(name=PAT_PSEUDO_CLASS_SPECIAL, wsc=WSC, comments=COMMENTS, ws=WS, nth=NTH) |
| 137 | +PAT_PSEUDO_NTH_CHILD = fr''' |
| 138 | +(?P<pseudo_nth_child>{PAT_PSEUDO_CLASS_SPECIAL} |
| 139 | +(?P<nth_child>{NTH}|even|odd))(?:{WSC}*\)|(?P<of>{COMMENTS}*{WS}{WSC}*of{COMMENTS}*{WS}{WSC}*)) |
| 140 | +''' |
147 | 141 | # Pseudo class `nth-of-type` (`:nth-of-type(an+b)`, `:first-of-type`, etc.)
|
148 |
| -PAT_PSEUDO_NTH_TYPE = r''' |
149 |
| -(?P<pseudo_nth_type>{name} |
150 |
| -(?P<nth_type>{nth}|even|odd)){ws}*\) |
151 |
| -'''.format(name=PAT_PSEUDO_CLASS_SPECIAL, ws=WSC, nth=NTH) |
| 142 | +PAT_PSEUDO_NTH_TYPE = fr''' |
| 143 | +(?P<pseudo_nth_type>{PAT_PSEUDO_CLASS_SPECIAL} |
| 144 | +(?P<nth_type>{NTH}|even|odd)){WSC}*\) |
| 145 | +''' |
152 | 146 | # Pseudo class language (`:lang("*-de", en)`)
|
153 |
| -PAT_PSEUDO_LANG = r'{name}(?P<values>{value}(?:{ws}*,{ws}*{value})*){ws}*\)'.format( |
154 |
| - name=PAT_PSEUDO_CLASS_SPECIAL, ws=WSC, value=VALUE |
155 |
| -) |
| 147 | +PAT_PSEUDO_LANG = fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*,{WSC}*{VALUE})*){WSC}*\)' |
156 | 148 | # Pseudo class direction (`:dir(ltr)`)
|
157 | 149 | PAT_PSEUDO_DIR = fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<dir>ltr|rtl){WSC}*\)'
|
158 | 150 | # Combining characters (`>`, `~`, ` `, `+`, `,`)
|
159 |
| -PAT_COMBINE = r'{wsc}*?(?P<relation>[,+>~]|{ws}(?![,+>~])){wsc}*'.format(ws=WS, wsc=WSC) |
| 151 | +PAT_COMBINE = fr'{WSC}*?(?P<relation>[,+>~]|{WS}(?![,+>~])){WSC}*' |
160 | 152 | # Extra: Contains (`:contains(text)`)
|
161 |
| -PAT_PSEUDO_CONTAINS = r'{name}(?P<values>{value}(?:{ws}*,{ws}*{value})*){ws}*\)'.format( |
162 |
| - name=PAT_PSEUDO_CLASS_SPECIAL, ws=WSC, value=VALUE |
163 |
| -) |
| 153 | +PAT_PSEUDO_CONTAINS = fr'{PAT_PSEUDO_CLASS_SPECIAL}(?P<values>{VALUE}(?:{WSC}*,{WSC}*{VALUE})*){WSC}*\)' |
164 | 154 |
|
165 | 155 | # Regular expressions
|
166 | 156 | # CSS escape pattern
|
167 | 157 | RE_CSS_ESC = re.compile(fr'(?:(\\[a-f0-9]{{1,6}}{WSC}?)|(\\[^\r\n\f])|(\\$))', re.I)
|
168 |
| -RE_CSS_STR_ESC = re.compile( |
169 |
| - fr'(?:(\\[a-f0-9]{{1,6}}{WS}?)|(\\[^\r\n\f])|(\\$)|(\\{NEWLINE}))', re.I |
170 |
| -) |
| 158 | +RE_CSS_STR_ESC = re.compile(fr'(?:(\\[a-f0-9]{{1,6}}{WS}?)|(\\[^\r\n\f])|(\\$)|(\\{NEWLINE}))', re.I) |
171 | 159 | # Pattern to break up `nth` specifiers
|
172 |
| -RE_NTH = re.compile( |
173 |
| - r'(?P<s1>[-+])?(?P<a>[0-9]+n?|n)(?:(?<=n){ws}*(?P<s2>[-+]){ws}*(?P<b>[0-9]+))?'.format(ws=WSC), |
174 |
| - re.I |
175 |
| -) |
| 160 | +RE_NTH = re.compile(fr'(?P<s1>[-+])?(?P<a>[0-9]+n?|n)(?:(?<=n){WSC}*(?P<s2>[-+]){WSC}*(?P<b>[0-9]+))?', re.I) |
176 | 161 | # Pattern to iterate multiple values.
|
177 |
| -RE_VALUES = re.compile(r'(?:(?P<value>{value})|(?P<split>{ws}*,{ws}*))'.format(ws=WSC, value=VALUE), re.X) |
| 162 | +RE_VALUES = re.compile(fr'(?:(?P<value>{VALUE})|(?P<split>{WSC}*,{WSC}*))', re.X) |
178 | 163 | # Whitespace checks
|
179 | 164 | RE_WS = re.compile(WS)
|
180 |
| -RE_WS_BEGIN = re.compile(f'^{WSC}*') |
181 |
| -RE_WS_END = re.compile(f'{WSC}*$') |
| 165 | +RE_WS_BEGIN = re.compile(fr'^{WSC}*') |
| 166 | +RE_WS_END = re.compile(fr'{WSC}*$') |
182 | 167 | RE_CUSTOM = re.compile(fr'^{PAT_PSEUDO_CLASS_CUSTOM}$', re.X)
|
183 | 168 |
|
184 | 169 | # Constants
|
@@ -419,11 +404,10 @@ def __str__(self) -> str: # pragma: no cover
|
419 | 404 | """String representation."""
|
420 | 405 |
|
421 | 406 | return (
|
422 |
| - '_Selector(tag={!r}, ids={!r}, classes={!r}, attributes={!r}, nth={!r}, selectors={!r}, ' |
423 |
| - 'relations={!r}, rel_type={!r}, contains={!r}, lang={!r}, flags={!r}, no_match={!r})' |
424 |
| - ).format( |
425 |
| - self.tag, self.ids, self.classes, self.attributes, self.nth, self.selectors, |
426 |
| - self.relations, self.rel_type, self.contains, self.lang, self.flags, self.no_match |
| 407 | + f'_Selector(tag={self.tag!r}, ids={self.ids!r}, classes={self.classes!r}, attributes={self.attributes!r}, ' |
| 408 | + f'nth={self.nth!r}, selectors={self.selectors!r}, relations={self.relations!r}, ' |
| 409 | + f'rel_type={self.rel_type!r}, contains={self.contains!r}, lang={self.lang!r}, flags={self.flags!r}, ' |
| 410 | + f'no_match={self.no_match!r})' |
427 | 411 | )
|
428 | 412 |
|
429 | 413 | __repr__ = __str__
|
|
0 commit comments