@projectwallace/css-parser 0.1.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.
- package/README.md +72 -0
- package/dist/arena.d.ts +84 -0
- package/dist/at-rule-prelude-parser-DlqYQAYH.js +464 -0
- package/dist/at-rule-prelude-parser.d.ts +24 -0
- package/dist/char-types.d.ts +7 -0
- package/dist/css-node.d.ts +31 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +28 -0
- package/dist/lexer-DXablYMZ.js +479 -0
- package/dist/lexer.d.ts +27 -0
- package/dist/parse-atrule-prelude.d.ts +8 -0
- package/dist/parse-atrule-prelude.js +11 -0
- package/dist/parse-selector.d.ts +7 -0
- package/dist/parse-selector.js +19 -0
- package/dist/parse.d.ts +9 -0
- package/dist/parse.js +512 -0
- package/dist/parser.d.ts +34 -0
- package/dist/selector-parser-2b3tGyri.js +365 -0
- package/dist/selector-parser.d.ts +25 -0
- package/dist/string-utils-B-rJII-E.js +440 -0
- package/dist/string-utils.d.ts +29 -0
- package/dist/token-types.d.ts +34 -0
- package/dist/tokenize.d.ts +8 -0
- package/dist/tokenize.js +14 -0
- package/dist/value-parser.d.ts +19 -0
- package/dist/walk.d.ts +20 -0
- package/package.json +78 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { parse } from './parse';
|
|
2
|
+
export { parse_selector } from './parse-selector';
|
|
3
|
+
export { parse_atrule_prelude } from './parse-atrule-prelude';
|
|
4
|
+
export { tokenize } from './tokenize';
|
|
5
|
+
export { walk, walk_enter_leave } from './walk';
|
|
6
|
+
export { type ParserOptions } from './parser';
|
|
7
|
+
export { CSSNode, type CSSNodeType } from './css-node';
|
|
8
|
+
export { NODE_STYLE_RULE, NODE_AT_RULE, NODE_COMMENT, NODE_DECLARATION, NODE_SELECTOR, NODE_STYLESHEET, NODE_VALUE_KEYWORD, NODE_VALUE_NUMBER, NODE_VALUE_DIMENSION, NODE_VALUE_STRING, NODE_VALUE_COLOR, NODE_VALUE_FUNCTION, NODE_VALUE_OPERATOR, NODE_SELECTOR_LIST, NODE_SELECTOR_TYPE, NODE_SELECTOR_CLASS, NODE_SELECTOR_ID, NODE_SELECTOR_ATTRIBUTE, NODE_SELECTOR_PSEUDO_CLASS, NODE_SELECTOR_PSEUDO_ELEMENT, NODE_SELECTOR_COMBINATOR, NODE_SELECTOR_UNIVERSAL, NODE_SELECTOR_NESTING, NODE_PRELUDE_MEDIA_QUERY, NODE_PRELUDE_MEDIA_FEATURE, NODE_PRELUDE_MEDIA_TYPE, NODE_PRELUDE_CONTAINER_QUERY, NODE_PRELUDE_SUPPORTS_QUERY, NODE_PRELUDE_LAYER_NAME, NODE_PRELUDE_IDENTIFIER, NODE_PRELUDE_OPERATOR, NODE_PRELUDE_IMPORT_URL, NODE_PRELUDE_IMPORT_LAYER, NODE_PRELUDE_IMPORT_SUPPORTS, FLAG_IMPORTANT, } from './parser';
|
|
9
|
+
export { TOKEN_IDENT, TOKEN_FUNCTION, TOKEN_AT_KEYWORD, TOKEN_HASH, TOKEN_STRING, TOKEN_BAD_STRING, TOKEN_URL, TOKEN_BAD_URL, TOKEN_DELIM, TOKEN_NUMBER, TOKEN_PERCENTAGE, TOKEN_DIMENSION, TOKEN_WHITESPACE, TOKEN_CDO, TOKEN_CDC, TOKEN_COLON, TOKEN_SEMICOLON, TOKEN_COMMA, TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET, TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, TOKEN_COMMENT, TOKEN_EOF, type Token, type TokenType, } from './token-types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export { parse } from './parse.js';
|
|
2
|
+
export { parse_selector } from './parse-selector.js';
|
|
3
|
+
export { parse_atrule_prelude } from './parse-atrule-prelude.js';
|
|
4
|
+
export { tokenize } from './tokenize.js';
|
|
5
|
+
export { C as CSSNode, I as FLAG_IMPORTANT, a as NODE_AT_RULE, b as NODE_COMMENT, c as NODE_DECLARATION, z as NODE_PRELUDE_CONTAINER_QUERY, D as NODE_PRELUDE_IDENTIFIER, G as NODE_PRELUDE_IMPORT_LAYER, H as NODE_PRELUDE_IMPORT_SUPPORTS, F as NODE_PRELUDE_IMPORT_URL, B as NODE_PRELUDE_LAYER_NAME, x as NODE_PRELUDE_MEDIA_FEATURE, w as NODE_PRELUDE_MEDIA_QUERY, y as NODE_PRELUDE_MEDIA_TYPE, E as NODE_PRELUDE_OPERATOR, A as NODE_PRELUDE_SUPPORTS_QUERY, d as NODE_SELECTOR, q as NODE_SELECTOR_ATTRIBUTE, o as NODE_SELECTOR_CLASS, t as NODE_SELECTOR_COMBINATOR, p as NODE_SELECTOR_ID, m as NODE_SELECTOR_LIST, v as NODE_SELECTOR_NESTING, r as NODE_SELECTOR_PSEUDO_CLASS, s as NODE_SELECTOR_PSEUDO_ELEMENT, n as NODE_SELECTOR_TYPE, u as NODE_SELECTOR_UNIVERSAL, e as NODE_STYLESHEET, N as NODE_STYLE_RULE, j as NODE_VALUE_COLOR, h as NODE_VALUE_DIMENSION, k as NODE_VALUE_FUNCTION, f as NODE_VALUE_KEYWORD, g as NODE_VALUE_NUMBER, l as NODE_VALUE_OPERATOR, i as NODE_VALUE_STRING } from './string-utils-B-rJII-E.js';
|
|
6
|
+
export { b as TOKEN_AT_KEYWORD, e as TOKEN_BAD_STRING, g as TOKEN_BAD_URL, n as TOKEN_CDC, m as TOKEN_CDO, o as TOKEN_COLON, q as TOKEN_COMMA, x as TOKEN_COMMENT, h as TOKEN_DELIM, k as TOKEN_DIMENSION, y as TOKEN_EOF, a as TOKEN_FUNCTION, c as TOKEN_HASH, T as TOKEN_IDENT, v as TOKEN_LEFT_BRACE, r as TOKEN_LEFT_BRACKET, t as TOKEN_LEFT_PAREN, i as TOKEN_NUMBER, j as TOKEN_PERCENTAGE, w as TOKEN_RIGHT_BRACE, s as TOKEN_RIGHT_BRACKET, u as TOKEN_RIGHT_PAREN, p as TOKEN_SEMICOLON, d as TOKEN_STRING, f as TOKEN_URL, l as TOKEN_WHITESPACE } from './lexer-DXablYMZ.js';
|
|
7
|
+
|
|
8
|
+
function walk(node, callback, depth = 0) {
|
|
9
|
+
callback(node, depth);
|
|
10
|
+
let child = node.first_child;
|
|
11
|
+
while (child) {
|
|
12
|
+
walk(child, callback, depth + 1);
|
|
13
|
+
child = child.next_sibling;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
const NOOP = function() {
|
|
17
|
+
};
|
|
18
|
+
function walk_enter_leave(node, { enter = NOOP, leave = NOOP } = {}) {
|
|
19
|
+
enter(node);
|
|
20
|
+
let child = node.first_child;
|
|
21
|
+
while (child) {
|
|
22
|
+
walk_enter_leave(child, { enter, leave });
|
|
23
|
+
child = child.next_sibling;
|
|
24
|
+
}
|
|
25
|
+
leave(node);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { walk, walk_enter_leave };
|
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
let CHAR_ALPHA = 1 << 0;
|
|
2
|
+
let CHAR_DIGIT = 1 << 1;
|
|
3
|
+
let CHAR_HEX = 1 << 2;
|
|
4
|
+
let CHAR_WHITESPACE = 1 << 3;
|
|
5
|
+
let CHAR_NEWLINE = 1 << 4;
|
|
6
|
+
let char_types = new Uint8Array(128);
|
|
7
|
+
for (let i = 48; i <= 57; i++) {
|
|
8
|
+
char_types[i] = CHAR_DIGIT;
|
|
9
|
+
}
|
|
10
|
+
for (let i = 48; i <= 57; i++) {
|
|
11
|
+
char_types[i] |= CHAR_HEX;
|
|
12
|
+
}
|
|
13
|
+
for (let i = 65; i <= 70; i++) {
|
|
14
|
+
char_types[i] = CHAR_HEX;
|
|
15
|
+
}
|
|
16
|
+
for (let i = 97; i <= 102; i++) {
|
|
17
|
+
char_types[i] = CHAR_HEX;
|
|
18
|
+
}
|
|
19
|
+
for (let i = 65; i <= 90; i++) {
|
|
20
|
+
char_types[i] |= CHAR_ALPHA;
|
|
21
|
+
}
|
|
22
|
+
for (let i = 97; i <= 122; i++) {
|
|
23
|
+
char_types[i] |= CHAR_ALPHA;
|
|
24
|
+
}
|
|
25
|
+
char_types[32] = CHAR_WHITESPACE;
|
|
26
|
+
char_types[9] = CHAR_WHITESPACE;
|
|
27
|
+
char_types[10] = CHAR_NEWLINE;
|
|
28
|
+
char_types[13] = CHAR_NEWLINE;
|
|
29
|
+
char_types[12] = CHAR_NEWLINE;
|
|
30
|
+
function is_digit(ch) {
|
|
31
|
+
return ch < 128 && (char_types[ch] & CHAR_DIGIT) !== 0;
|
|
32
|
+
}
|
|
33
|
+
function is_hex_digit(ch) {
|
|
34
|
+
return ch < 128 && (char_types[ch] & CHAR_HEX) !== 0;
|
|
35
|
+
}
|
|
36
|
+
function is_alpha(ch) {
|
|
37
|
+
return ch < 128 && (char_types[ch] & CHAR_ALPHA) !== 0;
|
|
38
|
+
}
|
|
39
|
+
function is_whitespace(ch) {
|
|
40
|
+
return ch < 128 && (char_types[ch] & CHAR_WHITESPACE) !== 0;
|
|
41
|
+
}
|
|
42
|
+
function is_newline(ch) {
|
|
43
|
+
return ch < 128 && (char_types[ch] & CHAR_NEWLINE) !== 0;
|
|
44
|
+
}
|
|
45
|
+
function is_ident_start(ch) {
|
|
46
|
+
if (ch >= 128) return true;
|
|
47
|
+
if (ch === 95) return true;
|
|
48
|
+
return is_alpha(ch);
|
|
49
|
+
}
|
|
50
|
+
function is_ident_char(ch) {
|
|
51
|
+
if (ch === 45) return true;
|
|
52
|
+
return is_ident_start(ch) || is_digit(ch);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const TOKEN_IDENT = 1;
|
|
56
|
+
const TOKEN_FUNCTION = 2;
|
|
57
|
+
const TOKEN_AT_KEYWORD = 3;
|
|
58
|
+
const TOKEN_HASH = 4;
|
|
59
|
+
const TOKEN_STRING = 5;
|
|
60
|
+
const TOKEN_BAD_STRING = 6;
|
|
61
|
+
const TOKEN_URL = 7;
|
|
62
|
+
const TOKEN_BAD_URL = 8;
|
|
63
|
+
const TOKEN_DELIM = 9;
|
|
64
|
+
const TOKEN_NUMBER = 10;
|
|
65
|
+
const TOKEN_PERCENTAGE = 11;
|
|
66
|
+
const TOKEN_DIMENSION = 12;
|
|
67
|
+
const TOKEN_WHITESPACE = 13;
|
|
68
|
+
const TOKEN_CDO = 14;
|
|
69
|
+
const TOKEN_CDC = 15;
|
|
70
|
+
const TOKEN_COLON = 16;
|
|
71
|
+
const TOKEN_SEMICOLON = 17;
|
|
72
|
+
const TOKEN_COMMA = 18;
|
|
73
|
+
const TOKEN_LEFT_BRACKET = 19;
|
|
74
|
+
const TOKEN_RIGHT_BRACKET = 20;
|
|
75
|
+
const TOKEN_LEFT_PAREN = 21;
|
|
76
|
+
const TOKEN_RIGHT_PAREN = 22;
|
|
77
|
+
const TOKEN_LEFT_BRACE = 23;
|
|
78
|
+
const TOKEN_RIGHT_BRACE = 24;
|
|
79
|
+
const TOKEN_COMMENT = 25;
|
|
80
|
+
const TOKEN_EOF = 26;
|
|
81
|
+
|
|
82
|
+
const CHAR_LEFT_BRACE = 123;
|
|
83
|
+
const CHAR_RIGHT_BRACE = 125;
|
|
84
|
+
const CHAR_COLON = 58;
|
|
85
|
+
const CHAR_SEMICOLON = 59;
|
|
86
|
+
const CHAR_COMMA = 44;
|
|
87
|
+
const CHAR_LEFT_BRACKET = 91;
|
|
88
|
+
const CHAR_RIGHT_BRACKET = 93;
|
|
89
|
+
const CHAR_LEFT_PAREN = 40;
|
|
90
|
+
const CHAR_RIGHT_PAREN = 41;
|
|
91
|
+
const CHAR_FORWARD_SLASH = 47;
|
|
92
|
+
const CHAR_ASTERISK = 42;
|
|
93
|
+
const CHAR_DOUBLE_QUOTE = 34;
|
|
94
|
+
const CHAR_SINGLE_QUOTE = 39;
|
|
95
|
+
const CHAR_DOT = 46;
|
|
96
|
+
const CHAR_LESS_THAN = 60;
|
|
97
|
+
const CHAR_EXCLAMATION = 33;
|
|
98
|
+
const CHAR_HYPHEN = 45;
|
|
99
|
+
const CHAR_GREATER_THAN = 62;
|
|
100
|
+
const CHAR_AT_SIGN = 64;
|
|
101
|
+
const CHAR_HASH = 35;
|
|
102
|
+
const CHAR_BACKSLASH = 92;
|
|
103
|
+
const CHAR_PLUS = 43;
|
|
104
|
+
const CHAR_PERCENT = 37;
|
|
105
|
+
const CHAR_LOWERCASE_E = 101;
|
|
106
|
+
const CHAR_UPPERCASE_E = 69;
|
|
107
|
+
const CHAR_CARRIAGE_RETURN = 13;
|
|
108
|
+
const CHAR_LINE_FEED = 10;
|
|
109
|
+
class Lexer {
|
|
110
|
+
source;
|
|
111
|
+
pos;
|
|
112
|
+
line;
|
|
113
|
+
column;
|
|
114
|
+
skip_comments;
|
|
115
|
+
// Current token properties (avoiding object allocation)
|
|
116
|
+
token_type;
|
|
117
|
+
token_start;
|
|
118
|
+
token_end;
|
|
119
|
+
token_line;
|
|
120
|
+
token_column;
|
|
121
|
+
constructor(source, skip_comments = false) {
|
|
122
|
+
this.source = source;
|
|
123
|
+
this.pos = 0;
|
|
124
|
+
this.line = 1;
|
|
125
|
+
this.column = 1;
|
|
126
|
+
this.skip_comments = skip_comments;
|
|
127
|
+
this.token_type = TOKEN_EOF;
|
|
128
|
+
this.token_start = 0;
|
|
129
|
+
this.token_end = 0;
|
|
130
|
+
this.token_line = 1;
|
|
131
|
+
this.token_column = 1;
|
|
132
|
+
}
|
|
133
|
+
// Fast token advancing without object allocation (for internal parser use)
|
|
134
|
+
next_token_fast(skip_whitespace = false) {
|
|
135
|
+
if (skip_whitespace) {
|
|
136
|
+
while (this.pos < this.source.length) {
|
|
137
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
138
|
+
if (!is_whitespace(ch2) && !is_newline(ch2)) break;
|
|
139
|
+
this.advance();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (this.pos >= this.source.length) {
|
|
143
|
+
return this.make_token(TOKEN_EOF, this.pos, this.pos);
|
|
144
|
+
}
|
|
145
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
146
|
+
let start = this.pos;
|
|
147
|
+
let start_line = this.line;
|
|
148
|
+
let start_column = this.column;
|
|
149
|
+
if (ch === CHAR_LEFT_BRACE) {
|
|
150
|
+
this.advance();
|
|
151
|
+
return this.make_token(TOKEN_LEFT_BRACE, start, this.pos, start_line, start_column);
|
|
152
|
+
}
|
|
153
|
+
if (ch === CHAR_RIGHT_BRACE) {
|
|
154
|
+
this.advance();
|
|
155
|
+
return this.make_token(TOKEN_RIGHT_BRACE, start, this.pos, start_line, start_column);
|
|
156
|
+
}
|
|
157
|
+
if (ch === CHAR_COLON) {
|
|
158
|
+
this.advance();
|
|
159
|
+
return this.make_token(TOKEN_COLON, start, this.pos, start_line, start_column);
|
|
160
|
+
}
|
|
161
|
+
if (ch === CHAR_SEMICOLON) {
|
|
162
|
+
this.advance();
|
|
163
|
+
return this.make_token(TOKEN_SEMICOLON, start, this.pos, start_line, start_column);
|
|
164
|
+
}
|
|
165
|
+
if (ch === CHAR_COMMA) {
|
|
166
|
+
this.advance();
|
|
167
|
+
return this.make_token(TOKEN_COMMA, start, this.pos, start_line, start_column);
|
|
168
|
+
}
|
|
169
|
+
if (ch === CHAR_LEFT_BRACKET) {
|
|
170
|
+
this.advance();
|
|
171
|
+
return this.make_token(TOKEN_LEFT_BRACKET, start, this.pos, start_line, start_column);
|
|
172
|
+
}
|
|
173
|
+
if (ch === CHAR_RIGHT_BRACKET) {
|
|
174
|
+
this.advance();
|
|
175
|
+
return this.make_token(TOKEN_RIGHT_BRACKET, start, this.pos, start_line, start_column);
|
|
176
|
+
}
|
|
177
|
+
if (ch === CHAR_LEFT_PAREN) {
|
|
178
|
+
this.advance();
|
|
179
|
+
return this.make_token(TOKEN_LEFT_PAREN, start, this.pos, start_line, start_column);
|
|
180
|
+
}
|
|
181
|
+
if (ch === CHAR_RIGHT_PAREN) {
|
|
182
|
+
this.advance();
|
|
183
|
+
return this.make_token(TOKEN_RIGHT_PAREN, start, this.pos, start_line, start_column);
|
|
184
|
+
}
|
|
185
|
+
if (is_whitespace(ch) || is_newline(ch)) {
|
|
186
|
+
return this.consume_whitespace(start_line, start_column);
|
|
187
|
+
}
|
|
188
|
+
if (ch === CHAR_FORWARD_SLASH && this.peek() === CHAR_ASTERISK) {
|
|
189
|
+
if (this.skip_comments) {
|
|
190
|
+
this.advance(2);
|
|
191
|
+
while (this.pos < this.source.length - 1) {
|
|
192
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
193
|
+
if (ch2 === CHAR_ASTERISK && this.source.charCodeAt(this.pos + 1) === CHAR_FORWARD_SLASH) {
|
|
194
|
+
this.advance(2);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
this.advance();
|
|
198
|
+
}
|
|
199
|
+
return this.next_token_fast(skip_whitespace);
|
|
200
|
+
}
|
|
201
|
+
return this.consume_comment(start_line, start_column);
|
|
202
|
+
}
|
|
203
|
+
if (ch === CHAR_DOUBLE_QUOTE || ch === CHAR_SINGLE_QUOTE) {
|
|
204
|
+
return this.consume_string(ch, start_line, start_column);
|
|
205
|
+
}
|
|
206
|
+
if (is_digit(ch)) {
|
|
207
|
+
return this.consume_number(start_line, start_column);
|
|
208
|
+
}
|
|
209
|
+
if (ch === CHAR_DOT && is_digit(this.peek())) {
|
|
210
|
+
return this.consume_number(start_line, start_column);
|
|
211
|
+
}
|
|
212
|
+
if (ch === CHAR_LESS_THAN && this.pos + 3 < this.source.length) {
|
|
213
|
+
if (this.source.charCodeAt(this.pos + 1) === CHAR_EXCLAMATION && this.source.charCodeAt(this.pos + 2) === CHAR_HYPHEN && this.source.charCodeAt(this.pos + 3) === CHAR_HYPHEN) {
|
|
214
|
+
this.advance(4);
|
|
215
|
+
return this.make_token(TOKEN_CDO, start, this.pos, start_line, start_column);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (ch === CHAR_HYPHEN && this.pos + 2 < this.source.length) {
|
|
219
|
+
if (this.source.charCodeAt(this.pos + 1) === CHAR_HYPHEN && this.source.charCodeAt(this.pos + 2) === CHAR_GREATER_THAN) {
|
|
220
|
+
this.advance(3);
|
|
221
|
+
return this.make_token(TOKEN_CDC, start, this.pos, start_line, start_column);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (ch === CHAR_AT_SIGN) {
|
|
225
|
+
return this.consume_at_keyword(start_line, start_column);
|
|
226
|
+
}
|
|
227
|
+
if (ch === CHAR_HASH) {
|
|
228
|
+
return this.consume_hash(start_line, start_column);
|
|
229
|
+
}
|
|
230
|
+
if (is_ident_start(ch)) {
|
|
231
|
+
return this.consume_ident_or_function(start_line, start_column);
|
|
232
|
+
}
|
|
233
|
+
if (ch === CHAR_HYPHEN) {
|
|
234
|
+
let next = this.peek();
|
|
235
|
+
if (is_ident_start(next) || next === CHAR_HYPHEN) {
|
|
236
|
+
return this.consume_ident_or_function(start_line, start_column);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (ch === CHAR_BACKSLASH) {
|
|
240
|
+
let next = this.peek();
|
|
241
|
+
if (next !== 0 && !is_newline(next)) {
|
|
242
|
+
return this.consume_ident_or_function(start_line, start_column);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (ch === CHAR_HYPHEN || ch === CHAR_PLUS) {
|
|
246
|
+
let next = this.peek();
|
|
247
|
+
if (is_digit(next) || next === CHAR_DOT && is_digit(this.peek(2))) {
|
|
248
|
+
return this.consume_number(start_line, start_column);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
this.advance();
|
|
252
|
+
return this.make_token(TOKEN_DELIM, start, this.pos, start_line, start_column);
|
|
253
|
+
}
|
|
254
|
+
consume_whitespace(start_line, start_column) {
|
|
255
|
+
let start = this.pos;
|
|
256
|
+
while (this.pos < this.source.length) {
|
|
257
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
258
|
+
if (!is_whitespace(ch) && !is_newline(ch)) break;
|
|
259
|
+
this.advance();
|
|
260
|
+
}
|
|
261
|
+
return this.make_token(TOKEN_WHITESPACE, start, this.pos, start_line, start_column);
|
|
262
|
+
}
|
|
263
|
+
consume_comment(start_line, start_column) {
|
|
264
|
+
let start = this.pos;
|
|
265
|
+
this.advance(2);
|
|
266
|
+
while (this.pos < this.source.length - 1) {
|
|
267
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
268
|
+
if (ch === CHAR_ASTERISK && this.source.charCodeAt(this.pos + 1) === CHAR_FORWARD_SLASH) {
|
|
269
|
+
this.advance(2);
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
this.advance();
|
|
273
|
+
}
|
|
274
|
+
return this.make_token(TOKEN_COMMENT, start, this.pos, start_line, start_column);
|
|
275
|
+
}
|
|
276
|
+
consume_string(quote, start_line, start_column) {
|
|
277
|
+
let start = this.pos;
|
|
278
|
+
this.advance();
|
|
279
|
+
while (this.pos < this.source.length) {
|
|
280
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
281
|
+
if (ch === quote) {
|
|
282
|
+
this.advance();
|
|
283
|
+
return this.make_token(TOKEN_STRING, start, this.pos, start_line, start_column);
|
|
284
|
+
}
|
|
285
|
+
if (is_newline(ch)) {
|
|
286
|
+
return this.make_token(TOKEN_BAD_STRING, start, this.pos, start_line, start_column);
|
|
287
|
+
}
|
|
288
|
+
if (ch === CHAR_BACKSLASH) {
|
|
289
|
+
this.advance();
|
|
290
|
+
if (this.pos < this.source.length) {
|
|
291
|
+
let next = this.source.charCodeAt(this.pos);
|
|
292
|
+
if (is_hex_digit(next)) {
|
|
293
|
+
this.consume_hex_escape();
|
|
294
|
+
} else if (!is_newline(next)) {
|
|
295
|
+
this.advance();
|
|
296
|
+
} else {
|
|
297
|
+
this.advance();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
this.advance();
|
|
303
|
+
}
|
|
304
|
+
return this.make_token(TOKEN_BAD_STRING, start, this.pos, start_line, start_column);
|
|
305
|
+
}
|
|
306
|
+
consume_hex_escape() {
|
|
307
|
+
let count = 0;
|
|
308
|
+
while (count < 6 && this.pos < this.source.length) {
|
|
309
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
310
|
+
if (!is_hex_digit(ch)) break;
|
|
311
|
+
this.advance();
|
|
312
|
+
count++;
|
|
313
|
+
}
|
|
314
|
+
if (this.pos < this.source.length) {
|
|
315
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
316
|
+
if (is_whitespace(ch) || is_newline(ch)) {
|
|
317
|
+
this.advance();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
consume_number(start_line, start_column) {
|
|
322
|
+
let start = this.pos;
|
|
323
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
324
|
+
if (ch === CHAR_PLUS || ch === CHAR_HYPHEN) {
|
|
325
|
+
this.advance();
|
|
326
|
+
}
|
|
327
|
+
while (this.pos < this.source.length && is_digit(this.source.charCodeAt(this.pos))) {
|
|
328
|
+
this.advance();
|
|
329
|
+
}
|
|
330
|
+
if (this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_DOT && this.pos + 1 < this.source.length && is_digit(this.source.charCodeAt(this.pos + 1))) {
|
|
331
|
+
this.advance();
|
|
332
|
+
while (this.pos < this.source.length && is_digit(this.source.charCodeAt(this.pos))) {
|
|
333
|
+
this.advance();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (this.pos < this.source.length) {
|
|
337
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
338
|
+
if (ch2 === CHAR_LOWERCASE_E || ch2 === CHAR_UPPERCASE_E) {
|
|
339
|
+
let next = this.peek();
|
|
340
|
+
if (is_digit(next) || (next === CHAR_PLUS || next === CHAR_HYPHEN) && is_digit(this.peek(2))) {
|
|
341
|
+
this.advance();
|
|
342
|
+
if (this.pos < this.source.length) {
|
|
343
|
+
let sign = this.source.charCodeAt(this.pos);
|
|
344
|
+
if (sign === CHAR_PLUS || sign === CHAR_HYPHEN) {
|
|
345
|
+
this.advance();
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
while (this.pos < this.source.length && is_digit(this.source.charCodeAt(this.pos))) {
|
|
349
|
+
this.advance();
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (this.pos < this.source.length) {
|
|
355
|
+
let ch2 = this.source.charCodeAt(this.pos);
|
|
356
|
+
if (ch2 === CHAR_PERCENT) {
|
|
357
|
+
this.advance();
|
|
358
|
+
return this.make_token(TOKEN_PERCENTAGE, start, this.pos, start_line, start_column);
|
|
359
|
+
}
|
|
360
|
+
if (is_ident_start(ch2) || ch2 === CHAR_HYPHEN && is_ident_start(this.peek())) {
|
|
361
|
+
while (this.pos < this.source.length && is_ident_char(this.source.charCodeAt(this.pos))) {
|
|
362
|
+
this.advance();
|
|
363
|
+
}
|
|
364
|
+
return this.make_token(TOKEN_DIMENSION, start, this.pos, start_line, start_column);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return this.make_token(TOKEN_NUMBER, start, this.pos, start_line, start_column);
|
|
368
|
+
}
|
|
369
|
+
consume_ident_or_function(start_line, start_column) {
|
|
370
|
+
let start = this.pos;
|
|
371
|
+
while (this.pos < this.source.length) {
|
|
372
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
373
|
+
if (ch === CHAR_BACKSLASH) {
|
|
374
|
+
if (this.pos + 1 >= this.source.length) break;
|
|
375
|
+
let next = this.source.charCodeAt(this.pos + 1);
|
|
376
|
+
if (is_newline(next)) break;
|
|
377
|
+
this.advance();
|
|
378
|
+
if (is_hex_digit(next)) {
|
|
379
|
+
this.advance();
|
|
380
|
+
for (let i = 0; i < 5 && this.pos < this.source.length; i++) {
|
|
381
|
+
if (!is_hex_digit(this.source.charCodeAt(this.pos))) break;
|
|
382
|
+
this.advance();
|
|
383
|
+
}
|
|
384
|
+
if (this.pos < this.source.length) {
|
|
385
|
+
let ws = this.source.charCodeAt(this.pos);
|
|
386
|
+
if (is_whitespace(ws) || is_newline(ws)) {
|
|
387
|
+
this.advance();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
this.advance();
|
|
392
|
+
}
|
|
393
|
+
} else if (is_ident_char(ch)) {
|
|
394
|
+
this.advance();
|
|
395
|
+
} else {
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_LEFT_PAREN) {
|
|
400
|
+
this.advance();
|
|
401
|
+
return this.make_token(TOKEN_FUNCTION, start, this.pos, start_line, start_column);
|
|
402
|
+
}
|
|
403
|
+
return this.make_token(TOKEN_IDENT, start, this.pos, start_line, start_column);
|
|
404
|
+
}
|
|
405
|
+
consume_at_keyword(start_line, start_column) {
|
|
406
|
+
let start = this.pos;
|
|
407
|
+
this.advance();
|
|
408
|
+
while (this.pos < this.source.length && is_ident_char(this.source.charCodeAt(this.pos))) {
|
|
409
|
+
this.advance();
|
|
410
|
+
}
|
|
411
|
+
return this.make_token(TOKEN_AT_KEYWORD, start, this.pos, start_line, start_column);
|
|
412
|
+
}
|
|
413
|
+
consume_hash(start_line, start_column) {
|
|
414
|
+
let start = this.pos;
|
|
415
|
+
this.advance();
|
|
416
|
+
while (this.pos < this.source.length && is_ident_char(this.source.charCodeAt(this.pos))) {
|
|
417
|
+
this.advance();
|
|
418
|
+
}
|
|
419
|
+
return this.make_token(TOKEN_HASH, start, this.pos, start_line, start_column);
|
|
420
|
+
}
|
|
421
|
+
advance(count = 1) {
|
|
422
|
+
if (count === 1) {
|
|
423
|
+
if (this.pos >= this.source.length) return;
|
|
424
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
425
|
+
this.pos++;
|
|
426
|
+
if (is_newline(ch)) {
|
|
427
|
+
if (ch === CHAR_CARRIAGE_RETURN && this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_LINE_FEED) {
|
|
428
|
+
this.pos++;
|
|
429
|
+
}
|
|
430
|
+
this.line++;
|
|
431
|
+
this.column = 1;
|
|
432
|
+
} else {
|
|
433
|
+
this.column++;
|
|
434
|
+
}
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
for (let i = 0; i < count; i++) {
|
|
438
|
+
if (this.pos >= this.source.length) break;
|
|
439
|
+
let ch = this.source.charCodeAt(this.pos);
|
|
440
|
+
this.pos++;
|
|
441
|
+
if (is_newline(ch)) {
|
|
442
|
+
if (ch === CHAR_CARRIAGE_RETURN && this.pos < this.source.length && this.source.charCodeAt(this.pos) === CHAR_LINE_FEED) {
|
|
443
|
+
this.pos++;
|
|
444
|
+
i++;
|
|
445
|
+
}
|
|
446
|
+
this.line++;
|
|
447
|
+
this.column = 1;
|
|
448
|
+
} else {
|
|
449
|
+
this.column++;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
peek(offset = 1) {
|
|
454
|
+
let index = this.pos + offset;
|
|
455
|
+
if (index >= this.source.length) return 0;
|
|
456
|
+
return this.source.charCodeAt(index);
|
|
457
|
+
}
|
|
458
|
+
make_token(type, start, end, line = this.line, column = this.column) {
|
|
459
|
+
this.token_type = type;
|
|
460
|
+
this.token_start = start;
|
|
461
|
+
this.token_end = end;
|
|
462
|
+
this.token_line = line;
|
|
463
|
+
this.token_column = column;
|
|
464
|
+
return type;
|
|
465
|
+
}
|
|
466
|
+
// Public API: returns Token object for backwards compatibility
|
|
467
|
+
next_token(skip_whitespace = false) {
|
|
468
|
+
this.next_token_fast(skip_whitespace);
|
|
469
|
+
return {
|
|
470
|
+
type: this.token_type,
|
|
471
|
+
start: this.token_start,
|
|
472
|
+
end: this.token_end,
|
|
473
|
+
line: this.token_line,
|
|
474
|
+
column: this.token_column
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
export { Lexer as L, TOKEN_IDENT as T, TOKEN_FUNCTION as a, TOKEN_AT_KEYWORD as b, TOKEN_HASH as c, TOKEN_STRING as d, TOKEN_BAD_STRING as e, TOKEN_URL as f, TOKEN_BAD_URL as g, TOKEN_DELIM as h, TOKEN_NUMBER as i, TOKEN_PERCENTAGE as j, TOKEN_DIMENSION as k, TOKEN_WHITESPACE as l, TOKEN_CDO as m, TOKEN_CDC as n, TOKEN_COLON as o, TOKEN_SEMICOLON as p, TOKEN_COMMA as q, TOKEN_LEFT_BRACKET as r, TOKEN_RIGHT_BRACKET as s, TOKEN_LEFT_PAREN as t, TOKEN_RIGHT_PAREN as u, TOKEN_LEFT_BRACE as v, TOKEN_RIGHT_BRACE as w, TOKEN_COMMENT as x, TOKEN_EOF as y };
|
package/dist/lexer.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Token, type TokenType } from './token-types';
|
|
2
|
+
export declare class Lexer {
|
|
3
|
+
source: string;
|
|
4
|
+
pos: number;
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
skip_comments: boolean;
|
|
8
|
+
token_type: TokenType;
|
|
9
|
+
token_start: number;
|
|
10
|
+
token_end: number;
|
|
11
|
+
token_line: number;
|
|
12
|
+
token_column: number;
|
|
13
|
+
constructor(source: string, skip_comments?: boolean);
|
|
14
|
+
next_token_fast(skip_whitespace?: boolean): TokenType;
|
|
15
|
+
consume_whitespace(start_line: number, start_column: number): TokenType;
|
|
16
|
+
consume_comment(start_line: number, start_column: number): TokenType;
|
|
17
|
+
consume_string(quote: number, start_line: number, start_column: number): TokenType;
|
|
18
|
+
consume_hex_escape(): void;
|
|
19
|
+
consume_number(start_line: number, start_column: number): TokenType;
|
|
20
|
+
consume_ident_or_function(start_line: number, start_column: number): TokenType;
|
|
21
|
+
consume_at_keyword(start_line: number, start_column: number): TokenType;
|
|
22
|
+
consume_hash(start_line: number, start_column: number): TokenType;
|
|
23
|
+
advance(count?: number): void;
|
|
24
|
+
peek(offset?: number): number;
|
|
25
|
+
make_token(type: TokenType, start: number, end: number, line?: number, column?: number): TokenType;
|
|
26
|
+
next_token(skip_whitespace?: boolean): Token | null;
|
|
27
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CSSNode } from './css-node';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an at-rule prelude string and return an array of AST nodes
|
|
4
|
+
* @param at_rule_name - The name of the at-rule (e.g., "media", "supports", "layer")
|
|
5
|
+
* @param prelude - The at-rule prelude to parse (e.g., "(min-width: 768px)", "utilities")
|
|
6
|
+
* @returns An array of CSSNode objects representing the parsed prelude
|
|
7
|
+
*/
|
|
8
|
+
export declare function parse_atrule_prelude(at_rule_name: string, prelude: string): CSSNode[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { K as CSSDataArena, C as CSSNode } from './string-utils-B-rJII-E.js';
|
|
2
|
+
import { A as AtRulePreludeParser } from './at-rule-prelude-parser-DlqYQAYH.js';
|
|
3
|
+
|
|
4
|
+
function parse_atrule_prelude(at_rule_name, prelude) {
|
|
5
|
+
const arena = new CSSDataArena(CSSDataArena.capacity_for_source(prelude.length));
|
|
6
|
+
const prelude_parser = new AtRulePreludeParser(arena, prelude);
|
|
7
|
+
const node_indices = prelude_parser.parse_prelude(at_rule_name, 0, prelude.length);
|
|
8
|
+
return node_indices.map((index) => new CSSNode(arena, prelude, index));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { parse_atrule_prelude };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CSSNode } from './css-node';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a CSS selector string and return an AST
|
|
4
|
+
* @param source - The CSS selector to parse (e.g., "div.class > p#id")
|
|
5
|
+
* @returns The root CSSNode of the selector AST
|
|
6
|
+
*/
|
|
7
|
+
export declare function parse_selector(source: string): CSSNode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { K as CSSDataArena, d as NODE_SELECTOR, C as CSSNode } from './string-utils-B-rJII-E.js';
|
|
2
|
+
import { S as SelectorParser } from './selector-parser-2b3tGyri.js';
|
|
3
|
+
|
|
4
|
+
function parse_selector(source) {
|
|
5
|
+
const arena = new CSSDataArena(CSSDataArena.capacity_for_source(source.length));
|
|
6
|
+
const selector_parser = new SelectorParser(arena, source);
|
|
7
|
+
const selector_index = selector_parser.parse_selector(0, source.length);
|
|
8
|
+
if (selector_index === null) {
|
|
9
|
+
const empty = arena.create_node();
|
|
10
|
+
arena.set_type(empty, NODE_SELECTOR);
|
|
11
|
+
arena.set_start_offset(empty, 0);
|
|
12
|
+
arena.set_length(empty, 0);
|
|
13
|
+
arena.set_start_line(empty, 1);
|
|
14
|
+
return new CSSNode(arena, source, empty);
|
|
15
|
+
}
|
|
16
|
+
return new CSSNode(arena, source, selector_index);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { parse_selector };
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ParserOptions } from './parser';
|
|
2
|
+
import type { CSSNode } from './css-node';
|
|
3
|
+
/**
|
|
4
|
+
* Parse CSS and return an AST
|
|
5
|
+
* @param source - The CSS source code to parse
|
|
6
|
+
* @param options - Parser options
|
|
7
|
+
* @returns The root CSSNode of the AST
|
|
8
|
+
*/
|
|
9
|
+
export declare function parse(source: string, options?: ParserOptions): CSSNode;
|