@projectwallace/css-parser 0.11.0 → 0.11.2
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/parse-atrule-prelude.js +22 -10
- package/dist/parse-selector.js +42 -9
- package/dist/parse.js +1 -1
- package/dist/string-utils.d.ts +15 -0
- package/dist/string-utils.js +12 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Lexer } from './tokenize.js';
|
|
2
|
-
import { CSSDataArena, PRELUDE_OPERATOR, MEDIA_TYPE, MEDIA_QUERY, MEDIA_FEATURE, FUNCTION, IDENTIFIER, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME,
|
|
3
|
-
import { TOKEN_COMMA, TOKEN_IDENT, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_FUNCTION, TOKEN_EOF, TOKEN_WHITESPACE,
|
|
4
|
-
import { str_equals, CHAR_LESS_THAN, CHAR_GREATER_THAN, CHAR_EQUALS, CHAR_COLON, is_whitespace } from './string-utils.js';
|
|
2
|
+
import { CSSDataArena, PRELUDE_OPERATOR, MEDIA_TYPE, MEDIA_QUERY, MEDIA_FEATURE, FUNCTION, IDENTIFIER, CONTAINER_QUERY, SUPPORTS_QUERY, LAYER_NAME, STRING, URL, DIMENSION, NUMBER, FEATURE_RANGE } from './arena.js';
|
|
3
|
+
import { TOKEN_COMMA, TOKEN_IDENT, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_FUNCTION, TOKEN_EOF, TOKEN_WHITESPACE, TOKEN_STRING, TOKEN_URL, TOKEN_DIMENSION, TOKEN_PERCENTAGE, TOKEN_NUMBER } from './token-types.js';
|
|
4
|
+
import { strip_vendor_prefix, str_equals, CHAR_LESS_THAN, CHAR_GREATER_THAN, CHAR_EQUALS, CHAR_COLON, is_whitespace } from './string-utils.js';
|
|
5
5
|
import { trim_boundaries, skip_whitespace_forward } from './parse-utils.js';
|
|
6
6
|
import { CSSNode } from './css-node.js';
|
|
7
7
|
|
|
@@ -26,20 +26,23 @@ class AtRulePreludeParser {
|
|
|
26
26
|
}
|
|
27
27
|
// Dispatch to appropriate parser based on at-rule type
|
|
28
28
|
parse_prelude_dispatch(at_rule_name) {
|
|
29
|
-
|
|
29
|
+
let normalized_name = strip_vendor_prefix(at_rule_name);
|
|
30
|
+
if (str_equals("media", normalized_name)) {
|
|
30
31
|
return this.parse_media_query_list();
|
|
31
|
-
} else if (str_equals("container",
|
|
32
|
+
} else if (str_equals("container", normalized_name)) {
|
|
32
33
|
return this.parse_container_query();
|
|
33
|
-
} else if (str_equals("supports",
|
|
34
|
+
} else if (str_equals("supports", normalized_name)) {
|
|
34
35
|
return this.parse_supports_query();
|
|
35
|
-
} else if (str_equals("layer",
|
|
36
|
+
} else if (str_equals("layer", normalized_name)) {
|
|
36
37
|
return this.parse_layer_names();
|
|
37
|
-
} else if (str_equals("keyframes",
|
|
38
|
+
} else if (str_equals("keyframes", normalized_name)) {
|
|
38
39
|
return this.parse_identifier();
|
|
39
|
-
} else if (str_equals("property",
|
|
40
|
+
} else if (str_equals("property", normalized_name)) {
|
|
40
41
|
return this.parse_identifier();
|
|
41
|
-
} else if (str_equals("import",
|
|
42
|
+
} else if (str_equals("import", normalized_name)) {
|
|
42
43
|
return this.parse_import_prelude();
|
|
44
|
+
} else if (str_equals("charset", normalized_name)) {
|
|
45
|
+
return this.parse_charset_prelude();
|
|
43
46
|
}
|
|
44
47
|
return [];
|
|
45
48
|
}
|
|
@@ -303,6 +306,15 @@ class AtRulePreludeParser {
|
|
|
303
306
|
let ident = this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end);
|
|
304
307
|
return [ident];
|
|
305
308
|
}
|
|
309
|
+
// Parse @charset prelude: "UTF-8"
|
|
310
|
+
parse_charset_prelude() {
|
|
311
|
+
this.skip_whitespace();
|
|
312
|
+
if (this.lexer.pos >= this.prelude_end) return [];
|
|
313
|
+
this.next_token();
|
|
314
|
+
if (this.lexer.token_type !== TOKEN_STRING) return [];
|
|
315
|
+
let str = this.create_node(STRING, this.lexer.token_start, this.lexer.token_end);
|
|
316
|
+
return [str];
|
|
317
|
+
}
|
|
306
318
|
// Parse @import prelude: url() [layer] [supports()] [media-query-list]
|
|
307
319
|
// @import url("styles.css") layer(base) supports(display: grid) screen and (min-width: 768px);
|
|
308
320
|
parse_import_prelude() {
|
package/dist/parse-selector.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Lexer } from './tokenize.js';
|
|
2
2
|
import { CSSDataArena, SELECTOR_LIST, SELECTOR, COMBINATOR, NESTING_SELECTOR, ID_SELECTOR, TYPE_SELECTOR, UNIVERSAL_SELECTOR, CLASS_SELECTOR, ATTRIBUTE_SELECTOR, ATTR_OPERATOR_NONE, ATTR_FLAG_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_CASE_INSENSITIVE, ATTR_FLAG_CASE_SENSITIVE, PSEUDO_ELEMENT_SELECTOR, PSEUDO_CLASS_SELECTOR, FLAG_HAS_PARENS, LANG_SELECTOR, NTH_OF_SELECTOR } from './arena.js';
|
|
3
|
-
import { TOKEN_COMMA, TOKEN_DELIM, TOKEN_EOF, TOKEN_WHITESPACE, TOKEN_FUNCTION, TOKEN_COLON, TOKEN_LEFT_BRACKET, TOKEN_HASH, TOKEN_IDENT, TOKEN_RIGHT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_STRING } from './token-types.js';
|
|
3
|
+
import { TOKEN_COMMENT, TOKEN_COMMA, TOKEN_DELIM, TOKEN_EOF, TOKEN_WHITESPACE, TOKEN_FUNCTION, TOKEN_COLON, TOKEN_LEFT_BRACKET, TOKEN_HASH, TOKEN_IDENT, TOKEN_RIGHT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_STRING } from './token-types.js';
|
|
4
4
|
import { skip_whitespace_and_comments_forward, skip_whitespace_and_comments_backward, skip_whitespace_forward } from './parse-utils.js';
|
|
5
5
|
import { CHAR_GREATER_THAN, CHAR_PLUS, CHAR_TILDE, CHAR_PERIOD, CHAR_ASTERISK, CHAR_AMPERSAND, CHAR_PIPE, CHAR_SPACE, CHAR_TAB, CHAR_NEWLINE, CHAR_CARRIAGE_RETURN, CHAR_FORM_FEED, is_combinator, is_whitespace, CHAR_EQUALS, CHAR_CARET, CHAR_DOLLAR, CHAR_SINGLE_QUOTE, CHAR_DOUBLE_QUOTE, CHAR_COLON, str_equals } from './string-utils.js';
|
|
6
6
|
import { ANplusBParser } from './parse-anplusb.js';
|
|
@@ -52,10 +52,29 @@ class SelectorParser {
|
|
|
52
52
|
}
|
|
53
53
|
this.skip_whitespace();
|
|
54
54
|
if (this.lexer.pos >= this.selector_end) break;
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
let token_type = TOKEN_EOF;
|
|
56
|
+
while (this.lexer.pos < this.selector_end) {
|
|
57
|
+
this.lexer.next_token_fast(false);
|
|
58
|
+
token_type = this.lexer.token_type;
|
|
59
|
+
if (token_type === TOKEN_COMMENT) {
|
|
60
|
+
this.skip_whitespace();
|
|
61
|
+
} else {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
57
65
|
if (token_type === TOKEN_COMMA) {
|
|
58
66
|
this.skip_whitespace();
|
|
67
|
+
while (this.lexer.pos < this.selector_end) {
|
|
68
|
+
const saved = this.lexer.save_position();
|
|
69
|
+
this.lexer.next_token_fast(false);
|
|
70
|
+
token_type = this.lexer.token_type;
|
|
71
|
+
if (token_type === TOKEN_COMMENT) {
|
|
72
|
+
this.skip_whitespace();
|
|
73
|
+
} else {
|
|
74
|
+
this.lexer.restore_position(saved);
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
59
78
|
continue;
|
|
60
79
|
} else {
|
|
61
80
|
break;
|
|
@@ -81,7 +100,7 @@ class SelectorParser {
|
|
|
81
100
|
if (token_type === TOKEN_DELIM) {
|
|
82
101
|
let ch = this.source.charCodeAt(this.lexer.token_start);
|
|
83
102
|
if (ch === CHAR_GREATER_THAN || ch === CHAR_PLUS || ch === CHAR_TILDE) {
|
|
84
|
-
let combinator = this.
|
|
103
|
+
let combinator = this.create_node_at(COMBINATOR, this.lexer.token_start, this.lexer.token_end, this.lexer.token_line, this.lexer.token_column);
|
|
85
104
|
components.push(combinator);
|
|
86
105
|
this.skip_whitespace();
|
|
87
106
|
} else {
|
|
@@ -237,40 +256,48 @@ class SelectorParser {
|
|
|
237
256
|
// Parse combinator (>, +, ~, or descendant space)
|
|
238
257
|
try_parse_combinator() {
|
|
239
258
|
let whitespace_start = this.lexer.pos;
|
|
259
|
+
let whitespace_start_line = this.lexer.line;
|
|
260
|
+
let whitespace_start_column = this.lexer.column;
|
|
240
261
|
let has_whitespace = false;
|
|
241
262
|
while (this.lexer.pos < this.selector_end) {
|
|
242
263
|
let ch = this.source.charCodeAt(this.lexer.pos);
|
|
243
264
|
if (ch === CHAR_SPACE || ch === CHAR_TAB || ch === CHAR_NEWLINE || ch === CHAR_CARRIAGE_RETURN || ch === CHAR_FORM_FEED) {
|
|
244
265
|
has_whitespace = true;
|
|
245
|
-
this.lexer.
|
|
266
|
+
this.lexer.advance();
|
|
246
267
|
} else {
|
|
247
268
|
break;
|
|
248
269
|
}
|
|
249
270
|
}
|
|
250
271
|
if (this.lexer.pos >= this.selector_end) {
|
|
251
272
|
this.lexer.pos = whitespace_start;
|
|
273
|
+
this.lexer.line = whitespace_start_line;
|
|
274
|
+
this.lexer.column = whitespace_start_column;
|
|
252
275
|
return null;
|
|
253
276
|
}
|
|
254
277
|
this.lexer.next_token_fast(false);
|
|
255
278
|
if (this.lexer.token_type === TOKEN_DELIM) {
|
|
256
279
|
let ch = this.source.charCodeAt(this.lexer.token_start);
|
|
257
280
|
if (is_combinator(ch)) {
|
|
258
|
-
return this.
|
|
281
|
+
return this.create_node_at(COMBINATOR, this.lexer.token_start, this.lexer.token_end, this.lexer.token_line, this.lexer.token_column);
|
|
259
282
|
}
|
|
260
283
|
}
|
|
261
284
|
if (has_whitespace) {
|
|
262
285
|
this.lexer.pos = whitespace_start;
|
|
286
|
+
this.lexer.line = whitespace_start_line;
|
|
287
|
+
this.lexer.column = whitespace_start_column;
|
|
263
288
|
while (this.lexer.pos < this.selector_end) {
|
|
264
289
|
let ch = this.source.charCodeAt(this.lexer.pos);
|
|
265
290
|
if (ch === CHAR_SPACE || ch === CHAR_TAB || ch === CHAR_NEWLINE || ch === CHAR_CARRIAGE_RETURN || ch === CHAR_FORM_FEED) {
|
|
266
|
-
this.lexer.
|
|
291
|
+
this.lexer.advance();
|
|
267
292
|
} else {
|
|
268
293
|
break;
|
|
269
294
|
}
|
|
270
295
|
}
|
|
271
|
-
return this.
|
|
296
|
+
return this.create_node_at(COMBINATOR, whitespace_start, this.lexer.pos, whitespace_start_line, whitespace_start_column);
|
|
272
297
|
}
|
|
273
298
|
this.lexer.pos = whitespace_start;
|
|
299
|
+
this.lexer.line = whitespace_start_line;
|
|
300
|
+
this.lexer.column = whitespace_start_column;
|
|
274
301
|
return null;
|
|
275
302
|
}
|
|
276
303
|
// Parse class selector (.classname)
|
|
@@ -572,7 +599,13 @@ class SelectorParser {
|
|
|
572
599
|
return -1;
|
|
573
600
|
}
|
|
574
601
|
create_node(type, start, end) {
|
|
575
|
-
let node = this.arena.create_node(type, start, end - start, this.lexer.
|
|
602
|
+
let node = this.arena.create_node(type, start, end - start, this.lexer.token_line, this.lexer.token_column);
|
|
603
|
+
this.arena.set_content_start_delta(node, 0);
|
|
604
|
+
this.arena.set_content_length(node, end - start);
|
|
605
|
+
return node;
|
|
606
|
+
}
|
|
607
|
+
create_node_at(type, start, end, line, column) {
|
|
608
|
+
let node = this.arena.create_node(type, start, end - start, line, column);
|
|
576
609
|
this.arena.set_content_start_delta(node, 0);
|
|
577
610
|
this.arena.set_content_length(node, end - start);
|
|
578
611
|
return node;
|
package/dist/parse.js
CHANGED
|
@@ -226,9 +226,9 @@ class Parser {
|
|
|
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_wrapper = this.arena.create_node(AT_RULE_PRELUDE, trimmed[0], trimmed[1] - trimmed[0], at_rule_line, at_rule_column);
|
|
229
230
|
let prelude_nodes = this.prelude_parser.parse_prelude(at_rule_name, trimmed[0], trimmed[1], at_rule_line, at_rule_column);
|
|
230
231
|
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
232
|
this.arena.append_children(prelude_wrapper, prelude_nodes);
|
|
233
233
|
}
|
|
234
234
|
}
|
package/dist/string-utils.d.ts
CHANGED
|
@@ -82,3 +82,18 @@ export declare function is_vendor_prefixed(source: string, start: number, end: n
|
|
|
82
82
|
* - `color` → false
|
|
83
83
|
*/
|
|
84
84
|
export declare function is_custom(str: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Strip vendor prefix from a string
|
|
87
|
+
*
|
|
88
|
+
* @param str - The string to strip vendor prefix from
|
|
89
|
+
* @returns The string without vendor prefix, or original string if no prefix found
|
|
90
|
+
*
|
|
91
|
+
* Examples:
|
|
92
|
+
* - `-webkit-keyframes` → `keyframes`
|
|
93
|
+
* - `-moz-appearance` → `appearance`
|
|
94
|
+
* - `-ms-filter` → `filter`
|
|
95
|
+
* - `-o-border-image` → `border-image`
|
|
96
|
+
* - `keyframes` → `keyframes` (no change)
|
|
97
|
+
* - `--custom-property` → `--custom-property` (custom property, not vendor prefix)
|
|
98
|
+
*/
|
|
99
|
+
export declare function strip_vendor_prefix(str: string): string;
|
package/dist/string-utils.js
CHANGED
|
@@ -114,5 +114,16 @@ function is_custom(str) {
|
|
|
114
114
|
if (str.length < 3) return false;
|
|
115
115
|
return str.charCodeAt(0) === CHAR_MINUS_HYPHEN && str.charCodeAt(1) === CHAR_MINUS_HYPHEN;
|
|
116
116
|
}
|
|
117
|
+
function strip_vendor_prefix(str) {
|
|
118
|
+
if (!is_vendor_prefixed(str)) {
|
|
119
|
+
return str;
|
|
120
|
+
}
|
|
121
|
+
for (let i = 2; i < str.length; i++) {
|
|
122
|
+
if (str.charCodeAt(i) === CHAR_MINUS_HYPHEN) {
|
|
123
|
+
return str.substring(i + 1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return str;
|
|
127
|
+
}
|
|
117
128
|
|
|
118
|
-
export { CHAR_AMPERSAND, CHAR_ASTERISK, CHAR_CARET, CHAR_CARRIAGE_RETURN, CHAR_COLON, CHAR_DOLLAR, CHAR_DOUBLE_QUOTE, CHAR_EQUALS, CHAR_FORM_FEED, CHAR_FORWARD_SLASH, CHAR_GREATER_THAN, CHAR_LESS_THAN, CHAR_MINUS_HYPHEN, CHAR_NEWLINE, CHAR_PERIOD, CHAR_PIPE, CHAR_PLUS, CHAR_SINGLE_QUOTE, CHAR_SPACE, CHAR_TAB, CHAR_TILDE, is_combinator, is_custom, is_digit, is_vendor_prefixed, is_whitespace, str_equals, str_index_of, str_starts_with };
|
|
129
|
+
export { CHAR_AMPERSAND, CHAR_ASTERISK, CHAR_CARET, CHAR_CARRIAGE_RETURN, CHAR_COLON, CHAR_DOLLAR, CHAR_DOUBLE_QUOTE, CHAR_EQUALS, CHAR_FORM_FEED, CHAR_FORWARD_SLASH, CHAR_GREATER_THAN, CHAR_LESS_THAN, CHAR_MINUS_HYPHEN, CHAR_NEWLINE, CHAR_PERIOD, CHAR_PIPE, CHAR_PLUS, CHAR_SINGLE_QUOTE, CHAR_SPACE, CHAR_TAB, CHAR_TILDE, is_combinator, is_custom, is_digit, is_vendor_prefixed, is_whitespace, str_equals, str_index_of, str_starts_with, strip_vendor_prefix };
|
package/package.json
CHANGED