@tbela99/css-parser 0.0.1-rc5 → 0.0.1-rc6
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 +59 -1
- package/dist/config.json.js +49 -0
- package/dist/index-umd-web.js +2509 -2223
- package/dist/index.cjs +2509 -2223
- package/dist/index.d.ts +35 -26
- package/dist/lib/ast/expand.js +159 -0
- package/dist/lib/ast/minify.js +89 -87
- package/dist/lib/ast/walk.js +10 -1
- package/dist/lib/parser/declaration/list.js +1 -1
- package/dist/lib/parser/declaration/map.js +8 -0
- package/dist/lib/parser/parse.js +36 -22
- package/dist/lib/parser/tokenize.js +136 -74
- package/dist/lib/parser/utils/syntax.js +10 -17
- package/dist/lib/renderer/render.js +16 -24
- package/dist/lib/transform.js +4 -1
- package/dist/node/index.js +5 -4
- package/dist/web/index.js +5 -4
- package/package.json +1 -1
package/dist/lib/parser/parse.js
CHANGED
|
@@ -53,14 +53,18 @@ async function parse(iterator, opt = {}) {
|
|
|
53
53
|
let i;
|
|
54
54
|
let loc;
|
|
55
55
|
for (i = 0; i < tokens.length; i++) {
|
|
56
|
-
if (tokens[i].typ == 'Comment') {
|
|
57
|
-
// @ts-ignore
|
|
58
|
-
context.chi.push(tokens[i]);
|
|
56
|
+
if (tokens[i].typ == 'Comment' || tokens[i].typ == 'CDOCOMM') {
|
|
59
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
|
+
}
|
|
60
62
|
loc = {
|
|
61
63
|
sta: position,
|
|
62
64
|
src
|
|
63
65
|
};
|
|
66
|
+
// @ts-ignore
|
|
67
|
+
context.chi.push(tokens[i]);
|
|
64
68
|
if (options.sourcemap) {
|
|
65
69
|
tokens[i].loc = loc;
|
|
66
70
|
}
|
|
@@ -91,7 +95,7 @@ async function parse(iterator, opt = {}) {
|
|
|
91
95
|
const atRule = tokens.shift();
|
|
92
96
|
const position = map.get(atRule);
|
|
93
97
|
if (atRule.val == 'charset' && position.ind > 0) {
|
|
94
|
-
errors.push({ action: 'drop', message: 'invalid @charset', location: { src, ...position } });
|
|
98
|
+
errors.push({ action: 'drop', message: 'parse: invalid @charset', location: { src, ...position } });
|
|
95
99
|
return null;
|
|
96
100
|
}
|
|
97
101
|
// @ts-ignore
|
|
@@ -121,12 +125,12 @@ async function parse(iterator, opt = {}) {
|
|
|
121
125
|
}
|
|
122
126
|
// @ts-ignore
|
|
123
127
|
if (tokens[0]?.typ != 'String' && tokens[0]?.typ != 'UrlFunc') {
|
|
124
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
128
|
+
errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
|
|
125
129
|
return null;
|
|
126
130
|
}
|
|
127
131
|
// @ts-ignore
|
|
128
132
|
if (tokens[0].typ == 'UrlFunc' && tokens[1]?.typ != 'Url-token' && tokens[1]?.typ != 'String') {
|
|
129
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
133
|
+
errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
|
|
130
134
|
return null;
|
|
131
135
|
}
|
|
132
136
|
}
|
|
@@ -162,7 +166,8 @@ async function parse(iterator, opt = {}) {
|
|
|
162
166
|
return null;
|
|
163
167
|
}
|
|
164
168
|
catch (error) {
|
|
165
|
-
|
|
169
|
+
// @ts-ignore
|
|
170
|
+
errors.push({ action: 'ignore', message: 'parse: ' + error.message, error });
|
|
166
171
|
}
|
|
167
172
|
}
|
|
168
173
|
}
|
|
@@ -179,7 +184,7 @@ async function parse(iterator, opt = {}) {
|
|
|
179
184
|
nam: renderToken(atRule, { removeComments: true }),
|
|
180
185
|
val: raw.join('')
|
|
181
186
|
};
|
|
182
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable:
|
|
187
|
+
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
183
188
|
if (delim.typ == 'Block-start') {
|
|
184
189
|
node.chi = [];
|
|
185
190
|
}
|
|
@@ -227,7 +232,7 @@ async function parse(iterator, opt = {}) {
|
|
|
227
232
|
chi: []
|
|
228
233
|
};
|
|
229
234
|
let raw = [...uniq.values()];
|
|
230
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
235
|
+
Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
|
|
231
236
|
loc = {
|
|
232
237
|
sta: position,
|
|
233
238
|
src
|
|
@@ -269,7 +274,7 @@ async function parse(iterator, opt = {}) {
|
|
|
269
274
|
if (name[i].typ != 'Whitespace' && name[i].typ != 'Comment') {
|
|
270
275
|
errors.push({
|
|
271
276
|
action: 'drop',
|
|
272
|
-
message: 'invalid declaration',
|
|
277
|
+
message: 'parse: invalid declaration',
|
|
273
278
|
location: { src, ...position }
|
|
274
279
|
});
|
|
275
280
|
return null;
|
|
@@ -279,7 +284,7 @@ async function parse(iterator, opt = {}) {
|
|
|
279
284
|
if (value == null) {
|
|
280
285
|
errors.push({
|
|
281
286
|
action: 'drop',
|
|
282
|
-
message: 'invalid declaration',
|
|
287
|
+
message: 'parse: invalid declaration',
|
|
283
288
|
location: { src, ...position }
|
|
284
289
|
});
|
|
285
290
|
return null;
|
|
@@ -287,7 +292,7 @@ async function parse(iterator, opt = {}) {
|
|
|
287
292
|
if (value.length == 0) {
|
|
288
293
|
errors.push({
|
|
289
294
|
action: 'drop',
|
|
290
|
-
message: 'invalid declaration',
|
|
295
|
+
message: 'parse: invalid declaration',
|
|
291
296
|
location: { src, ...position }
|
|
292
297
|
});
|
|
293
298
|
return null;
|
|
@@ -305,7 +310,7 @@ async function parse(iterator, opt = {}) {
|
|
|
305
310
|
if (node.val.length == 0) {
|
|
306
311
|
errors.push({
|
|
307
312
|
action: 'drop',
|
|
308
|
-
message: 'invalid declaration',
|
|
313
|
+
message: 'parse: invalid declaration',
|
|
309
314
|
location: { src, ...position }
|
|
310
315
|
});
|
|
311
316
|
return null;
|
|
@@ -323,18 +328,14 @@ async function parse(iterator, opt = {}) {
|
|
|
323
328
|
}
|
|
324
329
|
const iter = tokenize(iterator);
|
|
325
330
|
let item;
|
|
326
|
-
while (
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
break;
|
|
330
|
-
}
|
|
331
|
-
// console.debug({item});
|
|
331
|
+
while (item = iter.next().value) {
|
|
332
|
+
bytesIn = item.bytesIn;
|
|
333
|
+
// parse error
|
|
332
334
|
if (item.hint != null && item.hint.startsWith('Bad-')) {
|
|
333
335
|
// bad token
|
|
334
336
|
continue;
|
|
335
337
|
}
|
|
336
338
|
tokens.push(item);
|
|
337
|
-
bytesIn = item.bytesIn;
|
|
338
339
|
if (item.token == ';' || item.token == '{') {
|
|
339
340
|
let node = await parseNode(tokens);
|
|
340
341
|
if (node != null) {
|
|
@@ -378,15 +379,28 @@ async function parse(iterator, opt = {}) {
|
|
|
378
379
|
if (tokens.length > 0) {
|
|
379
380
|
await parseNode(tokens);
|
|
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;
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
381
393
|
const endParseTime = performance.now();
|
|
382
394
|
if (options.minify) {
|
|
383
395
|
if (ast.chi.length > 0) {
|
|
384
|
-
minify(ast, options, true);
|
|
396
|
+
minify(ast, options, true, errors);
|
|
385
397
|
}
|
|
386
398
|
}
|
|
387
399
|
const endTime = performance.now();
|
|
388
400
|
return {
|
|
389
|
-
ast,
|
|
401
|
+
ast,
|
|
402
|
+
errors,
|
|
403
|
+
stats: {
|
|
390
404
|
bytesIn,
|
|
391
405
|
parse: `${(endParseTime - startTime).toFixed(2)}ms`,
|
|
392
406
|
minify: `${(endTime - endParseTime).toFixed(2)}ms`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isWhiteSpace, isDigit,
|
|
1
|
+
import { isWhiteSpace, isNewLine, isDigit, isNonPrintable } from './utils/syntax.js';
|
|
2
2
|
|
|
3
3
|
function* tokenize(iterator) {
|
|
4
4
|
let ind = -1;
|
|
@@ -55,23 +55,7 @@ function* tokenize(iterator) {
|
|
|
55
55
|
}
|
|
56
56
|
break;
|
|
57
57
|
}
|
|
58
|
-
|
|
59
|
-
if (isNewLine(codepoint)) {
|
|
60
|
-
if (i == 1) {
|
|
61
|
-
buffer += value + escapeSequence.slice(0, i);
|
|
62
|
-
next(i + 1);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
// else {
|
|
66
|
-
yield pushToken(buffer + value + escapeSequence.slice(0, i), 'Bad-string');
|
|
67
|
-
buffer = '';
|
|
68
|
-
// }
|
|
69
|
-
next(i + 1);
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
// not hex or new line
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
else if (i == 1) {
|
|
58
|
+
if (i == 1) {
|
|
75
59
|
buffer += value + sequence[i];
|
|
76
60
|
next(2);
|
|
77
61
|
continue;
|
|
@@ -88,7 +72,7 @@ function* tokenize(iterator) {
|
|
|
88
72
|
else {
|
|
89
73
|
buffer += String.fromCodePoint(codepoint);
|
|
90
74
|
}
|
|
91
|
-
next(escapeSequence.length + 1);
|
|
75
|
+
next(escapeSequence.length + 1 + (isWhiteSpace(peek()?.charCodeAt(0)) ? 1 : 0));
|
|
92
76
|
continue;
|
|
93
77
|
}
|
|
94
78
|
buffer += next(2);
|
|
@@ -212,17 +196,18 @@ function* tokenize(iterator) {
|
|
|
212
196
|
buffer += next(3);
|
|
213
197
|
while (value = next()) {
|
|
214
198
|
buffer += value;
|
|
215
|
-
if (value == '
|
|
216
|
-
yield pushToken(buffer, 'CDOCOMM');
|
|
217
|
-
buffer = '';
|
|
199
|
+
if (value == '-' && peek(2) == '->') {
|
|
218
200
|
break;
|
|
219
201
|
}
|
|
220
202
|
}
|
|
203
|
+
if (value === '') {
|
|
204
|
+
yield pushToken(buffer, 'Bad-cdo');
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
yield pushToken(buffer + next(2), 'CDOCOMM');
|
|
208
|
+
}
|
|
209
|
+
buffer = '';
|
|
221
210
|
}
|
|
222
|
-
// if (!peek()) {
|
|
223
|
-
yield pushToken(buffer, 'Bad-cdo');
|
|
224
|
-
buffer = '';
|
|
225
|
-
// }
|
|
226
211
|
break;
|
|
227
212
|
case '\\':
|
|
228
213
|
// EOF
|
|
@@ -323,73 +308,150 @@ function* tokenize(iterator) {
|
|
|
323
308
|
if (buffer == 'url(') {
|
|
324
309
|
yield pushToken(buffer);
|
|
325
310
|
buffer = '';
|
|
326
|
-
|
|
327
|
-
let whitespace = '';
|
|
328
|
-
value = peek();
|
|
329
|
-
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
330
|
-
whitespace += value;
|
|
331
|
-
}
|
|
332
|
-
if (whitespace.length > 0) {
|
|
333
|
-
next(whitespace.length);
|
|
334
|
-
}
|
|
311
|
+
consumeWhiteSpace();
|
|
335
312
|
value = peek();
|
|
313
|
+
let cp;
|
|
314
|
+
let whitespace = '';
|
|
315
|
+
let hasWhiteSpace = false;
|
|
316
|
+
let errorState = false;
|
|
336
317
|
if (value == '"' || value == "'") {
|
|
337
|
-
|
|
318
|
+
const quote = value;
|
|
319
|
+
let inquote = true;
|
|
320
|
+
let hasNewLine = false;
|
|
321
|
+
buffer = next();
|
|
322
|
+
while (value = next()) {
|
|
323
|
+
cp = value.charCodeAt(0);
|
|
324
|
+
// consume an invalid string
|
|
325
|
+
if (inquote) {
|
|
326
|
+
buffer += value;
|
|
327
|
+
if (isNewLine(cp)) {
|
|
328
|
+
hasNewLine = true;
|
|
329
|
+
while (value = next()) {
|
|
330
|
+
buffer += value;
|
|
331
|
+
if (value == ';') {
|
|
332
|
+
inquote = false;
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (value === '') {
|
|
337
|
+
yield pushToken(buffer, 'Bad-string');
|
|
338
|
+
buffer = '';
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
cp = value.charCodeAt(0);
|
|
342
|
+
}
|
|
343
|
+
// '\\'
|
|
344
|
+
if (cp == 0x5c) {
|
|
345
|
+
buffer += next();
|
|
346
|
+
}
|
|
347
|
+
else if (value == quote) {
|
|
348
|
+
inquote = false;
|
|
349
|
+
}
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
if (!inquote) {
|
|
353
|
+
if (isWhiteSpace(cp)) {
|
|
354
|
+
whitespace += value;
|
|
355
|
+
while (value = peek()) {
|
|
356
|
+
hasWhiteSpace = true;
|
|
357
|
+
if (isWhiteSpace(value?.charCodeAt(0))) {
|
|
358
|
+
whitespace += next();
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
if (!(value = next())) {
|
|
364
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-url-token' : 'Url-token');
|
|
365
|
+
buffer = '';
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
cp = value.charCodeAt(0);
|
|
370
|
+
// ')'
|
|
371
|
+
if (cp == 0x29) {
|
|
372
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
|
|
373
|
+
yield pushToken('', 'End-parens');
|
|
374
|
+
buffer = '';
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
while (value = next()) {
|
|
378
|
+
cp = value.charCodeAt(0);
|
|
379
|
+
if (cp == 0x5c) {
|
|
380
|
+
buffer += value + next();
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
if (cp == 0x29) {
|
|
384
|
+
yield pushToken(buffer, 'Bad-string');
|
|
385
|
+
yield pushToken('', 'End-parens');
|
|
386
|
+
buffer = '';
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
buffer += value;
|
|
390
|
+
}
|
|
391
|
+
if (hasNewLine) {
|
|
392
|
+
yield pushToken(buffer, 'Bad-string');
|
|
393
|
+
buffer = '';
|
|
394
|
+
}
|
|
395
|
+
break;
|
|
396
|
+
}
|
|
397
|
+
buffer += value;
|
|
398
|
+
}
|
|
338
399
|
break;
|
|
339
400
|
}
|
|
340
401
|
else {
|
|
341
402
|
buffer = '';
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
// EOF -
|
|
345
|
-
if (cp == null) {
|
|
346
|
-
yield pushToken('', 'Bad-url-token');
|
|
347
|
-
break;
|
|
348
|
-
}
|
|
403
|
+
while (value = next()) {
|
|
404
|
+
cp = value.charCodeAt(0);
|
|
349
405
|
// ')'
|
|
350
|
-
if (cp == 0x29
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
else {
|
|
355
|
-
yield pushToken(buffer, 'Url-token');
|
|
356
|
-
}
|
|
357
|
-
if (cp != null) {
|
|
358
|
-
yield pushToken(next());
|
|
359
|
-
}
|
|
406
|
+
if (cp == 0x29) {
|
|
407
|
+
yield pushToken(buffer, 'Url-token');
|
|
408
|
+
yield pushToken('', 'End-parens');
|
|
409
|
+
buffer = '';
|
|
360
410
|
break;
|
|
361
411
|
}
|
|
362
412
|
if (isWhiteSpace(cp)) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
413
|
+
hasWhiteSpace = true;
|
|
414
|
+
whitespace = value;
|
|
415
|
+
while (isWhiteSpace(peek()?.charCodeAt(0))) {
|
|
416
|
+
whitespace += next();
|
|
417
|
+
}
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (isNonPrintable(cp) ||
|
|
421
|
+
// '"'
|
|
422
|
+
cp == 0x22 ||
|
|
423
|
+
// "'"
|
|
424
|
+
cp == 0x27 ||
|
|
425
|
+
// \('
|
|
426
|
+
cp == 0x28 ||
|
|
427
|
+
hasWhiteSpace) {
|
|
428
|
+
errorState = true;
|
|
429
|
+
}
|
|
430
|
+
if (errorState) {
|
|
431
|
+
buffer += whitespace + value;
|
|
432
|
+
while (value = peek()) {
|
|
366
433
|
cp = value.charCodeAt(0);
|
|
367
|
-
if (
|
|
368
|
-
|
|
434
|
+
if (cp == 0x5c) {
|
|
435
|
+
buffer += next(2);
|
|
369
436
|
continue;
|
|
370
437
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (cp == null || cp == 0x29) {
|
|
374
|
-
continue;
|
|
375
|
-
}
|
|
376
|
-
// bad url token
|
|
377
|
-
buffer += next(whitespace.length);
|
|
378
|
-
do {
|
|
379
|
-
value = peek();
|
|
380
|
-
cp = value.charCodeAt(0);
|
|
381
|
-
if (cp == null || cp == 0x29) {
|
|
438
|
+
// ')'
|
|
439
|
+
if (cp == 0x29) {
|
|
382
440
|
break;
|
|
383
441
|
}
|
|
384
442
|
buffer += next();
|
|
385
|
-
}
|
|
443
|
+
}
|
|
386
444
|
yield pushToken(buffer, 'Bad-url-token');
|
|
387
|
-
|
|
445
|
+
buffer = '';
|
|
446
|
+
break;
|
|
388
447
|
}
|
|
389
|
-
buffer +=
|
|
390
|
-
|
|
391
|
-
|
|
448
|
+
buffer += value;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
if (buffer !== '') {
|
|
452
|
+
yield pushToken(buffer, 'Url-token');
|
|
392
453
|
buffer = '';
|
|
454
|
+
break;
|
|
393
455
|
}
|
|
394
456
|
break;
|
|
395
457
|
}
|
|
@@ -96,6 +96,15 @@ function isIdent(name) {
|
|
|
96
96
|
}
|
|
97
97
|
return true;
|
|
98
98
|
}
|
|
99
|
+
function isNonPrintable(codepoint) {
|
|
100
|
+
// null -> backspace
|
|
101
|
+
return (codepoint >= 0 && codepoint <= 0x8) ||
|
|
102
|
+
// tab
|
|
103
|
+
codepoint == 0xb ||
|
|
104
|
+
// delete
|
|
105
|
+
codepoint == 0x7f ||
|
|
106
|
+
(codepoint >= 0xe && codepoint <= 0x1f);
|
|
107
|
+
}
|
|
99
108
|
function isPseudo(name) {
|
|
100
109
|
return name.charAt(0) == ':' &&
|
|
101
110
|
((name.endsWith('(') && isIdent(name.charAt(1) == ':' ? name.slice(2, -1) : name.slice(1, -1))) ||
|
|
@@ -239,22 +248,6 @@ function isHexColor(name) {
|
|
|
239
248
|
}
|
|
240
249
|
return true;
|
|
241
250
|
}
|
|
242
|
-
function isHexDigit(name) {
|
|
243
|
-
if (name.length || name.length > 6) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
for (let chr of name) {
|
|
247
|
-
let codepoint = chr.charCodeAt(0);
|
|
248
|
-
if (!isDigit(codepoint) &&
|
|
249
|
-
// A F
|
|
250
|
-
!(codepoint >= 0x41 && codepoint <= 0x46) &&
|
|
251
|
-
// a f
|
|
252
|
-
!(codepoint >= 0x61 && codepoint <= 0x66)) {
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return true;
|
|
257
|
-
}
|
|
258
251
|
function isFunction(name) {
|
|
259
252
|
return name.endsWith('(') && isIdent(name.slice(0, -1));
|
|
260
253
|
}
|
|
@@ -271,4 +264,4 @@ function isWhiteSpace(codepoint) {
|
|
|
271
264
|
codepoint == 0xa || codepoint == 0xc || codepoint == 0xd;
|
|
272
265
|
}
|
|
273
266
|
|
|
274
|
-
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor,
|
|
267
|
+
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getAngle, COLORS_NAMES, rgb2Hex, hsl2Hex, hwb2hex, cmyk2hex, NAMES_COLORS } from './utils/color.js';
|
|
2
|
+
import { expand } from '../ast/expand.js';
|
|
2
3
|
|
|
3
4
|
const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'];
|
|
4
5
|
function reduceNumber(val) {
|
|
@@ -20,6 +21,7 @@ function reduceNumber(val) {
|
|
|
20
21
|
}
|
|
21
22
|
function render(data, opt = {}) {
|
|
22
23
|
const startTime = performance.now();
|
|
24
|
+
const errors = [];
|
|
23
25
|
const options = Object.assign(opt.minify ?? true ? {
|
|
24
26
|
indent: '',
|
|
25
27
|
newLine: '',
|
|
@@ -29,23 +31,23 @@ function render(data, opt = {}) {
|
|
|
29
31
|
newLine: '\n',
|
|
30
32
|
compress: false,
|
|
31
33
|
removeComments: false,
|
|
32
|
-
}, { colorConvert: true, preserveLicense: false }, opt);
|
|
34
|
+
}, { colorConvert: true, expandNestingRules: false, preserveLicense: false }, opt);
|
|
33
35
|
return {
|
|
34
|
-
code: doRender(data, options, function reducer(acc, curr) {
|
|
36
|
+
code: doRender(options.expandNestingRules ? expand(data) : data, options, errors, function reducer(acc, curr) {
|
|
35
37
|
if (curr.typ == 'Comment' && options.removeComments) {
|
|
36
38
|
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
|
|
37
39
|
return acc;
|
|
38
40
|
}
|
|
39
41
|
return acc + curr.val;
|
|
40
42
|
}
|
|
41
|
-
return acc + renderToken(curr, options, reducer);
|
|
42
|
-
}, 0), stats: {
|
|
43
|
+
return acc + renderToken(curr, options, reducer, errors);
|
|
44
|
+
}, 0), errors, stats: {
|
|
43
45
|
total: `${(performance.now() - startTime).toFixed(2)}ms`
|
|
44
46
|
}
|
|
45
47
|
};
|
|
46
48
|
}
|
|
47
49
|
// @ts-ignore
|
|
48
|
-
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
50
|
+
function doRender(data, options, errors, reducer, level = 0, indents = []) {
|
|
49
51
|
if (indents.length < level + 1) {
|
|
50
52
|
indents.push(options.indent.repeat(level));
|
|
51
53
|
}
|
|
@@ -58,10 +60,11 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
58
60
|
case 'Declaration':
|
|
59
61
|
return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
|
|
60
62
|
case 'Comment':
|
|
63
|
+
case 'CDOCOMM':
|
|
61
64
|
return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
|
|
62
65
|
case 'StyleSheet':
|
|
63
66
|
return data.chi.reduce((css, node) => {
|
|
64
|
-
const str = doRender(node, options, reducer, level, indents);
|
|
67
|
+
const str = doRender(node, options, errors, reducer, level, indents);
|
|
65
68
|
if (str === '') {
|
|
66
69
|
return css;
|
|
67
70
|
}
|
|
@@ -83,7 +86,8 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
83
86
|
}
|
|
84
87
|
else if (node.typ == 'Declaration') {
|
|
85
88
|
if (node.val.length == 0) {
|
|
86
|
-
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
errors.push({ action: 'ignore', message: `render: invalid declaration ${JSON.stringify(node)}`, location: node.loc });
|
|
87
91
|
return '';
|
|
88
92
|
}
|
|
89
93
|
str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
|
@@ -92,7 +96,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
92
96
|
str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
|
|
93
97
|
}
|
|
94
98
|
else {
|
|
95
|
-
str = doRender(node, options, reducer, level + 1, indents);
|
|
99
|
+
str = doRender(node, options, errors, reducer, level + 1, indents);
|
|
96
100
|
}
|
|
97
101
|
if (css === '') {
|
|
98
102
|
return str;
|
|
@@ -112,7 +116,7 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
112
116
|
}
|
|
113
117
|
return '';
|
|
114
118
|
}
|
|
115
|
-
function renderToken(token, options = {}, reducer) {
|
|
119
|
+
function renderToken(token, options = {}, reducer, errors) {
|
|
116
120
|
if (reducer == null) {
|
|
117
121
|
reducer = function (acc, curr) {
|
|
118
122
|
if (curr.typ == 'Comment' && options.removeComments) {
|
|
@@ -121,7 +125,7 @@ function renderToken(token, options = {}, reducer) {
|
|
|
121
125
|
}
|
|
122
126
|
return acc + curr.val;
|
|
123
127
|
}
|
|
124
|
-
return acc + renderToken(curr, options, reducer);
|
|
128
|
+
return acc + renderToken(curr, options, reducer, errors);
|
|
125
129
|
};
|
|
126
130
|
}
|
|
127
131
|
switch (token.typ) {
|
|
@@ -274,18 +278,7 @@ function renderToken(token, options = {}, reducer) {
|
|
|
274
278
|
case 'Perc':
|
|
275
279
|
return token.val + '%';
|
|
276
280
|
case 'Number':
|
|
277
|
-
|
|
278
|
-
if (token.val.length < num.length) {
|
|
279
|
-
return token.val;
|
|
280
|
-
}
|
|
281
|
-
if (num.charAt(0) === '0' && num.length > 1) {
|
|
282
|
-
return num.slice(1);
|
|
283
|
-
}
|
|
284
|
-
const slice = num.slice(0, 2);
|
|
285
|
-
if (slice == '-0') {
|
|
286
|
-
return '-' + num.slice(2);
|
|
287
|
-
}
|
|
288
|
-
return num;
|
|
281
|
+
return reduceNumber(token.val);
|
|
289
282
|
case 'Comment':
|
|
290
283
|
if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
|
|
291
284
|
return '';
|
|
@@ -300,8 +293,7 @@ function renderToken(token, options = {}, reducer) {
|
|
|
300
293
|
case 'Delim':
|
|
301
294
|
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
302
295
|
}
|
|
303
|
-
|
|
304
|
-
// throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
296
|
+
errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
|
|
305
297
|
return '';
|
|
306
298
|
}
|
|
307
299
|
|
package/dist/lib/transform.js
CHANGED
|
@@ -8,7 +8,10 @@ async function transform(css, options = {}) {
|
|
|
8
8
|
return parse(css, options).then((parseResult) => {
|
|
9
9
|
const rendered = render(parseResult.ast, options);
|
|
10
10
|
return {
|
|
11
|
-
...parseResult,
|
|
11
|
+
...parseResult,
|
|
12
|
+
...rendered,
|
|
13
|
+
errors: parseResult.errors.concat(rendered.errors),
|
|
14
|
+
stats: {
|
|
12
15
|
bytesOut: rendered.code.length,
|
|
13
16
|
...parseResult.stats,
|
|
14
17
|
render: rendered.stats.total,
|
package/dist/node/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule } from '../lib/ast/minify.js';
|
|
2
|
+
export { walk, walkValues } from '../lib/ast/walk.js';
|
|
3
|
+
export { expand } from '../lib/ast/expand.js';
|
|
4
|
+
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
|
|
1
5
|
import { parse as parse$1 } from '../lib/parser/parse.js';
|
|
2
6
|
export { parseString, urlTokenMatcher } from '../lib/parser/parse.js';
|
|
3
7
|
export { tokenize } from '../lib/parser/tokenize.js';
|
|
4
|
-
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor,
|
|
8
|
+
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension } from '../lib/parser/utils/syntax.js';
|
|
5
9
|
export { getConfig } from '../lib/parser/utils/config.js';
|
|
6
10
|
export { funcList, matchType } from '../lib/parser/utils/type.js';
|
|
7
|
-
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
|
|
8
11
|
import { transform as transform$1 } from '../lib/transform.js';
|
|
9
|
-
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector } from '../lib/ast/minify.js';
|
|
10
|
-
export { walk } from '../lib/ast/walk.js';
|
|
11
12
|
import { load } from './load.js';
|
|
12
13
|
import { resolve } from '../lib/fs/resolve.js';
|
|
13
14
|
export { dirname, matchUrl } from '../lib/fs/resolve.js';
|
package/dist/web/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector, splitRule } from '../lib/ast/minify.js';
|
|
2
|
+
export { walk, walkValues } from '../lib/ast/walk.js';
|
|
3
|
+
export { expand } from '../lib/ast/expand.js';
|
|
4
|
+
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
|
|
1
5
|
import { parse as parse$1 } from '../lib/parser/parse.js';
|
|
2
6
|
export { parseString, urlTokenMatcher } from '../lib/parser/parse.js';
|
|
3
7
|
export { tokenize } from '../lib/parser/tokenize.js';
|
|
4
|
-
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor,
|
|
8
|
+
export { isAngle, isAtKeyword, isColor, isDigit, isDimension, isFrequency, isFunction, isHash, isHexColor, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPseudo, isResolution, isTime, isWhiteSpace, parseDimension } from '../lib/parser/utils/syntax.js';
|
|
5
9
|
export { getConfig } from '../lib/parser/utils/config.js';
|
|
6
10
|
export { funcList, matchType } from '../lib/parser/utils/type.js';
|
|
7
|
-
export { colorsFunc, render, renderToken } from '../lib/renderer/render.js';
|
|
8
11
|
import { transform as transform$1 } from '../lib/transform.js';
|
|
9
|
-
export { combinators, hasDeclaration, minify, minifyRule, reduceSelector } from '../lib/ast/minify.js';
|
|
10
|
-
export { walk } from '../lib/ast/walk.js';
|
|
11
12
|
import { load } from './load.js';
|
|
12
13
|
import { resolve, dirname } from '../lib/fs/resolve.js';
|
|
13
14
|
export { matchUrl } from '../lib/fs/resolve.js';
|