1 | /**
|
2 | * CSS Selector AST root.
|
3 | * Contains list of CSS rules (separated by a comma in the input CSS selector string).
|
4 | * Generated by {@link AstFactory.selector ast.selector}.
|
5 | */
|
6 | export interface AstSelector {
|
7 | type: 'Selector';
|
8 | /**
|
9 | * List of CSS rules. Every rule contains conditions. Selector is considered matched once at least one rule matches.
|
10 | */
|
11 | rules: AstRule[];
|
12 | }
|
13 | /**
|
14 | * A single CSS rule that contains match conditions.
|
15 | * Can nest another rule with or without a combinator (i.e. `"div > span"`).
|
16 | * Generated by {@link AstFactory.rule ast.rule}.
|
17 | */
|
18 | export interface AstRule {
|
19 | type: 'Rule';
|
20 | /** Items of a CSS rule. Can be tag, ids, class names, pseudo-classes and pseudo-elements. */
|
21 | items: (AstTagName | AstWildcardTag | AstId | AstClassName | AstAttribute | AstPseudoClass | AstPseudoElement)[];
|
22 | /** Rule combinator which was used to nest this rule (i.e. `">"` in case of `"div > span"` if the current rule is `"span"`). */
|
23 | combinator?: string;
|
24 | /** Nested rule if specified (i.e. `"div > span"`). */
|
25 | nestedRule?: AstRule;
|
26 | }
|
27 | /**
|
28 | * Named tag, i.e. `"div"`. Part of CSS Qualified Names.
|
29 | * Generated by {@link AstFactory.tagName ast.tagName}.
|
30 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors
|
31 | * @see https://drafts.csswg.org/css-namespaces-3/#css-qnames
|
32 | */
|
33 | export interface AstTagName {
|
34 | type: 'TagName';
|
35 | /** Tag name, i.e. `"div"`. */
|
36 | name: string;
|
37 | /** Namespace according to https://www.w3.org/TR/css3-namespace/. */
|
38 | namespace?: AstNamespaceName | AstWildcardNamespace | AstNoNamespace;
|
39 | }
|
40 | /**
|
41 | * ID condition. Matches by id attribute value.
|
42 | * Generated by {@link AstFactory.id ast.id}.
|
43 | * https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors
|
44 | * @example "#root"
|
45 | */
|
46 | export interface AstId {
|
47 | type: 'Id';
|
48 | /** ID name. I.e. `#root` -> `"root"`. */
|
49 | name: string;
|
50 | }
|
51 | /**
|
52 | * Class name condition. Matches by class attribute value.
|
53 | * Generated by {@link AstFactory.className ast.className}.
|
54 | * https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors
|
55 | * @example ".user"
|
56 | */
|
57 | export interface AstClassName {
|
58 | type: 'ClassName';
|
59 | /** ID name. I.e. `.user` -> `"user"`. */
|
60 | name: string;
|
61 | }
|
62 | /**
|
63 | * Wildcard tag (universal selector): `*`.
|
64 | * Generated by {@link AstFactory.wildcardTag ast.wildcardTag}.
|
65 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors
|
66 | * @see https://drafts.csswg.org/css-namespaces-3/#css-qnames
|
67 | */
|
68 | export interface AstWildcardTag {
|
69 | type: 'WildcardTag';
|
70 | /** Namespace according to https://www.w3.org/TR/css3-namespace/. */
|
71 | namespace?: AstNamespaceName | AstWildcardNamespace | AstNoNamespace;
|
72 | }
|
73 | /**
|
74 | * Named namespace declaration (i.e. `ns|div`).
|
75 | * Generated by {@link AstFactory.namespaceName ast.namespaceName}.
|
76 | * @see https://drafts.csswg.org/css-namespaces-3/#css-qnames
|
77 | */
|
78 | export interface AstNamespaceName {
|
79 | type: 'NamespaceName';
|
80 | /** Namespace name (i.e. `"ns"` in case of `"ns|div"`). "*/
|
81 | name: string;
|
82 | }
|
83 | /**
|
84 | * Wildcard namespace (universal selector): `*`.
|
85 | * Generated by {@link AstFactory.wildcardNamespace ast.wildcardNamespace}.
|
86 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors
|
87 | * @see https://drafts.csswg.org/css-namespaces-3/#css-qnames
|
88 | */
|
89 | export interface AstWildcardNamespace {
|
90 | type: 'WildcardNamespace';
|
91 | }
|
92 | /**
|
93 | * Explicit no-namespace declaration (i.e. `|div`).
|
94 | * Generated by {@link AstFactory.noNamespace ast.noNamespace}.
|
95 | * @see https://drafts.csswg.org/css-namespaces-3/#css-qnames
|
96 | */
|
97 | export interface AstNoNamespace {
|
98 | type: 'NoNamespace';
|
99 | }
|
100 | /**
|
101 | * Attribute selector.
|
102 | * Generated by {@link AstFactory.attribute ast.attribute}.
|
103 | * @example "[role='button' i]"
|
104 | */
|
105 | export interface AstAttribute {
|
106 | type: 'Attribute';
|
107 | /** Attribute name (i.e. `"href"` in case if `"[href]"`). */
|
108 | name: string;
|
109 | /** Namespace according to https://drafts.csswg.org/selectors/#attrnmsp. */
|
110 | namespace?: AstNamespaceName | AstWildcardNamespace | AstNoNamespace;
|
111 | /** Comparison operator (i.e. `"|="` in case if `"[role|=button]"`). */
|
112 | operator?: string;
|
113 | /** Comparison value (i.e. `"button"` in case if `"[role=button]"`). */
|
114 | value?: AstString | AstSubstitution;
|
115 | /** Comparison case sensitivity modifier (i.e. `"i"` in case if `"[role='button' i]"`). */
|
116 | caseSensitivityModifier?: string;
|
117 | }
|
118 | /**
|
119 | * Pseudo-class selector.
|
120 | * Generated by {@link AstFactory.pseudoClass ast.pseudoClass}.
|
121 | * @see https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements
|
122 | * @example ":lang(en)"
|
123 | */
|
124 | export interface AstPseudoClass {
|
125 | type: 'PseudoClass';
|
126 | /** Pseudo-class name (i.e. `"hover"` in case of `":hover"`). */
|
127 | name: string;
|
128 | /** Pseudo-class value (i.e. `"en"` in case of `":lang(en)"`). */
|
129 | argument?: AstSubstitution | AstSelector | AstString | AstFormula | AstFormulaOfSelector;
|
130 | }
|
131 | /**
|
132 | * Pseudo-class selector.
|
133 | * Generated by {@link AstFactory.pseudoElement ast.pseudoElement}.
|
134 | * @see https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements
|
135 | * @example "::before"
|
136 | */
|
137 | export interface AstPseudoElement {
|
138 | type: 'PseudoElement';
|
139 | /** Pseudo-element name (i.e. `"before"` in case of `"::before"`). */
|
140 | name: string;
|
141 | /** Pseudo-element value (i.e. `"foo"` in case of `"::part(foo)"`). */
|
142 | argument?: AstSubstitution | AstString | AstSelector;
|
143 | }
|
144 | /**
|
145 | * String value. Can be used as attribute value of pseudo-class string value.
|
146 | * For instance `:lang(en)` -> `{type: 'AstPseudoClass'..., argument: {type: 'String', value: 'en'}}`.
|
147 | * Generated by {@link AstFactory.string ast.string}.
|
148 | */
|
149 | export interface AstString {
|
150 | type: 'String';
|
151 | /** The actual string value. */
|
152 | value: string;
|
153 | }
|
154 | /**
|
155 | * Pseudo-class formula value. `a` is multiplier of `n` and `b` us added on top. Formula: `an + b`.
|
156 | * For instance `:nth-child(2n + 1)` -> `{type: 'AstPseudoClass'..., argument: {type: 'Formula', a: 2, b: 1}}`.
|
157 | * Generated by {@link AstFactory.formula ast.formula}.
|
158 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child#functional_notation
|
159 | */
|
160 | export interface AstFormula {
|
161 | type: 'Formula';
|
162 | /** Multiplier of `n`. */
|
163 | a: number;
|
164 | /** Constant added to `a*n`. */
|
165 | b: number;
|
166 | }
|
167 | /**
|
168 | * Pseudo-class formula of selector value. `a` is multiplier of `n` and `b` us added on top. Formula: `an + b`.
|
169 | * Formula is followed by `of` keyword and then goes a CSS selector.
|
170 | * For instance `:nth-child(2n + 1 of div)` ->
|
171 | * `{type: 'AstPseudoClass'..., argument: {type: 'FormulaOfSelector', a: 2, b: 1, selector: {type: 'Selector', rules: [{type: 'Rule', items: [{type: 'TagName', name: 'div'}]}]}}}`.
|
172 | * Generated by {@link AstFactory.formulaOfSelector ast.formulaOfSelector}.
|
173 | * @see https://developer.mozilla.org/en-US/docs/Web/CSS/:nth-child#functional_notation
|
174 | */
|
175 | export interface AstFormulaOfSelector {
|
176 | type: 'FormulaOfSelector';
|
177 | /** Multiplier of `n`. */
|
178 | a: number;
|
179 | /** Constant added to `a*n`. */
|
180 | b: number;
|
181 | /** Selector that goes after formula (i.e. `"div -> span"` in case of `":nth-child(2n + 1 of div > span)"` */
|
182 | selector: AstRule;
|
183 | }
|
184 | /**
|
185 | * Substitution is not part of CSS spec, but rather a useful extension on top of CSS if you need to pass variables.
|
186 | * Generated by {@link AstFactory.substitution ast.substitution}.
|
187 | */
|
188 | export interface AstSubstitution {
|
189 | type: 'Substitution';
|
190 | /** Substitution name (i.e. "var" in case of `"[role=$var]"` or `":lang($var)"`). */
|
191 | name: string;
|
192 | }
|
193 | /** One of pseudo-class argument types. */
|
194 | export type AstPseudoClassArgument = AstSubstitution | AstSelector | AstString | AstFormula | AstFormulaOfSelector;
|
195 | /** One of pseudo-element argument types. */
|
196 | export type AstPseudoElementArgument = AstSubstitution | AstString | AstSelector;
|
197 | /** One of CSS AST entity types. */
|
198 | export type AstEntity = AstSelector | AstRule | AstTagName | AstWildcardTag | AstId | AstClassName | AstNamespaceName | AstWildcardNamespace | AstNoNamespace | AstSubstitution | AstString | AstFormula | AstFormulaOfSelector | AstPseudoClass | AstAttribute | AstPseudoElement;
|
199 | type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never;
|
200 | type ToAstFactory<T> = UnionToIntersection<T extends {
|
201 | type: infer Type;
|
202 | } ? Type extends string ? {
|
203 | [K in Uncapitalize<Type>]: {} extends Omit<T, 'type'> ? (props?: {
|
204 | [PK in keyof Omit<T, 'type'>]: Omit<T, 'type'>[PK];
|
205 | }) => T : (props: {
|
206 | [PK in keyof Omit<T, 'type'>]: Omit<T, 'type'>[PK];
|
207 | }) => T;
|
208 | } & {
|
209 | [K in `is${Type}`]: (entity: unknown) => entity is T;
|
210 | } : never : never>;
|
211 | /** @internal */
|
212 | type AstFactoryBase = {
|
213 | [K in keyof ToAstFactory<AstEntity>]: ToAstFactory<AstEntity>[K];
|
214 | };
|
215 | /**
|
216 | * AST structure generators and matchers.
|
217 | * For instance, `ast.selector({rules: [...]})` creates AstSelector and `ast.isSelector(...)` checks if
|
218 | * AstSelector was specified.
|
219 | *
|
220 | * @example
|
221 | *
|
222 | * // Represents CSS selector: ns|div#user-34.user.user-active[role="button"]:lang(en)::before > *
|
223 | * const selector = ast.selector({
|
224 | * rules: [
|
225 | * ast.rule({
|
226 | * items: [
|
227 | * ast.tagName({name: 'div', namespace: ast.namespaceName({name: 'ns'})}),
|
228 | * ast.id({name: 'user-34'}),
|
229 | * ast.className({name: 'user'}),
|
230 | * ast.className({name: 'user-active'}),
|
231 | * ast.attribute({
|
232 | * name: 'role',
|
233 | * operator: '=',
|
234 | * value: ast.string({value: 'button'})
|
235 | * }),
|
236 | * ast.pseudoClass({
|
237 | * name: 'lang',
|
238 | * argument: ast.string({value: 'en'})
|
239 | * }),
|
240 | * ast.pseudoElement({name: 'before'})
|
241 | * ],
|
242 | * nestedRule: ast.rule({combinator: '>', items: [ast.wildcardTag()]})
|
243 | * })
|
244 | * ]
|
245 | * });
|
246 | * console.log(ast.isSelector(selector)); // prints true
|
247 | * console.log(ast.isRule(selector)); // prints false
|
248 | */
|
249 | export interface AstFactory extends AstFactoryBase {
|
250 | }
|
251 | /**
|
252 | * AST structure generators and matchers.
|
253 | * For instance, `ast.selector({rules: [...]})` creates AstSelector and `ast.isSelector(...)` checks if
|
254 | * AstSelector was specified.
|
255 | *
|
256 | * @example
|
257 | *
|
258 | * // Represents CSS selector: ns|div#user-34.user.user-active[role="button"]:lang(en)::before > *
|
259 | * const selector = ast.selector({
|
260 | * rules: [
|
261 | * ast.rule({
|
262 | * items: [
|
263 | * ast.tagName({name: 'div', namespace: ast.namespaceName({name: 'ns'})}),
|
264 | * ast.id({name: 'user-34'}),
|
265 | * ast.className({name: 'user'}),
|
266 | * ast.className({name: 'user-active'}),
|
267 | * ast.attribute({
|
268 | * name: 'role',
|
269 | * operator: '=',
|
270 | * value: ast.string({value: 'button'})
|
271 | * }),
|
272 | * ast.pseudoClass({
|
273 | * name: 'lang',
|
274 | * argument: ast.string({value: 'en'})
|
275 | * }),
|
276 | * ast.pseudoElement({name: 'before'})
|
277 | * ],
|
278 | * nestedRule: ast.rule({combinator: '>', items: [ast.wildcardTag()]})
|
279 | * })
|
280 | * ]
|
281 | * });
|
282 | * console.log(ast.isSelector(selector)); // prints true
|
283 | * console.log(ast.isRule(selector)); // prints false
|
284 | */
|
285 | export declare const ast: AstFactory;
|
286 | export {};
|