@tbela99/css-parser 0.9.0 → 1.0.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.md +1 -1
- package/README.md +22 -12
- package/dist/index-umd-web.js +2678 -2838
- package/dist/index.cjs +2468 -2628
- package/dist/index.d.ts +71 -26
- package/dist/lib/ast/expand.js +15 -2
- package/dist/lib/ast/features/calc.js +7 -10
- package/dist/lib/ast/features/index.js +1 -0
- package/dist/lib/ast/features/inlinecssvariables.js +0 -5
- package/dist/lib/ast/features/prefix.js +2 -7
- package/dist/lib/ast/features/shorthand.js +6 -9
- package/dist/lib/ast/features/transform.js +60 -0
- package/dist/lib/ast/math/expression.js +14 -10
- package/dist/lib/ast/math/math.js +14 -2
- package/dist/lib/ast/minify.js +47 -6
- package/dist/lib/ast/transform/compute.js +336 -0
- package/dist/lib/ast/transform/convert.js +33 -0
- package/dist/lib/ast/transform/matrix.js +111 -0
- package/dist/lib/ast/transform/minify.js +296 -0
- package/dist/lib/ast/transform/perspective.js +10 -0
- package/dist/lib/ast/transform/rotate.js +40 -0
- package/dist/lib/ast/transform/scale.js +32 -0
- package/dist/lib/ast/transform/skew.js +23 -0
- package/dist/lib/ast/transform/translate.js +32 -0
- package/dist/lib/ast/transform/utils.js +198 -0
- package/dist/lib/ast/types.js +2 -0
- package/dist/lib/ast/walk.js +23 -17
- package/dist/lib/parser/parse.js +174 -127
- package/dist/lib/parser/utils/declaration.js +1 -1
- package/dist/lib/renderer/color/{colormix.js → color-mix.js} +6 -0
- package/dist/lib/renderer/color/color.js +96 -20
- package/dist/lib/renderer/color/hex.js +17 -7
- package/dist/lib/renderer/color/hsl.js +7 -2
- package/dist/lib/renderer/color/lab.js +10 -1
- package/dist/lib/renderer/color/lch.js +8 -0
- package/dist/lib/renderer/color/oklab.js +8 -0
- package/dist/lib/renderer/color/oklch.js +8 -0
- package/dist/lib/renderer/color/prophotorgb.js +2 -2
- package/dist/lib/renderer/color/relativecolor.js +10 -21
- package/dist/lib/renderer/color/rgb.js +10 -7
- package/dist/lib/renderer/color/srgb.js +30 -6
- package/dist/lib/renderer/color/utils/components.js +13 -2
- package/dist/lib/renderer/color/xyz.js +2 -18
- package/dist/lib/renderer/color/xyzd50.js +20 -2
- package/dist/lib/renderer/render.js +70 -32
- package/dist/lib/renderer/sourcemap/sourcemap.js +1 -1
- package/dist/lib/syntax/syntax.js +75 -56
- package/dist/lib/validation/at-rules/container.js +6 -6
- package/dist/lib/validation/at-rules/document.js +40 -60
- package/dist/lib/validation/at-rules/import.js +61 -59
- package/dist/lib/validation/at-rules/keyframes.js +1 -1
- package/dist/lib/validation/at-rules/media.js +1 -1
- package/dist/lib/validation/at-rules/supports.js +40 -9
- package/dist/lib/validation/atrule.js +0 -4
- package/dist/lib/validation/config.json.js +83 -35
- package/dist/lib/validation/parser/parse.js +1 -95
- package/dist/lib/validation/parser/types.js +1 -2
- package/dist/lib/validation/selector.js +5 -2
- package/dist/lib/validation/syntaxes/compound-selector.js +2 -2
- package/dist/lib/validation/syntaxes/keyframe-block-list.js +2 -2
- package/dist/lib/validation/syntaxes/keyframe-selector.js +11 -90
- package/dist/lib/validation/syntaxes/layer-name.js +5 -16
- package/dist/lib/validation/syntaxes/relative-selector.js +15 -14
- package/dist/lib/validation/utils/list.js +18 -1
- package/dist/node/load.js +1 -1
- package/package.json +13 -12
- package/dist/lib/renderer/color/prophotoRgb.js +0 -56
- package/dist/lib/validation/declaration.js +0 -102
- package/dist/lib/validation/syntax.js +0 -1475
- package/dist/lib/validation/syntaxes/image.js +0 -29
|
@@ -2,14 +2,14 @@ import { getAngle, color2srgbvalues, clamp } from './color/color.js';
|
|
|
2
2
|
import { colorFuncColorSpace, COLORS_NAMES } from './color/utils/constants.js';
|
|
3
3
|
import { getComponents } from './color/utils/components.js';
|
|
4
4
|
import { reduceHexValue, srgb2hexvalues, rgb2hex, hsl2hex, hwb2hex, cmyk2hex, oklab2hex, oklch2hex, lab2hex, lch2hex } from './color/hex.js';
|
|
5
|
-
import { EnumToken } from '../ast/types.js';
|
|
5
|
+
import { EnumToken, funcLike } from '../ast/types.js';
|
|
6
6
|
import '../ast/minify.js';
|
|
7
7
|
import '../ast/walk.js';
|
|
8
8
|
import { expand } from '../ast/expand.js';
|
|
9
|
-
import { colorMix } from './color/
|
|
9
|
+
import { colorMix } from './color/color-mix.js';
|
|
10
10
|
import { parseRelativeColor } from './color/relativecolor.js';
|
|
11
11
|
import { SourceMap } from './sourcemap/sourcemap.js';
|
|
12
|
-
import { isColor, mathFuncs, isNewLine } from '../syntax/syntax.js';
|
|
12
|
+
import { isColor, pseudoElements, mathFuncs, isNewLine } from '../syntax/syntax.js';
|
|
13
13
|
|
|
14
14
|
const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk', 'color-mix', 'color', 'oklab', 'lab', 'oklch', 'lch', 'light-dark'];
|
|
15
15
|
function reduceNumber(val) {
|
|
@@ -109,7 +109,7 @@ function doRender(data, options = {}) {
|
|
|
109
109
|
return result;
|
|
110
110
|
}
|
|
111
111
|
function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
112
|
-
if ([EnumToken.RuleNodeType, EnumToken.AtRuleNodeType, EnumToken.KeyFrameRuleNodeType].includes(node.typ)) {
|
|
112
|
+
if ([EnumToken.RuleNodeType, EnumToken.AtRuleNodeType, EnumToken.KeyFrameRuleNodeType, EnumToken.KeyframeAtRuleNodeType].includes(node.typ)) {
|
|
113
113
|
let src = node.loc?.src ?? '';
|
|
114
114
|
let output = options.output ?? '';
|
|
115
115
|
if (!(src in cache)) {
|
|
@@ -152,7 +152,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
152
152
|
const indentSub = indents[level + 1];
|
|
153
153
|
switch (data.typ) {
|
|
154
154
|
case EnumToken.DeclarationNodeType:
|
|
155
|
-
return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
|
|
155
|
+
return `${data.nam}:${options.indent}${(options.minify ? filterValues(data.val) : data.val).reduce(reducer, '')}`;
|
|
156
156
|
case EnumToken.CommentNodeType:
|
|
157
157
|
case EnumToken.CDOCOMMNodeType:
|
|
158
158
|
if (data.val.startsWith('/*# sourceMappingURL=')) {
|
|
@@ -181,7 +181,8 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
181
181
|
case EnumToken.AtRuleNodeType:
|
|
182
182
|
case EnumToken.RuleNodeType:
|
|
183
183
|
case EnumToken.KeyFrameRuleNodeType:
|
|
184
|
-
|
|
184
|
+
case EnumToken.KeyframeAtRuleNodeType:
|
|
185
|
+
if ([EnumToken.AtRuleNodeType, EnumToken.KeyframeAtRuleNodeType].includes(data.typ) && !('chi' in data)) {
|
|
185
186
|
return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
186
187
|
}
|
|
187
188
|
// @ts-ignore
|
|
@@ -191,7 +192,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
191
192
|
str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
|
|
192
193
|
}
|
|
193
194
|
else if (node.typ == EnumToken.DeclarationNodeType) {
|
|
194
|
-
if (node.val.length == 0) {
|
|
195
|
+
if (!node.nam.startsWith('--') && node.val.length == 0) {
|
|
195
196
|
// @ts-ignore
|
|
196
197
|
errors.push({
|
|
197
198
|
action: 'ignore',
|
|
@@ -200,7 +201,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
200
201
|
});
|
|
201
202
|
return '';
|
|
202
203
|
}
|
|
203
|
-
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
204
|
+
str = `${node.nam}:${options.indent}${(options.minify ? filterValues(node.val) : node.val).reduce(reducer, '').trimEnd()};`;
|
|
204
205
|
}
|
|
205
206
|
else if (node.typ == EnumToken.AtRuleNodeType && !('chi' in node)) {
|
|
206
207
|
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
@@ -222,7 +223,7 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
222
223
|
if (children.endsWith(';')) {
|
|
223
224
|
children = children.slice(0, -1);
|
|
224
225
|
}
|
|
225
|
-
if (
|
|
226
|
+
if ([EnumToken.AtRuleNodeType, EnumToken.KeyframeAtRuleNodeType].includes(data.typ)) {
|
|
226
227
|
return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
227
228
|
}
|
|
228
229
|
return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
|
@@ -258,20 +259,25 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
258
259
|
if (isColor(token)) {
|
|
259
260
|
// @ts-ignore
|
|
260
261
|
token.typ = EnumToken.ColorTokenType;
|
|
262
|
+
// @ts-ignore
|
|
261
263
|
if (token.chi[0].typ == EnumToken.IdenTokenType && token.chi[0].val == 'from') {
|
|
262
264
|
// @ts-ignore
|
|
263
265
|
token.cal = 'rel';
|
|
264
266
|
}
|
|
265
|
-
else
|
|
266
|
-
|
|
267
|
-
token.cal = 'mix';
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
if (token.val == 'color') {
|
|
267
|
+
else { // @ts-ignore
|
|
268
|
+
if (token.val == 'color-mix' && token.chi[0].typ == EnumToken.IdenTokenType && token.chi[0].val == 'in') {
|
|
271
269
|
// @ts-ignore
|
|
272
|
-
token.cal = '
|
|
270
|
+
token.cal = 'mix';
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// @ts-ignore
|
|
274
|
+
if (token.val == 'color') {
|
|
275
|
+
// @ts-ignore
|
|
276
|
+
token.cal = 'col';
|
|
277
|
+
}
|
|
278
|
+
// @ts-ignore
|
|
279
|
+
token.chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommaTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
273
280
|
}
|
|
274
|
-
token.chi = token.chi.filter((t) => ![EnumToken.WhitespaceTokenType, EnumToken.CommaTokenType, EnumToken.CommentTokenType].includes(t.typ));
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
283
|
}
|
|
@@ -338,22 +344,36 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
338
344
|
if (value != null) {
|
|
339
345
|
token = value;
|
|
340
346
|
}
|
|
347
|
+
else if (!token.chi.some(t => t.typ == EnumToken.CommaTokenType)) {
|
|
348
|
+
token.chi = children.reduce((acc, curr, index) => {
|
|
349
|
+
if (acc.length > 0) {
|
|
350
|
+
acc.push({ typ: EnumToken.CommaTokenType });
|
|
351
|
+
}
|
|
352
|
+
acc.push(...curr);
|
|
353
|
+
return acc;
|
|
354
|
+
}, []);
|
|
355
|
+
}
|
|
341
356
|
}
|
|
342
357
|
if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color'].includes(token.val)) {
|
|
343
358
|
const chi = getComponents(token);
|
|
344
359
|
const offset = token.val == 'color' ? 2 : 1;
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
360
|
+
if (chi != null) {
|
|
361
|
+
// @ts-ignore
|
|
362
|
+
const color = chi[1];
|
|
363
|
+
const components = parseRelativeColor(token.val == 'color' ? chi[offset].val : token.val, color, chi[offset + 1], chi[offset + 2], chi[offset + 3], chi[offset + 4]);
|
|
364
|
+
if (components != null) {
|
|
365
|
+
token.chi = [...(token.val == 'color' ? [chi[offset]] : []), ...Object.values(components)];
|
|
366
|
+
delete token.cal;
|
|
367
|
+
}
|
|
351
368
|
}
|
|
352
369
|
}
|
|
353
370
|
if (token.val == 'color') {
|
|
354
371
|
if (token.chi[0].typ == EnumToken.IdenTokenType && colorFuncColorSpace.includes(token.chi[0].val.toLowerCase())) {
|
|
355
|
-
|
|
356
|
-
|
|
372
|
+
const values = color2srgbvalues(token);
|
|
373
|
+
if (Array.isArray(values) && values.every(t => !Number.isNaN(t))) {
|
|
374
|
+
// @ts-ignore
|
|
375
|
+
return reduceHexValue(srgb2hexvalues(...values));
|
|
376
|
+
}
|
|
357
377
|
}
|
|
358
378
|
}
|
|
359
379
|
if (token.cal != null) {
|
|
@@ -410,7 +430,7 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
410
430
|
else if (token.val == 'lch') {
|
|
411
431
|
value = lch2hex(token);
|
|
412
432
|
}
|
|
413
|
-
if (value !== '') {
|
|
433
|
+
if (value !== '' && value != null) {
|
|
414
434
|
return reduceHexValue(value);
|
|
415
435
|
}
|
|
416
436
|
}
|
|
@@ -589,8 +609,9 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
589
609
|
return '';
|
|
590
610
|
}
|
|
591
611
|
case EnumToken.PseudoClassTokenType:
|
|
612
|
+
case EnumToken.PseudoElementTokenType:
|
|
592
613
|
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
|
|
593
|
-
if (token.typ == EnumToken.
|
|
614
|
+
if (token.typ == EnumToken.PseudoElementTokenType && pseudoElements.includes(token.val.slice(1))) {
|
|
594
615
|
return token.val.slice(1);
|
|
595
616
|
}
|
|
596
617
|
case EnumToken.UrlTokenTokenType:
|
|
@@ -599,7 +620,11 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
599
620
|
if (!('original' in token)) {
|
|
600
621
|
// do not modify original token
|
|
601
622
|
token = { ...token };
|
|
602
|
-
Object.defineProperty(token, 'original', {
|
|
623
|
+
Object.defineProperty(token, 'original', {
|
|
624
|
+
enumerable: false,
|
|
625
|
+
writable: false,
|
|
626
|
+
value: token.val
|
|
627
|
+
});
|
|
603
628
|
}
|
|
604
629
|
// @ts-ignore
|
|
605
630
|
if (!(token.original in cache)) {
|
|
@@ -632,7 +657,7 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
632
657
|
case EnumToken.InvalidClassSelectorTokenType:
|
|
633
658
|
return token.val;
|
|
634
659
|
case EnumToken.DeclarationNodeType:
|
|
635
|
-
return token.nam + ':' + token.val.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
|
|
660
|
+
return token.nam + ':' + (options.minify ? filterValues(token.val) : token.val).reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
|
|
636
661
|
case EnumToken.MediaQueryConditionTokenType:
|
|
637
662
|
return renderToken(token.l, options, cache, reducer, errors) + renderToken(token.op, options, cache, reducer, errors) + token.r.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
|
|
638
663
|
case EnumToken.MediaFeatureTokenType:
|
|
@@ -645,11 +670,24 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
645
670
|
return 'and';
|
|
646
671
|
case EnumToken.MediaFeatureOrTokenType:
|
|
647
672
|
return 'or';
|
|
648
|
-
default:
|
|
649
|
-
|
|
673
|
+
// default:
|
|
674
|
+
//
|
|
675
|
+
// throw new Error(`render: unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
650
676
|
}
|
|
651
677
|
errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
|
|
652
678
|
return '';
|
|
653
679
|
}
|
|
680
|
+
function filterValues(values) {
|
|
681
|
+
let i = 0;
|
|
682
|
+
for (; i < values.length; i++) {
|
|
683
|
+
if (values[i].typ == EnumToken.ImportantTokenType && values[i - 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
684
|
+
values.splice(i - 1, 1);
|
|
685
|
+
}
|
|
686
|
+
else if (funcLike.includes(values[i].typ) && !['var', 'calc'].includes(values[i].val) && values[i + 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
687
|
+
values.splice(i + 1, 1);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
return values;
|
|
691
|
+
}
|
|
654
692
|
|
|
655
|
-
export { colorsFunc, doRender, reduceNumber, renderToken };
|
|
693
|
+
export { colorsFunc, doRender, filterValues, reduceNumber, renderToken };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { encode } from './lib/encode.js';
|
|
2
2
|
|
|
3
3
|
class SourceMap {
|
|
4
|
+
lastLocation = null;
|
|
4
5
|
#version = 3;
|
|
5
6
|
#sources = [];
|
|
6
7
|
#map = new Map;
|
|
7
8
|
#line = -1;
|
|
8
|
-
lastLocation = null;
|
|
9
9
|
add(source, original) {
|
|
10
10
|
if (original.src !== '') {
|
|
11
11
|
if (!this.#sources.includes(original.src)) {
|
|
@@ -19,12 +19,21 @@ const dimensionUnits = new Set([
|
|
|
19
19
|
const fontFormat = ['collection', 'embedded-opentype', 'opentype', 'svg', 'truetype', 'woff', 'woff2'];
|
|
20
20
|
const colorFontTech = ['color-colrv0', 'color-colrv1', 'color-svg', 'color-sbix', 'color-cbdt'];
|
|
21
21
|
const fontFeaturesTech = ['features-opentype', 'features-aat', 'features-graphite', 'incremental-patch', 'incremental-range', 'incremental-auto', 'variations', 'palettes'];
|
|
22
|
+
const transformFunctions = [
|
|
23
|
+
'translate', 'scale', 'rotate', 'skew', 'perspective',
|
|
24
|
+
'translateX', 'translateY', 'translateZ',
|
|
25
|
+
'scaleX', 'scaleY', 'scaleZ',
|
|
26
|
+
'rotateX', 'rotateY', 'rotateZ',
|
|
27
|
+
'skewX', 'skewY',
|
|
28
|
+
'rotate3d', 'translate3d', 'scale3d', 'matrix', 'matrix3d'
|
|
29
|
+
];
|
|
22
30
|
// https://drafts.csswg.org/mediaqueries/#media-types
|
|
23
31
|
const mediaTypes = ['all', 'print', 'screen',
|
|
24
32
|
/* deprecated */
|
|
25
33
|
'aural', 'braille', 'embossed', 'handheld', 'projection', 'tty', 'tv', 'speech'];
|
|
26
34
|
// https://www.w3.org/TR/css-values-4/#math-function
|
|
27
35
|
const mathFuncs = ['calc', 'clamp', 'min', 'max', 'round', 'mod', 'rem', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'pow', 'sqrt', 'hypot', 'log', 'exp', 'abs', 'sign'];
|
|
36
|
+
const pseudoElements = [':before', ':after', ':first-line', ':first-letter'];
|
|
28
37
|
const webkitPseudoAliasMap = {
|
|
29
38
|
'-webkit-autofill': 'autofill',
|
|
30
39
|
'-webkit-any': 'is',
|
|
@@ -409,7 +418,9 @@ function isColor(token) {
|
|
|
409
418
|
}
|
|
410
419
|
let isLegacySyntax = false;
|
|
411
420
|
if (token.typ == EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
|
|
421
|
+
// @ts-ignore
|
|
412
422
|
if (token.val == 'light-dark') {
|
|
423
|
+
// @ts-ignore
|
|
413
424
|
const children = token.chi.filter((t) => [EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.LiteralTokenType, EnumToken.ColorTokenType, EnumToken.FunctionTokenType, EnumToken.PercentageTokenType].includes(t.typ));
|
|
414
425
|
if (children.length != 2) {
|
|
415
426
|
return false;
|
|
@@ -418,7 +429,9 @@ function isColor(token) {
|
|
|
418
429
|
return true;
|
|
419
430
|
}
|
|
420
431
|
}
|
|
432
|
+
// @ts-ignore
|
|
421
433
|
if (token.val == 'color') {
|
|
434
|
+
// @ts-ignore
|
|
422
435
|
const children = token.chi.filter((t) => [EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.LiteralTokenType, EnumToken.ColorTokenType, EnumToken.FunctionTokenType, EnumToken.PercentageTokenType].includes(t.typ));
|
|
423
436
|
const isRelative = children[0].typ == EnumToken.IdenTokenType && children[0].val == 'from';
|
|
424
437
|
if (children.length < 4 || children.length > 8) {
|
|
@@ -467,73 +480,79 @@ function isColor(token) {
|
|
|
467
480
|
}
|
|
468
481
|
return true;
|
|
469
482
|
}
|
|
470
|
-
else
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if (![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)) {
|
|
477
|
-
acc[acc.length - 1].push(t);
|
|
483
|
+
else { // @ts-ignore
|
|
484
|
+
if (token.val == 'color-mix') {
|
|
485
|
+
// @ts-ignore
|
|
486
|
+
const children = token.chi.reduce((acc, t) => {
|
|
487
|
+
if (t.typ == EnumToken.CommaTokenType) {
|
|
488
|
+
acc.push([]);
|
|
478
489
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
if (children[0].length > 3 ||
|
|
484
|
-
children[0][0].typ != EnumToken.IdenTokenType ||
|
|
485
|
-
children[0][0].val != 'in' ||
|
|
486
|
-
!isColorspace(children[0][1]) ||
|
|
487
|
-
(children[0].length == 3 && !isHueInterpolationMethod(children[0][2])) ||
|
|
488
|
-
children[1].length > 2 ||
|
|
489
|
-
children[1][0].typ != EnumToken.ColorTokenType ||
|
|
490
|
-
children[2].length > 2 ||
|
|
491
|
-
children[2][0].typ != EnumToken.ColorTokenType) {
|
|
492
|
-
return false;
|
|
493
|
-
}
|
|
494
|
-
if (children[1].length == 2) {
|
|
495
|
-
if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == '0'))) {
|
|
496
|
-
return false;
|
|
490
|
+
else {
|
|
491
|
+
if (![EnumToken.WhitespaceTokenType, EnumToken.CommentTokenType].includes(t.typ)) {
|
|
492
|
+
acc[acc.length - 1].push(t);
|
|
493
|
+
}
|
|
497
494
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
495
|
+
return acc;
|
|
496
|
+
}, [[]]);
|
|
497
|
+
if (children.length == 3) {
|
|
498
|
+
if (children[0].length > 3 ||
|
|
499
|
+
children[0][0].typ != EnumToken.IdenTokenType ||
|
|
500
|
+
children[0][0].val != 'in' ||
|
|
501
|
+
!isColorspace(children[0][1]) ||
|
|
502
|
+
(children[0].length == 3 && !isHueInterpolationMethod(children[0][2])) ||
|
|
503
|
+
children[1].length > 2 ||
|
|
504
|
+
children[1][0].typ != EnumToken.ColorTokenType ||
|
|
505
|
+
children[2].length > 2 ||
|
|
506
|
+
children[2][0].typ != EnumToken.ColorTokenType) {
|
|
501
507
|
return false;
|
|
502
508
|
}
|
|
509
|
+
if (children[1].length == 2) {
|
|
510
|
+
if (!(children[1][1].typ == EnumToken.PercentageTokenType || (children[1][1].typ == EnumToken.NumberTokenType && children[1][1].val == '0'))) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
if (children[2].length == 2) {
|
|
515
|
+
if (!(children[2][1].typ == EnumToken.PercentageTokenType || (children[2][1].typ == EnumToken.NumberTokenType && children[2][1].val == '0'))) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return true;
|
|
503
520
|
}
|
|
504
|
-
return
|
|
505
|
-
}
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
else {
|
|
509
|
-
const keywords = ['from', 'none'];
|
|
510
|
-
if (['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch'].includes(token.val)) {
|
|
511
|
-
keywords.push('alpha', ...token.val.slice(-3).split(''));
|
|
521
|
+
return false;
|
|
512
522
|
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
523
|
+
else {
|
|
524
|
+
const keywords = ['from', 'none'];
|
|
525
|
+
// @ts-ignore
|
|
526
|
+
if (['rgb', 'hsl', 'hwb', 'lab', 'lch', 'oklab', 'oklch'].includes(token.val)) {
|
|
527
|
+
// @ts-ignore
|
|
528
|
+
keywords.push('alpha', ...token.val.slice(-3).split(''));
|
|
517
529
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
530
|
+
// @ts-ignore
|
|
531
|
+
for (const v of token.chi) {
|
|
532
|
+
if (v.typ == EnumToken.CommaTokenType) {
|
|
533
|
+
isLegacySyntax = true;
|
|
521
534
|
}
|
|
522
|
-
if (
|
|
523
|
-
if (
|
|
535
|
+
if (v.typ == EnumToken.IdenTokenType) {
|
|
536
|
+
if (!(keywords.includes(v.val) || v.val.toLowerCase() in COLORS_NAMES)) {
|
|
524
537
|
return false;
|
|
525
538
|
}
|
|
526
|
-
if (
|
|
527
|
-
|
|
539
|
+
if (keywords.includes(v.val)) {
|
|
540
|
+
if (isLegacySyntax) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
// @ts-ignore
|
|
544
|
+
if (v.val == 'from' && ['rgba', 'hsla'].includes(token.val)) {
|
|
545
|
+
return false;
|
|
546
|
+
}
|
|
528
547
|
}
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (v.typ == EnumToken.FunctionTokenType && (mathFuncs.includes(v.val) || v.val == 'var' || colorsFunc.includes(v.val))) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if (![EnumToken.ColorTokenType, EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.AngleTokenType, EnumToken.PercentageTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.LiteralTokenType].includes(v.typ)) {
|
|
554
|
+
return false;
|
|
529
555
|
}
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
if (v.typ == EnumToken.FunctionTokenType && (mathFuncs.includes(v.val) || v.val == 'var' || colorsFunc.includes(v.val))) {
|
|
533
|
-
continue;
|
|
534
|
-
}
|
|
535
|
-
if (![EnumToken.ColorTokenType, EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.AngleTokenType, EnumToken.PercentageTokenType, EnumToken.CommaTokenType, EnumToken.WhitespaceTokenType, EnumToken.LiteralTokenType].includes(v.typ)) {
|
|
536
|
-
return false;
|
|
537
556
|
}
|
|
538
557
|
}
|
|
539
558
|
}
|
|
@@ -811,4 +830,4 @@ function isWhiteSpace(codepoint) {
|
|
|
811
830
|
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
812
831
|
}
|
|
813
832
|
|
|
814
|
-
export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseDimension, webkitExtensions, webkitPseudoAliasMap };
|
|
833
|
+
export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseDimension, pseudoElements, transformFunctions, webkitExtensions, webkitPseudoAliasMap };
|
|
@@ -95,10 +95,10 @@ function validateAtRuleContainerQueryList(tokens, atRule) {
|
|
|
95
95
|
break;
|
|
96
96
|
}
|
|
97
97
|
token = queries[0];
|
|
98
|
-
if (token
|
|
98
|
+
if (token?.typ == EnumToken.MediaFeatureNotTokenType) {
|
|
99
99
|
token = token.val;
|
|
100
100
|
}
|
|
101
|
-
if (token
|
|
101
|
+
if (token?.typ != EnumToken.ParensTokenType && (token?.typ != EnumToken.FunctionTokenType || !['scroll-state', 'style'].includes(token.val))) {
|
|
102
102
|
return {
|
|
103
103
|
valid: ValidationLevel.Drop,
|
|
104
104
|
matches: [],
|
|
@@ -108,7 +108,7 @@ function validateAtRuleContainerQueryList(tokens, atRule) {
|
|
|
108
108
|
tokens
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
|
-
if (token
|
|
111
|
+
if (token?.typ == EnumToken.ParensTokenType) {
|
|
112
112
|
result = validateContainerSizeFeature(token.chi, atRule);
|
|
113
113
|
}
|
|
114
114
|
else if (token.val == 'scroll-state') {
|
|
@@ -126,7 +126,7 @@ function validateAtRuleContainerQueryList(tokens, atRule) {
|
|
|
126
126
|
break;
|
|
127
127
|
}
|
|
128
128
|
token = queries[0];
|
|
129
|
-
if (token
|
|
129
|
+
if (token?.typ != EnumToken.MediaFeatureAndTokenType && token?.typ != EnumToken.MediaFeatureOrTokenType) {
|
|
130
130
|
return {
|
|
131
131
|
valid: ValidationLevel.Drop,
|
|
132
132
|
matches: [],
|
|
@@ -137,9 +137,9 @@ function validateAtRuleContainerQueryList(tokens, atRule) {
|
|
|
137
137
|
};
|
|
138
138
|
}
|
|
139
139
|
if (tokenType == null) {
|
|
140
|
-
tokenType = token
|
|
140
|
+
tokenType = token?.typ;
|
|
141
141
|
}
|
|
142
|
-
if (tokenType != token
|
|
142
|
+
if (tokenType == null || tokenType != token?.typ) {
|
|
143
143
|
return {
|
|
144
144
|
valid: ValidationLevel.Drop,
|
|
145
145
|
matches: [],
|
|
@@ -6,6 +6,7 @@ import '../../renderer/color/utils/constants.js';
|
|
|
6
6
|
import '../../renderer/sourcemap/lib/encode.js';
|
|
7
7
|
import '../../parser/utils/config.js';
|
|
8
8
|
import { consumeWhitespace } from '../utils/whitespace.js';
|
|
9
|
+
import { splitTokenList } from '../utils/list.js';
|
|
9
10
|
import { validateURL } from '../syntaxes/url.js';
|
|
10
11
|
|
|
11
12
|
function validateAtRuleDocument(atRule, options, root) {
|
|
@@ -34,71 +35,50 @@ function validateAtRuleDocument(atRule, options, root) {
|
|
|
34
35
|
tokens
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
|
|
38
|
+
for (const t of splitTokenList(tokens)) {
|
|
39
|
+
if (t.length != 1) {
|
|
40
|
+
return {
|
|
41
|
+
valid: ValidationLevel.Drop,
|
|
42
|
+
matches: [],
|
|
43
|
+
node: t[0] ?? atRule,
|
|
44
|
+
syntax: '@document',
|
|
45
|
+
error: 'unexpected token',
|
|
46
|
+
tokens
|
|
47
|
+
};
|
|
48
|
+
}
|
|
38
49
|
// @ts-ignore
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
while (tokens.length > 0) {
|
|
49
|
-
if (tokens[0].typ == EnumToken.CommentTokenType) {
|
|
50
|
-
tokens.shift();
|
|
51
|
-
consumeWhitespace(tokens);
|
|
50
|
+
if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].some((f) => f.localeCompare(t[0].val, undefined, { sensitivity: 'base' }) == 0)) {
|
|
51
|
+
return {
|
|
52
|
+
valid: ValidationLevel.Drop,
|
|
53
|
+
matches: [],
|
|
54
|
+
node: t[0] ?? atRule,
|
|
55
|
+
syntax: '@document',
|
|
56
|
+
error: 'expecting any of url-prefix(), domain(), media-document(), regexp() but found ' + t[0].val,
|
|
57
|
+
tokens
|
|
58
|
+
};
|
|
52
59
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
if (t[0].typ == EnumToken.UrlFunctionTokenType) {
|
|
61
|
+
result = validateURL(t[0]);
|
|
62
|
+
if (result?.valid == ValidationLevel.Drop) {
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
57
65
|
continue;
|
|
58
66
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const children = tokens[0].chi.slice();
|
|
72
|
-
consumeWhitespace(children);
|
|
73
|
-
if (children.length == 0) {
|
|
74
|
-
// @ts-ignore
|
|
75
|
-
return {
|
|
76
|
-
valid: ValidationLevel.Drop,
|
|
77
|
-
matches: [],
|
|
78
|
-
node: tokens[0],
|
|
79
|
-
syntax: '@document',
|
|
80
|
-
error: 'expecting string argument',
|
|
81
|
-
tokens
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
if (children[0].typ == EnumToken.StringTokenType) {
|
|
85
|
-
children.shift();
|
|
86
|
-
consumeWhitespace(children);
|
|
87
|
-
}
|
|
88
|
-
if (children.length > 0) {
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
return {
|
|
91
|
-
valid: ValidationLevel.Drop,
|
|
92
|
-
matches: [],
|
|
93
|
-
node: children[0],
|
|
94
|
-
syntax: '@document',
|
|
95
|
-
error: 'unexpected token',
|
|
96
|
-
tokens
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
tokens.shift();
|
|
100
|
-
consumeWhitespace(tokens);
|
|
67
|
+
const children = t[0].chi.slice();
|
|
68
|
+
consumeWhitespace(children);
|
|
69
|
+
if (children.length != 1 || (children[0].typ != EnumToken.StringTokenType && children[0].typ != EnumToken.UrlTokenTokenType)) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
return {
|
|
72
|
+
valid: ValidationLevel.Drop,
|
|
73
|
+
matches: [],
|
|
74
|
+
node: tokens[0],
|
|
75
|
+
syntax: '@document',
|
|
76
|
+
error: 'expecting string argument',
|
|
77
|
+
tokens
|
|
78
|
+
};
|
|
101
79
|
}
|
|
80
|
+
tokens.shift();
|
|
81
|
+
consumeWhitespace(tokens);
|
|
102
82
|
}
|
|
103
83
|
// @ts-ignore
|
|
104
84
|
return {
|