@tbela99/css-parser 1.3.3 → 1.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/CHANGELOG.md +44 -0
- package/README.md +64 -48
- package/dist/config.json.js +3 -0
- package/dist/index-umd-web.js +2266 -631
- package/dist/index.cjs +2271 -620
- package/dist/index.d.ts +522 -181
- package/dist/lib/ast/expand.js +5 -10
- package/dist/lib/ast/features/calc.js +3 -2
- package/dist/lib/ast/features/inlinecssvariables.js +5 -3
- package/dist/lib/ast/features/prefix.js +1 -1
- package/dist/lib/ast/features/shorthand.js +1 -0
- package/dist/lib/ast/features/transform.js +13 -19
- package/dist/lib/ast/features/type.js +1 -1
- package/dist/lib/ast/minify.js +6 -3
- package/dist/lib/ast/transform/compute.js +2 -4
- package/dist/lib/ast/transform/matrix.js +20 -20
- package/dist/lib/ast/transform/minify.js +105 -12
- package/dist/lib/ast/transform/rotate.js +11 -11
- package/dist/lib/ast/transform/scale.js +6 -6
- package/dist/lib/ast/transform/skew.js +4 -4
- package/dist/lib/ast/transform/translate.js +3 -3
- package/dist/lib/ast/transform/utils.js +30 -37
- package/dist/lib/ast/types.js +76 -5
- package/dist/lib/ast/walk.js +77 -58
- package/dist/lib/fs/resolve.js +69 -10
- package/dist/lib/parser/declaration/list.js +6 -1
- package/dist/lib/parser/parse.js +1169 -312
- package/dist/lib/parser/tokenize.js +33 -20
- package/dist/lib/parser/utils/declaration.js +54 -0
- package/dist/lib/parser/utils/hash.js +86 -0
- package/dist/lib/parser/utils/text.js +8 -0
- package/dist/lib/renderer/render.js +26 -7
- package/dist/lib/syntax/color/relativecolor.js +0 -3
- package/dist/lib/syntax/syntax.js +36 -18
- package/dist/lib/validation/at-rules/container.js +11 -0
- package/dist/lib/validation/at-rules/counter-style.js +11 -0
- package/dist/lib/validation/at-rules/font-feature-values.js +11 -0
- package/dist/lib/validation/at-rules/keyframes.js +11 -0
- package/dist/lib/validation/at-rules/layer.js +11 -0
- package/dist/lib/validation/at-rules/media.js +11 -0
- package/dist/lib/validation/at-rules/page-margin-box.js +11 -0
- package/dist/lib/validation/at-rules/page.js +11 -0
- package/dist/lib/validation/at-rules/supports.js +11 -0
- package/dist/lib/validation/at-rules/when.js +11 -0
- package/dist/lib/validation/config.js +0 -2
- package/dist/lib/validation/config.json.js +36 -4
- package/dist/lib/validation/parser/parse.js +53 -2
- package/dist/lib/validation/syntax.js +204 -36
- package/dist/lib/validation/syntaxes/compound-selector.js +1 -2
- package/dist/lib/validation/syntaxes/relative-selector-list.js +2 -5
- package/dist/node.js +60 -18
- package/dist/types.d.ts +17 -0
- package/dist/types.js +20 -0
- package/dist/web.js +43 -17
- package/package.json +20 -17
- package/dist/lib/validation/parser/types.js +0 -54
|
@@ -12,6 +12,17 @@ import { validateMediaFeature, validateMediaCondition } from './media.js';
|
|
|
12
12
|
import { validateSupportCondition } from './supports.js';
|
|
13
13
|
|
|
14
14
|
function validateAtRuleWhen(atRule, options, root) {
|
|
15
|
+
if (!Array.isArray(atRule.chi)) {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
return {
|
|
18
|
+
valid: SyntaxValidationResult.Drop,
|
|
19
|
+
matches: [],
|
|
20
|
+
node: atRule,
|
|
21
|
+
syntax: '@' + atRule.nam,
|
|
22
|
+
error: 'expected supports body',
|
|
23
|
+
tokens: []
|
|
24
|
+
};
|
|
25
|
+
}
|
|
15
26
|
const slice = Array.isArray(atRule.tokens) ? atRule.tokens.slice() : [];
|
|
16
27
|
consumeWhitespace(slice);
|
|
17
28
|
if (slice.length == 0) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import config from './config.json.js';
|
|
2
|
-
import './parser/types.js';
|
|
3
2
|
import { parseSyntax } from './parser/parse.js';
|
|
4
3
|
|
|
5
4
|
const parsedSyntaxes = new Map();
|
|
@@ -51,7 +50,6 @@ function getParsedSyntax(group, key) {
|
|
|
51
50
|
const index = group + '.' + keys.join('.');
|
|
52
51
|
// @ts-ignore
|
|
53
52
|
if (!parsedSyntaxes.has(index)) {
|
|
54
|
-
// @ts-ignore
|
|
55
53
|
const syntax = parseSyntax(obj.syntax);
|
|
56
54
|
// @ts-ignore
|
|
57
55
|
parsedSyntaxes.set(index, syntax.chi);
|
|
@@ -753,7 +753,7 @@ var declarations = {
|
|
|
753
753
|
syntax: "[ <counter-name> <integer>? ]+ | none"
|
|
754
754
|
},
|
|
755
755
|
cursor: {
|
|
756
|
-
syntax: "[ [ <url> [ <x> <y> ]? , ]*
|
|
756
|
+
syntax: "[ [ <url> [ <x> <y> ]? , ]* <cursor-predefined> ] [ [ <url> [ <x> <y> ]? , ]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing | hand | -webkit-grab | -webkit-grabbing | -webkit-zoom-in | -webkit-zoom-out | -moz-grab | -moz-grabbing | -moz-zoom-in | -moz-zoom-out ] ]"
|
|
757
757
|
},
|
|
758
758
|
cx: {
|
|
759
759
|
syntax: "<length> | <percentage>"
|
|
@@ -1981,6 +1981,12 @@ var declarations = {
|
|
|
1981
1981
|
},
|
|
1982
1982
|
"white-space-trim": {
|
|
1983
1983
|
syntax: "none | discard-before || discard-after || discard-inner"
|
|
1984
|
+
},
|
|
1985
|
+
composes: {
|
|
1986
|
+
syntax: "<composes-selector>#"
|
|
1987
|
+
},
|
|
1988
|
+
"composes-selector": {
|
|
1989
|
+
syntax: "<ident>+ [from [global&&<string>]]?"
|
|
1984
1990
|
}
|
|
1985
1991
|
};
|
|
1986
1992
|
var functions = {
|
|
@@ -2006,7 +2012,7 @@ var functions = {
|
|
|
2006
2012
|
syntax: "atan2( <calc-sum>, <calc-sum> )"
|
|
2007
2013
|
},
|
|
2008
2014
|
attr: {
|
|
2009
|
-
syntax: "attr( <attr-name> <type
|
|
2015
|
+
syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
|
|
2010
2016
|
},
|
|
2011
2017
|
blur: {
|
|
2012
2018
|
syntax: "blur( <length>? )"
|
|
@@ -2359,7 +2365,7 @@ var syntaxes = {
|
|
|
2359
2365
|
syntax: "scroll | fixed | local"
|
|
2360
2366
|
},
|
|
2361
2367
|
"attr()": {
|
|
2362
|
-
syntax: "attr( <attr-name> <type
|
|
2368
|
+
syntax: "attr( <attr-name> <attr-type>? , <declaration-value>? )"
|
|
2363
2369
|
},
|
|
2364
2370
|
"attr-matcher": {
|
|
2365
2371
|
syntax: "[ '~' | '|' | '^' | '$' | '*' ]? '='"
|
|
@@ -2367,6 +2373,9 @@ var syntaxes = {
|
|
|
2367
2373
|
"attr-modifier": {
|
|
2368
2374
|
syntax: "i | s"
|
|
2369
2375
|
},
|
|
2376
|
+
"attr-type": {
|
|
2377
|
+
syntax: "type( <syntax> ) | raw-string | number | <attr-unit>"
|
|
2378
|
+
},
|
|
2370
2379
|
"attribute-selector": {
|
|
2371
2380
|
syntax: "'[' <wq-name> ']' | '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'"
|
|
2372
2381
|
},
|
|
@@ -2580,6 +2589,9 @@ var syntaxes = {
|
|
|
2580
2589
|
"cubic-bezier-easing-function": {
|
|
2581
2590
|
syntax: "ease | ease-in | ease-out | ease-in-out | cubic-bezier( <number [0,1]> , <number> , <number [0,1]> , <number> )"
|
|
2582
2591
|
},
|
|
2592
|
+
"cursor-predefined": {
|
|
2593
|
+
syntax: "auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out | grab | grabbing"
|
|
2594
|
+
},
|
|
2583
2595
|
"custom-color-space": {
|
|
2584
2596
|
syntax: "<dashed-ident>"
|
|
2585
2597
|
},
|
|
@@ -4190,7 +4202,27 @@ var atRules = {
|
|
|
4190
4202
|
}
|
|
4191
4203
|
},
|
|
4192
4204
|
"@nest": {
|
|
4193
|
-
|
|
4205
|
+
},
|
|
4206
|
+
"@stylistic": {
|
|
4207
|
+
syntax: " @stylistic { <feature-value-declaration-list> } "
|
|
4208
|
+
},
|
|
4209
|
+
"@historical-forms": {
|
|
4210
|
+
syntax: " @historical-forms { <feature-value-declaration-list> } "
|
|
4211
|
+
},
|
|
4212
|
+
"@styleset": {
|
|
4213
|
+
syntax: " @styleset { <feature-value-declaration-list> } "
|
|
4214
|
+
},
|
|
4215
|
+
"@character-variant": {
|
|
4216
|
+
syntax: " @character-variant { <feature-value-declaration-list> } "
|
|
4217
|
+
},
|
|
4218
|
+
"@swash": {
|
|
4219
|
+
syntax: " @swash { <feature-value-declaration-list> } "
|
|
4220
|
+
},
|
|
4221
|
+
"@ornaments": {
|
|
4222
|
+
syntax: " @ornaments { <feature-value-declaration-list> } "
|
|
4223
|
+
},
|
|
4224
|
+
"@annotation": {
|
|
4225
|
+
syntax: " @annotation { <feature-value-declaration-list> } "
|
|
4194
4226
|
}
|
|
4195
4227
|
};
|
|
4196
4228
|
var config = {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ValidationTokenEnum } from './types.js';
|
|
2
1
|
import { isIdent, isPseudo } from '../../syntax/syntax.js';
|
|
3
2
|
import { EnumToken } from '../../ast/types.js';
|
|
4
3
|
import '../../ast/minify.js';
|
|
@@ -9,6 +8,58 @@ import '../../parser/utils/config.js';
|
|
|
9
8
|
import '../../syntax/color/utils/constants.js';
|
|
10
9
|
import '../../renderer/sourcemap/lib/encode.js';
|
|
11
10
|
|
|
11
|
+
var ValidationTokenEnum;
|
|
12
|
+
(function (ValidationTokenEnum) {
|
|
13
|
+
ValidationTokenEnum[ValidationTokenEnum["Root"] = 0] = "Root";
|
|
14
|
+
ValidationTokenEnum[ValidationTokenEnum["Keyword"] = 1] = "Keyword";
|
|
15
|
+
ValidationTokenEnum[ValidationTokenEnum["PropertyType"] = 2] = "PropertyType";
|
|
16
|
+
ValidationTokenEnum[ValidationTokenEnum["DeclarationType"] = 3] = "DeclarationType";
|
|
17
|
+
ValidationTokenEnum[ValidationTokenEnum["AtRule"] = 4] = "AtRule";
|
|
18
|
+
ValidationTokenEnum[ValidationTokenEnum["ValidationFunctionDefinition"] = 5] = "ValidationFunctionDefinition";
|
|
19
|
+
ValidationTokenEnum[ValidationTokenEnum["OpenBracket"] = 6] = "OpenBracket";
|
|
20
|
+
ValidationTokenEnum[ValidationTokenEnum["CloseBracket"] = 7] = "CloseBracket";
|
|
21
|
+
ValidationTokenEnum[ValidationTokenEnum["OpenParenthesis"] = 8] = "OpenParenthesis";
|
|
22
|
+
ValidationTokenEnum[ValidationTokenEnum["CloseParenthesis"] = 9] = "CloseParenthesis";
|
|
23
|
+
ValidationTokenEnum[ValidationTokenEnum["Comma"] = 10] = "Comma";
|
|
24
|
+
ValidationTokenEnum[ValidationTokenEnum["Pipe"] = 11] = "Pipe";
|
|
25
|
+
ValidationTokenEnum[ValidationTokenEnum["Column"] = 12] = "Column";
|
|
26
|
+
ValidationTokenEnum[ValidationTokenEnum["Star"] = 13] = "Star";
|
|
27
|
+
ValidationTokenEnum[ValidationTokenEnum["OpenCurlyBrace"] = 14] = "OpenCurlyBrace";
|
|
28
|
+
ValidationTokenEnum[ValidationTokenEnum["CloseCurlyBrace"] = 15] = "CloseCurlyBrace";
|
|
29
|
+
ValidationTokenEnum[ValidationTokenEnum["HashMark"] = 16] = "HashMark";
|
|
30
|
+
ValidationTokenEnum[ValidationTokenEnum["QuestionMark"] = 17] = "QuestionMark";
|
|
31
|
+
ValidationTokenEnum[ValidationTokenEnum["Function"] = 18] = "Function";
|
|
32
|
+
ValidationTokenEnum[ValidationTokenEnum["Number"] = 19] = "Number";
|
|
33
|
+
ValidationTokenEnum[ValidationTokenEnum["Whitespace"] = 20] = "Whitespace";
|
|
34
|
+
ValidationTokenEnum[ValidationTokenEnum["Parenthesis"] = 21] = "Parenthesis";
|
|
35
|
+
ValidationTokenEnum[ValidationTokenEnum["Bracket"] = 22] = "Bracket";
|
|
36
|
+
ValidationTokenEnum[ValidationTokenEnum["Block"] = 23] = "Block";
|
|
37
|
+
ValidationTokenEnum[ValidationTokenEnum["AtLeastOnce"] = 24] = "AtLeastOnce";
|
|
38
|
+
ValidationTokenEnum[ValidationTokenEnum["Separator"] = 25] = "Separator";
|
|
39
|
+
ValidationTokenEnum[ValidationTokenEnum["Exclamation"] = 26] = "Exclamation";
|
|
40
|
+
ValidationTokenEnum[ValidationTokenEnum["Ampersand"] = 27] = "Ampersand";
|
|
41
|
+
ValidationTokenEnum[ValidationTokenEnum["PipeToken"] = 28] = "PipeToken";
|
|
42
|
+
ValidationTokenEnum[ValidationTokenEnum["ColumnToken"] = 29] = "ColumnToken";
|
|
43
|
+
ValidationTokenEnum[ValidationTokenEnum["AmpersandToken"] = 30] = "AmpersandToken";
|
|
44
|
+
ValidationTokenEnum[ValidationTokenEnum["Parens"] = 31] = "Parens";
|
|
45
|
+
ValidationTokenEnum[ValidationTokenEnum["PseudoClassToken"] = 32] = "PseudoClassToken";
|
|
46
|
+
ValidationTokenEnum[ValidationTokenEnum["PseudoClassFunctionToken"] = 33] = "PseudoClassFunctionToken";
|
|
47
|
+
ValidationTokenEnum[ValidationTokenEnum["StringToken"] = 34] = "StringToken";
|
|
48
|
+
ValidationTokenEnum[ValidationTokenEnum["AtRuleDefinition"] = 35] = "AtRuleDefinition";
|
|
49
|
+
ValidationTokenEnum[ValidationTokenEnum["DeclarationNameToken"] = 36] = "DeclarationNameToken";
|
|
50
|
+
ValidationTokenEnum[ValidationTokenEnum["DeclarationDefinitionToken"] = 37] = "DeclarationDefinitionToken";
|
|
51
|
+
ValidationTokenEnum[ValidationTokenEnum["SemiColon"] = 38] = "SemiColon";
|
|
52
|
+
ValidationTokenEnum[ValidationTokenEnum["Character"] = 39] = "Character";
|
|
53
|
+
ValidationTokenEnum[ValidationTokenEnum["InfinityToken"] = 40] = "InfinityToken";
|
|
54
|
+
})(ValidationTokenEnum || (ValidationTokenEnum = {}));
|
|
55
|
+
var ValidationSyntaxGroupEnum;
|
|
56
|
+
(function (ValidationSyntaxGroupEnum) {
|
|
57
|
+
ValidationSyntaxGroupEnum["Declarations"] = "declarations";
|
|
58
|
+
ValidationSyntaxGroupEnum["Functions"] = "functions";
|
|
59
|
+
ValidationSyntaxGroupEnum["Syntaxes"] = "syntaxes";
|
|
60
|
+
ValidationSyntaxGroupEnum["Selectors"] = "selectors";
|
|
61
|
+
ValidationSyntaxGroupEnum["AtRules"] = "atRules";
|
|
62
|
+
})(ValidationSyntaxGroupEnum || (ValidationSyntaxGroupEnum = {}));
|
|
12
63
|
const skipped = [
|
|
13
64
|
ValidationTokenEnum.Star,
|
|
14
65
|
ValidationTokenEnum.HashMark,
|
|
@@ -1040,4 +1091,4 @@ function minify(ast) {
|
|
|
1040
1091
|
return ast;
|
|
1041
1092
|
}
|
|
1042
1093
|
|
|
1043
|
-
export { parseSyntax, renderSyntax };
|
|
1094
|
+
export { ValidationSyntaxGroupEnum, ValidationTokenEnum, parseSyntax, renderSyntax };
|
|
@@ -1,22 +1,132 @@
|
|
|
1
|
-
import { ValidationTokenEnum } from './parser/
|
|
2
|
-
import {
|
|
3
|
-
import { EnumToken, SyntaxValidationResult, ColorType } from '../ast/types.js';
|
|
1
|
+
import { ValidationTokenEnum, renderSyntax } from './parser/parse.js';
|
|
2
|
+
import { SyntaxValidationResult, EnumToken, ColorType } from '../ast/types.js';
|
|
4
3
|
import '../ast/minify.js';
|
|
5
4
|
import '../ast/walk.js';
|
|
6
5
|
import '../parser/parse.js';
|
|
7
6
|
import '../parser/tokenize.js';
|
|
8
7
|
import '../parser/utils/config.js';
|
|
9
|
-
import { wildCardFuncs, isIdentColor, mathFuncs } from '../syntax/syntax.js';
|
|
8
|
+
import { wildCardFuncs, isIdentColor, mathFuncs, isColor } from '../syntax/syntax.js';
|
|
10
9
|
import { renderToken } from '../renderer/render.js';
|
|
11
10
|
import '../renderer/sourcemap/lib/encode.js';
|
|
12
11
|
import { getSyntaxConfig, getParsedSyntax, getSyntax } from './config.js';
|
|
13
12
|
import './syntaxes/complex-selector.js';
|
|
14
13
|
import { funcLike, colorsFunc } from '../syntax/color/utils/constants.js';
|
|
14
|
+
import '../../types.js';
|
|
15
15
|
import '../ast/features/type.js';
|
|
16
16
|
|
|
17
17
|
const config = getSyntaxConfig();
|
|
18
18
|
// @ts-ignore
|
|
19
19
|
const allValues = getSyntaxConfig()["declarations" /* ValidationSyntaxGroupEnum.Declarations */].all.syntax.trim().split(/[\s|]+/g);
|
|
20
|
+
/**
|
|
21
|
+
* Check if a node is allowed as child in a given context
|
|
22
|
+
* @param node
|
|
23
|
+
* @param context
|
|
24
|
+
*/
|
|
25
|
+
function isNodeAllowedInContext(node, context) {
|
|
26
|
+
if (node.typ == EnumToken.CommentNodeType || context == null) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
switch (context?.typ) {
|
|
30
|
+
case EnumToken.StyleSheetNodeType:
|
|
31
|
+
case EnumToken.RuleNodeType:
|
|
32
|
+
return node.typ == EnumToken.RuleNodeType ||
|
|
33
|
+
node.typ == EnumToken.AtRuleNodeType ||
|
|
34
|
+
node.typ == EnumToken.KeyframesAtRuleNodeType ||
|
|
35
|
+
(node.typ == EnumToken.DeclarationNodeType && context.typ == EnumToken.RuleNodeType) ||
|
|
36
|
+
(node.typ == EnumToken.CDOCOMMNodeType && context.typ == EnumToken.StyleSheetNodeType);
|
|
37
|
+
case EnumToken.KeyframesAtRuleNodeType:
|
|
38
|
+
return node.typ == EnumToken.KeyFramesRuleNodeType;
|
|
39
|
+
case EnumToken.KeyFramesRuleNodeType:
|
|
40
|
+
return node.typ == EnumToken.DeclarationNodeType;
|
|
41
|
+
case EnumToken.AtRuleNodeType:
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + context.nam)?.[0].chi ?? null;
|
|
44
|
+
//
|
|
45
|
+
if (syntax == null) {
|
|
46
|
+
// console.error(`syntax: Not found ${ValidationSyntaxGroupEnum.AtRules}@${(context as AstAtRule).nam}`);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
const stack = syntax.slice();
|
|
50
|
+
for (const child of stack) {
|
|
51
|
+
if (Array.isArray(child)) {
|
|
52
|
+
stack.push(...child);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if ('chi' in child && Array.isArray(child.chi)) {
|
|
56
|
+
stack.push(...child.chi);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
if (child.l != null) {
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
stack.push(child.l);
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
if (child.r != null) {
|
|
65
|
+
// @ts-ignore
|
|
66
|
+
stack.push(...(Array.isArray(child.r) ? child.r : [child.r]));
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
71
|
+
if (child.typ == ValidationTokenEnum.DeclarationDefinitionToken) {
|
|
72
|
+
if (node.nam == child.nam) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (child.typ == ValidationTokenEnum.PropertyType) {
|
|
78
|
+
if (['group-rule-body', 'block-contents', 'rule-list', 'stylesheet'].includes(child.val)) {
|
|
79
|
+
if ((node.typ == EnumToken.RuleNodeType ||
|
|
80
|
+
node.typ == EnumToken.AtRuleNodeType ||
|
|
81
|
+
node.typ == EnumToken.KeyframesAtRuleNodeType)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
85
|
+
let parent = node.parent;
|
|
86
|
+
while (parent != null) {
|
|
87
|
+
if (parent.parent?.typ == EnumToken.RuleNodeType) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
parent = parent.parent;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (['declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == EnumToken.DeclarationNodeType) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
if (child.val == 'page-body' && (node.typ == EnumToken.DeclarationNodeType || (node.typ == EnumToken.AtRuleNodeType && [
|
|
98
|
+
'top-left-corner', 'top-left', 'top-center', 'top-right', 'top-right-corner',
|
|
99
|
+
'bottom-left-corner', 'bottom-left', 'bottom-center', 'bottom-right', 'bottom-right-corner',
|
|
100
|
+
'left-top', 'left-middle', 'left-bottom', 'right-top', 'right-middle', 'right-bottom'
|
|
101
|
+
].includes(node.nam)))) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
if (child.val == 'feature-value-block-list' &&
|
|
105
|
+
(node.typ == EnumToken.AtRuleNodeType && ['stylistic', 'historical-forms', 'styleset', 'character-variant', 'swash', 'ornaments', 'annotation'].includes(node.nam))) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
if (['feature-value-declaration-list', 'feature-value-declaration'].includes(child.val) && node.typ == EnumToken.DeclarationNodeType) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
if (child.val == 'page-body') {
|
|
112
|
+
if (node.typ == EnumToken.DeclarationNodeType) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// console.error(`isNodeAllowedInContext: Not found ${(child as ValidationPropertyToken).val}`, {
|
|
117
|
+
// child,
|
|
118
|
+
// node
|
|
119
|
+
// });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Create a syntax validation context from a list of tokens
|
|
128
|
+
* @param input
|
|
129
|
+
*/
|
|
20
130
|
function createContext(input) {
|
|
21
131
|
const values = input.slice();
|
|
22
132
|
const result = values.filter(token => token.typ != EnumToken.CommentTokenType).slice();
|
|
@@ -77,7 +187,22 @@ function createContext(input) {
|
|
|
77
187
|
}
|
|
78
188
|
};
|
|
79
189
|
}
|
|
80
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Evaluate the validity of the syntax of a node
|
|
192
|
+
* @param node
|
|
193
|
+
* @param parent
|
|
194
|
+
* @param options
|
|
195
|
+
*/
|
|
196
|
+
function evaluateSyntax(node, parent, options) {
|
|
197
|
+
if (node.validSyntax) {
|
|
198
|
+
return {
|
|
199
|
+
valid: SyntaxValidationResult.Valid,
|
|
200
|
+
node,
|
|
201
|
+
syntax: null,
|
|
202
|
+
error: '',
|
|
203
|
+
context: []
|
|
204
|
+
};
|
|
205
|
+
}
|
|
81
206
|
let ast;
|
|
82
207
|
let result;
|
|
83
208
|
switch (node.typ) {
|
|
@@ -85,25 +210,34 @@ function evaluateSyntax(node, options) {
|
|
|
85
210
|
if (node.nam.startsWith('--')) {
|
|
86
211
|
break;
|
|
87
212
|
}
|
|
213
|
+
let token = null;
|
|
214
|
+
let values = node.val.slice();
|
|
88
215
|
ast = getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, node.nam);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
216
|
+
while (values.length > 0) {
|
|
217
|
+
token = values.at(-1);
|
|
218
|
+
if (token.typ == EnumToken.WhitespaceTokenType || token.typ == EnumToken.CommentTokenType) {
|
|
219
|
+
values.pop();
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
if (token.typ == EnumToken.ImportantTokenType) {
|
|
95
223
|
values.pop();
|
|
96
|
-
|
|
97
|
-
else {
|
|
98
|
-
if (token.typ == EnumToken.ImportantTokenType) {
|
|
224
|
+
if (values.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
|
|
99
225
|
values.pop();
|
|
100
|
-
if (values.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
|
|
101
|
-
values.pop();
|
|
102
|
-
}
|
|
103
226
|
}
|
|
104
|
-
|
|
227
|
+
}
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (ast == null) {
|
|
232
|
+
if (parent?.typ == EnumToken.AtRuleNodeType) {
|
|
233
|
+
ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]));
|
|
234
|
+
if (ast == null) {
|
|
235
|
+
ast = (getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, ['@' + parent.nam, 'descriptors', node.nam]) ?? getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + parent.nam))?.[0]?.chi;
|
|
236
|
+
values = [{ ...node, val: values }];
|
|
105
237
|
}
|
|
106
238
|
}
|
|
239
|
+
}
|
|
240
|
+
if (ast != null) {
|
|
107
241
|
result = doEvaluateSyntax(ast, createContext(values), { ...options, visited: new WeakMap() });
|
|
108
242
|
if (result.valid == SyntaxValidationResult.Valid && !result.context.done()) {
|
|
109
243
|
let token = null;
|
|
@@ -195,7 +329,7 @@ function doEvaluateSyntax(syntaxes, context, options) {
|
|
|
195
329
|
continue;
|
|
196
330
|
}
|
|
197
331
|
}
|
|
198
|
-
else if (options.
|
|
332
|
+
else if (options.occurrence !== false && syntax.occurence != null) {
|
|
199
333
|
result = matchOccurence(syntax, context, options);
|
|
200
334
|
}
|
|
201
335
|
else if (options.atLeastOnce !== false && syntax.atLeastOnce) {
|
|
@@ -284,7 +418,7 @@ function matchList(syntax, context, options) {
|
|
|
284
418
|
result = doEvaluateSyntax([syntax], createContext(tokens), {
|
|
285
419
|
...options,
|
|
286
420
|
isList: false,
|
|
287
|
-
|
|
421
|
+
occurrence: false
|
|
288
422
|
});
|
|
289
423
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
290
424
|
context = con.clone();
|
|
@@ -319,7 +453,7 @@ function matchOccurence(syntax, context, options) {
|
|
|
319
453
|
let counter = 0;
|
|
320
454
|
let result;
|
|
321
455
|
do {
|
|
322
|
-
result = match(syntax, context.clone(), { ...options,
|
|
456
|
+
result = match(syntax, context.clone(), { ...options, occurrence: false });
|
|
323
457
|
if (result.valid == SyntaxValidationResult.Drop) {
|
|
324
458
|
break;
|
|
325
459
|
}
|
|
@@ -370,7 +504,7 @@ function match(syntax, context, options) {
|
|
|
370
504
|
...options,
|
|
371
505
|
isRepeatable: null,
|
|
372
506
|
isList: null,
|
|
373
|
-
|
|
507
|
+
occurrence: null,
|
|
374
508
|
atLeastOnce: null
|
|
375
509
|
});
|
|
376
510
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
@@ -382,7 +516,7 @@ function match(syntax, context, options) {
|
|
|
382
516
|
case ValidationTokenEnum.Keyword:
|
|
383
517
|
success = (token.typ == EnumToken.IdenTokenType || token.typ == EnumToken.DashedIdenTokenType || isIdentColor(token)) &&
|
|
384
518
|
(token.val == syntax.val ||
|
|
385
|
-
syntax.val === token.val?.toLowerCase?.() ||
|
|
519
|
+
syntax.val.toLowerCase() === token.val?.toLowerCase?.() ||
|
|
386
520
|
// config.declarations.all
|
|
387
521
|
allValues.includes(token.val.toLowerCase()));
|
|
388
522
|
if (success) {
|
|
@@ -421,7 +555,7 @@ function match(syntax, context, options) {
|
|
|
421
555
|
...options,
|
|
422
556
|
isRepeatable: null,
|
|
423
557
|
isList: null,
|
|
424
|
-
|
|
558
|
+
occurrence: null,
|
|
425
559
|
atLeastOnce: null
|
|
426
560
|
});
|
|
427
561
|
case ValidationTokenEnum.Comma:
|
|
@@ -456,7 +590,7 @@ function match(syntax, context, options) {
|
|
|
456
590
|
...options,
|
|
457
591
|
isRepeatable: null,
|
|
458
592
|
isList: null,
|
|
459
|
-
|
|
593
|
+
occurrence: null,
|
|
460
594
|
atLeastOnce: null
|
|
461
595
|
}).valid == SyntaxValidationResult.Valid;
|
|
462
596
|
if (success) {
|
|
@@ -479,18 +613,20 @@ function match(syntax, context, options) {
|
|
|
479
613
|
}
|
|
480
614
|
function matchPropertyType(syntax, context, options) {
|
|
481
615
|
if (![
|
|
482
|
-
'
|
|
616
|
+
'color',
|
|
483
617
|
'integer',
|
|
618
|
+
'bg-position',
|
|
619
|
+
'composes-selector',
|
|
484
620
|
'length-percentage', 'flex', 'calc-sum', 'color',
|
|
485
621
|
'color-base', 'system-color', 'deprecated-system-color',
|
|
486
|
-
'pseudo-class-selector', 'pseudo-element-selector'
|
|
622
|
+
'pseudo-class-selector', 'pseudo-element-selector', 'feature-value-declaration'
|
|
487
623
|
].includes(syntax.val)) {
|
|
488
624
|
if (syntax.val in config["syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */]) {
|
|
489
625
|
return doEvaluateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, syntax.val), context, {
|
|
490
626
|
...options,
|
|
491
627
|
isRepeatable: null,
|
|
492
628
|
isList: null,
|
|
493
|
-
|
|
629
|
+
occurrence: null,
|
|
494
630
|
atLeastOnce: null
|
|
495
631
|
});
|
|
496
632
|
}
|
|
@@ -502,7 +638,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
502
638
|
...options,
|
|
503
639
|
isRepeatable: null,
|
|
504
640
|
isList: null,
|
|
505
|
-
|
|
641
|
+
occurrence: null,
|
|
506
642
|
atLeastOnce: null
|
|
507
643
|
});
|
|
508
644
|
if (result.valid == SyntaxValidationResult.Valid) {
|
|
@@ -511,6 +647,9 @@ function matchPropertyType(syntax, context, options) {
|
|
|
511
647
|
return { ...result, context };
|
|
512
648
|
}
|
|
513
649
|
switch (syntax.val) {
|
|
650
|
+
case 'composes-selector':
|
|
651
|
+
success = token.typ == EnumToken.ComposesSelectorNodeType;
|
|
652
|
+
break;
|
|
514
653
|
case 'bg-position': {
|
|
515
654
|
let val;
|
|
516
655
|
let keyworkMatchCount = 0;
|
|
@@ -607,6 +746,14 @@ function matchPropertyType(syntax, context, options) {
|
|
|
607
746
|
(token.typ == EnumToken.IdenTokenType && typeof Math[token.val.toUpperCase()] == 'number') ||
|
|
608
747
|
[EnumToken.BinaryExpressionTokenType, EnumToken.NumberTokenType, EnumToken.PercentageTokenType, EnumToken.DimensionTokenType, EnumToken.LengthTokenType, EnumToken.AngleTokenType, EnumToken.TimeTokenType, EnumToken.ResolutionTokenType, EnumToken.FrequencyTokenType].includes(token.typ);
|
|
609
748
|
break;
|
|
749
|
+
case 'declaration':
|
|
750
|
+
{
|
|
751
|
+
success = token.typ == EnumToken.DeclarationNodeType;
|
|
752
|
+
if (success) {
|
|
753
|
+
success = evaluateSyntax(token, null, options).valid == SyntaxValidationResult.Valid;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
break;
|
|
610
757
|
case 'declaration-value':
|
|
611
758
|
while (!context.done()) {
|
|
612
759
|
context.next();
|
|
@@ -633,13 +780,17 @@ function matchPropertyType(syntax, context, options) {
|
|
|
633
780
|
break;
|
|
634
781
|
case 'color':
|
|
635
782
|
case 'color-base':
|
|
636
|
-
success = token.typ == EnumToken.ColorTokenType ||
|
|
783
|
+
success = token.typ == EnumToken.ColorTokenType ||
|
|
784
|
+
(token.typ == EnumToken.IdenTokenType && 'currentcolor' === token.val.toLowerCase()) ||
|
|
785
|
+
(token.typ == EnumToken.IdenTokenType && 'transparent' === token.val.toLowerCase()) ||
|
|
786
|
+
(token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val) ||
|
|
787
|
+
isColor(token));
|
|
637
788
|
if (!success && token.typ == EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
|
|
638
789
|
success = doEvaluateSyntax(getParsedSyntax("functions" /* ValidationSyntaxGroupEnum.Functions */, token.val)?.[0]?.chi, createContext(token.chi), {
|
|
639
790
|
...options,
|
|
640
791
|
isRepeatable: null,
|
|
641
792
|
isList: null,
|
|
642
|
-
|
|
793
|
+
occurrence: null,
|
|
643
794
|
atLeastOnce: null
|
|
644
795
|
}).valid == SyntaxValidationResult.Valid;
|
|
645
796
|
}
|
|
@@ -647,8 +798,26 @@ function matchPropertyType(syntax, context, options) {
|
|
|
647
798
|
case 'hex-color':
|
|
648
799
|
success = (token.typ == EnumToken.ColorTokenType && token.kin == ColorType.HEX) || (token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val));
|
|
649
800
|
break;
|
|
801
|
+
case 'feature-value-declaration':
|
|
802
|
+
{
|
|
803
|
+
let hasNumber = false;
|
|
804
|
+
success = token.typ == EnumToken.DeclarationNodeType && token.val.length > 0 && token.val.every((val) => {
|
|
805
|
+
if (val.typ == EnumToken.WhitespaceTokenType || val.typ == EnumToken.CommentTokenType) {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
const success = (val.typ == EnumToken.NumberTokenType && Number.isInteger(+val.val) && val.val > 0) || (val.typ == EnumToken.FunctionTokenType && mathFuncs.includes(val.val.toLowerCase()) || (val.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(val.val)));
|
|
809
|
+
if (success) {
|
|
810
|
+
hasNumber = true;
|
|
811
|
+
}
|
|
812
|
+
if ('range' in syntax) {
|
|
813
|
+
return success && +val.val >= +syntax.range[0] && +val.val <= +syntax.range[1];
|
|
814
|
+
}
|
|
815
|
+
return success;
|
|
816
|
+
}) && hasNumber;
|
|
817
|
+
}
|
|
818
|
+
break;
|
|
650
819
|
case 'integer':
|
|
651
|
-
success = (token.typ == EnumToken.NumberTokenType &&
|
|
820
|
+
success = (token.typ == EnumToken.NumberTokenType && /^[+-]?\d+$/.test(token.val.toString())) || (token.typ == EnumToken.FunctionTokenType && mathFuncs.includes(token.val.toLowerCase()) || (token.typ == EnumToken.FunctionTokenType && wildCardFuncs.includes(token.val)));
|
|
652
821
|
if ('range' in syntax) {
|
|
653
822
|
success = success && +token.val >= +syntax.range[0] && +token.val <= +syntax.range[1];
|
|
654
823
|
}
|
|
@@ -712,7 +881,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
712
881
|
...options,
|
|
713
882
|
isRepeatable: null,
|
|
714
883
|
isList: null,
|
|
715
|
-
|
|
884
|
+
occurrence: null,
|
|
716
885
|
atLeastOnce: null
|
|
717
886
|
}).valid == SyntaxValidationResult.Valid;
|
|
718
887
|
}
|
|
@@ -728,7 +897,7 @@ function matchPropertyType(syntax, context, options) {
|
|
|
728
897
|
...options,
|
|
729
898
|
isRepeatable: null,
|
|
730
899
|
isList: null,
|
|
731
|
-
|
|
900
|
+
occurrence: null,
|
|
732
901
|
atLeastOnce: null
|
|
733
902
|
}).valid == SyntaxValidationResult.Valid;
|
|
734
903
|
}
|
|
@@ -875,7 +1044,6 @@ function allOf(syntax, context, options) {
|
|
|
875
1044
|
i = -1;
|
|
876
1045
|
}
|
|
877
1046
|
}
|
|
878
|
-
// console.error()
|
|
879
1047
|
const success = syntax.length == 0;
|
|
880
1048
|
return {
|
|
881
1049
|
valid: success ? SyntaxValidationResult.Valid : SyntaxValidationResult.Drop,
|
|
@@ -902,4 +1070,4 @@ function flatten(syntax) {
|
|
|
902
1070
|
return data;
|
|
903
1071
|
}
|
|
904
1072
|
|
|
905
|
-
export { createContext, doEvaluateSyntax, evaluateSyntax };
|
|
1073
|
+
export { createContext, doEvaluateSyntax, evaluateSyntax, isNodeAllowedInContext };
|
|
@@ -19,15 +19,12 @@ function validateRelativeSelectorList(tokens, root, options) {
|
|
|
19
19
|
return result;
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
// @ts-ignore
|
|
22
23
|
return {
|
|
23
24
|
valid: SyntaxValidationResult.Valid,
|
|
24
|
-
matches: [],
|
|
25
|
-
// @ts-ignore
|
|
26
25
|
node: root,
|
|
27
|
-
// @ts-ignore
|
|
28
26
|
syntax: null,
|
|
29
|
-
error: ''
|
|
30
|
-
tokens
|
|
27
|
+
error: ''
|
|
31
28
|
};
|
|
32
29
|
}
|
|
33
30
|
|