@tbela99/css-parser 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +29 -11
- package/dist/index-umd-web.js +2041 -1967
- package/dist/index.cjs +2129 -1964
- package/dist/index.d.ts +1936 -77
- package/dist/lib/ast/expand.js +4 -65
- package/dist/lib/ast/features/calc.js +3 -27
- package/dist/lib/ast/features/inlinecssvariables.js +2 -21
- package/dist/lib/ast/features/prefix.js +2 -1
- package/dist/lib/ast/features/transform.js +4 -3
- package/dist/lib/ast/features/type.js +9 -0
- package/dist/lib/ast/math/expression.js +26 -149
- package/dist/lib/ast/math/math.js +9 -9
- package/dist/lib/ast/minify.js +82 -171
- package/dist/lib/ast/transform/compute.js +4 -37
- package/dist/lib/ast/transform/matrix.js +33 -34
- package/dist/lib/ast/transform/minify.js +32 -51
- package/dist/lib/ast/transform/perspective.js +1 -1
- package/dist/lib/ast/transform/rotate.js +13 -13
- package/dist/lib/ast/transform/scale.js +8 -8
- package/dist/lib/ast/transform/skew.js +4 -4
- package/dist/lib/ast/transform/translate.js +8 -8
- package/dist/lib/ast/transform/utils.js +31 -39
- package/dist/lib/ast/types.js +459 -5
- package/dist/lib/ast/walk.js +18 -0
- package/dist/lib/fs/resolve.js +11 -3
- package/dist/lib/parser/declaration/map.js +1 -0
- package/dist/lib/parser/declaration/set.js +2 -2
- package/dist/lib/parser/parse.js +139 -32
- package/dist/lib/parser/tokenize.js +41 -93
- package/dist/lib/parser/utils/type.js +1 -1
- package/dist/lib/renderer/render.js +61 -30
- package/dist/lib/renderer/sourcemap/sourcemap.js +34 -0
- package/dist/lib/syntax/color/cmyk.js +2 -2
- package/dist/lib/syntax/color/color-mix.js +11 -12
- package/dist/lib/syntax/color/color.js +14 -7
- package/dist/lib/syntax/color/hsl.js +4 -4
- package/dist/lib/syntax/color/hwb.js +27 -8
- package/dist/lib/syntax/color/lab.js +4 -4
- package/dist/lib/syntax/color/lch.js +4 -4
- package/dist/lib/syntax/color/oklab.js +4 -4
- package/dist/lib/syntax/color/oklch.js +4 -4
- package/dist/lib/syntax/color/relativecolor.js +1 -1
- package/dist/lib/syntax/color/rgb.js +4 -4
- package/dist/lib/syntax/color/utils/components.js +15 -3
- package/dist/lib/syntax/color/utils/distance.js +15 -1
- package/dist/lib/syntax/syntax.js +18 -17
- package/dist/lib/syntax/utils.js +1 -1
- package/dist/lib/validation/at-rules/document.js +1 -1
- package/dist/lib/validation/at-rules/import.js +4 -4
- package/dist/lib/validation/at-rules/keyframes.js +0 -11
- package/dist/lib/validation/at-rules/supports.js +6 -6
- package/dist/lib/validation/config.js +0 -4
- package/dist/lib/validation/config.json.js +33 -30
- package/dist/lib/validation/parser/parse.js +0 -8
- package/dist/lib/validation/selector.js +0 -9
- package/dist/lib/validation/syntax.js +17 -135
- package/dist/lib/validation/syntaxes/complex-selector-list.js +0 -11
- package/dist/lib/validation/syntaxes/family-name.js +0 -32
- package/dist/lib/validation/syntaxes/keyframe-selector.js +0 -11
- package/dist/lib/validation/syntaxes/relative-selector-list.js +0 -26
- package/dist/lib/validation/syntaxes/url.js +0 -33
- package/dist/lib/validation/utils/list.js +0 -8
- package/dist/node.js +229 -0
- package/dist/web.js +158 -0
- package/package.json +14 -11
- package/dist/node/index.js +0 -57
- package/dist/node/load.js +0 -20
- package/dist/web/index.js +0 -66
- package/dist/web/load.js +0 -31
|
@@ -7,6 +7,7 @@ import '../../ast/walk.js';
|
|
|
7
7
|
import { parseString } from '../parse.js';
|
|
8
8
|
import '../tokenize.js';
|
|
9
9
|
import { renderToken } from '../../renderer/render.js';
|
|
10
|
+
import '../../renderer/sourcemap/lib/encode.js';
|
|
10
11
|
import '../../syntax/color/utils/constants.js';
|
|
11
12
|
import { PropertySet } from './set.js';
|
|
12
13
|
|
|
@@ -15,7 +15,7 @@ function dedup(values) {
|
|
|
15
15
|
while (i-- > 1) {
|
|
16
16
|
const t = value[i];
|
|
17
17
|
const k = value[i == 1 ? 0 : i % 2];
|
|
18
|
-
if (t.val == k.val && t.val ==
|
|
18
|
+
if (t.val == k.val && t.val == 0) {
|
|
19
19
|
if ((t.typ == EnumToken.NumberTokenType && isLength(k)) ||
|
|
20
20
|
(k.typ == EnumToken.NumberTokenType && isLength(t)) ||
|
|
21
21
|
(isLength(k) || isLength(t))) {
|
|
@@ -52,7 +52,7 @@ class PropertySet {
|
|
|
52
52
|
// @ts-ignore
|
|
53
53
|
for (let token of this.declarations.get(this.config.shorthand).val) {
|
|
54
54
|
// @ts-ignore
|
|
55
|
-
if (this.config.types.some(t => token.typ == EnumToken[t]) || (token.typ == EnumToken.NumberTokenType && token.val ==
|
|
55
|
+
if (this.config.types.some(t => token.typ == EnumToken[t]) || (token.typ == EnumToken.NumberTokenType && token.val == 0 &&
|
|
56
56
|
(this.config.types.includes('Length') ||
|
|
57
57
|
this.config.types.includes('Angle') ||
|
|
58
58
|
this.config.types.includes('Dimension')))) {
|
package/dist/lib/parser/parse.js
CHANGED
|
@@ -6,9 +6,10 @@ import { expand } from '../ast/expand.js';
|
|
|
6
6
|
import './utils/config.js';
|
|
7
7
|
import { parseDeclarationNode } from './utils/declaration.js';
|
|
8
8
|
import { renderToken } from '../renderer/render.js';
|
|
9
|
+
import '../renderer/sourcemap/lib/encode.js';
|
|
9
10
|
import { funcLike, timingFunc, timelineFunc, COLORS_NAMES, systemColors, deprecatedSystemColors, colorsFunc } from '../syntax/color/utils/constants.js';
|
|
10
11
|
import { buildExpression } from '../ast/math/expression.js';
|
|
11
|
-
import { tokenize } from './tokenize.js';
|
|
12
|
+
import { tokenize, tokenizeStream } from './tokenize.js';
|
|
12
13
|
import '../validation/config.js';
|
|
13
14
|
import '../validation/parser/types.js';
|
|
14
15
|
import '../validation/parser/parse.js';
|
|
@@ -40,10 +41,12 @@ function reject(reason) {
|
|
|
40
41
|
}
|
|
41
42
|
/**
|
|
42
43
|
* parse css string
|
|
43
|
-
* @param
|
|
44
|
+
* @param iter
|
|
44
45
|
* @param options
|
|
46
|
+
*
|
|
47
|
+
* @private
|
|
45
48
|
*/
|
|
46
|
-
async function doParse(
|
|
49
|
+
async function doParse(iter, options = {}) {
|
|
47
50
|
if (options.signal != null) {
|
|
48
51
|
options.signal.addEventListener('abort', reject);
|
|
49
52
|
}
|
|
@@ -113,15 +116,28 @@ async function doParse(iterator, options = {}) {
|
|
|
113
116
|
src: ''
|
|
114
117
|
};
|
|
115
118
|
}
|
|
116
|
-
const iter = tokenize(iterator);
|
|
117
119
|
let item;
|
|
118
120
|
let node;
|
|
119
121
|
const rawTokens = [];
|
|
120
122
|
const imports = [];
|
|
121
|
-
|
|
123
|
+
// @ts-ignore ignore error
|
|
124
|
+
const isAsync = typeof iter[Symbol.asyncIterator] === 'function';
|
|
125
|
+
while (item = isAsync ? (await iter.next()).value : iter.next().value) {
|
|
122
126
|
stats.bytesIn = item.bytesIn;
|
|
123
127
|
rawTokens.push(item);
|
|
124
128
|
if (item.hint != null && BadTokensTypes.includes(item.hint)) {
|
|
129
|
+
const node = getTokenType(item.token, item.hint);
|
|
130
|
+
errors.push({
|
|
131
|
+
action: 'drop',
|
|
132
|
+
message: 'Bad token',
|
|
133
|
+
syntax: null,
|
|
134
|
+
node,
|
|
135
|
+
location: {
|
|
136
|
+
src,
|
|
137
|
+
sta: item.sta,
|
|
138
|
+
end: item.end
|
|
139
|
+
}
|
|
140
|
+
});
|
|
125
141
|
// bad token
|
|
126
142
|
continue;
|
|
127
143
|
}
|
|
@@ -150,7 +166,7 @@ async function doParse(iterator, options = {}) {
|
|
|
150
166
|
let inBlock = 1;
|
|
151
167
|
tokens = [item];
|
|
152
168
|
do {
|
|
153
|
-
item = iter.next().value;
|
|
169
|
+
item = isAsync ? (await iter.next()).value : iter.next().value;
|
|
154
170
|
if (item == null) {
|
|
155
171
|
break;
|
|
156
172
|
}
|
|
@@ -166,7 +182,12 @@ async function doParse(iterator, options = {}) {
|
|
|
166
182
|
errors.push({
|
|
167
183
|
action: 'drop',
|
|
168
184
|
message: 'invalid block',
|
|
169
|
-
rawTokens: tokens.slice()
|
|
185
|
+
rawTokens: tokens.slice(),
|
|
186
|
+
location: {
|
|
187
|
+
src,
|
|
188
|
+
sta: tokens[0].sta,
|
|
189
|
+
end: tokens[tokens.length - 1].end
|
|
190
|
+
}
|
|
170
191
|
});
|
|
171
192
|
}
|
|
172
193
|
}
|
|
@@ -207,8 +228,8 @@ async function doParse(iterator, options = {}) {
|
|
|
207
228
|
}
|
|
208
229
|
}
|
|
209
230
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
210
|
-
// @ts-ignore
|
|
211
|
-
const index = context.chi.findIndex((node) => node
|
|
231
|
+
// @ts-ignore ignore error
|
|
232
|
+
const index = context.chi.findIndex((node) => node === context);
|
|
212
233
|
if (index > -1) {
|
|
213
234
|
context.chi.splice(index, 1);
|
|
214
235
|
}
|
|
@@ -219,13 +240,21 @@ async function doParse(iterator, options = {}) {
|
|
|
219
240
|
const token = node.tokens[0];
|
|
220
241
|
const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
|
|
221
242
|
try {
|
|
222
|
-
const root = await options.
|
|
223
|
-
return doParse(
|
|
243
|
+
const root = await options.getStream(url, options.src).then(async (stream) => {
|
|
244
|
+
return doParse(tokenizeStream(stream), Object.assign({}, options, {
|
|
224
245
|
minify: false,
|
|
225
246
|
setParent: false,
|
|
226
247
|
src: options.resolve(url, options.src).absolute
|
|
227
|
-
}));
|
|
248
|
+
})); // )
|
|
228
249
|
});
|
|
250
|
+
// const root: ParseResult = await options.load!(url, <string>options.src).then((src: string) => {
|
|
251
|
+
//
|
|
252
|
+
// return doParse(src, Object.assign({}, options, {
|
|
253
|
+
// minify: false,
|
|
254
|
+
// setParent: false,
|
|
255
|
+
// src: options.resolve!(url, options.src as string).absolute
|
|
256
|
+
// }))
|
|
257
|
+
// });
|
|
229
258
|
stats.importedBytesIn += root.stats.bytesIn;
|
|
230
259
|
stats.imports.push(root.stats);
|
|
231
260
|
node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
|
|
@@ -234,7 +263,7 @@ async function doParse(iterator, options = {}) {
|
|
|
234
263
|
}
|
|
235
264
|
}
|
|
236
265
|
catch (error) {
|
|
237
|
-
// @ts-ignore
|
|
266
|
+
// @ts-ignore ignore error
|
|
238
267
|
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
239
268
|
}
|
|
240
269
|
}));
|
|
@@ -258,28 +287,33 @@ async function doParse(iterator, options = {}) {
|
|
|
258
287
|
if (result.node.typ == EnumToken.DeclarationNodeType &&
|
|
259
288
|
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
260
289
|
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
261
|
-
const
|
|
290
|
+
const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
|
|
291
|
+
const results = isAsync ? await callable(result.node) : callable(result.node);
|
|
262
292
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
263
293
|
continue;
|
|
264
294
|
}
|
|
295
|
+
// @ts-ignore
|
|
265
296
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
266
297
|
}
|
|
267
298
|
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
268
|
-
const
|
|
299
|
+
const isAsync = Object.getPrototypeOf(options.visitor.Rule).constructor.name == 'AsyncFunction';
|
|
300
|
+
const results = isAsync ? await options.visitor.Rule(result.node) : options.visitor.Rule(result.node);
|
|
269
301
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
270
302
|
continue;
|
|
271
303
|
}
|
|
304
|
+
// @ts-ignore
|
|
272
305
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
273
306
|
}
|
|
274
307
|
else if (options.visitor.AtRule != null &&
|
|
275
308
|
result.node.typ == EnumToken.AtRuleNodeType &&
|
|
276
|
-
// @ts-ignore
|
|
277
309
|
(typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
|
|
278
310
|
const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
|
|
279
|
-
const
|
|
311
|
+
const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
|
|
312
|
+
const results = isAsync ? await callable(result.node) : callable(result.node);
|
|
280
313
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
281
314
|
continue;
|
|
282
315
|
}
|
|
316
|
+
// @ts-ignore
|
|
283
317
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
284
318
|
}
|
|
285
319
|
}
|
|
@@ -334,6 +368,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
334
368
|
errors.push({
|
|
335
369
|
action: 'drop',
|
|
336
370
|
message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
|
|
371
|
+
node: tokens[i],
|
|
337
372
|
location
|
|
338
373
|
});
|
|
339
374
|
continue;
|
|
@@ -388,7 +423,14 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
388
423
|
if (!(type == EnumToken.InvalidAtRuleTokenType &&
|
|
389
424
|
// @ts-ignore
|
|
390
425
|
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
391
|
-
|
|
426
|
+
// @ts-ignore
|
|
427
|
+
errors.push({
|
|
428
|
+
action: 'drop',
|
|
429
|
+
message: 'invalid @import',
|
|
430
|
+
location,
|
|
431
|
+
// @ts-ignore
|
|
432
|
+
rawTokens: [atRule, ...tokens]
|
|
433
|
+
});
|
|
392
434
|
return null;
|
|
393
435
|
}
|
|
394
436
|
}
|
|
@@ -464,7 +506,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
464
506
|
action: 'drop',
|
|
465
507
|
message: '@charset must have only one space',
|
|
466
508
|
// @ts-ignore
|
|
467
|
-
location
|
|
509
|
+
location, rawTokens: [atRule, ...tokens]
|
|
468
510
|
});
|
|
469
511
|
return null;
|
|
470
512
|
}
|
|
@@ -533,6 +575,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
533
575
|
errors.push({
|
|
534
576
|
action: 'drop',
|
|
535
577
|
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
578
|
+
node,
|
|
536
579
|
// @ts-ignore
|
|
537
580
|
location: { src, ...(map.get(valid.node) ?? location) }
|
|
538
581
|
});
|
|
@@ -581,7 +624,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
581
624
|
if (curr.typ == EnumToken.IdenTokenType && curr.val == 'from') {
|
|
582
625
|
Object.assign(curr, { typ: EnumToken.PercentageTokenType, val: '0' });
|
|
583
626
|
}
|
|
584
|
-
else if (curr.typ == EnumToken.PercentageTokenType && curr.val ==
|
|
627
|
+
else if (curr.typ == EnumToken.PercentageTokenType && curr.val == 100) {
|
|
585
628
|
Object.assign(curr, { typ: EnumToken.IdenTokenType, val: 'to' });
|
|
586
629
|
}
|
|
587
630
|
}
|
|
@@ -634,6 +677,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
634
677
|
errors.push({
|
|
635
678
|
action: 'drop',
|
|
636
679
|
message: valid.error + ' - "' + tokens.reduce((acc, curr) => acc + renderToken(curr, { minify: false }), '') + '"',
|
|
680
|
+
node,
|
|
637
681
|
// @ts-ignore
|
|
638
682
|
location
|
|
639
683
|
});
|
|
@@ -658,7 +702,7 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
658
702
|
val: tokens[i].val.charAt(0)
|
|
659
703
|
}, {
|
|
660
704
|
typ: EnumToken.NumberTokenType,
|
|
661
|
-
val: tokens[i].val.slice(1)
|
|
705
|
+
val: +tokens[i].val.slice(1)
|
|
662
706
|
});
|
|
663
707
|
}
|
|
664
708
|
else if (start == '/' && isFunction(val)) {
|
|
@@ -859,9 +903,10 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
859
903
|
}
|
|
860
904
|
}
|
|
861
905
|
}
|
|
906
|
+
const val = value.typ == EnumToken.IdenTokenType ? value.val.toLowerCase() : null;
|
|
862
907
|
if (value.typ == EnumToken.IdenTokenType) {
|
|
863
908
|
if (parent == null && mediaTypes.some((t) => {
|
|
864
|
-
if (
|
|
909
|
+
if (val === t) {
|
|
865
910
|
// @ts-ignore
|
|
866
911
|
value.typ = EnumToken.MediaFeatureTokenType;
|
|
867
912
|
return true;
|
|
@@ -870,18 +915,18 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
870
915
|
})) {
|
|
871
916
|
continue;
|
|
872
917
|
}
|
|
873
|
-
if (value.typ == EnumToken.IdenTokenType && 'and'
|
|
918
|
+
if (value.typ == EnumToken.IdenTokenType && 'and' === val) {
|
|
874
919
|
// @ts-ignore
|
|
875
920
|
value.typ = EnumToken.MediaFeatureAndTokenType;
|
|
876
921
|
continue;
|
|
877
922
|
}
|
|
878
|
-
if (value.typ == EnumToken.IdenTokenType && 'or'
|
|
923
|
+
if (value.typ == EnumToken.IdenTokenType && 'or' === val) {
|
|
879
924
|
// @ts-ignore
|
|
880
925
|
value.typ = EnumToken.MediaFeatureOrTokenType;
|
|
881
926
|
continue;
|
|
882
927
|
}
|
|
883
928
|
if (value.typ == EnumToken.IdenTokenType &&
|
|
884
|
-
['not', 'only'].some((t) =>
|
|
929
|
+
['not', 'only'].some((t) => val === t)) {
|
|
885
930
|
// @ts-ignore
|
|
886
931
|
const array = parent?.chi ?? tokens;
|
|
887
932
|
const startIndex = array.indexOf(value);
|
|
@@ -982,6 +1027,27 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
982
1027
|
}
|
|
983
1028
|
return tokens;
|
|
984
1029
|
}
|
|
1030
|
+
/**
|
|
1031
|
+
* parse a string as an array of declaration nodes
|
|
1032
|
+
* @param declaration
|
|
1033
|
+
*
|
|
1034
|
+
* Example:
|
|
1035
|
+
* ````ts
|
|
1036
|
+
*
|
|
1037
|
+
* const declarations = await parseDeclarations('color: red; background: blue');
|
|
1038
|
+
* console.log(declarations);
|
|
1039
|
+
* ```
|
|
1040
|
+
*/
|
|
1041
|
+
async function parseDeclarations(declaration) {
|
|
1042
|
+
return doParse(tokenize({
|
|
1043
|
+
stream: `.x{${declaration}}`,
|
|
1044
|
+
buffer: '',
|
|
1045
|
+
position: { ind: 0, lin: 1, col: 1 },
|
|
1046
|
+
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
1047
|
+
}), { setParent: false, minify: false, validation: false }).then(result => {
|
|
1048
|
+
return result.ast.chi[0].chi.filter(t => t.typ == EnumToken.DeclarationNodeType);
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
985
1051
|
/**
|
|
986
1052
|
* parse selector
|
|
987
1053
|
* @param tokens
|
|
@@ -1083,12 +1149,33 @@ function parseSelector(tokens) {
|
|
|
1083
1149
|
return tokens;
|
|
1084
1150
|
}
|
|
1085
1151
|
/**
|
|
1086
|
-
* parse css string
|
|
1152
|
+
* parse css string and return an array of tokens
|
|
1087
1153
|
* @param src
|
|
1088
1154
|
* @param options
|
|
1155
|
+
*
|
|
1156
|
+
* @private
|
|
1157
|
+
*
|
|
1158
|
+
* Example:
|
|
1159
|
+
*
|
|
1160
|
+
* ```ts
|
|
1161
|
+
*
|
|
1162
|
+
* import {parseString} from '@tbela99/css-parser';
|
|
1163
|
+
*
|
|
1164
|
+
* let tokens = parseString('body { color: red; }');
|
|
1165
|
+
* console.log(tokens);
|
|
1166
|
+
*
|
|
1167
|
+
* tokens = parseString('#c322c980');
|
|
1168
|
+
* console.log(tokens);
|
|
1169
|
+
* ```
|
|
1089
1170
|
*/
|
|
1090
1171
|
function parseString(src, options = { location: false }) {
|
|
1091
|
-
|
|
1172
|
+
const parseInfo = {
|
|
1173
|
+
stream: src,
|
|
1174
|
+
buffer: '',
|
|
1175
|
+
position: { ind: 0, lin: 1, col: 1 },
|
|
1176
|
+
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
1177
|
+
};
|
|
1178
|
+
return parseTokens([...tokenize(parseInfo)].reduce((acc, t) => {
|
|
1092
1179
|
if (t.hint == EnumToken.EOFTokenType) {
|
|
1093
1180
|
return acc;
|
|
1094
1181
|
}
|
|
@@ -1100,6 +1187,11 @@ function parseString(src, options = { location: false }) {
|
|
|
1100
1187
|
return acc;
|
|
1101
1188
|
}, []));
|
|
1102
1189
|
}
|
|
1190
|
+
/**
|
|
1191
|
+
* get token type from a string
|
|
1192
|
+
* @param val
|
|
1193
|
+
* @param hint
|
|
1194
|
+
*/
|
|
1103
1195
|
function getTokenType(val, hint) {
|
|
1104
1196
|
if (hint != null) {
|
|
1105
1197
|
return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
|
|
@@ -1194,19 +1286,19 @@ function getTokenType(val, hint) {
|
|
|
1194
1286
|
if (isNumber(val)) {
|
|
1195
1287
|
return {
|
|
1196
1288
|
typ: EnumToken.NumberTokenType,
|
|
1197
|
-
val
|
|
1289
|
+
val: +val
|
|
1198
1290
|
};
|
|
1199
1291
|
}
|
|
1200
1292
|
if (isPercentage(val)) {
|
|
1201
1293
|
return {
|
|
1202
1294
|
typ: EnumToken.PercentageTokenType,
|
|
1203
|
-
val: val.slice(0, -1)
|
|
1295
|
+
val: +val.slice(0, -1)
|
|
1204
1296
|
};
|
|
1205
1297
|
}
|
|
1206
1298
|
if (isFlex(val)) {
|
|
1207
1299
|
return {
|
|
1208
1300
|
typ: EnumToken.FlexTokenType,
|
|
1209
|
-
val: val.slice(0, -2)
|
|
1301
|
+
val: +val.slice(0, -2)
|
|
1210
1302
|
};
|
|
1211
1303
|
}
|
|
1212
1304
|
if (isDimension(val)) {
|
|
@@ -1265,9 +1357,24 @@ function getTokenType(val, hint) {
|
|
|
1265
1357
|
};
|
|
1266
1358
|
}
|
|
1267
1359
|
/**
|
|
1268
|
-
* parse
|
|
1360
|
+
* parse function tokens in a token array
|
|
1269
1361
|
* @param tokens
|
|
1270
1362
|
* @param options
|
|
1363
|
+
*
|
|
1364
|
+
* Example:
|
|
1365
|
+
*
|
|
1366
|
+
* ```ts
|
|
1367
|
+
*
|
|
1368
|
+
* import {parseString, parseTokens} from '@tbela99/css-parser';
|
|
1369
|
+
*
|
|
1370
|
+
* let tokens = parseString('body { color: red; }');
|
|
1371
|
+
* console.log(parseTokens(tokens));
|
|
1372
|
+
*
|
|
1373
|
+
* tokens = parseString('#c322c980');
|
|
1374
|
+
* console.log(parseTokens(tokens));
|
|
1375
|
+
* ```
|
|
1376
|
+
*
|
|
1377
|
+
* @private
|
|
1271
1378
|
*/
|
|
1272
1379
|
function parseTokens(tokens, options = {}) {
|
|
1273
1380
|
for (let i = 0; i < tokens.length; i++) {
|
|
@@ -1555,4 +1662,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
1555
1662
|
return tokens;
|
|
1556
1663
|
}
|
|
1557
1664
|
|
|
1558
|
-
export { doParse, getTokenType, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
1665
|
+
export { doParse, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
@@ -3,7 +3,7 @@ import '../ast/minify.js';
|
|
|
3
3
|
import '../ast/walk.js';
|
|
4
4
|
import './parse.js';
|
|
5
5
|
import './utils/config.js';
|
|
6
|
-
import { isWhiteSpace, isIdentStart, isIdent, isNewLine, isDigit
|
|
6
|
+
import { isWhiteSpace, isIdentStart, isIdent, isNewLine, isDigit } from '../syntax/syntax.js';
|
|
7
7
|
import '../syntax/color/utils/constants.js';
|
|
8
8
|
import '../renderer/sourcemap/lib/encode.js';
|
|
9
9
|
|
|
@@ -40,7 +40,7 @@ var TokenMap;
|
|
|
40
40
|
})(TokenMap || (TokenMap = {}));
|
|
41
41
|
function consumeWhiteSpace(parseInfo) {
|
|
42
42
|
let count = 0;
|
|
43
|
-
while (isWhiteSpace(parseInfo.stream.
|
|
43
|
+
while (isWhiteSpace(parseInfo.stream.charCodeAt(count + parseInfo.currentPosition.ind + 1))) {
|
|
44
44
|
count++;
|
|
45
45
|
}
|
|
46
46
|
next(parseInfo, count);
|
|
@@ -146,11 +146,8 @@ function peek(parseInfo, count = 1) {
|
|
|
146
146
|
}
|
|
147
147
|
return parseInfo.stream.slice(parseInfo.currentPosition.ind + 1, parseInfo.currentPosition.ind + count + 1);
|
|
148
148
|
}
|
|
149
|
-
function prev(parseInfo
|
|
150
|
-
|
|
151
|
-
return parseInfo.currentPosition.ind == 0 ? '' : parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
|
|
152
|
-
}
|
|
153
|
-
return parseInfo.stream.slice(parseInfo.currentPosition.ind - 1 - count, parseInfo.currentPosition.ind - 1);
|
|
149
|
+
function prev(parseInfo) {
|
|
150
|
+
return parseInfo.stream.charAt(parseInfo.currentPosition.ind - 1);
|
|
154
151
|
}
|
|
155
152
|
function next(parseInfo, count = 1) {
|
|
156
153
|
let char = '';
|
|
@@ -170,17 +167,14 @@ function next(parseInfo, count = 1) {
|
|
|
170
167
|
}
|
|
171
168
|
/**
|
|
172
169
|
* tokenize css string
|
|
173
|
-
* @param
|
|
170
|
+
* @param parseInfo
|
|
171
|
+
* @param yieldEOFToken
|
|
174
172
|
*/
|
|
175
|
-
function* tokenize(
|
|
176
|
-
const parseInfo = {
|
|
177
|
-
stream,
|
|
178
|
-
position: { ind: 0, lin: 1, col: 1 },
|
|
179
|
-
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
180
|
-
};
|
|
173
|
+
function* tokenize(parseInfo, yieldEOFToken = true) {
|
|
181
174
|
let value;
|
|
182
|
-
let buffer =
|
|
175
|
+
let buffer = parseInfo.buffer;
|
|
183
176
|
let charCode;
|
|
177
|
+
parseInfo.buffer = '';
|
|
184
178
|
while (value = next(parseInfo)) {
|
|
185
179
|
charCode = value.charCodeAt(0);
|
|
186
180
|
if (isWhiteSpace(charCode)) {
|
|
@@ -424,8 +418,6 @@ function* tokenize(stream) {
|
|
|
424
418
|
value = peek(parseInfo);
|
|
425
419
|
// let cp: number;
|
|
426
420
|
let whitespace = '';
|
|
427
|
-
let hasWhiteSpace = false;
|
|
428
|
-
let errorState = false;
|
|
429
421
|
if (value == '"' || value == "'") {
|
|
430
422
|
const quote = value;
|
|
431
423
|
let inquote = true;
|
|
@@ -445,11 +437,6 @@ function* tokenize(stream) {
|
|
|
445
437
|
break;
|
|
446
438
|
}
|
|
447
439
|
}
|
|
448
|
-
if (value === '') {
|
|
449
|
-
yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
|
|
450
|
-
buffer = '';
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
440
|
charCode = value.charCodeAt(0);
|
|
454
441
|
}
|
|
455
442
|
// '\\'
|
|
@@ -465,7 +452,6 @@ function* tokenize(stream) {
|
|
|
465
452
|
if (isWhiteSpace(charCode)) {
|
|
466
453
|
whitespace += value;
|
|
467
454
|
while (value = peek(parseInfo)) {
|
|
468
|
-
hasWhiteSpace = true;
|
|
469
455
|
if (isWhiteSpace(value?.charCodeAt(0))) {
|
|
470
456
|
whitespace += next(parseInfo);
|
|
471
457
|
continue;
|
|
@@ -488,16 +474,6 @@ function* tokenize(stream) {
|
|
|
488
474
|
}
|
|
489
475
|
while (value = next(parseInfo)) {
|
|
490
476
|
charCode = value.charCodeAt(0);
|
|
491
|
-
if (charCode == 0x5c) {
|
|
492
|
-
buffer += value + next(parseInfo);
|
|
493
|
-
continue;
|
|
494
|
-
}
|
|
495
|
-
if (charCode == 0x29) {
|
|
496
|
-
yield pushToken(buffer, parseInfo, EnumToken.BadStringTokenType);
|
|
497
|
-
yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
|
|
498
|
-
buffer = '';
|
|
499
|
-
break;
|
|
500
|
-
}
|
|
501
477
|
buffer += value;
|
|
502
478
|
}
|
|
503
479
|
if (hasNewLine) {
|
|
@@ -514,49 +490,12 @@ function* tokenize(stream) {
|
|
|
514
490
|
buffer = '';
|
|
515
491
|
while (value = next(parseInfo)) {
|
|
516
492
|
charCode = value.charCodeAt(0);
|
|
517
|
-
// ')'
|
|
518
|
-
if (charCode == 0x29) {
|
|
493
|
+
if (charCode == 0x29) { // ')'
|
|
519
494
|
yield pushToken(buffer, parseInfo, EnumToken.UrlTokenTokenType);
|
|
520
495
|
yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
|
|
521
496
|
buffer = '';
|
|
522
497
|
break;
|
|
523
498
|
}
|
|
524
|
-
if (isWhiteSpace(charCode)) {
|
|
525
|
-
hasWhiteSpace = true;
|
|
526
|
-
whitespace = value;
|
|
527
|
-
while (isWhiteSpace(peek(parseInfo)?.charCodeAt(0))) {
|
|
528
|
-
whitespace += next(parseInfo);
|
|
529
|
-
}
|
|
530
|
-
continue;
|
|
531
|
-
}
|
|
532
|
-
if (isNonPrintable(charCode) ||
|
|
533
|
-
// '"'
|
|
534
|
-
charCode == 0x22 ||
|
|
535
|
-
// "'"
|
|
536
|
-
charCode == 0x27 ||
|
|
537
|
-
// \('
|
|
538
|
-
charCode == 0x28 ||
|
|
539
|
-
hasWhiteSpace) {
|
|
540
|
-
errorState = true;
|
|
541
|
-
}
|
|
542
|
-
if (errorState) {
|
|
543
|
-
buffer += whitespace + value;
|
|
544
|
-
while (value = peek(parseInfo)) {
|
|
545
|
-
charCode = value.charCodeAt(0);
|
|
546
|
-
if (charCode == 0x5c) {
|
|
547
|
-
buffer += next(parseInfo, 2);
|
|
548
|
-
continue;
|
|
549
|
-
}
|
|
550
|
-
// ')'
|
|
551
|
-
if (charCode == 0x29) {
|
|
552
|
-
break;
|
|
553
|
-
}
|
|
554
|
-
buffer += next(parseInfo);
|
|
555
|
-
}
|
|
556
|
-
yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
|
|
557
|
-
buffer = '';
|
|
558
|
-
break;
|
|
559
|
-
}
|
|
560
499
|
buffer += value;
|
|
561
500
|
}
|
|
562
501
|
}
|
|
@@ -595,10 +534,6 @@ function* tokenize(stream) {
|
|
|
595
534
|
buffer = '!';
|
|
596
535
|
break;
|
|
597
536
|
case 64 /* TokenMap.AT */:
|
|
598
|
-
if (buffer.length > 0) {
|
|
599
|
-
yield pushToken(buffer, parseInfo);
|
|
600
|
-
buffer = '';
|
|
601
|
-
}
|
|
602
537
|
buffer = value;
|
|
603
538
|
{
|
|
604
539
|
let val = peek(parseInfo);
|
|
@@ -616,27 +551,40 @@ function* tokenize(stream) {
|
|
|
616
551
|
break;
|
|
617
552
|
default:
|
|
618
553
|
buffer += value;
|
|
619
|
-
if (buffer.length == 1) {
|
|
620
|
-
if (buffer == 'h') {
|
|
621
|
-
if (match(parseInfo, 'ttp://') || match(parseInfo, 'ttps://')) {
|
|
622
|
-
let val = peek(parseInfo);
|
|
623
|
-
while (val != ')' && val != ';' && !isWhiteSpace(val.charCodeAt(0))) {
|
|
624
|
-
buffer += next(parseInfo);
|
|
625
|
-
val = peek(parseInfo);
|
|
626
|
-
}
|
|
627
|
-
yield pushToken(buffer, parseInfo);
|
|
628
|
-
buffer = '';
|
|
629
|
-
break;
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
554
|
break;
|
|
634
555
|
}
|
|
635
556
|
}
|
|
636
|
-
if (
|
|
637
|
-
|
|
557
|
+
if (yieldEOFToken) {
|
|
558
|
+
if (buffer.length > 0) {
|
|
559
|
+
yield pushToken(buffer, parseInfo);
|
|
560
|
+
}
|
|
561
|
+
yield pushToken('', parseInfo, EnumToken.EOFTokenType);
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
parseInfo.buffer = buffer;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* tokenize readable stream
|
|
569
|
+
* @param input
|
|
570
|
+
*/
|
|
571
|
+
async function* tokenizeStream(input) {
|
|
572
|
+
const parseInfo = {
|
|
573
|
+
stream: '',
|
|
574
|
+
buffer: '',
|
|
575
|
+
position: { ind: 0, lin: 1, col: 1 },
|
|
576
|
+
currentPosition: { ind: -1, lin: 1, col: 0 }
|
|
577
|
+
};
|
|
578
|
+
const decoder = new TextDecoder('utf-8');
|
|
579
|
+
const reader = input.getReader();
|
|
580
|
+
while (true) {
|
|
581
|
+
const { done, value } = await reader.read();
|
|
582
|
+
parseInfo.stream += decoder.decode(value, { stream: true });
|
|
583
|
+
yield* tokenize(parseInfo, done);
|
|
584
|
+
if (done) {
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
638
587
|
}
|
|
639
|
-
yield pushToken('', parseInfo, EnumToken.EOFTokenType);
|
|
640
588
|
}
|
|
641
589
|
|
|
642
|
-
export { tokenize };
|
|
590
|
+
export { tokenize, tokenizeStream };
|
|
@@ -14,7 +14,7 @@ function matchType(val, properties) {
|
|
|
14
14
|
(properties.types.some((t) => EnumToken[t] == val.typ))) {
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
|
-
if (val.typ == EnumToken.NumberTokenType && val.val ==
|
|
17
|
+
if (val.typ == EnumToken.NumberTokenType && val.val == 0) {
|
|
18
18
|
// @ts-ignore
|
|
19
19
|
return properties.types.some((type) => {
|
|
20
20
|
// @ts-ignore
|