@projectwallace/css-parser 0.16.1 → 0.17.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.
@@ -1,8 +1,8 @@
1
1
  import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
- import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
- import { a as is_whitespace, l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-B0AZRxxt.js";
4
- import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
- import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-BmXnziOy.js";
2
+ import { l as CSSDataArena } from "./arena-CFwM4uQs.js";
3
+ import { a as is_whitespace, l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-ouWXNHdx.js";
4
+ import { t as CSSNode } from "./css-node-B3EzCweR.js";
5
+ import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-D7srNG13.js";
6
6
  //#region src/parse-atrule-prelude.ts
7
7
  /** @internal */
8
8
  var AtRulePreludeParser = class {
@@ -74,30 +74,30 @@ var AtRulePreludeParser = class {
74
74
  let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
75
75
  if (!str_equals("only", text) && !str_equals("not", text)) this.lexer.restore_position(saved_token_start);
76
76
  } else this.lexer.restore_position(saved_token_start);
77
- let components = [];
77
+ let first_component = 0;
78
+ let last_component = 0;
78
79
  while (this.lexer.pos < this.prelude_end) {
79
80
  this.skip_whitespace();
80
81
  if (this.lexer.pos >= this.prelude_end) break;
81
82
  if (this.peek_token_type() === 18) break;
82
83
  this.next_token();
83
84
  let token_type = this.lexer.token_type;
84
- if (token_type === 21) {
85
- let feature = this.parse_media_feature();
86
- if (feature !== null) components.push(feature);
87
- } else if (token_type === 1) {
85
+ let component = null;
86
+ if (token_type === 21) component = this.parse_media_feature();
87
+ else if (token_type === 1) {
88
88
  let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
89
- if (this.is_and_or_not(text)) {
90
- let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
91
- components.push(op);
92
- } else {
93
- let media_type = this.create_node(34, this.lexer.token_start, this.lexer.token_end);
94
- components.push(media_type);
95
- }
89
+ if (this.is_and_or_not(text)) component = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
90
+ else component = this.create_node(34, this.lexer.token_start, this.lexer.token_end);
96
91
  } else break;
92
+ if (component !== null) {
93
+ if (first_component === 0) first_component = component;
94
+ else this.arena.set_next_sibling(last_component, component);
95
+ last_component = component;
96
+ }
97
97
  }
98
- if (components.length === 0) return null;
98
+ if (first_component === 0) return null;
99
99
  let query_node = this.create_node(32, query_start, this.lexer.pos);
100
- this.arena.append_children(query_node, components);
100
+ this.arena.set_first_child(query_node, first_component);
101
101
  return query_node;
102
102
  }
103
103
  parse_media_feature() {
@@ -152,25 +152,24 @@ var AtRulePreludeParser = class {
152
152
  }
153
153
  let value_trimmed = trim_boundaries(this.source, colon_pos + 1, content_end);
154
154
  if (value_trimmed) {
155
- let value_nodes = this.parse_feature_value(value_trimmed[0], value_trimmed[1]);
156
- if (value_nodes.length > 0) this.arena.append_children(feature, value_nodes);
155
+ let value_first = this.parse_feature_value(value_trimmed[0], value_trimmed[1]);
156
+ if (value_first !== 0) this.arena.set_first_child(feature, value_first);
157
157
  }
158
158
  }
159
159
  return feature;
160
160
  }
161
161
  parse_container_query() {
162
- let nodes = [];
163
162
  let query_start = this.lexer.pos;
164
- let components = [];
163
+ let first_component = 0;
164
+ let last_component = 0;
165
165
  while (this.lexer.pos < this.prelude_end) {
166
166
  this.skip_whitespace();
167
167
  if (this.lexer.pos >= this.prelude_end) break;
168
168
  this.next_token();
169
169
  let token_type = this.lexer.token_type;
170
- if (token_type === 21) {
171
- let feature = this.parse_media_feature();
172
- if (feature !== null) components.push(feature);
173
- } else if (token_type === 2) {
170
+ let component = null;
171
+ if (token_type === 21) component = this.parse_media_feature();
172
+ else if (token_type === 2) {
174
173
  let func_name = this.source.substring(this.lexer.token_start, this.lexer.token_end - 1);
175
174
  let func_start = this.lexer.token_start;
176
175
  let content_start = this.lexer.token_end;
@@ -194,23 +193,22 @@ var AtRulePreludeParser = class {
194
193
  this.arena.set_content_length(func_node, func_name.length);
195
194
  this.arena.set_value_start_delta(func_node, content_start - func_start);
196
195
  this.arena.set_value_length(func_node, content_end - content_start);
197
- components.push(func_node);
196
+ component = func_node;
198
197
  } else if (token_type === 1) {
199
198
  let text = this.source.substring(this.lexer.token_start, this.lexer.token_end);
200
- if (this.is_and_or_not(text)) {
201
- let op = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
202
- components.push(op);
203
- } else {
204
- let name = this.create_node(10, this.lexer.token_start, this.lexer.token_end);
205
- components.push(name);
206
- }
199
+ if (this.is_and_or_not(text)) component = this.create_node(38, this.lexer.token_start, this.lexer.token_end);
200
+ else component = this.create_node(10, this.lexer.token_start, this.lexer.token_end);
201
+ }
202
+ if (component !== null) {
203
+ if (first_component === 0) first_component = component;
204
+ else this.arena.set_next_sibling(last_component, component);
205
+ last_component = component;
207
206
  }
208
207
  }
209
- if (components.length === 0) return [];
208
+ if (first_component === 0) return [];
210
209
  let query_node = this.create_node(35, query_start, this.lexer.pos);
211
- this.arena.append_children(query_node, components);
212
- nodes.push(query_node);
213
- return nodes;
210
+ this.arena.set_first_child(query_node, first_component);
211
+ return [query_node];
214
212
  }
215
213
  parse_supports_query() {
216
214
  let nodes = [];
@@ -240,7 +238,7 @@ var AtRulePreludeParser = class {
240
238
  let colon_pos = this.find_colon_at_depth_zero(trimmed[0], trimmed[1]);
241
239
  if (colon_pos !== -1) {
242
240
  let decl_child = this.create_supports_declaration(trimmed[0], trimmed[1], colon_pos);
243
- this.arena.append_children(query, [decl_child]);
241
+ this.arena.set_first_child(query, decl_child);
244
242
  }
245
243
  }
246
244
  nodes.push(query);
@@ -275,17 +273,17 @@ var AtRulePreludeParser = class {
275
273
  this.arena.set_content_start_delta(decl, 0);
276
274
  this.arena.set_content_length(decl, prop_trimmed[1] - prop_trimmed[0]);
277
275
  if (val_trimmed) {
278
- let value_nodes = this.parse_feature_value(val_trimmed[0], val_trimmed[1]);
276
+ let value_first = this.parse_feature_value(val_trimmed[0], val_trimmed[1]);
279
277
  let value_node;
280
- if (value_nodes.length === 0) value_node = this.arena.create_node(50, val_trimmed[0], 0, this.lexer.token_line, this.lexer.token_column);
278
+ if (value_first === 0) value_node = this.arena.create_node(50, val_trimmed[0], 0, this.lexer.token_line, this.lexer.token_column);
281
279
  else {
282
280
  value_node = this.arena.create_node(50, val_trimmed[0], val_trimmed[1] - val_trimmed[0], this.lexer.token_line, this.lexer.token_column);
283
- this.arena.append_children(value_node, value_nodes);
281
+ this.arena.set_first_child(value_node, value_first);
284
282
  }
285
- this.arena.append_children(decl, [value_node]);
283
+ this.arena.set_first_child(decl, value_node);
286
284
  }
287
285
  let supports_decl = this.create_node(57, content_start, content_end);
288
- this.arena.append_children(supports_decl, [decl]);
286
+ this.arena.set_first_child(supports_decl, decl);
289
287
  return supports_decl;
290
288
  }
291
289
  parse_layer_names() {
@@ -296,9 +294,24 @@ var AtRulePreludeParser = class {
296
294
  this.next_token();
297
295
  let token_type = this.lexer.token_type;
298
296
  if (token_type === 1) {
299
- let layer = this.create_node(37, this.lexer.token_start, this.lexer.token_end);
297
+ let name_start = this.lexer.token_start;
298
+ let name_end = this.lexer.token_end;
299
+ while (this.lexer.pos < this.prelude_end) {
300
+ let saved = this.lexer.save_position();
301
+ if (this.next_token() !== 9 || this.source.charCodeAt(this.lexer.token_start) !== 46 || this.lexer.token_start !== name_end) {
302
+ this.lexer.restore_position(saved);
303
+ break;
304
+ }
305
+ let dot_end = this.lexer.token_end;
306
+ if (this.next_token() !== 1 || this.lexer.token_start !== dot_end) {
307
+ this.lexer.restore_position(saved);
308
+ break;
309
+ }
310
+ name_end = this.lexer.token_end;
311
+ }
312
+ let layer = this.create_node(37, name_start, name_end);
300
313
  this.arena.set_content_start_delta(layer, 0);
301
- this.arena.set_content_length(layer, this.lexer.token_end - this.lexer.token_start);
314
+ this.arena.set_content_length(layer, name_end - name_start);
302
315
  nodes.push(layer);
303
316
  } else if (token_type === 18) continue;
304
317
  else if (token_type === 13) continue;
@@ -470,7 +483,8 @@ var AtRulePreludeParser = class {
470
483
  parse_feature_value(start, end) {
471
484
  const saved_position = this.lexer.save_position();
472
485
  this.lexer.seek(start, this.lexer.line, this.lexer.column);
473
- let nodes = [];
486
+ let first_node = 0;
487
+ let last_node = 0;
474
488
  while (this.lexer.pos < end) {
475
489
  this.lexer.next_token_fast(false);
476
490
  if (this.lexer.token_start >= end) break;
@@ -481,10 +495,14 @@ var AtRulePreludeParser = class {
481
495
  }
482
496
  if (all_whitespace) continue;
483
497
  let node = this.parse_value_token();
484
- if (node !== null) nodes.push(node);
498
+ if (node !== null) {
499
+ if (first_node === 0) first_node = node;
500
+ else this.arena.set_next_sibling(last_node, node);
501
+ last_node = node;
502
+ }
485
503
  }
486
504
  this.lexer.restore_position(saved_position);
487
- return nodes;
505
+ return first_node;
488
506
  }
489
507
  parse_namespace_prelude() {
490
508
  let nodes = [];
@@ -543,7 +561,8 @@ var AtRulePreludeParser = class {
543
561
  }
544
562
  parse_feature_range(feature_start, feature_end, content_start, content_end) {
545
563
  let range_node = this.create_node(39, feature_start, feature_end);
546
- let children = [];
564
+ let first_child = 0;
565
+ let last_child = 0;
547
566
  let feature_name_start = -1;
548
567
  let feature_name_end = -1;
549
568
  let pos = content_start;
@@ -555,7 +574,9 @@ var AtRulePreludeParser = class {
555
574
  let op_start = pos++;
556
575
  if (pos < content_end && this.source.charCodeAt(pos) === 61) pos++;
557
576
  let op = this.create_node(38, op_start, pos);
558
- children.push(op);
577
+ if (first_child === 0) first_child = op;
578
+ else this.arena.set_next_sibling(last_child, op);
579
+ last_child = op;
559
580
  } else {
560
581
  let saved = this.lexer.save_position();
561
582
  this.lexer.pos = pos;
@@ -564,8 +585,12 @@ var AtRulePreludeParser = class {
564
585
  feature_name_start = this.lexer.token_start;
565
586
  feature_name_end = this.lexer.token_end;
566
587
  } else {
567
- let value_nodes = this.parse_feature_value(this.lexer.token_start, this.lexer.token_end);
568
- children.push(...value_nodes);
588
+ let value_first = this.parse_feature_value(this.lexer.token_start, this.lexer.token_end);
589
+ if (value_first !== 0) {
590
+ if (first_child === 0) first_child = value_first;
591
+ else this.arena.set_next_sibling(last_child, value_first);
592
+ last_child = this.arena.get_last_sibling(value_first);
593
+ }
569
594
  }
570
595
  pos = this.lexer.pos;
571
596
  this.lexer.restore_position(saved);
@@ -575,7 +600,7 @@ var AtRulePreludeParser = class {
575
600
  this.arena.set_content_start_delta(range_node, feature_name_start - feature_start);
576
601
  this.arena.set_content_length(range_node, feature_name_end - feature_name_start);
577
602
  }
578
- this.arena.append_children(range_node, children);
603
+ if (first_child !== 0) this.arena.set_first_child(range_node, first_child);
579
604
  return range_node;
580
605
  }
581
606
  };
@@ -1,7 +1,6 @@
1
- import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
1
+ import { l as CSSDataArena } from "./arena-Bx5vp6Sl.js";
2
2
  import { n as Lexer } from "./tokenize-DeZYFa9R.js";
3
- import { d as Declaration } from "./node-types-BrZu8T2C.js";
4
-
3
+ import { d as Declaration } from "./node-types-BRnQyc9B.js";
5
4
  //#region src/parse-declaration.d.ts
6
5
  /** @internal */
7
6
  declare class DeclarationParser {
@@ -1,8 +1,8 @@
1
1
  import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
- import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
- import { i as is_vendor_prefixed } from "./parse-dimension-B0AZRxxt.js";
4
- import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
- import { i as trim_boundaries } from "./parse-utils-BmXnziOy.js";
2
+ import { l as CSSDataArena } from "./arena-CFwM4uQs.js";
3
+ import { i as is_vendor_prefixed } from "./parse-dimension-ouWXNHdx.js";
4
+ import { t as CSSNode } from "./css-node-B3EzCweR.js";
5
+ import { i as trim_boundaries } from "./parse-utils-D7srNG13.js";
6
6
  import { ValueParser } from "./parse-value.js";
7
7
  //#region src/parse-declaration.ts
8
8
  /** @internal */
@@ -110,17 +110,17 @@ var DeclarationParser = class {
110
110
  this.arena.set_value_length(declaration, trimmed[1] - trimmed[0]);
111
111
  if (this.value_parser) {
112
112
  let valueNode = this.value_parser.parse_value(value_start, trimmed[1], value_start_line, value_start_column);
113
- this.arena.append_children(declaration, [valueNode]);
113
+ this.arena.set_first_child(declaration, valueNode);
114
114
  } else {
115
115
  let rawNode = this.arena.create_node(8, trimmed[0], trimmed[1] - trimmed[0], value_start_line, value_start_column);
116
- this.arena.append_children(declaration, [rawNode]);
116
+ this.arena.set_first_child(declaration, rawNode);
117
117
  }
118
118
  } else {
119
119
  this.arena.set_value_start_delta(declaration, value_start - prop_start);
120
120
  this.arena.set_value_length(declaration, 0);
121
121
  if (this.value_parser) {
122
122
  let valueNode = this.value_parser.parse_value(value_start, value_start, value_start_line, value_start_column);
123
- this.arena.append_children(declaration, [valueNode]);
123
+ this.arena.set_first_child(declaration, valueNode);
124
124
  }
125
125
  }
126
126
  if (has_important) this.arena.set_flag(declaration, 1);
@@ -27,15 +27,7 @@ function str_equals(a, b) {
27
27
  }
28
28
  return true;
29
29
  }
30
- /**
31
- * Case-insensitive ASCII prefix check without allocations
32
- * Returns true if string `str` starts with prefix (case-insensitive)
33
- *
34
- * IMPORTANT: prefix MUST be lowercase for correct comparison
35
- *
36
- * @param str - The string to check
37
- * @param prefix - The lowercase prefix to match against
38
- */
30
+ /** Case-insensitive ASCII prefix check without allocations. `prefix` MUST be lowercase. */
39
31
  function str_starts_with(str, prefix) {
40
32
  if (str.length < prefix.length) return false;
41
33
  for (let i = 0; i < prefix.length; i++) {
@@ -46,16 +38,7 @@ function str_starts_with(str, prefix) {
46
38
  }
47
39
  return true;
48
40
  }
49
- /**
50
- * Case-insensitive character/substring search without allocations
51
- * Returns the index of the first occurrence of searchChar (case-insensitive)
52
- *
53
- * IMPORTANT: searchChar MUST be lowercase for correct comparison
54
- *
55
- * @param str - The string to search in
56
- * @param searchChar - The lowercase character/substring to find
57
- * @returns The index of the first match, or -1 if not found
58
- */
41
+ /** Case-insensitive substring search without allocations, or -1 if not found. `searchChar` MUST be lowercase. */
59
42
  function str_index_of(str, searchChar) {
60
43
  if (searchChar.length === 0) return -1;
61
44
  if (searchChar.length === 1) {
@@ -93,37 +76,12 @@ function is_vendor_prefixed(source, start, end) {
93
76
  for (let i = start + 2; i < end; i++) if (source.charCodeAt(i) === 45) return true;
94
77
  return false;
95
78
  }
96
- /**
97
- * Check if a string is a CSS custom property (starts with --)
98
- *
99
- * @param str - The string to check
100
- * @returns true if the string starts with -- (custom property)
101
- *
102
- * Examples:
103
- * - `--primary-color` → true
104
- * - `--my-var` → true
105
- * - `-webkit-transform` → false (vendor prefix, not custom)
106
- * - `border-radius` → false (standard property)
107
- * - `color` → false
108
- */
79
+ /** True if the string is a CSS custom property (starts with `--`). */
109
80
  function is_custom(str) {
110
81
  if (str.length < 3) return false;
111
82
  return str.charCodeAt(0) === 45 && str.charCodeAt(1) === 45;
112
83
  }
113
- /**
114
- * Strip vendor prefix from a string
115
- *
116
- * @param str - The string to strip vendor prefix from
117
- * @returns The string without vendor prefix, or original string if no prefix found
118
- *
119
- * Examples:
120
- * - `-webkit-keyframes` → `keyframes`
121
- * - `-moz-appearance` → `appearance`
122
- * - `-ms-filter` → `filter`
123
- * - `-o-border-image` → `border-image`
124
- * - `keyframes` → `keyframes` (no change)
125
- * - `--custom-property` → `--custom-property` (custom property, not vendor prefix)
126
- */
84
+ /** Strip a vendor prefix, e.g. `-webkit-keyframes` → `keyframes`. Returns the input unchanged if it has no prefix. */
127
85
  function strip_vendor_prefix(str) {
128
86
  if (!is_vendor_prefixed(str)) return str;
129
87
  for (let i = 2; i < str.length; i++) if (str.charCodeAt(i) === 45) return str.substring(i + 1);
@@ -131,18 +89,7 @@ function strip_vendor_prefix(str) {
131
89
  }
132
90
  //#endregion
133
91
  //#region src/parse-dimension.ts
134
- /**
135
- * Parse a dimension string into numeric value and unit
136
- *
137
- * @param text - Dimension text like "100px", "50%", "1.5em"
138
- * @returns Object with value (number) and unit (string)
139
- *
140
- * Examples:
141
- * - "100px" → { value: 100, unit: "px" }
142
- * - "50%" → { value: 50, unit: "%" }
143
- * - "1.5em" → { value: 1.5, unit: "em" }
144
- * - "-10rem" → { value: -10, unit: "rem" }
145
- */
92
+ /** Parse a dimension string into value and unit, e.g. "100px" → { value: 100, unit: "px" } or "2%" → { value: 2, unit: "%" } */
146
93
  function parse_dimension(text) {
147
94
  let num_end = 0;
148
95
  for (let i = 0; i < text.length; i++) {
@@ -1,16 +1,5 @@
1
1
  //#region src/parse-dimension.d.ts
2
- /**
3
- * Parse a dimension string into numeric value and unit
4
- *
5
- * @param text - Dimension text like "100px", "50%", "1.5em"
6
- * @returns Object with value (number) and unit (string)
7
- *
8
- * Examples:
9
- * - "100px" → { value: 100, unit: "px" }
10
- * - "50%" → { value: 50, unit: "%" }
11
- * - "1.5em" → { value: 1.5, unit: "em" }
12
- * - "-10rem" → { value: -10, unit: "rem" }
13
- */
2
+ /** Parse a dimension string into value and unit, e.g. "100px" → { value: 100, unit: "px" } or "2%" → { value: 2, unit: "%" } */
14
3
  declare function parse_dimension(text: string): {
15
4
  value: number;
16
5
  unit: string;
@@ -1,2 +1,2 @@
1
- import { t as parse_dimension } from "./parse-dimension-B0AZRxxt.js";
1
+ import { t as parse_dimension } from "./parse-dimension-ouWXNHdx.js";
2
2
  export { parse_dimension };
@@ -1,6 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
- import { F as Selector, I as SelectorList } from "./node-types-BrZu8T2C.js";
3
-
1
+ import { l as CSSDataArena } from "./arena-Bx5vp6Sl.js";
2
+ import { F as Selector, I as SelectorList } from "./node-types-BRnQyc9B.js";
4
3
  //#region src/parse-selector.d.ts
5
4
  /** @internal */
6
5
  declare class SelectorParser {
@@ -1,8 +1,8 @@
1
1
  import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
- import { l as CSSDataArena } from "./arena-CCye9VYE.js";
3
- import { a as is_whitespace, n as is_combinator, o as str_equals } from "./parse-dimension-B0AZRxxt.js";
4
- import { t as CSSNode } from "./css-node-CuLhABl8.js";
5
- import { n as skip_whitespace_and_comments_forward, r as skip_whitespace_forward, t as skip_whitespace_and_comments_backward } from "./parse-utils-BmXnziOy.js";
2
+ import { l as CSSDataArena } from "./arena-CFwM4uQs.js";
3
+ import { a as is_whitespace, n as is_combinator, o as str_equals } from "./parse-dimension-ouWXNHdx.js";
4
+ import { t as CSSNode } from "./css-node-B3EzCweR.js";
5
+ import { n as skip_whitespace_and_comments_forward, r as skip_whitespace_forward, t as skip_whitespace_and_comments_backward } from "./parse-utils-D7srNG13.js";
6
6
  import { ANplusBParser } from "./parse-anplusb.js";
7
7
  //#region src/parse-selector.ts
8
8
  /** @internal */
@@ -25,7 +25,8 @@ var SelectorParser = class {
25
25
  return this.parse_selector_list(allow_relative);
26
26
  }
27
27
  parse_selector_list(allow_relative = true) {
28
- let selectors = [];
28
+ let first_selector = 0;
29
+ let last_selector = 0;
29
30
  let list_start = this.lexer.pos;
30
31
  let list_line = this.lexer.line;
31
32
  let list_column = this.lexer.column;
@@ -38,14 +39,10 @@ var SelectorParser = class {
38
39
  let selector_wrapper = this.arena.create_node(5, selector_start, this.lexer.pos - selector_start, selector_line, selector_column);
39
40
  this.arena.set_content_start_delta(selector_wrapper, 0);
40
41
  this.arena.set_content_length(selector_wrapper, this.lexer.pos - selector_start);
41
- let last_component = complex_selector;
42
- let next_sibling = this.arena.get_next_sibling(last_component);
43
- while (next_sibling !== 0) {
44
- last_component = next_sibling;
45
- next_sibling = this.arena.get_next_sibling(last_component);
46
- }
47
42
  this.arena.set_first_child(selector_wrapper, complex_selector);
48
- selectors.push(selector_wrapper);
43
+ if (first_selector === 0) first_selector = selector_wrapper;
44
+ else this.arena.set_next_sibling(last_selector, selector_wrapper);
45
+ last_selector = selector_wrapper;
49
46
  }
50
47
  this.skip_whitespace();
51
48
  if (this.lexer.pos >= this.selector_end) break;
@@ -55,15 +52,16 @@ var SelectorParser = class {
55
52
  continue;
56
53
  } else break;
57
54
  }
58
- if (selectors.length > 0) {
55
+ if (first_selector !== 0) {
59
56
  let list_node = this.arena.create_node(20, list_start, this.lexer.pos - list_start, list_line, list_column);
60
- this.arena.append_children(list_node, selectors);
57
+ this.arena.set_first_child(list_node, first_selector);
61
58
  return list_node;
62
59
  }
63
60
  return null;
64
61
  }
65
62
  parse_complex_selector(allow_relative = true) {
66
- let components = [];
63
+ let first_component = 0;
64
+ let chain_tail = 0;
67
65
  this.skip_whitespace();
68
66
  if (allow_relative && this.lexer.pos < this.selector_end) {
69
67
  const saved = this.lexer.save_position();
@@ -72,7 +70,8 @@ var SelectorParser = class {
72
70
  let ch = this.source.charCodeAt(this.lexer.token_start);
73
71
  if (ch === 62 || ch === 43 || ch === 126) {
74
72
  let combinator = this.create_node_at(27, this.lexer.token_start, this.lexer.token_end, this.lexer.token_line, this.lexer.token_column);
75
- components.push(combinator);
73
+ first_component = combinator;
74
+ chain_tail = combinator;
76
75
  this.skip_whitespace();
77
76
  } else this.lexer.restore_position(saved);
78
77
  } else this.lexer.restore_position(saved);
@@ -80,10 +79,13 @@ var SelectorParser = class {
80
79
  while (this.lexer.pos < this.selector_end) {
81
80
  let compound = this.parse_compound_selector();
82
81
  if (compound === null) break;
83
- components.push(compound);
82
+ if (chain_tail === 0) first_component = compound;
83
+ else this.arena.set_next_sibling(chain_tail, compound);
84
+ chain_tail = this.arena.get_last_sibling(compound);
84
85
  let combinator = this.try_parse_combinator();
85
86
  if (combinator !== null) {
86
- components.push(combinator);
87
+ this.arena.set_next_sibling(chain_tail, combinator);
88
+ chain_tail = combinator;
87
89
  this.skip_whitespace();
88
90
  continue;
89
91
  }
@@ -101,16 +103,11 @@ var SelectorParser = class {
101
103
  this.lexer.restore_position(saved);
102
104
  break;
103
105
  }
104
- if (components.length === 0) return null;
105
- for (let i = 0; i < components.length - 1; i++) {
106
- let last_node = components[i];
107
- while (this.arena.get_next_sibling(last_node) !== 0) last_node = this.arena.get_next_sibling(last_node);
108
- this.arena.set_next_sibling(last_node, components[i + 1]);
109
- }
110
- return components[0];
106
+ return first_component === 0 ? null : first_component;
111
107
  }
112
108
  parse_compound_selector() {
113
- let parts = [];
109
+ let first_part = 0;
110
+ let last_part = 0;
114
111
  while (this.lexer.pos < this.selector_end) {
115
112
  const saved = this.lexer.save_position();
116
113
  this.lexer.next_token_fast(false);
@@ -121,11 +118,11 @@ var SelectorParser = class {
121
118
  this.lexer.restore_position(saved);
122
119
  break;
123
120
  }
124
- parts.push(part);
121
+ if (first_part === 0) first_part = part;
122
+ else this.arena.set_next_sibling(last_part, part);
123
+ last_part = part;
125
124
  }
126
- if (parts.length === 0) return null;
127
- for (let i = 0; i < parts.length - 1; i++) this.arena.set_next_sibling(parts[i], parts[i + 1]);
128
- return parts[0];
125
+ return first_part === 0 ? null : first_part;
129
126
  }
130
127
  parse_simple_selector() {
131
128
  let token_type = this.lexer.token_type;
@@ -1,27 +1,11 @@
1
- import { a as is_whitespace } from "./parse-dimension-B0AZRxxt.js";
1
+ import { a as is_whitespace } from "./parse-dimension-ouWXNHdx.js";
2
2
  //#region src/parse-utils.ts
3
- /**
4
- * Skip whitespace forward from a position
5
- *
6
- * @param source - The source string
7
- * @param pos - Starting position
8
- * @param end - End boundary (exclusive)
9
- * @returns New position after skipping whitespace
10
- * @internal
11
- */
3
+ /** @internal */
12
4
  function skip_whitespace_forward(source, pos, end) {
13
5
  while (pos < end && is_whitespace(source.charCodeAt(pos))) pos++;
14
6
  return pos;
15
7
  }
16
- /**
17
- * Skip whitespace and comments forward from a position
18
- *
19
- * @param source - The source string
20
- * @param pos - Starting position
21
- * @param end - End boundary (exclusive)
22
- * @returns New position after skipping whitespace/comments
23
- * @internal
24
- */
8
+ /** @internal */
25
9
  function skip_whitespace_and_comments_forward(source, pos, end) {
26
10
  while (pos < end) {
27
11
  let ch = source.charCodeAt(pos);
@@ -44,15 +28,7 @@ function skip_whitespace_and_comments_forward(source, pos, end) {
44
28
  }
45
29
  return pos;
46
30
  }
47
- /**
48
- * Skip whitespace and comments backward from a position
49
- *
50
- * @param source - The source string
51
- * @param pos - Starting position (exclusive, scanning backward from pos-1)
52
- * @param start - Start boundary (inclusive, won't go before this)
53
- * @returns New position after skipping whitespace/comments backward
54
- * @internal
55
- */
31
+ /** @internal */
56
32
  function skip_whitespace_and_comments_backward(source, pos, start) {
57
33
  while (pos > start) {
58
34
  let ch = source.charCodeAt(pos - 1);
@@ -76,17 +52,8 @@ function skip_whitespace_and_comments_backward(source, pos, start) {
76
52
  return pos;
77
53
  }
78
54
  /**
79
- * Trim whitespace and comments from both ends of a string range
80
- *
81
- * @param source - The source string
82
- * @param start - Start offset in source
83
- * @param end - End offset in source
84
- * @returns [trimmed_start, trimmed_end] or null if all whitespace/comments
55
+ * Trims whitespace and CSS comments from both ends; returns null if the range is only whitespace/comments.
85
56
  * @internal
86
- *
87
- * Skips whitespace (space, tab, newline, CR, FF) and CSS comments from both ends
88
- * of the specified range. Returns the trimmed boundaries or null if the range
89
- * contains only whitespace and comments.
90
57
  */
91
58
  function trim_boundaries(source, start, end) {
92
59
  start = skip_whitespace_and_comments_forward(source, start, end);
@@ -1,6 +1,5 @@
1
- import { l as CSSDataArena } from "./arena-DfpuGV9Y.js";
2
- import { q as Value } from "./node-types-BrZu8T2C.js";
3
-
1
+ import { l as CSSDataArena } from "./arena-Bx5vp6Sl.js";
2
+ import { q as Value } from "./node-types-BRnQyc9B.js";
4
3
  //#region src/parse-value.d.ts
5
4
  /** @internal */
6
5
  declare class ValueParser {
@@ -10,7 +9,6 @@ declare class ValueParser {
10
9
  private value_end;
11
10
  constructor(arena: CSSDataArena, source: string);
12
11
  parse_value(start: number, end: number, start_line: number, start_column: number): number;
13
- private parse_value_tokens;
14
12
  private is_whitespace_inline;
15
13
  private parse_value_node;
16
14
  private create_node;