@projectwallace/css-parser 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/arena.d.ts +1 -0
- package/dist/arena.js +2 -1
- package/dist/char-types.d.ts +6 -0
- package/dist/char-types.js +1 -1
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +4 -3
- package/dist/css-node.d.ts +21 -37
- package/dist/css-node.js +43 -105
- package/dist/index.js +1 -1
- package/dist/parse-selector.js +9 -3
- package/dist/parse.js +28 -11
- package/dist/tokenize.js +70 -55
- package/package.json +3 -2
package/dist/arena.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare const SUPPORTS_QUERY = 36;
|
|
|
36
36
|
export declare const LAYER_NAME = 37;
|
|
37
37
|
export declare const PRELUDE_OPERATOR = 38;
|
|
38
38
|
export declare const FEATURE_RANGE = 39;
|
|
39
|
+
export declare const AT_RULE_PRELUDE = 40;
|
|
39
40
|
export declare const FLAG_IMPORTANT: number;
|
|
40
41
|
export declare const FLAG_HAS_ERROR: number;
|
|
41
42
|
export declare const FLAG_LENGTH_OVERFLOW: number;
|
package/dist/arena.js
CHANGED
|
@@ -37,6 +37,7 @@ const SUPPORTS_QUERY = 36;
|
|
|
37
37
|
const LAYER_NAME = 37;
|
|
38
38
|
const PRELUDE_OPERATOR = 38;
|
|
39
39
|
const FEATURE_RANGE = 39;
|
|
40
|
+
const AT_RULE_PRELUDE = 40;
|
|
40
41
|
const FLAG_IMPORTANT = 1 << 0;
|
|
41
42
|
const FLAG_HAS_ERROR = 1 << 1;
|
|
42
43
|
const FLAG_LENGTH_OVERFLOW = 1 << 2;
|
|
@@ -284,4 +285,4 @@ class CSSDataArena {
|
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
287
|
|
|
287
|
-
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, CSSDataArena, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_BROWSERHACK, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, FLAG_HAS_ERROR, FLAG_HAS_PARENS, FLAG_IMPORTANT, FLAG_LENGTH_OVERFLOW, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE };
|
|
288
|
+
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, AT_RULE_PRELUDE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, CSSDataArena, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_BROWSERHACK, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, FLAG_HAS_ERROR, FLAG_HAS_PARENS, FLAG_IMPORTANT, FLAG_LENGTH_OVERFLOW, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE };
|
package/dist/char-types.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export declare let CHAR_ALPHA: number;
|
|
2
|
+
export declare let CHAR_DIGIT: number;
|
|
3
|
+
export declare let CHAR_HEX: number;
|
|
4
|
+
export declare let CHAR_WHITESPACE: number;
|
|
5
|
+
export declare let CHAR_NEWLINE: number;
|
|
6
|
+
export declare let char_types: Uint8Array<ArrayBuffer>;
|
|
1
7
|
export declare function is_digit(ch: number): boolean;
|
|
2
8
|
export declare function is_hex_digit(ch: number): boolean;
|
|
3
9
|
export declare function is_alpha(ch: number): boolean;
|
package/dist/char-types.js
CHANGED
|
@@ -52,4 +52,4 @@ function is_ident_char(ch) {
|
|
|
52
52
|
return is_ident_start(ch) || is_digit(ch);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export { is_alpha, is_digit, is_hex_digit, is_ident_char, is_ident_start, is_newline, is_whitespace };
|
|
55
|
+
export { CHAR_ALPHA, CHAR_DIGIT, CHAR_HEX, CHAR_NEWLINE, CHAR_WHITESPACE, char_types, is_alpha, is_digit, is_hex_digit, is_ident_char, is_ident_start, is_newline, is_whitespace };
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE, FLAG_IMPORTANT, ATTR_OPERATOR_NONE, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_FLAG_NONE, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE } from './arena';
|
|
2
|
-
export { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE, FLAG_IMPORTANT, ATTR_OPERATOR_NONE, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_FLAG_NONE, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, };
|
|
1
|
+
import { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE, AT_RULE_PRELUDE, FLAG_IMPORTANT, ATTR_OPERATOR_NONE, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_FLAG_NONE, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE } from './arena';
|
|
2
|
+
export { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE, AT_RULE_PRELUDE, FLAG_IMPORTANT, ATTR_OPERATOR_NONE, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_FLAG_NONE, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, };
|
|
3
3
|
export declare const NODE_TYPES: {
|
|
4
4
|
readonly STYLESHEET: 1;
|
|
5
5
|
readonly STYLE_RULE: 2;
|
|
@@ -39,4 +39,5 @@ export declare const NODE_TYPES: {
|
|
|
39
39
|
readonly LAYER_NAME: 37;
|
|
40
40
|
readonly PRELUDE_OPERATOR: 38;
|
|
41
41
|
readonly FEATURE_RANGE: 39;
|
|
42
|
+
readonly AT_RULE_PRELUDE: 40;
|
|
42
43
|
};
|
package/dist/constants.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FEATURE_RANGE, PRELUDE_OPERATOR, LAYER_NAME, SUPPORTS_QUERY, CONTAINER_QUERY, MEDIA_TYPE, MEDIA_FEATURE, MEDIA_QUERY, LANG_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NESTING_SELECTOR, UNIVERSAL_SELECTOR, COMBINATOR, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, ATTRIBUTE_SELECTOR, ID_SELECTOR, CLASS_SELECTOR, TYPE_SELECTOR, SELECTOR_LIST, VALUE, URL, PARENTHESIS, OPERATOR, FUNCTION, HASH, STRING, DIMENSION, NUMBER, IDENTIFIER, BLOCK, COMMENT, SELECTOR, DECLARATION, AT_RULE, STYLE_RULE, STYLESHEET } from './arena.js';
|
|
1
|
+
import { AT_RULE_PRELUDE, FEATURE_RANGE, PRELUDE_OPERATOR, LAYER_NAME, SUPPORTS_QUERY, CONTAINER_QUERY, MEDIA_TYPE, MEDIA_FEATURE, MEDIA_QUERY, LANG_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NESTING_SELECTOR, UNIVERSAL_SELECTOR, COMBINATOR, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, ATTRIBUTE_SELECTOR, ID_SELECTOR, CLASS_SELECTOR, TYPE_SELECTOR, SELECTOR_LIST, VALUE, URL, PARENTHESIS, OPERATOR, FUNCTION, HASH, STRING, DIMENSION, NUMBER, IDENTIFIER, BLOCK, COMMENT, SELECTOR, DECLARATION, AT_RULE, STYLE_RULE, STYLESHEET } from './arena.js';
|
|
2
2
|
export { ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, FLAG_IMPORTANT } from './arena.js';
|
|
3
3
|
|
|
4
4
|
const NODE_TYPES = {
|
|
@@ -43,7 +43,8 @@ const NODE_TYPES = {
|
|
|
43
43
|
SUPPORTS_QUERY,
|
|
44
44
|
LAYER_NAME,
|
|
45
45
|
PRELUDE_OPERATOR,
|
|
46
|
-
FEATURE_RANGE
|
|
46
|
+
FEATURE_RANGE,
|
|
47
|
+
AT_RULE_PRELUDE
|
|
47
48
|
};
|
|
48
49
|
|
|
49
|
-
export { ATTRIBUTE_SELECTOR, AT_RULE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NODE_TYPES, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE };
|
|
50
|
+
export { ATTRIBUTE_SELECTOR, AT_RULE, AT_RULE_PRELUDE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NODE_TYPES, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE };
|
package/dist/css-node.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CSSDataArena } from './arena';
|
|
2
|
-
import { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE } from './arena';
|
|
2
|
+
import { STYLESHEET, STYLE_RULE, AT_RULE, DECLARATION, SELECTOR, COMMENT, BLOCK, IDENTIFIER, NUMBER, DIMENSION, STRING, HASH, FUNCTION, OPERATOR, PARENTHESIS, URL, VALUE, SELECTOR_LIST, TYPE_SELECTOR, CLASS_SELECTOR, ID_SELECTOR, ATTRIBUTE_SELECTOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, COMBINATOR, UNIVERSAL_SELECTOR, NESTING_SELECTOR, NTH_SELECTOR, NTH_OF_SELECTOR, LANG_SELECTOR, MEDIA_QUERY, MEDIA_FEATURE, MEDIA_TYPE, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, PRELUDE_OPERATOR, FEATURE_RANGE, AT_RULE_PRELUDE } from './arena';
|
|
3
3
|
export declare const TYPE_NAMES: {
|
|
4
4
|
readonly 1: "StyleSheet";
|
|
5
5
|
readonly 2: "Rule";
|
|
@@ -39,9 +39,10 @@ export declare const TYPE_NAMES: {
|
|
|
39
39
|
readonly 37: "Layer";
|
|
40
40
|
readonly 38: "Operator";
|
|
41
41
|
readonly 39: "MediaFeatureRange";
|
|
42
|
+
readonly 40: "AtrulePrelude";
|
|
42
43
|
};
|
|
43
44
|
export type TypeName = (typeof TYPE_NAMES)[keyof typeof TYPE_NAMES] | 'unknown';
|
|
44
|
-
export type CSSNodeType = typeof STYLESHEET | typeof STYLE_RULE | typeof AT_RULE | typeof DECLARATION | typeof SELECTOR | typeof COMMENT | typeof BLOCK | typeof IDENTIFIER | typeof NUMBER | typeof DIMENSION | typeof STRING | typeof HASH | typeof FUNCTION | typeof OPERATOR | typeof PARENTHESIS | typeof URL | typeof VALUE | typeof SELECTOR_LIST | typeof TYPE_SELECTOR | typeof CLASS_SELECTOR | typeof ID_SELECTOR | typeof ATTRIBUTE_SELECTOR | typeof PSEUDO_CLASS_SELECTOR | typeof PSEUDO_ELEMENT_SELECTOR | typeof COMBINATOR | typeof UNIVERSAL_SELECTOR | typeof NESTING_SELECTOR | typeof NTH_SELECTOR | typeof NTH_OF_SELECTOR | typeof LANG_SELECTOR | typeof MEDIA_QUERY | typeof MEDIA_FEATURE | typeof MEDIA_TYPE | typeof CONTAINER_QUERY | typeof SUPPORTS_QUERY | typeof LAYER_NAME | typeof PRELUDE_OPERATOR | typeof FEATURE_RANGE;
|
|
45
|
+
export type CSSNodeType = typeof STYLESHEET | typeof STYLE_RULE | typeof AT_RULE | typeof DECLARATION | typeof SELECTOR | typeof COMMENT | typeof BLOCK | typeof IDENTIFIER | typeof NUMBER | typeof DIMENSION | typeof STRING | typeof HASH | typeof FUNCTION | typeof OPERATOR | typeof PARENTHESIS | typeof URL | typeof VALUE | typeof SELECTOR_LIST | typeof TYPE_SELECTOR | typeof CLASS_SELECTOR | typeof ID_SELECTOR | typeof ATTRIBUTE_SELECTOR | typeof PSEUDO_CLASS_SELECTOR | typeof PSEUDO_ELEMENT_SELECTOR | typeof COMBINATOR | typeof UNIVERSAL_SELECTOR | typeof NESTING_SELECTOR | typeof NTH_SELECTOR | typeof NTH_OF_SELECTOR | typeof LANG_SELECTOR | typeof MEDIA_QUERY | typeof MEDIA_FEATURE | typeof MEDIA_TYPE | typeof CONTAINER_QUERY | typeof SUPPORTS_QUERY | typeof LAYER_NAME | typeof PRELUDE_OPERATOR | typeof FEATURE_RANGE | typeof AT_RULE_PRELUDE;
|
|
45
46
|
export interface CloneOptions {
|
|
46
47
|
/**
|
|
47
48
|
* Recursively clone all children
|
|
@@ -63,7 +64,7 @@ export type PlainCSSNode = {
|
|
|
63
64
|
property?: string;
|
|
64
65
|
value?: string | number | null;
|
|
65
66
|
unit?: string;
|
|
66
|
-
prelude?:
|
|
67
|
+
prelude?: PlainCSSNode | null;
|
|
67
68
|
is_important?: boolean;
|
|
68
69
|
is_vendor_prefixed?: boolean;
|
|
69
70
|
is_browserhack?: boolean;
|
|
@@ -107,31 +108,33 @@ export declare class CSSNode {
|
|
|
107
108
|
/** Get the numeric value for NUMBER and DIMENSION nodes, or null for other node types */
|
|
108
109
|
get value_as_number(): number | null;
|
|
109
110
|
/**
|
|
110
|
-
* Get the prelude
|
|
111
|
-
*
|
|
111
|
+
* Get the prelude node:
|
|
112
|
+
* - For at-rules: AT_RULE_PRELUDE wrapper containing structured prelude children (media queries, layer names, etc.)
|
|
113
|
+
* - For style rules: SELECTOR_LIST or SELECTOR node
|
|
114
|
+
* Returns null if no prelude exists
|
|
112
115
|
*/
|
|
113
|
-
get prelude():
|
|
116
|
+
get prelude(): CSSNode | null | undefined;
|
|
114
117
|
/**
|
|
115
118
|
* Get the attribute operator (for attribute selectors: =, ~=, |=, ^=, $=, *=)
|
|
116
119
|
* Returns one of the ATTR_OPERATOR_* constants
|
|
117
120
|
*/
|
|
118
|
-
get attr_operator(): number;
|
|
121
|
+
get attr_operator(): number | undefined;
|
|
119
122
|
/**
|
|
120
123
|
* Get the attribute flags (for attribute selectors: i, s)
|
|
121
124
|
* Returns one of the ATTR_FLAG_* constants
|
|
122
125
|
*/
|
|
123
|
-
get attr_flags(): number;
|
|
126
|
+
get attr_flags(): number | undefined;
|
|
124
127
|
/** Get the unit for dimension nodes (e.g., "px" from "100px", "%" from "50%") */
|
|
125
|
-
get unit(): string |
|
|
128
|
+
get unit(): string | undefined;
|
|
126
129
|
/** Check if this declaration has !important */
|
|
127
|
-
get is_important(): boolean |
|
|
130
|
+
get is_important(): boolean | undefined;
|
|
128
131
|
/** Check if this declaration has a browser hack prefix */
|
|
129
|
-
get is_browserhack(): boolean |
|
|
132
|
+
get is_browserhack(): boolean | undefined;
|
|
130
133
|
/** Check if this has a vendor prefix (computed on-demand) */
|
|
131
134
|
get is_vendor_prefixed(): boolean;
|
|
132
135
|
/** Check if this node has an error */
|
|
133
136
|
get has_error(): boolean;
|
|
134
|
-
/** Check if this
|
|
137
|
+
/** Check if this node has a prelude (at-rules and style rules) */
|
|
135
138
|
get has_prelude(): boolean;
|
|
136
139
|
/** Check if this rule has a block { } */
|
|
137
140
|
get has_block(): boolean;
|
|
@@ -140,7 +143,7 @@ export declare class CSSNode {
|
|
|
140
143
|
/** Get the block node (for style rules and at-rules with blocks) */
|
|
141
144
|
get block(): CSSNode | null;
|
|
142
145
|
/** Check if this block is empty (no declarations or rules, only comments allowed) */
|
|
143
|
-
get is_empty(): boolean;
|
|
146
|
+
get is_empty(): boolean | undefined;
|
|
144
147
|
/** Get start line number */
|
|
145
148
|
get line(): number;
|
|
146
149
|
/** Get start column number */
|
|
@@ -171,37 +174,18 @@ export declare class CSSNode {
|
|
|
171
174
|
/** Make CSSNode iterable over its children */
|
|
172
175
|
[Symbol.iterator](): Iterator<CSSNode>;
|
|
173
176
|
/** Get the 'a' coefficient from An+B expression (e.g., "2n" from "2n+1", "odd" from "odd") */
|
|
174
|
-
get nth_a(): string |
|
|
177
|
+
get nth_a(): string | undefined;
|
|
175
178
|
/** Get the 'b' coefficient from An+B expression (e.g., "+1" from "2n+1") */
|
|
176
|
-
get nth_b(): string |
|
|
179
|
+
get nth_b(): string | undefined;
|
|
177
180
|
/** Get the An+B formula node from :nth-child(2n+1 of .foo) */
|
|
178
|
-
get nth(): CSSNode |
|
|
181
|
+
get nth(): CSSNode | undefined;
|
|
179
182
|
/** Get the selector list from :nth-child(2n+1 of .foo) */
|
|
180
|
-
get selector(): CSSNode |
|
|
183
|
+
get selector(): CSSNode | undefined;
|
|
181
184
|
/**
|
|
182
185
|
* Get selector list from pseudo-class functions
|
|
183
186
|
* Works for :is(.a), :not(.b), :has(.c), :where(.d), :nth-child(2n of .e)
|
|
184
187
|
*/
|
|
185
|
-
get selector_list(): CSSNode |
|
|
186
|
-
/**
|
|
187
|
-
* Iterator over first compound selector parts (zero allocation)
|
|
188
|
-
* Yields parts before the first combinator
|
|
189
|
-
*/
|
|
190
|
-
compound_parts(): IterableIterator<CSSNode>;
|
|
191
|
-
/**
|
|
192
|
-
* Get first compound selector as array
|
|
193
|
-
* Returns array of parts before first combinator
|
|
194
|
-
*/
|
|
195
|
-
get first_compound(): CSSNode[];
|
|
196
|
-
/**
|
|
197
|
-
* Split selector into compound selectors
|
|
198
|
-
* Returns array of compound arrays split by combinators
|
|
199
|
-
*/
|
|
200
|
-
get all_compounds(): CSSNode[][];
|
|
201
|
-
/** Check if selector is compound (no combinators) */
|
|
202
|
-
get is_compound(): boolean;
|
|
203
|
-
/** Get text of first compound selector (no node allocation) */
|
|
204
|
-
get first_compound_text(): string;
|
|
188
|
+
get selector_list(): CSSNode | undefined;
|
|
205
189
|
/**
|
|
206
190
|
* Clone this node as a mutable plain JavaScript object with children as arrays.
|
|
207
191
|
* See API.md for examples.
|
package/dist/css-node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DECLARATION, DIMENSION, NUMBER, URL, STRING, FLAG_IMPORTANT, FLAG_BROWSERHACK, IDENTIFIER, FUNCTION,
|
|
1
|
+
import { DECLARATION, DIMENSION, NUMBER, URL, STRING, AT_RULE, AT_RULE_PRELUDE, STYLE_RULE, ATTRIBUTE_SELECTOR, FLAG_IMPORTANT, FLAG_BROWSERHACK, IDENTIFIER, FUNCTION, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, FLAG_HAS_ERROR, FLAG_HAS_BLOCK, FLAG_HAS_DECLARATIONS, BLOCK, COMMENT, FLAG_HAS_PARENS, NTH_SELECTOR, NTH_OF_SELECTOR, SELECTOR_LIST, FEATURE_RANGE, PRELUDE_OPERATOR, LAYER_NAME, SUPPORTS_QUERY, CONTAINER_QUERY, MEDIA_TYPE, MEDIA_FEATURE, MEDIA_QUERY, LANG_SELECTOR, NESTING_SELECTOR, UNIVERSAL_SELECTOR, COMBINATOR, ID_SELECTOR, CLASS_SELECTOR, TYPE_SELECTOR, VALUE, PARENTHESIS, OPERATOR, HASH, SELECTOR, STYLESHEET } from './arena.js';
|
|
2
2
|
import { str_starts_with, is_vendor_prefixed, is_whitespace, CHAR_MINUS_HYPHEN, CHAR_PLUS } from './string-utils.js';
|
|
3
3
|
import { parse_dimension } from './parse-utils.js';
|
|
4
4
|
|
|
@@ -40,7 +40,8 @@ const TYPE_NAMES = {
|
|
|
40
40
|
[SUPPORTS_QUERY]: "SupportsQuery",
|
|
41
41
|
[LAYER_NAME]: "Layer",
|
|
42
42
|
[PRELUDE_OPERATOR]: "Operator",
|
|
43
|
-
[FEATURE_RANGE]: "MediaFeatureRange"
|
|
43
|
+
[FEATURE_RANGE]: "MediaFeatureRange",
|
|
44
|
+
[AT_RULE_PRELUDE]: "AtrulePrelude"
|
|
44
45
|
};
|
|
45
46
|
class CSSNode {
|
|
46
47
|
arena;
|
|
@@ -137,18 +138,30 @@ class CSSNode {
|
|
|
137
138
|
return null;
|
|
138
139
|
}
|
|
139
140
|
/**
|
|
140
|
-
* Get the prelude
|
|
141
|
-
*
|
|
141
|
+
* Get the prelude node:
|
|
142
|
+
* - For at-rules: AT_RULE_PRELUDE wrapper containing structured prelude children (media queries, layer names, etc.)
|
|
143
|
+
* - For style rules: SELECTOR_LIST or SELECTOR node
|
|
144
|
+
* Returns null if no prelude exists
|
|
142
145
|
*/
|
|
143
146
|
get prelude() {
|
|
144
|
-
|
|
145
|
-
|
|
147
|
+
if (this.type === AT_RULE) {
|
|
148
|
+
let first = this.first_child;
|
|
149
|
+
if (first && first.type === AT_RULE_PRELUDE) {
|
|
150
|
+
return first;
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
if (this.type === STYLE_RULE) {
|
|
155
|
+
return this.first_child;
|
|
156
|
+
}
|
|
157
|
+
return void 0;
|
|
146
158
|
}
|
|
147
159
|
/**
|
|
148
160
|
* Get the attribute operator (for attribute selectors: =, ~=, |=, ^=, $=, *=)
|
|
149
161
|
* Returns one of the ATTR_OPERATOR_* constants
|
|
150
162
|
*/
|
|
151
163
|
get attr_operator() {
|
|
164
|
+
if (this.type !== ATTRIBUTE_SELECTOR) return void 0;
|
|
152
165
|
return this.arena.get_attr_operator(this.index);
|
|
153
166
|
}
|
|
154
167
|
/**
|
|
@@ -156,21 +169,22 @@ class CSSNode {
|
|
|
156
169
|
* Returns one of the ATTR_FLAG_* constants
|
|
157
170
|
*/
|
|
158
171
|
get attr_flags() {
|
|
172
|
+
if (this.type !== ATTRIBUTE_SELECTOR) return void 0;
|
|
159
173
|
return this.arena.get_attr_flags(this.index);
|
|
160
174
|
}
|
|
161
175
|
/** Get the unit for dimension nodes (e.g., "px" from "100px", "%" from "50%") */
|
|
162
176
|
get unit() {
|
|
163
|
-
if (this.type !== DIMENSION) return
|
|
177
|
+
if (this.type !== DIMENSION) return void 0;
|
|
164
178
|
return parse_dimension(this.text).unit;
|
|
165
179
|
}
|
|
166
180
|
/** Check if this declaration has !important */
|
|
167
181
|
get is_important() {
|
|
168
|
-
if (this.type !== DECLARATION) return
|
|
182
|
+
if (this.type !== DECLARATION) return void 0;
|
|
169
183
|
return this.arena.has_flag(this.index, FLAG_IMPORTANT);
|
|
170
184
|
}
|
|
171
185
|
/** Check if this declaration has a browser hack prefix */
|
|
172
186
|
get is_browserhack() {
|
|
173
|
-
if (this.type !== DECLARATION) return
|
|
187
|
+
if (this.type !== DECLARATION) return void 0;
|
|
174
188
|
return this.arena.has_flag(this.index, FLAG_BROWSERHACK);
|
|
175
189
|
}
|
|
176
190
|
/** Check if this has a vendor prefix (computed on-demand) */
|
|
@@ -195,9 +209,15 @@ class CSSNode {
|
|
|
195
209
|
get has_error() {
|
|
196
210
|
return this.arena.has_flag(this.index, FLAG_HAS_ERROR);
|
|
197
211
|
}
|
|
198
|
-
/** Check if this
|
|
212
|
+
/** Check if this node has a prelude (at-rules and style rules) */
|
|
199
213
|
get has_prelude() {
|
|
200
|
-
|
|
214
|
+
if (this.type === AT_RULE) {
|
|
215
|
+
return this.arena.get_value_length(this.index) > 0;
|
|
216
|
+
}
|
|
217
|
+
if (this.type === STYLE_RULE) {
|
|
218
|
+
return this.first_child !== null;
|
|
219
|
+
}
|
|
220
|
+
return false;
|
|
201
221
|
}
|
|
202
222
|
/** Check if this rule has a block { } */
|
|
203
223
|
get has_block() {
|
|
@@ -232,7 +252,7 @@ class CSSNode {
|
|
|
232
252
|
}
|
|
233
253
|
/** Check if this block is empty (no declarations or rules, only comments allowed) */
|
|
234
254
|
get is_empty() {
|
|
235
|
-
if (this.type !== BLOCK) return
|
|
255
|
+
if (this.type !== BLOCK) return void 0;
|
|
236
256
|
let child = this.first_child;
|
|
237
257
|
while (child) {
|
|
238
258
|
if (child.type !== COMMENT) {
|
|
@@ -317,17 +337,17 @@ class CSSNode {
|
|
|
317
337
|
// --- An+B Expression Helpers (for NODE_SELECTOR_NTH) ---
|
|
318
338
|
/** Get the 'a' coefficient from An+B expression (e.g., "2n" from "2n+1", "odd" from "odd") */
|
|
319
339
|
get nth_a() {
|
|
320
|
-
if (this.type !== NTH_SELECTOR) return
|
|
340
|
+
if (this.type !== NTH_SELECTOR && this.type !== NTH_OF_SELECTOR) return void 0;
|
|
321
341
|
let len = this.arena.get_content_length(this.index);
|
|
322
|
-
if (len === 0) return
|
|
342
|
+
if (len === 0) return void 0;
|
|
323
343
|
let start = this.arena.get_content_start(this.index);
|
|
324
344
|
return this.source.substring(start, start + len);
|
|
325
345
|
}
|
|
326
346
|
/** Get the 'b' coefficient from An+B expression (e.g., "+1" from "2n+1") */
|
|
327
347
|
get nth_b() {
|
|
328
|
-
if (this.type !== NTH_SELECTOR) return
|
|
348
|
+
if (this.type !== NTH_SELECTOR && this.type !== NTH_OF_SELECTOR) return void 0;
|
|
329
349
|
let len = this.arena.get_value_length(this.index);
|
|
330
|
-
if (len === 0) return
|
|
350
|
+
if (len === 0) return void 0;
|
|
331
351
|
let start = this.arena.get_value_start(this.index);
|
|
332
352
|
let value = this.source.substring(start, start + len);
|
|
333
353
|
let check_pos = start - 1;
|
|
@@ -349,14 +369,14 @@ class CSSNode {
|
|
|
349
369
|
// --- Pseudo-Class Nth-Of Helpers (for NODE_SELECTOR_NTH_OF) ---
|
|
350
370
|
/** Get the An+B formula node from :nth-child(2n+1 of .foo) */
|
|
351
371
|
get nth() {
|
|
352
|
-
if (this.type !== NTH_OF_SELECTOR) return
|
|
353
|
-
return this.first_child;
|
|
372
|
+
if (this.type !== NTH_OF_SELECTOR) return void 0;
|
|
373
|
+
return this.first_child ?? void 0;
|
|
354
374
|
}
|
|
355
375
|
/** Get the selector list from :nth-child(2n+1 of .foo) */
|
|
356
376
|
get selector() {
|
|
357
|
-
if (this.type !== NTH_OF_SELECTOR) return
|
|
377
|
+
if (this.type !== NTH_OF_SELECTOR) return void 0;
|
|
358
378
|
let first = this.first_child;
|
|
359
|
-
return first
|
|
379
|
+
return first?.next_sibling ?? void 0;
|
|
360
380
|
}
|
|
361
381
|
// --- Pseudo-Class Selector List Helper ---
|
|
362
382
|
/**
|
|
@@ -364,95 +384,16 @@ class CSSNode {
|
|
|
364
384
|
* Works for :is(.a), :not(.b), :has(.c), :where(.d), :nth-child(2n of .e)
|
|
365
385
|
*/
|
|
366
386
|
get selector_list() {
|
|
367
|
-
if (this.type !== PSEUDO_CLASS_SELECTOR) return
|
|
387
|
+
if (this.type !== PSEUDO_CLASS_SELECTOR) return void 0;
|
|
368
388
|
let child = this.first_child;
|
|
369
|
-
if (!child) return
|
|
389
|
+
if (!child) return void 0;
|
|
370
390
|
if (child.type === SELECTOR_LIST) {
|
|
371
391
|
return child;
|
|
372
392
|
}
|
|
373
393
|
if (child.type === NTH_OF_SELECTOR) {
|
|
374
394
|
return child.selector;
|
|
375
395
|
}
|
|
376
|
-
return
|
|
377
|
-
}
|
|
378
|
-
// --- Compound Selector Helpers (for NODE_SELECTOR) ---
|
|
379
|
-
/**
|
|
380
|
-
* Iterator over first compound selector parts (zero allocation)
|
|
381
|
-
* Yields parts before the first combinator
|
|
382
|
-
*/
|
|
383
|
-
*compound_parts() {
|
|
384
|
-
if (this.type !== SELECTOR) return;
|
|
385
|
-
let child = this.first_child;
|
|
386
|
-
while (child) {
|
|
387
|
-
if (child.type === COMBINATOR) break;
|
|
388
|
-
yield child;
|
|
389
|
-
child = child.next_sibling;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
/**
|
|
393
|
-
* Get first compound selector as array
|
|
394
|
-
* Returns array of parts before first combinator
|
|
395
|
-
*/
|
|
396
|
-
get first_compound() {
|
|
397
|
-
if (this.type !== SELECTOR) return [];
|
|
398
|
-
let result = [];
|
|
399
|
-
let child = this.first_child;
|
|
400
|
-
while (child) {
|
|
401
|
-
if (child.type === COMBINATOR) break;
|
|
402
|
-
result.push(child);
|
|
403
|
-
child = child.next_sibling;
|
|
404
|
-
}
|
|
405
|
-
return result;
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Split selector into compound selectors
|
|
409
|
-
* Returns array of compound arrays split by combinators
|
|
410
|
-
*/
|
|
411
|
-
get all_compounds() {
|
|
412
|
-
if (this.type !== SELECTOR) return [];
|
|
413
|
-
let compounds = [];
|
|
414
|
-
let current_compound = [];
|
|
415
|
-
let child = this.first_child;
|
|
416
|
-
while (child) {
|
|
417
|
-
if (child.type === COMBINATOR) {
|
|
418
|
-
if (current_compound.length > 0) {
|
|
419
|
-
compounds.push(current_compound);
|
|
420
|
-
current_compound = [];
|
|
421
|
-
}
|
|
422
|
-
} else {
|
|
423
|
-
current_compound.push(child);
|
|
424
|
-
}
|
|
425
|
-
child = child.next_sibling;
|
|
426
|
-
}
|
|
427
|
-
if (current_compound.length > 0) {
|
|
428
|
-
compounds.push(current_compound);
|
|
429
|
-
}
|
|
430
|
-
return compounds;
|
|
431
|
-
}
|
|
432
|
-
/** Check if selector is compound (no combinators) */
|
|
433
|
-
get is_compound() {
|
|
434
|
-
if (this.type !== SELECTOR) return false;
|
|
435
|
-
let child = this.first_child;
|
|
436
|
-
while (child) {
|
|
437
|
-
if (child.type === COMBINATOR) return false;
|
|
438
|
-
child = child.next_sibling;
|
|
439
|
-
}
|
|
440
|
-
return true;
|
|
441
|
-
}
|
|
442
|
-
/** Get text of first compound selector (no node allocation) */
|
|
443
|
-
get first_compound_text() {
|
|
444
|
-
if (this.type !== SELECTOR) return "";
|
|
445
|
-
let start = -1;
|
|
446
|
-
let end = -1;
|
|
447
|
-
let child = this.first_child;
|
|
448
|
-
while (child) {
|
|
449
|
-
if (child.type === COMBINATOR) break;
|
|
450
|
-
if (start === -1) start = child.start;
|
|
451
|
-
end = child.start + child.length;
|
|
452
|
-
child = child.next_sibling;
|
|
453
|
-
}
|
|
454
|
-
if (start === -1) return "";
|
|
455
|
-
return this.source.substring(start, end);
|
|
396
|
+
return void 0;
|
|
456
397
|
}
|
|
457
398
|
// --- Node Cloning ---
|
|
458
399
|
/**
|
|
@@ -477,9 +418,6 @@ class CSSNode {
|
|
|
477
418
|
plain.value = this.value;
|
|
478
419
|
if (this.unit) plain.unit = this.unit;
|
|
479
420
|
}
|
|
480
|
-
if (this.type === AT_RULE && this.prelude) {
|
|
481
|
-
plain.prelude = this.prelude;
|
|
482
|
-
}
|
|
483
421
|
if (this.type === DECLARATION) {
|
|
484
422
|
plain.is_important = this.is_important;
|
|
485
423
|
plain.is_browserhack = this.is_browserhack;
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,6 @@ export { tokenize } from './tokenize.js';
|
|
|
7
7
|
export { BREAK, SKIP, traverse, walk } from './walk.js';
|
|
8
8
|
export { is_custom, is_vendor_prefixed, str_equals, str_index_of, str_starts_with } from './string-utils.js';
|
|
9
9
|
export { CSSNode, TYPE_NAMES } from './css-node.js';
|
|
10
|
-
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE } from './arena.js';
|
|
10
|
+
export { ATTRIBUTE_SELECTOR, ATTR_FLAG_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, ATTR_FLAG_NONE, ATTR_OPERATOR_CARET_EQUAL, ATTR_OPERATOR_DOLLAR_EQUAL, ATTR_OPERATOR_EQUAL, ATTR_OPERATOR_NONE, ATTR_OPERATOR_PIPE_EQUAL, ATTR_OPERATOR_STAR_EQUAL, ATTR_OPERATOR_TILDE_EQUAL, AT_RULE, AT_RULE_PRELUDE, BLOCK, CLASS_SELECTOR, COMBINATOR, COMMENT, CONTAINER_QUERY, DECLARATION, DIMENSION, FEATURE_RANGE, FLAG_IMPORTANT, FUNCTION, HASH, IDENTIFIER, ID_SELECTOR, LANG_SELECTOR, LAYER_NAME, MEDIA_FEATURE, MEDIA_QUERY, MEDIA_TYPE, NESTING_SELECTOR, NTH_OF_SELECTOR, NTH_SELECTOR, NUMBER, OPERATOR, PARENTHESIS, PRELUDE_OPERATOR, PSEUDO_CLASS_SELECTOR, PSEUDO_ELEMENT_SELECTOR, SELECTOR, SELECTOR_LIST, STRING, STYLESHEET, STYLE_RULE, SUPPORTS_QUERY, TYPE_SELECTOR, UNIVERSAL_SELECTOR, URL, VALUE } from './arena.js';
|
|
11
11
|
export { NODE_TYPES } from './constants.js';
|
|
12
12
|
export { TOKEN_AT_KEYWORD, TOKEN_BAD_STRING, TOKEN_BAD_URL, TOKEN_CDC, TOKEN_CDO, TOKEN_COLON, TOKEN_COMMA, TOKEN_COMMENT, TOKEN_DELIM, TOKEN_DIMENSION, TOKEN_EOF, TOKEN_FUNCTION, TOKEN_HASH, TOKEN_IDENT, TOKEN_LEFT_BRACE, TOKEN_LEFT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_NUMBER, TOKEN_PERCENTAGE, TOKEN_RIGHT_BRACE, TOKEN_RIGHT_BRACKET, TOKEN_RIGHT_PAREN, TOKEN_SEMICOLON, TOKEN_STRING, TOKEN_URL, TOKEN_WHITESPACE } from './token-types.js';
|
package/dist/parse-selector.js
CHANGED
|
@@ -34,9 +34,13 @@ class SelectorParser {
|
|
|
34
34
|
let list_column = this.lexer.column;
|
|
35
35
|
while (this.lexer.pos < this.selector_end) {
|
|
36
36
|
let selector_start = this.lexer.pos;
|
|
37
|
+
let selector_line = this.lexer.line;
|
|
38
|
+
let selector_column = this.lexer.column;
|
|
37
39
|
let complex_selector = this.parse_complex_selector(allow_relative);
|
|
38
40
|
if (complex_selector !== null) {
|
|
39
|
-
let selector_wrapper = this.create_node(SELECTOR, selector_start, this.lexer.pos);
|
|
41
|
+
let selector_wrapper = this.arena.create_node(SELECTOR, selector_start, this.lexer.pos - selector_start, selector_line, selector_column);
|
|
42
|
+
this.arena.set_content_start_delta(selector_wrapper, 0);
|
|
43
|
+
this.arena.set_content_length(selector_wrapper, this.lexer.pos - selector_start);
|
|
40
44
|
let last_component = complex_selector;
|
|
41
45
|
let next_sibling = this.arena.get_next_sibling(last_component);
|
|
42
46
|
while (next_sibling !== 0) {
|
|
@@ -573,9 +577,11 @@ class SelectorParser {
|
|
|
573
577
|
this.arena.set_content_length(node, end - start);
|
|
574
578
|
return node;
|
|
575
579
|
}
|
|
576
|
-
// Helper to skip whitespace
|
|
580
|
+
// Helper to skip whitespace and update line/column
|
|
577
581
|
skip_whitespace() {
|
|
578
|
-
this.lexer.pos
|
|
582
|
+
while (this.lexer.pos < this.selector_end && is_whitespace(this.source.charCodeAt(this.lexer.pos))) {
|
|
583
|
+
this.lexer.advance();
|
|
584
|
+
}
|
|
579
585
|
}
|
|
580
586
|
}
|
|
581
587
|
function parse_selector(source) {
|
package/dist/parse.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Lexer } from './tokenize.js';
|
|
2
|
-
import { CSSDataArena, STYLESHEET, STYLE_RULE, FLAG_HAS_BLOCK, BLOCK, FLAG_HAS_DECLARATIONS, SELECTOR_LIST, AT_RULE } from './arena.js';
|
|
2
|
+
import { CSSDataArena, STYLESHEET, STYLE_RULE, FLAG_HAS_BLOCK, BLOCK, FLAG_HAS_DECLARATIONS, SELECTOR_LIST, AT_RULE, AT_RULE_PRELUDE } from './arena.js';
|
|
3
3
|
import { CSSNode } from './css-node.js';
|
|
4
4
|
import { SelectorParser } from './parse-selector.js';
|
|
5
5
|
import { AtRulePreludeParser } from './parse-atrule-prelude.js';
|
|
@@ -167,13 +167,13 @@ class Parser {
|
|
|
167
167
|
this.next_token();
|
|
168
168
|
}
|
|
169
169
|
if (this.parse_selectors_enabled && this.selector_parser) {
|
|
170
|
-
let
|
|
171
|
-
if (
|
|
172
|
-
return
|
|
170
|
+
let selector = this.selector_parser.parse_selector(selector_start, last_end, selector_line, selector_column);
|
|
171
|
+
if (selector !== null) {
|
|
172
|
+
return selector;
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
-
let
|
|
176
|
-
return
|
|
175
|
+
let selector_list = this.arena.create_node(SELECTOR_LIST, selector_start, last_end - selector_start, selector_line, selector_column);
|
|
176
|
+
return selector_list;
|
|
177
177
|
}
|
|
178
178
|
// Parse a declaration: property: value;
|
|
179
179
|
parse_declaration() {
|
|
@@ -221,12 +221,16 @@ class Parser {
|
|
|
221
221
|
this.next_token();
|
|
222
222
|
}
|
|
223
223
|
let trimmed = trim_boundaries(this.source, prelude_start, prelude_end);
|
|
224
|
-
let
|
|
224
|
+
let prelude_wrapper = null;
|
|
225
225
|
if (trimmed) {
|
|
226
226
|
this.arena.set_value_start_delta(at_rule, trimmed[0] - at_rule_start);
|
|
227
227
|
this.arena.set_value_length(at_rule, trimmed[1] - trimmed[0]);
|
|
228
228
|
if (this.prelude_parser) {
|
|
229
|
-
prelude_nodes = this.prelude_parser.parse_prelude(at_rule_name, trimmed[0], trimmed[1], at_rule_line, at_rule_column);
|
|
229
|
+
let prelude_nodes = this.prelude_parser.parse_prelude(at_rule_name, trimmed[0], trimmed[1], at_rule_line, at_rule_column);
|
|
230
|
+
if (prelude_nodes.length > 0) {
|
|
231
|
+
prelude_wrapper = this.arena.create_node(AT_RULE_PRELUDE, trimmed[0], trimmed[1] - trimmed[0], at_rule_line, at_rule_column);
|
|
232
|
+
this.arena.append_children(prelude_wrapper, prelude_nodes);
|
|
233
|
+
}
|
|
230
234
|
}
|
|
231
235
|
}
|
|
232
236
|
let last_end = this.lexer.token_end;
|
|
@@ -304,13 +308,26 @@ class Parser {
|
|
|
304
308
|
this.arena.set_length(block_node, last_end - block_start);
|
|
305
309
|
}
|
|
306
310
|
this.arena.append_children(block_node, block_children);
|
|
307
|
-
|
|
311
|
+
let at_rule_children = [];
|
|
312
|
+
if (prelude_wrapper !== null) {
|
|
313
|
+
at_rule_children.push(prelude_wrapper);
|
|
314
|
+
}
|
|
315
|
+
at_rule_children.push(block_node);
|
|
316
|
+
this.arena.set_length(at_rule, last_end - at_rule_start);
|
|
317
|
+
this.arena.append_children(at_rule, at_rule_children);
|
|
308
318
|
} else if (this.peek_type() === TOKEN_SEMICOLON) {
|
|
309
319
|
last_end = this.lexer.token_end;
|
|
310
320
|
this.next_token();
|
|
321
|
+
this.arena.set_length(at_rule, last_end - at_rule_start);
|
|
322
|
+
if (prelude_wrapper !== null) {
|
|
323
|
+
this.arena.append_children(at_rule, [prelude_wrapper]);
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
this.arena.set_length(at_rule, last_end - at_rule_start);
|
|
327
|
+
if (prelude_wrapper !== null) {
|
|
328
|
+
this.arena.append_children(at_rule, [prelude_wrapper]);
|
|
329
|
+
}
|
|
311
330
|
}
|
|
312
|
-
this.arena.set_length(at_rule, last_end - at_rule_start);
|
|
313
|
-
this.arena.append_children(at_rule, prelude_nodes);
|
|
314
331
|
return at_rule;
|
|
315
332
|
}
|
|
316
333
|
// Determine if an at-rule contains declarations or nested rules
|
package/dist/tokenize.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { TOKEN_EOF,
|
|
1
|
+
import { char_types, CHAR_WHITESPACE, CHAR_NEWLINE, CHAR_DIGIT, is_ident_start, is_newline, is_hex_digit, is_whitespace, is_ident_char } from './char-types.js';
|
|
2
|
+
import { TOKEN_EOF, TOKEN_RIGHT_PAREN, TOKEN_LEFT_PAREN, TOKEN_RIGHT_BRACKET, TOKEN_LEFT_BRACKET, TOKEN_COMMA, TOKEN_SEMICOLON, TOKEN_COLON, TOKEN_RIGHT_BRACE, TOKEN_LEFT_BRACE, TOKEN_CDO, TOKEN_CDC, TOKEN_DELIM, TOKEN_WHITESPACE, TOKEN_COMMENT, TOKEN_STRING, TOKEN_BAD_STRING, TOKEN_PERCENTAGE, TOKEN_DIMENSION, TOKEN_NUMBER, TOKEN_FUNCTION, TOKEN_IDENT, TOKEN_AT_KEYWORD, TOKEN_HASH } from './token-types.js';
|
|
3
3
|
|
|
4
4
|
const CHAR_LEFT_BRACE = 123;
|
|
5
5
|
const CHAR_RIGHT_BRACE = 125;
|
|
@@ -57,7 +57,7 @@ class Lexer {
|
|
|
57
57
|
if (skip_whitespace) {
|
|
58
58
|
while (this.pos < this.source.length) {
|
|
59
59
|
let ch2 = this.source.charCodeAt(this.pos);
|
|
60
|
-
if (
|
|
60
|
+
if (ch2 >= 128 || (char_types[ch2] & (CHAR_WHITESPACE | CHAR_NEWLINE)) === 0) break;
|
|
61
61
|
this.advance();
|
|
62
62
|
}
|
|
63
63
|
}
|
|
@@ -68,43 +68,36 @@ class Lexer {
|
|
|
68
68
|
let start = this.pos;
|
|
69
69
|
let start_line = this.line;
|
|
70
70
|
let start_column = this.column;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (ch === CHAR_LEFT_PAREN) {
|
|
100
|
-
this.advance();
|
|
101
|
-
return this.make_token(TOKEN_LEFT_PAREN, start, this.pos, start_line, start_column);
|
|
102
|
-
}
|
|
103
|
-
if (ch === CHAR_RIGHT_PAREN) {
|
|
104
|
-
this.advance();
|
|
105
|
-
return this.make_token(TOKEN_RIGHT_PAREN, start, this.pos, start_line, start_column);
|
|
71
|
+
switch (ch) {
|
|
72
|
+
case CHAR_LEFT_BRACE:
|
|
73
|
+
this.advance();
|
|
74
|
+
return this.make_token(TOKEN_LEFT_BRACE, start, this.pos, start_line, start_column);
|
|
75
|
+
case CHAR_RIGHT_BRACE:
|
|
76
|
+
this.advance();
|
|
77
|
+
return this.make_token(TOKEN_RIGHT_BRACE, start, this.pos, start_line, start_column);
|
|
78
|
+
case CHAR_COLON:
|
|
79
|
+
this.advance();
|
|
80
|
+
return this.make_token(TOKEN_COLON, start, this.pos, start_line, start_column);
|
|
81
|
+
case CHAR_SEMICOLON:
|
|
82
|
+
this.advance();
|
|
83
|
+
return this.make_token(TOKEN_SEMICOLON, start, this.pos, start_line, start_column);
|
|
84
|
+
case CHAR_COMMA:
|
|
85
|
+
this.advance();
|
|
86
|
+
return this.make_token(TOKEN_COMMA, start, this.pos, start_line, start_column);
|
|
87
|
+
case CHAR_LEFT_BRACKET:
|
|
88
|
+
this.advance();
|
|
89
|
+
return this.make_token(TOKEN_LEFT_BRACKET, start, this.pos, start_line, start_column);
|
|
90
|
+
case CHAR_RIGHT_BRACKET:
|
|
91
|
+
this.advance();
|
|
92
|
+
return this.make_token(TOKEN_RIGHT_BRACKET, start, this.pos, start_line, start_column);
|
|
93
|
+
case CHAR_LEFT_PAREN:
|
|
94
|
+
this.advance();
|
|
95
|
+
return this.make_token(TOKEN_LEFT_PAREN, start, this.pos, start_line, start_column);
|
|
96
|
+
case CHAR_RIGHT_PAREN:
|
|
97
|
+
this.advance();
|
|
98
|
+
return this.make_token(TOKEN_RIGHT_PAREN, start, this.pos, start_line, start_column);
|
|
106
99
|
}
|
|
107
|
-
if (
|
|
100
|
+
if (ch < 128 && (char_types[ch] & (CHAR_WHITESPACE | CHAR_NEWLINE)) !== 0) {
|
|
108
101
|
return this.consume_whitespace(start_line, start_column);
|
|
109
102
|
}
|
|
110
103
|
if (ch === CHAR_FORWARD_SLASH && this.peek() === CHAR_ASTERISK) {
|
|
@@ -112,7 +105,7 @@ class Lexer {
|
|
|
112
105
|
this.advance(2);
|
|
113
106
|
while (this.pos < this.source.length - 1) {
|
|
114
107
|
let ch2 = this.source.charCodeAt(this.pos);
|
|
115
|
-
if (ch2 === CHAR_ASTERISK && this.
|
|
108
|
+
if (ch2 === CHAR_ASTERISK && this.peek() === CHAR_FORWARD_SLASH) {
|
|
116
109
|
this.advance(2);
|
|
117
110
|
break;
|
|
118
111
|
}
|
|
@@ -125,20 +118,23 @@ class Lexer {
|
|
|
125
118
|
if (ch === CHAR_DOUBLE_QUOTE || ch === CHAR_SINGLE_QUOTE) {
|
|
126
119
|
return this.consume_string(ch, start_line, start_column);
|
|
127
120
|
}
|
|
128
|
-
if (
|
|
121
|
+
if (ch < 128 && (char_types[ch] & CHAR_DIGIT) !== 0) {
|
|
129
122
|
return this.consume_number(start_line, start_column);
|
|
130
123
|
}
|
|
131
|
-
if (ch === CHAR_DOT
|
|
132
|
-
|
|
124
|
+
if (ch === CHAR_DOT) {
|
|
125
|
+
let next = this.peek();
|
|
126
|
+
if (next < 128 && (char_types[next] & CHAR_DIGIT) !== 0) {
|
|
127
|
+
return this.consume_number(start_line, start_column);
|
|
128
|
+
}
|
|
133
129
|
}
|
|
134
130
|
if (ch === CHAR_LESS_THAN && this.pos + 3 < this.source.length) {
|
|
135
|
-
if (this.
|
|
131
|
+
if (this.peek() === CHAR_EXCLAMATION && this.peek(2) === CHAR_HYPHEN && this.peek(3) === CHAR_HYPHEN) {
|
|
136
132
|
this.advance(4);
|
|
137
133
|
return this.make_token(TOKEN_CDO, start, this.pos, start_line, start_column);
|
|
138
134
|
}
|
|
139
135
|
}
|
|
140
136
|
if (ch === CHAR_HYPHEN && this.pos + 2 < this.source.length) {
|
|
141
|
-
if (this.
|
|
137
|
+
if (this.peek() === CHAR_HYPHEN && this.peek(2) === CHAR_GREATER_THAN) {
|
|
142
138
|
this.advance(3);
|
|
143
139
|
return this.make_token(TOKEN_CDC, start, this.pos, start_line, start_column);
|
|
144
140
|
}
|
|
@@ -166,9 +162,16 @@ class Lexer {
|
|
|
166
162
|
}
|
|
167
163
|
if (ch === CHAR_HYPHEN || ch === CHAR_PLUS) {
|
|
168
164
|
let next = this.peek();
|
|
169
|
-
|
|
165
|
+
let is_next_digit = next < 128 && (char_types[next] & CHAR_DIGIT) !== 0;
|
|
166
|
+
if (is_next_digit) {
|
|
170
167
|
return this.consume_number(start_line, start_column);
|
|
171
168
|
}
|
|
169
|
+
if (next === CHAR_DOT) {
|
|
170
|
+
let next2 = this.peek(2);
|
|
171
|
+
if (next2 < 128 && (char_types[next2] & CHAR_DIGIT) !== 0) {
|
|
172
|
+
return this.consume_number(start_line, start_column);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
172
175
|
}
|
|
173
176
|
this.advance();
|
|
174
177
|
return this.make_token(TOKEN_DELIM, start, this.pos, start_line, start_column);
|
|
@@ -177,7 +180,7 @@ class Lexer {
|
|
|
177
180
|
let start = this.pos;
|
|
178
181
|
while (this.pos < this.source.length) {
|
|
179
182
|
let ch = this.source.charCodeAt(this.pos);
|
|
180
|
-
if (
|
|
183
|
+
if (ch >= 128 || (char_types[ch] & (CHAR_WHITESPACE | CHAR_NEWLINE)) === 0) break;
|
|
181
184
|
this.advance();
|
|
182
185
|
}
|
|
183
186
|
return this.make_token(TOKEN_WHITESPACE, start, this.pos, start_line, start_column);
|
|
@@ -187,7 +190,7 @@ class Lexer {
|
|
|
187
190
|
this.advance(2);
|
|
188
191
|
while (this.pos < this.source.length - 1) {
|
|
189
192
|
let ch = this.source.charCodeAt(this.pos);
|
|
190
|
-
if (ch === CHAR_ASTERISK && this.
|
|
193
|
+
if (ch === CHAR_ASTERISK && this.peek() === CHAR_FORWARD_SLASH) {
|
|
191
194
|
this.advance(2);
|
|
192
195
|
break;
|
|
193
196
|
}
|
|
@@ -246,20 +249,30 @@ class Lexer {
|
|
|
246
249
|
if (ch === CHAR_PLUS || ch === CHAR_HYPHEN) {
|
|
247
250
|
this.advance();
|
|
248
251
|
}
|
|
249
|
-
while (this.pos < this.source.length
|
|
252
|
+
while (this.pos < this.source.length) {
|
|
253
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
254
|
+
if (ch2 >= 128 || (char_types[ch2] & CHAR_DIGIT) === 0) break;
|
|
250
255
|
this.advance();
|
|
251
256
|
}
|
|
252
|
-
if (this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_DOT && this.pos + 1 < this.source.length
|
|
253
|
-
this.
|
|
254
|
-
|
|
257
|
+
if (this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_DOT && this.pos + 1 < this.source.length) {
|
|
258
|
+
let next = this.peek();
|
|
259
|
+
if (next < 128 && (char_types[next] & CHAR_DIGIT) !== 0) {
|
|
255
260
|
this.advance();
|
|
261
|
+
while (this.pos < this.source.length) {
|
|
262
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
263
|
+
if (ch2 >= 128 || (char_types[ch2] & CHAR_DIGIT) === 0) break;
|
|
264
|
+
this.advance();
|
|
265
|
+
}
|
|
256
266
|
}
|
|
257
267
|
}
|
|
258
268
|
if (this.pos < this.source.length) {
|
|
259
269
|
let ch2 = this.source.charCodeAt(this.pos);
|
|
260
270
|
if (ch2 === CHAR_LOWERCASE_E || ch2 === CHAR_UPPERCASE_E) {
|
|
261
271
|
let next = this.peek();
|
|
262
|
-
|
|
272
|
+
let is_next_digit = next < 128 && (char_types[next] & CHAR_DIGIT) !== 0;
|
|
273
|
+
let next2 = this.peek(2);
|
|
274
|
+
let is_next2_digit = next2 < 128 && (char_types[next2] & CHAR_DIGIT) !== 0;
|
|
275
|
+
if (is_next_digit || (next === CHAR_PLUS || next === CHAR_HYPHEN) && is_next2_digit) {
|
|
263
276
|
this.advance();
|
|
264
277
|
if (this.pos < this.source.length) {
|
|
265
278
|
let sign = this.source.charCodeAt(this.pos);
|
|
@@ -267,7 +280,9 @@ class Lexer {
|
|
|
267
280
|
this.advance();
|
|
268
281
|
}
|
|
269
282
|
}
|
|
270
|
-
while (this.pos < this.source.length
|
|
283
|
+
while (this.pos < this.source.length) {
|
|
284
|
+
let ch3 = this.source.charCodeAt(this.pos);
|
|
285
|
+
if (ch3 >= 128 || (char_types[ch3] & CHAR_DIGIT) === 0) break;
|
|
271
286
|
this.advance();
|
|
272
287
|
}
|
|
273
288
|
}
|
|
@@ -294,7 +309,7 @@ class Lexer {
|
|
|
294
309
|
let ch = this.source.charCodeAt(this.pos);
|
|
295
310
|
if (ch === CHAR_BACKSLASH) {
|
|
296
311
|
if (this.pos + 1 >= this.source.length) break;
|
|
297
|
-
let next = this.
|
|
312
|
+
let next = this.peek();
|
|
298
313
|
if (is_newline(next)) break;
|
|
299
314
|
this.advance();
|
|
300
315
|
if (is_hex_digit(next)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@projectwallace/css-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "High-performance CSS lexer and parser, optimized for CSS inspection and analysis",
|
|
5
5
|
"author": "Bart Veneman <bart@projectwallace.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
"benchmark:memory": "npm run build && node --expose-gc benchmark/memory.ts",
|
|
61
61
|
"lint": "oxlint --config .oxlintrc.json",
|
|
62
62
|
"lint-package": "publint",
|
|
63
|
-
"check": "tsc --noEmit"
|
|
63
|
+
"check": "tsc --noEmit",
|
|
64
|
+
"precommit": "npm run test -- --run; npm run lint; npm run check"
|
|
64
65
|
},
|
|
65
66
|
"keywords": [
|
|
66
67
|
"css",
|