@tbela99/css-parser 0.2.0 → 0.4.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/{LICENSE → LICENSE.md} +1 -1
- package/README.md +250 -77
- package/dist/config.json.js +245 -1
- package/dist/index-umd-web.js +4241 -1583
- package/dist/index.cjs +4242 -1584
- package/dist/index.d.ts +71 -23
- package/dist/lib/ast/expand.js +1 -1
- package/dist/lib/ast/features/calc.js +31 -192
- package/dist/lib/ast/features/index.js +3 -3
- package/dist/lib/ast/features/inlinecssvariables.js +6 -6
- package/dist/lib/ast/features/shorthand.js +5 -6
- package/dist/lib/ast/math/expression.js +220 -0
- package/dist/lib/ast/{features/utils → math}/math.js +4 -4
- package/dist/lib/ast/minify.js +0 -1
- package/dist/lib/ast/types.js +31 -13
- package/dist/lib/ast/utils/minifyfeature.js +4 -3
- package/dist/lib/ast/walk.js +24 -4
- package/dist/lib/fs/resolve.js +4 -3
- package/dist/lib/parser/declaration/list.js +6 -2
- package/dist/lib/parser/declaration/map.js +158 -24
- package/dist/lib/parser/declaration/set.js +42 -22
- package/dist/lib/parser/parse.js +345 -349
- package/dist/lib/parser/tokenize.js +220 -223
- package/dist/lib/parser/utils/declaration.js +67 -0
- package/dist/lib/parser/utils/syntax.js +172 -6
- package/dist/lib/parser/utils/type.js +2 -2
- package/dist/lib/renderer/color/a98rgb.js +64 -0
- package/dist/lib/renderer/color/color.js +521 -0
- package/dist/lib/renderer/color/colormix.js +337 -0
- package/dist/lib/renderer/color/hex.js +92 -0
- package/dist/lib/renderer/color/hsl.js +118 -0
- package/dist/lib/renderer/color/hsv.js +20 -0
- package/dist/lib/renderer/color/hwb.js +101 -0
- package/dist/lib/renderer/color/lab.js +136 -0
- package/dist/lib/renderer/color/lch.js +79 -0
- package/dist/lib/renderer/color/oklab.js +121 -0
- package/dist/lib/renderer/color/oklch.js +65 -0
- package/dist/lib/renderer/color/p3.js +57 -0
- package/dist/lib/renderer/color/prophotorgb.js +56 -0
- package/dist/lib/renderer/color/rec2020.js +70 -0
- package/dist/lib/renderer/color/relativecolor.js +152 -0
- package/dist/lib/renderer/color/rgb.js +44 -0
- package/dist/lib/renderer/color/srgb.js +261 -0
- package/dist/lib/renderer/color/utils/components.js +20 -0
- package/dist/lib/renderer/color/utils/constants.js +191 -0
- package/dist/lib/renderer/color/utils/matrix.js +35 -0
- package/dist/lib/renderer/color/xyz.js +64 -0
- package/dist/lib/renderer/color/xyzd50.js +33 -0
- package/dist/lib/renderer/render.js +128 -30
- package/dist/node/index.js +1 -1
- package/dist/node/load.js +1 -1
- package/dist/web/index.js +1 -1
- package/package.json +19 -18
- package/quickjs.sh +1 -0
- package/dist/lib/iterable/weakmap.js +0 -53
- package/dist/lib/renderer/utils/color.js +0 -499
- /package/dist/lib/iterable/{set.js → weakset.js} +0 -0
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,24 +1,15 @@
|
|
|
1
|
-
import { isPseudo, isAtKeyword, isFunction, isNumber, isDimension, parseDimension,
|
|
2
|
-
import { EnumToken } from '../ast/types.js';
|
|
1
|
+
import { isPseudo, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isIdent, isHexColor, isHash, isIdentStart, isColor } from './utils/syntax.js';
|
|
2
|
+
import { EnumToken, funcLike } from '../ast/types.js';
|
|
3
3
|
import { minify, combinators } from '../ast/minify.js';
|
|
4
4
|
import { walkValues, walk } from '../ast/walk.js';
|
|
5
5
|
import { expand } from '../ast/expand.js';
|
|
6
|
+
import { parseDeclaration } from './utils/declaration.js';
|
|
6
7
|
import { renderToken } from '../renderer/render.js';
|
|
7
|
-
import { COLORS_NAMES } from '../renderer/utils/
|
|
8
|
+
import { COLORS_NAMES } from '../renderer/color/utils/constants.js';
|
|
8
9
|
import { tokenize } from './tokenize.js';
|
|
9
10
|
|
|
10
11
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
11
12
|
const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
|
|
12
|
-
const funcLike = [
|
|
13
|
-
EnumToken.ParensTokenType,
|
|
14
|
-
EnumToken.FunctionTokenType,
|
|
15
|
-
EnumToken.UrlFunctionTokenType,
|
|
16
|
-
EnumToken.StartParensTokenType,
|
|
17
|
-
EnumToken.ImageFunctionTokenType,
|
|
18
|
-
EnumToken.PseudoClassFuncTokenType,
|
|
19
|
-
EnumToken.TimingFunctionTokenType,
|
|
20
|
-
EnumToken.TimingFunctionTokenType
|
|
21
|
-
];
|
|
22
13
|
const BadTokensTypes = [
|
|
23
14
|
EnumToken.BadCommentTokenType,
|
|
24
15
|
EnumToken.BadCdoTokenType,
|
|
@@ -37,6 +28,7 @@ async function doParse(iterator, options = {}) {
|
|
|
37
28
|
src: '',
|
|
38
29
|
sourcemap: false,
|
|
39
30
|
minify: true,
|
|
31
|
+
parseColor: true,
|
|
40
32
|
nestingRules: false,
|
|
41
33
|
resolveImport: false,
|
|
42
34
|
resolveUrls: false,
|
|
@@ -58,13 +50,19 @@ async function doParse(iterator, options = {}) {
|
|
|
58
50
|
const errors = [];
|
|
59
51
|
const src = options.src;
|
|
60
52
|
const stack = [];
|
|
53
|
+
const stats = {
|
|
54
|
+
bytesIn: 0,
|
|
55
|
+
importedBytesIn: 0,
|
|
56
|
+
parse: `0ms`,
|
|
57
|
+
minify: `0ms`,
|
|
58
|
+
total: `0ms`
|
|
59
|
+
};
|
|
61
60
|
let ast = {
|
|
62
61
|
typ: EnumToken.StyleSheetNodeType,
|
|
63
62
|
chi: []
|
|
64
63
|
};
|
|
65
64
|
let tokens = [];
|
|
66
65
|
let map = new Map;
|
|
67
|
-
let bytesIn = 0;
|
|
68
66
|
let context = ast;
|
|
69
67
|
if (options.sourcemap) {
|
|
70
68
|
ast.loc = {
|
|
@@ -76,315 +74,21 @@ async function doParse(iterator, options = {}) {
|
|
|
76
74
|
src: ''
|
|
77
75
|
};
|
|
78
76
|
}
|
|
79
|
-
async function parseNode(results) {
|
|
80
|
-
let tokens = results.map(mapToken);
|
|
81
|
-
let i;
|
|
82
|
-
let loc;
|
|
83
|
-
for (i = 0; i < tokens.length; i++) {
|
|
84
|
-
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
85
|
-
const position = map.get(tokens[i]);
|
|
86
|
-
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
|
|
87
|
-
errors.push({
|
|
88
|
-
action: 'drop',
|
|
89
|
-
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
90
|
-
location: { src, ...position }
|
|
91
|
-
});
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
loc = {
|
|
95
|
-
sta: position,
|
|
96
|
-
src
|
|
97
|
-
};
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
context.chi.push(tokens[i]);
|
|
100
|
-
if (options.sourcemap) {
|
|
101
|
-
tokens[i].loc = loc;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
tokens = tokens.slice(i);
|
|
109
|
-
if (tokens.length == 0) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
|
-
let delim = tokens.at(-1);
|
|
113
|
-
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
114
|
-
tokens.pop();
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
delim = { typ: EnumToken.SemiColonTokenType };
|
|
118
|
-
}
|
|
119
|
-
// @ts-ignore
|
|
120
|
-
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
121
|
-
tokens.pop();
|
|
122
|
-
}
|
|
123
|
-
if (tokens.length == 0) {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
127
|
-
const atRule = tokens.shift();
|
|
128
|
-
const position = map.get(atRule);
|
|
129
|
-
if (atRule.val == 'charset') {
|
|
130
|
-
if (position.ind > 0) {
|
|
131
|
-
errors.push({
|
|
132
|
-
action: 'drop',
|
|
133
|
-
message: 'doParse: invalid @charset',
|
|
134
|
-
location: { src, ...position }
|
|
135
|
-
});
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
if (options.removeCharset) {
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// @ts-ignore
|
|
143
|
-
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
144
|
-
tokens.shift();
|
|
145
|
-
}
|
|
146
|
-
if (atRule.val == 'import') {
|
|
147
|
-
// only @charset and @layer are accepted before @import
|
|
148
|
-
if (context.chi.length > 0) {
|
|
149
|
-
let i = context.chi.length;
|
|
150
|
-
while (i--) {
|
|
151
|
-
const type = context.chi[i].typ;
|
|
152
|
-
if (type == EnumToken.CommentNodeType) {
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
155
|
-
if (type != EnumToken.AtRuleNodeType) {
|
|
156
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
const name = context.chi[i].nam;
|
|
160
|
-
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
161
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// @ts-ignore
|
|
168
|
-
if (tokens[0]?.typ != EnumToken.StringTokenType && tokens[0]?.typ != EnumToken.UrlFunctionTokenType) {
|
|
169
|
-
errors.push({
|
|
170
|
-
action: 'drop',
|
|
171
|
-
message: 'doParse: invalid @import',
|
|
172
|
-
location: { src, ...position }
|
|
173
|
-
});
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
// @ts-ignore
|
|
177
|
-
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1]?.typ != EnumToken.UrlTokenTokenType && tokens[1]?.typ != EnumToken.StringTokenType) {
|
|
178
|
-
errors.push({
|
|
179
|
-
action: 'drop',
|
|
180
|
-
message: 'doParse: invalid @import',
|
|
181
|
-
location: { src, ...position }
|
|
182
|
-
});
|
|
183
|
-
return null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
if (atRule.val == 'import') {
|
|
187
|
-
// @ts-ignore
|
|
188
|
-
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1].typ == EnumToken.UrlTokenTokenType) {
|
|
189
|
-
tokens.shift();
|
|
190
|
-
// @ts-ignore
|
|
191
|
-
tokens[0].typ = EnumToken.StringTokenType;
|
|
192
|
-
// @ts-ignore
|
|
193
|
-
tokens[0].val = `"${tokens[0].val}"`;
|
|
194
|
-
}
|
|
195
|
-
// @ts-ignore
|
|
196
|
-
if (tokens[0].typ == EnumToken.StringTokenType) {
|
|
197
|
-
if (options.resolveImport) {
|
|
198
|
-
const url = tokens[0].val.slice(1, -1);
|
|
199
|
-
try {
|
|
200
|
-
// @ts-ignore
|
|
201
|
-
const root = await options.load(url, options.src).then((src) => {
|
|
202
|
-
return doParse(src, Object.assign({}, options, {
|
|
203
|
-
minify: false,
|
|
204
|
-
// @ts-ignore
|
|
205
|
-
src: options.resolve(url, options.src).absolute
|
|
206
|
-
}));
|
|
207
|
-
});
|
|
208
|
-
bytesIn += root.stats.bytesIn;
|
|
209
|
-
if (root.ast.chi.length > 0) {
|
|
210
|
-
// @todo - filter charset, layer and scope
|
|
211
|
-
context.chi.push(...root.ast.chi);
|
|
212
|
-
}
|
|
213
|
-
if (root.errors.length > 0) {
|
|
214
|
-
errors.push(...root.errors);
|
|
215
|
-
}
|
|
216
|
-
return null;
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
226
|
-
// allowed nesting at-rules
|
|
227
|
-
// there must be a top level rule in the stack
|
|
228
|
-
const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
|
|
229
|
-
acc.push(renderToken(curr, { removeComments: true }));
|
|
230
|
-
return acc;
|
|
231
|
-
}, []);
|
|
232
|
-
const node = {
|
|
233
|
-
typ: EnumToken.AtRuleNodeType,
|
|
234
|
-
nam: renderToken(atRule, { removeComments: true }),
|
|
235
|
-
val: raw.join('')
|
|
236
|
-
};
|
|
237
|
-
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
238
|
-
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
239
|
-
node.chi = [];
|
|
240
|
-
}
|
|
241
|
-
loc = {
|
|
242
|
-
sta: position,
|
|
243
|
-
src
|
|
244
|
-
};
|
|
245
|
-
if (options.sourcemap) {
|
|
246
|
-
node.loc = loc;
|
|
247
|
-
}
|
|
248
|
-
// @ts-ignore
|
|
249
|
-
context.chi.push(node);
|
|
250
|
-
return delim.typ == EnumToken.BlockStartTokenType ? node : null;
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
// rule
|
|
254
|
-
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
255
|
-
const position = map.get(tokens[0]);
|
|
256
|
-
const uniq = new Map;
|
|
257
|
-
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
258
|
-
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
259
|
-
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
260
|
-
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
261
|
-
combinators.includes(array[index - 1]?.val) ||
|
|
262
|
-
combinators.includes(array[index + 1]?.val)) {
|
|
263
|
-
return acc;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
let t = renderToken(curr, { minify: false });
|
|
267
|
-
if (t == ',') {
|
|
268
|
-
acc.push([]);
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
acc[acc.length - 1].push(t);
|
|
272
|
-
}
|
|
273
|
-
return acc;
|
|
274
|
-
}, [[]]).reduce((acc, curr) => {
|
|
275
|
-
acc.set(curr.join(''), curr);
|
|
276
|
-
return acc;
|
|
277
|
-
}, uniq);
|
|
278
|
-
const node = {
|
|
279
|
-
typ: EnumToken.RuleNodeType,
|
|
280
|
-
// @ts-ignore
|
|
281
|
-
sel: [...uniq.keys()].join(','),
|
|
282
|
-
chi: []
|
|
283
|
-
};
|
|
284
|
-
let raw = [...uniq.values()];
|
|
285
|
-
Object.defineProperty(node, 'raw', {
|
|
286
|
-
enumerable: false,
|
|
287
|
-
configurable: true,
|
|
288
|
-
writable: true,
|
|
289
|
-
value: raw
|
|
290
|
-
});
|
|
291
|
-
loc = {
|
|
292
|
-
sta: position,
|
|
293
|
-
src
|
|
294
|
-
};
|
|
295
|
-
if (options.sourcemap) {
|
|
296
|
-
node.loc = loc;
|
|
297
|
-
}
|
|
298
|
-
// @ts-ignore
|
|
299
|
-
context.chi.push(node);
|
|
300
|
-
return node;
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
// declaration
|
|
304
|
-
// @ts-ignore
|
|
305
|
-
let name = null;
|
|
306
|
-
// @ts-ignore
|
|
307
|
-
let value = null;
|
|
308
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
309
|
-
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
313
|
-
name = tokens.slice(0, i);
|
|
314
|
-
value = parseTokens(tokens.slice(i + 1), {
|
|
315
|
-
parseColor: true,
|
|
316
|
-
src: options.src,
|
|
317
|
-
resolveUrls: options.resolveUrls,
|
|
318
|
-
resolve: options.resolve,
|
|
319
|
-
cwd: options.cwd
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (name == null) {
|
|
324
|
-
name = tokens;
|
|
325
|
-
}
|
|
326
|
-
const position = map.get(name[0]);
|
|
327
|
-
if (name.length > 0) {
|
|
328
|
-
for (let i = 1; i < name.length; i++) {
|
|
329
|
-
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
330
|
-
errors.push({
|
|
331
|
-
action: 'drop',
|
|
332
|
-
message: 'doParse: invalid declaration',
|
|
333
|
-
location: { src, ...position }
|
|
334
|
-
});
|
|
335
|
-
return null;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
if (value == null || value.length == 0) {
|
|
340
|
-
errors.push({
|
|
341
|
-
action: 'drop',
|
|
342
|
-
message: 'doParse: invalid declaration',
|
|
343
|
-
location: { src, ...position }
|
|
344
|
-
});
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
const node = {
|
|
348
|
-
typ: EnumToken.DeclarationNodeType,
|
|
349
|
-
// @ts-ignore
|
|
350
|
-
nam: renderToken(name.shift(), { removeComments: true }),
|
|
351
|
-
// @ts-ignore
|
|
352
|
-
val: value
|
|
353
|
-
};
|
|
354
|
-
while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
355
|
-
node.val.shift();
|
|
356
|
-
}
|
|
357
|
-
if (node.val.length == 0) {
|
|
358
|
-
errors.push({
|
|
359
|
-
action: 'drop',
|
|
360
|
-
message: 'doParse: invalid declaration',
|
|
361
|
-
location: { src, ...position }
|
|
362
|
-
});
|
|
363
|
-
return null;
|
|
364
|
-
}
|
|
365
|
-
// @ts-ignore
|
|
366
|
-
context.chi.push(node);
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
function mapToken(token) {
|
|
372
|
-
const node = getTokenType(token.token, token.hint);
|
|
373
|
-
map.set(node, token.position);
|
|
374
|
-
return node;
|
|
375
|
-
}
|
|
376
77
|
const iter = tokenize(iterator);
|
|
377
78
|
let item;
|
|
378
79
|
while (item = iter.next().value) {
|
|
379
|
-
bytesIn = item.bytesIn;
|
|
80
|
+
stats.bytesIn = item.bytesIn;
|
|
81
|
+
//
|
|
380
82
|
// doParse error
|
|
381
83
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
382
84
|
// bad token
|
|
383
85
|
continue;
|
|
384
86
|
}
|
|
385
|
-
|
|
87
|
+
if (item.hint != EnumToken.EOFTokenType) {
|
|
88
|
+
tokens.push(item);
|
|
89
|
+
}
|
|
386
90
|
if (item.token == ';' || item.token == '{') {
|
|
387
|
-
let node = await parseNode(tokens);
|
|
91
|
+
let node = await parseNode(tokens, context, stats, options, errors, src, map);
|
|
388
92
|
if (node != null) {
|
|
389
93
|
stack.push(node);
|
|
390
94
|
// @ts-ignore
|
|
@@ -411,7 +115,7 @@ async function doParse(iterator, options = {}) {
|
|
|
411
115
|
map = new Map;
|
|
412
116
|
}
|
|
413
117
|
else if (item.token == '}') {
|
|
414
|
-
await parseNode(tokens);
|
|
118
|
+
await parseNode(tokens, context, stats, options, errors, src, map);
|
|
415
119
|
const previousNode = stack.pop();
|
|
416
120
|
// @ts-ignore
|
|
417
121
|
context = stack[stack.length - 1] || ast;
|
|
@@ -424,12 +128,12 @@ async function doParse(iterator, options = {}) {
|
|
|
424
128
|
}
|
|
425
129
|
}
|
|
426
130
|
if (tokens.length > 0) {
|
|
427
|
-
await parseNode(tokens);
|
|
131
|
+
await parseNode(tokens, context, stats, options, errors, src, map);
|
|
428
132
|
}
|
|
429
133
|
while (stack.length > 0 && context != ast) {
|
|
430
134
|
const previousNode = stack.pop();
|
|
431
135
|
// @ts-ignore
|
|
432
|
-
context = stack[stack.length - 1]
|
|
136
|
+
context = stack[stack.length - 1] ?? ast;
|
|
433
137
|
// @ts-ignore
|
|
434
138
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
435
139
|
context.chi.pop();
|
|
@@ -447,7 +151,7 @@ async function doParse(iterator, options = {}) {
|
|
|
447
151
|
// @ts-ignore
|
|
448
152
|
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
449
153
|
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
450
|
-
const results = callable(result.node);
|
|
154
|
+
const results = await callable(result.node);
|
|
451
155
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
452
156
|
continue;
|
|
453
157
|
}
|
|
@@ -455,7 +159,7 @@ async function doParse(iterator, options = {}) {
|
|
|
455
159
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
456
160
|
}
|
|
457
161
|
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
458
|
-
const results = options.visitor.Rule(result.node);
|
|
162
|
+
const results = await options.visitor.Rule(result.node);
|
|
459
163
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
460
164
|
continue;
|
|
461
165
|
}
|
|
@@ -467,7 +171,7 @@ async function doParse(iterator, options = {}) {
|
|
|
467
171
|
// @ts-ignore
|
|
468
172
|
(typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
|
|
469
173
|
const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
|
|
470
|
-
const results = callable(result.node);
|
|
174
|
+
const results = await callable(result.node);
|
|
471
175
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
472
176
|
continue;
|
|
473
177
|
}
|
|
@@ -485,11 +189,12 @@ async function doParse(iterator, options = {}) {
|
|
|
485
189
|
if (options.signal != null) {
|
|
486
190
|
options.signal.removeEventListener('abort', reject);
|
|
487
191
|
}
|
|
192
|
+
stats.bytesIn += stats.importedBytesIn;
|
|
488
193
|
resolve({
|
|
489
194
|
ast,
|
|
490
195
|
errors,
|
|
491
196
|
stats: {
|
|
492
|
-
|
|
197
|
+
...stats,
|
|
493
198
|
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
494
199
|
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
495
200
|
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
@@ -497,6 +202,295 @@ async function doParse(iterator, options = {}) {
|
|
|
497
202
|
});
|
|
498
203
|
});
|
|
499
204
|
}
|
|
205
|
+
async function parseNode(results, context, stats, options, errors, src, map) {
|
|
206
|
+
let tokens = results.map((t) => mapToken(t, map));
|
|
207
|
+
let i;
|
|
208
|
+
let loc;
|
|
209
|
+
for (i = 0; i < tokens.length; i++) {
|
|
210
|
+
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
211
|
+
const position = map.get(tokens[i]);
|
|
212
|
+
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
|
|
213
|
+
errors.push({
|
|
214
|
+
action: 'drop',
|
|
215
|
+
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
216
|
+
location: { src, ...position }
|
|
217
|
+
});
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
loc = {
|
|
221
|
+
sta: position,
|
|
222
|
+
src
|
|
223
|
+
};
|
|
224
|
+
// @ts-ignore
|
|
225
|
+
context.chi.push(tokens[i]);
|
|
226
|
+
if (options.sourcemap) {
|
|
227
|
+
tokens[i].loc = loc;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
tokens = tokens.slice(i);
|
|
235
|
+
if (tokens.length == 0) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
let delim = tokens.at(-1);
|
|
239
|
+
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
240
|
+
tokens.pop();
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
delim = { typ: EnumToken.SemiColonTokenType };
|
|
244
|
+
}
|
|
245
|
+
// @ts-ignore
|
|
246
|
+
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
247
|
+
tokens.pop();
|
|
248
|
+
}
|
|
249
|
+
if (tokens.length == 0) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
253
|
+
const atRule = tokens.shift();
|
|
254
|
+
const position = map.get(atRule);
|
|
255
|
+
if (atRule.val == 'charset') {
|
|
256
|
+
if (position.ind > 0) {
|
|
257
|
+
errors.push({
|
|
258
|
+
action: 'drop',
|
|
259
|
+
message: 'doParse: invalid @charset',
|
|
260
|
+
location: { src, ...position }
|
|
261
|
+
});
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
if (options.removeCharset) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// @ts-ignore
|
|
269
|
+
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
270
|
+
tokens.shift();
|
|
271
|
+
}
|
|
272
|
+
if (atRule.val == 'import') {
|
|
273
|
+
// only @charset and @layer are accepted before @import
|
|
274
|
+
if (context.chi.length > 0) {
|
|
275
|
+
let i = context.chi.length;
|
|
276
|
+
while (i--) {
|
|
277
|
+
const type = context.chi[i].typ;
|
|
278
|
+
if (type == EnumToken.CommentNodeType) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if (type != EnumToken.AtRuleNodeType) {
|
|
282
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
const name = context.chi[i].nam;
|
|
286
|
+
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
287
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// @ts-ignore
|
|
294
|
+
if (tokens[0]?.typ != EnumToken.StringTokenType && tokens[0]?.typ != EnumToken.UrlFunctionTokenType) {
|
|
295
|
+
errors.push({
|
|
296
|
+
action: 'drop',
|
|
297
|
+
message: 'doParse: invalid @import',
|
|
298
|
+
location: { src, ...position }
|
|
299
|
+
});
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
// @ts-ignore
|
|
303
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1]?.typ != EnumToken.UrlTokenTokenType && tokens[1]?.typ != EnumToken.StringTokenType) {
|
|
304
|
+
errors.push({
|
|
305
|
+
action: 'drop',
|
|
306
|
+
message: 'doParse: invalid @import',
|
|
307
|
+
location: { src, ...position }
|
|
308
|
+
});
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (atRule.val == 'import') {
|
|
313
|
+
// @ts-ignore
|
|
314
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1].typ == EnumToken.UrlTokenTokenType) {
|
|
315
|
+
tokens.shift();
|
|
316
|
+
// @ts-ignore
|
|
317
|
+
tokens[0].typ = EnumToken.StringTokenType;
|
|
318
|
+
// @ts-ignore
|
|
319
|
+
tokens[0].val = `"${tokens[0].val}"`;
|
|
320
|
+
}
|
|
321
|
+
// @ts-ignore
|
|
322
|
+
if (tokens[0].typ == EnumToken.StringTokenType) {
|
|
323
|
+
if (options.resolveImport) {
|
|
324
|
+
const url = tokens[0].val.slice(1, -1);
|
|
325
|
+
try {
|
|
326
|
+
// @ts-ignore
|
|
327
|
+
const root = await options.load(url, options.src).then((src) => {
|
|
328
|
+
return doParse(src, Object.assign({}, options, {
|
|
329
|
+
minify: false,
|
|
330
|
+
// @ts-ignore
|
|
331
|
+
src: options.resolve(url, options.src).absolute
|
|
332
|
+
}));
|
|
333
|
+
});
|
|
334
|
+
stats.importedBytesIn += root.stats.bytesIn;
|
|
335
|
+
if (root.ast.chi.length > 0) {
|
|
336
|
+
// @todo - filter charset, layer and scope
|
|
337
|
+
context.chi.push(...root.ast.chi);
|
|
338
|
+
}
|
|
339
|
+
if (root.errors.length > 0) {
|
|
340
|
+
errors.push(...root.errors);
|
|
341
|
+
}
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
// @ts-ignore
|
|
346
|
+
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
352
|
+
// allowed nesting at-rules
|
|
353
|
+
// there must be a top level rule in the stack
|
|
354
|
+
const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
|
|
355
|
+
acc.push(renderToken(curr, { removeComments: true }));
|
|
356
|
+
return acc;
|
|
357
|
+
}, []);
|
|
358
|
+
const node = {
|
|
359
|
+
typ: EnumToken.AtRuleNodeType,
|
|
360
|
+
nam: renderToken(atRule, { removeComments: true }),
|
|
361
|
+
val: raw.join('')
|
|
362
|
+
};
|
|
363
|
+
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
364
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
365
|
+
node.chi = [];
|
|
366
|
+
}
|
|
367
|
+
loc = {
|
|
368
|
+
sta: position,
|
|
369
|
+
src
|
|
370
|
+
};
|
|
371
|
+
if (options.sourcemap) {
|
|
372
|
+
node.loc = loc;
|
|
373
|
+
}
|
|
374
|
+
// @ts-ignore
|
|
375
|
+
context.chi.push(node);
|
|
376
|
+
return delim.typ == EnumToken.BlockStartTokenType ? node : null;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
// rule
|
|
380
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
381
|
+
const position = map.get(tokens[0]);
|
|
382
|
+
const uniq = new Map;
|
|
383
|
+
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
384
|
+
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
385
|
+
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
386
|
+
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
387
|
+
combinators.includes(array[index - 1]?.val) ||
|
|
388
|
+
combinators.includes(array[index + 1]?.val)) {
|
|
389
|
+
return acc;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
let t = renderToken(curr, { minify: false });
|
|
393
|
+
if (t == ',') {
|
|
394
|
+
acc.push([]);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
acc[acc.length - 1].push(t);
|
|
398
|
+
}
|
|
399
|
+
return acc;
|
|
400
|
+
}, [[]]).reduce((acc, curr) => {
|
|
401
|
+
acc.set(curr.join(''), curr);
|
|
402
|
+
return acc;
|
|
403
|
+
}, uniq);
|
|
404
|
+
const node = {
|
|
405
|
+
typ: EnumToken.RuleNodeType,
|
|
406
|
+
// @ts-ignore
|
|
407
|
+
sel: [...uniq.keys()].join(','),
|
|
408
|
+
chi: []
|
|
409
|
+
};
|
|
410
|
+
let raw = [...uniq.values()];
|
|
411
|
+
Object.defineProperty(node, 'raw', {
|
|
412
|
+
enumerable: false,
|
|
413
|
+
configurable: true,
|
|
414
|
+
writable: true,
|
|
415
|
+
value: raw
|
|
416
|
+
});
|
|
417
|
+
loc = {
|
|
418
|
+
sta: position,
|
|
419
|
+
src
|
|
420
|
+
};
|
|
421
|
+
if (options.sourcemap) {
|
|
422
|
+
node.loc = loc;
|
|
423
|
+
}
|
|
424
|
+
// @ts-ignore
|
|
425
|
+
context.chi.push(node);
|
|
426
|
+
return node;
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
// declaration
|
|
430
|
+
// @ts-ignore
|
|
431
|
+
let name = null;
|
|
432
|
+
// @ts-ignore
|
|
433
|
+
let value = null;
|
|
434
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
435
|
+
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
439
|
+
name = tokens.slice(0, i);
|
|
440
|
+
value = parseTokens(tokens.slice(i + 1), {
|
|
441
|
+
parseColor: options.parseColor,
|
|
442
|
+
src: options.src,
|
|
443
|
+
resolveUrls: options.resolveUrls,
|
|
444
|
+
resolve: options.resolve,
|
|
445
|
+
cwd: options.cwd
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
if (name == null) {
|
|
450
|
+
name = tokens;
|
|
451
|
+
}
|
|
452
|
+
const position = map.get(name[0]);
|
|
453
|
+
if (name.length > 0) {
|
|
454
|
+
for (let i = 1; i < name.length; i++) {
|
|
455
|
+
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
456
|
+
errors.push({
|
|
457
|
+
action: 'drop',
|
|
458
|
+
message: 'doParse: invalid declaration',
|
|
459
|
+
location: { src, ...position }
|
|
460
|
+
});
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (value == null || value.length == 0) {
|
|
466
|
+
errors.push({
|
|
467
|
+
action: 'drop',
|
|
468
|
+
message: 'doParse: invalid declaration',
|
|
469
|
+
location: { src, ...position }
|
|
470
|
+
});
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
const node = {
|
|
474
|
+
typ: EnumToken.DeclarationNodeType,
|
|
475
|
+
// @ts-ignore
|
|
476
|
+
nam: renderToken(name.shift(), { removeComments: true }),
|
|
477
|
+
// @ts-ignore
|
|
478
|
+
val: value
|
|
479
|
+
};
|
|
480
|
+
const result = parseDeclaration(node, errors, src, position);
|
|
481
|
+
if (result != null) {
|
|
482
|
+
// @ts-ignore
|
|
483
|
+
context.chi.push(node);
|
|
484
|
+
}
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function mapToken(token, map) {
|
|
490
|
+
const node = getTokenType(token.token, token.hint);
|
|
491
|
+
map.set(node, token.position);
|
|
492
|
+
return node;
|
|
493
|
+
}
|
|
500
494
|
function parseString(src, options = { location: false }) {
|
|
501
495
|
return parseTokens([...tokenize(src)].map(t => {
|
|
502
496
|
const token = getTokenType(t.token, t.hint);
|
|
@@ -620,15 +614,21 @@ function getTokenType(val, hint) {
|
|
|
620
614
|
val
|
|
621
615
|
};
|
|
622
616
|
}
|
|
623
|
-
if (isDimension(val)) {
|
|
624
|
-
return parseDimension(val);
|
|
625
|
-
}
|
|
626
617
|
if (isPercentage(val)) {
|
|
627
618
|
return {
|
|
628
619
|
typ: EnumToken.PercentageTokenType,
|
|
629
620
|
val: val.slice(0, -1)
|
|
630
621
|
};
|
|
631
622
|
}
|
|
623
|
+
if (isFlex(val)) {
|
|
624
|
+
return {
|
|
625
|
+
typ: EnumToken.FlexTokenType,
|
|
626
|
+
val: val.slice(0, -2)
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
if (isDimension(val)) {
|
|
630
|
+
return parseDimension(val);
|
|
631
|
+
}
|
|
632
632
|
const v = val.toLowerCase();
|
|
633
633
|
if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
|
|
634
634
|
return {
|
|
@@ -728,15 +728,6 @@ function parseTokens(tokens, options = {}) {
|
|
|
728
728
|
// @ts-ignore
|
|
729
729
|
parseTokens(t.chi, t.typ);
|
|
730
730
|
}
|
|
731
|
-
// @ts-ignore
|
|
732
|
-
// t.chi.forEach(val => {
|
|
733
|
-
// if (val.typ == EnumToken.StringTokenType) {
|
|
734
|
-
// const slice = val.val.slice(1, -1);
|
|
735
|
-
// if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
736
|
-
// Object.assign(val, {typ: EnumToken.IdenTokenType, val: slice});
|
|
737
|
-
// }
|
|
738
|
-
// }
|
|
739
|
-
// });
|
|
740
731
|
let m = t.chi.length;
|
|
741
732
|
let val;
|
|
742
733
|
for (m = 0; m < t.chi.length; m++) {
|
|
@@ -871,6 +862,11 @@ function parseTokens(tokens, options = {}) {
|
|
|
871
862
|
// @ts-ignore
|
|
872
863
|
t.chi.pop();
|
|
873
864
|
}
|
|
865
|
+
// @ts-ignore
|
|
866
|
+
if (t.chi.length > 0) {
|
|
867
|
+
// @ts-ignore
|
|
868
|
+
parseTokens(t.chi, options);
|
|
869
|
+
}
|
|
874
870
|
if (t.typ == EnumToken.FunctionTokenType && t.val == 'calc') {
|
|
875
871
|
for (const { value, parent } of walkValues(t.chi)) {
|
|
876
872
|
if (value.typ == EnumToken.WhitespaceTokenType) {
|
|
@@ -893,35 +889,37 @@ function parseTokens(tokens, options = {}) {
|
|
|
893
889
|
}
|
|
894
890
|
}
|
|
895
891
|
}
|
|
892
|
+
else if (t.typ == EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
|
|
893
|
+
// @ts-ignore
|
|
894
|
+
t.typ = EnumToken.GridTemplateFuncTokenType;
|
|
895
|
+
}
|
|
896
896
|
else if (t.typ == EnumToken.StartParensTokenType) {
|
|
897
897
|
// @ts-ignore
|
|
898
898
|
t.typ = EnumToken.ParensTokenType;
|
|
899
899
|
}
|
|
900
900
|
// @ts-ignore
|
|
901
901
|
if (options.parseColor && t.typ == EnumToken.FunctionTokenType && isColor(t)) {
|
|
902
|
-
// if (isColor) {
|
|
903
902
|
// @ts-ignore
|
|
904
903
|
t.typ = EnumToken.ColorTokenType;
|
|
905
904
|
// @ts-ignore
|
|
906
905
|
t.kin = t.val;
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
906
|
+
if (t.chi[0].typ == EnumToken.IdenTokenType) {
|
|
907
|
+
if (t.chi[0].val == 'from') {
|
|
908
|
+
// @ts-ignore
|
|
909
|
+
t.cal = 'rel';
|
|
910
|
+
}
|
|
910
911
|
// @ts-ignore
|
|
911
|
-
if (
|
|
912
|
+
else if (t.val == 'color-mix' && t.chi[0].val == 'in') {
|
|
912
913
|
// @ts-ignore
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
}
|
|
914
|
+
t.cal = 'mix';
|
|
915
|
+
}
|
|
916
|
+
else if (t.val == 'color') {
|
|
917
917
|
// @ts-ignore
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
t.chi.splice(m - 1, 1);
|
|
921
|
-
m--;
|
|
922
|
-
}
|
|
918
|
+
t.cal = 'col';
|
|
919
|
+
// t.chi = t.chi.filter((t: Token) => [EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.PercentageTokenType].includes(t.typ));
|
|
923
920
|
}
|
|
924
921
|
}
|
|
922
|
+
t.chi = t.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommaTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
925
923
|
continue;
|
|
926
924
|
}
|
|
927
925
|
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
@@ -946,8 +944,6 @@ function parseTokens(tokens, options = {}) {
|
|
|
946
944
|
}
|
|
947
945
|
// @ts-ignore
|
|
948
946
|
if (t.chi.length > 0) {
|
|
949
|
-
// @ts-ignore
|
|
950
|
-
parseTokens(t.chi, options);
|
|
951
947
|
if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
|
|
952
948
|
//
|
|
953
949
|
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
|