@tbela99/css-parser 1.3.0 → 1.3.2
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 +10 -0
- package/README.md +28 -10
- package/dist/index-umd-web.js +1610 -1170
- package/dist/index.cjs +1699 -1168
- package/dist/index.d.ts +1834 -71
- package/dist/lib/ast/expand.js +4 -65
- package/dist/lib/ast/features/calc.js +2 -2
- package/dist/lib/ast/features/inlinecssvariables.js +2 -2
- package/dist/lib/ast/features/prefix.js +2 -1
- package/dist/lib/ast/features/transform.js +2 -1
- package/dist/lib/ast/features/type.js +9 -0
- package/dist/lib/ast/math/math.js +1 -1
- package/dist/lib/ast/minify.js +82 -171
- package/dist/lib/ast/types.js +369 -4
- 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/parse.js +106 -21
- package/dist/lib/parser/tokenize.js +40 -80
- package/dist/lib/renderer/render.js +25 -3
- package/dist/lib/renderer/sourcemap/sourcemap.js +34 -0
- package/dist/lib/syntax/color/color.js +7 -0
- package/dist/lib/syntax/color/utils/distance.js +5 -1
- package/dist/lib/syntax/syntax.js +10 -0
- package/dist/lib/validation/config.json.js +33 -30
- package/dist/lib/validation/syntax.js +3 -1
- 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
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,12 +116,13 @@ 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)) {
|
|
@@ -162,7 +166,7 @@ async function doParse(iterator, options = {}) {
|
|
|
162
166
|
let inBlock = 1;
|
|
163
167
|
tokens = [item];
|
|
164
168
|
do {
|
|
165
|
-
item = iter.next().value;
|
|
169
|
+
item = isAsync ? (await iter.next()).value : iter.next().value;
|
|
166
170
|
if (item == null) {
|
|
167
171
|
break;
|
|
168
172
|
}
|
|
@@ -224,8 +228,8 @@ async function doParse(iterator, options = {}) {
|
|
|
224
228
|
}
|
|
225
229
|
}
|
|
226
230
|
if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
|
|
227
|
-
// @ts-ignore
|
|
228
|
-
const index = context.chi.findIndex((node) => node
|
|
231
|
+
// @ts-ignore ignore error
|
|
232
|
+
const index = context.chi.findIndex((node) => node === context);
|
|
229
233
|
if (index > -1) {
|
|
230
234
|
context.chi.splice(index, 1);
|
|
231
235
|
}
|
|
@@ -236,13 +240,21 @@ async function doParse(iterator, options = {}) {
|
|
|
236
240
|
const token = node.tokens[0];
|
|
237
241
|
const url = token.typ == EnumToken.StringTokenType ? token.val.slice(1, -1) : token.val;
|
|
238
242
|
try {
|
|
239
|
-
const root = await options.
|
|
240
|
-
return doParse(
|
|
243
|
+
const root = await options.getStream(url, options.src).then(async (stream) => {
|
|
244
|
+
return doParse(tokenizeStream(stream), Object.assign({}, options, {
|
|
241
245
|
minify: false,
|
|
242
246
|
setParent: false,
|
|
243
247
|
src: options.resolve(url, options.src).absolute
|
|
244
|
-
}));
|
|
248
|
+
})); // )
|
|
245
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
|
+
// });
|
|
246
258
|
stats.importedBytesIn += root.stats.bytesIn;
|
|
247
259
|
stats.imports.push(root.stats);
|
|
248
260
|
node.parent.chi.splice(node.parent.chi.indexOf(node), 1, ...root.ast.chi);
|
|
@@ -251,7 +263,7 @@ async function doParse(iterator, options = {}) {
|
|
|
251
263
|
}
|
|
252
264
|
}
|
|
253
265
|
catch (error) {
|
|
254
|
-
// @ts-ignore
|
|
266
|
+
// @ts-ignore ignore error
|
|
255
267
|
errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
|
|
256
268
|
}
|
|
257
269
|
}));
|
|
@@ -275,28 +287,33 @@ async function doParse(iterator, options = {}) {
|
|
|
275
287
|
if (result.node.typ == EnumToken.DeclarationNodeType &&
|
|
276
288
|
(typeof options.visitor.Declaration == 'function' || options.visitor.Declaration?.[result.node.nam] != null)) {
|
|
277
289
|
const callable = typeof options.visitor.Declaration == 'function' ? options.visitor.Declaration : options.visitor.Declaration[result.node.nam];
|
|
278
|
-
const
|
|
290
|
+
const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
|
|
291
|
+
const results = isAsync ? await callable(result.node) : callable(result.node);
|
|
279
292
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
280
293
|
continue;
|
|
281
294
|
}
|
|
295
|
+
// @ts-ignore
|
|
282
296
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
283
297
|
}
|
|
284
298
|
else if (options.visitor.Rule != null && result.node.typ == EnumToken.RuleNodeType) {
|
|
285
|
-
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);
|
|
286
301
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
287
302
|
continue;
|
|
288
303
|
}
|
|
304
|
+
// @ts-ignore
|
|
289
305
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
290
306
|
}
|
|
291
307
|
else if (options.visitor.AtRule != null &&
|
|
292
308
|
result.node.typ == EnumToken.AtRuleNodeType &&
|
|
293
|
-
// @ts-ignore
|
|
294
309
|
(typeof options.visitor.AtRule == 'function' || options.visitor.AtRule?.[result.node.nam] != null)) {
|
|
295
310
|
const callable = typeof options.visitor.AtRule == 'function' ? options.visitor.AtRule : options.visitor.AtRule[result.node.nam];
|
|
296
|
-
const
|
|
311
|
+
const isAsync = Object.getPrototypeOf(callable).constructor.name == 'AsyncFunction';
|
|
312
|
+
const results = isAsync ? await callable(result.node) : callable(result.node);
|
|
297
313
|
if (results == null || (Array.isArray(results) && results.length == 0)) {
|
|
298
314
|
continue;
|
|
299
315
|
}
|
|
316
|
+
// @ts-ignore
|
|
300
317
|
result.parent.chi.splice(result.parent.chi.indexOf(result.node), 1, ...(Array.isArray(results) ? results : [results]));
|
|
301
318
|
}
|
|
302
319
|
}
|
|
@@ -407,7 +424,13 @@ function parseNode(results, context, options, errors, src, map, rawTokens) {
|
|
|
407
424
|
// @ts-ignore
|
|
408
425
|
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
|
|
409
426
|
// @ts-ignore
|
|
410
|
-
errors.push({
|
|
427
|
+
errors.push({
|
|
428
|
+
action: 'drop',
|
|
429
|
+
message: 'invalid @import',
|
|
430
|
+
location,
|
|
431
|
+
// @ts-ignore
|
|
432
|
+
rawTokens: [atRule, ...tokens]
|
|
433
|
+
});
|
|
411
434
|
return null;
|
|
412
435
|
}
|
|
413
436
|
}
|
|
@@ -1004,6 +1027,27 @@ function parseAtRulePrelude(tokens, atRule) {
|
|
|
1004
1027
|
}
|
|
1005
1028
|
return tokens;
|
|
1006
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
|
+
}
|
|
1007
1051
|
/**
|
|
1008
1052
|
* parse selector
|
|
1009
1053
|
* @param tokens
|
|
@@ -1105,12 +1149,33 @@ function parseSelector(tokens) {
|
|
|
1105
1149
|
return tokens;
|
|
1106
1150
|
}
|
|
1107
1151
|
/**
|
|
1108
|
-
* parse css string
|
|
1152
|
+
* parse css string and return an array of tokens
|
|
1109
1153
|
* @param src
|
|
1110
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
|
+
* ```
|
|
1111
1170
|
*/
|
|
1112
1171
|
function parseString(src, options = { location: false }) {
|
|
1113
|
-
|
|
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) => {
|
|
1114
1179
|
if (t.hint == EnumToken.EOFTokenType) {
|
|
1115
1180
|
return acc;
|
|
1116
1181
|
}
|
|
@@ -1122,6 +1187,11 @@ function parseString(src, options = { location: false }) {
|
|
|
1122
1187
|
return acc;
|
|
1123
1188
|
}, []));
|
|
1124
1189
|
}
|
|
1190
|
+
/**
|
|
1191
|
+
* get token type from a string
|
|
1192
|
+
* @param val
|
|
1193
|
+
* @param hint
|
|
1194
|
+
*/
|
|
1125
1195
|
function getTokenType(val, hint) {
|
|
1126
1196
|
if (hint != null) {
|
|
1127
1197
|
return enumTokenHints.has(hint) ? { typ: hint } : { typ: hint, val };
|
|
@@ -1287,9 +1357,24 @@ function getTokenType(val, hint) {
|
|
|
1287
1357
|
};
|
|
1288
1358
|
}
|
|
1289
1359
|
/**
|
|
1290
|
-
* parse
|
|
1360
|
+
* parse function tokens in a token array
|
|
1291
1361
|
* @param tokens
|
|
1292
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
|
|
1293
1378
|
*/
|
|
1294
1379
|
function parseTokens(tokens, options = {}) {
|
|
1295
1380
|
for (let i = 0; i < tokens.length; i++) {
|
|
@@ -1577,4 +1662,4 @@ function parseTokens(tokens, options = {}) {
|
|
|
1577
1662
|
return tokens;
|
|
1578
1663
|
}
|
|
1579
1664
|
|
|
1580
|
-
export { doParse, getTokenType, parseAtRulePrelude, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
1665
|
+
export { doParse, getTokenType, parseAtRulePrelude, parseDeclarations, parseSelector, parseString, parseTokens, urlTokenMatcher };
|
|
@@ -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)) {
|
|
@@ -443,11 +437,6 @@ function* tokenize(stream) {
|
|
|
443
437
|
break;
|
|
444
438
|
}
|
|
445
439
|
}
|
|
446
|
-
if (value === '') {
|
|
447
|
-
yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
|
|
448
|
-
buffer = '';
|
|
449
|
-
break;
|
|
450
|
-
}
|
|
451
440
|
charCode = value.charCodeAt(0);
|
|
452
441
|
}
|
|
453
442
|
// '\\'
|
|
@@ -485,16 +474,6 @@ function* tokenize(stream) {
|
|
|
485
474
|
}
|
|
486
475
|
while (value = next(parseInfo)) {
|
|
487
476
|
charCode = value.charCodeAt(0);
|
|
488
|
-
if (charCode == 0x5c) {
|
|
489
|
-
buffer += value + next(parseInfo);
|
|
490
|
-
continue;
|
|
491
|
-
}
|
|
492
|
-
if (charCode == 0x29) {
|
|
493
|
-
yield pushToken(buffer, parseInfo, EnumToken.BadStringTokenType);
|
|
494
|
-
yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
|
|
495
|
-
buffer = '';
|
|
496
|
-
break;
|
|
497
|
-
}
|
|
498
477
|
buffer += value;
|
|
499
478
|
}
|
|
500
479
|
if (hasNewLine) {
|
|
@@ -511,40 +490,12 @@ function* tokenize(stream) {
|
|
|
511
490
|
buffer = '';
|
|
512
491
|
while (value = next(parseInfo)) {
|
|
513
492
|
charCode = value.charCodeAt(0);
|
|
514
|
-
// ')'
|
|
515
|
-
if (charCode == 0x29) {
|
|
493
|
+
if (charCode == 0x29) { // ')'
|
|
516
494
|
yield pushToken(buffer, parseInfo, EnumToken.UrlTokenTokenType);
|
|
517
495
|
yield pushToken('', parseInfo, EnumToken.EndParensTokenType);
|
|
518
496
|
buffer = '';
|
|
519
497
|
break;
|
|
520
498
|
}
|
|
521
|
-
// if (errorState) {
|
|
522
|
-
//
|
|
523
|
-
// buffer += whitespace + value;
|
|
524
|
-
//
|
|
525
|
-
// while (value = peek(parseInfo)) {
|
|
526
|
-
//
|
|
527
|
-
// charCode = value.charCodeAt(0);
|
|
528
|
-
//
|
|
529
|
-
// if (charCode == 0x5c) {
|
|
530
|
-
//
|
|
531
|
-
// buffer += next(parseInfo, 2);
|
|
532
|
-
// continue;
|
|
533
|
-
// }
|
|
534
|
-
//
|
|
535
|
-
// // ')'
|
|
536
|
-
// if (charCode == 0x29) {
|
|
537
|
-
//
|
|
538
|
-
// break;
|
|
539
|
-
// }
|
|
540
|
-
//
|
|
541
|
-
// buffer += next(parseInfo);
|
|
542
|
-
// }
|
|
543
|
-
//
|
|
544
|
-
// yield pushToken(buffer, parseInfo, EnumToken.BadUrlTokenType);
|
|
545
|
-
// buffer = '';
|
|
546
|
-
// break;
|
|
547
|
-
// }
|
|
548
499
|
buffer += value;
|
|
549
500
|
}
|
|
550
501
|
}
|
|
@@ -583,10 +534,6 @@ function* tokenize(stream) {
|
|
|
583
534
|
buffer = '!';
|
|
584
535
|
break;
|
|
585
536
|
case 64 /* TokenMap.AT */:
|
|
586
|
-
if (buffer.length > 0) {
|
|
587
|
-
yield pushToken(buffer, parseInfo);
|
|
588
|
-
buffer = '';
|
|
589
|
-
}
|
|
590
537
|
buffer = value;
|
|
591
538
|
{
|
|
592
539
|
let val = peek(parseInfo);
|
|
@@ -604,27 +551,40 @@ function* tokenize(stream) {
|
|
|
604
551
|
break;
|
|
605
552
|
default:
|
|
606
553
|
buffer += value;
|
|
607
|
-
if (buffer.length == 1) {
|
|
608
|
-
if (buffer == 'h') {
|
|
609
|
-
if (match(parseInfo, 'ttp://') || match(parseInfo, 'ttps://')) {
|
|
610
|
-
let val = peek(parseInfo);
|
|
611
|
-
while (val != ')' && val != ';' && !isWhiteSpace(val.charCodeAt(0))) {
|
|
612
|
-
buffer += next(parseInfo);
|
|
613
|
-
val = peek(parseInfo);
|
|
614
|
-
}
|
|
615
|
-
yield pushToken(buffer, parseInfo);
|
|
616
|
-
buffer = '';
|
|
617
|
-
break;
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
554
|
break;
|
|
622
555
|
}
|
|
623
556
|
}
|
|
624
|
-
if (
|
|
625
|
-
|
|
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
|
+
}
|
|
626
587
|
}
|
|
627
|
-
yield pushToken('', parseInfo, EnumToken.EOFTokenType);
|
|
628
588
|
}
|
|
629
589
|
|
|
630
|
-
export { tokenize };
|
|
590
|
+
export { tokenize, tokenizeStream };
|
|
@@ -8,6 +8,11 @@ import { isColor, pseudoElements, mathFuncs, isNewLine } from '../syntax/syntax.
|
|
|
8
8
|
import { minifyNumber } from '../syntax/utils.js';
|
|
9
9
|
import { SourceMap } from './sourcemap/sourcemap.js';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Update position
|
|
13
|
+
* @param position
|
|
14
|
+
* @param str
|
|
15
|
+
*/
|
|
11
16
|
function update(position, str) {
|
|
12
17
|
let i = 0;
|
|
13
18
|
for (; i < str.length; i++) {
|
|
@@ -24,6 +29,7 @@ function update(position, str) {
|
|
|
24
29
|
* render ast
|
|
25
30
|
* @param data
|
|
26
31
|
* @param options
|
|
32
|
+
* @private
|
|
27
33
|
*/
|
|
28
34
|
function doRender(data, options = {}) {
|
|
29
35
|
const minify = options.minify ?? true;
|
|
@@ -91,6 +97,17 @@ function doRender(data, options = {}) {
|
|
|
91
97
|
}
|
|
92
98
|
return result;
|
|
93
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Update source map
|
|
102
|
+
* @param node
|
|
103
|
+
* @param options
|
|
104
|
+
* @param cache
|
|
105
|
+
* @param sourcemap
|
|
106
|
+
* @param position
|
|
107
|
+
* @param str
|
|
108
|
+
*
|
|
109
|
+
* @internal
|
|
110
|
+
*/
|
|
94
111
|
function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
95
112
|
if ([
|
|
96
113
|
EnumToken.RuleNodeType, EnumToken.AtRuleNodeType,
|
|
@@ -126,6 +143,8 @@ function updateSourceMap(node, options, cache, sourcemap, position, str) {
|
|
|
126
143
|
* @param cache
|
|
127
144
|
* @param level
|
|
128
145
|
* @param indents
|
|
146
|
+
*
|
|
147
|
+
* @internal
|
|
129
148
|
*/
|
|
130
149
|
function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
|
|
131
150
|
if (indents.length < level + 1) {
|
|
@@ -224,9 +243,6 @@ function renderAstNode(data, options, sourcemap, position, errors, reducer, cach
|
|
|
224
243
|
* render ast token
|
|
225
244
|
* @param token
|
|
226
245
|
* @param options
|
|
227
|
-
* @param cache
|
|
228
|
-
* @param reducer
|
|
229
|
-
* @param errors
|
|
230
246
|
*/
|
|
231
247
|
function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
|
|
232
248
|
if (reducer == null) {
|
|
@@ -590,6 +606,12 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
|
|
|
590
606
|
errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
|
|
591
607
|
return '';
|
|
592
608
|
}
|
|
609
|
+
/**
|
|
610
|
+
* Remove whitespace tokens that are not needed
|
|
611
|
+
* @param values
|
|
612
|
+
*
|
|
613
|
+
* @internal
|
|
614
|
+
*/
|
|
593
615
|
function filterValues(values) {
|
|
594
616
|
let i = 0;
|
|
595
617
|
for (; i < values.length; i++) {
|
|
@@ -1,11 +1,39 @@
|
|
|
1
1
|
import { encode } from './lib/encode.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Source map class
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
3
7
|
class SourceMap {
|
|
8
|
+
/**
|
|
9
|
+
* Last location
|
|
10
|
+
*/
|
|
4
11
|
lastLocation = null;
|
|
12
|
+
/**
|
|
13
|
+
* Version
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
5
16
|
#version = 3;
|
|
17
|
+
/**
|
|
18
|
+
* Sources
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
6
21
|
#sources = [];
|
|
22
|
+
/**
|
|
23
|
+
* Map
|
|
24
|
+
* @private
|
|
25
|
+
*/
|
|
7
26
|
#map = new Map;
|
|
27
|
+
/**
|
|
28
|
+
* Line
|
|
29
|
+
* @private
|
|
30
|
+
*/
|
|
8
31
|
#line = -1;
|
|
32
|
+
/**
|
|
33
|
+
* Add a location
|
|
34
|
+
* @param source
|
|
35
|
+
* @param original
|
|
36
|
+
*/
|
|
9
37
|
add(source, original) {
|
|
10
38
|
if (original.src !== '') {
|
|
11
39
|
if (!this.#sources.includes(original.src)) {
|
|
@@ -32,10 +60,16 @@ class SourceMap {
|
|
|
32
60
|
this.lastLocation = original;
|
|
33
61
|
}
|
|
34
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Convert to URL encoded string
|
|
65
|
+
*/
|
|
35
66
|
toUrl() {
|
|
36
67
|
// /*# sourceMappingURL = ${url} */
|
|
37
68
|
return `data:application/json,${encodeURIComponent(JSON.stringify(this.toJSON()))}`;
|
|
38
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Convert to JSON object
|
|
72
|
+
*/
|
|
39
73
|
toJSON() {
|
|
40
74
|
const mappings = [];
|
|
41
75
|
let i = 0;
|
|
@@ -31,6 +31,13 @@ import '../../renderer/sourcemap/lib/encode.js';
|
|
|
31
31
|
* Converts a color to another color space
|
|
32
32
|
* @param token
|
|
33
33
|
* @param to
|
|
34
|
+
*
|
|
35
|
+
* <code>
|
|
36
|
+
*
|
|
37
|
+
* const token = {typ: EnumToken.ColorTokenType, kin: ColorType.HEX, val: '#F00'}
|
|
38
|
+
* const result = convertColor(token, ColorType.LCH);
|
|
39
|
+
*
|
|
40
|
+
* </code>
|
|
34
41
|
*/
|
|
35
42
|
function convertColor(token, to) {
|
|
36
43
|
if (token.kin == ColorType.SYS ||
|
|
@@ -13,15 +13,19 @@ import '../../../renderer/sourcemap/lib/encode.js';
|
|
|
13
13
|
* Calculate the distance between two okLab colors.
|
|
14
14
|
* @param okLab1
|
|
15
15
|
* @param okLab2
|
|
16
|
+
*
|
|
17
|
+
* @private
|
|
16
18
|
*/
|
|
17
19
|
function okLabDistance(okLab1, okLab2) {
|
|
18
20
|
return Math.sqrt(Math.pow(okLab1[0] - okLab2[0], 2) + Math.pow(okLab1[1] - okLab2[1], 2) + Math.pow(okLab1[2] - okLab2[2], 2));
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
|
-
* Check if two colors are close.
|
|
23
|
+
* Check if two colors are close in okLab space.
|
|
22
24
|
* @param color1
|
|
23
25
|
* @param color2
|
|
24
26
|
* @param threshold
|
|
27
|
+
*
|
|
28
|
+
* @private
|
|
25
29
|
*/
|
|
26
30
|
function isOkLabClose(color1, color2, threshold = .01) {
|
|
27
31
|
color1 = convertColor(color1, ColorType.OKLAB);
|
|
@@ -21,6 +21,11 @@ const dimensionUnits = new Set([
|
|
|
21
21
|
const fontFormat = ['collection', 'embedded-opentype', 'opentype', 'svg', 'truetype', 'woff', 'woff2'];
|
|
22
22
|
const colorFontTech = ['color-colrv0', 'color-colrv1', 'color-svg', 'color-sbix', 'color-cbdt'];
|
|
23
23
|
const fontFeaturesTech = ['features-opentype', 'features-aat', 'features-graphite', 'incremental-patch', 'incremental-range', 'incremental-auto', 'variations', 'palettes'];
|
|
24
|
+
/**
|
|
25
|
+
* supported transform functions
|
|
26
|
+
*
|
|
27
|
+
* @internal
|
|
28
|
+
*/
|
|
24
29
|
const transformFunctions = [
|
|
25
30
|
'translate', 'scale', 'rotate', 'skew', 'perspective',
|
|
26
31
|
'translateX', 'translateY', 'translateZ',
|
|
@@ -34,6 +39,11 @@ const mediaTypes = ['all', 'print', 'screen',
|
|
|
34
39
|
/* deprecated */
|
|
35
40
|
'aural', 'braille', 'embossed', 'handheld', 'projection', 'tty', 'tv', 'speech'];
|
|
36
41
|
// https://www.w3.org/TR/css-values-4/#math-function
|
|
42
|
+
/**
|
|
43
|
+
* supported math functions
|
|
44
|
+
*
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
37
47
|
const mathFuncs = ['minmax', 'repeat', 'fit-content', 'calc', 'clamp', 'min', 'max', 'round', 'mod', 'rem', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'pow', 'sqrt', 'hypot', 'log', 'exp', 'abs', 'sign'];
|
|
38
48
|
const wildCardFuncs = ['var', 'env'];
|
|
39
49
|
const pseudoElements = [':before', ':after', ':first-line', ':first-letter'];
|