@projectwallace/css-parser 0.12.1 → 0.12.3
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-anplusb.js +2 -2
- package/dist/parse-atrule-prelude.js +16 -8
- package/dist/parse-selector.js +25 -5
- package/package.json +1 -1
package/dist/parse-anplusb.js
CHANGED
|
@@ -2,7 +2,7 @@ import { Lexer } from './tokenize.js';
|
|
|
2
2
|
import { NTH_SELECTOR, CSSDataArena } from './arena.js';
|
|
3
3
|
import { TOKEN_IDENT, TOKEN_DELIM, TOKEN_DIMENSION, TOKEN_NUMBER } from './token-types.js';
|
|
4
4
|
import { str_equals, CHAR_MINUS_HYPHEN, CHAR_PLUS, str_index_of } from './string-utils.js';
|
|
5
|
-
import {
|
|
5
|
+
import { skip_whitespace_and_comments_forward } from './parse-utils.js';
|
|
6
6
|
import { CSSNode } from './css-node.js';
|
|
7
7
|
|
|
8
8
|
class ANplusBParser {
|
|
@@ -186,7 +186,7 @@ class ANplusBParser {
|
|
|
186
186
|
return null;
|
|
187
187
|
}
|
|
188
188
|
skip_whitespace() {
|
|
189
|
-
this.lexer.pos =
|
|
189
|
+
this.lexer.pos = skip_whitespace_and_comments_forward(this.source, this.lexer.pos, this.expr_end);
|
|
190
190
|
}
|
|
191
191
|
create_anplusb_node(start, a_start, a_end, b_start, b_end) {
|
|
192
192
|
const node = this.arena.create_node(NTH_SELECTOR, start, this.lexer.pos - start, this.lexer.line, 1);
|
|
@@ -2,7 +2,7 @@ import { Lexer } from './tokenize.js';
|
|
|
2
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
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
4
|
import { strip_vendor_prefix, str_equals, CHAR_LESS_THAN, CHAR_GREATER_THAN, CHAR_EQUALS, CHAR_COLON, is_whitespace } from './string-utils.js';
|
|
5
|
-
import {
|
|
5
|
+
import { skip_whitespace_and_comments_forward, trim_boundaries } from './parse-utils.js';
|
|
6
6
|
import { CSSNode } from './css-node.js';
|
|
7
7
|
|
|
8
8
|
class AtRulePreludeParser {
|
|
@@ -134,23 +134,31 @@ class AtRulePreludeParser {
|
|
|
134
134
|
let content_end = this.lexer.token_start;
|
|
135
135
|
let feature_end = this.lexer.token_end;
|
|
136
136
|
let has_comparison = false;
|
|
137
|
-
|
|
137
|
+
let i = content_start;
|
|
138
|
+
while (i < content_end) {
|
|
139
|
+
i = skip_whitespace_and_comments_forward(this.source, i, content_end);
|
|
140
|
+
if (i >= content_end) break;
|
|
138
141
|
let ch = this.source.charCodeAt(i);
|
|
139
142
|
if (ch === CHAR_LESS_THAN || ch === CHAR_GREATER_THAN || ch === CHAR_EQUALS) {
|
|
140
143
|
has_comparison = true;
|
|
141
144
|
break;
|
|
142
145
|
}
|
|
146
|
+
i++;
|
|
143
147
|
}
|
|
144
148
|
if (has_comparison) {
|
|
145
149
|
return this.parse_feature_range(feature_start, feature_end, content_start, content_end);
|
|
146
150
|
}
|
|
147
151
|
let feature = this.create_node(MEDIA_FEATURE, feature_start, feature_end);
|
|
148
152
|
let colon_pos = -1;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
let j = content_start;
|
|
154
|
+
while (j < content_end) {
|
|
155
|
+
j = skip_whitespace_and_comments_forward(this.source, j, content_end);
|
|
156
|
+
if (j >= content_end) break;
|
|
157
|
+
if (this.source.charCodeAt(j) === CHAR_COLON) {
|
|
158
|
+
colon_pos = j;
|
|
152
159
|
break;
|
|
153
160
|
}
|
|
161
|
+
j++;
|
|
154
162
|
}
|
|
155
163
|
if (colon_pos !== -1) {
|
|
156
164
|
let name_trimmed = trim_boundaries(this.source, content_start, colon_pos);
|
|
@@ -458,9 +466,9 @@ class AtRulePreludeParser {
|
|
|
458
466
|
this.lexer.restore_position(saved);
|
|
459
467
|
return null;
|
|
460
468
|
}
|
|
461
|
-
// Helper: Skip whitespace
|
|
469
|
+
// Helper: Skip whitespace and comments
|
|
462
470
|
skip_whitespace() {
|
|
463
|
-
this.lexer.pos =
|
|
471
|
+
this.lexer.pos = skip_whitespace_and_comments_forward(this.source, this.lexer.pos, this.prelude_end);
|
|
464
472
|
}
|
|
465
473
|
// Helper: Peek at next token type without consuming
|
|
466
474
|
peek_token_type() {
|
|
@@ -524,7 +532,7 @@ class AtRulePreludeParser {
|
|
|
524
532
|
let feature_name_end = -1;
|
|
525
533
|
let pos = content_start;
|
|
526
534
|
while (pos < content_end) {
|
|
527
|
-
pos =
|
|
535
|
+
pos = skip_whitespace_and_comments_forward(this.source, pos, content_end);
|
|
528
536
|
if (pos >= content_end) break;
|
|
529
537
|
let ch = this.source.charCodeAt(pos);
|
|
530
538
|
if (ch === CHAR_LESS_THAN || ch === CHAR_GREATER_THAN || ch === CHAR_EQUALS) {
|
package/dist/parse-selector.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Lexer } from './tokenize.js';
|
|
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';
|
|
2
|
+
import { CSSDataArena, SELECTOR_LIST, SELECTOR, COMBINATOR, DIMENSION, 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_PERCENTAGE, 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, is_combinator, is_whitespace, CHAR_EQUALS, CHAR_CARET, CHAR_DOLLAR, CHAR_SINGLE_QUOTE, CHAR_DOUBLE_QUOTE, CHAR_COLON, str_equals, CHAR_FORWARD_SLASH } from './string-utils.js';
|
|
6
6
|
import { ANplusBParser } from './parse-anplusb.js';
|
|
@@ -193,6 +193,8 @@ class SelectorParser {
|
|
|
193
193
|
return this.parse_pseudo(start);
|
|
194
194
|
case TOKEN_FUNCTION:
|
|
195
195
|
return this.parse_pseudo_function(start, end);
|
|
196
|
+
case TOKEN_PERCENTAGE:
|
|
197
|
+
return this.create_node(DIMENSION, start, end);
|
|
196
198
|
case TOKEN_WHITESPACE:
|
|
197
199
|
case TOKEN_COMMA:
|
|
198
200
|
return null;
|
|
@@ -222,22 +224,30 @@ class SelectorParser {
|
|
|
222
224
|
// Parse type selector or namespace selector (ns|E or ns|*)
|
|
223
225
|
// Called when we've seen an IDENT token
|
|
224
226
|
parse_type_or_namespace_selector(start, end) {
|
|
227
|
+
const saved = this.lexer.save_position();
|
|
228
|
+
this.skip_whitespace();
|
|
225
229
|
if (this.lexer.pos < this.selector_end && this.source.charCodeAt(this.lexer.pos) === CHAR_PIPE) {
|
|
226
230
|
this.lexer.pos++;
|
|
227
231
|
let node = this.parse_namespace_local_part(start, start, end - start);
|
|
228
232
|
if (node !== null) return node;
|
|
229
233
|
this.lexer.pos = end;
|
|
234
|
+
} else {
|
|
235
|
+
this.lexer.restore_position(saved);
|
|
230
236
|
}
|
|
231
237
|
return this.create_node(TYPE_SELECTOR, start, end);
|
|
232
238
|
}
|
|
233
239
|
// Parse universal selector or namespace selector (*|E or *|*)
|
|
234
240
|
// Called when we've seen a * DELIM token
|
|
235
241
|
parse_universal_or_namespace_selector(start, end) {
|
|
242
|
+
const saved = this.lexer.save_position();
|
|
243
|
+
this.skip_whitespace();
|
|
236
244
|
if (this.lexer.pos < this.selector_end && this.source.charCodeAt(this.lexer.pos) === CHAR_PIPE) {
|
|
237
245
|
this.lexer.pos++;
|
|
238
246
|
let node = this.parse_namespace_local_part(start, start, end - start);
|
|
239
247
|
if (node !== null) return node;
|
|
240
248
|
this.lexer.pos = end;
|
|
249
|
+
} else {
|
|
250
|
+
this.lexer.restore_position(saved);
|
|
241
251
|
}
|
|
242
252
|
return this.create_node(UNIVERSAL_SELECTOR, start, end);
|
|
243
253
|
}
|
|
@@ -420,10 +430,14 @@ class SelectorParser {
|
|
|
420
430
|
// Parse pseudo-class or pseudo-element (:hover, ::before)
|
|
421
431
|
parse_pseudo(start) {
|
|
422
432
|
const saved = this.lexer.save_position();
|
|
433
|
+
const saved_ws = this.lexer.save_position();
|
|
434
|
+
this.skip_whitespace();
|
|
423
435
|
let is_pseudo_element = false;
|
|
424
436
|
if (this.lexer.pos < this.selector_end && this.source.charCodeAt(this.lexer.pos) === CHAR_COLON) {
|
|
425
437
|
is_pseudo_element = true;
|
|
426
438
|
this.lexer.pos++;
|
|
439
|
+
} else {
|
|
440
|
+
this.lexer.restore_position(saved_ws);
|
|
427
441
|
}
|
|
428
442
|
this.lexer.next_token_fast(false);
|
|
429
443
|
let token_type = this.lexer.token_type;
|
|
@@ -564,16 +578,22 @@ class SelectorParser {
|
|
|
564
578
|
return anplusb_parser.parse_anplusb(start, end, this.lexer.line);
|
|
565
579
|
}
|
|
566
580
|
}
|
|
567
|
-
// Find the position of standalone "of" keyword
|
|
581
|
+
// Find the position of standalone "of" keyword (case-insensitive)
|
|
568
582
|
find_of_keyword(start, end) {
|
|
569
|
-
|
|
570
|
-
|
|
583
|
+
let i = start;
|
|
584
|
+
while (i < end - 1) {
|
|
585
|
+
i = skip_whitespace_and_comments_forward(this.source, i, end);
|
|
586
|
+
if (i >= end - 1) break;
|
|
587
|
+
let ch1 = this.source.charCodeAt(i);
|
|
588
|
+
let ch2 = this.source.charCodeAt(i + 1);
|
|
589
|
+
if ((ch1 === 111 || ch1 === 79) && (ch2 === 102 || ch2 === 70)) {
|
|
571
590
|
let before_ok = i === start || is_whitespace(this.source.charCodeAt(i - 1));
|
|
572
591
|
let after_ok = i + 2 >= end || is_whitespace(this.source.charCodeAt(i + 2));
|
|
573
592
|
if (before_ok && after_ok) {
|
|
574
593
|
return i;
|
|
575
594
|
}
|
|
576
595
|
}
|
|
596
|
+
i++;
|
|
577
597
|
}
|
|
578
598
|
return -1;
|
|
579
599
|
}
|
package/package.json
CHANGED