@tbela99/css-parser 0.8.0 → 0.9.1
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/.editorconfig +484 -0
- package/README.md +13 -8
- package/dist/index-umd-web.js +2451 -2554
- package/dist/index.cjs +2605 -2708
- package/dist/index.d.ts +73 -23
- package/dist/lib/ast/expand.js +29 -4
- package/dist/lib/ast/math/expression.js +1 -1
- package/dist/lib/ast/minify.js +31 -17
- package/dist/lib/ast/types.js +2 -0
- package/dist/lib/ast/walk.js +12 -0
- package/dist/lib/parser/declaration/map.js +59 -52
- package/dist/lib/parser/declaration/set.js +0 -12
- package/dist/lib/parser/parse.js +204 -139
- package/dist/lib/parser/tokenize.js +15 -3
- package/dist/lib/renderer/color/color.js +2 -2
- package/dist/lib/renderer/color/hex.js +1 -1
- package/dist/lib/renderer/color/hsl.js +1 -1
- package/dist/lib/renderer/color/hwb.js +2 -2
- package/dist/lib/renderer/color/lab.js +3 -2
- package/dist/lib/renderer/color/lch.js +1 -1
- package/dist/lib/renderer/color/oklab.js +2 -2
- package/dist/lib/renderer/color/oklch.js +1 -1
- package/dist/lib/renderer/color/p3.js +1 -1
- package/dist/lib/renderer/color/prophotoRgb.js +2 -2
- package/dist/lib/renderer/color/prophotorgb.js +2 -2
- package/dist/lib/renderer/color/rgb.js +1 -1
- package/dist/lib/renderer/color/srgb.js +2 -2
- package/dist/lib/renderer/color/utils/constants.js +1 -1
- package/dist/lib/renderer/color/xyz.js +2 -18
- package/dist/lib/renderer/color/xyzd50.js +20 -2
- package/dist/lib/renderer/render.js +37 -8
- package/dist/lib/renderer/sourcemap/sourcemap.js +1 -1
- package/dist/lib/syntax/syntax.js +337 -1
- package/dist/lib/validation/at-rules/container.js +353 -0
- package/dist/lib/validation/at-rules/counter-style.js +2 -2
- package/dist/lib/validation/at-rules/custom-media.js +52 -0
- package/dist/lib/validation/at-rules/document.js +40 -60
- package/dist/lib/validation/at-rules/else.js +5 -0
- package/dist/lib/validation/at-rules/font-feature-values.js +3 -0
- package/dist/lib/validation/at-rules/import.js +64 -59
- package/dist/lib/validation/at-rules/layer.js +3 -0
- package/dist/lib/validation/at-rules/media.js +118 -29
- package/dist/lib/validation/at-rules/supports.js +51 -20
- package/dist/lib/validation/at-rules/when.js +178 -0
- package/dist/lib/validation/atrule.js +25 -10
- package/dist/lib/validation/config.js +20 -15
- package/dist/lib/validation/config.json.js +242 -74
- package/dist/lib/validation/declaration.js +32 -10
- package/dist/lib/validation/parser/parse.js +87 -103
- package/dist/lib/validation/parser/types.js +2 -2
- package/dist/lib/validation/selector.js +6 -3
- package/dist/lib/validation/syntax.js +86 -6
- package/dist/lib/validation/syntaxes/complex-selector-list.js +16 -12
- package/dist/lib/validation/syntaxes/complex-selector.js +17 -247
- package/dist/lib/validation/syntaxes/compound-selector.js +226 -0
- package/dist/lib/validation/syntaxes/image.js +29 -0
- package/dist/lib/validation/syntaxes/keyframe-block-list.js +1 -1
- package/dist/lib/validation/syntaxes/keyframe-selector.js +1 -1
- package/dist/lib/validation/syntaxes/layer-name.js +5 -16
- package/dist/lib/validation/syntaxes/relative-selector-list.js +43 -13
- package/dist/lib/validation/utils/list.js +2 -2
- package/dist/node/index.js +1 -1
- package/dist/web/index.js +1 -1
- package/package.json +10 -9
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { webkitPseudoAliasMap, isIdentStart, isIdent, mathFuncs, isColor, isHexColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isHash, mediaTypes } from '../syntax/syntax.js';
|
|
2
2
|
import './utils/config.js';
|
|
3
3
|
import { EnumToken, funcLike, ValidationLevel } from '../ast/types.js';
|
|
4
4
|
import { minify, definedPropertySettings, combinators } from '../ast/minify.js';
|
|
@@ -13,6 +13,7 @@ import '../validation/parser/types.js';
|
|
|
13
13
|
import '../validation/parser/parse.js';
|
|
14
14
|
import { validateSelector } from '../validation/selector.js';
|
|
15
15
|
import { validateAtRule } from '../validation/atrule.js';
|
|
16
|
+
import '../validation/syntaxes/complex-selector.js';
|
|
16
17
|
|
|
17
18
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
18
19
|
const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
|
|
@@ -29,51 +30,14 @@ const enumTokenHints = new Set([
|
|
|
29
30
|
EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DashMatchTokenType, EnumToken.ContainMatchTokenType,
|
|
30
31
|
EnumToken.EOFTokenType
|
|
31
32
|
]);
|
|
32
|
-
const webkitPseudoAliasMap = {
|
|
33
|
-
'-webkit-autofill': 'autofill',
|
|
34
|
-
'-webkit-any': 'is',
|
|
35
|
-
'-moz-any': 'is',
|
|
36
|
-
'-webkit-border-after': 'border-block-end',
|
|
37
|
-
'-webkit-border-after-color': 'border-block-end-color',
|
|
38
|
-
'-webkit-border-after-style': 'border-block-end-style',
|
|
39
|
-
'-webkit-border-after-width': 'border-block-end-width',
|
|
40
|
-
'-webkit-border-before': 'border-block-start',
|
|
41
|
-
'-webkit-border-before-color': 'border-block-start-color',
|
|
42
|
-
'-webkit-border-before-style': 'border-block-start-style',
|
|
43
|
-
'-webkit-border-before-width': 'border-block-start-width',
|
|
44
|
-
'-webkit-border-end': 'border-inline-end',
|
|
45
|
-
'-webkit-border-end-color': 'border-inline-end-color',
|
|
46
|
-
'-webkit-border-end-style': 'border-inline-end-style',
|
|
47
|
-
'-webkit-border-end-width': 'border-inline-end-width',
|
|
48
|
-
'-webkit-border-start': 'border-inline-start',
|
|
49
|
-
'-webkit-border-start-color': 'border-inline-start-color',
|
|
50
|
-
'-webkit-border-start-style': 'border-inline-start-style',
|
|
51
|
-
'-webkit-border-start-width': 'border-inline-start-width',
|
|
52
|
-
'-webkit-box-align': 'align-items',
|
|
53
|
-
'-webkit-box-direction': 'flex-direction',
|
|
54
|
-
'-webkit-box-flex': 'flex-grow',
|
|
55
|
-
'-webkit-box-lines': 'flex-flow',
|
|
56
|
-
'-webkit-box-ordinal-group': 'order',
|
|
57
|
-
'-webkit-box-orient': 'flex-direction',
|
|
58
|
-
'-webkit-box-pack': 'justify-content',
|
|
59
|
-
'-webkit-column-break-after': 'break-after',
|
|
60
|
-
'-webkit-column-break-before': 'break-before',
|
|
61
|
-
'-webkit-column-break-inside': 'break-inside',
|
|
62
|
-
'-webkit-font-feature-settings': 'font-feature-settings',
|
|
63
|
-
'-webkit-hyphenate-character': 'hyphenate-character',
|
|
64
|
-
'-webkit-initial-letter': 'initial-letter',
|
|
65
|
-
'-webkit-margin-end': 'margin-block-end',
|
|
66
|
-
'-webkit-margin-start': 'margin-block-start',
|
|
67
|
-
'-webkit-padding-after': 'padding-block-end',
|
|
68
|
-
'-webkit-padding-before': 'padding-block-start',
|
|
69
|
-
'-webkit-padding-end': 'padding-inline-end',
|
|
70
|
-
'-webkit-padding-start': 'padding-inline-start',
|
|
71
|
-
'-webkit-min-device-pixel-ratio': 'min-resolution',
|
|
72
|
-
'-webkit-max-device-pixel-ratio': 'max-resolution'
|
|
73
|
-
};
|
|
74
33
|
function reject(reason) {
|
|
75
34
|
throw new Error(reason ?? 'Parsing aborted');
|
|
76
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* parse css string
|
|
38
|
+
* @param iterator
|
|
39
|
+
* @param options
|
|
40
|
+
*/
|
|
77
41
|
async function doParse(iterator, options = {}) {
|
|
78
42
|
if (options.signal != null) {
|
|
79
43
|
options.signal.addEventListener('abort', reject);
|
|
@@ -82,6 +46,7 @@ async function doParse(iterator, options = {}) {
|
|
|
82
46
|
src: '',
|
|
83
47
|
sourcemap: false,
|
|
84
48
|
minify: true,
|
|
49
|
+
pass: 1,
|
|
85
50
|
parseColor: true,
|
|
86
51
|
nestingRules: false,
|
|
87
52
|
resolveImport: false,
|
|
@@ -95,6 +60,7 @@ async function doParse(iterator, options = {}) {
|
|
|
95
60
|
setParent: true,
|
|
96
61
|
removePrefix: false,
|
|
97
62
|
validation: true,
|
|
63
|
+
lenient: true,
|
|
98
64
|
...options
|
|
99
65
|
};
|
|
100
66
|
if (options.expandNestingRules) {
|
|
@@ -133,9 +99,10 @@ async function doParse(iterator, options = {}) {
|
|
|
133
99
|
}
|
|
134
100
|
const iter = tokenize(iterator);
|
|
135
101
|
let item;
|
|
102
|
+
const rawTokens = [];
|
|
136
103
|
while (item = iter.next().value) {
|
|
137
104
|
stats.bytesIn = item.bytesIn;
|
|
138
|
-
|
|
105
|
+
rawTokens.push(item);
|
|
139
106
|
// doParse error
|
|
140
107
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
141
108
|
// bad token
|
|
@@ -145,7 +112,8 @@ async function doParse(iterator, options = {}) {
|
|
|
145
112
|
tokens.push(item);
|
|
146
113
|
}
|
|
147
114
|
if (item.token == ';' || item.token == '{') {
|
|
148
|
-
let node = await parseNode(tokens, context, stats, options, errors, src, map);
|
|
115
|
+
let node = await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
116
|
+
rawTokens.length = 0;
|
|
149
117
|
if (node != null) {
|
|
150
118
|
// @ts-ignore
|
|
151
119
|
stack.push(node);
|
|
@@ -171,7 +139,8 @@ async function doParse(iterator, options = {}) {
|
|
|
171
139
|
map = new Map;
|
|
172
140
|
}
|
|
173
141
|
else if (item.token == '}') {
|
|
174
|
-
await parseNode(tokens, context, stats, options, errors, src, map);
|
|
142
|
+
await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
143
|
+
rawTokens.length = 0;
|
|
175
144
|
const previousNode = stack.pop();
|
|
176
145
|
// @ts-ignore
|
|
177
146
|
context = stack[stack.length - 1] ?? ast;
|
|
@@ -194,9 +163,10 @@ async function doParse(iterator, options = {}) {
|
|
|
194
163
|
}
|
|
195
164
|
}
|
|
196
165
|
if (tokens.length > 0) {
|
|
197
|
-
await parseNode(tokens, context, stats, options, errors, src, map);
|
|
166
|
+
await parseNode(tokens, context, stats, options, errors, src, map, rawTokens);
|
|
167
|
+
rawTokens.length = 0;
|
|
198
168
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
199
|
-
const index = context.chi.findIndex(node => node == context);
|
|
169
|
+
const index = context.chi.findIndex((node) => node == context);
|
|
200
170
|
if (index > -1) {
|
|
201
171
|
context.chi.splice(index, 1);
|
|
202
172
|
}
|
|
@@ -206,6 +176,7 @@ async function doParse(iterator, options = {}) {
|
|
|
206
176
|
const previousNode = stack.pop();
|
|
207
177
|
// @ts-ignore
|
|
208
178
|
context = stack[stack.length - 1] ?? ast;
|
|
179
|
+
// remove empty nodes
|
|
209
180
|
// @ts-ignore
|
|
210
181
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
211
182
|
// @ts-ignore
|
|
@@ -255,36 +226,12 @@ async function doParse(iterator, options = {}) {
|
|
|
255
226
|
}
|
|
256
227
|
if (options.minify) {
|
|
257
228
|
if (ast.chi.length > 0) {
|
|
258
|
-
|
|
229
|
+
let passes = options.pass ?? 1;
|
|
230
|
+
while (passes--) {
|
|
231
|
+
minify(ast, options, true, errors, false);
|
|
232
|
+
}
|
|
259
233
|
}
|
|
260
234
|
}
|
|
261
|
-
// if (options.setParent) {
|
|
262
|
-
//
|
|
263
|
-
// const nodes: Array<AstRule | AstAtRule | AstRuleStyleSheet> = [ast];
|
|
264
|
-
// let node: AstNode;
|
|
265
|
-
//
|
|
266
|
-
// while ((node = nodes.shift()!)) {
|
|
267
|
-
//
|
|
268
|
-
// // @ts-ignore
|
|
269
|
-
// if (node.chi.length > 0) {
|
|
270
|
-
//
|
|
271
|
-
// // @ts-ignore
|
|
272
|
-
// for (const child of node.chi) {
|
|
273
|
-
//
|
|
274
|
-
// if (child.parent != node) {
|
|
275
|
-
//
|
|
276
|
-
// Object.defineProperty(child, 'parent', {...definedPropertySettings, value: node});
|
|
277
|
-
// }
|
|
278
|
-
//
|
|
279
|
-
// if ('chi' in child && child.chi.length > 0) {
|
|
280
|
-
//
|
|
281
|
-
// // @ts-ignore
|
|
282
|
-
// nodes.push(<AstRule | AstAtRule>child);
|
|
283
|
-
// }
|
|
284
|
-
// }
|
|
285
|
-
// }
|
|
286
|
-
// }
|
|
287
|
-
// }
|
|
288
235
|
const endTime = performance.now();
|
|
289
236
|
if (options.signal != null) {
|
|
290
237
|
options.signal.removeEventListener('abort', reject);
|
|
@@ -301,7 +248,17 @@ async function doParse(iterator, options = {}) {
|
|
|
301
248
|
}
|
|
302
249
|
};
|
|
303
250
|
}
|
|
304
|
-
|
|
251
|
+
function getLastNode(context) {
|
|
252
|
+
let i = context.chi.length;
|
|
253
|
+
while (i--) {
|
|
254
|
+
if ([EnumToken.CommentTokenType, EnumToken.CDOCOMMTokenType, EnumToken.WhitespaceTokenType].includes(context.chi[i].typ)) {
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
return context.chi[i];
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
async function parseNode(results, context, stats, options, errors, src, map, rawTokens) {
|
|
305
262
|
let tokens = [];
|
|
306
263
|
for (const t of results) {
|
|
307
264
|
const node = getTokenType(t.token, t.hint);
|
|
@@ -356,24 +313,6 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
356
313
|
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
357
314
|
const atRule = tokens.shift();
|
|
358
315
|
const position = map.get(atRule);
|
|
359
|
-
// if (atRule.val == 'charset') {
|
|
360
|
-
//
|
|
361
|
-
// if (context.typ != EnumToken.StyleSheetNodeType || context.chi.some(t => t.typ != EnumToken.CDOCOMMTokenType && t.typ != EnumToken.CommentNodeType)) {
|
|
362
|
-
//
|
|
363
|
-
// errors.push({
|
|
364
|
-
// action: 'drop',
|
|
365
|
-
// message: 'doParse: invalid @charset',
|
|
366
|
-
// location: {src, ...position}
|
|
367
|
-
// });
|
|
368
|
-
//
|
|
369
|
-
// return null;
|
|
370
|
-
// }
|
|
371
|
-
//
|
|
372
|
-
// if (options.removeCharset) {
|
|
373
|
-
//
|
|
374
|
-
// return null;
|
|
375
|
-
// }
|
|
376
|
-
// }
|
|
377
316
|
// @ts-ignore
|
|
378
317
|
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
379
318
|
tokens.shift();
|
|
@@ -391,8 +330,13 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
391
330
|
continue;
|
|
392
331
|
}
|
|
393
332
|
if (type != EnumToken.AtRuleNodeType) {
|
|
394
|
-
|
|
395
|
-
|
|
333
|
+
// @ts-ignore
|
|
334
|
+
if (!(type == EnumToken.InvalidAtRuleTokenType &&
|
|
335
|
+
// @ts-ignore
|
|
336
|
+
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
337
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
396
340
|
}
|
|
397
341
|
// @ts-ignore
|
|
398
342
|
const name = context.chi[i].nam;
|
|
@@ -427,12 +371,20 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
427
371
|
if (tokens[0].typ == EnumToken.UrlFunctionTokenType) {
|
|
428
372
|
if (tokens[1].typ == EnumToken.UrlTokenTokenType || tokens[1].typ == EnumToken.StringTokenType) {
|
|
429
373
|
tokens.shift();
|
|
430
|
-
if (tokens[
|
|
374
|
+
if (tokens[0]?.typ == EnumToken.UrlTokenTokenType) {
|
|
431
375
|
// @ts-ignore
|
|
432
376
|
tokens[0].typ = EnumToken.StringTokenType;
|
|
433
377
|
// @ts-ignore
|
|
434
378
|
tokens[0].val = `"${tokens[0].val}"`;
|
|
435
379
|
}
|
|
380
|
+
// @ts-ignore
|
|
381
|
+
while (tokens[1]?.typ == EnumToken.WhitespaceTokenType || tokens[1]?.typ == EnumToken.CommentTokenType) {
|
|
382
|
+
tokens.splice(1, 1);
|
|
383
|
+
}
|
|
384
|
+
// @ts-ignore
|
|
385
|
+
if (tokens[1]?.typ == EnumToken.EndParensTokenType) {
|
|
386
|
+
tokens.splice(1, 1);
|
|
387
|
+
}
|
|
436
388
|
}
|
|
437
389
|
}
|
|
438
390
|
// @ts-ignore
|
|
@@ -470,8 +422,43 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
470
422
|
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
471
423
|
// allowed nesting at-rules
|
|
472
424
|
// there must be a top level rule in the stack
|
|
473
|
-
if (atRule.val == 'charset'
|
|
474
|
-
|
|
425
|
+
if (atRule.val == 'charset') {
|
|
426
|
+
let spaces = 0;
|
|
427
|
+
// https://developer.mozilla.org/en-US/docs/Web/CSS/@charset
|
|
428
|
+
for (let k = 1; k < rawTokens.length; k++) {
|
|
429
|
+
if (rawTokens[k].hint == EnumToken.WhitespaceTokenType) {
|
|
430
|
+
spaces += rawTokens[k].len;
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
if (rawTokens[k].hint == EnumToken.CommentTokenType) {
|
|
434
|
+
continue;
|
|
435
|
+
}
|
|
436
|
+
if (rawTokens[k].hint == EnumToken.CDOCOMMTokenType) {
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
if (spaces > 1) {
|
|
440
|
+
errors.push({
|
|
441
|
+
action: 'drop',
|
|
442
|
+
message: '@charset must have only one space',
|
|
443
|
+
// @ts-ignore
|
|
444
|
+
location: { src, ...(map.get(atRule) ?? position) }
|
|
445
|
+
});
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
if (rawTokens[k].hint != EnumToken.StringTokenType || rawTokens[k].token[0] != '"') {
|
|
449
|
+
errors.push({
|
|
450
|
+
action: 'drop',
|
|
451
|
+
message: '@charset expects a "<charset>"',
|
|
452
|
+
// @ts-ignore
|
|
453
|
+
location: { src, ...(map.get(atRule) ?? position) }
|
|
454
|
+
});
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
if (options.removeCharset) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
475
462
|
}
|
|
476
463
|
const t = parseAtRulePrelude(parseTokens(tokens, { minify: options.minify }), atRule);
|
|
477
464
|
const raw = t.reduce((acc, curr) => {
|
|
@@ -481,11 +468,11 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
481
468
|
const node = {
|
|
482
469
|
typ: EnumToken.AtRuleNodeType,
|
|
483
470
|
nam: renderToken(atRule, { removeComments: true }),
|
|
484
|
-
tokens: t,
|
|
471
|
+
// tokens: t,
|
|
485
472
|
val: raw.join('')
|
|
486
473
|
};
|
|
487
474
|
Object.defineProperties(node, {
|
|
488
|
-
tokens: { ...definedPropertySettings, enumerable:
|
|
475
|
+
tokens: { ...definedPropertySettings, enumerable: false, value: tokens.slice() },
|
|
489
476
|
raw: { ...definedPropertySettings, value: raw }
|
|
490
477
|
});
|
|
491
478
|
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
@@ -499,11 +486,36 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
499
486
|
node.loc = loc;
|
|
500
487
|
}
|
|
501
488
|
if (options.validation) {
|
|
502
|
-
|
|
489
|
+
let isValid = true;
|
|
490
|
+
if (node.nam == 'else') {
|
|
491
|
+
const prev = getLastNode(context);
|
|
492
|
+
if (prev != null && prev.typ == EnumToken.AtRuleNodeType && ['when', 'else'].includes(prev.nam)) {
|
|
493
|
+
if (prev.nam == 'else') {
|
|
494
|
+
isValid = Array.isArray(prev.tokens) && prev.tokens.length > 0;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
isValid = false;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const valid = isValid ? validateAtRule(node, options, context) : {
|
|
502
|
+
valid: ValidationLevel.Drop,
|
|
503
|
+
node,
|
|
504
|
+
syntax: '@' + node.nam,
|
|
505
|
+
error: '@' + node.nam + ' not allowed here'};
|
|
503
506
|
if (valid.valid == ValidationLevel.Drop) {
|
|
507
|
+
errors.push({
|
|
508
|
+
action: 'drop',
|
|
509
|
+
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
510
|
+
// @ts-ignore
|
|
511
|
+
location: { src, ...(map.get(valid.node) ?? position) }
|
|
512
|
+
});
|
|
504
513
|
// @ts-ignore
|
|
505
514
|
node.typ = EnumToken.InvalidAtRuleTokenType;
|
|
506
515
|
}
|
|
516
|
+
else {
|
|
517
|
+
node.val = node.tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false, removeComments: true }), '');
|
|
518
|
+
}
|
|
507
519
|
}
|
|
508
520
|
// @ts-ignore
|
|
509
521
|
context.chi.push(node);
|
|
@@ -585,7 +597,7 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
585
597
|
};
|
|
586
598
|
Object.defineProperty(node, 'tokens', {
|
|
587
599
|
...definedPropertySettings,
|
|
588
|
-
enumerable:
|
|
600
|
+
enumerable: false,
|
|
589
601
|
value: tokens.slice()
|
|
590
602
|
});
|
|
591
603
|
let raw = [...uniq.values()];
|
|
@@ -682,7 +694,24 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
682
694
|
};
|
|
683
695
|
const result = parseDeclarationNode(node, errors, src, position);
|
|
684
696
|
if (result != null) {
|
|
685
|
-
if (options.validation)
|
|
697
|
+
// if (options.validation) {
|
|
698
|
+
//
|
|
699
|
+
// const valid: ValidationResult = validateDeclaration(result, options, context);
|
|
700
|
+
//
|
|
701
|
+
// // console.error({valid});
|
|
702
|
+
//
|
|
703
|
+
// if (valid.valid == ValidationLevel.Drop) {
|
|
704
|
+
//
|
|
705
|
+
// errors.push({
|
|
706
|
+
// action: 'drop',
|
|
707
|
+
// message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, {minify: false}), '') + '"',
|
|
708
|
+
// // @ts-ignore
|
|
709
|
+
// location: {src, ...(map.get(valid.node) ?? position)}
|
|
710
|
+
// });
|
|
711
|
+
//
|
|
712
|
+
// return null;
|
|
713
|
+
// }
|
|
714
|
+
// }
|
|
686
715
|
// @ts-ignore
|
|
687
716
|
context.chi.push(result);
|
|
688
717
|
Object.defineProperty(result, 'parent', { ...definedPropertySettings, value: context });
|
|
@@ -691,6 +720,11 @@ async function parseNode(results, context, stats, options, errors, src, map) {
|
|
|
691
720
|
}
|
|
692
721
|
}
|
|
693
722
|
}
|
|
723
|
+
/**
|
|
724
|
+
* parse at-rule prelude
|
|
725
|
+
* @param tokens
|
|
726
|
+
* @param atRule
|
|
727
|
+
*/
|
|
694
728
|
function parseAtRulePrelude(tokens, atRule) {
|
|
695
729
|
// @ts-ignore
|
|
696
730
|
for (const { value, parent } of walkValues(tokens, null, null, true)) {
|
|
@@ -759,17 +793,18 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
759
793
|
continue;
|
|
760
794
|
}
|
|
761
795
|
}
|
|
762
|
-
if (value.typ == EnumToken.ParensTokenType) {
|
|
796
|
+
if (value.typ == EnumToken.ParensTokenType || (value.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'style', 'scroll-state'].includes(value.val))) {
|
|
763
797
|
// @todo parse range and declarations
|
|
764
798
|
// parseDeclaration(parent.chi);
|
|
765
799
|
let i;
|
|
766
800
|
let nameIndex = -1;
|
|
767
801
|
let valueIndex = -1;
|
|
802
|
+
const dashedIdent = value.typ == EnumToken.FunctionTokenType && value.val == 'style';
|
|
768
803
|
for (let i = 0; i < value.chi.length; i++) {
|
|
769
804
|
if (value.chi[i].typ == EnumToken.CommentTokenType || value.chi[i].typ == EnumToken.WhitespaceTokenType) {
|
|
770
805
|
continue;
|
|
771
806
|
}
|
|
772
|
-
if (value.chi[i].typ == EnumToken.IdenTokenType) {
|
|
807
|
+
if ((dashedIdent && value.chi[i].typ == EnumToken.DashedIdenTokenType) || value.chi[i].typ == EnumToken.IdenTokenType || value.chi[i].typ == EnumToken.FunctionTokenType || value.chi[i].typ == EnumToken.ColorTokenType) {
|
|
773
808
|
nameIndex = i;
|
|
774
809
|
}
|
|
775
810
|
break;
|
|
@@ -798,6 +833,13 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
798
833
|
].includes(value.chi[valueIndex].typ)) {
|
|
799
834
|
const val = value.chi.splice(valueIndex, 1)[0];
|
|
800
835
|
const node = value.chi.splice(nameIndex, 1)[0];
|
|
836
|
+
// 'background'
|
|
837
|
+
// @ts-ignore
|
|
838
|
+
if (node.typ == EnumToken.ColorTokenType && node.kin == 'dpsys') {
|
|
839
|
+
// @ts-ignore
|
|
840
|
+
delete node.kin;
|
|
841
|
+
node.typ = EnumToken.IdenTokenType;
|
|
842
|
+
}
|
|
801
843
|
while (value.chi[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
802
844
|
value.chi.shift();
|
|
803
845
|
}
|
|
@@ -815,6 +857,10 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
815
857
|
}
|
|
816
858
|
return tokens;
|
|
817
859
|
}
|
|
860
|
+
/**
|
|
861
|
+
* parse selector
|
|
862
|
+
* @param tokens
|
|
863
|
+
*/
|
|
818
864
|
function parseSelector(tokens) {
|
|
819
865
|
for (const { value, previousValue, nextValue, parent } of walkValues(tokens)) {
|
|
820
866
|
if (value.typ == EnumToken.CommentTokenType ||
|
|
@@ -958,6 +1004,11 @@ function parseSelector(tokens) {
|
|
|
958
1004
|
//
|
|
959
1005
|
// return doParse(`.x{${src}`, options).then((result: ParseResult) => <AstDeclaration[]>(<AstRule>result.ast.chi[0]).chi.filter(t => t.typ == EnumToken.DeclarationNodeType));
|
|
960
1006
|
// }
|
|
1007
|
+
/**
|
|
1008
|
+
* parse string
|
|
1009
|
+
* @param src
|
|
1010
|
+
* @param options
|
|
1011
|
+
*/
|
|
961
1012
|
function parseString(src, options = { location: false }) {
|
|
962
1013
|
return parseTokens([...tokenize(src)].map(t => {
|
|
963
1014
|
const token = getTokenType(t.token, t.hint);
|
|
@@ -1019,10 +1070,16 @@ function getTokenType(val, hint) {
|
|
|
1019
1070
|
val: val.slice(0, -1),
|
|
1020
1071
|
chi: []
|
|
1021
1072
|
}
|
|
1022
|
-
:
|
|
1023
|
-
|
|
1073
|
+
: (
|
|
1074
|
+
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
|
|
1075
|
+
val.startsWith('::') || pseudoElements.includes(val) ? {
|
|
1076
|
+
typ: EnumToken.PseudoElementTokenType,
|
|
1024
1077
|
val
|
|
1025
|
-
}
|
|
1078
|
+
} :
|
|
1079
|
+
{
|
|
1080
|
+
typ: EnumToken.PseudoClassTokenType,
|
|
1081
|
+
val
|
|
1082
|
+
});
|
|
1026
1083
|
}
|
|
1027
1084
|
if (isAtKeyword(val)) {
|
|
1028
1085
|
return {
|
|
@@ -1039,7 +1096,7 @@ function getTokenType(val, hint) {
|
|
|
1039
1096
|
chi: []
|
|
1040
1097
|
};
|
|
1041
1098
|
}
|
|
1042
|
-
if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade'].includes(val)) {
|
|
1099
|
+
if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade', 'paint'].includes(val)) {
|
|
1043
1100
|
return {
|
|
1044
1101
|
typ: EnumToken.ImageFunctionTokenType,
|
|
1045
1102
|
val,
|
|
@@ -1139,6 +1196,11 @@ function getTokenType(val, hint) {
|
|
|
1139
1196
|
val
|
|
1140
1197
|
};
|
|
1141
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* parse token list
|
|
1201
|
+
* @param tokens
|
|
1202
|
+
* @param options
|
|
1203
|
+
*/
|
|
1142
1204
|
function parseTokens(tokens, options = {}) {
|
|
1143
1205
|
for (let i = 0; i < tokens.length; i++) {
|
|
1144
1206
|
const t = tokens[i];
|
|
@@ -1194,25 +1256,25 @@ function parseTokens(tokens, options = {}) {
|
|
|
1194
1256
|
break;
|
|
1195
1257
|
}
|
|
1196
1258
|
}
|
|
1197
|
-
Object.assign(t, {
|
|
1259
|
+
const attr = Object.assign(t, {
|
|
1198
1260
|
typ: inAttr == 0 ? EnumToken.AttrTokenType : EnumToken.InvalidAttrTokenType,
|
|
1199
1261
|
chi: tokens.splice(i + 1, k - i)
|
|
1200
1262
|
});
|
|
1201
1263
|
// @ts-ignore
|
|
1202
|
-
if (
|
|
1264
|
+
if (attr.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
|
|
1203
1265
|
// @ts-ignore
|
|
1204
|
-
|
|
1266
|
+
attr.chi.pop();
|
|
1205
1267
|
}
|
|
1206
1268
|
// @ts-ignore
|
|
1207
|
-
if (
|
|
1269
|
+
if (attr.chi.length > 1) {
|
|
1208
1270
|
/*(<AttrToken>t).chi =*/
|
|
1209
1271
|
// @ts-ignore
|
|
1210
|
-
parseTokens(
|
|
1272
|
+
parseTokens(attr.chi, t.typ);
|
|
1211
1273
|
}
|
|
1212
|
-
let m =
|
|
1274
|
+
let m = attr.chi.length;
|
|
1213
1275
|
let val;
|
|
1214
|
-
for (m = 0; m <
|
|
1215
|
-
val =
|
|
1276
|
+
for (m = 0; m < attr.chi.length; m++) {
|
|
1277
|
+
val = attr.chi[m];
|
|
1216
1278
|
if (val.typ == EnumToken.StringTokenType) {
|
|
1217
1279
|
const slice = val.val.slice(1, -1);
|
|
1218
1280
|
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
@@ -1222,55 +1284,55 @@ function parseTokens(tokens, options = {}) {
|
|
|
1222
1284
|
else if (val.typ == EnumToken.LiteralTokenType && val.val == '|') {
|
|
1223
1285
|
let upper = m;
|
|
1224
1286
|
let lower = m;
|
|
1225
|
-
while (++upper <
|
|
1226
|
-
if (
|
|
1287
|
+
while (++upper < attr.chi.length) {
|
|
1288
|
+
if (attr.chi[upper].typ == EnumToken.CommentTokenType) {
|
|
1227
1289
|
continue;
|
|
1228
1290
|
}
|
|
1229
1291
|
break;
|
|
1230
1292
|
}
|
|
1231
1293
|
while (lower-- > 0) {
|
|
1232
|
-
if (
|
|
1294
|
+
if (attr.chi[lower].typ == EnumToken.CommentTokenType) {
|
|
1233
1295
|
continue;
|
|
1234
1296
|
}
|
|
1235
1297
|
break;
|
|
1236
1298
|
}
|
|
1237
1299
|
// @ts-ignore
|
|
1238
|
-
|
|
1300
|
+
attr.chi[m] = {
|
|
1239
1301
|
typ: EnumToken.NameSpaceAttributeTokenType,
|
|
1240
|
-
l:
|
|
1241
|
-
r:
|
|
1302
|
+
l: attr.chi[lower],
|
|
1303
|
+
r: attr.chi[upper]
|
|
1242
1304
|
};
|
|
1243
|
-
|
|
1305
|
+
attr.chi.splice(upper, 1);
|
|
1244
1306
|
if (lower >= 0) {
|
|
1245
|
-
|
|
1307
|
+
attr.chi.splice(lower, 1);
|
|
1246
1308
|
m--;
|
|
1247
1309
|
}
|
|
1248
1310
|
}
|
|
1249
1311
|
else if ([
|
|
1250
1312
|
EnumToken.DashMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DelimTokenType
|
|
1251
|
-
].includes(
|
|
1313
|
+
].includes(attr.chi[m].typ)) {
|
|
1252
1314
|
let upper = m;
|
|
1253
1315
|
let lower = m;
|
|
1254
|
-
while (++upper <
|
|
1255
|
-
if (
|
|
1316
|
+
while (++upper < attr.chi.length) {
|
|
1317
|
+
if (attr.chi[upper].typ == EnumToken.CommentTokenType) {
|
|
1256
1318
|
continue;
|
|
1257
1319
|
}
|
|
1258
1320
|
break;
|
|
1259
1321
|
}
|
|
1260
1322
|
while (lower-- > 0) {
|
|
1261
|
-
if (
|
|
1323
|
+
if (attr.chi[lower].typ == EnumToken.CommentTokenType) {
|
|
1262
1324
|
continue;
|
|
1263
1325
|
}
|
|
1264
1326
|
break;
|
|
1265
1327
|
}
|
|
1266
|
-
val =
|
|
1328
|
+
val = attr.chi[lower];
|
|
1267
1329
|
if (val.typ == EnumToken.StringTokenType) {
|
|
1268
1330
|
const slice = val.val.slice(1, -1);
|
|
1269
1331
|
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
1270
1332
|
Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
|
|
1271
1333
|
}
|
|
1272
1334
|
}
|
|
1273
|
-
val =
|
|
1335
|
+
val = attr.chi[upper];
|
|
1274
1336
|
if (val.typ == EnumToken.StringTokenType) {
|
|
1275
1337
|
const slice = val.val.slice(1, -1);
|
|
1276
1338
|
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
@@ -1390,7 +1452,9 @@ function parseTokens(tokens, options = {}) {
|
|
|
1390
1452
|
t.typ = EnumToken.ColorTokenType;
|
|
1391
1453
|
// @ts-ignore
|
|
1392
1454
|
t.kin = t.val;
|
|
1455
|
+
// @ts-ignore
|
|
1393
1456
|
if (t.chi[0].typ == EnumToken.IdenTokenType) {
|
|
1457
|
+
// @ts-ignore
|
|
1394
1458
|
if (t.chi[0].val == 'from') {
|
|
1395
1459
|
// @ts-ignore
|
|
1396
1460
|
t.cal = 'rel';
|
|
@@ -1400,10 +1464,11 @@ function parseTokens(tokens, options = {}) {
|
|
|
1400
1464
|
// @ts-ignore
|
|
1401
1465
|
t.cal = 'mix';
|
|
1402
1466
|
}
|
|
1403
|
-
else
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1467
|
+
else { // @ts-ignore
|
|
1468
|
+
if (t.val == 'color') {
|
|
1469
|
+
// @ts-ignore
|
|
1470
|
+
t.cal = 'col';
|
|
1471
|
+
}
|
|
1407
1472
|
}
|
|
1408
1473
|
}
|
|
1409
1474
|
const filter = [EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType];
|
|
@@ -1437,7 +1502,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
1437
1502
|
if (t.chi.length > 0) {
|
|
1438
1503
|
if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
|
|
1439
1504
|
//
|
|
1440
|
-
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
|
|
1505
|
+
const count = t.chi.filter((t) => t.typ != EnumToken.CommentTokenType).length;
|
|
1441
1506
|
if (count == 1 ||
|
|
1442
1507
|
(i == 0 &&
|
|
1443
1508
|
(tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1)) ||
|
|
@@ -1474,4 +1539,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
1474
1539
|
return tokens;
|
|
1475
1540
|
}
|
|
1476
1541
|
|
|
1477
|
-
export { doParse,
|
|
1542
|
+
export { doParse, parseSelector, parseString, parseTokens, urlTokenMatcher };
|