@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,366 @@
|
|
|
1
|
+
import { adoptBuffer } from './adopt-buffer.js';
|
|
2
|
+
import { cmpStr } from './utils.js';
|
|
3
|
+
import tokenNames from './names.js';
|
|
4
|
+
import {
|
|
5
|
+
WhiteSpace,
|
|
6
|
+
Comment,
|
|
7
|
+
Delim,
|
|
8
|
+
EOF,
|
|
9
|
+
Function as FunctionToken,
|
|
10
|
+
LeftParenthesis,
|
|
11
|
+
RightParenthesis,
|
|
12
|
+
LeftSquareBracket,
|
|
13
|
+
RightSquareBracket,
|
|
14
|
+
LeftCurlyBracket,
|
|
15
|
+
RightCurlyBracket
|
|
16
|
+
} from './types.js';
|
|
17
|
+
|
|
18
|
+
const OFFSET_MASK = 0x00FFFFFF;
|
|
19
|
+
const TYPE_SHIFT = 24;
|
|
20
|
+
const BLOCK_OPEN_TOKEN = 1;
|
|
21
|
+
const BLOCK_CLOSE_TOKEN = 2;
|
|
22
|
+
const balancePair = new Uint8Array(32); // 32b of memory ought to be enough for anyone (any number of tokens)
|
|
23
|
+
balancePair[FunctionToken] = RightParenthesis;
|
|
24
|
+
balancePair[LeftParenthesis] = RightParenthesis;
|
|
25
|
+
balancePair[LeftSquareBracket] = RightSquareBracket;
|
|
26
|
+
balancePair[LeftCurlyBracket] = RightCurlyBracket;
|
|
27
|
+
|
|
28
|
+
const blockTokens = new Uint8Array(32);
|
|
29
|
+
blockTokens[FunctionToken] = BLOCK_OPEN_TOKEN;
|
|
30
|
+
blockTokens[LeftParenthesis] = BLOCK_OPEN_TOKEN;
|
|
31
|
+
blockTokens[LeftSquareBracket] = BLOCK_OPEN_TOKEN;
|
|
32
|
+
blockTokens[LeftCurlyBracket] = BLOCK_OPEN_TOKEN;
|
|
33
|
+
blockTokens[RightParenthesis] = BLOCK_CLOSE_TOKEN;
|
|
34
|
+
blockTokens[RightSquareBracket] = BLOCK_CLOSE_TOKEN;
|
|
35
|
+
blockTokens[RightCurlyBracket] = BLOCK_CLOSE_TOKEN;
|
|
36
|
+
|
|
37
|
+
function boundIndex(index, min, max) {
|
|
38
|
+
return index < min ? min : index > max ? max : index;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export class TokenStream {
|
|
42
|
+
constructor(source, tokenize) {
|
|
43
|
+
this.setSource(source, tokenize);
|
|
44
|
+
}
|
|
45
|
+
reset() {
|
|
46
|
+
this.eof = false;
|
|
47
|
+
this.tokenIndex = -1;
|
|
48
|
+
this.tokenType = 0;
|
|
49
|
+
this.tokenStart = this.firstCharOffset;
|
|
50
|
+
this.tokenEnd = this.firstCharOffset;
|
|
51
|
+
}
|
|
52
|
+
setSource(source = '', tokenize = () => {}) {
|
|
53
|
+
source = String(source || '');
|
|
54
|
+
|
|
55
|
+
const sourceLength = source.length;
|
|
56
|
+
const offsetAndType = adoptBuffer(this.offsetAndType, source.length + 1); // +1 because of eof-token
|
|
57
|
+
const balance = adoptBuffer(this.balance, source.length + 1);
|
|
58
|
+
let tokenCount = 0;
|
|
59
|
+
let firstCharOffset = -1;
|
|
60
|
+
let balanceCloseType = 0;
|
|
61
|
+
let balanceStart = source.length;
|
|
62
|
+
|
|
63
|
+
// capture buffers
|
|
64
|
+
this.offsetAndType = null;
|
|
65
|
+
this.balance = null;
|
|
66
|
+
balance.fill(0);
|
|
67
|
+
|
|
68
|
+
tokenize(source, (type, start, end) => {
|
|
69
|
+
const index = tokenCount++;
|
|
70
|
+
|
|
71
|
+
// type & offset
|
|
72
|
+
offsetAndType[index] = (type << TYPE_SHIFT) | end;
|
|
73
|
+
|
|
74
|
+
if (firstCharOffset === -1) {
|
|
75
|
+
firstCharOffset = start;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// balance
|
|
79
|
+
balance[index] = balanceStart;
|
|
80
|
+
|
|
81
|
+
if (type === balanceCloseType) {
|
|
82
|
+
const prevBalanceStart = balance[balanceStart];
|
|
83
|
+
|
|
84
|
+
// set reference to balance end for a block opener
|
|
85
|
+
balance[balanceStart] = index;
|
|
86
|
+
|
|
87
|
+
// pop state
|
|
88
|
+
balanceStart = prevBalanceStart;
|
|
89
|
+
balanceCloseType = balancePair[offsetAndType[prevBalanceStart] >> TYPE_SHIFT];
|
|
90
|
+
} else if (this.isBlockOpenerTokenType(type)) { // check for FunctionToken, <(-token>, <[-token> and <{-token>
|
|
91
|
+
// push state
|
|
92
|
+
balanceStart = index;
|
|
93
|
+
balanceCloseType = balancePair[type];
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// finalize buffers
|
|
98
|
+
offsetAndType[tokenCount] = (EOF << TYPE_SHIFT) | sourceLength; // <EOF-token>
|
|
99
|
+
balance[tokenCount] = tokenCount; // prevents false positive balance match with any token
|
|
100
|
+
|
|
101
|
+
// reverse references from balance start to end
|
|
102
|
+
// tokens
|
|
103
|
+
// token: a ( [ b c ] d e ) {
|
|
104
|
+
// index: 0 1 2 3 4 5 6 7 8 9
|
|
105
|
+
// before
|
|
106
|
+
// balance: 0 8 5 2 2 2 1 1 1 0
|
|
107
|
+
// - > > < < < < < < -
|
|
108
|
+
// after
|
|
109
|
+
// balance: 9 8 5 5 5 2 8 8 1 9
|
|
110
|
+
// > > > > > < > > < >
|
|
111
|
+
for (let i = 0; i < tokenCount; i++) {
|
|
112
|
+
const balanceStart = balance[i];
|
|
113
|
+
|
|
114
|
+
if (balanceStart <= i) {
|
|
115
|
+
const balanceEnd = balance[balanceStart];
|
|
116
|
+
|
|
117
|
+
if (balanceEnd !== i) {
|
|
118
|
+
balance[i] = balanceEnd;
|
|
119
|
+
}
|
|
120
|
+
} else if (balanceStart > tokenCount) {
|
|
121
|
+
balance[i] = tokenCount;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// balance[0] = tokenCount;
|
|
126
|
+
|
|
127
|
+
this.source = source;
|
|
128
|
+
this.firstCharOffset = firstCharOffset === -1 ? 0 : firstCharOffset;
|
|
129
|
+
this.tokenCount = tokenCount;
|
|
130
|
+
this.offsetAndType = offsetAndType;
|
|
131
|
+
this.balance = balance;
|
|
132
|
+
|
|
133
|
+
this.reset();
|
|
134
|
+
this.next();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
lookupType(offset) {
|
|
138
|
+
offset += this.tokenIndex;
|
|
139
|
+
|
|
140
|
+
if (offset < this.tokenCount) {
|
|
141
|
+
return this.offsetAndType[offset] >> TYPE_SHIFT;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return EOF;
|
|
145
|
+
}
|
|
146
|
+
lookupTypeNonSC(idx) {
|
|
147
|
+
for (let offset = this.tokenIndex; offset < this.tokenCount; offset++) {
|
|
148
|
+
const tokenType = this.offsetAndType[offset] >> TYPE_SHIFT;
|
|
149
|
+
|
|
150
|
+
if (tokenType !== WhiteSpace && tokenType !== Comment) {
|
|
151
|
+
if (idx-- === 0) {
|
|
152
|
+
return tokenType;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return EOF;
|
|
158
|
+
}
|
|
159
|
+
lookupOffset(offset) {
|
|
160
|
+
offset += this.tokenIndex;
|
|
161
|
+
|
|
162
|
+
if (offset < this.tokenCount) {
|
|
163
|
+
return this.offsetAndType[offset - 1] & OFFSET_MASK;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return this.source.length;
|
|
167
|
+
}
|
|
168
|
+
lookupOffsetNonSC(idx) {
|
|
169
|
+
for (let offset = this.tokenIndex; offset < this.tokenCount; offset++) {
|
|
170
|
+
const tokenType = this.offsetAndType[offset] >> TYPE_SHIFT;
|
|
171
|
+
|
|
172
|
+
if (tokenType !== WhiteSpace && tokenType !== Comment) {
|
|
173
|
+
if (idx-- === 0) {
|
|
174
|
+
return offset - this.tokenIndex;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return EOF;
|
|
180
|
+
}
|
|
181
|
+
lookupValue(offset, referenceStr) {
|
|
182
|
+
offset += this.tokenIndex;
|
|
183
|
+
|
|
184
|
+
if (offset < this.tokenCount) {
|
|
185
|
+
return cmpStr(
|
|
186
|
+
this.source,
|
|
187
|
+
this.offsetAndType[offset - 1] & OFFSET_MASK,
|
|
188
|
+
this.offsetAndType[offset] & OFFSET_MASK,
|
|
189
|
+
referenceStr
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
getTokenStart(tokenIndex) {
|
|
196
|
+
if (tokenIndex === this.tokenIndex) {
|
|
197
|
+
return this.tokenStart;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (tokenIndex > 0) {
|
|
201
|
+
return tokenIndex < this.tokenCount
|
|
202
|
+
? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK
|
|
203
|
+
: this.offsetAndType[this.tokenCount] & OFFSET_MASK;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return this.firstCharOffset;
|
|
207
|
+
}
|
|
208
|
+
getTokenEnd(tokenIndex) {
|
|
209
|
+
if (tokenIndex === this.tokenIndex) {
|
|
210
|
+
return this.tokenEnd;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return this.offsetAndType[boundIndex(tokenIndex, 0, this.tokenCount)] & OFFSET_MASK;
|
|
214
|
+
}
|
|
215
|
+
getTokenType(tokenIndex) {
|
|
216
|
+
if (tokenIndex === this.tokenIndex) {
|
|
217
|
+
return this.tokenType;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return this.offsetAndType[boundIndex(tokenIndex, 0, this.tokenCount)] >> TYPE_SHIFT;
|
|
221
|
+
}
|
|
222
|
+
substrToCursor(start) {
|
|
223
|
+
return this.source.substring(start, this.tokenStart);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
isBlockOpenerTokenType(tokenType) {
|
|
227
|
+
return blockTokens[tokenType] === BLOCK_OPEN_TOKEN;
|
|
228
|
+
}
|
|
229
|
+
isBlockCloserTokenType(tokenType) {
|
|
230
|
+
return blockTokens[tokenType] === BLOCK_CLOSE_TOKEN;
|
|
231
|
+
}
|
|
232
|
+
getBlockTokenPairIndex(tokenIndex) {
|
|
233
|
+
const type = this.getTokenType(tokenIndex);
|
|
234
|
+
|
|
235
|
+
if (blockTokens[type] === 1) {
|
|
236
|
+
// block open token
|
|
237
|
+
const pairIndex = this.balance[tokenIndex];
|
|
238
|
+
const closeType = this.getTokenType(pairIndex);
|
|
239
|
+
|
|
240
|
+
return balancePair[type] === closeType ? pairIndex : -1;
|
|
241
|
+
} else if (blockTokens[type] === 2) {
|
|
242
|
+
// block close token
|
|
243
|
+
const pairIndex = this.balance[tokenIndex];
|
|
244
|
+
const openType = this.getTokenType(pairIndex);
|
|
245
|
+
|
|
246
|
+
return balancePair[openType] === type ? pairIndex : -1;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return -1;
|
|
250
|
+
}
|
|
251
|
+
isBalanceEdge(tokenIndex) {
|
|
252
|
+
return this.balance[this.tokenIndex] < tokenIndex;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
isDelim(code, offset) {
|
|
256
|
+
if (offset) {
|
|
257
|
+
return (
|
|
258
|
+
this.lookupType(offset) === Delim &&
|
|
259
|
+
this.source.charCodeAt(this.lookupOffset(offset)) === code
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return (
|
|
264
|
+
this.tokenType === Delim &&
|
|
265
|
+
this.source.charCodeAt(this.tokenStart) === code
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
skip(tokenCount) {
|
|
270
|
+
let next = this.tokenIndex + tokenCount;
|
|
271
|
+
|
|
272
|
+
if (next < this.tokenCount) {
|
|
273
|
+
this.tokenIndex = next;
|
|
274
|
+
this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
|
|
275
|
+
next = this.offsetAndType[next];
|
|
276
|
+
this.tokenType = next >> TYPE_SHIFT;
|
|
277
|
+
this.tokenEnd = next & OFFSET_MASK;
|
|
278
|
+
} else {
|
|
279
|
+
this.tokenIndex = this.tokenCount;
|
|
280
|
+
this.next();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
next() {
|
|
284
|
+
let next = this.tokenIndex + 1;
|
|
285
|
+
|
|
286
|
+
if (next < this.tokenCount) {
|
|
287
|
+
this.tokenIndex = next;
|
|
288
|
+
this.tokenStart = this.tokenEnd;
|
|
289
|
+
next = this.offsetAndType[next];
|
|
290
|
+
this.tokenType = next >> TYPE_SHIFT;
|
|
291
|
+
this.tokenEnd = next & OFFSET_MASK;
|
|
292
|
+
} else {
|
|
293
|
+
this.eof = true;
|
|
294
|
+
this.tokenIndex = this.tokenCount;
|
|
295
|
+
this.tokenType = EOF;
|
|
296
|
+
this.tokenStart = this.tokenEnd = this.source.length;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
skipSC() {
|
|
300
|
+
while (this.tokenType === WhiteSpace || this.tokenType === Comment) {
|
|
301
|
+
this.next();
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
skipUntilBalanced(startToken, stopConsume) {
|
|
305
|
+
let cursor = startToken;
|
|
306
|
+
let balanceEnd = 0;
|
|
307
|
+
let offset = 0;
|
|
308
|
+
|
|
309
|
+
loop:
|
|
310
|
+
for (; cursor < this.tokenCount; cursor++) {
|
|
311
|
+
balanceEnd = this.balance[cursor];
|
|
312
|
+
|
|
313
|
+
// stop scanning on balance edge that points to offset before start token
|
|
314
|
+
if (balanceEnd < startToken) {
|
|
315
|
+
break loop;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
offset = cursor > 0 ? this.offsetAndType[cursor - 1] & OFFSET_MASK : this.firstCharOffset;
|
|
319
|
+
|
|
320
|
+
// check stop condition
|
|
321
|
+
switch (stopConsume(this.source.charCodeAt(offset))) {
|
|
322
|
+
case 1: // just stop
|
|
323
|
+
break loop;
|
|
324
|
+
|
|
325
|
+
case 2: // stop & included
|
|
326
|
+
cursor++;
|
|
327
|
+
break loop;
|
|
328
|
+
|
|
329
|
+
default:
|
|
330
|
+
// fast forward to the end of balanced block for an open block tokens
|
|
331
|
+
if (this.isBlockOpenerTokenType(this.offsetAndType[cursor] >> TYPE_SHIFT)) {
|
|
332
|
+
cursor = balanceEnd;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
this.skip(cursor - this.tokenIndex);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
forEachToken(fn) {
|
|
341
|
+
for (let i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) {
|
|
342
|
+
const start = offset;
|
|
343
|
+
const item = this.offsetAndType[i];
|
|
344
|
+
const end = item & OFFSET_MASK;
|
|
345
|
+
const type = item >> TYPE_SHIFT;
|
|
346
|
+
|
|
347
|
+
offset = end;
|
|
348
|
+
|
|
349
|
+
fn(type, start, end, i);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
dump() {
|
|
353
|
+
const tokens = new Array(this.tokenCount);
|
|
354
|
+
|
|
355
|
+
this.forEachToken((type, start, end, index) => {
|
|
356
|
+
tokens[index] = {
|
|
357
|
+
idx: index,
|
|
358
|
+
type: tokenNames[type],
|
|
359
|
+
chunk: this.source.substring(start, end),
|
|
360
|
+
balance: this.balance[index]
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
return tokens;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
const EOF = 0;
|
|
2
|
+
|
|
3
|
+
// https://drafts.csswg.org/css-syntax-3/
|
|
4
|
+
// § 4.2. Definitions
|
|
5
|
+
|
|
6
|
+
// digit
|
|
7
|
+
// A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
|
|
8
|
+
export function isDigit(code) {
|
|
9
|
+
return code >= 0x0030 && code <= 0x0039;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// hex digit
|
|
13
|
+
// A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F),
|
|
14
|
+
// or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
|
|
15
|
+
export function isHexDigit(code) {
|
|
16
|
+
return (
|
|
17
|
+
isDigit(code) || // 0 .. 9
|
|
18
|
+
(code >= 0x0041 && code <= 0x0046) || // A .. F
|
|
19
|
+
(code >= 0x0061 && code <= 0x0066) // a .. f
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// uppercase letter
|
|
24
|
+
// A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
|
|
25
|
+
export function isUppercaseLetter(code) {
|
|
26
|
+
return code >= 0x0041 && code <= 0x005A;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// lowercase letter
|
|
30
|
+
// A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
|
|
31
|
+
export function isLowercaseLetter(code) {
|
|
32
|
+
return code >= 0x0061 && code <= 0x007A;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// letter
|
|
36
|
+
// An uppercase letter or a lowercase letter.
|
|
37
|
+
export function isLetter(code) {
|
|
38
|
+
return isUppercaseLetter(code) || isLowercaseLetter(code);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// non-ASCII code point
|
|
42
|
+
// A code point with a value equal to or greater than U+0080 <control>.
|
|
43
|
+
//
|
|
44
|
+
// 2024-09-02: The latest spec narrows the range for non-ASCII characters (see https://github.com/csstree/csstree/issues/188).
|
|
45
|
+
// However, all modern browsers support a wider range, and strictly following the latest spec could result
|
|
46
|
+
// in some CSS being parsed incorrectly, even though it works in the browser. Therefore, this function adheres
|
|
47
|
+
// to the previous, broader definition of non-ASCII characters.
|
|
48
|
+
export function isNonAscii(code) {
|
|
49
|
+
return code >= 0x0080;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// name-start code point
|
|
53
|
+
// A letter, a non-ASCII code point, or U+005F LOW LINE (_).
|
|
54
|
+
export function isNameStart(code) {
|
|
55
|
+
return isLetter(code) || isNonAscii(code) || code === 0x005F;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// name code point
|
|
59
|
+
// A name-start code point, a digit, or U+002D HYPHEN-MINUS (-).
|
|
60
|
+
export function isName(code) {
|
|
61
|
+
return isNameStart(code) || isDigit(code) || code === 0x002D;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// non-printable code point
|
|
65
|
+
// A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION,
|
|
66
|
+
// or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE.
|
|
67
|
+
export function isNonPrintable(code) {
|
|
68
|
+
return (
|
|
69
|
+
(code >= 0x0000 && code <= 0x0008) ||
|
|
70
|
+
(code === 0x000B) ||
|
|
71
|
+
(code >= 0x000E && code <= 0x001F) ||
|
|
72
|
+
(code === 0x007F)
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// newline
|
|
77
|
+
// U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition,
|
|
78
|
+
// as they are converted to U+000A LINE FEED during preprocessing.
|
|
79
|
+
// TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED
|
|
80
|
+
export function isNewline(code) {
|
|
81
|
+
return code === 0x000A || code === 0x000D || code === 0x000C;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// whitespace
|
|
85
|
+
// A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
|
|
86
|
+
export function isWhiteSpace(code) {
|
|
87
|
+
return isNewline(code) || code === 0x0020 || code === 0x0009;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// § 4.3.8. Check if two code points are a valid escape
|
|
91
|
+
export function isValidEscape(first, second) {
|
|
92
|
+
// If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
|
|
93
|
+
if (first !== 0x005C) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Otherwise, if the second code point is a newline or EOF, return false.
|
|
98
|
+
if (isNewline(second) || second === EOF) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Otherwise, return true.
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// § 4.3.9. Check if three code points would start an identifier
|
|
107
|
+
export function isIdentifierStart(first, second, third) {
|
|
108
|
+
// Look at the first code point:
|
|
109
|
+
|
|
110
|
+
// U+002D HYPHEN-MINUS
|
|
111
|
+
if (first === 0x002D) {
|
|
112
|
+
// If the second code point is a name-start code point or a U+002D HYPHEN-MINUS,
|
|
113
|
+
// or the second and third code points are a valid escape, return true. Otherwise, return false.
|
|
114
|
+
return (
|
|
115
|
+
isNameStart(second) ||
|
|
116
|
+
second === 0x002D ||
|
|
117
|
+
isValidEscape(second, third)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// name-start code point
|
|
122
|
+
if (isNameStart(first)) {
|
|
123
|
+
// Return true.
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// U+005C REVERSE SOLIDUS (\)
|
|
128
|
+
if (first === 0x005C) {
|
|
129
|
+
// If the first and second code points are a valid escape, return true. Otherwise, return false.
|
|
130
|
+
return isValidEscape(first, second);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// anything else
|
|
134
|
+
// Return false.
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// § 4.3.10. Check if three code points would start a number
|
|
139
|
+
export function isNumberStart(first, second, third) {
|
|
140
|
+
// Look at the first code point:
|
|
141
|
+
|
|
142
|
+
// U+002B PLUS SIGN (+)
|
|
143
|
+
// U+002D HYPHEN-MINUS (-)
|
|
144
|
+
if (first === 0x002B || first === 0x002D) {
|
|
145
|
+
// If the second code point is a digit, return true.
|
|
146
|
+
if (isDigit(second)) {
|
|
147
|
+
return 2;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Otherwise, if the second code point is a U+002E FULL STOP (.)
|
|
151
|
+
// and the third code point is a digit, return true.
|
|
152
|
+
// Otherwise, return false.
|
|
153
|
+
return second === 0x002E && isDigit(third) ? 3 : 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// U+002E FULL STOP (.)
|
|
157
|
+
if (first === 0x002E) {
|
|
158
|
+
// If the second code point is a digit, return true. Otherwise, return false.
|
|
159
|
+
return isDigit(second) ? 2 : 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// digit
|
|
163
|
+
if (isDigit(first)) {
|
|
164
|
+
// Return true.
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// anything else
|
|
169
|
+
// Return false.
|
|
170
|
+
return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
//
|
|
174
|
+
// Misc
|
|
175
|
+
//
|
|
176
|
+
|
|
177
|
+
// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
|
|
178
|
+
export function isBOM(code) {
|
|
179
|
+
// UTF-16BE
|
|
180
|
+
if (code === 0xFEFF) {
|
|
181
|
+
return 1;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// UTF-16LE
|
|
185
|
+
if (code === 0xFFFE) {
|
|
186
|
+
return 1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Fast code category
|
|
193
|
+
// Only ASCII code points has a special meaning, that's why we define a maps for 0..127 codes only
|
|
194
|
+
const CATEGORY = new Array(0x80);
|
|
195
|
+
export const EofCategory = 0x80;
|
|
196
|
+
export const WhiteSpaceCategory = 0x82;
|
|
197
|
+
export const DigitCategory = 0x83;
|
|
198
|
+
export const NameStartCategory = 0x84;
|
|
199
|
+
export const NonPrintableCategory = 0x85;
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < CATEGORY.length; i++) {
|
|
202
|
+
CATEGORY[i] =
|
|
203
|
+
isWhiteSpace(i) && WhiteSpaceCategory ||
|
|
204
|
+
isDigit(i) && DigitCategory ||
|
|
205
|
+
isNameStart(i) && NameStartCategory ||
|
|
206
|
+
isNonPrintable(i) && NonPrintableCategory ||
|
|
207
|
+
i || EofCategory;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function charCodeCategory(code) {
|
|
211
|
+
return code < 0x80 ? CATEGORY[code] : NameStartCategory;
|
|
212
|
+
}
|