@tbela99/css-parser 0.0.1 → 0.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/README.md +318 -34
- package/dist/config.json.js +386 -4
- package/dist/index-umd-web.js +3260 -1563
- package/dist/index.cjs +3259 -1564
- package/dist/index.d.ts +687 -536
- package/dist/lib/ast/expand.js +14 -14
- package/dist/lib/ast/features/calc.js +225 -0
- package/dist/lib/ast/features/index.js +3 -0
- package/dist/lib/ast/features/inlinecssvariables.js +130 -0
- package/dist/lib/ast/features/shorthand.js +46 -0
- package/dist/lib/ast/features/utils/math.js +95 -0
- package/dist/lib/ast/minify.js +401 -372
- package/dist/lib/ast/types.js +101 -0
- package/dist/lib/ast/utils/minifyfeature.js +8 -0
- package/dist/lib/ast/walk.js +37 -9
- package/dist/lib/iterable/set.js +48 -0
- package/dist/lib/iterable/weakmap.js +53 -0
- package/dist/lib/parser/declaration/list.js +18 -4
- package/dist/lib/parser/declaration/map.js +102 -33
- package/dist/lib/parser/declaration/set.js +18 -12
- package/dist/lib/parser/parse.js +661 -421
- package/dist/lib/parser/tokenize.js +82 -46
- package/dist/lib/parser/utils/syntax.js +13 -10
- package/dist/lib/parser/utils/type.js +23 -6
- package/dist/lib/renderer/render.js +253 -84
- package/dist/lib/renderer/sourcemap/lib/encode.js +37 -0
- package/dist/lib/renderer/sourcemap/sourcemap.js +58 -0
- package/dist/lib/renderer/utils/color.js +25 -20
- package/dist/node/index.js +30 -15
- package/dist/web/index.js +36 -19
- package/package.json +9 -6
- package/dist/lib/transform.js +0 -24
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,238 +1,243 @@
|
|
|
1
1
|
import { isPseudo, isAtKeyword, isFunction, isNumber, isDimension, parseDimension, isPercentage, isIdent, isHexColor, isHash, isIdentStart, isColor } from './utils/syntax.js';
|
|
2
|
+
import { EnumToken } from '../ast/types.js';
|
|
3
|
+
import { minify, combinators } from '../ast/minify.js';
|
|
4
|
+
import { walkValues, walk } from '../ast/walk.js';
|
|
5
|
+
import { expand } from '../ast/expand.js';
|
|
2
6
|
import { renderToken } from '../renderer/render.js';
|
|
3
7
|
import { COLORS_NAMES } from '../renderer/utils/color.js';
|
|
4
|
-
import { minify, combinators } from '../ast/minify.js';
|
|
5
8
|
import { tokenize } from './tokenize.js';
|
|
6
9
|
|
|
7
10
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
8
|
-
const trimWhiteSpace = [
|
|
9
|
-
const funcLike = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const stack = [];
|
|
33
|
-
const ast = {
|
|
34
|
-
typ: "StyleSheet",
|
|
35
|
-
chi: []
|
|
36
|
-
};
|
|
37
|
-
let tokens = [];
|
|
38
|
-
let map = new Map;
|
|
39
|
-
let bytesIn = 0;
|
|
40
|
-
let context = ast;
|
|
41
|
-
if (options.sourcemap) {
|
|
42
|
-
ast.loc = {
|
|
43
|
-
sta: {
|
|
44
|
-
ind: 0,
|
|
45
|
-
lin: 1,
|
|
46
|
-
col: 1
|
|
47
|
-
},
|
|
48
|
-
src: ''
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
async function parseNode(results) {
|
|
52
|
-
let tokens = results.map(mapToken);
|
|
53
|
-
let i;
|
|
54
|
-
let loc;
|
|
55
|
-
for (i = 0; i < tokens.length; i++) {
|
|
56
|
-
if (tokens[i].typ == 'Comment' || tokens[i].typ == 'CDOCOMM') {
|
|
57
|
-
const position = map.get(tokens[i]);
|
|
58
|
-
if (tokens[i].typ == 'CDOCOMM' && context.typ != 'StyleSheet') {
|
|
59
|
-
errors.push({ action: 'drop', message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`, location: { src, ...position } });
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
loc = {
|
|
63
|
-
sta: position,
|
|
64
|
-
src
|
|
65
|
-
};
|
|
66
|
-
// @ts-ignore
|
|
67
|
-
context.chi.push(tokens[i]);
|
|
68
|
-
if (options.sourcemap) {
|
|
69
|
-
tokens[i].loc = loc;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else if (tokens[i].typ != 'Whitespace') {
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
tokens = tokens.slice(i);
|
|
77
|
-
if (tokens.length == 0) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
let delim = tokens.at(-1);
|
|
81
|
-
if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
|
|
82
|
-
tokens.pop();
|
|
11
|
+
const trimWhiteSpace = [EnumToken.CommentTokenType, EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType];
|
|
12
|
+
const funcLike = [
|
|
13
|
+
EnumToken.ParensTokenType,
|
|
14
|
+
EnumToken.FunctionTokenType,
|
|
15
|
+
EnumToken.UrlFunctionTokenType,
|
|
16
|
+
EnumToken.StartParensTokenType,
|
|
17
|
+
EnumToken.ImageFunctionTokenType,
|
|
18
|
+
EnumToken.PseudoClassFuncTokenType,
|
|
19
|
+
EnumToken.TimingFunctionTokenType,
|
|
20
|
+
EnumToken.TimingFunctionTokenType
|
|
21
|
+
];
|
|
22
|
+
const BadTokensTypes = [
|
|
23
|
+
EnumToken.BadCommentTokenType,
|
|
24
|
+
EnumToken.BadCdoTokenType,
|
|
25
|
+
EnumToken.BadUrlTokenType,
|
|
26
|
+
EnumToken.BadStringTokenType
|
|
27
|
+
];
|
|
28
|
+
const webkitPseudoAliasMap = {
|
|
29
|
+
'-webkit-autofill': 'autofill'
|
|
30
|
+
};
|
|
31
|
+
async function doParse(iterator, options = {}) {
|
|
32
|
+
return new Promise(async (resolve, reject) => {
|
|
33
|
+
if (options.signal != null) {
|
|
34
|
+
options.signal.addEventListener('abort', reject);
|
|
83
35
|
}
|
|
84
|
-
|
|
85
|
-
|
|
36
|
+
options = {
|
|
37
|
+
src: '',
|
|
38
|
+
sourcemap: false,
|
|
39
|
+
minify: true,
|
|
40
|
+
nestingRules: false,
|
|
41
|
+
resolveImport: false,
|
|
42
|
+
resolveUrls: false,
|
|
43
|
+
removeCharset: false,
|
|
44
|
+
removeEmpty: true,
|
|
45
|
+
removeDuplicateDeclarations: true,
|
|
46
|
+
computeShorthand: true,
|
|
47
|
+
computeCalcExpression: true,
|
|
48
|
+
inlineCssVariables: false,
|
|
49
|
+
...options
|
|
50
|
+
};
|
|
51
|
+
if (options.expandNestingRules) {
|
|
52
|
+
options.nestingRules = false;
|
|
86
53
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
tokens.pop();
|
|
54
|
+
if (options.resolveImport) {
|
|
55
|
+
options.resolveUrls = true;
|
|
90
56
|
}
|
|
91
|
-
|
|
92
|
-
|
|
57
|
+
const startTime = performance.now();
|
|
58
|
+
const errors = [];
|
|
59
|
+
const src = options.src;
|
|
60
|
+
const stack = [];
|
|
61
|
+
let ast = {
|
|
62
|
+
typ: EnumToken.StyleSheetNodeType,
|
|
63
|
+
chi: []
|
|
64
|
+
};
|
|
65
|
+
let tokens = [];
|
|
66
|
+
let map = new Map;
|
|
67
|
+
let bytesIn = 0;
|
|
68
|
+
let context = ast;
|
|
69
|
+
if (options.sourcemap) {
|
|
70
|
+
ast.loc = {
|
|
71
|
+
sta: {
|
|
72
|
+
ind: 0,
|
|
73
|
+
lin: 1,
|
|
74
|
+
col: 1
|
|
75
|
+
},
|
|
76
|
+
src: ''
|
|
77
|
+
};
|
|
93
78
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
79
|
+
async function parseNode(results) {
|
|
80
|
+
let tokens = results.map(mapToken);
|
|
81
|
+
let i;
|
|
82
|
+
let loc;
|
|
83
|
+
for (i = 0; i < tokens.length; i++) {
|
|
84
|
+
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
85
|
+
const position = map.get(tokens[i]);
|
|
86
|
+
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != EnumToken.StyleSheetNodeType) {
|
|
87
|
+
errors.push({
|
|
88
|
+
action: 'drop',
|
|
89
|
+
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
90
|
+
location: { src, ...position }
|
|
91
|
+
});
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
loc = {
|
|
95
|
+
sta: position,
|
|
96
|
+
src
|
|
97
|
+
};
|
|
98
|
+
// @ts-ignore
|
|
99
|
+
context.chi.push(tokens[i]);
|
|
100
|
+
if (options.sourcemap) {
|
|
101
|
+
tokens[i].loc = loc;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
tokens = tokens.slice(i);
|
|
109
|
+
if (tokens.length == 0) {
|
|
99
110
|
return null;
|
|
100
111
|
}
|
|
112
|
+
let delim = tokens.at(-1);
|
|
113
|
+
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
114
|
+
tokens.pop();
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
delim = { typ: EnumToken.SemiColonTokenType };
|
|
118
|
+
}
|
|
101
119
|
// @ts-ignore
|
|
102
|
-
while ([
|
|
103
|
-
tokens.
|
|
120
|
+
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
121
|
+
tokens.pop();
|
|
104
122
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
break;
|
|
123
|
+
if (tokens.length == 0) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
127
|
+
const atRule = tokens.shift();
|
|
128
|
+
const position = map.get(atRule);
|
|
129
|
+
if (atRule.val == 'charset') {
|
|
130
|
+
if (position.ind > 0) {
|
|
131
|
+
errors.push({
|
|
132
|
+
action: 'drop',
|
|
133
|
+
message: 'doParse: invalid @charset',
|
|
134
|
+
location: { src, ...position }
|
|
135
|
+
});
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (options.removeCharset) {
|
|
139
|
+
return null;
|
|
124
140
|
}
|
|
125
141
|
}
|
|
126
142
|
// @ts-ignore
|
|
127
|
-
|
|
128
|
-
errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
if (tokens[0].typ == 'UrlFunc' && tokens[1]?.typ != 'Url-token' && tokens[1]?.typ != 'String') {
|
|
133
|
-
errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (atRule.val == 'import') {
|
|
138
|
-
// @ts-ignore
|
|
139
|
-
if (tokens[0].typ == 'UrlFunc' && tokens[1].typ == 'Url-token') {
|
|
143
|
+
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
140
144
|
tokens.shift();
|
|
141
|
-
// @ts-ignore
|
|
142
|
-
tokens[0].typ = 'String';
|
|
143
|
-
// @ts-ignore
|
|
144
|
-
tokens[0].val = `"${tokens[0].val}"`;
|
|
145
145
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
minify: false,
|
|
155
|
-
// @ts-ignore
|
|
156
|
-
src: options.resolve(url, options.src).absolute
|
|
157
|
-
}));
|
|
158
|
-
});
|
|
159
|
-
bytesIn += root.stats.bytesIn;
|
|
160
|
-
if (root.ast.chi.length > 0) {
|
|
161
|
-
context.chi.push(...root.ast.chi);
|
|
146
|
+
if (atRule.val == 'import') {
|
|
147
|
+
// only @charset and @layer are accepted before @import
|
|
148
|
+
if (context.chi.length > 0) {
|
|
149
|
+
let i = context.chi.length;
|
|
150
|
+
while (i--) {
|
|
151
|
+
const type = context.chi[i].typ;
|
|
152
|
+
if (type == EnumToken.CommentNodeType) {
|
|
153
|
+
continue;
|
|
162
154
|
}
|
|
163
|
-
if (
|
|
164
|
-
errors.push(...
|
|
155
|
+
if (type != EnumToken.AtRuleNodeType) {
|
|
156
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
157
|
+
return null;
|
|
165
158
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
159
|
+
const name = context.chi[i].nam;
|
|
160
|
+
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
161
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
171
165
|
}
|
|
172
166
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}, []);
|
|
182
|
-
const node = {
|
|
183
|
-
typ: 'AtRule',
|
|
184
|
-
nam: renderToken(atRule, { removeComments: true }),
|
|
185
|
-
val: raw.join('')
|
|
186
|
-
};
|
|
187
|
-
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
188
|
-
if (delim.typ == 'Block-start') {
|
|
189
|
-
node.chi = [];
|
|
190
|
-
}
|
|
191
|
-
loc = {
|
|
192
|
-
sta: position,
|
|
193
|
-
src
|
|
194
|
-
};
|
|
195
|
-
if (options.sourcemap) {
|
|
196
|
-
node.loc = loc;
|
|
197
|
-
}
|
|
198
|
-
// @ts-ignore
|
|
199
|
-
context.chi.push(node);
|
|
200
|
-
return delim.typ == 'Block-start' ? node : null;
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
// rule
|
|
204
|
-
if (delim.typ == 'Block-start') {
|
|
205
|
-
const position = map.get(tokens[0]);
|
|
206
|
-
const uniq = new Map;
|
|
207
|
-
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
208
|
-
if (curr.typ == 'Whitespace') {
|
|
209
|
-
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
210
|
-
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
211
|
-
combinators.includes(array[index - 1]?.val) ||
|
|
212
|
-
combinators.includes(array[index + 1]?.val)) {
|
|
213
|
-
return acc;
|
|
214
|
-
}
|
|
167
|
+
// @ts-ignore
|
|
168
|
+
if (tokens[0]?.typ != EnumToken.StringTokenType && tokens[0]?.typ != EnumToken.UrlFunctionTokenType) {
|
|
169
|
+
errors.push({
|
|
170
|
+
action: 'drop',
|
|
171
|
+
message: 'doParse: invalid @import',
|
|
172
|
+
location: { src, ...position }
|
|
173
|
+
});
|
|
174
|
+
return null;
|
|
215
175
|
}
|
|
216
|
-
|
|
217
|
-
if (
|
|
218
|
-
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1]?.typ != EnumToken.UrlTokenTokenType && tokens[1]?.typ != EnumToken.StringTokenType) {
|
|
178
|
+
errors.push({
|
|
179
|
+
action: 'drop',
|
|
180
|
+
message: 'doParse: invalid @import',
|
|
181
|
+
location: { src, ...position }
|
|
182
|
+
});
|
|
183
|
+
return null;
|
|
219
184
|
}
|
|
220
|
-
|
|
221
|
-
|
|
185
|
+
}
|
|
186
|
+
if (atRule.val == 'import') {
|
|
187
|
+
// @ts-ignore
|
|
188
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1].typ == EnumToken.UrlTokenTokenType) {
|
|
189
|
+
tokens.shift();
|
|
190
|
+
// @ts-ignore
|
|
191
|
+
tokens[0].typ = EnumToken.StringTokenType;
|
|
192
|
+
// @ts-ignore
|
|
193
|
+
tokens[0].val = `"${tokens[0].val}"`;
|
|
222
194
|
}
|
|
195
|
+
// @ts-ignore
|
|
196
|
+
if (tokens[0].typ == EnumToken.StringTokenType) {
|
|
197
|
+
if (options.resolveImport) {
|
|
198
|
+
const url = tokens[0].val.slice(1, -1);
|
|
199
|
+
try {
|
|
200
|
+
// @ts-ignore
|
|
201
|
+
const root = await options.load(url, options.src).then((src) => {
|
|
202
|
+
return doParse(src, Object.assign({}, options, {
|
|
203
|
+
minify: false,
|
|
204
|
+
// @ts-ignore
|
|
205
|
+
src: options.resolve(url, options.src).absolute
|
|
206
|
+
}));
|
|
207
|
+
});
|
|
208
|
+
bytesIn += root.stats.bytesIn;
|
|
209
|
+
if (root.ast.chi.length > 0) {
|
|
210
|
+
// @todo - filter charset, layer and scope
|
|
211
|
+
context.chi.push(...root.ast.chi);
|
|
212
|
+
}
|
|
213
|
+
if (root.errors.length > 0) {
|
|
214
|
+
errors.push(...root.errors);
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
catch (error) {
|
|
219
|
+
// @ts-ignore
|
|
220
|
+
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
226
|
+
// allowed nesting at-rules
|
|
227
|
+
// there must be a top level rule in the stack
|
|
228
|
+
const raw = parseTokens(tokens, { minify: options.minify }).reduce((acc, curr) => {
|
|
229
|
+
acc.push(renderToken(curr, { removeComments: true }));
|
|
223
230
|
return acc;
|
|
224
|
-
}, [
|
|
225
|
-
acc.set(curr.join(''), curr);
|
|
226
|
-
return acc;
|
|
227
|
-
}, uniq);
|
|
231
|
+
}, []);
|
|
228
232
|
const node = {
|
|
229
|
-
typ:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
chi: []
|
|
233
|
+
typ: EnumToken.AtRuleNodeType,
|
|
234
|
+
nam: renderToken(atRule, { removeComments: true }),
|
|
235
|
+
val: raw.join('')
|
|
233
236
|
};
|
|
234
|
-
let raw = [...uniq.values()];
|
|
235
237
|
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
238
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
239
|
+
node.chi = [];
|
|
240
|
+
}
|
|
236
241
|
loc = {
|
|
237
242
|
sta: position,
|
|
238
243
|
src
|
|
@@ -242,171 +247,255 @@ async function parse(iterator, opt = {}) {
|
|
|
242
247
|
}
|
|
243
248
|
// @ts-ignore
|
|
244
249
|
context.chi.push(node);
|
|
245
|
-
return node;
|
|
250
|
+
return delim.typ == EnumToken.BlockStartTokenType ? node : null;
|
|
246
251
|
}
|
|
247
252
|
else {
|
|
248
|
-
//
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
253
|
+
// rule
|
|
254
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
255
|
+
const position = map.get(tokens[0]);
|
|
256
|
+
const uniq = new Map;
|
|
257
|
+
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
258
|
+
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
259
|
+
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
260
|
+
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
261
|
+
combinators.includes(array[index - 1]?.val) ||
|
|
262
|
+
combinators.includes(array[index + 1]?.val)) {
|
|
263
|
+
return acc;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
let t = renderToken(curr, { minify: false });
|
|
267
|
+
if (t == ',') {
|
|
268
|
+
acc.push([]);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
acc[acc.length - 1].push(t);
|
|
272
|
+
}
|
|
273
|
+
return acc;
|
|
274
|
+
}, [[]]).reduce((acc, curr) => {
|
|
275
|
+
acc.set(curr.join(''), curr);
|
|
276
|
+
return acc;
|
|
277
|
+
}, uniq);
|
|
278
|
+
const node = {
|
|
279
|
+
typ: EnumToken.RuleNodeType,
|
|
280
|
+
// @ts-ignore
|
|
281
|
+
sel: [...uniq.keys()].join(','),
|
|
282
|
+
chi: []
|
|
283
|
+
};
|
|
284
|
+
let raw = [...uniq.values()];
|
|
285
|
+
Object.defineProperty(node, 'raw', {
|
|
286
|
+
enumerable: false,
|
|
287
|
+
configurable: true,
|
|
288
|
+
writable: true,
|
|
289
|
+
value: raw
|
|
290
|
+
});
|
|
291
|
+
loc = {
|
|
292
|
+
sta: position,
|
|
293
|
+
src
|
|
294
|
+
};
|
|
295
|
+
if (options.sourcemap) {
|
|
296
|
+
node.loc = loc;
|
|
266
297
|
}
|
|
298
|
+
// @ts-ignore
|
|
299
|
+
context.chi.push(node);
|
|
300
|
+
return node;
|
|
267
301
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
302
|
+
else {
|
|
303
|
+
// declaration
|
|
304
|
+
// @ts-ignore
|
|
305
|
+
let name = null;
|
|
306
|
+
// @ts-ignore
|
|
307
|
+
let value = null;
|
|
308
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
309
|
+
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
313
|
+
name = tokens.slice(0, i);
|
|
314
|
+
value = parseTokens(tokens.slice(i + 1), {
|
|
315
|
+
parseColor: true,
|
|
316
|
+
src: options.src,
|
|
317
|
+
resolveUrls: options.resolveUrls,
|
|
318
|
+
resolve: options.resolve,
|
|
319
|
+
cwd: options.cwd
|
|
279
320
|
});
|
|
280
|
-
return null;
|
|
281
321
|
}
|
|
282
322
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
323
|
+
if (name == null) {
|
|
324
|
+
name = tokens;
|
|
325
|
+
}
|
|
326
|
+
const position = map.get(name[0]);
|
|
327
|
+
if (name.length > 0) {
|
|
328
|
+
for (let i = 1; i < name.length; i++) {
|
|
329
|
+
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
330
|
+
errors.push({
|
|
331
|
+
action: 'drop',
|
|
332
|
+
message: 'doParse: invalid declaration',
|
|
333
|
+
location: { src, ...position }
|
|
334
|
+
});
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (value == null || value.length == 0) {
|
|
340
|
+
errors.push({
|
|
341
|
+
action: 'drop',
|
|
342
|
+
message: 'doParse: invalid declaration',
|
|
343
|
+
location: { src, ...position }
|
|
344
|
+
});
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
const node = {
|
|
348
|
+
typ: EnumToken.DeclarationNodeType,
|
|
349
|
+
// @ts-ignore
|
|
350
|
+
nam: renderToken(name.shift(), { removeComments: true }),
|
|
351
|
+
// @ts-ignore
|
|
352
|
+
val: value
|
|
353
|
+
};
|
|
354
|
+
while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
355
|
+
node.val.shift();
|
|
356
|
+
}
|
|
357
|
+
if (node.val.length == 0) {
|
|
358
|
+
errors.push({
|
|
359
|
+
action: 'drop',
|
|
360
|
+
message: 'doParse: invalid declaration',
|
|
361
|
+
location: { src, ...position }
|
|
362
|
+
});
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
304
365
|
// @ts-ignore
|
|
305
|
-
|
|
306
|
-
};
|
|
307
|
-
while (node.val[0]?.typ == 'Whitespace') {
|
|
308
|
-
node.val.shift();
|
|
309
|
-
}
|
|
310
|
-
if (node.val.length == 0) {
|
|
311
|
-
errors.push({
|
|
312
|
-
action: 'drop',
|
|
313
|
-
message: 'parse: invalid declaration',
|
|
314
|
-
location: { src, ...position }
|
|
315
|
-
});
|
|
366
|
+
context.chi.push(node);
|
|
316
367
|
return null;
|
|
317
368
|
}
|
|
318
|
-
// @ts-ignore
|
|
319
|
-
context.chi.push(node);
|
|
320
|
-
return null;
|
|
321
369
|
}
|
|
322
370
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
return node;
|
|
328
|
-
}
|
|
329
|
-
const iter = tokenize(iterator);
|
|
330
|
-
let item;
|
|
331
|
-
while (item = iter.next().value) {
|
|
332
|
-
bytesIn = item.bytesIn;
|
|
333
|
-
// parse error
|
|
334
|
-
if (item.hint != null && item.hint.startsWith('Bad-')) {
|
|
335
|
-
// bad token
|
|
336
|
-
continue;
|
|
371
|
+
function mapToken(token) {
|
|
372
|
+
const node = getTokenType(token.token, token.hint);
|
|
373
|
+
map.set(node, token.position);
|
|
374
|
+
return node;
|
|
337
375
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
376
|
+
const iter = tokenize(iterator);
|
|
377
|
+
let item;
|
|
378
|
+
while (item = iter.next().value) {
|
|
379
|
+
bytesIn = item.bytesIn;
|
|
380
|
+
// doParse error
|
|
381
|
+
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
382
|
+
// bad token
|
|
383
|
+
continue;
|
|
345
384
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
385
|
+
tokens.push(item);
|
|
386
|
+
if (item.token == ';' || item.token == '{') {
|
|
387
|
+
let node = await parseNode(tokens);
|
|
388
|
+
if (node != null) {
|
|
389
|
+
stack.push(node);
|
|
390
|
+
// @ts-ignore
|
|
391
|
+
context = node;
|
|
392
|
+
}
|
|
393
|
+
else if (item.token == '{') {
|
|
394
|
+
// node == null
|
|
395
|
+
// consume and throw away until the closing '}' or EOF
|
|
396
|
+
let inBlock = 1;
|
|
397
|
+
do {
|
|
398
|
+
item = iter.next().value;
|
|
399
|
+
if (item == null) {
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
402
|
+
if (item.token == '{') {
|
|
403
|
+
inBlock++;
|
|
404
|
+
}
|
|
405
|
+
else if (item.token == '}') {
|
|
406
|
+
inBlock--;
|
|
407
|
+
}
|
|
408
|
+
} while (inBlock != 0);
|
|
409
|
+
}
|
|
410
|
+
tokens = [];
|
|
411
|
+
map = new Map;
|
|
412
|
+
}
|
|
413
|
+
else if (item.token == '}') {
|
|
414
|
+
await parseNode(tokens);
|
|
415
|
+
const previousNode = stack.pop();
|
|
416
|
+
// @ts-ignore
|
|
417
|
+
context = stack[stack.length - 1] || ast;
|
|
418
|
+
// @ts-ignore
|
|
419
|
+
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
420
|
+
context.chi.pop();
|
|
421
|
+
}
|
|
422
|
+
tokens = [];
|
|
423
|
+
map = new Map;
|
|
362
424
|
}
|
|
363
|
-
tokens = [];
|
|
364
|
-
map = new Map;
|
|
365
425
|
}
|
|
366
|
-
|
|
426
|
+
if (tokens.length > 0) {
|
|
367
427
|
await parseNode(tokens);
|
|
428
|
+
}
|
|
429
|
+
while (stack.length > 0 && context != ast) {
|
|
368
430
|
const previousNode = stack.pop();
|
|
369
431
|
// @ts-ignore
|
|
370
432
|
context = stack[stack.length - 1] || ast;
|
|
371
433
|
// @ts-ignore
|
|
372
434
|
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
373
435
|
context.chi.pop();
|
|
436
|
+
continue;
|
|
374
437
|
}
|
|
375
|
-
|
|
376
|
-
map = new Map;
|
|
438
|
+
break;
|
|
377
439
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
while (stack.length > 0 && context != ast) {
|
|
383
|
-
const previousNode = stack.pop();
|
|
384
|
-
// @ts-ignore
|
|
385
|
-
context = stack[stack.length - 1] || ast;
|
|
386
|
-
// @ts-ignore
|
|
387
|
-
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
388
|
-
context.chi.pop();
|
|
389
|
-
continue;
|
|
440
|
+
const endParseTime = performance.now();
|
|
441
|
+
if (options.expandNestingRules) {
|
|
442
|
+
ast = expand(ast);
|
|
390
443
|
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
444
|
+
if (options.visitor != null) {
|
|
445
|
+
for (const result of walk(ast)) {
|
|
446
|
+
if (result.node.typ == EnumToken.DeclarationNodeType &&
|
|
447
|
+
// @ts-ignore
|
|
448
|
+
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
449
|
+
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
450
|
+
const results = callable(result.node);
|
|
451
|
+
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
// @ts-ignore
|
|
455
|
+
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
456
|
+
}
|
|
457
|
+
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
458
|
+
const results = options.visitor.Rule(result.node);
|
|
459
|
+
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
// @ts-ignore
|
|
463
|
+
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
464
|
+
}
|
|
465
|
+
else if (options.visitor.AtRule != null &&
|
|
466
|
+
result.node.typ == EnumToken.AtRuleNodeType &&
|
|
467
|
+
// @ts-ignore
|
|
468
|
+
(typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
|
|
469
|
+
const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
|
|
470
|
+
const results = callable(result.node);
|
|
471
|
+
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
472
|
+
continue;
|
|
473
|
+
}
|
|
474
|
+
// @ts-ignore
|
|
475
|
+
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
397
478
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
errors,
|
|
403
|
-
stats: {
|
|
404
|
-
bytesIn,
|
|
405
|
-
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
406
|
-
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
407
|
-
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
479
|
+
if (options.minify) {
|
|
480
|
+
if (ast.chi.length > 0) {
|
|
481
|
+
minify(ast, options, true, errors, false);
|
|
482
|
+
}
|
|
408
483
|
}
|
|
409
|
-
|
|
484
|
+
const endTime = performance.now();
|
|
485
|
+
if (options.signal != null) {
|
|
486
|
+
options.signal.removeEventListener('abort', reject);
|
|
487
|
+
}
|
|
488
|
+
resolve({
|
|
489
|
+
ast,
|
|
490
|
+
errors,
|
|
491
|
+
stats: {
|
|
492
|
+
bytesIn,
|
|
493
|
+
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
494
|
+
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
495
|
+
total: `${(endTime - startTime).toFixed(2)}ms`
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
});
|
|
410
499
|
}
|
|
411
500
|
function parseString(src, options = { location: false }) {
|
|
412
501
|
return parseTokens([...tokenize(src)].map(t => {
|
|
@@ -423,81 +512,111 @@ function getTokenType(val, hint) {
|
|
|
423
512
|
}
|
|
424
513
|
if (hint != null) {
|
|
425
514
|
return ([
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
515
|
+
EnumToken.WhitespaceTokenType, EnumToken.SemiColonTokenType, EnumToken.ColonTokenType, EnumToken.BlockStartTokenType,
|
|
516
|
+
EnumToken.BlockStartTokenType, EnumToken.AttrStartTokenType, EnumToken.AttrEndTokenType, EnumToken.StartParensTokenType, EnumToken.EndParensTokenType,
|
|
517
|
+
EnumToken.CommaTokenType, EnumToken.GtTokenType, EnumToken.LtTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.CommaTokenType,
|
|
518
|
+
EnumToken.StartMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DashMatchTokenType, EnumToken.ContainMatchTokenType,
|
|
519
|
+
EnumToken.EOFTokenType
|
|
429
520
|
].includes(hint) ? { typ: hint } : { typ: hint, val });
|
|
430
521
|
}
|
|
431
522
|
if (val == ' ') {
|
|
432
|
-
return { typ:
|
|
523
|
+
return { typ: EnumToken.WhitespaceTokenType };
|
|
433
524
|
}
|
|
434
525
|
if (val == ';') {
|
|
435
|
-
return { typ:
|
|
526
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
436
527
|
}
|
|
437
528
|
if (val == '{') {
|
|
438
|
-
return { typ:
|
|
529
|
+
return { typ: EnumToken.BlockStartTokenType };
|
|
439
530
|
}
|
|
440
531
|
if (val == '}') {
|
|
441
|
-
return { typ:
|
|
532
|
+
return { typ: EnumToken.BlockEndTokenType };
|
|
442
533
|
}
|
|
443
534
|
if (val == '[') {
|
|
444
|
-
return { typ:
|
|
535
|
+
return { typ: EnumToken.AttrStartTokenType };
|
|
445
536
|
}
|
|
446
537
|
if (val == ']') {
|
|
447
|
-
return { typ:
|
|
538
|
+
return { typ: EnumToken.AttrEndTokenType };
|
|
448
539
|
}
|
|
449
540
|
if (val == ':') {
|
|
450
|
-
return { typ:
|
|
541
|
+
return { typ: EnumToken.ColonTokenType };
|
|
451
542
|
}
|
|
452
543
|
if (val == ')') {
|
|
453
|
-
return { typ:
|
|
544
|
+
return { typ: EnumToken.EndParensTokenType };
|
|
454
545
|
}
|
|
455
546
|
if (val == '(') {
|
|
456
|
-
return { typ:
|
|
547
|
+
return { typ: EnumToken.StartParensTokenType };
|
|
457
548
|
}
|
|
458
549
|
if (val == '=') {
|
|
459
|
-
return { typ:
|
|
550
|
+
return { typ: EnumToken.DelimTokenType, val };
|
|
460
551
|
}
|
|
461
552
|
if (val == ';') {
|
|
462
|
-
return { typ:
|
|
553
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
463
554
|
}
|
|
464
555
|
if (val == ',') {
|
|
465
|
-
return { typ:
|
|
556
|
+
return { typ: EnumToken.CommaTokenType };
|
|
466
557
|
}
|
|
467
558
|
if (val == '<') {
|
|
468
|
-
return { typ:
|
|
559
|
+
return { typ: EnumToken.LtTokenType };
|
|
469
560
|
}
|
|
470
561
|
if (val == '>') {
|
|
471
|
-
return { typ:
|
|
562
|
+
return { typ: EnumToken.GtTokenType };
|
|
472
563
|
}
|
|
473
564
|
if (isPseudo(val)) {
|
|
474
565
|
return val.endsWith('(') ? {
|
|
475
|
-
typ:
|
|
566
|
+
typ: EnumToken.PseudoClassFuncTokenType,
|
|
476
567
|
val: val.slice(0, -1),
|
|
477
568
|
chi: []
|
|
478
569
|
}
|
|
479
570
|
: {
|
|
480
|
-
typ:
|
|
571
|
+
typ: EnumToken.PseudoClassTokenType,
|
|
481
572
|
val
|
|
482
573
|
};
|
|
483
574
|
}
|
|
484
575
|
if (isAtKeyword(val)) {
|
|
485
576
|
return {
|
|
486
|
-
typ:
|
|
577
|
+
typ: EnumToken.AtRuleTokenType,
|
|
487
578
|
val: val.slice(1)
|
|
488
579
|
};
|
|
489
580
|
}
|
|
490
581
|
if (isFunction(val)) {
|
|
491
582
|
val = val.slice(0, -1);
|
|
583
|
+
if (val == 'url') {
|
|
584
|
+
return {
|
|
585
|
+
typ: EnumToken.UrlFunctionTokenType,
|
|
586
|
+
val,
|
|
587
|
+
chi: []
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
if (['linear-gradient', 'radial-gradient', 'repeating-linear-gradient', 'repeating-radial-gradient', 'conic-gradient', 'image', 'image-set', 'element', 'cross-fade'].includes(val)) {
|
|
591
|
+
return {
|
|
592
|
+
typ: EnumToken.ImageFunctionTokenType,
|
|
593
|
+
val,
|
|
594
|
+
chi: []
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
if (['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear', 'step-start', 'step-end', 'steps', 'cubic-bezier'].includes(val)) {
|
|
598
|
+
return {
|
|
599
|
+
typ: EnumToken.TimingFunctionTokenType,
|
|
600
|
+
val,
|
|
601
|
+
chi: []
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
if (['view', 'scroll'].includes(val)) {
|
|
605
|
+
return {
|
|
606
|
+
typ: EnumToken.TimelineFunctionTokenType,
|
|
607
|
+
val,
|
|
608
|
+
chi: []
|
|
609
|
+
};
|
|
610
|
+
}
|
|
492
611
|
return {
|
|
493
|
-
typ:
|
|
612
|
+
typ: EnumToken.FunctionTokenType,
|
|
494
613
|
val,
|
|
495
614
|
chi: []
|
|
496
615
|
};
|
|
497
616
|
}
|
|
498
617
|
if (isNumber(val)) {
|
|
499
618
|
return {
|
|
500
|
-
typ:
|
|
619
|
+
typ: EnumToken.NumberTokenType,
|
|
501
620
|
val
|
|
502
621
|
};
|
|
503
622
|
}
|
|
@@ -506,114 +625,210 @@ function getTokenType(val, hint) {
|
|
|
506
625
|
}
|
|
507
626
|
if (isPercentage(val)) {
|
|
508
627
|
return {
|
|
509
|
-
typ:
|
|
628
|
+
typ: EnumToken.PercentageTokenType,
|
|
510
629
|
val: val.slice(0, -1)
|
|
511
630
|
};
|
|
512
631
|
}
|
|
513
632
|
const v = val.toLowerCase();
|
|
514
633
|
if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
|
|
515
634
|
return {
|
|
516
|
-
typ:
|
|
635
|
+
typ: EnumToken.ColorTokenType,
|
|
517
636
|
val,
|
|
518
637
|
kin: 'lit'
|
|
519
638
|
};
|
|
520
639
|
}
|
|
521
640
|
if (isIdent(val)) {
|
|
522
641
|
return {
|
|
523
|
-
typ: '
|
|
642
|
+
typ: val.startsWith('--') ? EnumToken.DashedIdenTokenType : EnumToken.IdenTokenType,
|
|
524
643
|
val
|
|
525
644
|
};
|
|
526
645
|
}
|
|
527
646
|
if (val.charAt(0) == '#' && isHexColor(val)) {
|
|
528
647
|
return {
|
|
529
|
-
typ:
|
|
648
|
+
typ: EnumToken.ColorTokenType,
|
|
530
649
|
val,
|
|
531
650
|
kin: 'hex'
|
|
532
651
|
};
|
|
533
652
|
}
|
|
534
653
|
if (val.charAt(0) == '#' && isHash(val)) {
|
|
535
654
|
return {
|
|
536
|
-
typ:
|
|
655
|
+
typ: EnumToken.HashTokenType,
|
|
537
656
|
val
|
|
538
657
|
};
|
|
539
658
|
}
|
|
540
659
|
if ('"\''.includes(val.charAt(0))) {
|
|
541
660
|
return {
|
|
542
|
-
typ:
|
|
661
|
+
typ: EnumToken.UnclosedStringTokenType,
|
|
543
662
|
val
|
|
544
663
|
};
|
|
545
664
|
}
|
|
546
665
|
return {
|
|
547
|
-
typ:
|
|
666
|
+
typ: EnumToken.LiteralTokenType,
|
|
548
667
|
val
|
|
549
668
|
};
|
|
550
669
|
}
|
|
551
670
|
function parseTokens(tokens, options = {}) {
|
|
552
671
|
for (let i = 0; i < tokens.length; i++) {
|
|
553
672
|
const t = tokens[i];
|
|
554
|
-
if (t.typ ==
|
|
673
|
+
if (t.typ == EnumToken.WhitespaceTokenType && ((i == 0 ||
|
|
555
674
|
i + 1 == tokens.length ||
|
|
556
|
-
[
|
|
675
|
+
[EnumToken.CommaTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.ColumnCombinatorTokenType].includes(tokens[i + 1].typ)) ||
|
|
557
676
|
(i > 0 &&
|
|
558
|
-
// tokens[i + 1]?.typ !=
|
|
677
|
+
// tokens[i + 1]?.typ != Literal ||
|
|
559
678
|
// funcLike.includes(tokens[i - 1].typ) &&
|
|
560
679
|
// !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
|
|
561
680
|
trimWhiteSpace.includes(tokens[i - 1].typ)))) {
|
|
562
681
|
tokens.splice(i--, 1);
|
|
563
682
|
continue;
|
|
564
683
|
}
|
|
565
|
-
if (t.typ ==
|
|
684
|
+
if (t.typ == EnumToken.ColonTokenType) {
|
|
566
685
|
const typ = tokens[i + 1]?.typ;
|
|
567
686
|
if (typ != null) {
|
|
568
|
-
if (typ ==
|
|
687
|
+
if (typ == EnumToken.FunctionTokenType) {
|
|
569
688
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
570
|
-
tokens[i + 1].typ =
|
|
689
|
+
tokens[i + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
571
690
|
}
|
|
572
|
-
else if (typ ==
|
|
691
|
+
else if (typ == EnumToken.IdenTokenType) {
|
|
692
|
+
if (tokens[i + 1].val in webkitPseudoAliasMap) {
|
|
693
|
+
tokens[i + 1].val = webkitPseudoAliasMap[tokens[i + 1].val];
|
|
694
|
+
}
|
|
573
695
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
574
|
-
tokens[i + 1].typ =
|
|
696
|
+
tokens[i + 1].typ = EnumToken.PseudoClassTokenType;
|
|
575
697
|
}
|
|
576
|
-
if (typ ==
|
|
698
|
+
if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
|
|
577
699
|
tokens.splice(i, 1);
|
|
578
700
|
i--;
|
|
579
|
-
continue;
|
|
580
701
|
}
|
|
581
702
|
}
|
|
703
|
+
continue;
|
|
582
704
|
}
|
|
583
|
-
if (t.typ ==
|
|
705
|
+
if (t.typ == EnumToken.AttrStartTokenType) {
|
|
584
706
|
let k = i;
|
|
585
707
|
let inAttr = 1;
|
|
586
708
|
while (++k < tokens.length) {
|
|
587
|
-
if (tokens[k].typ ==
|
|
709
|
+
if (tokens[k].typ == EnumToken.AttrEndTokenType) {
|
|
588
710
|
inAttr--;
|
|
589
711
|
}
|
|
590
|
-
else if (tokens[k].typ ==
|
|
712
|
+
else if (tokens[k].typ == EnumToken.AttrStartTokenType) {
|
|
591
713
|
inAttr++;
|
|
592
714
|
}
|
|
593
715
|
if (inAttr == 0) {
|
|
594
716
|
break;
|
|
595
717
|
}
|
|
596
718
|
}
|
|
597
|
-
Object.assign(t, { typ:
|
|
719
|
+
Object.assign(t, { typ: EnumToken.AttrTokenType, chi: tokens.splice(i + 1, k - i) });
|
|
598
720
|
// @ts-ignore
|
|
599
|
-
if (t.chi.at(-1).typ ==
|
|
721
|
+
if (t.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
|
|
600
722
|
// @ts-ignore
|
|
601
723
|
t.chi.pop();
|
|
724
|
+
}
|
|
725
|
+
// @ts-ignore
|
|
726
|
+
if (t.chi.length > 1) {
|
|
727
|
+
/*(<AttrToken>t).chi =*/
|
|
602
728
|
// @ts-ignore
|
|
603
|
-
|
|
604
|
-
|
|
729
|
+
parseTokens(t.chi, t.typ);
|
|
730
|
+
}
|
|
731
|
+
// @ts-ignore
|
|
732
|
+
// t.chi.forEach(val => {
|
|
733
|
+
// if (val.typ == EnumToken.StringTokenType) {
|
|
734
|
+
// const slice = val.val.slice(1, -1);
|
|
735
|
+
// if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
736
|
+
// Object.assign(val, {typ: EnumToken.IdenTokenType, val: slice});
|
|
737
|
+
// }
|
|
738
|
+
// }
|
|
739
|
+
// });
|
|
740
|
+
let m = t.chi.length;
|
|
741
|
+
let val;
|
|
742
|
+
for (m = 0; m < t.chi.length; m++) {
|
|
743
|
+
val = t.chi[m];
|
|
744
|
+
if (val.typ == EnumToken.StringTokenType) {
|
|
745
|
+
const slice = val.val.slice(1, -1);
|
|
746
|
+
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
747
|
+
Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
else if (val.typ == EnumToken.LiteralTokenType && val.val == '|') {
|
|
751
|
+
let upper = m;
|
|
752
|
+
let lower = m;
|
|
753
|
+
while (++upper < t.chi.length) {
|
|
754
|
+
if (t.chi[upper].typ == EnumToken.CommentTokenType) {
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
while (lower-- > 0) {
|
|
760
|
+
if (t.chi[lower].typ == EnumToken.CommentTokenType) {
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
break;
|
|
764
|
+
}
|
|
605
765
|
// @ts-ignore
|
|
606
|
-
|
|
766
|
+
t.chi[m] = {
|
|
767
|
+
typ: EnumToken.NameSpaceAttributeTokenType,
|
|
768
|
+
l: t.chi[lower],
|
|
769
|
+
r: t.chi[upper]
|
|
770
|
+
};
|
|
771
|
+
t.chi.splice(upper, 1);
|
|
772
|
+
if (lower >= 0) {
|
|
773
|
+
t.chi.splice(lower, 1);
|
|
774
|
+
m--;
|
|
775
|
+
}
|
|
607
776
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
777
|
+
else if ([
|
|
778
|
+
EnumToken.DashMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType
|
|
779
|
+
].includes(t.chi[m].typ)) {
|
|
780
|
+
let upper = m;
|
|
781
|
+
let lower = m;
|
|
782
|
+
while (++upper < t.chi.length) {
|
|
783
|
+
if (t.chi[upper].typ == EnumToken.CommentTokenType) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
break;
|
|
787
|
+
}
|
|
788
|
+
while (lower-- > 0) {
|
|
789
|
+
if (t.chi[lower].typ == EnumToken.CommentTokenType) {
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
val = t.chi[lower];
|
|
795
|
+
if (val.typ == EnumToken.StringTokenType) {
|
|
611
796
|
const slice = val.val.slice(1, -1);
|
|
612
797
|
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
613
|
-
Object.assign(val, { typ:
|
|
798
|
+
Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
|
|
614
799
|
}
|
|
615
800
|
}
|
|
616
|
-
|
|
801
|
+
val = t.chi[upper];
|
|
802
|
+
if (val.typ == EnumToken.StringTokenType) {
|
|
803
|
+
const slice = val.val.slice(1, -1);
|
|
804
|
+
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
805
|
+
Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
t.chi[m] = {
|
|
809
|
+
typ: EnumToken.MatchExpressionTokenType,
|
|
810
|
+
op: t.chi[m].typ,
|
|
811
|
+
l: t.chi[lower],
|
|
812
|
+
r: t.chi[upper]
|
|
813
|
+
};
|
|
814
|
+
t.chi.splice(upper, 1);
|
|
815
|
+
t.chi.splice(lower, 1);
|
|
816
|
+
upper = m;
|
|
817
|
+
m--;
|
|
818
|
+
while (upper < t.chi.length && t.chi[upper].typ == EnumToken.WhitespaceTokenType) {
|
|
819
|
+
upper++;
|
|
820
|
+
}
|
|
821
|
+
if (upper < t.chi.length &&
|
|
822
|
+
t.chi[upper].typ == EnumToken.Iden &&
|
|
823
|
+
['i', 's'].includes(t.chi[upper].val.toLowerCase())) {
|
|
824
|
+
t.chi[m].attr = t.chi[upper].val;
|
|
825
|
+
t.chi.splice(upper, 1);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
m = t.chi.length;
|
|
830
|
+
while (t.chi.at(-1)?.typ == EnumToken.WhitespaceTokenType) {
|
|
831
|
+
t.chi.pop();
|
|
617
832
|
}
|
|
618
833
|
continue;
|
|
619
834
|
}
|
|
@@ -621,18 +836,18 @@ function parseTokens(tokens, options = {}) {
|
|
|
621
836
|
let parens = 1;
|
|
622
837
|
let k = i;
|
|
623
838
|
while (++k < tokens.length) {
|
|
624
|
-
if (tokens[k].typ ==
|
|
839
|
+
if (tokens[k].typ == EnumToken.ColonTokenType) {
|
|
625
840
|
const typ = tokens[k + 1]?.typ;
|
|
626
841
|
if (typ != null) {
|
|
627
|
-
if (typ ==
|
|
628
|
-
tokens[k + 1].typ =
|
|
842
|
+
if (typ == EnumToken.IdenTokenType) {
|
|
843
|
+
tokens[k + 1].typ = EnumToken.PseudoClassTokenType;
|
|
629
844
|
tokens[k + 1].val = ':' + tokens[k + 1].val;
|
|
630
845
|
}
|
|
631
|
-
else if (typ ==
|
|
632
|
-
tokens[k + 1].typ =
|
|
846
|
+
else if (typ == EnumToken.FunctionTokenType) {
|
|
847
|
+
tokens[k + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
633
848
|
tokens[k + 1].val = ':' + tokens[k + 1].val;
|
|
634
849
|
}
|
|
635
|
-
if (typ ==
|
|
850
|
+
if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
|
|
636
851
|
tokens.splice(k, 1);
|
|
637
852
|
k--;
|
|
638
853
|
continue;
|
|
@@ -642,7 +857,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
642
857
|
if (funcLike.includes(tokens[k].typ)) {
|
|
643
858
|
parens++;
|
|
644
859
|
}
|
|
645
|
-
else if (tokens[k].typ ==
|
|
860
|
+
else if (tokens[k].typ == EnumToken.EndParensTokenType) {
|
|
646
861
|
parens--;
|
|
647
862
|
}
|
|
648
863
|
if (parens == 0) {
|
|
@@ -652,29 +867,55 @@ function parseTokens(tokens, options = {}) {
|
|
|
652
867
|
// @ts-ignore
|
|
653
868
|
t.chi = tokens.splice(i + 1, k - i);
|
|
654
869
|
// @ts-ignore
|
|
655
|
-
if (t.chi.at(-1)?.typ ==
|
|
870
|
+
if (t.chi.at(-1)?.typ == EnumToken.EndParensTokenType) {
|
|
656
871
|
// @ts-ignore
|
|
657
872
|
t.chi.pop();
|
|
658
873
|
}
|
|
874
|
+
if (t.typ == EnumToken.FunctionTokenType && t.val == 'calc') {
|
|
875
|
+
for (const { value, parent } of walkValues(t.chi)) {
|
|
876
|
+
if (value.typ == EnumToken.WhitespaceTokenType) {
|
|
877
|
+
const p = (parent ?? t);
|
|
878
|
+
for (let i = 0; i < (p).chi.length; i++) {
|
|
879
|
+
// @ts-ignore
|
|
880
|
+
if (p.chi[i] == value) {
|
|
881
|
+
// @ts-ignore
|
|
882
|
+
(p).chi.splice(i, 1);
|
|
883
|
+
i--;
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
else if (value.typ == EnumToken.LiteralTokenType && ['+', '-', '/', '*'].includes(value.val)) {
|
|
889
|
+
// @ts-ignore
|
|
890
|
+
value.typ = value.val == '+' ? EnumToken.Add : (value.val == '-' ? EnumToken.Sub : (value.val == '*' ? EnumToken.Mul : EnumToken.Div));
|
|
891
|
+
// @ts-ignore
|
|
892
|
+
delete value.val;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
else if (t.typ == EnumToken.StartParensTokenType) {
|
|
897
|
+
// @ts-ignore
|
|
898
|
+
t.typ = EnumToken.ParensTokenType;
|
|
899
|
+
}
|
|
659
900
|
// @ts-ignore
|
|
660
|
-
if (options.parseColor && t.typ ==
|
|
901
|
+
if (options.parseColor && t.typ == EnumToken.FunctionTokenType && isColor(t)) {
|
|
661
902
|
// if (isColor) {
|
|
662
903
|
// @ts-ignore
|
|
663
|
-
t.typ =
|
|
904
|
+
t.typ = EnumToken.ColorTokenType;
|
|
664
905
|
// @ts-ignore
|
|
665
906
|
t.kin = t.val;
|
|
666
907
|
// @ts-ignore
|
|
667
908
|
let m = t.chi.length;
|
|
668
909
|
while (m-- > 0) {
|
|
669
910
|
// @ts-ignore
|
|
670
|
-
if ([
|
|
911
|
+
if ([EnumToken.LiteralTokenType].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
|
|
671
912
|
// @ts-ignore
|
|
672
|
-
if (t.chi[m + 1]?.typ ==
|
|
913
|
+
if (t.chi[m + 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
673
914
|
// @ts-ignore
|
|
674
915
|
t.chi.splice(m + 1, 1);
|
|
675
916
|
}
|
|
676
917
|
// @ts-ignore
|
|
677
|
-
if (t.chi[m - 1]?.typ ==
|
|
918
|
+
if (t.chi[m - 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
678
919
|
// @ts-ignore
|
|
679
920
|
t.chi.splice(m - 1, 1);
|
|
680
921
|
m--;
|
|
@@ -682,22 +923,21 @@ function parseTokens(tokens, options = {}) {
|
|
|
682
923
|
}
|
|
683
924
|
}
|
|
684
925
|
continue;
|
|
685
|
-
// }
|
|
686
926
|
}
|
|
687
|
-
if (t.typ ==
|
|
927
|
+
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
688
928
|
// @ts-ignore
|
|
689
|
-
if (t.chi[0]?.typ ==
|
|
929
|
+
if (t.chi[0]?.typ == EnumToken.StringTokenType) {
|
|
690
930
|
// @ts-ignore
|
|
691
931
|
const value = t.chi[0].val.slice(1, -1);
|
|
692
932
|
// @ts-ignore
|
|
693
933
|
if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
|
|
694
934
|
// @ts-ignore
|
|
695
|
-
t.chi[0].typ =
|
|
935
|
+
t.chi[0].typ = EnumToken.UrlTokenTokenType;
|
|
696
936
|
// @ts-ignore
|
|
697
937
|
t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
|
|
698
938
|
}
|
|
699
939
|
}
|
|
700
|
-
if (t.chi[0]?.typ ==
|
|
940
|
+
if (t.chi[0]?.typ == EnumToken.UrlTokenTokenType) {
|
|
701
941
|
if (options.src !== '' && options.resolveUrls) {
|
|
702
942
|
// @ts-ignore
|
|
703
943
|
t.chi[0].val = options.resolve(t.chi[0].val, options.src, options.cwd).relative;
|
|
@@ -708,13 +948,13 @@ function parseTokens(tokens, options = {}) {
|
|
|
708
948
|
if (t.chi.length > 0) {
|
|
709
949
|
// @ts-ignore
|
|
710
950
|
parseTokens(t.chi, options);
|
|
711
|
-
if (t.typ ==
|
|
951
|
+
if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
|
|
712
952
|
//
|
|
713
|
-
const count = t.chi.filter(t => t.typ !=
|
|
953
|
+
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
|
|
714
954
|
if (count == 1 ||
|
|
715
955
|
(i == 0 &&
|
|
716
|
-
(tokens[i + 1]?.typ ==
|
|
717
|
-
(tokens[i - 1]?.typ ==
|
|
956
|
+
(tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1)) ||
|
|
957
|
+
(tokens[i - 1]?.typ == EnumToken.CommaTokenType && (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1))) {
|
|
718
958
|
tokens.splice(i, 1, ...t.chi);
|
|
719
959
|
i = Math.max(0, i - t.chi.length);
|
|
720
960
|
}
|
|
@@ -723,22 +963,22 @@ function parseTokens(tokens, options = {}) {
|
|
|
723
963
|
continue;
|
|
724
964
|
}
|
|
725
965
|
if (options.parseColor) {
|
|
726
|
-
if (t.typ ==
|
|
966
|
+
if (t.typ == EnumToken.IdenTokenType) {
|
|
727
967
|
// named color
|
|
728
968
|
const value = t.val.toLowerCase();
|
|
729
969
|
if (value in COLORS_NAMES) {
|
|
730
970
|
Object.assign(t, {
|
|
731
|
-
typ:
|
|
971
|
+
typ: EnumToken.ColorTokenType,
|
|
732
972
|
val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
|
|
733
973
|
kin: 'hex'
|
|
734
974
|
});
|
|
735
975
|
}
|
|
736
976
|
continue;
|
|
737
977
|
}
|
|
738
|
-
if (t.typ ==
|
|
978
|
+
if (t.typ == EnumToken.HashTokenType && isHexColor(t.val)) {
|
|
739
979
|
// hex color
|
|
740
980
|
// @ts-ignore
|
|
741
|
-
t.typ =
|
|
981
|
+
t.typ = EnumToken.ColorTokenType;
|
|
742
982
|
// @ts-ignore
|
|
743
983
|
t.kin = 'hex';
|
|
744
984
|
}
|
|
@@ -747,4 +987,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
747
987
|
return tokens;
|
|
748
988
|
}
|
|
749
989
|
|
|
750
|
-
export {
|
|
990
|
+
export { doParse, parseString, parseTokens, urlTokenMatcher };
|