@projectwallace/css-parser 0.17.0 → 0.18.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.
@@ -7,6 +7,7 @@ declare class AtRulePreludeParser {
7
7
  private arena;
8
8
  private source;
9
9
  private prelude_end;
10
+ private value_node_parser;
10
11
  constructor(arena: CSSDataArena, source: string);
11
12
  parse_prelude(at_rule_name: string, start: number, end: number, line?: number, column?: number): number[];
12
13
  private parse_prelude_dispatch;
@@ -30,7 +31,6 @@ declare class AtRulePreludeParser {
30
31
  private skip_whitespace;
31
32
  private peek_token_type;
32
33
  private next_token;
33
- private parse_value_token;
34
34
  private parse_feature_value;
35
35
  private parse_namespace_prelude;
36
36
  private parse_scope_prelude;
@@ -1,8 +1,9 @@
1
1
  import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
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";
3
+ import { l as strip_vendor_prefix, o as str_equals } from "./parse-dimension-ouWXNHdx.js";
4
4
  import { t as CSSNode } from "./css-node-B3EzCweR.js";
5
5
  import { i as trim_boundaries, n as skip_whitespace_and_comments_forward } from "./parse-utils-D7srNG13.js";
6
+ import { t as ValueNodeParser } from "./value-node-parser-CZ47v3hp.js";
6
7
  //#region src/parse-atrule-prelude.ts
7
8
  /** @internal */
8
9
  var AtRulePreludeParser = class {
@@ -10,11 +11,13 @@ var AtRulePreludeParser = class {
10
11
  arena;
11
12
  source;
12
13
  prelude_end;
14
+ value_node_parser;
13
15
  constructor(arena, source) {
14
16
  this.arena = arena;
15
17
  this.source = source;
16
18
  this.lexer = new Lexer(source);
17
19
  this.prelude_end = 0;
20
+ this.value_node_parser = new ValueNodeParser(arena, source);
18
21
  }
19
22
  parse_prelude(at_rule_name, start, end, line = 1, column = 1) {
20
23
  this.prelude_end = end;
@@ -107,7 +110,7 @@ var AtRulePreludeParser = class {
107
110
  while (this.lexer.pos < this.prelude_end && depth > 0) {
108
111
  this.next_token();
109
112
  let token_type = this.lexer.token_type;
110
- if (token_type === 21) depth++;
113
+ if (token_type === 21 || token_type === 2) depth++;
111
114
  else if (token_type === 22) depth--;
112
115
  }
113
116
  if (depth !== 0) return null;
@@ -224,7 +227,7 @@ var AtRulePreludeParser = class {
224
227
  while (this.lexer.pos < this.prelude_end && depth > 0) {
225
228
  this.next_token();
226
229
  let inner_token_type = this.lexer.token_type;
227
- if (inner_token_type === 21) depth++;
230
+ if (inner_token_type === 21 || inner_token_type === 2) depth++;
228
231
  else if (inner_token_type === 22) depth--;
229
232
  }
230
233
  if (depth === 0) {
@@ -470,39 +473,8 @@ var AtRulePreludeParser = class {
470
473
  }
471
474
  return this.lexer.next_token_fast(false);
472
475
  }
473
- parse_value_token() {
474
- switch (this.lexer.token_type) {
475
- case 1: return this.create_node(10, this.lexer.token_start, this.lexer.token_end);
476
- case 10: return this.create_node(11, this.lexer.token_start, this.lexer.token_end);
477
- case 11:
478
- case 12: return this.create_node(12, this.lexer.token_start, this.lexer.token_end);
479
- case 5: return this.create_node(13, this.lexer.token_start, this.lexer.token_end);
480
- default: return null;
481
- }
482
- }
483
476
  parse_feature_value(start, end) {
484
- const saved_position = this.lexer.save_position();
485
- this.lexer.seek(start, this.lexer.line, this.lexer.column);
486
- let first_node = 0;
487
- let last_node = 0;
488
- while (this.lexer.pos < end) {
489
- this.lexer.next_token_fast(false);
490
- if (this.lexer.token_start >= end) break;
491
- let all_whitespace = true;
492
- for (let i = this.lexer.token_start; i < this.lexer.token_end && i < end; i++) if (!is_whitespace(this.source.charCodeAt(i))) {
493
- all_whitespace = false;
494
- break;
495
- }
496
- if (all_whitespace) continue;
497
- let node = this.parse_value_token();
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
- }
503
- }
504
- this.lexer.restore_position(saved_position);
505
- return first_node;
477
+ return this.value_node_parser.parse_chain(start, end, this.lexer.line, this.lexer.column);
506
478
  }
507
479
  parse_namespace_prelude() {
508
480
  let nodes = [];
@@ -531,7 +503,7 @@ var AtRulePreludeParser = class {
531
503
  let depth = 1;
532
504
  while (this.lexer.pos < this.prelude_end && depth > 0) {
533
505
  this.next_token();
534
- if (this.lexer.token_type === 21) depth++;
506
+ if (this.lexer.token_type === 21 || this.lexer.token_type === 2) depth++;
535
507
  else if (this.lexer.token_type === 22) depth--;
536
508
  }
537
509
  let content_end = this.lexer.token_start;
@@ -3,19 +3,10 @@ import { q as Value } from "./node-types-BRnQyc9B.js";
3
3
  //#region src/parse-value.d.ts
4
4
  /** @internal */
5
5
  declare class ValueParser {
6
- private lexer;
6
+ private nodes;
7
7
  private arena;
8
- private source;
9
- private value_end;
10
8
  constructor(arena: CSSDataArena, source: string);
11
9
  parse_value(start: number, end: number, start_line: number, start_column: number): number;
12
- private is_whitespace_inline;
13
- private parse_value_node;
14
- private create_node;
15
- private create_operator_node;
16
- private parse_operator_node;
17
- private parse_function_node;
18
- private parse_parenthesis_node;
19
10
  }
20
11
  /**
21
12
  * Parse a CSS declaration value string and return a VALUE node
@@ -1,181 +1,25 @@
1
- import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
1
  import { l as CSSDataArena } from "./arena-CFwM4uQs.js";
3
- import { a as is_whitespace, o as str_equals } from "./parse-dimension-ouWXNHdx.js";
4
2
  import { t as CSSNode } from "./css-node-B3EzCweR.js";
3
+ import { t as ValueNodeParser } from "./value-node-parser-CZ47v3hp.js";
5
4
  //#region src/parse-value.ts
6
5
  /** @internal */
7
6
  var ValueParser = class {
8
- lexer;
7
+ nodes;
9
8
  arena;
10
- source;
11
- value_end;
12
9
  constructor(arena, source) {
13
10
  this.arena = arena;
14
- this.source = source;
15
- this.lexer = new Lexer(source);
16
- this.value_end = 0;
11
+ this.nodes = new ValueNodeParser(arena, source);
17
12
  }
18
13
  parse_value(start, end, start_line, start_column) {
19
- this.value_end = end;
20
- this.lexer.seek(start, start_line, start_column);
21
- let first_node = 0;
22
- let last_node = 0;
23
- while (this.lexer.pos < this.value_end) {
24
- this.lexer.next_token_fast(false);
25
- if (this.lexer.token_start >= this.value_end) break;
26
- if (this.lexer.token_type === 26) break;
27
- if (this.is_whitespace_inline()) continue;
28
- let node = this.parse_value_node();
29
- if (node !== null) {
30
- if (first_node === 0) first_node = node;
31
- else this.arena.set_next_sibling(last_node, node);
32
- last_node = node;
33
- }
34
- }
14
+ let first_node = this.nodes.parse_chain(start, end, start_line, start_column);
35
15
  if (first_node === 0) return this.arena.create_node(50, start, 0, start_line, start_column);
16
+ let last_node = this.nodes.last_chain_node;
36
17
  let first_node_start = this.arena.get_start_offset(first_node);
37
18
  let last_node_end = this.arena.get_start_offset(last_node) + this.arena.get_length(last_node);
38
19
  let value_node = this.arena.create_node(50, first_node_start, last_node_end - first_node_start, start_line, start_column);
39
20
  this.arena.set_first_child(value_node, first_node);
40
21
  return value_node;
41
22
  }
42
- is_whitespace_inline() {
43
- if (this.lexer.token_start >= this.lexer.token_end) return false;
44
- for (let i = this.lexer.token_start; i < this.lexer.token_end; i++) if (!is_whitespace(this.source.charCodeAt(i))) return false;
45
- return true;
46
- }
47
- parse_value_node() {
48
- let token_type = this.lexer.token_type;
49
- let start = this.lexer.token_start;
50
- let end = this.lexer.token_end;
51
- switch (token_type) {
52
- case 1: return this.create_node(10, start, end);
53
- case 10: return this.create_node(11, start, end);
54
- case 11:
55
- case 12: return this.create_node(12, start, end);
56
- case 5: return this.create_node(13, start, end);
57
- case 4: return this.create_node(14, start, end);
58
- case 27: return this.create_node(19, start, end);
59
- case 2: return this.parse_function_node(start, end);
60
- case 9: return this.parse_operator_node(start, end);
61
- case 18: return this.create_node(16, start, end);
62
- case 21: return this.parse_parenthesis_node(start, end);
63
- default: return null;
64
- }
65
- }
66
- create_node(node_type, start, end) {
67
- let node = this.arena.create_node(node_type, start, end - start, this.lexer.token_line, this.lexer.token_column);
68
- this.arena.set_content_length(node, end - start);
69
- return node;
70
- }
71
- create_operator_node(start, end) {
72
- return this.create_node(16, start, end);
73
- }
74
- parse_operator_node(start, end) {
75
- let ch = this.source.charCodeAt(start);
76
- if (ch === 43 || ch === 45 || ch === 42 || ch === 47) return this.create_operator_node(start, end);
77
- return null;
78
- }
79
- parse_function_node(start, end) {
80
- let name_end = end - 1;
81
- let func_name_substr = this.source.substring(start, name_end);
82
- let node = this.arena.create_node(str_equals("url", func_name_substr) ? 18 : 15, start, 0, this.lexer.token_line, this.lexer.token_column);
83
- this.arena.set_content_start_delta(node, 0);
84
- this.arena.set_content_length(node, name_end - start);
85
- if (str_equals("url", func_name_substr) || str_equals("src", func_name_substr)) {
86
- let save_pos = this.lexer.save_position();
87
- this.lexer.next_token_fast(false);
88
- while (this.is_whitespace_inline() && this.lexer.pos < this.value_end) this.lexer.next_token_fast(false);
89
- let first_token_type = this.lexer.token_type;
90
- this.lexer.restore_position(save_pos);
91
- if (first_token_type === 5) {} else {
92
- let paren_depth = 1;
93
- let func_end = end;
94
- let content_start = end;
95
- let content_end = end;
96
- while (paren_depth > 0) {
97
- this.lexer.next_token_fast(false);
98
- let token_type = this.lexer.token_type;
99
- if (token_type === 26) break;
100
- if (token_type === 21 || token_type === 2) paren_depth++;
101
- else if (token_type === 22) {
102
- paren_depth--;
103
- if (paren_depth === 0) {
104
- content_end = this.lexer.token_start;
105
- func_end = this.lexer.token_end;
106
- break;
107
- }
108
- }
109
- }
110
- this.arena.set_length(node, func_end - start);
111
- this.arena.set_value_start_delta(node, content_start - start);
112
- this.arena.set_value_length(node, content_end - content_start);
113
- return node;
114
- }
115
- }
116
- let first_arg = 0;
117
- let last_arg = 0;
118
- let paren_depth = 1;
119
- let func_end = end;
120
- let content_start = end;
121
- let content_end = end;
122
- while (this.lexer.pos < this.value_end && paren_depth > 0) {
123
- this.lexer.next_token_fast(false);
124
- let token_type = this.lexer.token_type;
125
- if (token_type === 26) break;
126
- if (this.lexer.token_start >= this.value_end) break;
127
- if (token_type === 22) {
128
- paren_depth--;
129
- if (paren_depth === 0) {
130
- content_end = this.lexer.token_start;
131
- func_end = this.lexer.token_end;
132
- break;
133
- }
134
- }
135
- if (this.is_whitespace_inline()) continue;
136
- let arg_node = this.parse_value_node();
137
- if (arg_node !== null) {
138
- if (first_arg === 0) first_arg = arg_node;
139
- else this.arena.set_next_sibling(last_arg, arg_node);
140
- last_arg = arg_node;
141
- }
142
- }
143
- this.arena.set_length(node, func_end - start);
144
- this.arena.set_value_start_delta(node, content_start - start);
145
- this.arena.set_value_length(node, content_end - content_start);
146
- if (first_arg !== 0) this.arena.set_first_child(node, first_arg);
147
- return node;
148
- }
149
- parse_parenthesis_node(start, end) {
150
- let node = this.arena.create_node(17, start, 0, this.lexer.token_line, this.lexer.token_column);
151
- let first_child = 0;
152
- let last_child = 0;
153
- let paren_depth = 1;
154
- let paren_end = end;
155
- while (this.lexer.pos < this.value_end && paren_depth > 0) {
156
- this.lexer.next_token_fast(false);
157
- let token_type = this.lexer.token_type;
158
- if (token_type === 26) break;
159
- if (this.lexer.token_start >= this.value_end) break;
160
- if (token_type === 22) {
161
- paren_depth--;
162
- if (paren_depth === 0) {
163
- paren_end = this.lexer.token_end;
164
- break;
165
- }
166
- }
167
- if (this.is_whitespace_inline()) continue;
168
- let child_node = this.parse_value_node();
169
- if (child_node !== null) {
170
- if (first_child === 0) first_child = child_node;
171
- else this.arena.set_next_sibling(last_child, child_node);
172
- last_child = child_node;
173
- }
174
- }
175
- this.arena.set_length(node, paren_end - start);
176
- if (first_child !== 0) this.arena.set_first_child(node, first_child);
177
- return node;
178
- }
179
23
  };
180
24
  /**
181
25
  * Parse a CSS declaration value string and return a VALUE node
@@ -0,0 +1,176 @@
1
+ import { t as Lexer } from "./tokenize-BiRLfVbm.js";
2
+ import "./arena-CFwM4uQs.js";
3
+ import { a as is_whitespace, o as str_equals } from "./parse-dimension-ouWXNHdx.js";
4
+ //#region src/value-node-parser.ts
5
+ /** @internal */
6
+ var ValueNodeParser = class {
7
+ lexer;
8
+ arena;
9
+ source;
10
+ end = 0;
11
+ last_chain_node = 0;
12
+ constructor(arena, source) {
13
+ this.arena = arena;
14
+ this.source = source;
15
+ this.lexer = new Lexer(source);
16
+ }
17
+ parse_chain(start, end, start_line, start_column) {
18
+ this.end = end;
19
+ this.lexer.seek(start, start_line, start_column);
20
+ let first_node = 0;
21
+ let last_node = 0;
22
+ while (this.lexer.pos < this.end) {
23
+ this.lexer.next_token_fast(false);
24
+ if (this.lexer.token_start >= this.end) break;
25
+ if (this.lexer.token_type === 26) break;
26
+ if (this.is_whitespace_inline()) continue;
27
+ let node = this.parse_value_node();
28
+ if (node !== null) {
29
+ if (first_node === 0) first_node = node;
30
+ else this.arena.set_next_sibling(last_node, node);
31
+ last_node = node;
32
+ }
33
+ }
34
+ this.last_chain_node = last_node;
35
+ return first_node;
36
+ }
37
+ is_whitespace_inline() {
38
+ if (this.lexer.token_start >= this.lexer.token_end) return false;
39
+ for (let i = this.lexer.token_start; i < this.lexer.token_end; i++) if (!is_whitespace(this.source.charCodeAt(i))) return false;
40
+ return true;
41
+ }
42
+ parse_value_node() {
43
+ let token_type = this.lexer.token_type;
44
+ let start = this.lexer.token_start;
45
+ let end = this.lexer.token_end;
46
+ switch (token_type) {
47
+ case 1: return this.create_node(10, start, end);
48
+ case 10: return this.create_node(11, start, end);
49
+ case 11:
50
+ case 12: return this.create_node(12, start, end);
51
+ case 5: return this.create_node(13, start, end);
52
+ case 4: return this.create_node(14, start, end);
53
+ case 27: return this.create_node(19, start, end);
54
+ case 2: return this.parse_function_node(start, end);
55
+ case 9: return this.parse_operator_node(start, end);
56
+ case 18: return this.create_node(16, start, end);
57
+ case 21: return this.parse_parenthesis_node(start, end);
58
+ default: return null;
59
+ }
60
+ }
61
+ create_node(node_type, start, end) {
62
+ let node = this.arena.create_node(node_type, start, end - start, this.lexer.token_line, this.lexer.token_column);
63
+ this.arena.set_content_length(node, end - start);
64
+ return node;
65
+ }
66
+ create_operator_node(start, end) {
67
+ return this.create_node(16, start, end);
68
+ }
69
+ parse_operator_node(start, end) {
70
+ let ch = this.source.charCodeAt(start);
71
+ if (ch === 43 || ch === 45 || ch === 42 || ch === 47) return this.create_operator_node(start, end);
72
+ return null;
73
+ }
74
+ parse_function_node(start, end) {
75
+ let name_end = end - 1;
76
+ let func_name_substr = this.source.substring(start, name_end);
77
+ let node = this.arena.create_node(str_equals("url", func_name_substr) ? 18 : 15, start, 0, this.lexer.token_line, this.lexer.token_column);
78
+ this.arena.set_content_start_delta(node, 0);
79
+ this.arena.set_content_length(node, name_end - start);
80
+ if (str_equals("url", func_name_substr) || str_equals("src", func_name_substr)) {
81
+ let save_pos = this.lexer.save_position();
82
+ this.lexer.next_token_fast(false);
83
+ while (this.is_whitespace_inline() && this.lexer.pos < this.end) this.lexer.next_token_fast(false);
84
+ let first_token_type = this.lexer.token_type;
85
+ this.lexer.restore_position(save_pos);
86
+ if (first_token_type === 5) {} else {
87
+ let paren_depth = 1;
88
+ let func_end = end;
89
+ let content_start = end;
90
+ let content_end = end;
91
+ while (paren_depth > 0) {
92
+ this.lexer.next_token_fast(false);
93
+ let token_type = this.lexer.token_type;
94
+ if (token_type === 26) break;
95
+ if (token_type === 21 || token_type === 2) paren_depth++;
96
+ else if (token_type === 22) {
97
+ paren_depth--;
98
+ if (paren_depth === 0) {
99
+ content_end = this.lexer.token_start;
100
+ func_end = this.lexer.token_end;
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ this.arena.set_length(node, func_end - start);
106
+ this.arena.set_value_start_delta(node, content_start - start);
107
+ this.arena.set_value_length(node, content_end - content_start);
108
+ return node;
109
+ }
110
+ }
111
+ let first_arg = 0;
112
+ let last_arg = 0;
113
+ let paren_depth = 1;
114
+ let func_end = end;
115
+ let content_start = end;
116
+ let content_end = end;
117
+ while (this.lexer.pos < this.end && paren_depth > 0) {
118
+ this.lexer.next_token_fast(false);
119
+ let token_type = this.lexer.token_type;
120
+ if (token_type === 26) break;
121
+ if (this.lexer.token_start >= this.end) break;
122
+ if (token_type === 22) {
123
+ paren_depth--;
124
+ if (paren_depth === 0) {
125
+ content_end = this.lexer.token_start;
126
+ func_end = this.lexer.token_end;
127
+ break;
128
+ }
129
+ }
130
+ if (this.is_whitespace_inline()) continue;
131
+ let arg_node = this.parse_value_node();
132
+ if (arg_node !== null) {
133
+ if (first_arg === 0) first_arg = arg_node;
134
+ else this.arena.set_next_sibling(last_arg, arg_node);
135
+ last_arg = arg_node;
136
+ }
137
+ }
138
+ this.arena.set_length(node, func_end - start);
139
+ this.arena.set_value_start_delta(node, content_start - start);
140
+ this.arena.set_value_length(node, content_end - content_start);
141
+ if (first_arg !== 0) this.arena.set_first_child(node, first_arg);
142
+ return node;
143
+ }
144
+ parse_parenthesis_node(start, end) {
145
+ let node = this.arena.create_node(17, start, 0, this.lexer.token_line, this.lexer.token_column);
146
+ let first_child = 0;
147
+ let last_child = 0;
148
+ let paren_depth = 1;
149
+ let paren_end = end;
150
+ while (this.lexer.pos < this.end && paren_depth > 0) {
151
+ this.lexer.next_token_fast(false);
152
+ let token_type = this.lexer.token_type;
153
+ if (token_type === 26) break;
154
+ if (this.lexer.token_start >= this.end) break;
155
+ if (token_type === 22) {
156
+ paren_depth--;
157
+ if (paren_depth === 0) {
158
+ paren_end = this.lexer.token_end;
159
+ break;
160
+ }
161
+ }
162
+ if (this.is_whitespace_inline()) continue;
163
+ let child_node = this.parse_value_node();
164
+ if (child_node !== null) {
165
+ if (first_child === 0) first_child = child_node;
166
+ else this.arena.set_next_sibling(last_child, child_node);
167
+ last_child = child_node;
168
+ }
169
+ }
170
+ this.arena.set_length(node, paren_end - start);
171
+ if (first_child !== 0) this.arena.set_first_child(node, first_child);
172
+ return node;
173
+ }
174
+ };
175
+ //#endregion
176
+ export { ValueNodeParser as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@projectwallace/css-parser",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "description": "High-performance CSS lexer and parser, optimized for CSS inspection and analysis",
5
5
  "keywords": [
6
6
  "ast",