@projectwallace/css-parser 0.13.5 → 0.13.6

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.
Files changed (41) hide show
  1. package/dist/css-node-2ejJUrIw.js +645 -0
  2. package/dist/css-node-DqyvMXBN.d.ts +313 -0
  3. package/dist/index.d.ts +150 -16
  4. package/dist/index.js +103 -13
  5. package/dist/parse-anplusb.d.ts +26 -2
  6. package/dist/parse-anplusb.js +191 -207
  7. package/dist/parse-atrule-prelude.d.ts +40 -2
  8. package/dist/parse-atrule-prelude.js +556 -652
  9. package/dist/parse-declaration.d.ts +16 -2
  10. package/dist/parse-declaration.js +140 -167
  11. package/dist/parse-dimension-CCn_XRDe.js +177 -0
  12. package/dist/parse-dimension.d.ts +6 -3
  13. package/dist/parse-dimension.js +1 -35
  14. package/dist/parse-selector.d.ts +37 -2
  15. package/dist/parse-selector.js +508 -635
  16. package/dist/parse-utils-DnsZRpfd.js +98 -0
  17. package/dist/parse-value.d.ts +23 -2
  18. package/dist/parse-value.js +176 -224
  19. package/dist/parse.d.ts +38 -8
  20. package/dist/parse.js +274 -353
  21. package/dist/tokenize-BQFB1jXg.js +540 -0
  22. package/dist/tokenize-odLrcjj2.d.ts +110 -0
  23. package/dist/tokenize.d.ts +2 -26
  24. package/dist/tokenize.js +1 -545
  25. package/package.json +20 -26
  26. package/dist/arena.d.ts +0 -60
  27. package/dist/arena.js +0 -291
  28. package/dist/char-types.d.ts +0 -14
  29. package/dist/char-types.js +0 -53
  30. package/dist/constants.d.ts +0 -44
  31. package/dist/constants.js +0 -51
  32. package/dist/css-node.d.ts +0 -203
  33. package/dist/css-node.js +0 -498
  34. package/dist/parse-utils.d.ts +0 -1
  35. package/dist/parse-utils.js +0 -60
  36. package/dist/string-utils.d.ts +0 -99
  37. package/dist/string-utils.js +0 -129
  38. package/dist/token-types.d.ts +0 -35
  39. package/dist/token-types.js +0 -29
  40. package/dist/walk.d.ts +0 -28
  41. package/dist/walk.js +0 -51
@@ -1,655 +1,559 @@
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, STRING, URL, DIMENSION, NUMBER, PRELUDE_SELECTORLIST, 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
- import { skip_whitespace_and_comments_forward, trim_boundaries } from './parse-utils.js';
6
- import { CSSNode } from './css-node.js';
7
-
8
- class AtRulePreludeParser {
9
- lexer;
10
- arena;
11
- source;
12
- prelude_end;
13
- constructor(arena, source) {
14
- this.arena = arena;
15
- this.source = source;
16
- this.lexer = new Lexer(source);
17
- this.prelude_end = 0;
18
- }
19
- // Parse an at-rule prelude into nodes (standalone use)
20
- parse_prelude(at_rule_name, start, end, line = 1, column = 1) {
21
- this.prelude_end = end;
22
- this.lexer.seek(start, line, column);
23
- return this.parse_prelude_dispatch(at_rule_name);
24
- }
25
- // Dispatch to appropriate parser based on at-rule type
26
- parse_prelude_dispatch(at_rule_name) {
27
- let normalized_name = strip_vendor_prefix(at_rule_name).toLowerCase();
28
- switch (normalized_name) {
29
- case "media":
30
- return this.parse_media_query_list();
31
- case "container":
32
- return this.parse_container_query();
33
- case "supports":
34
- return this.parse_supports_query();
35
- case "layer":
36
- return this.parse_layer_names();
37
- case "keyframes":
38
- case "property":
39
- case "counter-style":
40
- case "color-profile":
41
- case "font-palette-values":
42
- case "position-try":
43
- case "font-feature-values":
44
- case "page":
45
- return this.parse_identifier();
46
- case "import":
47
- return this.parse_import_prelude();
48
- case "charset":
49
- return this.parse_charset_prelude();
50
- case "namespace":
51
- return this.parse_namespace_prelude();
52
- case "scope":
53
- return this.parse_scope_prelude();
54
- case "custom-media":
55
- return this.parse_custom_media_prelude();
56
- }
57
- return [];
58
- }
59
- // Parse media query list: screen, (min-width: 768px), ...
60
- parse_media_query_list() {
61
- let nodes = [];
62
- while (this.lexer.pos < this.prelude_end) {
63
- this.skip_whitespace();
64
- if (this.lexer.pos >= this.prelude_end) break;
65
- let query = this.parse_single_media_query();
66
- if (query !== null) {
67
- nodes.push(query);
68
- }
69
- this.skip_whitespace();
70
- const saved = this.lexer.save_position();
71
- this.next_token();
72
- if (this.lexer.token_type !== TOKEN_COMMA) {
73
- this.lexer.restore_position(saved);
74
- }
75
- }
76
- return nodes;
77
- }
78
- create_node(type, start, end) {
79
- return this.arena.create_node(type, start, end - start, this.lexer.token_line, this.lexer.token_column);
80
- }
81
- is_and_or_not(str) {
82
- return str_equals("and", str) || str_equals("or", str) || str_equals("not", str);
83
- }
84
- // Parse a single media query: screen and (min-width: 768px)
85
- parse_single_media_query() {
86
- let query_start = this.lexer.pos;
87
- this.skip_whitespace();
88
- if (this.lexer.pos >= this.prelude_end) return null;
89
- const saved_token_start = this.lexer.save_position();
90
- this.next_token();
91
- if (this.lexer.token_type === TOKEN_IDENT) {
92
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
93
- if (!str_equals("only", text) && !str_equals("not", text)) {
94
- this.lexer.restore_position(saved_token_start);
95
- }
96
- } else {
97
- this.lexer.restore_position(saved_token_start);
98
- }
99
- let components = [];
100
- while (this.lexer.pos < this.prelude_end) {
101
- this.skip_whitespace();
102
- if (this.lexer.pos >= this.prelude_end) break;
103
- if (this.peek_token_type() === TOKEN_COMMA) break;
104
- this.next_token();
105
- let token_type = this.lexer.token_type;
106
- if (token_type === TOKEN_LEFT_PAREN) {
107
- let feature = this.parse_media_feature();
108
- if (feature !== null) {
109
- components.push(feature);
110
- }
111
- } else if (token_type === TOKEN_IDENT) {
112
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
113
- if (this.is_and_or_not(text)) {
114
- let op = this.create_node(PRELUDE_OPERATOR, this.lexer.token_start, this.lexer.token_end);
115
- components.push(op);
116
- } else {
117
- let media_type = this.create_node(MEDIA_TYPE, this.lexer.token_start, this.lexer.token_end);
118
- components.push(media_type);
119
- }
120
- } else {
121
- break;
122
- }
123
- }
124
- if (components.length === 0) return null;
125
- let query_node = this.create_node(MEDIA_QUERY, query_start, this.lexer.pos);
126
- this.arena.append_children(query_node, components);
127
- return query_node;
128
- }
129
- // Parse media feature: (min-width: 768px) or range: (50px <= width <= 100px)
130
- parse_media_feature() {
131
- let feature_start = this.lexer.token_start;
132
- let depth = 1;
133
- let content_start = this.lexer.pos;
134
- while (this.lexer.pos < this.prelude_end && depth > 0) {
135
- this.next_token();
136
- let token_type = this.lexer.token_type;
137
- if (token_type === TOKEN_LEFT_PAREN) {
138
- depth++;
139
- } else if (token_type === TOKEN_RIGHT_PAREN) {
140
- depth--;
141
- }
142
- }
143
- if (depth !== 0) return null;
144
- let content_end = this.lexer.token_start;
145
- let feature_end = this.lexer.token_end;
146
- let has_comparison = false;
147
- let i = content_start;
148
- while (i < content_end) {
149
- i = skip_whitespace_and_comments_forward(this.source, i, content_end);
150
- if (i >= content_end) break;
151
- let ch = this.source.charCodeAt(i);
152
- if (ch === CHAR_LESS_THAN || ch === CHAR_GREATER_THAN || ch === CHAR_EQUALS) {
153
- has_comparison = true;
154
- break;
155
- }
156
- i++;
157
- }
158
- if (has_comparison) {
159
- return this.parse_feature_range(feature_start, feature_end, content_start, content_end);
160
- }
161
- let feature = this.create_node(MEDIA_FEATURE, feature_start, feature_end);
162
- let colon_pos = -1;
163
- let j = content_start;
164
- while (j < content_end) {
165
- j = skip_whitespace_and_comments_forward(this.source, j, content_end);
166
- if (j >= content_end) break;
167
- if (this.source.charCodeAt(j) === CHAR_COLON) {
168
- colon_pos = j;
169
- break;
170
- }
171
- j++;
172
- }
173
- if (colon_pos !== -1) {
174
- let name_trimmed = trim_boundaries(this.source, content_start, colon_pos);
175
- if (name_trimmed) {
176
- this.arena.set_content_start_delta(feature, name_trimmed[0] - feature_start);
177
- this.arena.set_content_length(feature, name_trimmed[1] - name_trimmed[0]);
178
- }
179
- let value_trimmed = trim_boundaries(this.source, colon_pos + 1, content_end);
180
- if (value_trimmed) {
181
- let value_nodes = this.parse_feature_value(value_trimmed[0], value_trimmed[1]);
182
- if (value_nodes.length > 0) {
183
- this.arena.append_children(feature, value_nodes);
184
- }
185
- }
186
- } else {
187
- let trimmed = trim_boundaries(this.source, content_start, content_end);
188
- if (trimmed) {
189
- this.arena.set_content_start_delta(feature, trimmed[0] - feature_start);
190
- this.arena.set_content_length(feature, trimmed[1] - trimmed[0]);
191
- }
192
- }
193
- return feature;
194
- }
195
- // Parse container query: [name] and (min-width: 400px)
196
- parse_container_query() {
197
- let nodes = [];
198
- let query_start = this.lexer.pos;
199
- let components = [];
200
- while (this.lexer.pos < this.prelude_end) {
201
- this.skip_whitespace();
202
- if (this.lexer.pos >= this.prelude_end) break;
203
- this.next_token();
204
- let token_type = this.lexer.token_type;
205
- if (token_type === TOKEN_LEFT_PAREN) {
206
- let feature = this.parse_media_feature();
207
- if (feature !== null) {
208
- components.push(feature);
209
- }
210
- } else if (token_type === TOKEN_FUNCTION) {
211
- let func_name = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
212
- let func_start = this.lexer.token_start;
213
- let content_start = this.lexer.token_end;
214
- let paren_depth = 1;
215
- let func_end = this.lexer.token_end;
216
- let content_end = content_start;
217
- while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
218
- this.next_token();
219
- let inner_token = this.lexer.token_type;
220
- if (inner_token === TOKEN_LEFT_PAREN || inner_token === TOKEN_FUNCTION) {
221
- paren_depth++;
222
- } else if (inner_token === TOKEN_RIGHT_PAREN) {
223
- paren_depth--;
224
- if (paren_depth === 0) {
225
- content_end = this.lexer.token_start;
226
- func_end = this.lexer.token_end;
227
- }
228
- } else if (inner_token === TOKEN_EOF) {
229
- break;
230
- }
231
- }
232
- let func_node = this.create_node(FUNCTION, func_start, func_end);
233
- this.arena.set_content_start_delta(func_node, 0);
234
- this.arena.set_content_length(func_node, func_name.length);
235
- this.arena.set_value_start_delta(func_node, content_start - func_start);
236
- this.arena.set_value_length(func_node, content_end - content_start);
237
- components.push(func_node);
238
- } else if (token_type === TOKEN_IDENT) {
239
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
240
- if (this.is_and_or_not(text)) {
241
- let op = this.create_node(PRELUDE_OPERATOR, this.lexer.token_start, this.lexer.token_end);
242
- components.push(op);
243
- } else {
244
- let name = this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end);
245
- components.push(name);
246
- }
247
- }
248
- }
249
- if (components.length === 0) return [];
250
- let query_node = this.create_node(CONTAINER_QUERY, query_start, this.lexer.pos);
251
- this.arena.append_children(query_node, components);
252
- nodes.push(query_node);
253
- return nodes;
254
- }
255
- // Parse supports query: (display: flex) and (gap: 1rem)
256
- parse_supports_query() {
257
- let nodes = [];
258
- while (this.lexer.pos < this.prelude_end) {
259
- this.skip_whitespace();
260
- if (this.lexer.pos >= this.prelude_end) break;
261
- this.next_token();
262
- let token_type = this.lexer.token_type;
263
- if (token_type === TOKEN_LEFT_PAREN) {
264
- let feature_start = this.lexer.token_start;
265
- let depth = 1;
266
- let content_start = this.lexer.pos;
267
- while (this.lexer.pos < this.prelude_end && depth > 0) {
268
- this.next_token();
269
- let inner_token_type = this.lexer.token_type;
270
- if (inner_token_type === TOKEN_LEFT_PAREN) {
271
- depth++;
272
- } else if (inner_token_type === TOKEN_RIGHT_PAREN) {
273
- depth--;
274
- }
275
- }
276
- if (depth === 0) {
277
- let content_end = this.lexer.token_start;
278
- let feature_end = this.lexer.token_end;
279
- let query = this.create_node(SUPPORTS_QUERY, feature_start, feature_end);
280
- let trimmed = trim_boundaries(this.source, content_start, content_end);
281
- if (trimmed) {
282
- this.arena.set_value_start_delta(query, trimmed[0] - feature_start);
283
- this.arena.set_value_length(query, trimmed[1] - trimmed[0]);
284
- }
285
- nodes.push(query);
286
- }
287
- } else if (token_type === TOKEN_IDENT) {
288
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
289
- if (this.is_and_or_not(text)) {
290
- let op = this.create_node(PRELUDE_OPERATOR, this.lexer.token_start, this.lexer.token_end);
291
- nodes.push(op);
292
- }
293
- }
294
- }
295
- return nodes;
296
- }
297
- // Parse layer names: base, components, utilities
298
- parse_layer_names() {
299
- let nodes = [];
300
- while (this.lexer.pos < this.prelude_end) {
301
- this.skip_whitespace();
302
- if (this.lexer.pos >= this.prelude_end) break;
303
- this.next_token();
304
- let token_type = this.lexer.token_type;
305
- if (token_type === TOKEN_IDENT) {
306
- let layer = this.create_node(LAYER_NAME, this.lexer.token_start, this.lexer.token_end);
307
- this.arena.set_value_start_delta(layer, 0);
308
- this.arena.set_value_length(layer, this.lexer.token_end - this.lexer.token_start);
309
- nodes.push(layer);
310
- } else if (token_type === TOKEN_COMMA) {
311
- continue;
312
- } else if (token_type === TOKEN_WHITESPACE) {
313
- continue;
314
- }
315
- }
316
- return nodes;
317
- }
318
- // Parse single identifier: keyframe name, property name
319
- parse_identifier() {
320
- this.skip_whitespace();
321
- if (this.lexer.pos >= this.prelude_end) return [];
322
- this.next_token();
323
- if (this.lexer.token_type !== TOKEN_IDENT) return [];
324
- let ident = this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end);
325
- return [ident];
326
- }
327
- // Parse @charset prelude: "UTF-8"
328
- parse_charset_prelude() {
329
- this.skip_whitespace();
330
- if (this.lexer.pos >= this.prelude_end) return [];
331
- this.next_token();
332
- if (this.lexer.token_type !== TOKEN_STRING) return [];
333
- let str = this.create_node(STRING, this.lexer.token_start, this.lexer.token_end);
334
- return [str];
335
- }
336
- // Parse @import prelude: url() [layer] [supports()] [media-query-list]
337
- // @import url("styles.css") layer(base) supports(display: grid) screen and (min-width: 768px);
338
- parse_import_prelude() {
339
- let nodes = [];
340
- this.skip_whitespace();
341
- if (this.lexer.pos >= this.prelude_end) return [];
342
- let url_node = this.parse_import_url();
343
- if (url_node !== null) {
344
- nodes.push(url_node);
345
- } else {
346
- return [];
347
- }
348
- this.skip_whitespace();
349
- if (this.lexer.pos >= this.prelude_end) return nodes;
350
- let layer_node = this.parse_import_layer();
351
- if (layer_node !== null) {
352
- nodes.push(layer_node);
353
- }
354
- this.skip_whitespace();
355
- if (this.lexer.pos >= this.prelude_end) return nodes;
356
- let supports_node = this.parse_import_supports();
357
- if (supports_node !== null) {
358
- nodes.push(supports_node);
359
- }
360
- this.skip_whitespace();
361
- if (this.lexer.pos >= this.prelude_end) return nodes;
362
- let media_nodes = this.parse_media_query_list();
363
- nodes.push(...media_nodes);
364
- return nodes;
365
- }
366
- // Parse import URL: url("file.css") or "file.css"
367
- parse_import_url() {
368
- this.next_token();
369
- if (this.lexer.token_type !== TOKEN_URL && this.lexer.token_type !== TOKEN_FUNCTION && this.lexer.token_type !== TOKEN_STRING) {
370
- return null;
371
- }
372
- let url_start = this.lexer.token_start;
373
- let url_end = this.lexer.token_end;
374
- if (this.lexer.token_type === TOKEN_FUNCTION) {
375
- let paren_depth = 1;
376
- while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
377
- let tokenType = this.next_token();
378
- if (tokenType === TOKEN_LEFT_PAREN || tokenType === TOKEN_FUNCTION) {
379
- paren_depth++;
380
- } else if (tokenType === TOKEN_RIGHT_PAREN) {
381
- paren_depth--;
382
- if (paren_depth === 0) {
383
- url_end = this.lexer.token_end;
384
- }
385
- } else if (tokenType === TOKEN_EOF) {
386
- break;
387
- }
388
- }
389
- }
390
- let url_node = this.create_node(URL, url_start, url_end);
391
- return url_node;
392
- }
393
- // Parse import layer: layer or layer(name)
394
- parse_import_layer() {
395
- const saved = this.lexer.save_position();
396
- this.next_token();
397
- if (this.lexer.token_type === TOKEN_IDENT || this.lexer.token_type === TOKEN_FUNCTION) {
398
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
399
- if (this.lexer.token_type === TOKEN_FUNCTION && text.endsWith("(")) {
400
- text = text.slice(0, -1);
401
- }
402
- if (str_equals("layer", text)) {
403
- let layer_start = this.lexer.token_start;
404
- let layer_end = this.lexer.token_end;
405
- let content_start = 0;
406
- let content_length = 0;
407
- if (this.lexer.token_type === TOKEN_FUNCTION) {
408
- content_start = this.lexer.pos;
409
- let paren_depth = 1;
410
- while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
411
- let tokenType = this.next_token();
412
- if (tokenType === TOKEN_LEFT_PAREN || tokenType === TOKEN_FUNCTION) {
413
- paren_depth++;
414
- } else if (tokenType === TOKEN_RIGHT_PAREN) {
415
- paren_depth--;
416
- if (paren_depth === 0) {
417
- content_length = this.lexer.token_start - content_start;
418
- layer_end = this.lexer.token_end;
419
- }
420
- } else if (tokenType === TOKEN_EOF) {
421
- break;
422
- }
423
- }
424
- }
425
- let layer_node = this.create_node(LAYER_NAME, layer_start, layer_end);
426
- if (content_length > 0) {
427
- let trimmed = trim_boundaries(this.source, content_start, content_start + content_length);
428
- if (trimmed) {
429
- this.arena.set_content_start_delta(layer_node, trimmed[0] - layer_start);
430
- this.arena.set_content_length(layer_node, trimmed[1] - trimmed[0]);
431
- this.arena.set_value_start_delta(layer_node, trimmed[0] - layer_start);
432
- this.arena.set_value_length(layer_node, trimmed[1] - trimmed[0]);
433
- }
434
- }
435
- return layer_node;
436
- }
437
- }
438
- this.lexer.restore_position(saved);
439
- return null;
440
- }
441
- // Parse import supports: supports(condition)
442
- parse_import_supports() {
443
- const saved = this.lexer.save_position();
444
- this.next_token();
445
- if (this.lexer.token_type === TOKEN_FUNCTION) {
446
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
447
- if (str_equals("supports", text)) {
448
- let supports_start = this.lexer.token_start;
449
- let content_start = this.lexer.token_end;
450
- let paren_depth = 1;
451
- let supports_end = this.lexer.token_end;
452
- let content_end = content_start;
453
- while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
454
- let tokenType = this.next_token();
455
- if (tokenType === TOKEN_LEFT_PAREN || tokenType === TOKEN_FUNCTION) {
456
- paren_depth++;
457
- } else if (tokenType === TOKEN_RIGHT_PAREN) {
458
- paren_depth--;
459
- if (paren_depth === 0) {
460
- content_end = this.lexer.token_start;
461
- supports_end = this.lexer.token_end;
462
- }
463
- } else if (tokenType === TOKEN_EOF) {
464
- break;
465
- }
466
- }
467
- let supports_node = this.create_node(SUPPORTS_QUERY, supports_start, supports_end);
468
- let trimmed = trim_boundaries(this.source, content_start, content_end);
469
- if (trimmed) {
470
- this.arena.set_value_start_delta(supports_node, trimmed[0] - supports_start);
471
- this.arena.set_value_length(supports_node, trimmed[1] - trimmed[0]);
472
- }
473
- return supports_node;
474
- }
475
- }
476
- this.lexer.restore_position(saved);
477
- return null;
478
- }
479
- // Helper: Skip whitespace and comments
480
- skip_whitespace() {
481
- this.lexer.skip_whitespace_in_range(this.prelude_end);
482
- }
483
- // Helper: Peek at next token type without consuming
484
- peek_token_type() {
485
- const saved = this.lexer.save_position();
486
- this.next_token();
487
- let type = this.lexer.token_type;
488
- this.lexer.restore_position(saved);
489
- return type;
490
- }
491
- // Helper: Get next token
492
- next_token() {
493
- if (this.lexer.pos >= this.prelude_end) {
494
- this.lexer.token_type = TOKEN_EOF;
495
- return TOKEN_EOF;
496
- }
497
- return this.lexer.next_token_fast(false);
498
- }
499
- // Helper: Parse a single value token into a node
500
- parse_value_token() {
501
- switch (this.lexer.token_type) {
502
- case TOKEN_IDENT:
503
- return this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end);
504
- case TOKEN_NUMBER:
505
- return this.create_node(NUMBER, this.lexer.token_start, this.lexer.token_end);
506
- case TOKEN_PERCENTAGE:
507
- case TOKEN_DIMENSION:
508
- return this.create_node(DIMENSION, this.lexer.token_start, this.lexer.token_end);
509
- case TOKEN_STRING:
510
- return this.create_node(STRING, this.lexer.token_start, this.lexer.token_end);
511
- default:
512
- return null;
513
- }
514
- }
515
- // Helper: Parse feature value portion into typed nodes
516
- parse_feature_value(start, end) {
517
- let temp_lexer = new Lexer(this.source);
518
- temp_lexer.seek(start, this.lexer.line, this.lexer.column);
519
- let nodes = [];
520
- let saved_lexer = this.lexer;
521
- this.lexer = temp_lexer;
522
- while (this.lexer.pos < end) {
523
- this.lexer.next_token_fast(false);
524
- if (this.lexer.token_start >= end) break;
525
- let all_whitespace = true;
526
- for (let i = this.lexer.token_start; i < this.lexer.token_end && i < end; i++) {
527
- if (!is_whitespace(this.source.charCodeAt(i))) {
528
- all_whitespace = false;
529
- break;
530
- }
531
- }
532
- if (all_whitespace) continue;
533
- let node = this.parse_value_token();
534
- if (node !== null) nodes.push(node);
535
- }
536
- this.lexer = saved_lexer;
537
- return nodes;
538
- }
539
- // Parse @namespace prelude: [prefix] url("...") | "..."
540
- // e.g. @namespace url("http://www.w3.org/1999/xhtml");
541
- // e.g. @namespace svg url("http://www.w3.org/2000/svg");
542
- parse_namespace_prelude() {
543
- let nodes = [];
544
- this.skip_whitespace();
545
- if (this.lexer.pos >= this.prelude_end) return [];
546
- const saved = this.lexer.save_position();
547
- this.next_token();
548
- if (this.lexer.token_type === TOKEN_IDENT) {
549
- nodes.push(this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end));
550
- this.skip_whitespace();
551
- } else {
552
- this.lexer.restore_position(saved);
553
- }
554
- const url_node = this.parse_import_url();
555
- if (url_node !== null) nodes.push(url_node);
556
- return nodes;
557
- }
558
- // Parse @scope prelude: [(<scope-start>)] [to (<scope-end>)]
559
- // e.g. @scope (.parent) to (.child) { }
560
- parse_scope_prelude() {
561
- let nodes = [];
562
- while (this.lexer.pos < this.prelude_end) {
563
- this.skip_whitespace();
564
- if (this.lexer.pos >= this.prelude_end) break;
565
- const token_type = this.peek_token_type();
566
- if (token_type === TOKEN_LEFT_PAREN) {
567
- this.next_token();
568
- let paren_start = this.lexer.token_start;
569
- let content_start = this.lexer.pos;
570
- let depth = 1;
571
- while (this.lexer.pos < this.prelude_end && depth > 0) {
572
- this.next_token();
573
- if (this.lexer.token_type === TOKEN_LEFT_PAREN) depth++;
574
- else if (this.lexer.token_type === TOKEN_RIGHT_PAREN) depth--;
575
- }
576
- let content_end = this.lexer.token_start;
577
- let paren_end = this.lexer.token_end;
578
- let scope_node = this.create_node(PRELUDE_SELECTORLIST, paren_start, paren_end);
579
- let trimmed = trim_boundaries(this.source, content_start, content_end);
580
- if (trimmed) {
581
- this.arena.set_value_start_delta(scope_node, trimmed[0] - paren_start);
582
- this.arena.set_value_length(scope_node, trimmed[1] - trimmed[0]);
583
- }
584
- nodes.push(scope_node);
585
- } else if (token_type === TOKEN_IDENT) {
586
- this.next_token();
587
- let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
588
- if (str_equals("to", text)) {
589
- nodes.push(this.create_node(PRELUDE_OPERATOR, this.lexer.token_start, this.lexer.token_end));
590
- }
591
- } else {
592
- this.next_token();
593
- }
594
- }
595
- return nodes;
596
- }
597
- // Parse @custom-media prelude: --name <media-condition>
598
- // e.g. @custom-media --small (max-width: 30em);
599
- parse_custom_media_prelude() {
600
- let nodes = [];
601
- this.skip_whitespace();
602
- if (this.lexer.pos >= this.prelude_end) return [];
603
- this.next_token();
604
- if (this.lexer.token_type !== TOKEN_IDENT) return [];
605
- nodes.push(this.create_node(IDENTIFIER, this.lexer.token_start, this.lexer.token_end));
606
- nodes.push(...this.parse_media_query_list());
607
- return nodes;
608
- }
609
- // Parse media feature range syntax: (50px <= width <= 100px)
610
- parse_feature_range(feature_start, feature_end, content_start, content_end) {
611
- let range_node = this.create_node(FEATURE_RANGE, feature_start, feature_end);
612
- let children = [];
613
- let feature_name_start = -1;
614
- let feature_name_end = -1;
615
- let pos = content_start;
616
- while (pos < content_end) {
617
- pos = skip_whitespace_and_comments_forward(this.source, pos, content_end);
618
- if (pos >= content_end) break;
619
- let ch = this.source.charCodeAt(pos);
620
- if (ch === CHAR_LESS_THAN || ch === CHAR_GREATER_THAN || ch === CHAR_EQUALS) {
621
- let op_start = pos++;
622
- if (pos < content_end && this.source.charCodeAt(pos) === CHAR_EQUALS) pos++;
623
- let op = this.create_node(PRELUDE_OPERATOR, op_start, pos);
624
- children.push(op);
625
- } else {
626
- let saved = this.lexer.save_position();
627
- this.lexer.pos = pos;
628
- this.next_token();
629
- if (this.lexer.token_type === TOKEN_IDENT) {
630
- feature_name_start = this.lexer.token_start;
631
- feature_name_end = this.lexer.token_end;
632
- } else {
633
- let value_nodes = this.parse_feature_value(this.lexer.token_start, this.lexer.token_end);
634
- children.push(...value_nodes);
635
- }
636
- pos = this.lexer.pos;
637
- this.lexer.restore_position(saved);
638
- }
639
- }
640
- if (feature_name_start !== -1) {
641
- this.arena.set_content_start_delta(range_node, feature_name_start - feature_start);
642
- this.arena.set_content_length(range_node, feature_name_end - feature_name_start);
643
- }
644
- this.arena.append_children(range_node, children);
645
- return range_node;
646
- }
647
- }
1
+ import { t as Lexer } from "./tokenize-BQFB1jXg.js";
2
+ import { C as CSSDataArena, r as CSSNode } from "./css-node-2ejJUrIw.js";
3
+ import { a as is_whitespace, l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-CCn_XRDe.js";
4
+ import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-DnsZRpfd.js";
5
+ //#region src/parse-atrule-prelude.ts
6
+ /** @internal */
7
+ var AtRulePreludeParser = class {
8
+ lexer;
9
+ arena;
10
+ source;
11
+ prelude_end;
12
+ constructor(arena, source) {
13
+ this.arena = arena;
14
+ this.source = source;
15
+ this.lexer = new Lexer(source);
16
+ this.prelude_end = 0;
17
+ }
18
+ parse_prelude(at_rule_name, start, end, line = 1, column = 1) {
19
+ this.prelude_end = end;
20
+ this.lexer.seek(start, line, column);
21
+ return this.parse_prelude_dispatch(at_rule_name);
22
+ }
23
+ parse_prelude_dispatch(at_rule_name) {
24
+ switch (strip_vendor_prefix(at_rule_name).toLowerCase()) {
25
+ case "media": return this.parse_media_query_list();
26
+ case "container": return this.parse_container_query();
27
+ case "supports": return this.parse_supports_query();
28
+ case "layer": return this.parse_layer_names();
29
+ case "keyframes":
30
+ case "property":
31
+ case "counter-style":
32
+ case "color-profile":
33
+ case "font-palette-values":
34
+ case "position-try":
35
+ case "font-feature-values":
36
+ case "page": return this.parse_identifier();
37
+ case "function": return this.parse_function_prelude();
38
+ case "import": return this.parse_import_prelude();
39
+ case "charset": return this.parse_charset_prelude();
40
+ case "namespace": return this.parse_namespace_prelude();
41
+ case "scope": return this.parse_scope_prelude();
42
+ case "custom-media": return this.parse_custom_media_prelude();
43
+ }
44
+ return [];
45
+ }
46
+ parse_media_query_list() {
47
+ let nodes = [];
48
+ while (this.lexer.pos < this.prelude_end) {
49
+ this.skip_whitespace();
50
+ if (this.lexer.pos >= this.prelude_end) break;
51
+ let query = this.parse_single_media_query();
52
+ if (query !== null) nodes.push(query);
53
+ this.skip_whitespace();
54
+ const saved = this.lexer.save_position();
55
+ this.next_token();
56
+ if (this.lexer.token_type !== 18) this.lexer.restore_position(saved);
57
+ }
58
+ return nodes;
59
+ }
60
+ create_node(type, start, end) {
61
+ return this.arena.create_node(type, start, end - start, this.lexer.token_line, this.lexer.token_column);
62
+ }
63
+ is_and_or_not(str) {
64
+ return str_equals("and", str) || str_equals("or", str) || str_equals("not", str);
65
+ }
66
+ parse_single_media_query() {
67
+ let query_start = this.lexer.pos;
68
+ this.skip_whitespace();
69
+ if (this.lexer.pos >= this.prelude_end) return null;
70
+ const saved_token_start = this.lexer.save_position();
71
+ this.next_token();
72
+ if (this.lexer.token_type === 1) {
73
+ let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
74
+ if (!str_equals("only", text) && !str_equals("not", text)) this.lexer.restore_position(saved_token_start);
75
+ } else this.lexer.restore_position(saved_token_start);
76
+ let components = [];
77
+ while (this.lexer.pos < this.prelude_end) {
78
+ this.skip_whitespace();
79
+ if (this.lexer.pos >= this.prelude_end) break;
80
+ if (this.peek_token_type() === 18) break;
81
+ this.next_token();
82
+ let token_type = this.lexer.token_type;
83
+ if (token_type === 21) {
84
+ let feature = this.parse_media_feature();
85
+ if (feature !== null) components.push(feature);
86
+ } else if (token_type === 1) {
87
+ let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
88
+ if (this.is_and_or_not(text)) {
89
+ let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
90
+ components.push(op);
91
+ } else {
92
+ let media_type = this.create_node(34, this.lexer.token_start, this.lexer.token_end);
93
+ components.push(media_type);
94
+ }
95
+ } else break;
96
+ }
97
+ if (components.length === 0) return null;
98
+ let query_node = this.create_node(32, query_start, this.lexer.pos);
99
+ this.arena.append_children(query_node, components);
100
+ return query_node;
101
+ }
102
+ parse_media_feature() {
103
+ let feature_start = this.lexer.token_start;
104
+ let depth = 1;
105
+ let content_start = this.lexer.pos;
106
+ while (this.lexer.pos < this.prelude_end && depth > 0) {
107
+ this.next_token();
108
+ let token_type = this.lexer.token_type;
109
+ if (token_type === 21) depth++;
110
+ else if (token_type === 22) depth--;
111
+ }
112
+ if (depth !== 0) return null;
113
+ let content_end = this.lexer.token_start;
114
+ let feature_end = this.lexer.token_end;
115
+ let has_comparison = false;
116
+ let i = content_start;
117
+ while (i < content_end) {
118
+ i = skip_whitespace_and_comments_forward(this.source, i, content_end);
119
+ if (i >= content_end) break;
120
+ let ch = this.source.charCodeAt(i);
121
+ if (ch === 60 || ch === 62 || ch === 61) {
122
+ has_comparison = true;
123
+ break;
124
+ }
125
+ i++;
126
+ }
127
+ if (has_comparison) return this.parse_feature_range(feature_start, feature_end, content_start, content_end);
128
+ let feature = this.create_node(33, feature_start, feature_end);
129
+ let colon_pos = -1;
130
+ let j = content_start;
131
+ while (j < content_end) {
132
+ j = skip_whitespace_and_comments_forward(this.source, j, content_end);
133
+ if (j >= content_end) break;
134
+ if (this.source.charCodeAt(j) === 58) {
135
+ colon_pos = j;
136
+ break;
137
+ }
138
+ j++;
139
+ }
140
+ if (colon_pos !== -1) {
141
+ let name_trimmed = trim_boundaries(this.source, content_start, colon_pos);
142
+ if (name_trimmed) {
143
+ this.arena.set_content_start_delta(feature, name_trimmed[0] - feature_start);
144
+ this.arena.set_content_length(feature, name_trimmed[1] - name_trimmed[0]);
145
+ }
146
+ let value_trimmed = trim_boundaries(this.source, colon_pos + 1, content_end);
147
+ if (value_trimmed) {
148
+ let value_nodes = this.parse_feature_value(value_trimmed[0], value_trimmed[1]);
149
+ if (value_nodes.length > 0) this.arena.append_children(feature, value_nodes);
150
+ }
151
+ } else {
152
+ let trimmed = trim_boundaries(this.source, content_start, content_end);
153
+ if (trimmed) {
154
+ this.arena.set_content_start_delta(feature, trimmed[0] - feature_start);
155
+ this.arena.set_content_length(feature, trimmed[1] - trimmed[0]);
156
+ }
157
+ }
158
+ return feature;
159
+ }
160
+ parse_container_query() {
161
+ let nodes = [];
162
+ let query_start = this.lexer.pos;
163
+ let components = [];
164
+ while (this.lexer.pos < this.prelude_end) {
165
+ this.skip_whitespace();
166
+ if (this.lexer.pos >= this.prelude_end) break;
167
+ this.next_token();
168
+ let token_type = this.lexer.token_type;
169
+ if (token_type === 21) {
170
+ let feature = this.parse_media_feature();
171
+ if (feature !== null) components.push(feature);
172
+ } else if (token_type === 2) {
173
+ let func_name = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
174
+ let func_start = this.lexer.token_start;
175
+ let content_start = this.lexer.token_end;
176
+ let paren_depth = 1;
177
+ let func_end = this.lexer.token_end;
178
+ let content_end = content_start;
179
+ while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
180
+ this.next_token();
181
+ let inner_token = this.lexer.token_type;
182
+ if (inner_token === 21 || inner_token === 2) paren_depth++;
183
+ else if (inner_token === 22) {
184
+ paren_depth--;
185
+ if (paren_depth === 0) {
186
+ content_end = this.lexer.token_start;
187
+ func_end = this.lexer.token_end;
188
+ }
189
+ } else if (inner_token === 26) break;
190
+ }
191
+ let func_node = this.create_node(15, func_start, func_end);
192
+ this.arena.set_content_start_delta(func_node, 0);
193
+ this.arena.set_content_length(func_node, func_name.length);
194
+ this.arena.set_value_start_delta(func_node, content_start - func_start);
195
+ this.arena.set_value_length(func_node, content_end - content_start);
196
+ components.push(func_node);
197
+ } else if (token_type === 1) {
198
+ let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
199
+ if (this.is_and_or_not(text)) {
200
+ let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
201
+ components.push(op);
202
+ } else {
203
+ let name = this.create_node(10, this.lexer.token_start, this.lexer.token_end);
204
+ components.push(name);
205
+ }
206
+ }
207
+ }
208
+ if (components.length === 0) return [];
209
+ let query_node = this.create_node(35, query_start, this.lexer.pos);
210
+ this.arena.append_children(query_node, components);
211
+ nodes.push(query_node);
212
+ return nodes;
213
+ }
214
+ parse_supports_query() {
215
+ let nodes = [];
216
+ while (this.lexer.pos < this.prelude_end) {
217
+ this.skip_whitespace();
218
+ if (this.lexer.pos >= this.prelude_end) break;
219
+ this.next_token();
220
+ let token_type = this.lexer.token_type;
221
+ if (token_type === 21) {
222
+ let feature_start = this.lexer.token_start;
223
+ let depth = 1;
224
+ let content_start = this.lexer.pos;
225
+ while (this.lexer.pos < this.prelude_end && depth > 0) {
226
+ this.next_token();
227
+ let inner_token_type = this.lexer.token_type;
228
+ if (inner_token_type === 21) depth++;
229
+ else if (inner_token_type === 22) depth--;
230
+ }
231
+ if (depth === 0) {
232
+ let content_end = this.lexer.token_start;
233
+ let feature_end = this.lexer.token_end;
234
+ let query = this.create_node(36, feature_start, feature_end);
235
+ let trimmed = trim_boundaries(this.source, content_start, content_end);
236
+ if (trimmed) {
237
+ this.arena.set_value_start_delta(query, trimmed[0] - feature_start);
238
+ this.arena.set_value_length(query, trimmed[1] - trimmed[0]);
239
+ }
240
+ nodes.push(query);
241
+ }
242
+ } else if (token_type === 1) {
243
+ let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
244
+ if (this.is_and_or_not(text)) {
245
+ let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
246
+ nodes.push(op);
247
+ }
248
+ }
249
+ }
250
+ return nodes;
251
+ }
252
+ parse_layer_names() {
253
+ let nodes = [];
254
+ while (this.lexer.pos < this.prelude_end) {
255
+ this.skip_whitespace();
256
+ if (this.lexer.pos >= this.prelude_end) break;
257
+ this.next_token();
258
+ let token_type = this.lexer.token_type;
259
+ if (token_type === 1) {
260
+ let layer = this.create_node(37, this.lexer.token_start, this.lexer.token_end);
261
+ this.arena.set_value_start_delta(layer, 0);
262
+ this.arena.set_value_length(layer, this.lexer.token_end - this.lexer.token_start);
263
+ nodes.push(layer);
264
+ } else if (token_type === 18) continue;
265
+ else if (token_type === 13) continue;
266
+ }
267
+ return nodes;
268
+ }
269
+ parse_function_prelude() {
270
+ this.skip_whitespace();
271
+ if (this.lexer.pos >= this.prelude_end) return [];
272
+ this.next_token();
273
+ if (this.lexer.token_type !== 2) return [];
274
+ let name_start = this.lexer.token_start;
275
+ let name_end = this.lexer.token_end - 1;
276
+ return [this.create_node(10, name_start, name_end)];
277
+ }
278
+ parse_identifier() {
279
+ this.skip_whitespace();
280
+ if (this.lexer.pos >= this.prelude_end) return [];
281
+ this.next_token();
282
+ if (this.lexer.token_type !== 1) return [];
283
+ return [this.create_node(10, this.lexer.token_start, this.lexer.token_end)];
284
+ }
285
+ parse_charset_prelude() {
286
+ this.skip_whitespace();
287
+ if (this.lexer.pos >= this.prelude_end) return [];
288
+ this.next_token();
289
+ if (this.lexer.token_type !== 5) return [];
290
+ return [this.create_node(13, this.lexer.token_start, this.lexer.token_end)];
291
+ }
292
+ parse_import_prelude() {
293
+ let nodes = [];
294
+ this.skip_whitespace();
295
+ if (this.lexer.pos >= this.prelude_end) return [];
296
+ let url_node = this.parse_import_url();
297
+ if (url_node !== null) nodes.push(url_node);
298
+ else return [];
299
+ this.skip_whitespace();
300
+ if (this.lexer.pos >= this.prelude_end) return nodes;
301
+ let layer_node = this.parse_import_layer();
302
+ if (layer_node !== null) nodes.push(layer_node);
303
+ this.skip_whitespace();
304
+ if (this.lexer.pos >= this.prelude_end) return nodes;
305
+ let supports_node = this.parse_import_supports();
306
+ if (supports_node !== null) nodes.push(supports_node);
307
+ this.skip_whitespace();
308
+ if (this.lexer.pos >= this.prelude_end) return nodes;
309
+ let media_nodes = this.parse_media_query_list();
310
+ nodes.push(...media_nodes);
311
+ return nodes;
312
+ }
313
+ parse_import_url() {
314
+ this.next_token();
315
+ if (this.lexer.token_type !== 7 && this.lexer.token_type !== 2 && this.lexer.token_type !== 5) return null;
316
+ let url_start = this.lexer.token_start;
317
+ let url_end = this.lexer.token_end;
318
+ if (this.lexer.token_type === 2) {
319
+ let paren_depth = 1;
320
+ while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
321
+ let tokenType = this.next_token();
322
+ if (tokenType === 21 || tokenType === 2) paren_depth++;
323
+ else if (tokenType === 22) {
324
+ paren_depth--;
325
+ if (paren_depth === 0) url_end = this.lexer.token_end;
326
+ } else if (tokenType === 26) break;
327
+ }
328
+ }
329
+ return this.create_node(18, url_start, url_end);
330
+ }
331
+ parse_import_layer() {
332
+ const saved = this.lexer.save_position();
333
+ this.next_token();
334
+ if (this.lexer.token_type === 1 || this.lexer.token_type === 2) {
335
+ let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
336
+ if (this.lexer.token_type === 2 && text.endsWith("(")) text = text.slice(0, -1);
337
+ if (str_equals("layer", text)) {
338
+ let layer_start = this.lexer.token_start;
339
+ let layer_end = this.lexer.token_end;
340
+ let content_start = 0;
341
+ let content_length = 0;
342
+ if (this.lexer.token_type === 2) {
343
+ content_start = this.lexer.pos;
344
+ let paren_depth = 1;
345
+ while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
346
+ let tokenType = this.next_token();
347
+ if (tokenType === 21 || tokenType === 2) paren_depth++;
348
+ else if (tokenType === 22) {
349
+ paren_depth--;
350
+ if (paren_depth === 0) {
351
+ content_length = this.lexer.token_start - content_start;
352
+ layer_end = this.lexer.token_end;
353
+ }
354
+ } else if (tokenType === 26) break;
355
+ }
356
+ }
357
+ let layer_node = this.create_node(37, layer_start, layer_end);
358
+ if (content_length > 0) {
359
+ let trimmed = trim_boundaries(this.source, content_start, content_start + content_length);
360
+ if (trimmed) {
361
+ this.arena.set_content_start_delta(layer_node, trimmed[0] - layer_start);
362
+ this.arena.set_content_length(layer_node, trimmed[1] - trimmed[0]);
363
+ this.arena.set_value_start_delta(layer_node, trimmed[0] - layer_start);
364
+ this.arena.set_value_length(layer_node, trimmed[1] - trimmed[0]);
365
+ }
366
+ }
367
+ return layer_node;
368
+ }
369
+ }
370
+ this.lexer.restore_position(saved);
371
+ return null;
372
+ }
373
+ parse_import_supports() {
374
+ const saved = this.lexer.save_position();
375
+ this.next_token();
376
+ if (this.lexer.token_type === 2) {
377
+ if (str_equals("supports", this.source.substring(this.lexer.token_start, this.lexer.token_end - 1))) {
378
+ let supports_start = this.lexer.token_start;
379
+ let content_start = this.lexer.token_end;
380
+ let paren_depth = 1;
381
+ let supports_end = this.lexer.token_end;
382
+ let content_end = content_start;
383
+ while (this.lexer.pos < this.prelude_end && paren_depth > 0) {
384
+ let tokenType = this.next_token();
385
+ if (tokenType === 21 || tokenType === 2) paren_depth++;
386
+ else if (tokenType === 22) {
387
+ paren_depth--;
388
+ if (paren_depth === 0) {
389
+ content_end = this.lexer.token_start;
390
+ supports_end = this.lexer.token_end;
391
+ }
392
+ } else if (tokenType === 26) break;
393
+ }
394
+ let supports_node = this.create_node(36, supports_start, supports_end);
395
+ let trimmed = trim_boundaries(this.source, content_start, content_end);
396
+ if (trimmed) {
397
+ this.arena.set_value_start_delta(supports_node, trimmed[0] - supports_start);
398
+ this.arena.set_value_length(supports_node, trimmed[1] - trimmed[0]);
399
+ }
400
+ return supports_node;
401
+ }
402
+ }
403
+ this.lexer.restore_position(saved);
404
+ return null;
405
+ }
406
+ skip_whitespace() {
407
+ this.lexer.skip_whitespace_in_range(this.prelude_end);
408
+ }
409
+ peek_token_type() {
410
+ const saved = this.lexer.save_position();
411
+ this.next_token();
412
+ let type = this.lexer.token_type;
413
+ this.lexer.restore_position(saved);
414
+ return type;
415
+ }
416
+ next_token() {
417
+ if (this.lexer.pos >= this.prelude_end) {
418
+ this.lexer.token_type = 26;
419
+ return 26;
420
+ }
421
+ return this.lexer.next_token_fast(false);
422
+ }
423
+ parse_value_token() {
424
+ switch (this.lexer.token_type) {
425
+ case 1: return this.create_node(10, this.lexer.token_start, this.lexer.token_end);
426
+ case 10: return this.create_node(11, this.lexer.token_start, this.lexer.token_end);
427
+ case 11:
428
+ case 12: return this.create_node(12, this.lexer.token_start, this.lexer.token_end);
429
+ case 5: return this.create_node(13, this.lexer.token_start, this.lexer.token_end);
430
+ default: return null;
431
+ }
432
+ }
433
+ parse_feature_value(start, end) {
434
+ let temp_lexer = new Lexer(this.source);
435
+ temp_lexer.seek(start, this.lexer.line, this.lexer.column);
436
+ let nodes = [];
437
+ let saved_lexer = this.lexer;
438
+ this.lexer = temp_lexer;
439
+ while (this.lexer.pos < end) {
440
+ this.lexer.next_token_fast(false);
441
+ if (this.lexer.token_start >= end) break;
442
+ let all_whitespace = true;
443
+ for (let i = this.lexer.token_start; i < this.lexer.token_end && i < end; i++) if (!is_whitespace(this.source.charCodeAt(i))) {
444
+ all_whitespace = false;
445
+ break;
446
+ }
447
+ if (all_whitespace) continue;
448
+ let node = this.parse_value_token();
449
+ if (node !== null) nodes.push(node);
450
+ }
451
+ this.lexer = saved_lexer;
452
+ return nodes;
453
+ }
454
+ parse_namespace_prelude() {
455
+ let nodes = [];
456
+ this.skip_whitespace();
457
+ if (this.lexer.pos >= this.prelude_end) return [];
458
+ const saved = this.lexer.save_position();
459
+ this.next_token();
460
+ if (this.lexer.token_type === 1) {
461
+ nodes.push(this.create_node(10, this.lexer.token_start, this.lexer.token_end));
462
+ this.skip_whitespace();
463
+ } else this.lexer.restore_position(saved);
464
+ const url_node = this.parse_import_url();
465
+ if (url_node !== null) nodes.push(url_node);
466
+ return nodes;
467
+ }
468
+ parse_scope_prelude() {
469
+ let nodes = [];
470
+ while (this.lexer.pos < this.prelude_end) {
471
+ this.skip_whitespace();
472
+ if (this.lexer.pos >= this.prelude_end) break;
473
+ const token_type = this.peek_token_type();
474
+ if (token_type === 21) {
475
+ this.next_token();
476
+ let paren_start = this.lexer.token_start;
477
+ let content_start = this.lexer.pos;
478
+ let depth = 1;
479
+ while (this.lexer.pos < this.prelude_end && depth > 0) {
480
+ this.next_token();
481
+ if (this.lexer.token_type === 21) depth++;
482
+ else if (this.lexer.token_type === 22) depth--;
483
+ }
484
+ let content_end = this.lexer.token_start;
485
+ let paren_end = this.lexer.token_end;
486
+ let scope_node = this.create_node(41, paren_start, paren_end);
487
+ let trimmed = trim_boundaries(this.source, content_start, content_end);
488
+ if (trimmed) {
489
+ this.arena.set_value_start_delta(scope_node, trimmed[0] - paren_start);
490
+ this.arena.set_value_length(scope_node, trimmed[1] - trimmed[0]);
491
+ }
492
+ nodes.push(scope_node);
493
+ } else if (token_type === 1) {
494
+ this.next_token();
495
+ if (str_equals("to", this.source.substring(this.lexer.token_start, this.lexer.token_end))) nodes.push(this.create_node(38, this.lexer.token_start, this.lexer.token_end));
496
+ } else this.next_token();
497
+ }
498
+ return nodes;
499
+ }
500
+ parse_custom_media_prelude() {
501
+ let nodes = [];
502
+ this.skip_whitespace();
503
+ if (this.lexer.pos >= this.prelude_end) return [];
504
+ this.next_token();
505
+ if (this.lexer.token_type !== 1) return [];
506
+ nodes.push(this.create_node(10, this.lexer.token_start, this.lexer.token_end));
507
+ nodes.push(...this.parse_media_query_list());
508
+ return nodes;
509
+ }
510
+ parse_feature_range(feature_start, feature_end, content_start, content_end) {
511
+ let range_node = this.create_node(39, feature_start, feature_end);
512
+ let children = [];
513
+ let feature_name_start = -1;
514
+ let feature_name_end = -1;
515
+ let pos = content_start;
516
+ while (pos < content_end) {
517
+ pos = skip_whitespace_and_comments_forward(this.source, pos, content_end);
518
+ if (pos >= content_end) break;
519
+ let ch = this.source.charCodeAt(pos);
520
+ if (ch === 60 || ch === 62 || ch === 61) {
521
+ let op_start = pos++;
522
+ if (pos < content_end && this.source.charCodeAt(pos) === 61) pos++;
523
+ let op = this.create_node(38, op_start, pos);
524
+ children.push(op);
525
+ } else {
526
+ let saved = this.lexer.save_position();
527
+ this.lexer.pos = pos;
528
+ this.next_token();
529
+ if (this.lexer.token_type === 1) {
530
+ feature_name_start = this.lexer.token_start;
531
+ feature_name_end = this.lexer.token_end;
532
+ } else {
533
+ let value_nodes = this.parse_feature_value(this.lexer.token_start, this.lexer.token_end);
534
+ children.push(...value_nodes);
535
+ }
536
+ pos = this.lexer.pos;
537
+ this.lexer.restore_position(saved);
538
+ }
539
+ }
540
+ if (feature_name_start !== -1) {
541
+ this.arena.set_content_start_delta(range_node, feature_name_start - feature_start);
542
+ this.arena.set_content_length(range_node, feature_name_end - feature_name_start);
543
+ }
544
+ this.arena.append_children(range_node, children);
545
+ return range_node;
546
+ }
547
+ };
548
+ /**
549
+ * Parse an at-rule prelude string and return an array of AST nodes
550
+ * @param at_rule_name - The name of the at-rule (e.g., "media", "supports", "layer")
551
+ * @param prelude - The at-rule prelude to parse (e.g., "(min-width: 768px)", "utilities")
552
+ * @returns An array of CSSNode objects representing the parsed prelude
553
+ */
648
554
  function parse_atrule_prelude(at_rule_name, prelude) {
649
- const arena = new CSSDataArena(CSSDataArena.capacity_for_source(prelude.length));
650
- const prelude_parser = new AtRulePreludeParser(arena, prelude);
651
- const node_indices = prelude_parser.parse_prelude(at_rule_name, 0, prelude.length);
652
- return node_indices.map((index) => new CSSNode(arena, prelude, index));
555
+ const arena = new CSSDataArena(CSSDataArena.capacity_for_source(prelude.length));
556
+ return new AtRulePreludeParser(arena, prelude).parse_prelude(at_rule_name, 0, prelude.length).map((index) => new CSSNode(arena, prelude, index));
653
557
  }
654
-
558
+ //#endregion
655
559
  export { AtRulePreludeParser, parse_atrule_prelude };