@tbela99/css-parser 0.0.1-rc7 → 0.1.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 +157 -41
- package/dist/index-umd-web.js +2058 -1242
- package/dist/index.cjs +2052 -1238
- package/dist/index.d.ts +677 -332
- package/dist/lib/ast/expand.js +14 -20
- package/dist/lib/ast/features/calc.js +256 -0
- package/dist/lib/ast/features/index.js +3 -0
- package/dist/lib/ast/features/inlinecssvariables.js +115 -0
- package/dist/lib/ast/features/shorthand.js +45 -0
- package/dist/lib/ast/minify.js +395 -371
- package/dist/lib/ast/types.js +88 -0
- package/dist/lib/ast/utiles/minifyfeature.js +8 -0
- package/dist/lib/ast/walk.js +24 -9
- package/dist/lib/parser/declaration/list.js +18 -4
- package/dist/lib/parser/declaration/map.js +51 -30
- package/dist/lib/parser/declaration/set.js +18 -12
- package/dist/lib/parser/parse.js +176 -136
- package/dist/lib/parser/tokenize.js +42 -35
- package/dist/lib/parser/utils/eq.js +1 -1
- package/dist/lib/parser/utils/syntax.js +13 -10
- package/dist/lib/parser/utils/type.js +18 -6
- package/dist/lib/renderer/render.js +201 -79
- 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 +29 -10
- package/dist/web/index.js +33 -12
- package/package.json +5 -4
- package/dist/lib/transform.js +0 -24
package/dist/lib/parser/parse.js
CHANGED
|
@@ -1,37 +1,47 @@
|
|
|
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 } 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
|
-
const startTime = performance.now();
|
|
17
|
-
const errors = [];
|
|
18
|
-
const options = {
|
|
11
|
+
const trimWhiteSpace = [EnumToken.GtTokenType, EnumToken.GteTokenType, EnumToken.LtTokenType, EnumToken.LteTokenType];
|
|
12
|
+
const funcLike = [EnumToken.ParensTokenType, EnumToken.StartParensTokenType, EnumToken.FunctionTokenType, EnumToken.UrlFunctionTokenType, EnumToken.PseudoClassFuncTokenType];
|
|
13
|
+
const BadTokensTypes = [EnumToken.BadCommentTokenType,
|
|
14
|
+
EnumToken.BadCdoTokenType,
|
|
15
|
+
EnumToken.BadUrlTokenType,
|
|
16
|
+
EnumToken.BadStringTokenType];
|
|
17
|
+
async function doParse(iterator, options = {}) {
|
|
18
|
+
options = {
|
|
19
19
|
src: '',
|
|
20
20
|
sourcemap: false,
|
|
21
21
|
minify: true,
|
|
22
22
|
nestingRules: false,
|
|
23
23
|
resolveImport: false,
|
|
24
24
|
resolveUrls: false,
|
|
25
|
+
removeCharset: false,
|
|
25
26
|
removeEmpty: true,
|
|
26
|
-
|
|
27
|
+
removeDuplicateDeclarations: true,
|
|
28
|
+
computeShorthand: true,
|
|
29
|
+
computeCalcExpression: true,
|
|
30
|
+
inlineCssVariables: false,
|
|
31
|
+
...options
|
|
27
32
|
};
|
|
33
|
+
if (options.expandNestingRules) {
|
|
34
|
+
options.nestingRules = false;
|
|
35
|
+
}
|
|
28
36
|
if (options.resolveImport) {
|
|
29
37
|
options.resolveUrls = true;
|
|
30
38
|
}
|
|
39
|
+
const startTime = performance.now();
|
|
40
|
+
const errors = [];
|
|
31
41
|
const src = options.src;
|
|
32
42
|
const stack = [];
|
|
33
|
-
|
|
34
|
-
typ:
|
|
43
|
+
let ast = {
|
|
44
|
+
typ: 2 /* NodeType.StyleSheetNodeType */,
|
|
35
45
|
chi: []
|
|
36
46
|
};
|
|
37
47
|
let tokens = [];
|
|
@@ -53,10 +63,14 @@ async function parse(iterator, opt = {}) {
|
|
|
53
63
|
let i;
|
|
54
64
|
let loc;
|
|
55
65
|
for (i = 0; i < tokens.length; i++) {
|
|
56
|
-
if (tokens[i].typ ==
|
|
66
|
+
if (tokens[i].typ == EnumToken.CommentTokenType || tokens[i].typ == EnumToken.CDOCOMMTokenType) {
|
|
57
67
|
const position = map.get(tokens[i]);
|
|
58
|
-
if (tokens[i].typ ==
|
|
59
|
-
errors.push({
|
|
68
|
+
if (tokens[i].typ == EnumToken.CDOCOMMTokenType && context.typ != 2 /* NodeType.StyleSheetNodeType */) {
|
|
69
|
+
errors.push({
|
|
70
|
+
action: 'drop',
|
|
71
|
+
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
72
|
+
location: { src, ...position }
|
|
73
|
+
});
|
|
60
74
|
continue;
|
|
61
75
|
}
|
|
62
76
|
loc = {
|
|
@@ -69,7 +83,7 @@ async function parse(iterator, opt = {}) {
|
|
|
69
83
|
tokens[i].loc = loc;
|
|
70
84
|
}
|
|
71
85
|
}
|
|
72
|
-
else if (tokens[i].typ !=
|
|
86
|
+
else if (tokens[i].typ != EnumToken.WhitespaceTokenType) {
|
|
73
87
|
break;
|
|
74
88
|
}
|
|
75
89
|
}
|
|
@@ -78,28 +92,33 @@ async function parse(iterator, opt = {}) {
|
|
|
78
92
|
return null;
|
|
79
93
|
}
|
|
80
94
|
let delim = tokens.at(-1);
|
|
81
|
-
if (delim.typ ==
|
|
95
|
+
if (delim.typ == EnumToken.SemiColonTokenType || delim.typ == EnumToken.BlockStartTokenType || delim.typ == EnumToken.BlockEndTokenType) {
|
|
82
96
|
tokens.pop();
|
|
83
97
|
}
|
|
84
98
|
else {
|
|
85
|
-
delim = { typ:
|
|
99
|
+
delim = { typ: EnumToken.SemiColonTokenType };
|
|
86
100
|
}
|
|
87
101
|
// @ts-ignore
|
|
88
|
-
while ([
|
|
102
|
+
while ([EnumToken.WhitespaceTokenType, EnumToken.BadStringTokenType, EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
|
|
89
103
|
tokens.pop();
|
|
90
104
|
}
|
|
91
105
|
if (tokens.length == 0) {
|
|
92
106
|
return null;
|
|
93
107
|
}
|
|
94
|
-
if (tokens[0]?.typ ==
|
|
108
|
+
if (tokens[0]?.typ == EnumToken.AtRuleTokenType) {
|
|
95
109
|
const atRule = tokens.shift();
|
|
96
110
|
const position = map.get(atRule);
|
|
97
|
-
if (atRule.val == 'charset'
|
|
98
|
-
|
|
99
|
-
|
|
111
|
+
if (atRule.val == 'charset') {
|
|
112
|
+
if (position.ind > 0) {
|
|
113
|
+
errors.push({ action: 'drop', message: 'doParse: invalid @charset', location: { src, ...position } });
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
if (options.removeCharset) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
100
119
|
}
|
|
101
120
|
// @ts-ignore
|
|
102
|
-
while ([
|
|
121
|
+
while ([EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
|
|
103
122
|
tokens.shift();
|
|
104
123
|
}
|
|
105
124
|
if (atRule.val == 'import') {
|
|
@@ -108,10 +127,10 @@ async function parse(iterator, opt = {}) {
|
|
|
108
127
|
let i = context.chi.length;
|
|
109
128
|
while (i--) {
|
|
110
129
|
const type = context.chi[i].typ;
|
|
111
|
-
if (type ==
|
|
130
|
+
if (type == 0 /* NodeType.CommentNodeType */) {
|
|
112
131
|
continue;
|
|
113
132
|
}
|
|
114
|
-
if (type !=
|
|
133
|
+
if (type != 3 /* NodeType.AtRuleNodeType */) {
|
|
115
134
|
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
116
135
|
return null;
|
|
117
136
|
}
|
|
@@ -124,33 +143,33 @@ async function parse(iterator, opt = {}) {
|
|
|
124
143
|
}
|
|
125
144
|
}
|
|
126
145
|
// @ts-ignore
|
|
127
|
-
if (tokens[0]?.typ !=
|
|
128
|
-
errors.push({ action: 'drop', message: '
|
|
146
|
+
if (tokens[0]?.typ != EnumToken.StringTokenType && tokens[0]?.typ != EnumToken.UrlFunctionTokenType) {
|
|
147
|
+
errors.push({ action: 'drop', message: 'doParse: invalid @import', location: { src, ...position } });
|
|
129
148
|
return null;
|
|
130
149
|
}
|
|
131
150
|
// @ts-ignore
|
|
132
|
-
if (tokens[0].typ ==
|
|
133
|
-
errors.push({ action: 'drop', message: '
|
|
151
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1]?.typ != EnumToken.UrlTokenTokenType && tokens[1]?.typ != EnumToken.StringTokenType) {
|
|
152
|
+
errors.push({ action: 'drop', message: 'doParse: invalid @import', location: { src, ...position } });
|
|
134
153
|
return null;
|
|
135
154
|
}
|
|
136
155
|
}
|
|
137
156
|
if (atRule.val == 'import') {
|
|
138
157
|
// @ts-ignore
|
|
139
|
-
if (tokens[0].typ ==
|
|
158
|
+
if (tokens[0].typ == EnumToken.UrlFunctionTokenType && tokens[1].typ == EnumToken.UrlTokenTokenType) {
|
|
140
159
|
tokens.shift();
|
|
141
160
|
// @ts-ignore
|
|
142
|
-
tokens[0].typ =
|
|
161
|
+
tokens[0].typ = EnumToken.StringTokenType;
|
|
143
162
|
// @ts-ignore
|
|
144
163
|
tokens[0].val = `"${tokens[0].val}"`;
|
|
145
164
|
}
|
|
146
165
|
// @ts-ignore
|
|
147
|
-
if (tokens[0].typ ==
|
|
166
|
+
if (tokens[0].typ == EnumToken.StringTokenType) {
|
|
148
167
|
if (options.resolveImport) {
|
|
149
168
|
const url = tokens[0].val.slice(1, -1);
|
|
150
169
|
try {
|
|
151
170
|
// @ts-ignore
|
|
152
171
|
const root = await options.load(url, options.src).then((src) => {
|
|
153
|
-
return
|
|
172
|
+
return doParse(src, Object.assign({}, options, {
|
|
154
173
|
minify: false,
|
|
155
174
|
// @ts-ignore
|
|
156
175
|
src: options.resolve(url, options.src).absolute
|
|
@@ -158,6 +177,7 @@ async function parse(iterator, opt = {}) {
|
|
|
158
177
|
});
|
|
159
178
|
bytesIn += root.stats.bytesIn;
|
|
160
179
|
if (root.ast.chi.length > 0) {
|
|
180
|
+
// @todo - filter charset, layer and scope
|
|
161
181
|
context.chi.push(...root.ast.chi);
|
|
162
182
|
}
|
|
163
183
|
if (root.errors.length > 0) {
|
|
@@ -167,7 +187,7 @@ async function parse(iterator, opt = {}) {
|
|
|
167
187
|
}
|
|
168
188
|
catch (error) {
|
|
169
189
|
// @ts-ignore
|
|
170
|
-
errors.push({ action: 'ignore', message: '
|
|
190
|
+
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
171
191
|
}
|
|
172
192
|
}
|
|
173
193
|
}
|
|
@@ -180,12 +200,12 @@ async function parse(iterator, opt = {}) {
|
|
|
180
200
|
return acc;
|
|
181
201
|
}, []);
|
|
182
202
|
const node = {
|
|
183
|
-
typ:
|
|
203
|
+
typ: 3 /* NodeType.AtRuleNodeType */,
|
|
184
204
|
nam: renderToken(atRule, { removeComments: true }),
|
|
185
205
|
val: raw.join('')
|
|
186
206
|
};
|
|
187
207
|
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
188
|
-
if (delim.typ ==
|
|
208
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
189
209
|
node.chi = [];
|
|
190
210
|
}
|
|
191
211
|
loc = {
|
|
@@ -197,15 +217,15 @@ async function parse(iterator, opt = {}) {
|
|
|
197
217
|
}
|
|
198
218
|
// @ts-ignore
|
|
199
219
|
context.chi.push(node);
|
|
200
|
-
return delim.typ ==
|
|
220
|
+
return delim.typ == EnumToken.BlockStartTokenType ? node : null;
|
|
201
221
|
}
|
|
202
222
|
else {
|
|
203
223
|
// rule
|
|
204
|
-
if (delim.typ ==
|
|
224
|
+
if (delim.typ == EnumToken.BlockStartTokenType) {
|
|
205
225
|
const position = map.get(tokens[0]);
|
|
206
226
|
const uniq = new Map;
|
|
207
227
|
parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
|
|
208
|
-
if (curr.typ ==
|
|
228
|
+
if (curr.typ == EnumToken.WhitespaceTokenType) {
|
|
209
229
|
if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
|
|
210
230
|
trimWhiteSpace.includes(array[index + 1]?.typ) ||
|
|
211
231
|
combinators.includes(array[index - 1]?.val) ||
|
|
@@ -226,7 +246,7 @@ async function parse(iterator, opt = {}) {
|
|
|
226
246
|
return acc;
|
|
227
247
|
}, uniq);
|
|
228
248
|
const node = {
|
|
229
|
-
typ:
|
|
249
|
+
typ: 4 /* NodeType.RuleNodeType */,
|
|
230
250
|
// @ts-ignore
|
|
231
251
|
sel: [...uniq.keys()].join(','),
|
|
232
252
|
chi: []
|
|
@@ -251,10 +271,10 @@ async function parse(iterator, opt = {}) {
|
|
|
251
271
|
// @ts-ignore
|
|
252
272
|
let value = null;
|
|
253
273
|
for (let i = 0; i < tokens.length; i++) {
|
|
254
|
-
if (tokens[i].typ ==
|
|
274
|
+
if (tokens[i].typ == EnumToken.CommentTokenType) {
|
|
255
275
|
continue;
|
|
256
276
|
}
|
|
257
|
-
if (tokens[i].typ ==
|
|
277
|
+
if (tokens[i].typ == EnumToken.ColonTokenType) {
|
|
258
278
|
name = tokens.slice(0, i);
|
|
259
279
|
value = parseTokens(tokens.slice(i + 1), {
|
|
260
280
|
parseColor: true,
|
|
@@ -271,46 +291,38 @@ async function parse(iterator, opt = {}) {
|
|
|
271
291
|
const position = map.get(name[0]);
|
|
272
292
|
if (name.length > 0) {
|
|
273
293
|
for (let i = 1; i < name.length; i++) {
|
|
274
|
-
if (name[i].typ !=
|
|
294
|
+
if (name[i].typ != EnumToken.WhitespaceTokenType && name[i].typ != EnumToken.CommentTokenType) {
|
|
275
295
|
errors.push({
|
|
276
296
|
action: 'drop',
|
|
277
|
-
message: '
|
|
297
|
+
message: 'doParse: invalid declaration',
|
|
278
298
|
location: { src, ...position }
|
|
279
299
|
});
|
|
280
300
|
return null;
|
|
281
301
|
}
|
|
282
302
|
}
|
|
283
303
|
}
|
|
284
|
-
if (value == null) {
|
|
285
|
-
errors.push({
|
|
286
|
-
action: 'drop',
|
|
287
|
-
message: 'parse: invalid declaration',
|
|
288
|
-
location: { src, ...position }
|
|
289
|
-
});
|
|
290
|
-
return null;
|
|
291
|
-
}
|
|
292
|
-
if (value.length == 0) {
|
|
304
|
+
if (value == null || value.length == 0) {
|
|
293
305
|
errors.push({
|
|
294
306
|
action: 'drop',
|
|
295
|
-
message: '
|
|
307
|
+
message: 'doParse: invalid declaration',
|
|
296
308
|
location: { src, ...position }
|
|
297
309
|
});
|
|
298
310
|
return null;
|
|
299
311
|
}
|
|
300
312
|
const node = {
|
|
301
|
-
typ:
|
|
313
|
+
typ: 5 /* NodeType.DeclarationNodeType */,
|
|
302
314
|
// @ts-ignore
|
|
303
315
|
nam: renderToken(name.shift(), { removeComments: true }),
|
|
304
316
|
// @ts-ignore
|
|
305
317
|
val: value
|
|
306
318
|
};
|
|
307
|
-
while (node.val[0]?.typ ==
|
|
319
|
+
while (node.val[0]?.typ == EnumToken.WhitespaceTokenType) {
|
|
308
320
|
node.val.shift();
|
|
309
321
|
}
|
|
310
322
|
if (node.val.length == 0) {
|
|
311
323
|
errors.push({
|
|
312
324
|
action: 'drop',
|
|
313
|
-
message: '
|
|
325
|
+
message: 'doParse: invalid declaration',
|
|
314
326
|
location: { src, ...position }
|
|
315
327
|
});
|
|
316
328
|
return null;
|
|
@@ -330,8 +342,8 @@ async function parse(iterator, opt = {}) {
|
|
|
330
342
|
let item;
|
|
331
343
|
while (item = iter.next().value) {
|
|
332
344
|
bytesIn = item.bytesIn;
|
|
333
|
-
//
|
|
334
|
-
if (item.hint != null && item.hint
|
|
345
|
+
// doParse error
|
|
346
|
+
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
335
347
|
// bad token
|
|
336
348
|
continue;
|
|
337
349
|
}
|
|
@@ -391,9 +403,12 @@ async function parse(iterator, opt = {}) {
|
|
|
391
403
|
break;
|
|
392
404
|
}
|
|
393
405
|
const endParseTime = performance.now();
|
|
406
|
+
if (options.expandNestingRules) {
|
|
407
|
+
ast = expand(ast);
|
|
408
|
+
}
|
|
394
409
|
if (options.minify) {
|
|
395
410
|
if (ast.chi.length > 0) {
|
|
396
|
-
minify(ast, options, true, errors);
|
|
411
|
+
minify(ast, options, true, errors, false);
|
|
397
412
|
}
|
|
398
413
|
}
|
|
399
414
|
const endTime = performance.now();
|
|
@@ -423,81 +438,81 @@ function getTokenType(val, hint) {
|
|
|
423
438
|
}
|
|
424
439
|
if (hint != null) {
|
|
425
440
|
return ([
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
441
|
+
EnumToken.WhitespaceTokenType, EnumToken.SemiColonTokenType, EnumToken.ColonTokenType, EnumToken.BlockStartTokenType,
|
|
442
|
+
EnumToken.BlockStartTokenType, EnumToken.AttrStartTokenType, EnumToken.AttrEndTokenType, EnumToken.StartParensTokenType, EnumToken.EndParensTokenType,
|
|
443
|
+
EnumToken.CommaTokenType, EnumToken.GtTokenType, EnumToken.LtTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType, EnumToken.EOFTokenType
|
|
429
444
|
].includes(hint) ? { typ: hint } : { typ: hint, val });
|
|
430
445
|
}
|
|
431
446
|
if (val == ' ') {
|
|
432
|
-
return { typ:
|
|
447
|
+
return { typ: EnumToken.WhitespaceTokenType };
|
|
433
448
|
}
|
|
434
449
|
if (val == ';') {
|
|
435
|
-
return { typ:
|
|
450
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
436
451
|
}
|
|
437
452
|
if (val == '{') {
|
|
438
|
-
return { typ:
|
|
453
|
+
return { typ: EnumToken.BlockStartTokenType };
|
|
439
454
|
}
|
|
440
455
|
if (val == '}') {
|
|
441
|
-
return { typ:
|
|
456
|
+
return { typ: EnumToken.BlockEndTokenType };
|
|
442
457
|
}
|
|
443
458
|
if (val == '[') {
|
|
444
|
-
return { typ:
|
|
459
|
+
return { typ: EnumToken.AttrStartTokenType };
|
|
445
460
|
}
|
|
446
461
|
if (val == ']') {
|
|
447
|
-
return { typ:
|
|
462
|
+
return { typ: EnumToken.AttrEndTokenType };
|
|
448
463
|
}
|
|
449
464
|
if (val == ':') {
|
|
450
|
-
return { typ:
|
|
465
|
+
return { typ: EnumToken.ColonTokenType };
|
|
451
466
|
}
|
|
452
467
|
if (val == ')') {
|
|
453
|
-
return { typ:
|
|
468
|
+
return { typ: EnumToken.EndParensTokenType };
|
|
454
469
|
}
|
|
455
470
|
if (val == '(') {
|
|
456
|
-
return { typ:
|
|
471
|
+
return { typ: EnumToken.StartParensTokenType };
|
|
457
472
|
}
|
|
458
473
|
if (val == '=') {
|
|
459
|
-
return { typ:
|
|
474
|
+
return { typ: EnumToken.DelimTokenType, val };
|
|
460
475
|
}
|
|
461
476
|
if (val == ';') {
|
|
462
|
-
return { typ:
|
|
477
|
+
return { typ: EnumToken.SemiColonTokenType };
|
|
463
478
|
}
|
|
464
479
|
if (val == ',') {
|
|
465
|
-
return { typ:
|
|
480
|
+
return { typ: EnumToken.CommaTokenType };
|
|
466
481
|
}
|
|
467
482
|
if (val == '<') {
|
|
468
|
-
return { typ:
|
|
483
|
+
return { typ: EnumToken.LtTokenType };
|
|
469
484
|
}
|
|
470
485
|
if (val == '>') {
|
|
471
|
-
return { typ:
|
|
486
|
+
return { typ: EnumToken.GtTokenType };
|
|
472
487
|
}
|
|
473
488
|
if (isPseudo(val)) {
|
|
474
489
|
return val.endsWith('(') ? {
|
|
475
|
-
typ:
|
|
490
|
+
typ: EnumToken.PseudoClassFuncTokenType,
|
|
476
491
|
val: val.slice(0, -1),
|
|
477
492
|
chi: []
|
|
478
493
|
}
|
|
479
494
|
: {
|
|
480
|
-
typ:
|
|
495
|
+
typ: EnumToken.PseudoClassTokenType,
|
|
481
496
|
val
|
|
482
497
|
};
|
|
483
498
|
}
|
|
484
499
|
if (isAtKeyword(val)) {
|
|
485
500
|
return {
|
|
486
|
-
typ:
|
|
501
|
+
typ: EnumToken.AtRuleTokenType,
|
|
487
502
|
val: val.slice(1)
|
|
488
503
|
};
|
|
489
504
|
}
|
|
490
505
|
if (isFunction(val)) {
|
|
491
506
|
val = val.slice(0, -1);
|
|
492
507
|
return {
|
|
493
|
-
typ: val == 'url' ?
|
|
508
|
+
typ: val == 'url' ? EnumToken.UrlFunctionTokenType : EnumToken.FunctionTokenType,
|
|
494
509
|
val,
|
|
495
510
|
chi: []
|
|
496
511
|
};
|
|
497
512
|
}
|
|
498
513
|
if (isNumber(val)) {
|
|
499
514
|
return {
|
|
500
|
-
typ:
|
|
515
|
+
typ: EnumToken.NumberTokenType,
|
|
501
516
|
val
|
|
502
517
|
};
|
|
503
518
|
}
|
|
@@ -506,97 +521,97 @@ function getTokenType(val, hint) {
|
|
|
506
521
|
}
|
|
507
522
|
if (isPercentage(val)) {
|
|
508
523
|
return {
|
|
509
|
-
typ:
|
|
524
|
+
typ: EnumToken.PercentageTokenType,
|
|
510
525
|
val: val.slice(0, -1)
|
|
511
526
|
};
|
|
512
527
|
}
|
|
513
528
|
const v = val.toLowerCase();
|
|
514
529
|
if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
|
|
515
530
|
return {
|
|
516
|
-
typ:
|
|
531
|
+
typ: EnumToken.ColorTokenType,
|
|
517
532
|
val,
|
|
518
533
|
kin: 'lit'
|
|
519
534
|
};
|
|
520
535
|
}
|
|
521
536
|
if (isIdent(val)) {
|
|
522
537
|
return {
|
|
523
|
-
typ:
|
|
538
|
+
typ: EnumToken.IdenTokenType,
|
|
524
539
|
val
|
|
525
540
|
};
|
|
526
541
|
}
|
|
527
542
|
if (val.charAt(0) == '#' && isHexColor(val)) {
|
|
528
543
|
return {
|
|
529
|
-
typ:
|
|
544
|
+
typ: EnumToken.ColorTokenType,
|
|
530
545
|
val,
|
|
531
546
|
kin: 'hex'
|
|
532
547
|
};
|
|
533
548
|
}
|
|
534
549
|
if (val.charAt(0) == '#' && isHash(val)) {
|
|
535
550
|
return {
|
|
536
|
-
typ:
|
|
551
|
+
typ: EnumToken.HashTokenType,
|
|
537
552
|
val
|
|
538
553
|
};
|
|
539
554
|
}
|
|
540
555
|
if ('"\''.includes(val.charAt(0))) {
|
|
541
556
|
return {
|
|
542
|
-
typ:
|
|
557
|
+
typ: EnumToken.UnclosedStringTokenType,
|
|
543
558
|
val
|
|
544
559
|
};
|
|
545
560
|
}
|
|
546
561
|
return {
|
|
547
|
-
typ:
|
|
562
|
+
typ: EnumToken.LiteralTokenType,
|
|
548
563
|
val
|
|
549
564
|
};
|
|
550
565
|
}
|
|
551
566
|
function parseTokens(tokens, options = {}) {
|
|
552
567
|
for (let i = 0; i < tokens.length; i++) {
|
|
553
568
|
const t = tokens[i];
|
|
554
|
-
if (t.typ ==
|
|
569
|
+
if (t.typ == EnumToken.WhitespaceTokenType && ((i == 0 ||
|
|
555
570
|
i + 1 == tokens.length ||
|
|
556
|
-
[
|
|
571
|
+
[EnumToken.CommaTokenType, EnumToken.GteTokenType, EnumToken.LteTokenType].includes(tokens[i + 1].typ)) ||
|
|
557
572
|
(i > 0 &&
|
|
558
|
-
// tokens[i + 1]?.typ !=
|
|
573
|
+
// tokens[i + 1]?.typ != Literal ||
|
|
559
574
|
// funcLike.includes(tokens[i - 1].typ) &&
|
|
560
575
|
// !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
|
|
561
576
|
trimWhiteSpace.includes(tokens[i - 1].typ)))) {
|
|
562
577
|
tokens.splice(i--, 1);
|
|
563
578
|
continue;
|
|
564
579
|
}
|
|
565
|
-
if (t.typ ==
|
|
580
|
+
if (t.typ == EnumToken.ColonTokenType) {
|
|
566
581
|
const typ = tokens[i + 1]?.typ;
|
|
567
582
|
if (typ != null) {
|
|
568
|
-
if (typ ==
|
|
583
|
+
if (typ == EnumToken.FunctionTokenType) {
|
|
569
584
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
570
|
-
tokens[i + 1].typ =
|
|
585
|
+
tokens[i + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
571
586
|
}
|
|
572
|
-
else if (typ ==
|
|
587
|
+
else if (typ == EnumToken.IdenTokenType) {
|
|
573
588
|
tokens[i + 1].val = ':' + tokens[i + 1].val;
|
|
574
|
-
tokens[i + 1].typ =
|
|
589
|
+
tokens[i + 1].typ = EnumToken.PseudoClassTokenType;
|
|
575
590
|
}
|
|
576
|
-
if (typ ==
|
|
591
|
+
if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
|
|
577
592
|
tokens.splice(i, 1);
|
|
578
593
|
i--;
|
|
579
594
|
continue;
|
|
580
595
|
}
|
|
581
596
|
}
|
|
582
597
|
}
|
|
583
|
-
if (t.typ ==
|
|
598
|
+
if (t.typ == EnumToken.AttrStartTokenType) {
|
|
584
599
|
let k = i;
|
|
585
600
|
let inAttr = 1;
|
|
586
601
|
while (++k < tokens.length) {
|
|
587
|
-
if (tokens[k].typ ==
|
|
602
|
+
if (tokens[k].typ == EnumToken.AttrEndTokenType) {
|
|
588
603
|
inAttr--;
|
|
589
604
|
}
|
|
590
|
-
else if (tokens[k].typ ==
|
|
605
|
+
else if (tokens[k].typ == EnumToken.AttrStartTokenType) {
|
|
591
606
|
inAttr++;
|
|
592
607
|
}
|
|
593
608
|
if (inAttr == 0) {
|
|
594
609
|
break;
|
|
595
610
|
}
|
|
596
611
|
}
|
|
597
|
-
Object.assign(t, { typ:
|
|
612
|
+
Object.assign(t, { typ: EnumToken.AttrTokenType, chi: tokens.splice(i + 1, k - i) });
|
|
598
613
|
// @ts-ignore
|
|
599
|
-
if (t.chi.at(-1).typ ==
|
|
614
|
+
if (t.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
|
|
600
615
|
// @ts-ignore
|
|
601
616
|
t.chi.pop();
|
|
602
617
|
// @ts-ignore
|
|
@@ -607,10 +622,10 @@ function parseTokens(tokens, options = {}) {
|
|
|
607
622
|
}
|
|
608
623
|
// @ts-ignore
|
|
609
624
|
t.chi.forEach(val => {
|
|
610
|
-
if (val.typ ==
|
|
625
|
+
if (val.typ == EnumToken.StringTokenType) {
|
|
611
626
|
const slice = val.val.slice(1, -1);
|
|
612
627
|
if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
|
|
613
|
-
Object.assign(val, { typ:
|
|
628
|
+
Object.assign(val, { typ: EnumToken.IdenTokenType, val: slice });
|
|
614
629
|
}
|
|
615
630
|
}
|
|
616
631
|
});
|
|
@@ -621,18 +636,18 @@ function parseTokens(tokens, options = {}) {
|
|
|
621
636
|
let parens = 1;
|
|
622
637
|
let k = i;
|
|
623
638
|
while (++k < tokens.length) {
|
|
624
|
-
if (tokens[k].typ ==
|
|
639
|
+
if (tokens[k].typ == EnumToken.ColonTokenType) {
|
|
625
640
|
const typ = tokens[k + 1]?.typ;
|
|
626
641
|
if (typ != null) {
|
|
627
|
-
if (typ ==
|
|
628
|
-
tokens[k + 1].typ =
|
|
642
|
+
if (typ == EnumToken.IdenTokenType) {
|
|
643
|
+
tokens[k + 1].typ = EnumToken.PseudoClassTokenType;
|
|
629
644
|
tokens[k + 1].val = ':' + tokens[k + 1].val;
|
|
630
645
|
}
|
|
631
|
-
else if (typ ==
|
|
632
|
-
tokens[k + 1].typ =
|
|
646
|
+
else if (typ == EnumToken.FunctionTokenType) {
|
|
647
|
+
tokens[k + 1].typ = EnumToken.PseudoClassFuncTokenType;
|
|
633
648
|
tokens[k + 1].val = ':' + tokens[k + 1].val;
|
|
634
649
|
}
|
|
635
|
-
if (typ ==
|
|
650
|
+
if (typ == EnumToken.FunctionTokenType || typ == EnumToken.IdenTokenType) {
|
|
636
651
|
tokens.splice(k, 1);
|
|
637
652
|
k--;
|
|
638
653
|
continue;
|
|
@@ -642,7 +657,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
642
657
|
if (funcLike.includes(tokens[k].typ)) {
|
|
643
658
|
parens++;
|
|
644
659
|
}
|
|
645
|
-
else if (tokens[k].typ ==
|
|
660
|
+
else if (tokens[k].typ == EnumToken.EndParensTokenType) {
|
|
646
661
|
parens--;
|
|
647
662
|
}
|
|
648
663
|
if (parens == 0) {
|
|
@@ -652,29 +667,55 @@ function parseTokens(tokens, options = {}) {
|
|
|
652
667
|
// @ts-ignore
|
|
653
668
|
t.chi = tokens.splice(i + 1, k - i);
|
|
654
669
|
// @ts-ignore
|
|
655
|
-
if (t.chi.at(-1)?.typ ==
|
|
670
|
+
if (t.chi.at(-1)?.typ == EnumToken.EndParensTokenType) {
|
|
656
671
|
// @ts-ignore
|
|
657
672
|
t.chi.pop();
|
|
658
673
|
}
|
|
674
|
+
if (t.typ == EnumToken.FunctionTokenType && t.val == 'calc') {
|
|
675
|
+
for (const { value, parent } of walkValues(t.chi)) {
|
|
676
|
+
if (value.typ == EnumToken.WhitespaceTokenType) {
|
|
677
|
+
const p = (parent ?? t);
|
|
678
|
+
for (let i = 0; i < (p).chi.length; i++) {
|
|
679
|
+
// @ts-ignore
|
|
680
|
+
if (p.chi[i] == value) {
|
|
681
|
+
// @ts-ignore
|
|
682
|
+
(p).chi.splice(i, 1);
|
|
683
|
+
i--;
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
else if (value.typ == EnumToken.LiteralTokenType && ['+', '-', '/', '*'].includes(value.val)) {
|
|
689
|
+
// @ts-ignore
|
|
690
|
+
value.typ = value.val == '+' ? EnumToken.Add : (value.val == '-' ? EnumToken.Sub : (value.val == '*' ? EnumToken.Mul : EnumToken.Div));
|
|
691
|
+
// @ts-ignore
|
|
692
|
+
delete value.val;
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else if (t.typ == EnumToken.StartParensTokenType) {
|
|
697
|
+
// @ts-ignore
|
|
698
|
+
t.typ = EnumToken.ParensTokenType;
|
|
699
|
+
}
|
|
659
700
|
// @ts-ignore
|
|
660
|
-
if (options.parseColor && t.typ ==
|
|
701
|
+
if (options.parseColor && t.typ == EnumToken.FunctionTokenType && isColor(t)) {
|
|
661
702
|
// if (isColor) {
|
|
662
703
|
// @ts-ignore
|
|
663
|
-
t.typ =
|
|
704
|
+
t.typ = EnumToken.ColorTokenType;
|
|
664
705
|
// @ts-ignore
|
|
665
706
|
t.kin = t.val;
|
|
666
707
|
// @ts-ignore
|
|
667
708
|
let m = t.chi.length;
|
|
668
709
|
while (m-- > 0) {
|
|
669
710
|
// @ts-ignore
|
|
670
|
-
if ([
|
|
711
|
+
if ([EnumToken.LiteralTokenType].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
|
|
671
712
|
// @ts-ignore
|
|
672
|
-
if (t.chi[m + 1]?.typ ==
|
|
713
|
+
if (t.chi[m + 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
673
714
|
// @ts-ignore
|
|
674
715
|
t.chi.splice(m + 1, 1);
|
|
675
716
|
}
|
|
676
717
|
// @ts-ignore
|
|
677
|
-
if (t.chi[m - 1]?.typ ==
|
|
718
|
+
if (t.chi[m - 1]?.typ == EnumToken.WhitespaceTokenType) {
|
|
678
719
|
// @ts-ignore
|
|
679
720
|
t.chi.splice(m - 1, 1);
|
|
680
721
|
m--;
|
|
@@ -682,22 +723,21 @@ function parseTokens(tokens, options = {}) {
|
|
|
682
723
|
}
|
|
683
724
|
}
|
|
684
725
|
continue;
|
|
685
|
-
// }
|
|
686
726
|
}
|
|
687
|
-
if (t.typ ==
|
|
727
|
+
if (t.typ == EnumToken.UrlFunctionTokenType) {
|
|
688
728
|
// @ts-ignore
|
|
689
|
-
if (t.chi[0]?.typ ==
|
|
729
|
+
if (t.chi[0]?.typ == EnumToken.StringTokenType) {
|
|
690
730
|
// @ts-ignore
|
|
691
731
|
const value = t.chi[0].val.slice(1, -1);
|
|
692
732
|
// @ts-ignore
|
|
693
733
|
if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
|
|
694
734
|
// @ts-ignore
|
|
695
|
-
t.chi[0].typ =
|
|
735
|
+
t.chi[0].typ = EnumToken.UrlTokenTokenType;
|
|
696
736
|
// @ts-ignore
|
|
697
737
|
t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
|
|
698
738
|
}
|
|
699
739
|
}
|
|
700
|
-
if (t.chi[0]?.typ ==
|
|
740
|
+
if (t.chi[0]?.typ == EnumToken.UrlTokenTokenType) {
|
|
701
741
|
if (options.src !== '' && options.resolveUrls) {
|
|
702
742
|
// @ts-ignore
|
|
703
743
|
t.chi[0].val = options.resolve(t.chi[0].val, options.src, options.cwd).relative;
|
|
@@ -708,13 +748,13 @@ function parseTokens(tokens, options = {}) {
|
|
|
708
748
|
if (t.chi.length > 0) {
|
|
709
749
|
// @ts-ignore
|
|
710
750
|
parseTokens(t.chi, options);
|
|
711
|
-
if (t.typ ==
|
|
751
|
+
if (t.typ == EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
|
|
712
752
|
//
|
|
713
|
-
const count = t.chi.filter(t => t.typ !=
|
|
753
|
+
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
|
|
714
754
|
if (count == 1 ||
|
|
715
755
|
(i == 0 &&
|
|
716
|
-
(tokens[i + 1]?.typ ==
|
|
717
|
-
(tokens[i - 1]?.typ ==
|
|
756
|
+
(tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1)) ||
|
|
757
|
+
(tokens[i - 1]?.typ == EnumToken.CommaTokenType && (tokens[i + 1]?.typ == EnumToken.CommaTokenType || tokens.length == i + 1))) {
|
|
718
758
|
tokens.splice(i, 1, ...t.chi);
|
|
719
759
|
i = Math.max(0, i - t.chi.length);
|
|
720
760
|
}
|
|
@@ -723,22 +763,22 @@ function parseTokens(tokens, options = {}) {
|
|
|
723
763
|
continue;
|
|
724
764
|
}
|
|
725
765
|
if (options.parseColor) {
|
|
726
|
-
if (t.typ ==
|
|
766
|
+
if (t.typ == EnumToken.IdenTokenType) {
|
|
727
767
|
// named color
|
|
728
768
|
const value = t.val.toLowerCase();
|
|
729
769
|
if (value in COLORS_NAMES) {
|
|
730
770
|
Object.assign(t, {
|
|
731
|
-
typ:
|
|
771
|
+
typ: EnumToken.ColorTokenType,
|
|
732
772
|
val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
|
|
733
773
|
kin: 'hex'
|
|
734
774
|
});
|
|
735
775
|
}
|
|
736
776
|
continue;
|
|
737
777
|
}
|
|
738
|
-
if (t.typ ==
|
|
778
|
+
if (t.typ == EnumToken.HashTokenType && isHexColor(t.val)) {
|
|
739
779
|
// hex color
|
|
740
780
|
// @ts-ignore
|
|
741
|
-
t.typ =
|
|
781
|
+
t.typ = EnumToken.ColorTokenType;
|
|
742
782
|
// @ts-ignore
|
|
743
783
|
t.kin = 'hex';
|
|
744
784
|
}
|
|
@@ -747,4 +787,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
747
787
|
return tokens;
|
|
748
788
|
}
|
|
749
789
|
|
|
750
|
-
export {
|
|
790
|
+
export { doParse, parseString, parseTokens, urlTokenMatcher };
|