@eslint/css-tree 3.2.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 +20 -0
- package/README.md +194 -0
- package/cjs/convertor/create.cjs +32 -0
- package/cjs/convertor/index.cjs +8 -0
- package/cjs/data-patch.cjs +7 -0
- package/cjs/data.cjs +120 -0
- package/cjs/definition-syntax/SyntaxError.cjs +16 -0
- package/cjs/definition-syntax/generate.cjs +139 -0
- package/cjs/definition-syntax/index.cjs +13 -0
- package/cjs/definition-syntax/parse.cjs +556 -0
- package/cjs/definition-syntax/scanner.cjs +113 -0
- package/cjs/definition-syntax/walk.cjs +57 -0
- package/cjs/generator/create.cjs +102 -0
- package/cjs/generator/index.cjs +8 -0
- package/cjs/generator/sourceMap.cjs +96 -0
- package/cjs/generator/token-before.cjs +170 -0
- package/cjs/index.cjs +65 -0
- package/cjs/lexer/Lexer.cjs +517 -0
- package/cjs/lexer/error.cjs +128 -0
- package/cjs/lexer/generic-an-plus-b.cjs +235 -0
- package/cjs/lexer/generic-const.cjs +12 -0
- package/cjs/lexer/generic-urange.cjs +149 -0
- package/cjs/lexer/generic.cjs +589 -0
- package/cjs/lexer/index.cjs +7 -0
- package/cjs/lexer/match-graph.cjs +530 -0
- package/cjs/lexer/match.cjs +632 -0
- package/cjs/lexer/prepare-tokens.cjs +54 -0
- package/cjs/lexer/search.cjs +65 -0
- package/cjs/lexer/structure.cjs +173 -0
- package/cjs/lexer/trace.cjs +73 -0
- package/cjs/lexer/units.cjs +38 -0
- package/cjs/parser/SyntaxError.cjs +74 -0
- package/cjs/parser/create.cjs +378 -0
- package/cjs/parser/index.cjs +8 -0
- package/cjs/parser/parse-selector.cjs +8 -0
- package/cjs/parser/sequence.cjs +47 -0
- package/cjs/syntax/atrule/container.cjs +32 -0
- package/cjs/syntax/atrule/font-face.cjs +12 -0
- package/cjs/syntax/atrule/import.cjs +101 -0
- package/cjs/syntax/atrule/index.cjs +27 -0
- package/cjs/syntax/atrule/layer.cjs +16 -0
- package/cjs/syntax/atrule/media.cjs +16 -0
- package/cjs/syntax/atrule/nest.cjs +16 -0
- package/cjs/syntax/atrule/page.cjs +16 -0
- package/cjs/syntax/atrule/scope.cjs +16 -0
- package/cjs/syntax/atrule/starting-style.cjs +12 -0
- package/cjs/syntax/atrule/supports.cjs +16 -0
- package/cjs/syntax/config/generator.cjs +9 -0
- package/cjs/syntax/config/lexer.cjs +14 -0
- package/cjs/syntax/config/mix.cjs +126 -0
- package/cjs/syntax/config/parser-selector.cjs +19 -0
- package/cjs/syntax/config/parser.cjs +49 -0
- package/cjs/syntax/config/walker.cjs +9 -0
- package/cjs/syntax/create.cjs +58 -0
- package/cjs/syntax/function/expression.cjs +11 -0
- package/cjs/syntax/function/var.cjs +43 -0
- package/cjs/syntax/index.cjs +14 -0
- package/cjs/syntax/node/AnPlusB.cjs +293 -0
- package/cjs/syntax/node/Atrule.cjs +103 -0
- package/cjs/syntax/node/AtrulePrelude.cjs +52 -0
- package/cjs/syntax/node/AttributeSelector.cjs +148 -0
- package/cjs/syntax/node/Block.cjs +96 -0
- package/cjs/syntax/node/Brackets.cjs +38 -0
- package/cjs/syntax/node/CDC.cjs +26 -0
- package/cjs/syntax/node/CDO.cjs +26 -0
- package/cjs/syntax/node/ClassSelector.cjs +31 -0
- package/cjs/syntax/node/Combinator.cjs +61 -0
- package/cjs/syntax/node/Comment.cjs +40 -0
- package/cjs/syntax/node/Condition.cjs +120 -0
- package/cjs/syntax/node/Declaration.cjs +166 -0
- package/cjs/syntax/node/DeclarationList.cjs +62 -0
- package/cjs/syntax/node/Dimension.cjs +30 -0
- package/cjs/syntax/node/Feature.cjs +101 -0
- package/cjs/syntax/node/FeatureFunction.cjs +67 -0
- package/cjs/syntax/node/FeatureRange.cjs +133 -0
- package/cjs/syntax/node/Function.cjs +45 -0
- package/cjs/syntax/node/GeneralEnclosed.cjs +68 -0
- package/cjs/syntax/node/Hash.cjs +30 -0
- package/cjs/syntax/node/IdSelector.cjs +33 -0
- package/cjs/syntax/node/Identifier.cjs +25 -0
- package/cjs/syntax/node/Layer.cjs +35 -0
- package/cjs/syntax/node/LayerList.cjs +43 -0
- package/cjs/syntax/node/MediaQuery.cjs +100 -0
- package/cjs/syntax/node/MediaQueryList.cjs +41 -0
- package/cjs/syntax/node/NestingSelector.cjs +29 -0
- package/cjs/syntax/node/Nth.cjs +54 -0
- package/cjs/syntax/node/Number.cjs +25 -0
- package/cjs/syntax/node/Operator.cjs +28 -0
- package/cjs/syntax/node/Parentheses.cjs +38 -0
- package/cjs/syntax/node/Percentage.cjs +25 -0
- package/cjs/syntax/node/PseudoClassSelector.cjs +67 -0
- package/cjs/syntax/node/PseudoElementSelector.cjs +69 -0
- package/cjs/syntax/node/Ratio.cjs +71 -0
- package/cjs/syntax/node/Raw.cjs +48 -0
- package/cjs/syntax/node/Rule.cjs +58 -0
- package/cjs/syntax/node/Scope.cjs +69 -0
- package/cjs/syntax/node/Selector.cjs +38 -0
- package/cjs/syntax/node/SelectorList.cjs +43 -0
- package/cjs/syntax/node/String.cjs +26 -0
- package/cjs/syntax/node/StyleSheet.cjs +83 -0
- package/cjs/syntax/node/SupportsDeclaration.cjs +38 -0
- package/cjs/syntax/node/TypeSelector.cjs +59 -0
- package/cjs/syntax/node/UnicodeRange.cjs +158 -0
- package/cjs/syntax/node/Url.cjs +54 -0
- package/cjs/syntax/node/Value.cjs +26 -0
- package/cjs/syntax/node/WhiteSpace.cjs +34 -0
- package/cjs/syntax/node/index-generate.cjs +103 -0
- package/cjs/syntax/node/index-parse-selector.cjs +39 -0
- package/cjs/syntax/node/index-parse.cjs +103 -0
- package/cjs/syntax/node/index.cjs +103 -0
- package/cjs/syntax/pseudo/index.cjs +60 -0
- package/cjs/syntax/pseudo/lang.cjs +37 -0
- package/cjs/syntax/scope/atrulePrelude.cjs +9 -0
- package/cjs/syntax/scope/default.cjs +76 -0
- package/cjs/syntax/scope/index.cjs +11 -0
- package/cjs/syntax/scope/selector.cjs +88 -0
- package/cjs/syntax/scope/value.cjs +29 -0
- package/cjs/tokenizer/OffsetToLocation.cjs +91 -0
- package/cjs/tokenizer/TokenStream.cjs +358 -0
- package/cjs/tokenizer/adopt-buffer.cjs +13 -0
- package/cjs/tokenizer/char-code-definitions.cjs +236 -0
- package/cjs/tokenizer/index.cjs +554 -0
- package/cjs/tokenizer/names.cjs +32 -0
- package/cjs/tokenizer/types.cjs +57 -0
- package/cjs/tokenizer/utils.cjs +261 -0
- package/cjs/utils/List.cjs +473 -0
- package/cjs/utils/clone.cjs +25 -0
- package/cjs/utils/create-custom-error.cjs +18 -0
- package/cjs/utils/ident.cjs +102 -0
- package/cjs/utils/index.cjs +20 -0
- package/cjs/utils/names.cjs +113 -0
- package/cjs/utils/string.cjs +99 -0
- package/cjs/utils/url.cjs +108 -0
- package/cjs/version.cjs +5 -0
- package/cjs/walker/create.cjs +291 -0
- package/cjs/walker/index.cjs +8 -0
- package/data/patch.json +874 -0
- package/dist/csstree.esm.js +12 -0
- package/dist/csstree.js +12 -0
- package/dist/data.cjs +1341 -0
- package/dist/data.js +1341 -0
- package/dist/version.cjs +1 -0
- package/dist/version.js +1 -0
- package/lib/convertor/create.js +28 -0
- package/lib/convertor/index.js +4 -0
- package/lib/data-patch.js +6 -0
- package/lib/data.js +118 -0
- package/lib/definition-syntax/SyntaxError.js +12 -0
- package/lib/definition-syntax/generate.js +135 -0
- package/lib/definition-syntax/index.js +4 -0
- package/lib/definition-syntax/parse.js +552 -0
- package/lib/definition-syntax/scanner.js +109 -0
- package/lib/definition-syntax/walk.js +53 -0
- package/lib/generator/create.js +97 -0
- package/lib/generator/index.js +4 -0
- package/lib/generator/sourceMap.js +92 -0
- package/lib/generator/token-before.js +182 -0
- package/lib/index.d.ts +3016 -0
- package/lib/index.js +30 -0
- package/lib/lexer/Lexer.js +511 -0
- package/lib/lexer/error.js +123 -0
- package/lib/lexer/generic-an-plus-b.js +238 -0
- package/lib/lexer/generic-const.js +8 -0
- package/lib/lexer/generic-urange.js +151 -0
- package/lib/lexer/generic.js +622 -0
- package/lib/lexer/index.js +1 -0
- package/lib/lexer/match-graph.js +527 -0
- package/lib/lexer/match.js +630 -0
- package/lib/lexer/prepare-tokens.js +50 -0
- package/lib/lexer/search.js +61 -0
- package/lib/lexer/structure.js +169 -0
- package/lib/lexer/trace.js +66 -0
- package/lib/lexer/units.js +27 -0
- package/lib/parser/SyntaxError.js +70 -0
- package/lib/parser/create.js +388 -0
- package/lib/parser/index.js +4 -0
- package/lib/parser/parse-selector.js +4 -0
- package/lib/parser/sequence.js +43 -0
- package/lib/syntax/atrule/container.js +28 -0
- package/lib/syntax/atrule/font-face.js +8 -0
- package/lib/syntax/atrule/import.js +104 -0
- package/lib/syntax/atrule/index.js +23 -0
- package/lib/syntax/atrule/layer.js +12 -0
- package/lib/syntax/atrule/media.js +12 -0
- package/lib/syntax/atrule/nest.js +12 -0
- package/lib/syntax/atrule/page.js +12 -0
- package/lib/syntax/atrule/scope.js +12 -0
- package/lib/syntax/atrule/starting-style.js +8 -0
- package/lib/syntax/atrule/supports.js +12 -0
- package/lib/syntax/config/generator.js +5 -0
- package/lib/syntax/config/lexer.js +10 -0
- package/lib/syntax/config/mix.js +122 -0
- package/lib/syntax/config/parser-selector.js +15 -0
- package/lib/syntax/config/parser.js +45 -0
- package/lib/syntax/config/walker.js +5 -0
- package/lib/syntax/create.js +55 -0
- package/lib/syntax/function/expression.js +7 -0
- package/lib/syntax/function/var.js +39 -0
- package/lib/syntax/index.js +10 -0
- package/lib/syntax/node/AnPlusB.js +292 -0
- package/lib/syntax/node/Atrule.js +100 -0
- package/lib/syntax/node/AtrulePrelude.js +47 -0
- package/lib/syntax/node/AttributeSelector.js +147 -0
- package/lib/syntax/node/Block.js +95 -0
- package/lib/syntax/node/Brackets.js +35 -0
- package/lib/syntax/node/CDC.js +19 -0
- package/lib/syntax/node/CDO.js +19 -0
- package/lib/syntax/node/ClassSelector.js +24 -0
- package/lib/syntax/node/Combinator.js +54 -0
- package/lib/syntax/node/Comment.js +33 -0
- package/lib/syntax/node/Condition.js +123 -0
- package/lib/syntax/node/Declaration.js +165 -0
- package/lib/syntax/node/DeclarationList.js +62 -0
- package/lib/syntax/node/Dimension.js +23 -0
- package/lib/syntax/node/Feature.js +103 -0
- package/lib/syntax/node/FeatureFunction.js +63 -0
- package/lib/syntax/node/FeatureRange.js +133 -0
- package/lib/syntax/node/Function.js +41 -0
- package/lib/syntax/node/GeneralEnclosed.js +66 -0
- package/lib/syntax/node/Hash.js +23 -0
- package/lib/syntax/node/IdSelector.js +26 -0
- package/lib/syntax/node/Identifier.js +18 -0
- package/lib/syntax/node/Layer.js +28 -0
- package/lib/syntax/node/LayerList.js +36 -0
- package/lib/syntax/node/MediaQuery.js +102 -0
- package/lib/syntax/node/MediaQueryList.js +34 -0
- package/lib/syntax/node/NestingSelector.js +22 -0
- package/lib/syntax/node/Nth.js +47 -0
- package/lib/syntax/node/Number.js +18 -0
- package/lib/syntax/node/Operator.js +21 -0
- package/lib/syntax/node/Parentheses.js +34 -0
- package/lib/syntax/node/Percentage.js +18 -0
- package/lib/syntax/node/PseudoClassSelector.js +65 -0
- package/lib/syntax/node/PseudoElementSelector.js +66 -0
- package/lib/syntax/node/Ratio.js +68 -0
- package/lib/syntax/node/Raw.js +41 -0
- package/lib/syntax/node/Rule.js +51 -0
- package/lib/syntax/node/Scope.js +66 -0
- package/lib/syntax/node/Selector.js +31 -0
- package/lib/syntax/node/SelectorList.js +35 -0
- package/lib/syntax/node/String.js +19 -0
- package/lib/syntax/node/StyleSheet.js +82 -0
- package/lib/syntax/node/SupportsDeclaration.js +34 -0
- package/lib/syntax/node/TypeSelector.js +52 -0
- package/lib/syntax/node/UnicodeRange.js +156 -0
- package/lib/syntax/node/Url.js +52 -0
- package/lib/syntax/node/Value.js +19 -0
- package/lib/syntax/node/WhiteSpace.js +27 -0
- package/lib/syntax/node/index-generate.js +49 -0
- package/lib/syntax/node/index-parse-selector.js +17 -0
- package/lib/syntax/node/index-parse.js +49 -0
- package/lib/syntax/node/index.js +49 -0
- package/lib/syntax/pseudo/index.js +56 -0
- package/lib/syntax/pseudo/lang.js +33 -0
- package/lib/syntax/scope/atrulePrelude.js +5 -0
- package/lib/syntax/scope/default.js +85 -0
- package/lib/syntax/scope/index.js +3 -0
- package/lib/syntax/scope/selector.js +94 -0
- package/lib/syntax/scope/value.js +25 -0
- package/lib/tokenizer/OffsetToLocation.js +87 -0
- package/lib/tokenizer/TokenStream.js +366 -0
- package/lib/tokenizer/adopt-buffer.js +9 -0
- package/lib/tokenizer/char-code-definitions.js +212 -0
- package/lib/tokenizer/index.js +513 -0
- package/lib/tokenizer/names.js +28 -0
- package/lib/tokenizer/types.js +28 -0
- package/lib/tokenizer/utils.js +254 -0
- package/lib/utils/List.js +469 -0
- package/lib/utils/clone.js +21 -0
- package/lib/utils/create-custom-error.js +14 -0
- package/lib/utils/ident.js +101 -0
- package/lib/utils/index.js +6 -0
- package/lib/utils/names.js +106 -0
- package/lib/utils/string.js +99 -0
- package/lib/utils/url.js +108 -0
- package/lib/version.js +5 -0
- package/lib/walker/create.js +287 -0
- package/lib/walker/index.js +4 -0
- package/package.json +133 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { isCustomProperty } from '../../utils/names.js';
|
|
2
|
+
import {
|
|
3
|
+
Ident,
|
|
4
|
+
Hash,
|
|
5
|
+
Colon,
|
|
6
|
+
Semicolon,
|
|
7
|
+
Delim,
|
|
8
|
+
WhiteSpace
|
|
9
|
+
} from '../../tokenizer/index.js';
|
|
10
|
+
|
|
11
|
+
const EXCLAMATIONMARK = 0x0021; // U+0021 EXCLAMATION MARK (!)
|
|
12
|
+
const NUMBERSIGN = 0x0023; // U+0023 NUMBER SIGN (#)
|
|
13
|
+
const DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($)
|
|
14
|
+
const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
|
|
15
|
+
const ASTERISK = 0x002A; // U+002A ASTERISK (*)
|
|
16
|
+
const PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
|
|
17
|
+
const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
|
|
18
|
+
|
|
19
|
+
function consumeValueRaw() {
|
|
20
|
+
return this.Raw(this.consumeUntilExclamationMarkOrSemicolon, true);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function consumeCustomPropertyRaw() {
|
|
24
|
+
return this.Raw(this.consumeUntilExclamationMarkOrSemicolon, false);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function consumeValue() {
|
|
28
|
+
const startValueToken = this.tokenIndex;
|
|
29
|
+
const value = this.Value();
|
|
30
|
+
|
|
31
|
+
if (value.type !== 'Raw' &&
|
|
32
|
+
this.eof === false &&
|
|
33
|
+
this.tokenType !== Semicolon &&
|
|
34
|
+
this.isDelim(EXCLAMATIONMARK) === false &&
|
|
35
|
+
this.isBalanceEdge(startValueToken) === false) {
|
|
36
|
+
this.error();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const name = 'Declaration';
|
|
43
|
+
export const walkContext = 'declaration';
|
|
44
|
+
export const structure = {
|
|
45
|
+
important: [Boolean, String],
|
|
46
|
+
property: String,
|
|
47
|
+
value: ['Value', 'Raw']
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export function parse() {
|
|
51
|
+
const start = this.tokenStart;
|
|
52
|
+
const startToken = this.tokenIndex;
|
|
53
|
+
const property = readProperty.call(this);
|
|
54
|
+
const customProperty = isCustomProperty(property);
|
|
55
|
+
const parseValue = customProperty ? this.parseCustomProperty : this.parseValue;
|
|
56
|
+
const consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw;
|
|
57
|
+
let important = false;
|
|
58
|
+
let value;
|
|
59
|
+
|
|
60
|
+
this.skipSC();
|
|
61
|
+
this.eat(Colon);
|
|
62
|
+
|
|
63
|
+
const valueStart = this.tokenIndex;
|
|
64
|
+
|
|
65
|
+
if (!customProperty) {
|
|
66
|
+
this.skipSC();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (parseValue) {
|
|
70
|
+
value = this.parseWithFallback(consumeValue, consumeRaw);
|
|
71
|
+
} else {
|
|
72
|
+
value = consumeRaw.call(this, this.tokenIndex);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (customProperty && value.type === 'Value' && value.children.isEmpty) {
|
|
76
|
+
for (let offset = valueStart - this.tokenIndex; offset <= 0; offset++) {
|
|
77
|
+
if (this.lookupType(offset) === WhiteSpace) {
|
|
78
|
+
value.children.appendData({
|
|
79
|
+
type: 'WhiteSpace',
|
|
80
|
+
loc: null,
|
|
81
|
+
value: ' '
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this.isDelim(EXCLAMATIONMARK)) {
|
|
89
|
+
important = getImportant.call(this);
|
|
90
|
+
this.skipSC();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Do not include semicolon to range per spec
|
|
94
|
+
// https://drafts.csswg.org/css-syntax/#declaration-diagram
|
|
95
|
+
|
|
96
|
+
if (this.eof === false &&
|
|
97
|
+
this.tokenType !== Semicolon &&
|
|
98
|
+
this.isBalanceEdge(startToken) === false) {
|
|
99
|
+
this.error();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
type: 'Declaration',
|
|
104
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
105
|
+
important,
|
|
106
|
+
property,
|
|
107
|
+
value
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function generate(node) {
|
|
112
|
+
this.token(Ident, node.property);
|
|
113
|
+
this.token(Colon, ':');
|
|
114
|
+
this.node(node.value);
|
|
115
|
+
|
|
116
|
+
if (node.important) {
|
|
117
|
+
this.token(Delim, '!');
|
|
118
|
+
this.token(Ident, node.important === true ? 'important' : node.important);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function readProperty() {
|
|
123
|
+
const start = this.tokenStart;
|
|
124
|
+
|
|
125
|
+
// hacks
|
|
126
|
+
if (this.tokenType === Delim) {
|
|
127
|
+
switch (this.charCodeAt(this.tokenStart)) {
|
|
128
|
+
case ASTERISK:
|
|
129
|
+
case DOLLARSIGN:
|
|
130
|
+
case PLUSSIGN:
|
|
131
|
+
case NUMBERSIGN:
|
|
132
|
+
case AMPERSAND:
|
|
133
|
+
this.next();
|
|
134
|
+
break;
|
|
135
|
+
|
|
136
|
+
// TODO: not sure we should support this hack
|
|
137
|
+
case SOLIDUS:
|
|
138
|
+
this.next();
|
|
139
|
+
if (this.isDelim(SOLIDUS)) {
|
|
140
|
+
this.next();
|
|
141
|
+
}
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (this.tokenType === Hash) {
|
|
147
|
+
this.eat(Hash);
|
|
148
|
+
} else {
|
|
149
|
+
this.eat(Ident);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return this.substrToCursor(start);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ! ws* important
|
|
156
|
+
function getImportant() {
|
|
157
|
+
this.eat(Delim);
|
|
158
|
+
this.skipSC();
|
|
159
|
+
|
|
160
|
+
const important = this.consume(Ident);
|
|
161
|
+
|
|
162
|
+
// store original value in case it differ from `important`
|
|
163
|
+
// for better original source restoring and hacks like `!ie` support
|
|
164
|
+
return important === 'important' ? true : important;
|
|
165
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WhiteSpace,
|
|
3
|
+
Comment,
|
|
4
|
+
Semicolon,
|
|
5
|
+
AtKeyword
|
|
6
|
+
} from '../../tokenizer/index.js';
|
|
7
|
+
|
|
8
|
+
const AMPERSAND = 0x0026; // U+0026 AMPERSAND (&)
|
|
9
|
+
|
|
10
|
+
function consumeRaw() {
|
|
11
|
+
return this.Raw(this.consumeUntilSemicolonIncluded, true);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const name = 'DeclarationList';
|
|
15
|
+
export const structure = {
|
|
16
|
+
children: [[
|
|
17
|
+
'Declaration',
|
|
18
|
+
'Atrule',
|
|
19
|
+
'Rule'
|
|
20
|
+
]]
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function parse() {
|
|
24
|
+
const children = this.createList();
|
|
25
|
+
|
|
26
|
+
scan:
|
|
27
|
+
while (!this.eof) {
|
|
28
|
+
switch (this.tokenType) {
|
|
29
|
+
case WhiteSpace:
|
|
30
|
+
case Comment:
|
|
31
|
+
case Semicolon:
|
|
32
|
+
this.next();
|
|
33
|
+
break;
|
|
34
|
+
|
|
35
|
+
case AtKeyword:
|
|
36
|
+
children.push(this.parseWithFallback(this.Atrule.bind(this, true), consumeRaw));
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
default:
|
|
40
|
+
if (this.isDelim(AMPERSAND)) {
|
|
41
|
+
children.push(this.parseWithFallback(this.Rule, consumeRaw));
|
|
42
|
+
} else {
|
|
43
|
+
children.push(this.parseWithFallback(this.Declaration, consumeRaw));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
type: 'DeclarationList',
|
|
50
|
+
loc: this.getLocationFromList(children),
|
|
51
|
+
children
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function generate(node) {
|
|
56
|
+
this.children(node, prev => {
|
|
57
|
+
if (prev.type === 'Declaration') {
|
|
58
|
+
this.token(Semicolon, ';');
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Dimension } from '../../tokenizer/index.js';
|
|
2
|
+
|
|
3
|
+
export const name = 'Dimension';
|
|
4
|
+
export const structure = {
|
|
5
|
+
value: String,
|
|
6
|
+
unit: String
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export function parse() {
|
|
10
|
+
const start = this.tokenStart;
|
|
11
|
+
const value = this.consumeNumber(Dimension);
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
type: 'Dimension',
|
|
15
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
16
|
+
value,
|
|
17
|
+
unit: this.substring(start + value.length, this.tokenStart)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function generate(node) {
|
|
22
|
+
this.token(Dimension, node.value + node.unit);
|
|
23
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ident,
|
|
3
|
+
Number,
|
|
4
|
+
Dimension,
|
|
5
|
+
Function as FunctionToken,
|
|
6
|
+
LeftParenthesis,
|
|
7
|
+
RightParenthesis,
|
|
8
|
+
Colon,
|
|
9
|
+
Delim
|
|
10
|
+
} from '../../tokenizer/index.js';
|
|
11
|
+
|
|
12
|
+
const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
|
|
13
|
+
|
|
14
|
+
export const name = 'Feature';
|
|
15
|
+
export const structure = {
|
|
16
|
+
kind: String,
|
|
17
|
+
name: String,
|
|
18
|
+
value: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function', null]
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function parse(kind) {
|
|
22
|
+
const start = this.tokenStart;
|
|
23
|
+
let name;
|
|
24
|
+
let value = null;
|
|
25
|
+
|
|
26
|
+
this.eat(LeftParenthesis);
|
|
27
|
+
this.skipSC();
|
|
28
|
+
|
|
29
|
+
name = this.consume(Ident);
|
|
30
|
+
this.skipSC();
|
|
31
|
+
|
|
32
|
+
if (this.tokenType !== RightParenthesis) {
|
|
33
|
+
this.eat(Colon);
|
|
34
|
+
this.skipSC();
|
|
35
|
+
|
|
36
|
+
switch (this.tokenType) {
|
|
37
|
+
case Number:
|
|
38
|
+
if (this.lookupNonWSType(1) === Delim) {
|
|
39
|
+
value = this.Ratio();
|
|
40
|
+
} else {
|
|
41
|
+
value = this.Number();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
break;
|
|
45
|
+
|
|
46
|
+
case Dimension:
|
|
47
|
+
value = this.Dimension();
|
|
48
|
+
break;
|
|
49
|
+
|
|
50
|
+
case Ident:
|
|
51
|
+
value = this.Identifier();
|
|
52
|
+
break;
|
|
53
|
+
|
|
54
|
+
case FunctionToken:
|
|
55
|
+
value = this.parseWithFallback(
|
|
56
|
+
() => {
|
|
57
|
+
const res = this.Function(this.readSequence, this.scope.Value);
|
|
58
|
+
|
|
59
|
+
this.skipSC();
|
|
60
|
+
|
|
61
|
+
if (this.isDelim(SOLIDUS)) {
|
|
62
|
+
this.error();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return res;
|
|
66
|
+
},
|
|
67
|
+
() => {
|
|
68
|
+
return this.Ratio();
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
break;
|
|
72
|
+
|
|
73
|
+
default:
|
|
74
|
+
this.error('Number, dimension, ratio or identifier is expected');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.skipSC();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!this.eof) {
|
|
81
|
+
this.eat(RightParenthesis);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
type: 'Feature',
|
|
86
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
87
|
+
kind,
|
|
88
|
+
name,
|
|
89
|
+
value
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function generate(node) {
|
|
94
|
+
this.token(LeftParenthesis, '(');
|
|
95
|
+
this.token(Ident, node.name);
|
|
96
|
+
|
|
97
|
+
if (node.value !== null) {
|
|
98
|
+
this.token(Colon, ':');
|
|
99
|
+
this.node(node.value);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.token(RightParenthesis, ')');
|
|
103
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Function as FunctionToken,
|
|
3
|
+
RightParenthesis
|
|
4
|
+
} from '../../tokenizer/index.js';
|
|
5
|
+
|
|
6
|
+
export const name = 'FeatureFunction';
|
|
7
|
+
export const structure = {
|
|
8
|
+
kind: String,
|
|
9
|
+
feature: String,
|
|
10
|
+
value: ['Declaration', 'Selector']
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function getFeatureParser(kind, name) {
|
|
14
|
+
const featuresOfKind = this.features[kind] || {};
|
|
15
|
+
const parser = featuresOfKind[name];
|
|
16
|
+
|
|
17
|
+
if (typeof parser !== 'function') {
|
|
18
|
+
this.error(`Unknown feature ${name}()`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return parser;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function parse(kind = 'unknown') {
|
|
25
|
+
const start = this.tokenStart;
|
|
26
|
+
const functionName = this.consumeFunctionName();
|
|
27
|
+
const valueParser = getFeatureParser.call(this, kind, functionName.toLowerCase());
|
|
28
|
+
|
|
29
|
+
this.skipSC();
|
|
30
|
+
|
|
31
|
+
const value = this.parseWithFallback(
|
|
32
|
+
() => {
|
|
33
|
+
const startValueToken = this.tokenIndex;
|
|
34
|
+
const value = valueParser.call(this);
|
|
35
|
+
|
|
36
|
+
if (this.eof === false &&
|
|
37
|
+
this.isBalanceEdge(startValueToken) === false) {
|
|
38
|
+
this.error();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return value;
|
|
42
|
+
},
|
|
43
|
+
() => this.Raw(null, false)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
if (!this.eof) {
|
|
47
|
+
this.eat(RightParenthesis);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
type: 'FeatureFunction',
|
|
52
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
53
|
+
kind,
|
|
54
|
+
feature: functionName,
|
|
55
|
+
value
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function generate(node) {
|
|
60
|
+
this.token(FunctionToken, node.feature + '(');
|
|
61
|
+
this.node(node.value);
|
|
62
|
+
this.token(RightParenthesis, ')');
|
|
63
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ident,
|
|
3
|
+
Number,
|
|
4
|
+
Dimension,
|
|
5
|
+
Function as FunctionToken,
|
|
6
|
+
LeftParenthesis,
|
|
7
|
+
RightParenthesis
|
|
8
|
+
} from '../../tokenizer/index.js';
|
|
9
|
+
|
|
10
|
+
const SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
|
|
11
|
+
const LESSTHANSIGN = 0x003C; // U+003C LESS-THAN SIGN (<)
|
|
12
|
+
const EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)
|
|
13
|
+
const GREATERTHANSIGN = 0x003E; // U+003E GREATER-THAN SIGN (>)
|
|
14
|
+
|
|
15
|
+
export const name = 'FeatureRange';
|
|
16
|
+
export const structure = {
|
|
17
|
+
kind: String,
|
|
18
|
+
left: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function'],
|
|
19
|
+
leftComparison: String,
|
|
20
|
+
middle: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function'],
|
|
21
|
+
rightComparison: [String, null],
|
|
22
|
+
right: ['Identifier', 'Number', 'Dimension', 'Ratio', 'Function', null]
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function readTerm() {
|
|
26
|
+
this.skipSC();
|
|
27
|
+
|
|
28
|
+
switch (this.tokenType) {
|
|
29
|
+
case Number:
|
|
30
|
+
if (this.isDelim(SOLIDUS, this.lookupOffsetNonSC(1))) {
|
|
31
|
+
return this.Ratio();
|
|
32
|
+
} else {
|
|
33
|
+
return this.Number();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
case Dimension:
|
|
37
|
+
return this.Dimension();
|
|
38
|
+
|
|
39
|
+
case Ident:
|
|
40
|
+
return this.Identifier();
|
|
41
|
+
|
|
42
|
+
case FunctionToken:
|
|
43
|
+
return this.parseWithFallback(
|
|
44
|
+
() => {
|
|
45
|
+
const res = this.Function(this.readSequence, this.scope.Value);
|
|
46
|
+
|
|
47
|
+
this.skipSC();
|
|
48
|
+
|
|
49
|
+
if (this.isDelim(SOLIDUS)) {
|
|
50
|
+
this.error();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return res;
|
|
54
|
+
},
|
|
55
|
+
() => {
|
|
56
|
+
return this.Ratio();
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
default:
|
|
61
|
+
this.error('Number, dimension, ratio or identifier is expected');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function readComparison(expectColon) {
|
|
66
|
+
this.skipSC();
|
|
67
|
+
|
|
68
|
+
if (this.isDelim(LESSTHANSIGN) ||
|
|
69
|
+
this.isDelim(GREATERTHANSIGN)) {
|
|
70
|
+
const value = this.source[this.tokenStart];
|
|
71
|
+
|
|
72
|
+
this.next();
|
|
73
|
+
|
|
74
|
+
if (this.isDelim(EQUALSSIGN)) {
|
|
75
|
+
this.next();
|
|
76
|
+
return value + '=';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (this.isDelim(EQUALSSIGN)) {
|
|
83
|
+
return '=';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.error(`Expected ${expectColon ? '":", ' : ''}"<", ">", "=" or ")"`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function parse(kind = 'unknown') {
|
|
90
|
+
const start = this.tokenStart;
|
|
91
|
+
|
|
92
|
+
this.skipSC();
|
|
93
|
+
this.eat(LeftParenthesis);
|
|
94
|
+
|
|
95
|
+
const left = readTerm.call(this);
|
|
96
|
+
const leftComparison = readComparison.call(this, left.type === 'Identifier');
|
|
97
|
+
const middle = readTerm.call(this);
|
|
98
|
+
let rightComparison = null;
|
|
99
|
+
let right = null;
|
|
100
|
+
|
|
101
|
+
if (this.lookupNonWSType(0) !== RightParenthesis) {
|
|
102
|
+
rightComparison = readComparison.call(this);
|
|
103
|
+
right = readTerm.call(this);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.skipSC();
|
|
107
|
+
this.eat(RightParenthesis);
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
type: 'FeatureRange',
|
|
111
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
112
|
+
kind,
|
|
113
|
+
left,
|
|
114
|
+
leftComparison,
|
|
115
|
+
middle,
|
|
116
|
+
rightComparison,
|
|
117
|
+
right
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function generate(node) {
|
|
122
|
+
this.token(LeftParenthesis, '(');
|
|
123
|
+
this.node(node.left);
|
|
124
|
+
this.tokenize(node.leftComparison);
|
|
125
|
+
this.node(node.middle);
|
|
126
|
+
|
|
127
|
+
if (node.right) {
|
|
128
|
+
this.tokenize(node.rightComparison);
|
|
129
|
+
this.node(node.right);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.token(RightParenthesis, ')');
|
|
133
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Function as FunctionToken,
|
|
3
|
+
RightParenthesis
|
|
4
|
+
} from '../../tokenizer/index.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export const name = 'Function';
|
|
8
|
+
export const walkContext = 'function';
|
|
9
|
+
export const structure = {
|
|
10
|
+
name: String,
|
|
11
|
+
children: [[]]
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// <function-token> <sequence> )
|
|
15
|
+
export function parse(readSequence, recognizer) {
|
|
16
|
+
const start = this.tokenStart;
|
|
17
|
+
const name = this.consumeFunctionName();
|
|
18
|
+
const nameLowerCase = name.toLowerCase();
|
|
19
|
+
let children;
|
|
20
|
+
|
|
21
|
+
children = recognizer.hasOwnProperty(nameLowerCase)
|
|
22
|
+
? recognizer[nameLowerCase].call(this, recognizer)
|
|
23
|
+
: readSequence.call(this, recognizer);
|
|
24
|
+
|
|
25
|
+
if (!this.eof) {
|
|
26
|
+
this.eat(RightParenthesis);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
type: 'Function',
|
|
31
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
32
|
+
name,
|
|
33
|
+
children
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function generate(node) {
|
|
38
|
+
this.token(FunctionToken, node.name + '(');
|
|
39
|
+
this.children(node);
|
|
40
|
+
this.token(RightParenthesis, ')');
|
|
41
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Function as FunctionToken,
|
|
3
|
+
LeftParenthesis,
|
|
4
|
+
RightParenthesis
|
|
5
|
+
} from '../../tokenizer/index.js';
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const name = 'GeneralEnclosed';
|
|
9
|
+
export const structure = {
|
|
10
|
+
kind: String,
|
|
11
|
+
function: [String, null],
|
|
12
|
+
children: [[]]
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// <function-token> <any-value> )
|
|
16
|
+
// ( <any-value> )
|
|
17
|
+
export function parse(kind) {
|
|
18
|
+
const start = this.tokenStart;
|
|
19
|
+
let functionName = null;
|
|
20
|
+
|
|
21
|
+
if (this.tokenType === FunctionToken) {
|
|
22
|
+
functionName = this.consumeFunctionName();
|
|
23
|
+
} else {
|
|
24
|
+
this.eat(LeftParenthesis);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const children = this.parseWithFallback(
|
|
28
|
+
() => {
|
|
29
|
+
const startValueToken = this.tokenIndex;
|
|
30
|
+
const children = this.readSequence(this.scope.Value);
|
|
31
|
+
|
|
32
|
+
if (this.eof === false &&
|
|
33
|
+
this.isBalanceEdge(startValueToken) === false) {
|
|
34
|
+
this.error();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return children;
|
|
38
|
+
},
|
|
39
|
+
() => this.createSingleNodeList(
|
|
40
|
+
this.Raw(null, false)
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (!this.eof) {
|
|
45
|
+
this.eat(RightParenthesis);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
type: 'GeneralEnclosed',
|
|
50
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
51
|
+
kind,
|
|
52
|
+
function: functionName,
|
|
53
|
+
children
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function generate(node) {
|
|
58
|
+
if (node.function) {
|
|
59
|
+
this.token(FunctionToken, node.function + '(');
|
|
60
|
+
} else {
|
|
61
|
+
this.token(LeftParenthesis, '(');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.children(node);
|
|
65
|
+
this.token(RightParenthesis, ')');
|
|
66
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Hash } from '../../tokenizer/index.js';
|
|
2
|
+
|
|
3
|
+
// '#' ident
|
|
4
|
+
export const xxx = 'XXX';
|
|
5
|
+
export const name = 'Hash';
|
|
6
|
+
export const structure = {
|
|
7
|
+
value: String
|
|
8
|
+
};
|
|
9
|
+
export function parse() {
|
|
10
|
+
const start = this.tokenStart;
|
|
11
|
+
|
|
12
|
+
this.eat(Hash);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
type: 'Hash',
|
|
16
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
17
|
+
value: this.substrToCursor(start + 1)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function generate(node) {
|
|
21
|
+
this.token(Hash, '#' + node.value);
|
|
22
|
+
}
|
|
23
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Hash, Delim } from '../../tokenizer/index.js';
|
|
2
|
+
|
|
3
|
+
export const name = 'IdSelector';
|
|
4
|
+
export const structure = {
|
|
5
|
+
name: String
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export function parse() {
|
|
9
|
+
const start = this.tokenStart;
|
|
10
|
+
|
|
11
|
+
// TODO: check value is an ident
|
|
12
|
+
this.eat(Hash);
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
type: 'IdSelector',
|
|
16
|
+
loc: this.getLocation(start, this.tokenStart),
|
|
17
|
+
name: this.substrToCursor(start + 1)
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function generate(node) {
|
|
22
|
+
// Using Delim instead of Hash is a hack to avoid for a whitespace between ident and id-selector
|
|
23
|
+
// in safe mode (e.g. "a#id"), because IE11 doesn't allow a sequence <ident-token> <hash-token>
|
|
24
|
+
// without a whitespace in values (e.g. "1px solid#000")
|
|
25
|
+
this.token(Delim, '#' + node.name);
|
|
26
|
+
}
|