@tbela99/css-parser 0.0.1-alpha4 → 0.0.1-rc1
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/.gitattributes +3 -0
- package/README.md +20 -6
- package/dist/config.json.js +95 -4
- package/dist/index-umd-web.js +1885 -1385
- package/dist/index.cjs +1885 -1385
- package/dist/index.d.ts +333 -14
- package/dist/index.js +6 -2
- package/dist/lib/ast/minify.js +796 -0
- package/dist/lib/{walker → ast}/walk.js +1 -1
- package/dist/lib/parser/declaration/list.js +38 -9
- package/dist/lib/parser/declaration/map.js +203 -145
- package/dist/lib/parser/declaration/set.js +26 -34
- package/dist/lib/parser/parse.js +241 -663
- package/dist/lib/parser/tokenize.js +452 -0
- package/dist/lib/parser/utils/eq.js +29 -5
- package/dist/lib/parser/utils/syntax.js +24 -7
- package/dist/lib/renderer/render.js +14 -28
- package/dist/lib/transform.js +1 -1
- package/dist/node/index.js +1 -0
- package/dist/web/index.js +6 -2
- package/package.json +12 -5
- package/dist/lib/parser/deduplicate.js +0 -542
package/dist/index.cjs
CHANGED
|
@@ -6,13 +6,14 @@ var promises = require('fs/promises');
|
|
|
6
6
|
// https://www.w3.org/TR/2021/CRD-css-syntax-3-20211224/#typedef-ident-token
|
|
7
7
|
// '\\'
|
|
8
8
|
const REVERSE_SOLIDUS = 0x5c;
|
|
9
|
+
const dimensionUnits = [
|
|
10
|
+
'q', 'cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb',
|
|
11
|
+
'dvh', 'dvi', 'dvmax', 'dvmin', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb',
|
|
12
|
+
'lvh', 'lvi', 'lvmax', 'lvw', 'mm', 'pc', 'pt', 'px', 'rem', 'rlh', 'svb',
|
|
13
|
+
'svh', 'svi', 'svmin', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'
|
|
14
|
+
];
|
|
9
15
|
function isLength(dimension) {
|
|
10
|
-
return 'unit' in dimension &&
|
|
11
|
-
'q', 'cap', 'ch', 'cm', 'cqb', 'cqh', 'cqi', 'cqmax', 'cqmin', 'cqw', 'dvb',
|
|
12
|
-
'dvh', 'dvi', 'dvmax', 'dvmin', 'dvw', 'em', 'ex', 'ic', 'in', 'lh', 'lvb',
|
|
13
|
-
'lvh', 'lvi', 'lvmax', 'lvw', 'mm', 'pc', 'pt', 'px', 'rem', 'rlh', 'svb',
|
|
14
|
-
'svh', 'svi', 'svmin', 'svw', 'vb', 'vh', 'vi', 'vmax', 'vmin', 'vw'
|
|
15
|
-
].includes(dimension.unit.toLowerCase());
|
|
16
|
+
return 'unit' in dimension && dimensionUnits.includes(dimension.unit.toLowerCase());
|
|
16
17
|
}
|
|
17
18
|
function isResolution(dimension) {
|
|
18
19
|
return 'unit' in dimension && ['dpi', 'dpcm', 'dppx', 'x'].includes(dimension.unit.toLowerCase());
|
|
@@ -237,6 +238,22 @@ function isHexColor(name) {
|
|
|
237
238
|
}
|
|
238
239
|
return true;
|
|
239
240
|
}
|
|
241
|
+
function isHexDigit(name) {
|
|
242
|
+
if (name.length || name.length > 6) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
for (let chr of name) {
|
|
246
|
+
let codepoint = chr.charCodeAt(0);
|
|
247
|
+
if (!isDigit(codepoint) &&
|
|
248
|
+
// A F
|
|
249
|
+
!(codepoint >= 0x41 && codepoint <= 0x46) &&
|
|
250
|
+
// a f
|
|
251
|
+
!(codepoint >= 0x61 && codepoint <= 0x66)) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
240
257
|
function isFunction(name) {
|
|
241
258
|
return name.endsWith('(') && isIdent(name.slice(0, -1));
|
|
242
259
|
}
|
|
@@ -372,6 +389,7 @@ var properties = {
|
|
|
372
389
|
},
|
|
373
390
|
"border-width": {
|
|
374
391
|
shorthand: "border-width",
|
|
392
|
+
map: "border",
|
|
375
393
|
properties: [
|
|
376
394
|
"border-top-width",
|
|
377
395
|
"border-right-width",
|
|
@@ -382,6 +400,9 @@ var properties = {
|
|
|
382
400
|
"Length",
|
|
383
401
|
"Perc"
|
|
384
402
|
],
|
|
403
|
+
"default": [
|
|
404
|
+
"medium"
|
|
405
|
+
],
|
|
385
406
|
keywords: [
|
|
386
407
|
"thin",
|
|
387
408
|
"medium",
|
|
@@ -389,19 +410,24 @@ var properties = {
|
|
|
389
410
|
]
|
|
390
411
|
},
|
|
391
412
|
"border-top-width": {
|
|
413
|
+
map: "border",
|
|
392
414
|
shorthand: "border-width"
|
|
393
415
|
},
|
|
394
416
|
"border-right-width": {
|
|
417
|
+
map: "border",
|
|
395
418
|
shorthand: "border-width"
|
|
396
419
|
},
|
|
397
420
|
"border-bottom-width": {
|
|
421
|
+
map: "border",
|
|
398
422
|
shorthand: "border-width"
|
|
399
423
|
},
|
|
400
424
|
"border-left-width": {
|
|
425
|
+
map: "border",
|
|
401
426
|
shorthand: "border-width"
|
|
402
427
|
},
|
|
403
428
|
"border-style": {
|
|
404
429
|
shorthand: "border-style",
|
|
430
|
+
map: "border",
|
|
405
431
|
properties: [
|
|
406
432
|
"border-top-style",
|
|
407
433
|
"border-right-style",
|
|
@@ -410,6 +436,9 @@ var properties = {
|
|
|
410
436
|
],
|
|
411
437
|
types: [
|
|
412
438
|
],
|
|
439
|
+
"default": [
|
|
440
|
+
"none"
|
|
441
|
+
],
|
|
413
442
|
keywords: [
|
|
414
443
|
"none",
|
|
415
444
|
"hidden",
|
|
@@ -424,19 +453,24 @@ var properties = {
|
|
|
424
453
|
]
|
|
425
454
|
},
|
|
426
455
|
"border-top-style": {
|
|
456
|
+
map: "border",
|
|
427
457
|
shorthand: "border-style"
|
|
428
458
|
},
|
|
429
459
|
"border-right-style": {
|
|
460
|
+
map: "border",
|
|
430
461
|
shorthand: "border-style"
|
|
431
462
|
},
|
|
432
463
|
"border-bottom-style": {
|
|
464
|
+
map: "border",
|
|
433
465
|
shorthand: "border-style"
|
|
434
466
|
},
|
|
435
467
|
"border-left-style": {
|
|
468
|
+
map: "border",
|
|
436
469
|
shorthand: "border-style"
|
|
437
470
|
},
|
|
438
471
|
"border-color": {
|
|
439
472
|
shorthand: "border-color",
|
|
473
|
+
map: "border",
|
|
440
474
|
properties: [
|
|
441
475
|
"border-top-color",
|
|
442
476
|
"border-right-color",
|
|
@@ -446,23 +480,95 @@ var properties = {
|
|
|
446
480
|
types: [
|
|
447
481
|
"Color"
|
|
448
482
|
],
|
|
483
|
+
"default": [
|
|
484
|
+
"currentcolor"
|
|
485
|
+
],
|
|
449
486
|
keywords: [
|
|
450
487
|
]
|
|
451
488
|
},
|
|
452
489
|
"border-top-color": {
|
|
490
|
+
map: "border",
|
|
453
491
|
shorthand: "border-color"
|
|
454
492
|
},
|
|
455
493
|
"border-right-color": {
|
|
494
|
+
map: "border",
|
|
456
495
|
shorthand: "border-color"
|
|
457
496
|
},
|
|
458
497
|
"border-bottom-color": {
|
|
498
|
+
map: "border",
|
|
459
499
|
shorthand: "border-color"
|
|
460
500
|
},
|
|
461
501
|
"border-left-color": {
|
|
502
|
+
map: "border",
|
|
462
503
|
shorthand: "border-color"
|
|
463
504
|
}
|
|
464
505
|
};
|
|
465
506
|
var map = {
|
|
507
|
+
border: {
|
|
508
|
+
shorthand: "border",
|
|
509
|
+
pattern: "border-color border-style border-width",
|
|
510
|
+
keywords: [
|
|
511
|
+
"none"
|
|
512
|
+
],
|
|
513
|
+
"default": [
|
|
514
|
+
"0",
|
|
515
|
+
"none"
|
|
516
|
+
],
|
|
517
|
+
properties: {
|
|
518
|
+
"border-color": {
|
|
519
|
+
types: [
|
|
520
|
+
"Color"
|
|
521
|
+
],
|
|
522
|
+
"default": [
|
|
523
|
+
"currentcolor"
|
|
524
|
+
],
|
|
525
|
+
keywords: [
|
|
526
|
+
]
|
|
527
|
+
},
|
|
528
|
+
"border-style": {
|
|
529
|
+
types: [
|
|
530
|
+
],
|
|
531
|
+
"default": [
|
|
532
|
+
"none"
|
|
533
|
+
],
|
|
534
|
+
keywords: [
|
|
535
|
+
"none",
|
|
536
|
+
"hidden",
|
|
537
|
+
"dotted",
|
|
538
|
+
"dashed",
|
|
539
|
+
"solid",
|
|
540
|
+
"double",
|
|
541
|
+
"groove",
|
|
542
|
+
"ridge",
|
|
543
|
+
"inset",
|
|
544
|
+
"outset"
|
|
545
|
+
]
|
|
546
|
+
},
|
|
547
|
+
"border-width": {
|
|
548
|
+
types: [
|
|
549
|
+
"Length",
|
|
550
|
+
"Perc"
|
|
551
|
+
],
|
|
552
|
+
"default": [
|
|
553
|
+
"medium"
|
|
554
|
+
],
|
|
555
|
+
keywords: [
|
|
556
|
+
"thin",
|
|
557
|
+
"medium",
|
|
558
|
+
"thick"
|
|
559
|
+
]
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
"border-color": {
|
|
564
|
+
shorthand: "border"
|
|
565
|
+
},
|
|
566
|
+
"border-style": {
|
|
567
|
+
shorthand: "border"
|
|
568
|
+
},
|
|
569
|
+
"border-width": {
|
|
570
|
+
shorthand: "border"
|
|
571
|
+
},
|
|
466
572
|
outline: {
|
|
467
573
|
shorthand: "outline",
|
|
468
574
|
pattern: "outline-color outline-style outline-width",
|
|
@@ -479,12 +585,10 @@ var map = {
|
|
|
479
585
|
"Color"
|
|
480
586
|
],
|
|
481
587
|
"default": [
|
|
482
|
-
"currentColor"
|
|
483
|
-
"invert"
|
|
588
|
+
"currentColor"
|
|
484
589
|
],
|
|
485
590
|
keywords: [
|
|
486
|
-
"currentColor"
|
|
487
|
-
"invert"
|
|
591
|
+
"currentColor"
|
|
488
592
|
]
|
|
489
593
|
},
|
|
490
594
|
"outline-style": {
|
|
@@ -822,6 +926,7 @@ var map = {
|
|
|
822
926
|
"default": [
|
|
823
927
|
"transparent"
|
|
824
928
|
],
|
|
929
|
+
multiple: true,
|
|
825
930
|
keywords: [
|
|
826
931
|
]
|
|
827
932
|
},
|
|
@@ -842,6 +947,7 @@ var map = {
|
|
|
842
947
|
"default": [
|
|
843
948
|
"scroll"
|
|
844
949
|
],
|
|
950
|
+
multiple: true,
|
|
845
951
|
keywords: [
|
|
846
952
|
"scroll",
|
|
847
953
|
"fixed",
|
|
@@ -854,6 +960,7 @@ var map = {
|
|
|
854
960
|
"default": [
|
|
855
961
|
"border-box"
|
|
856
962
|
],
|
|
963
|
+
multiple: true,
|
|
857
964
|
keywords: [
|
|
858
965
|
"border-box",
|
|
859
966
|
"padding-box",
|
|
@@ -867,6 +974,7 @@ var map = {
|
|
|
867
974
|
"default": [
|
|
868
975
|
"padding-box"
|
|
869
976
|
],
|
|
977
|
+
multiple: true,
|
|
870
978
|
keywords: [
|
|
871
979
|
"border-box",
|
|
872
980
|
"padding-box",
|
|
@@ -1455,9 +1563,8 @@ function hsl2rgb(h, s, l, a = null) {
|
|
|
1455
1563
|
return values;
|
|
1456
1564
|
}
|
|
1457
1565
|
|
|
1458
|
-
const indents = [];
|
|
1459
1566
|
function render(data, opt = {}) {
|
|
1460
|
-
const options = Object.assign(opt.
|
|
1567
|
+
const options = Object.assign(opt.minify ?? true ? {
|
|
1461
1568
|
indent: '',
|
|
1462
1569
|
newLine: '',
|
|
1463
1570
|
removeComments: true
|
|
@@ -1473,27 +1580,12 @@ function render(data, opt = {}) {
|
|
|
1473
1580
|
return acc;
|
|
1474
1581
|
}
|
|
1475
1582
|
}
|
|
1476
|
-
// if (options.compress && curr.typ == 'Whitespace') {
|
|
1477
|
-
//
|
|
1478
|
-
// if (original[index + 1]?.typ == 'Start-parens' ||
|
|
1479
|
-
// (index > 0 && (original[index - 1].typ == 'Pseudo-class-func' ||
|
|
1480
|
-
// original[index - 1].typ == 'End-parens' ||
|
|
1481
|
-
// original[index - 1].typ == 'UrlFunc' ||
|
|
1482
|
-
// original[index - 1].typ == 'Func' ||
|
|
1483
|
-
// (
|
|
1484
|
-
// original[index - 1].typ == 'Color' &&
|
|
1485
|
-
// (<ColorToken>original[index - 1]).kin != 'hex' &&
|
|
1486
|
-
// (<ColorToken>original[index - 1]).kin != 'lit')))) {
|
|
1487
|
-
//
|
|
1488
|
-
// return acc;
|
|
1489
|
-
// }
|
|
1490
|
-
// }
|
|
1491
1583
|
return acc + renderToken(curr, options);
|
|
1492
1584
|
}
|
|
1493
|
-
return { code: doRender(data, options, reducer) };
|
|
1585
|
+
return { code: doRender(data, options, reducer, 0) };
|
|
1494
1586
|
}
|
|
1495
1587
|
// @ts-ignore
|
|
1496
|
-
function doRender(data, options, reducer, level = 0) {
|
|
1588
|
+
function doRender(data, options, reducer, level = 0, indents = []) {
|
|
1497
1589
|
if (indents.length < level + 1) {
|
|
1498
1590
|
indents.push(options.indent.repeat(level));
|
|
1499
1591
|
}
|
|
@@ -1507,7 +1599,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1507
1599
|
return options.removeComments ? '' : data.val;
|
|
1508
1600
|
case 'StyleSheet':
|
|
1509
1601
|
return data.chi.reduce((css, node) => {
|
|
1510
|
-
const str = doRender(node, options, reducer, level);
|
|
1602
|
+
const str = doRender(node, options, reducer, level, indents);
|
|
1511
1603
|
if (str === '') {
|
|
1512
1604
|
return css;
|
|
1513
1605
|
}
|
|
@@ -1534,7 +1626,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1534
1626
|
str = `@${node.nam} ${node.val};`;
|
|
1535
1627
|
}
|
|
1536
1628
|
else {
|
|
1537
|
-
str = doRender(node, options, reducer, level + 1);
|
|
1629
|
+
str = doRender(node, options, reducer, level + 1, indents);
|
|
1538
1630
|
}
|
|
1539
1631
|
if (css === '') {
|
|
1540
1632
|
return str;
|
|
@@ -1542,8 +1634,7 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1542
1634
|
if (str === '') {
|
|
1543
1635
|
return css;
|
|
1544
1636
|
}
|
|
1545
|
-
|
|
1546
|
-
return `${css}${options.newLine}${indentSub}${str}`;
|
|
1637
|
+
return `${css}${options.newLine}${indentSub}${str}`;
|
|
1547
1638
|
}, '');
|
|
1548
1639
|
if (children.endsWith(';')) {
|
|
1549
1640
|
children = children.slice(0, -1);
|
|
@@ -1558,8 +1649,11 @@ function doRender(data, options, reducer, level = 0) {
|
|
|
1558
1649
|
function renderToken(token, options = {}) {
|
|
1559
1650
|
switch (token.typ) {
|
|
1560
1651
|
case 'Color':
|
|
1561
|
-
if (options.
|
|
1562
|
-
|
|
1652
|
+
if (options.minify || options.colorConvert) {
|
|
1653
|
+
if (token.kin == 'lit' && token.val.toLowerCase() == 'currentcolor') {
|
|
1654
|
+
return 'currentcolor';
|
|
1655
|
+
}
|
|
1656
|
+
let value = token.kin == 'hex' ? token.val.toLowerCase() : (token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : '');
|
|
1563
1657
|
if (token.val == 'rgb' || token.val == 'rgba') {
|
|
1564
1658
|
value = rgb2Hex(token);
|
|
1565
1659
|
}
|
|
@@ -1603,7 +1697,7 @@ function renderToken(token, options = {}) {
|
|
|
1603
1697
|
case 'UrlFunc':
|
|
1604
1698
|
case 'Pseudo-class-func':
|
|
1605
1699
|
// @ts-ignore
|
|
1606
|
-
return ( /* options.
|
|
1700
|
+
return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce((acc, curr) => {
|
|
1607
1701
|
if (options.removeComments && curr.typ == 'Comment') {
|
|
1608
1702
|
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
|
|
1609
1703
|
return acc;
|
|
@@ -1694,21 +1788,45 @@ function renderToken(token, options = {}) {
|
|
|
1694
1788
|
case 'String':
|
|
1695
1789
|
case 'Iden':
|
|
1696
1790
|
case 'Delim':
|
|
1697
|
-
return /* options.
|
|
1791
|
+
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
1698
1792
|
}
|
|
1699
1793
|
throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1700
1794
|
}
|
|
1701
1795
|
|
|
1702
1796
|
function eq(a, b) {
|
|
1703
|
-
if (
|
|
1797
|
+
if (a == null || b == null) {
|
|
1798
|
+
return a == b;
|
|
1799
|
+
}
|
|
1800
|
+
if (typeof a != 'object' || typeof b != 'object') {
|
|
1704
1801
|
return a === b;
|
|
1705
1802
|
}
|
|
1803
|
+
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
|
|
1804
|
+
return false;
|
|
1805
|
+
}
|
|
1806
|
+
if (Array.isArray(a)) {
|
|
1807
|
+
if (a.length != b.length) {
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
let i = 0;
|
|
1811
|
+
for (; i < a.length; i++) {
|
|
1812
|
+
if (!eq(a[i], b[i])) {
|
|
1813
|
+
return false;
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
return true;
|
|
1817
|
+
}
|
|
1706
1818
|
const k1 = Object.keys(a);
|
|
1707
1819
|
const k2 = Object.keys(b);
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1820
|
+
if (k1.length != k2.length) {
|
|
1821
|
+
return false;
|
|
1822
|
+
}
|
|
1823
|
+
let key;
|
|
1824
|
+
for (key of k1) {
|
|
1825
|
+
if (!eq(a[key], b[key])) {
|
|
1826
|
+
return false;
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
return true;
|
|
1712
1830
|
}
|
|
1713
1831
|
|
|
1714
1832
|
class PropertySet {
|
|
@@ -1720,8 +1838,7 @@ class PropertySet {
|
|
|
1720
1838
|
}
|
|
1721
1839
|
add(declaration) {
|
|
1722
1840
|
if (declaration.nam == this.config.shorthand) {
|
|
1723
|
-
this.declarations
|
|
1724
|
-
this.declarations.set(declaration.nam, declaration);
|
|
1841
|
+
this.declarations = new Map;
|
|
1725
1842
|
}
|
|
1726
1843
|
else {
|
|
1727
1844
|
// expand shorthand
|
|
@@ -1744,6 +1861,10 @@ class PropertySet {
|
|
|
1744
1861
|
}
|
|
1745
1862
|
if (token.typ != 'Whitespace' && token.typ != 'Comment') {
|
|
1746
1863
|
if (token.typ == 'Iden' && this.config.keywords.includes(token.val)) {
|
|
1864
|
+
if (tokens.length == 0) {
|
|
1865
|
+
tokens.push([]);
|
|
1866
|
+
current++;
|
|
1867
|
+
}
|
|
1747
1868
|
tokens[current].push(token);
|
|
1748
1869
|
}
|
|
1749
1870
|
if (token.typ == 'Literal' && token.val == this.config.separator) {
|
|
@@ -1759,10 +1880,6 @@ class PropertySet {
|
|
|
1759
1880
|
this.declarations.delete(this.config.shorthand);
|
|
1760
1881
|
for (const values of tokens) {
|
|
1761
1882
|
this.config.properties.forEach((property, index) => {
|
|
1762
|
-
// if (property == declaration.nam) {
|
|
1763
|
-
//
|
|
1764
|
-
// return;
|
|
1765
|
-
// }
|
|
1766
1883
|
if (!this.declarations.has(property)) {
|
|
1767
1884
|
this.declarations.set(property, {
|
|
1768
1885
|
typ: 'Declaration',
|
|
@@ -1791,30 +1908,20 @@ class PropertySet {
|
|
|
1791
1908
|
this.declarations.set(declaration.nam, declaration);
|
|
1792
1909
|
return this;
|
|
1793
1910
|
}
|
|
1794
|
-
// declaration.chi = declaration.chi.reduce((acc: Token[], token: Token) => {
|
|
1795
|
-
//
|
|
1796
|
-
// if (this.config.types.includes(token.typ) || ('0' == (<DimensionToken>token).chi && (
|
|
1797
|
-
// this.config.types.includes('Length') ||
|
|
1798
|
-
// this.config.types.includes('Angle') ||
|
|
1799
|
-
// this.config.types.includes('Dimension'))) || (token.typ == 'Iden' && this.config.keywords.includes(token.chi))) {
|
|
1800
|
-
//
|
|
1801
|
-
// acc.push(token);
|
|
1802
|
-
// }
|
|
1803
|
-
//
|
|
1804
|
-
// return acc;
|
|
1805
|
-
// }, <Token[]>[]);
|
|
1806
|
-
this.declarations.set(declaration.nam, declaration);
|
|
1807
1911
|
}
|
|
1912
|
+
this.declarations.set(declaration.nam, declaration);
|
|
1808
1913
|
return this;
|
|
1809
1914
|
}
|
|
1915
|
+
isShortHand() {
|
|
1916
|
+
if (this.declarations.has(this.config.shorthand)) {
|
|
1917
|
+
return this.declarations.size == 1;
|
|
1918
|
+
}
|
|
1919
|
+
return this.config.properties.length == this.declarations.size;
|
|
1920
|
+
}
|
|
1810
1921
|
[Symbol.iterator]() {
|
|
1811
1922
|
let iterator;
|
|
1812
1923
|
const declarations = this.declarations;
|
|
1813
|
-
if (declarations.size < this.config.properties.length
|
|
1814
|
-
return !declarations.has(property) || (index > 0 &&
|
|
1815
|
-
// @ts-ignore
|
|
1816
|
-
declarations.get(property).val.length != declarations.get(this.config.properties[Math.floor(index / 2)]).val.length);
|
|
1817
|
-
})) {
|
|
1924
|
+
if (declarations.size < this.config.properties.length) {
|
|
1818
1925
|
iterator = declarations.values();
|
|
1819
1926
|
}
|
|
1820
1927
|
else {
|
|
@@ -1872,17 +1979,20 @@ class PropertySet {
|
|
|
1872
1979
|
return acc;
|
|
1873
1980
|
}, [])
|
|
1874
1981
|
}][Symbol.iterator]();
|
|
1875
|
-
return {
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
}
|
|
1982
|
+
// return {
|
|
1983
|
+
// next() {
|
|
1984
|
+
//
|
|
1985
|
+
// return iterator.next();
|
|
1986
|
+
// }
|
|
1987
|
+
// }
|
|
1880
1988
|
}
|
|
1881
|
-
return
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1989
|
+
return iterator;
|
|
1990
|
+
// return {
|
|
1991
|
+
// next() {
|
|
1992
|
+
//
|
|
1993
|
+
// return iterator.next();
|
|
1994
|
+
// }
|
|
1995
|
+
// }
|
|
1886
1996
|
}
|
|
1887
1997
|
}
|
|
1888
1998
|
|
|
@@ -1897,34 +2007,7 @@ function matchType(val, properties) {
|
|
|
1897
2007
|
return false;
|
|
1898
2008
|
}
|
|
1899
2009
|
|
|
1900
|
-
|
|
1901
|
-
if (val == 'transparent' || val == 'currentcolor') {
|
|
1902
|
-
return {
|
|
1903
|
-
typ: 'Color',
|
|
1904
|
-
val,
|
|
1905
|
-
kin: 'lit'
|
|
1906
|
-
};
|
|
1907
|
-
}
|
|
1908
|
-
if (val.endsWith('%')) {
|
|
1909
|
-
return {
|
|
1910
|
-
typ: 'Perc',
|
|
1911
|
-
val: val.slice(0, -1)
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
return {
|
|
1915
|
-
typ: isNumber(val) ? 'Number' : 'Iden',
|
|
1916
|
-
val
|
|
1917
|
-
};
|
|
1918
|
-
}
|
|
1919
|
-
function parseString(val) {
|
|
1920
|
-
return val.split(/\s/).map(getTokenType).reduce((acc, curr) => {
|
|
1921
|
-
if (acc.length > 0) {
|
|
1922
|
-
acc.push({ typ: 'Whitespace' });
|
|
1923
|
-
}
|
|
1924
|
-
acc.push(curr);
|
|
1925
|
-
return acc;
|
|
1926
|
-
}, []);
|
|
1927
|
-
}
|
|
2010
|
+
const propertiesConfig = getConfig();
|
|
1928
2011
|
class PropertyMap {
|
|
1929
2012
|
config;
|
|
1930
2013
|
declarations;
|
|
@@ -1939,7 +2022,7 @@ class PropertyMap {
|
|
|
1939
2022
|
}
|
|
1940
2023
|
add(declaration) {
|
|
1941
2024
|
if (declaration.nam == this.config.shorthand) {
|
|
1942
|
-
this.declarations
|
|
2025
|
+
this.declarations = new Map;
|
|
1943
2026
|
this.declarations.set(declaration.nam, declaration);
|
|
1944
2027
|
}
|
|
1945
2028
|
else {
|
|
@@ -2016,8 +2099,7 @@ class PropertyMap {
|
|
|
2016
2099
|
const defaults = parseString(props.default[0]);
|
|
2017
2100
|
if (!(property in tokens)) {
|
|
2018
2101
|
tokens[property] = [
|
|
2019
|
-
[...defaults
|
|
2020
|
-
]
|
|
2102
|
+
[...defaults]
|
|
2021
2103
|
];
|
|
2022
2104
|
}
|
|
2023
2105
|
else {
|
|
@@ -2051,145 +2133,229 @@ class PropertyMap {
|
|
|
2051
2133
|
}, new Map);
|
|
2052
2134
|
}
|
|
2053
2135
|
}
|
|
2054
|
-
|
|
2136
|
+
// @ts-ignore
|
|
2137
|
+
const config = propertiesConfig.properties[declaration.nam];
|
|
2138
|
+
let property = declaration.nam;
|
|
2139
|
+
if (config != null) {
|
|
2140
|
+
property = config.shorthand;
|
|
2141
|
+
let value = this.declarations.get(property);
|
|
2142
|
+
if (!(value instanceof PropertySet)) {
|
|
2143
|
+
// @ts-ignore
|
|
2144
|
+
this.declarations.set(property, new PropertySet(propertiesConfig.properties[config.shorthand]));
|
|
2145
|
+
// Token[]
|
|
2146
|
+
if (value != null) {
|
|
2147
|
+
// @ts-ignore
|
|
2148
|
+
this.declarations.get(property).add(value);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
this.declarations.get(property).add(declaration);
|
|
2152
|
+
}
|
|
2153
|
+
else {
|
|
2154
|
+
this.declarations.set(declaration.nam, declaration);
|
|
2155
|
+
}
|
|
2055
2156
|
}
|
|
2056
2157
|
return this;
|
|
2057
2158
|
}
|
|
2058
2159
|
[Symbol.iterator]() {
|
|
2059
|
-
let
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
return this.declarations.values();
|
|
2069
|
-
}
|
|
2070
|
-
let count = 0;
|
|
2071
|
-
const separator = this.config.separator;
|
|
2072
|
-
const tokens = {};
|
|
2073
|
-
// @ts-ignore
|
|
2074
|
-
const valid = Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
2075
|
-
if (!this.declarations.has(curr[0])) {
|
|
2076
|
-
if (curr[1].required) {
|
|
2077
|
-
acc.push(curr[0]);
|
|
2160
|
+
let iterable;
|
|
2161
|
+
let requiredCount = 0;
|
|
2162
|
+
let property;
|
|
2163
|
+
let isShorthand = true;
|
|
2164
|
+
for (property of Object.keys(this.config.properties)) {
|
|
2165
|
+
if (this.config.properties[property].required) {
|
|
2166
|
+
if (!this.declarations.has(property)) {
|
|
2167
|
+
isShorthand = false;
|
|
2168
|
+
break;
|
|
2078
2169
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
for (const val of this.declarations.get(curr[0]).val) {
|
|
2085
|
-
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
2086
|
-
current++;
|
|
2087
|
-
if (tokens[curr[0]].length == current) {
|
|
2088
|
-
tokens[curr[0]].push([]);
|
|
2170
|
+
else {
|
|
2171
|
+
const val = this.declarations.get(property);
|
|
2172
|
+
if (val instanceof PropertySet && !val.isShortHand()) {
|
|
2173
|
+
isShorthand = false;
|
|
2174
|
+
break;
|
|
2089
2175
|
}
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2093
|
-
continue;
|
|
2094
|
-
}
|
|
2095
|
-
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(val, props.separator)) {
|
|
2096
|
-
continue;
|
|
2097
|
-
}
|
|
2098
|
-
if (matchType(val, curr[1])) {
|
|
2099
|
-
if (!(curr[0] in tokens)) {
|
|
2100
|
-
tokens[curr[0]] = [[]];
|
|
2176
|
+
else {
|
|
2177
|
+
requiredCount++;
|
|
2101
2178
|
}
|
|
2102
|
-
// is default value
|
|
2103
|
-
tokens[curr[0]][current].push(val);
|
|
2104
|
-
continue;
|
|
2105
2179
|
}
|
|
2106
|
-
acc.push(curr[0]);
|
|
2107
|
-
break;
|
|
2108
|
-
}
|
|
2109
|
-
if (count == 0) {
|
|
2110
|
-
count = current;
|
|
2111
2180
|
}
|
|
2112
|
-
return acc;
|
|
2113
|
-
}, []);
|
|
2114
|
-
if (valid.length > 0 || Object.values(tokens).every(v => v.every(v => v.length == count))) {
|
|
2115
|
-
return this.declarations.values();
|
|
2116
2181
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2182
|
+
if (requiredCount == 0) {
|
|
2183
|
+
requiredCount = this.declarations.size;
|
|
2184
|
+
}
|
|
2185
|
+
if (!isShorthand || requiredCount < this.requiredCount) {
|
|
2186
|
+
// @ts-ignore
|
|
2187
|
+
iterable = this.declarations.values();
|
|
2188
|
+
}
|
|
2189
|
+
else {
|
|
2190
|
+
let count = 0;
|
|
2191
|
+
const separator = this.config.separator;
|
|
2192
|
+
const tokens = {};
|
|
2193
|
+
// @ts-ignore
|
|
2194
|
+
/* const valid: string[] =*/ Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
2195
|
+
if (!this.declarations.has(curr[0])) {
|
|
2196
|
+
if (curr[1].required) {
|
|
2197
|
+
acc.push(curr[0]);
|
|
2126
2198
|
}
|
|
2127
|
-
acc.push(curr);
|
|
2128
2199
|
return acc;
|
|
2129
|
-
}, []);
|
|
2130
|
-
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
|
|
2131
|
-
continue;
|
|
2132
2200
|
}
|
|
2133
|
-
|
|
2201
|
+
let current = 0;
|
|
2202
|
+
const props = this.config.properties[curr[0]];
|
|
2203
|
+
const declaration = this.declarations.get(curr[0]);
|
|
2204
|
+
// @ts-ignore
|
|
2205
|
+
for (const val of (declaration instanceof PropertySet ? [...declaration][0] : declaration).val) {
|
|
2206
|
+
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
2207
|
+
current++;
|
|
2208
|
+
if (tokens[curr[0]].length == current) {
|
|
2209
|
+
tokens[curr[0]].push([]);
|
|
2210
|
+
}
|
|
2211
|
+
continue;
|
|
2212
|
+
}
|
|
2134
2213
|
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2135
|
-
|
|
2214
|
+
continue;
|
|
2136
2215
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
if (
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2216
|
+
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
|
|
2217
|
+
continue;
|
|
2218
|
+
}
|
|
2219
|
+
if (matchType(val, curr[1])) {
|
|
2220
|
+
if (!(curr[0] in tokens)) {
|
|
2221
|
+
tokens[curr[0]] = [[]];
|
|
2222
|
+
}
|
|
2223
|
+
// is default value
|
|
2224
|
+
tokens[curr[0]][current].push(val);
|
|
2225
|
+
// continue;
|
|
2226
|
+
}
|
|
2227
|
+
else {
|
|
2228
|
+
acc.push(curr[0]);
|
|
2229
|
+
break;
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
if (count == 0) {
|
|
2233
|
+
count = current;
|
|
2234
|
+
}
|
|
2235
|
+
return acc;
|
|
2236
|
+
}, []);
|
|
2237
|
+
count++;
|
|
2238
|
+
if (!Object.values(tokens).every(v => v.length == count)) {
|
|
2239
|
+
// @ts-ignore
|
|
2240
|
+
iterable = this.declarations.values();
|
|
2241
|
+
}
|
|
2242
|
+
else {
|
|
2243
|
+
const values = Object.entries(tokens).reduce((acc, curr) => {
|
|
2244
|
+
const props = this.config.properties[curr[0]];
|
|
2245
|
+
for (let i = 0; i < curr[1].length; i++) {
|
|
2246
|
+
if (acc.length == i) {
|
|
2247
|
+
acc.push([]);
|
|
2248
|
+
}
|
|
2249
|
+
let values = curr[1][i].reduce((acc, curr) => {
|
|
2250
|
+
if (acc.length > 0) {
|
|
2251
|
+
acc.push({ typ: 'Whitespace' });
|
|
2252
|
+
}
|
|
2253
|
+
acc.push(curr);
|
|
2254
|
+
return acc;
|
|
2255
|
+
}, []);
|
|
2256
|
+
// @todo remove renderToken call
|
|
2257
|
+
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
|
|
2258
|
+
continue;
|
|
2259
|
+
}
|
|
2260
|
+
let doFilterDefault = true;
|
|
2261
|
+
if (curr[0] in propertiesConfig.properties) {
|
|
2262
|
+
for (let v of values) {
|
|
2263
|
+
if (!['Whitespace', 'Comment', 'Iden'].includes(v.typ)
|
|
2264
|
+
|| (v.typ == 'Iden' && !this.config.properties[curr[0]].default.includes(v.val))) {
|
|
2265
|
+
doFilterDefault = false;
|
|
2266
|
+
break;
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
// remove default values
|
|
2271
|
+
values = values.filter((val) => {
|
|
2272
|
+
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2273
|
+
return false;
|
|
2274
|
+
}
|
|
2275
|
+
return !doFilterDefault || !(val.typ == 'Iden' && props.default.includes(val.val));
|
|
2276
|
+
});
|
|
2277
|
+
if (values.length > 0) {
|
|
2278
|
+
if ('mapping' in props) {
|
|
2145
2279
|
// @ts-ignore
|
|
2146
|
-
if (
|
|
2147
|
-
|
|
2148
|
-
|
|
2280
|
+
if (!('constraints' in props) || !('max' in props.constraints) || values.length <= props.constraints.mapping.max) {
|
|
2281
|
+
let i = values.length;
|
|
2282
|
+
while (i--) {
|
|
2283
|
+
// @ts-ignore
|
|
2284
|
+
if (values[i].typ == 'Iden' && values[i].val in props.mapping) {
|
|
2285
|
+
// @ts-ignore
|
|
2286
|
+
values.splice(i, 1, ...parseString(props.mapping[values[i].val]));
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2149
2289
|
}
|
|
2150
2290
|
}
|
|
2291
|
+
if ('prefix' in props) {
|
|
2292
|
+
// @ts-ignore
|
|
2293
|
+
acc[i].push({ ...props.prefix });
|
|
2294
|
+
}
|
|
2295
|
+
else if (acc[i].length > 0) {
|
|
2296
|
+
acc[i].push({ typ: 'Whitespace' });
|
|
2297
|
+
}
|
|
2298
|
+
acc[i].push(...values.reduce((acc, curr) => {
|
|
2299
|
+
if (acc.length > 0) {
|
|
2300
|
+
// @ts-ignore
|
|
2301
|
+
acc.push({ ...(props.separator ?? { typ: 'Whitespace' }) });
|
|
2302
|
+
}
|
|
2303
|
+
// @ts-ignore
|
|
2304
|
+
acc.push(curr);
|
|
2305
|
+
return acc;
|
|
2306
|
+
}, []));
|
|
2151
2307
|
}
|
|
2152
2308
|
}
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2309
|
+
return acc;
|
|
2310
|
+
}, []).reduce((acc, curr) => {
|
|
2311
|
+
if (acc.length > 0) {
|
|
2312
|
+
acc.push({ ...separator });
|
|
2156
2313
|
}
|
|
2157
|
-
|
|
2158
|
-
|
|
2314
|
+
if (curr.length == 0 && this.config.default.length > 0) {
|
|
2315
|
+
curr.push(...parseString(this.config.default[0]).reduce((acc, curr) => {
|
|
2316
|
+
if (acc.length > 0) {
|
|
2317
|
+
acc.push({ typ: 'Whitespace' });
|
|
2318
|
+
}
|
|
2319
|
+
acc.push(curr);
|
|
2320
|
+
return acc;
|
|
2321
|
+
}, []));
|
|
2159
2322
|
}
|
|
2160
|
-
acc
|
|
2161
|
-
|
|
2323
|
+
acc.push(...curr);
|
|
2324
|
+
return acc;
|
|
2325
|
+
}, []);
|
|
2326
|
+
iterable = [{
|
|
2327
|
+
typ: 'Declaration',
|
|
2328
|
+
nam: this.config.shorthand,
|
|
2329
|
+
val: values
|
|
2330
|
+
}][Symbol.iterator]();
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
const iterators = [];
|
|
2334
|
+
return {
|
|
2335
|
+
// @ts-ignore
|
|
2336
|
+
next() {
|
|
2337
|
+
let v = iterable.next();
|
|
2338
|
+
while (v.done || v.value instanceof PropertySet) {
|
|
2339
|
+
if (v.value instanceof PropertySet) {
|
|
2340
|
+
// @ts-ignore
|
|
2341
|
+
iterators.push(iterable);
|
|
2342
|
+
iterable = v.value[Symbol.iterator]();
|
|
2343
|
+
v = iterable.next();
|
|
2344
|
+
}
|
|
2345
|
+
if (v.done) {
|
|
2346
|
+
if (iterators.length > 0) {
|
|
2162
2347
|
// @ts-ignore
|
|
2163
|
-
|
|
2348
|
+
iterable = iterators.pop();
|
|
2349
|
+
v = iterable.next();
|
|
2164
2350
|
}
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
}
|
|
2351
|
+
if (v.done && iterators.length == 0) {
|
|
2352
|
+
break;
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2169
2355
|
}
|
|
2356
|
+
return v;
|
|
2170
2357
|
}
|
|
2171
|
-
|
|
2172
|
-
}, []).reduce((acc, curr) => {
|
|
2173
|
-
if (acc.length > 0) {
|
|
2174
|
-
acc.push({ ...separator });
|
|
2175
|
-
}
|
|
2176
|
-
if (curr.length == 0) {
|
|
2177
|
-
curr.push(...this.config.default[0].split(/\s/).map(getTokenType).reduce((acc, curr) => {
|
|
2178
|
-
if (acc.length > 0) {
|
|
2179
|
-
acc.push({ typ: 'Whitespace' });
|
|
2180
|
-
}
|
|
2181
|
-
acc.push(curr);
|
|
2182
|
-
return acc;
|
|
2183
|
-
}, []));
|
|
2184
|
-
}
|
|
2185
|
-
acc.push(...curr);
|
|
2186
|
-
return acc;
|
|
2187
|
-
}, []);
|
|
2188
|
-
return [{
|
|
2189
|
-
typ: 'Declaration',
|
|
2190
|
-
nam: this.config.shorthand,
|
|
2191
|
-
val: values
|
|
2192
|
-
}][Symbol.iterator]();
|
|
2358
|
+
};
|
|
2193
2359
|
}
|
|
2194
2360
|
}
|
|
2195
2361
|
|
|
@@ -2199,33 +2365,61 @@ class PropertyList {
|
|
|
2199
2365
|
constructor() {
|
|
2200
2366
|
this.declarations = new Map;
|
|
2201
2367
|
}
|
|
2368
|
+
set(nam, value) {
|
|
2369
|
+
return this.add({ typ: 'Declaration', nam, val: Array.isArray(value) ? value : parseString(String(value)) });
|
|
2370
|
+
}
|
|
2202
2371
|
add(declaration) {
|
|
2203
2372
|
if (declaration.typ != 'Declaration') {
|
|
2204
2373
|
this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
|
|
2205
2374
|
return this;
|
|
2206
2375
|
}
|
|
2207
|
-
|
|
2376
|
+
let propertyName = declaration.nam;
|
|
2377
|
+
let shortHandType;
|
|
2378
|
+
let shorthand;
|
|
2208
2379
|
if (propertyName in config.properties) {
|
|
2209
2380
|
// @ts-ignore
|
|
2210
|
-
|
|
2381
|
+
if ('map' in config.properties[propertyName]) {
|
|
2382
|
+
shortHandType = 'map';
|
|
2383
|
+
// @ts-ignore
|
|
2384
|
+
shorthand = config.properties[propertyName].map;
|
|
2385
|
+
}
|
|
2386
|
+
else {
|
|
2387
|
+
shortHandType = 'set';
|
|
2388
|
+
// @ts-ignore
|
|
2389
|
+
shorthand = config.properties[propertyName].shorthand;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
else if (propertyName in config.map) {
|
|
2393
|
+
shortHandType = 'map';
|
|
2394
|
+
// @ts-ignore
|
|
2395
|
+
shorthand = config.map[propertyName].shorthand;
|
|
2396
|
+
}
|
|
2397
|
+
// @ts-ignore
|
|
2398
|
+
if (shortHandType == 'map') {
|
|
2399
|
+
// @ts-ignore
|
|
2211
2400
|
if (!this.declarations.has(shorthand)) {
|
|
2212
2401
|
// @ts-ignore
|
|
2213
|
-
this.declarations.set(shorthand, new
|
|
2402
|
+
this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
|
|
2214
2403
|
}
|
|
2404
|
+
// @ts-ignore
|
|
2215
2405
|
this.declarations.get(shorthand).add(declaration);
|
|
2216
|
-
return this;
|
|
2406
|
+
// return this;
|
|
2217
2407
|
}
|
|
2218
|
-
|
|
2408
|
+
// @ts-ignore
|
|
2409
|
+
else if (shortHandType == 'set') {
|
|
2219
2410
|
// @ts-ignore
|
|
2220
|
-
const shorthand = config.
|
|
2411
|
+
// const shorthand: string = <string>config.properties[propertyName].shorthand;
|
|
2221
2412
|
if (!this.declarations.has(shorthand)) {
|
|
2222
2413
|
// @ts-ignore
|
|
2223
|
-
this.declarations.set(shorthand, new
|
|
2414
|
+
this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
|
|
2224
2415
|
}
|
|
2416
|
+
// @ts-ignore
|
|
2225
2417
|
this.declarations.get(shorthand).add(declaration);
|
|
2226
|
-
return this;
|
|
2418
|
+
// return this;
|
|
2419
|
+
}
|
|
2420
|
+
else {
|
|
2421
|
+
this.declarations.set(propertyName, declaration);
|
|
2227
2422
|
}
|
|
2228
|
-
this.declarations.set(propertyName, declaration);
|
|
2229
2423
|
return this;
|
|
2230
2424
|
}
|
|
2231
2425
|
[Symbol.iterator]() {
|
|
@@ -2254,8 +2448,300 @@ class PropertyList {
|
|
|
2254
2448
|
}
|
|
2255
2449
|
}
|
|
2256
2450
|
|
|
2257
|
-
const
|
|
2258
|
-
|
|
2451
|
+
const combinators = ['+', '>', '~'];
|
|
2452
|
+
const notEndingWith = ['(', '['].concat(combinators);
|
|
2453
|
+
function minify(ast, options = {}, recursive = false) {
|
|
2454
|
+
function wrapNodes(previous, node, match, ast, i, nodeIndex) {
|
|
2455
|
+
// @ts-ignore
|
|
2456
|
+
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
2457
|
+
// @ts-ignore
|
|
2458
|
+
let nSel = match.selector2.reduce(reducer, []).join(',');
|
|
2459
|
+
// @ts-ignore
|
|
2460
|
+
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
2461
|
+
// @ts-ignore
|
|
2462
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
2463
|
+
enumerable: false,
|
|
2464
|
+
writable: true,
|
|
2465
|
+
// @ts-ignore
|
|
2466
|
+
value: match.match.map(t => t.slice())
|
|
2467
|
+
});
|
|
2468
|
+
if (pSel == '&' || pSel === '') {
|
|
2469
|
+
// @ts-ignore
|
|
2470
|
+
wrapper.chi.push(...previous.chi);
|
|
2471
|
+
// @ts-ignore
|
|
2472
|
+
if ((nSel == '&' || nSel === '') && hasOnlyDeclarations(previous)) {
|
|
2473
|
+
// @ts-ignore
|
|
2474
|
+
wrapper.chi.push(...node.chi);
|
|
2475
|
+
}
|
|
2476
|
+
else {
|
|
2477
|
+
// @ts-ignore
|
|
2478
|
+
wrapper.chi.push(node);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
else {
|
|
2482
|
+
// @ts-ignore
|
|
2483
|
+
wrapper.chi.push(previous, node);
|
|
2484
|
+
}
|
|
2485
|
+
// @ts-ignore
|
|
2486
|
+
ast.chi.splice(i, 1, wrapper);
|
|
2487
|
+
// @ts-ignore
|
|
2488
|
+
ast.chi.splice(nodeIndex, 1);
|
|
2489
|
+
// @ts-ignore
|
|
2490
|
+
previous.sel = pSel;
|
|
2491
|
+
// @ts-ignore
|
|
2492
|
+
previous.raw = match.selector1;
|
|
2493
|
+
// @ts-ignore
|
|
2494
|
+
node.sel = nSel;
|
|
2495
|
+
// @ts-ignore
|
|
2496
|
+
node.raw = match.selector2;
|
|
2497
|
+
reduceRuleSelector(wrapper);
|
|
2498
|
+
return wrapper;
|
|
2499
|
+
}
|
|
2500
|
+
function reducer(acc, curr, index, array) {
|
|
2501
|
+
// trim :is()
|
|
2502
|
+
if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
|
|
2503
|
+
curr = curr.slice(1, -1);
|
|
2504
|
+
}
|
|
2505
|
+
if (curr[0] == '&') {
|
|
2506
|
+
if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
|
|
2507
|
+
curr.splice(0, 2);
|
|
2508
|
+
}
|
|
2509
|
+
else if (combinators.includes(curr[1])) {
|
|
2510
|
+
curr.splice(0, 1);
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
else if (ast.typ == 'Rule' && (isIdent(curr[0]) || isFunction(curr[0]))) {
|
|
2514
|
+
curr.unshift('&', ' ');
|
|
2515
|
+
}
|
|
2516
|
+
acc.push(curr.join(''));
|
|
2517
|
+
return acc;
|
|
2518
|
+
}
|
|
2519
|
+
function diff(n1, n2, options = {}) {
|
|
2520
|
+
let node1 = n1;
|
|
2521
|
+
let node2 = n2;
|
|
2522
|
+
let exchanged = false;
|
|
2523
|
+
if (node1.chi.length > node2.chi.length) {
|
|
2524
|
+
const t = node1;
|
|
2525
|
+
node1 = node2;
|
|
2526
|
+
node2 = t;
|
|
2527
|
+
exchanged = true;
|
|
2528
|
+
}
|
|
2529
|
+
let i = node1.chi.length;
|
|
2530
|
+
let j = node2.chi.length;
|
|
2531
|
+
if (i == 0 || j == 0) {
|
|
2532
|
+
// @ts-ignore
|
|
2533
|
+
return null;
|
|
2534
|
+
}
|
|
2535
|
+
// @ts-ignore
|
|
2536
|
+
const raw1 = node1.raw;
|
|
2537
|
+
// @ts-ignore
|
|
2538
|
+
const raw2 = node2.raw;
|
|
2539
|
+
// @ts-ignore
|
|
2540
|
+
node1 = { ...node1, chi: node1.chi.slice() };
|
|
2541
|
+
node2 = { ...node2, chi: node2.chi.slice() };
|
|
2542
|
+
if (raw1 != null) {
|
|
2543
|
+
Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
|
|
2544
|
+
}
|
|
2545
|
+
if (raw2 != null) {
|
|
2546
|
+
Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
|
|
2547
|
+
}
|
|
2548
|
+
const intersect = [];
|
|
2549
|
+
while (i--) {
|
|
2550
|
+
if (node1.chi[i].typ == 'Comment') {
|
|
2551
|
+
continue;
|
|
2552
|
+
}
|
|
2553
|
+
j = node2.chi.length;
|
|
2554
|
+
if (j == 0) {
|
|
2555
|
+
break;
|
|
2556
|
+
}
|
|
2557
|
+
while (j--) {
|
|
2558
|
+
if (node2.chi[j].typ == 'Comment') {
|
|
2559
|
+
continue;
|
|
2560
|
+
}
|
|
2561
|
+
if (node1.chi[i].nam == node2.chi[j].nam) {
|
|
2562
|
+
if (eq(node1.chi[i], node2.chi[j])) {
|
|
2563
|
+
intersect.push(node1.chi[i]);
|
|
2564
|
+
node1.chi.splice(i, 1);
|
|
2565
|
+
node2.chi.splice(j, 1);
|
|
2566
|
+
break;
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
}
|
|
2571
|
+
// @ts-ignore
|
|
2572
|
+
const result = (intersect.length == 0 ? null : {
|
|
2573
|
+
...node1,
|
|
2574
|
+
// @ts-ignore
|
|
2575
|
+
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
|
|
2576
|
+
chi: intersect.reverse()
|
|
2577
|
+
});
|
|
2578
|
+
if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0)) {
|
|
2579
|
+
// @ts-ignore
|
|
2580
|
+
return null;
|
|
2581
|
+
}
|
|
2582
|
+
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
|
|
2583
|
+
}
|
|
2584
|
+
function matchSelectors(selector1, selector2, parentType) {
|
|
2585
|
+
let match = [[]];
|
|
2586
|
+
const j = Math.min(selector1.reduce((acc, curr) => Math.min(acc, curr.length), selector1.length > 0 ? selector1[0].length : 0), selector2.reduce((acc, curr) => Math.min(acc, curr.length), selector2.length > 0 ? selector2[0].length : 0));
|
|
2587
|
+
let i = 0;
|
|
2588
|
+
let k;
|
|
2589
|
+
let l;
|
|
2590
|
+
let token;
|
|
2591
|
+
let matching = true;
|
|
2592
|
+
let matchFunction = 0;
|
|
2593
|
+
let inAttr = 0;
|
|
2594
|
+
for (; i < j; i++) {
|
|
2595
|
+
k = 0;
|
|
2596
|
+
token = selector1[0][i];
|
|
2597
|
+
for (; k < selector1.length; k++) {
|
|
2598
|
+
if (selector1[k][i] != token) {
|
|
2599
|
+
matching = false;
|
|
2600
|
+
break;
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
if (matching) {
|
|
2604
|
+
l = 0;
|
|
2605
|
+
for (; l < selector2.length; l++) {
|
|
2606
|
+
if (selector2[l][i] != token) {
|
|
2607
|
+
matching = false;
|
|
2608
|
+
break;
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
}
|
|
2612
|
+
if (!matching) {
|
|
2613
|
+
break;
|
|
2614
|
+
}
|
|
2615
|
+
if (token == ',') {
|
|
2616
|
+
match.push([]);
|
|
2617
|
+
}
|
|
2618
|
+
else {
|
|
2619
|
+
if (token.endsWith('(')) {
|
|
2620
|
+
matchFunction++;
|
|
2621
|
+
}
|
|
2622
|
+
if (token.endsWith('[')) {
|
|
2623
|
+
inAttr++;
|
|
2624
|
+
}
|
|
2625
|
+
else if (token == ')') {
|
|
2626
|
+
matchFunction--;
|
|
2627
|
+
}
|
|
2628
|
+
else if (token == ']') {
|
|
2629
|
+
inAttr--;
|
|
2630
|
+
}
|
|
2631
|
+
match.at(-1).push(token);
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
// invalid function
|
|
2635
|
+
if (matchFunction != 0 || inAttr != 0) {
|
|
2636
|
+
return null;
|
|
2637
|
+
}
|
|
2638
|
+
if (parentType != 'Rule') {
|
|
2639
|
+
for (const part of match) {
|
|
2640
|
+
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
|
|
2641
|
+
return null;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
if (match.length > 1) {
|
|
2646
|
+
console.error(`unsupported multilevel matching`);
|
|
2647
|
+
console.error({ match, selector1, selector2 });
|
|
2648
|
+
return null;
|
|
2649
|
+
}
|
|
2650
|
+
for (const part of match) {
|
|
2651
|
+
while (part.length > 0) {
|
|
2652
|
+
const token = part.at(-1);
|
|
2653
|
+
if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
|
|
2654
|
+
part.pop();
|
|
2655
|
+
continue;
|
|
2656
|
+
}
|
|
2657
|
+
break;
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
if (match.every(t => t.length == 0)) {
|
|
2661
|
+
return null;
|
|
2662
|
+
}
|
|
2663
|
+
if (eq([['&']], match)) {
|
|
2664
|
+
return null;
|
|
2665
|
+
}
|
|
2666
|
+
function reduce(acc, curr) {
|
|
2667
|
+
if (acc === null) {
|
|
2668
|
+
return null;
|
|
2669
|
+
}
|
|
2670
|
+
let hasCompoundSelector = true;
|
|
2671
|
+
curr = curr.slice(match[0].length);
|
|
2672
|
+
while (curr.length > 0) {
|
|
2673
|
+
if (curr[0] == ' ') {
|
|
2674
|
+
hasCompoundSelector = false;
|
|
2675
|
+
curr.unshift('&');
|
|
2676
|
+
continue;
|
|
2677
|
+
}
|
|
2678
|
+
break;
|
|
2679
|
+
}
|
|
2680
|
+
// invalid function match
|
|
2681
|
+
if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
|
|
2682
|
+
return null;
|
|
2683
|
+
}
|
|
2684
|
+
if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
|
|
2685
|
+
return null;
|
|
2686
|
+
}
|
|
2687
|
+
if (hasCompoundSelector && curr.length > 0) {
|
|
2688
|
+
hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
2689
|
+
}
|
|
2690
|
+
if (curr[0] == ':is(') {
|
|
2691
|
+
let inFunction = 0;
|
|
2692
|
+
let canReduce = true;
|
|
2693
|
+
const isCompound = curr.reduce((acc, token, index) => {
|
|
2694
|
+
if (index == 0) {
|
|
2695
|
+
inFunction++;
|
|
2696
|
+
canReduce = curr[1] == '&';
|
|
2697
|
+
}
|
|
2698
|
+
else if (token.endsWith('(')) {
|
|
2699
|
+
if (inFunction == 0) {
|
|
2700
|
+
canReduce = false;
|
|
2701
|
+
}
|
|
2702
|
+
inFunction++;
|
|
2703
|
+
}
|
|
2704
|
+
else if (token == ')') {
|
|
2705
|
+
inFunction--;
|
|
2706
|
+
}
|
|
2707
|
+
else if (token == ',') {
|
|
2708
|
+
if (!canReduce) {
|
|
2709
|
+
canReduce = curr[index + 1] == '&';
|
|
2710
|
+
}
|
|
2711
|
+
acc.push([]);
|
|
2712
|
+
}
|
|
2713
|
+
else
|
|
2714
|
+
acc.at(-1)?.push(token);
|
|
2715
|
+
return acc;
|
|
2716
|
+
}, [[]]);
|
|
2717
|
+
if (inFunction > 0) {
|
|
2718
|
+
canReduce = false;
|
|
2719
|
+
}
|
|
2720
|
+
if (canReduce) {
|
|
2721
|
+
curr = isCompound.reduce((acc, curr) => {
|
|
2722
|
+
if (acc.length > 0) {
|
|
2723
|
+
acc.push(',');
|
|
2724
|
+
}
|
|
2725
|
+
acc.push(...curr);
|
|
2726
|
+
return acc;
|
|
2727
|
+
}, []);
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
|
|
2731
|
+
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
|
|
2732
|
+
return acc;
|
|
2733
|
+
}
|
|
2734
|
+
// @ts-ignore
|
|
2735
|
+
selector1 = selector1.reduce(reduce, []);
|
|
2736
|
+
// @ts-ignore
|
|
2737
|
+
selector2 = selector2.reduce(reduce, []);
|
|
2738
|
+
return selector1 == null || selector2 == null ? null : {
|
|
2739
|
+
eq: eq(selector1, selector2),
|
|
2740
|
+
match,
|
|
2741
|
+
selector1,
|
|
2742
|
+
selector2
|
|
2743
|
+
};
|
|
2744
|
+
}
|
|
2259
2745
|
// @ts-ignore
|
|
2260
2746
|
if (('chi' in ast) && ast.chi?.length > 0) {
|
|
2261
2747
|
let i = 0;
|
|
@@ -2270,6 +2756,14 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2270
2756
|
}
|
|
2271
2757
|
// @ts-ignore
|
|
2272
2758
|
node = ast.chi[i];
|
|
2759
|
+
// @ts-ignore
|
|
2760
|
+
if (previous == node) {
|
|
2761
|
+
// console.error('idem!');
|
|
2762
|
+
// @ts-ignore
|
|
2763
|
+
ast.chi.splice(i, 1);
|
|
2764
|
+
i--;
|
|
2765
|
+
continue;
|
|
2766
|
+
}
|
|
2273
2767
|
if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
|
2274
2768
|
continue;
|
|
2275
2769
|
}
|
|
@@ -2282,120 +2776,118 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2282
2776
|
// @ts-ignore
|
|
2283
2777
|
if (node.typ == 'Rule') {
|
|
2284
2778
|
reduceRuleSelector(node);
|
|
2779
|
+
let wrapper;
|
|
2780
|
+
let match;
|
|
2285
2781
|
// @ts-ignore
|
|
2286
|
-
if (options.nestingRules
|
|
2287
|
-
const match = [];
|
|
2782
|
+
if (options.nestingRules) {
|
|
2288
2783
|
// @ts-ignore
|
|
2289
|
-
|
|
2290
|
-
// @ts-ignore
|
|
2291
|
-
if (node.raw[0][0] != previous.raw[0][0]) {
|
|
2292
|
-
break;
|
|
2293
|
-
}
|
|
2294
|
-
// @ts-ignore
|
|
2295
|
-
match.push(node.raw[0].shift());
|
|
2296
|
-
// @ts-ignore
|
|
2297
|
-
previous.raw[0].shift();
|
|
2298
|
-
}
|
|
2299
|
-
if (match.length > 0) {
|
|
2784
|
+
if (previous?.typ == 'Rule') {
|
|
2300
2785
|
// @ts-ignore
|
|
2301
|
-
|
|
2786
|
+
reduceRuleSelector(previous);
|
|
2302
2787
|
// @ts-ignore
|
|
2303
|
-
|
|
2304
|
-
// @ts-ignore
|
|
2305
|
-
wrapper.chi.push(...previous.chi);
|
|
2306
|
-
}
|
|
2307
|
-
else {
|
|
2308
|
-
// @ts-ignore
|
|
2309
|
-
previous.sel = previous.raw.reduce((acc, curr) => {
|
|
2310
|
-
acc.push(curr.join(''));
|
|
2311
|
-
return acc;
|
|
2312
|
-
}, []).join(',');
|
|
2313
|
-
// @ts-ignore
|
|
2314
|
-
wrapper.chi.push(previous);
|
|
2315
|
-
}
|
|
2788
|
+
match = matchSelectors(previous.raw, node.raw, ast.typ);
|
|
2316
2789
|
// @ts-ignore
|
|
2317
|
-
if (
|
|
2318
|
-
// @ts-ignore
|
|
2319
|
-
if (previous.raw.length == 0) {
|
|
2320
|
-
// @ts-ignore
|
|
2321
|
-
wrapper.chi.push(...node.chi);
|
|
2322
|
-
}
|
|
2323
|
-
else {
|
|
2324
|
-
if (hasOnlyDeclarations(wrapper)) {
|
|
2325
|
-
wrapper.chi.push(...node.chi);
|
|
2326
|
-
}
|
|
2327
|
-
else {
|
|
2328
|
-
// @ts-ignore
|
|
2329
|
-
node.raw[0].push('&');
|
|
2330
|
-
// @ts-ignore
|
|
2331
|
-
node.sel = node.raw.reduce((acc, curr) => {
|
|
2332
|
-
acc.push(curr.join(''));
|
|
2333
|
-
return acc;
|
|
2334
|
-
}, []).join(',');
|
|
2335
|
-
// @ts-ignore
|
|
2336
|
-
wrapper.chi.push(node);
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
}
|
|
2340
|
-
else {
|
|
2790
|
+
if (match != null) {
|
|
2341
2791
|
// @ts-ignore
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
return acc;
|
|
2345
|
-
}, []).join(',');
|
|
2792
|
+
wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
|
|
2793
|
+
nodeIndex = i - 1;
|
|
2346
2794
|
// @ts-ignore
|
|
2347
|
-
|
|
2795
|
+
previous = ast.chi[nodeIndex];
|
|
2348
2796
|
}
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
// @ts-ignore
|
|
2353
|
-
ast.chi.splice(nodeIndex, 1);
|
|
2797
|
+
}
|
|
2798
|
+
// @ts-ignore
|
|
2799
|
+
if (wrapper != null) {
|
|
2354
2800
|
// @ts-ignore
|
|
2355
2801
|
while (i < ast.chi.length) {
|
|
2356
2802
|
// @ts-ignore
|
|
2357
2803
|
const nextNode = ast.chi[i];
|
|
2358
2804
|
// @ts-ignore
|
|
2359
|
-
if (nextNode.typ != 'Rule'
|
|
2805
|
+
if (nextNode.typ != 'Rule') {
|
|
2806
|
+
// i--;
|
|
2807
|
+
// previous = wrapper;
|
|
2808
|
+
// nodeIndex = i;
|
|
2360
2809
|
break;
|
|
2361
2810
|
}
|
|
2362
2811
|
reduceRuleSelector(nextNode);
|
|
2363
2812
|
// @ts-ignore
|
|
2364
|
-
|
|
2813
|
+
match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
|
|
2814
|
+
// @ts-ignore
|
|
2815
|
+
if (match == null) {
|
|
2365
2816
|
break;
|
|
2366
2817
|
}
|
|
2367
2818
|
// @ts-ignore
|
|
2368
|
-
|
|
2819
|
+
wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
|
|
2820
|
+
}
|
|
2821
|
+
nodeIndex = --i;
|
|
2822
|
+
// @ts-ignore
|
|
2823
|
+
previous = ast.chi[nodeIndex];
|
|
2824
|
+
minify(wrapper, options, recursive);
|
|
2825
|
+
continue;
|
|
2826
|
+
}
|
|
2827
|
+
// @ts-ignore
|
|
2828
|
+
else if (node.optimized != null &&
|
|
2829
|
+
// @ts-ignore
|
|
2830
|
+
node.optimized.match &&
|
|
2831
|
+
// @ts-ignore
|
|
2832
|
+
node.optimized.selector.length > 1) {
|
|
2833
|
+
// @ts-ignore
|
|
2834
|
+
wrapper = { ...node, chi: [], sel: node.optimized.optimized[0] };
|
|
2835
|
+
// @ts-ignore
|
|
2836
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
2837
|
+
enumerable: false,
|
|
2838
|
+
writable: true,
|
|
2369
2839
|
// @ts-ignore
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2840
|
+
value: [[node.optimized.optimized[0]]]
|
|
2841
|
+
});
|
|
2842
|
+
// @ts-ignore
|
|
2843
|
+
node.sel = node.optimized.selector.reduce(reducer, []).join(',');
|
|
2844
|
+
// @ts-ignore
|
|
2845
|
+
node.raw = node.optimized.selector.slice();
|
|
2846
|
+
// @ts-ignore
|
|
2847
|
+
wrapper.chi.push(node);
|
|
2848
|
+
// @ts-ignore
|
|
2849
|
+
ast.chi.splice(i, 1, wrapper);
|
|
2850
|
+
node = wrapper;
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
// @ts-ignore
|
|
2854
|
+
else if (node.optimized?.match) {
|
|
2855
|
+
let wrap = true;
|
|
2856
|
+
// @ts-ignore
|
|
2857
|
+
const selector = node.optimized.selector.reduce((acc, curr) => {
|
|
2858
|
+
if (curr[0] == '&') {
|
|
2859
|
+
if (curr[1] == ' ') {
|
|
2860
|
+
curr.splice(0, 2);
|
|
2861
|
+
}
|
|
2862
|
+
else {
|
|
2863
|
+
if (ast.typ != 'Rule' && combinators.includes(curr[1])) {
|
|
2864
|
+
wrap = false;
|
|
2378
2865
|
}
|
|
2379
2866
|
else {
|
|
2380
|
-
|
|
2381
|
-
nextNode.raw[0].push('&');
|
|
2867
|
+
curr.splice(0, 1);
|
|
2382
2868
|
}
|
|
2383
2869
|
}
|
|
2384
|
-
// @ts-ignore
|
|
2385
|
-
nextNode.sel = nextNode.raw.reduce((acc, curr) => {
|
|
2386
|
-
acc.push(curr.join(''));
|
|
2387
|
-
return acc;
|
|
2388
|
-
}, []).join(',');
|
|
2389
|
-
wrapper.chi.push(nextNode);
|
|
2390
|
-
// @ts-ignore
|
|
2391
|
-
ast.chi.splice(i, 1);
|
|
2392
2870
|
}
|
|
2393
|
-
|
|
2394
|
-
|
|
2871
|
+
else if (combinators.includes(curr[0])) {
|
|
2872
|
+
curr.unshift('&');
|
|
2873
|
+
wrap = false;
|
|
2874
|
+
}
|
|
2395
2875
|
// @ts-ignore
|
|
2396
|
-
|
|
2397
|
-
|
|
2876
|
+
acc.push(curr);
|
|
2877
|
+
return acc;
|
|
2878
|
+
}, []);
|
|
2879
|
+
if (!wrap) {
|
|
2880
|
+
wrap = selector.some(s => s[0] != '&');
|
|
2398
2881
|
}
|
|
2882
|
+
const rule = selector.map(s => {
|
|
2883
|
+
if (s[0] == '&') {
|
|
2884
|
+
// @ts-ignore
|
|
2885
|
+
s[0] = node.optimized.optimized[0];
|
|
2886
|
+
}
|
|
2887
|
+
return s.join('');
|
|
2888
|
+
}).join(',');
|
|
2889
|
+
// @ts-ignore
|
|
2890
|
+
node.sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
|
|
2399
2891
|
}
|
|
2400
2892
|
}
|
|
2401
2893
|
// @ts-ignore
|
|
@@ -2425,10 +2917,11 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2425
2917
|
ast.chi.splice(nodeIndex, 1);
|
|
2426
2918
|
// @ts-ignore
|
|
2427
2919
|
if (hasDeclaration(node)) {
|
|
2428
|
-
|
|
2920
|
+
// @ts-ignore
|
|
2921
|
+
minifyRule(node);
|
|
2429
2922
|
}
|
|
2430
2923
|
else {
|
|
2431
|
-
|
|
2924
|
+
minify(node, options, recursive);
|
|
2432
2925
|
}
|
|
2433
2926
|
i--;
|
|
2434
2927
|
previous = node;
|
|
@@ -2469,10 +2962,11 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2469
2962
|
if (recursive && previous != node) {
|
|
2470
2963
|
// @ts-ignore
|
|
2471
2964
|
if (hasDeclaration(previous)) {
|
|
2472
|
-
|
|
2965
|
+
// @ts-ignore
|
|
2966
|
+
minifyRule(previous);
|
|
2473
2967
|
}
|
|
2474
2968
|
else {
|
|
2475
|
-
|
|
2969
|
+
minify(previous, options, recursive);
|
|
2476
2970
|
}
|
|
2477
2971
|
}
|
|
2478
2972
|
}
|
|
@@ -2483,98 +2977,176 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2483
2977
|
if (recursive && node != null && ('chi' in node)) {
|
|
2484
2978
|
// @ts-ignore
|
|
2485
2979
|
if (node.chi.some(n => n.typ == 'Declaration')) {
|
|
2486
|
-
|
|
2980
|
+
minifyRule(node);
|
|
2487
2981
|
}
|
|
2488
2982
|
else {
|
|
2983
|
+
// @ts-ignore
|
|
2489
2984
|
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
|
|
2490
|
-
|
|
2985
|
+
minify(node, options, recursive);
|
|
2491
2986
|
}
|
|
2492
2987
|
}
|
|
2493
2988
|
}
|
|
2494
2989
|
}
|
|
2495
2990
|
return ast;
|
|
2496
2991
|
}
|
|
2497
|
-
function
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
if (node.chi[k].typ == 'Comment') {
|
|
2501
|
-
continue;
|
|
2502
|
-
}
|
|
2503
|
-
return node.chi[k].typ == 'Declaration';
|
|
2504
|
-
}
|
|
2505
|
-
return true;
|
|
2506
|
-
}
|
|
2507
|
-
function hasDeclaration(node) {
|
|
2508
|
-
// @ts-ignore
|
|
2509
|
-
for (let i = 0; i < node.chi?.length; i++) {
|
|
2510
|
-
// @ts-ignore
|
|
2511
|
-
if (node.chi[i].typ == 'Comment') {
|
|
2512
|
-
continue;
|
|
2513
|
-
}
|
|
2514
|
-
// @ts-ignore
|
|
2515
|
-
return node.chi[i].typ == 'Declaration';
|
|
2992
|
+
function reduceSelector(selector) {
|
|
2993
|
+
if (selector.length == 0) {
|
|
2994
|
+
return null;
|
|
2516
2995
|
}
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2996
|
+
const optimized = [];
|
|
2997
|
+
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
|
|
2998
|
+
let i = 0;
|
|
2999
|
+
let j;
|
|
3000
|
+
let match;
|
|
3001
|
+
for (; i < k; i++) {
|
|
3002
|
+
const item = selector[0][i];
|
|
3003
|
+
match = true;
|
|
3004
|
+
for (j = 1; j < selector.length; j++) {
|
|
3005
|
+
if (item != selector[j][i]) {
|
|
3006
|
+
match = false;
|
|
3007
|
+
break;
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
if (!match) {
|
|
3011
|
+
break;
|
|
3012
|
+
}
|
|
3013
|
+
optimized.push(item);
|
|
3014
|
+
}
|
|
3015
|
+
while (optimized.length > 0) {
|
|
3016
|
+
const last = optimized.at(-1);
|
|
3017
|
+
if ((last == ' ' || combinators.includes(last))) {
|
|
3018
|
+
optimized.pop();
|
|
3019
|
+
continue;
|
|
3020
|
+
}
|
|
3021
|
+
break;
|
|
3022
|
+
}
|
|
3023
|
+
selector.forEach((selector) => selector.splice(0, optimized.length));
|
|
3024
|
+
// combinator
|
|
3025
|
+
if (combinators.includes(optimized.at(-1))) {
|
|
3026
|
+
const combinator = optimized.pop();
|
|
3027
|
+
selector.forEach(selector => selector.unshift(combinator));
|
|
3028
|
+
}
|
|
3029
|
+
let reducible = optimized.length == 1;
|
|
3030
|
+
if (optimized[0] == '&' && optimized[1] == ' ') {
|
|
3031
|
+
optimized.splice(0, 2);
|
|
3032
|
+
}
|
|
3033
|
+
if (optimized.length == 0 ||
|
|
3034
|
+
(optimized[0].charAt(0) == '&' ||
|
|
3035
|
+
selector.length == 1)) {
|
|
3036
|
+
return {
|
|
3037
|
+
match: false,
|
|
3038
|
+
optimized,
|
|
3039
|
+
selector: selector.map(selector => selector[0] == '&' && selector[1] == ' ' ? selector.slice(2) : selector),
|
|
3040
|
+
reducible: selector.length > 1 && selector.every((selector) => !combinators.includes(selector[0]))
|
|
3041
|
+
};
|
|
3042
|
+
}
|
|
3043
|
+
return {
|
|
3044
|
+
match: true,
|
|
3045
|
+
optimized,
|
|
3046
|
+
selector: selector.reduce((acc, curr) => {
|
|
3047
|
+
let hasCompound = true;
|
|
3048
|
+
if (hasCompound && curr.length > 0) {
|
|
3049
|
+
hasCompound = !['&'].concat(combinators).includes(curr[0].charAt(0));
|
|
3050
|
+
}
|
|
3051
|
+
// @ts-ignore
|
|
3052
|
+
if (hasCompound && curr[0] == ' ') {
|
|
3053
|
+
hasCompound = false;
|
|
3054
|
+
curr.unshift('&');
|
|
3055
|
+
}
|
|
3056
|
+
if (curr.length == 0) {
|
|
3057
|
+
curr.push('&');
|
|
3058
|
+
hasCompound = false;
|
|
3059
|
+
}
|
|
3060
|
+
if (reducible) {
|
|
3061
|
+
const chr = curr[0].charAt(0);
|
|
3062
|
+
// @ts-ignore
|
|
3063
|
+
reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
|
|
3064
|
+
}
|
|
3065
|
+
acc.push(hasCompound ? ['&'].concat(curr) : curr);
|
|
3066
|
+
return acc;
|
|
3067
|
+
}, []),
|
|
3068
|
+
reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
|
|
3069
|
+
};
|
|
3070
|
+
}
|
|
3071
|
+
function hasOnlyDeclarations(node) {
|
|
3072
|
+
let k = node.chi.length;
|
|
3073
|
+
while (k--) {
|
|
3074
|
+
if (node.chi[k].typ == 'Comment') {
|
|
3075
|
+
continue;
|
|
3076
|
+
}
|
|
3077
|
+
return node.chi[k].typ == 'Declaration';
|
|
3078
|
+
}
|
|
3079
|
+
return true;
|
|
3080
|
+
}
|
|
3081
|
+
function hasDeclaration(node) {
|
|
3082
|
+
// @ts-ignore
|
|
3083
|
+
for (let i = 0; i < node.chi?.length; i++) {
|
|
3084
|
+
// @ts-ignore
|
|
3085
|
+
if (node.chi[i].typ == 'Comment') {
|
|
3086
|
+
continue;
|
|
3087
|
+
}
|
|
3088
|
+
// @ts-ignore
|
|
3089
|
+
return node.chi[i].typ == 'Declaration';
|
|
3090
|
+
}
|
|
3091
|
+
return true;
|
|
3092
|
+
}
|
|
3093
|
+
function minifyRule(ast) {
|
|
3094
|
+
// @ts-ignore
|
|
2521
3095
|
if (!('chi' in ast) || ast.chi?.length <= 1) {
|
|
2522
3096
|
return ast;
|
|
2523
3097
|
}
|
|
2524
3098
|
// @ts-ignore
|
|
2525
3099
|
const j = ast.chi.length;
|
|
2526
3100
|
let k = 0;
|
|
2527
|
-
let
|
|
3101
|
+
let properties = new PropertyList();
|
|
2528
3102
|
// @ts-ignore
|
|
2529
3103
|
for (; k < j; k++) {
|
|
2530
3104
|
// @ts-ignore
|
|
2531
3105
|
const node = ast.chi[k];
|
|
2532
|
-
if (node.typ == 'Comment') {
|
|
2533
|
-
|
|
2534
|
-
map.set(node, node);
|
|
3106
|
+
if (node.typ == 'Comment' || node.typ == 'Declaration') {
|
|
3107
|
+
properties.add(node);
|
|
2535
3108
|
continue;
|
|
2536
3109
|
}
|
|
2537
|
-
|
|
2538
|
-
break;
|
|
2539
|
-
}
|
|
2540
|
-
if (node.nam in configuration.map ||
|
|
2541
|
-
node.nam in configuration.properties) {
|
|
2542
|
-
// @ts-ignore
|
|
2543
|
-
const shorthand = node.nam in configuration.map ? configuration.map[node.nam].shorthand : configuration.properties[node.nam].shorthand;
|
|
2544
|
-
if (!map.has(shorthand)) {
|
|
2545
|
-
map.set(shorthand, new PropertyList());
|
|
2546
|
-
}
|
|
2547
|
-
map.get(shorthand).add(node);
|
|
2548
|
-
}
|
|
2549
|
-
else {
|
|
2550
|
-
map.set(node.nam, node);
|
|
2551
|
-
}
|
|
2552
|
-
}
|
|
2553
|
-
const children = [];
|
|
2554
|
-
for (let child of map.values()) {
|
|
2555
|
-
if (child instanceof PropertyList) {
|
|
2556
|
-
// @ts-ignore
|
|
2557
|
-
children.push(...child);
|
|
2558
|
-
}
|
|
2559
|
-
else {
|
|
2560
|
-
// @ts-ignore
|
|
2561
|
-
children.push(child);
|
|
2562
|
-
}
|
|
3110
|
+
break;
|
|
2563
3111
|
}
|
|
2564
3112
|
// @ts-ignore
|
|
2565
|
-
ast.chi =
|
|
3113
|
+
ast.chi = [...properties].concat(ast.chi.slice(k));
|
|
2566
3114
|
return ast;
|
|
2567
3115
|
}
|
|
2568
3116
|
function splitRule(buffer) {
|
|
2569
|
-
const result = [];
|
|
3117
|
+
const result = [[]];
|
|
2570
3118
|
let str = '';
|
|
2571
3119
|
for (let i = 0; i < buffer.length; i++) {
|
|
2572
3120
|
let chr = buffer.charAt(i);
|
|
3121
|
+
if (isWhiteSpace(chr.charCodeAt(0))) {
|
|
3122
|
+
let k = i;
|
|
3123
|
+
while (k + 1 < buffer.length) {
|
|
3124
|
+
if (isWhiteSpace(buffer[k + 1].charCodeAt(0))) {
|
|
3125
|
+
k++;
|
|
3126
|
+
continue;
|
|
3127
|
+
}
|
|
3128
|
+
break;
|
|
3129
|
+
}
|
|
3130
|
+
if (str !== '') {
|
|
3131
|
+
// @ts-ignore
|
|
3132
|
+
result.at(-1).push(str);
|
|
3133
|
+
str = '';
|
|
3134
|
+
}
|
|
3135
|
+
// @ts-ignore
|
|
3136
|
+
if (result.at(-1).length > 0) {
|
|
3137
|
+
// @ts-ignore
|
|
3138
|
+
result.at(-1).push(' ');
|
|
3139
|
+
}
|
|
3140
|
+
i = k;
|
|
3141
|
+
continue;
|
|
3142
|
+
}
|
|
2573
3143
|
if (chr == ',') {
|
|
2574
3144
|
if (str !== '') {
|
|
2575
|
-
|
|
3145
|
+
// @ts-ignore
|
|
3146
|
+
result.at(-1).push(str);
|
|
2576
3147
|
str = '';
|
|
2577
3148
|
}
|
|
3149
|
+
result.push([]);
|
|
2578
3150
|
continue;
|
|
2579
3151
|
}
|
|
2580
3152
|
str += chr;
|
|
@@ -2624,198 +3196,64 @@ function splitRule(buffer) {
|
|
|
2624
3196
|
}
|
|
2625
3197
|
}
|
|
2626
3198
|
if (str !== '') {
|
|
2627
|
-
|
|
3199
|
+
// @ts-ignore
|
|
3200
|
+
result.at(-1).push(str);
|
|
2628
3201
|
}
|
|
2629
3202
|
return result;
|
|
2630
3203
|
}
|
|
2631
3204
|
function reduceRuleSelector(node) {
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
// @ts-ignore
|
|
2635
|
-
let optimized = reduceSelector(node.raw);
|
|
2636
|
-
if (optimized != null) {
|
|
2637
|
-
Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
|
|
2638
|
-
}
|
|
2639
|
-
if (optimized != null && optimized.match && optimized.reducible) {
|
|
2640
|
-
const raw = [
|
|
2641
|
-
[
|
|
2642
|
-
optimized.optimized[0], ':is('
|
|
2643
|
-
].concat(optimized.selector.reduce((acc, curr) => {
|
|
2644
|
-
if (acc.length > 0) {
|
|
2645
|
-
acc.push(',');
|
|
2646
|
-
}
|
|
2647
|
-
acc.push(...curr);
|
|
2648
|
-
return acc;
|
|
2649
|
-
}, [])).concat(')')
|
|
2650
|
-
];
|
|
2651
|
-
const sel = raw[0].join('');
|
|
2652
|
-
if (sel.length < node.sel.length) {
|
|
2653
|
-
node.sel = sel;
|
|
2654
|
-
// node.raw = raw;
|
|
2655
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
2656
|
-
}
|
|
2657
|
-
}
|
|
2658
|
-
}
|
|
2659
|
-
}
|
|
2660
|
-
function diff(n1, n2, options = {}) {
|
|
2661
|
-
let node1 = n1;
|
|
2662
|
-
let node2 = n2;
|
|
2663
|
-
let exchanged = false;
|
|
2664
|
-
if (node1.chi.length > node2.chi.length) {
|
|
2665
|
-
const t = node1;
|
|
2666
|
-
node1 = node2;
|
|
2667
|
-
node2 = t;
|
|
2668
|
-
exchanged = true;
|
|
2669
|
-
}
|
|
2670
|
-
let i = node1.chi.length;
|
|
2671
|
-
let j = node2.chi.length;
|
|
2672
|
-
if (i == 0 || j == 0) {
|
|
2673
|
-
// @ts-ignore
|
|
2674
|
-
return null;
|
|
3205
|
+
if (node.raw == null) {
|
|
3206
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: splitRule(node.sel) });
|
|
2675
3207
|
}
|
|
2676
3208
|
// @ts-ignore
|
|
2677
|
-
|
|
2678
|
-
// @ts-ignore
|
|
2679
|
-
const optimized1 = node1.optimized;
|
|
3209
|
+
// if (node.raw != null) {
|
|
2680
3210
|
// @ts-ignore
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
Object.defineProperty(node1, 'raw', { enumerable: false, writable: true, value: raw1 });
|
|
2688
|
-
}
|
|
2689
|
-
if (optimized1 != null) {
|
|
2690
|
-
Object.defineProperty(node1, 'optimized', { enumerable: false, writable: true, value: optimized1 });
|
|
2691
|
-
}
|
|
2692
|
-
if (raw2 != null) {
|
|
2693
|
-
Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
|
|
2694
|
-
}
|
|
2695
|
-
if (optimized2 != null) {
|
|
2696
|
-
Object.defineProperty(node2, 'optimized', { enumerable: false, writable: true, value: optimized2 });
|
|
3211
|
+
let optimized = reduceSelector(node.raw.reduce((acc, curr) => {
|
|
3212
|
+
acc.push(curr.slice());
|
|
3213
|
+
return acc;
|
|
3214
|
+
}, []));
|
|
3215
|
+
if (optimized != null) {
|
|
3216
|
+
Object.defineProperty(node, 'optimized', { enumerable: false, writable: true, value: optimized });
|
|
2697
3217
|
}
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
break;
|
|
2706
|
-
}
|
|
2707
|
-
while (j--) {
|
|
2708
|
-
if (node2.chi[j].typ == 'Comment') {
|
|
2709
|
-
continue;
|
|
2710
|
-
}
|
|
2711
|
-
if (node1.chi[i].nam == node2.chi[j].nam) {
|
|
2712
|
-
if (eq(node1.chi[i], node2.chi[j])) {
|
|
2713
|
-
intersect.push(node1.chi[i]);
|
|
2714
|
-
node1.chi.splice(i, 1);
|
|
2715
|
-
node2.chi.splice(j, 1);
|
|
2716
|
-
break;
|
|
3218
|
+
if (optimized != null && optimized.match && optimized.reducible && optimized.selector.length > 1) {
|
|
3219
|
+
const raw = [
|
|
3220
|
+
[
|
|
3221
|
+
optimized.optimized[0], ':is('
|
|
3222
|
+
].concat(optimized.selector.reduce((acc, curr) => {
|
|
3223
|
+
if (acc.length > 0) {
|
|
3224
|
+
acc.push(',');
|
|
2717
3225
|
}
|
|
2718
|
-
|
|
3226
|
+
acc.push(...curr);
|
|
3227
|
+
return acc;
|
|
3228
|
+
}, [])).concat(')')
|
|
3229
|
+
];
|
|
3230
|
+
const sel = raw[0].join('');
|
|
3231
|
+
if (sel.length < node.sel.length) {
|
|
3232
|
+
node.sel = sel;
|
|
3233
|
+
// node.raw = raw;
|
|
3234
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
2719
3235
|
}
|
|
2720
3236
|
}
|
|
3237
|
+
// }
|
|
3238
|
+
}
|
|
3239
|
+
|
|
3240
|
+
function* walk(node) {
|
|
2721
3241
|
// @ts-ignore
|
|
2722
|
-
|
|
2723
|
-
...node1,
|
|
2724
|
-
// @ts-ignore
|
|
2725
|
-
sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(),
|
|
2726
|
-
chi: intersect.reverse()
|
|
2727
|
-
});
|
|
2728
|
-
if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + render(curr, options).code.length, 0)) {
|
|
2729
|
-
// @ts-ignore
|
|
2730
|
-
return null;
|
|
2731
|
-
}
|
|
2732
|
-
return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 };
|
|
3242
|
+
yield* doWalk(node, null, null);
|
|
2733
3243
|
}
|
|
2734
|
-
function
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
|
|
2740
|
-
let i = 0;
|
|
2741
|
-
let j;
|
|
2742
|
-
let match;
|
|
2743
|
-
for (; i < k; i++) {
|
|
2744
|
-
const item = selector[0][i];
|
|
2745
|
-
match = true;
|
|
2746
|
-
for (j = 1; j < selector.length; j++) {
|
|
2747
|
-
if (item != selector[j][i]) {
|
|
2748
|
-
match = false;
|
|
2749
|
-
break;
|
|
2750
|
-
}
|
|
2751
|
-
}
|
|
2752
|
-
if (!match) {
|
|
2753
|
-
break;
|
|
3244
|
+
function* doWalk(node, parent, root) {
|
|
3245
|
+
yield { node, parent, root };
|
|
3246
|
+
if ('chi' in node) {
|
|
3247
|
+
for (const child of node.chi) {
|
|
3248
|
+
yield* doWalk(child, node, (root ?? node));
|
|
2754
3249
|
}
|
|
2755
|
-
optimized.push(item);
|
|
2756
|
-
}
|
|
2757
|
-
if (optimized.at(-1) == ' ') {
|
|
2758
|
-
optimized.pop();
|
|
2759
3250
|
}
|
|
2760
|
-
let reducible = optimized.length == 1;
|
|
2761
|
-
if (optimized.length == 0) {
|
|
2762
|
-
return { match: false, optimized, selector, reducible };
|
|
2763
|
-
}
|
|
2764
|
-
return {
|
|
2765
|
-
match: true,
|
|
2766
|
-
optimized,
|
|
2767
|
-
selector: selector.reduce((acc, curr) => {
|
|
2768
|
-
const slice = curr.slice(optimized.length);
|
|
2769
|
-
// @ts-ignore
|
|
2770
|
-
if (slice.length > 0 && slice[0] == ' ') {
|
|
2771
|
-
slice.shift();
|
|
2772
|
-
}
|
|
2773
|
-
if (slice.length == 0) {
|
|
2774
|
-
slice.push('&');
|
|
2775
|
-
}
|
|
2776
|
-
if (reducible) {
|
|
2777
|
-
const chr = slice[0].charAt(0);
|
|
2778
|
-
// @ts-ignore
|
|
2779
|
-
reducible = chr == '.' || chr == ':' || isIdentStart(chr.codePointAt(0));
|
|
2780
|
-
}
|
|
2781
|
-
acc.push(slice);
|
|
2782
|
-
return acc;
|
|
2783
|
-
}, []),
|
|
2784
|
-
reducible
|
|
2785
|
-
};
|
|
2786
|
-
}
|
|
2787
|
-
function reducer(acc, curr) {
|
|
2788
|
-
acc.push(curr.join(''));
|
|
2789
|
-
return acc;
|
|
2790
3251
|
}
|
|
2791
3252
|
|
|
2792
|
-
|
|
2793
|
-
const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
2794
|
-
async function parse$1(iterator, opt = {}) {
|
|
2795
|
-
const errors = [];
|
|
2796
|
-
const options = {
|
|
2797
|
-
src: '',
|
|
2798
|
-
sourcemap: false,
|
|
2799
|
-
compress: false,
|
|
2800
|
-
nestingRules: false,
|
|
2801
|
-
resolveImport: false,
|
|
2802
|
-
resolveUrls: false,
|
|
2803
|
-
removeEmpty: true,
|
|
2804
|
-
...opt
|
|
2805
|
-
};
|
|
2806
|
-
if (options.resolveImport) {
|
|
2807
|
-
options.resolveUrls = true;
|
|
2808
|
-
}
|
|
3253
|
+
function* tokenize(iterator) {
|
|
2809
3254
|
let ind = -1;
|
|
2810
3255
|
let lin = 1;
|
|
2811
3256
|
let col = 0;
|
|
2812
|
-
const tokens = [];
|
|
2813
|
-
const src = options.src;
|
|
2814
|
-
const stack = [];
|
|
2815
|
-
const ast = {
|
|
2816
|
-
typ: "StyleSheet",
|
|
2817
|
-
chi: []
|
|
2818
|
-
};
|
|
2819
3257
|
const position = {
|
|
2820
3258
|
ind: Math.max(ind, 0),
|
|
2821
3259
|
lin: lin,
|
|
@@ -2823,899 +3261,965 @@ async function parse$1(iterator, opt = {}) {
|
|
|
2823
3261
|
};
|
|
2824
3262
|
let value;
|
|
2825
3263
|
let buffer = '';
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
if (options.sourcemap) {
|
|
2831
|
-
ast.loc = {
|
|
2832
|
-
sta: {
|
|
2833
|
-
ind: ind,
|
|
2834
|
-
lin: lin,
|
|
2835
|
-
col: col
|
|
2836
|
-
},
|
|
2837
|
-
src: ''
|
|
2838
|
-
};
|
|
2839
|
-
}
|
|
2840
|
-
function getType(val) {
|
|
2841
|
-
if (val === '') {
|
|
2842
|
-
throw new Error('empty string?');
|
|
2843
|
-
}
|
|
2844
|
-
if (val == ':') {
|
|
2845
|
-
return { typ: 'Colon' };
|
|
2846
|
-
}
|
|
2847
|
-
if (val == ')') {
|
|
2848
|
-
return { typ: 'End-parens' };
|
|
2849
|
-
}
|
|
2850
|
-
if (val == '(') {
|
|
2851
|
-
return { typ: 'Start-parens' };
|
|
2852
|
-
}
|
|
2853
|
-
if (val == '=') {
|
|
2854
|
-
return { typ: 'Delim', val };
|
|
2855
|
-
}
|
|
2856
|
-
if (val == ';') {
|
|
2857
|
-
return { typ: 'Semi-colon' };
|
|
2858
|
-
}
|
|
2859
|
-
if (val == ',') {
|
|
2860
|
-
return { typ: 'Comma' };
|
|
2861
|
-
}
|
|
2862
|
-
if (val == '<') {
|
|
2863
|
-
return { typ: 'Lt' };
|
|
3264
|
+
function consumeWhiteSpace() {
|
|
3265
|
+
let count = 0;
|
|
3266
|
+
while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
|
|
3267
|
+
count++;
|
|
2864
3268
|
}
|
|
2865
|
-
|
|
2866
|
-
|
|
3269
|
+
next(count);
|
|
3270
|
+
return count;
|
|
3271
|
+
}
|
|
3272
|
+
function pushToken(token, hint) {
|
|
3273
|
+
const result = { token, hint, position: { ...position }, bytesIn: ind };
|
|
3274
|
+
position.ind = ind;
|
|
3275
|
+
position.lin = lin;
|
|
3276
|
+
position.col = col == 0 ? 1 : col;
|
|
3277
|
+
return result;
|
|
3278
|
+
}
|
|
3279
|
+
function* consumeString(quoteStr) {
|
|
3280
|
+
const quote = quoteStr;
|
|
3281
|
+
let value;
|
|
3282
|
+
let hasNewLine = false;
|
|
3283
|
+
if (buffer.length > 0) {
|
|
3284
|
+
yield pushToken(buffer);
|
|
3285
|
+
buffer = '';
|
|
2867
3286
|
}
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
3287
|
+
buffer += quoteStr;
|
|
3288
|
+
while (value = peek()) {
|
|
3289
|
+
if (ind >= iterator.length) {
|
|
3290
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
3291
|
+
break;
|
|
2873
3292
|
}
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
};
|
|
2892
|
-
}
|
|
2893
|
-
if (isNumber(val)) {
|
|
2894
|
-
return {
|
|
2895
|
-
typ: 'Number',
|
|
2896
|
-
val
|
|
2897
|
-
};
|
|
2898
|
-
}
|
|
2899
|
-
if (isDimension(val)) {
|
|
2900
|
-
return parseDimension(val);
|
|
2901
|
-
}
|
|
2902
|
-
if (isPercentage(val)) {
|
|
2903
|
-
return {
|
|
2904
|
-
typ: 'Perc',
|
|
2905
|
-
val: val.slice(0, -1)
|
|
2906
|
-
};
|
|
2907
|
-
}
|
|
2908
|
-
if (val == 'currentColor') {
|
|
2909
|
-
return {
|
|
2910
|
-
typ: 'Color',
|
|
2911
|
-
val,
|
|
2912
|
-
kin: 'lit'
|
|
2913
|
-
};
|
|
2914
|
-
}
|
|
2915
|
-
if (isIdent(val)) {
|
|
2916
|
-
return {
|
|
2917
|
-
typ: 'Iden',
|
|
2918
|
-
val
|
|
2919
|
-
};
|
|
2920
|
-
}
|
|
2921
|
-
if (val.charAt(0) == '#' && isHash(val)) {
|
|
2922
|
-
return {
|
|
2923
|
-
typ: 'Hash',
|
|
2924
|
-
val
|
|
2925
|
-
};
|
|
2926
|
-
}
|
|
2927
|
-
if ('"\''.includes(val.charAt(0))) {
|
|
2928
|
-
return {
|
|
2929
|
-
typ: 'Unclosed-string',
|
|
2930
|
-
val
|
|
2931
|
-
};
|
|
2932
|
-
}
|
|
2933
|
-
return {
|
|
2934
|
-
typ: 'Literal',
|
|
2935
|
-
val
|
|
2936
|
-
};
|
|
2937
|
-
}
|
|
2938
|
-
// consume and throw away
|
|
2939
|
-
function consume(open, close) {
|
|
2940
|
-
let count = 1;
|
|
2941
|
-
let chr;
|
|
2942
|
-
while (true) {
|
|
2943
|
-
chr = next();
|
|
2944
|
-
if (chr == '\\') {
|
|
2945
|
-
if (peek() === '') {
|
|
3293
|
+
if (value == '\\') {
|
|
3294
|
+
const sequence = peek(6);
|
|
3295
|
+
let escapeSequence = '';
|
|
3296
|
+
let codepoint;
|
|
3297
|
+
let i;
|
|
3298
|
+
for (i = 1; i < sequence.length; i++) {
|
|
3299
|
+
codepoint = sequence.charCodeAt(i);
|
|
3300
|
+
if (codepoint == 0x20 ||
|
|
3301
|
+
(codepoint >= 0x61 && codepoint <= 0x66) ||
|
|
3302
|
+
(codepoint >= 0x41 && codepoint <= 0x46) ||
|
|
3303
|
+
(codepoint >= 0x30 && codepoint <= 0x39)) {
|
|
3304
|
+
escapeSequence += sequence[i];
|
|
3305
|
+
if (codepoint == 0x20) {
|
|
3306
|
+
break;
|
|
3307
|
+
}
|
|
3308
|
+
continue;
|
|
3309
|
+
}
|
|
2946
3310
|
break;
|
|
2947
3311
|
}
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
3312
|
+
// not hex or new line
|
|
3313
|
+
// @ts-ignore
|
|
3314
|
+
if (i == 1 && !isNewLine(codepoint)) {
|
|
3315
|
+
buffer += sequence[i];
|
|
3316
|
+
next(2);
|
|
3317
|
+
continue;
|
|
3318
|
+
}
|
|
3319
|
+
if (escapeSequence.trimEnd().length > 0) {
|
|
3320
|
+
const codepoint = Number(`0x${escapeSequence.trimEnd()}`);
|
|
3321
|
+
if (codepoint == 0 ||
|
|
3322
|
+
// leading surrogate
|
|
3323
|
+
(0xD800 <= codepoint && codepoint <= 0xDBFF) ||
|
|
3324
|
+
// trailing surrogate
|
|
3325
|
+
(0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
|
|
3326
|
+
buffer += String.fromCodePoint(0xFFFD);
|
|
2956
3327
|
}
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
break;
|
|
3328
|
+
else {
|
|
3329
|
+
buffer += String.fromCodePoint(codepoint);
|
|
2960
3330
|
}
|
|
3331
|
+
next(escapeSequence.length + 1);
|
|
3332
|
+
continue;
|
|
2961
3333
|
}
|
|
3334
|
+
// buffer += value;
|
|
3335
|
+
if (ind >= iterator.length) {
|
|
3336
|
+
// drop '\\' at the end
|
|
3337
|
+
yield pushToken(buffer);
|
|
3338
|
+
break;
|
|
3339
|
+
}
|
|
3340
|
+
buffer += next(2);
|
|
3341
|
+
continue;
|
|
2962
3342
|
}
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
if (chr === '' || count == 0) {
|
|
3343
|
+
if (value == quote) {
|
|
3344
|
+
buffer += value;
|
|
3345
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
|
|
3346
|
+
next();
|
|
3347
|
+
// i += value.length;
|
|
3348
|
+
buffer = '';
|
|
2970
3349
|
break;
|
|
2971
3350
|
}
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
async function parseNode(tokens) {
|
|
2975
|
-
let i;
|
|
2976
|
-
let loc;
|
|
2977
|
-
for (i = 0; i < tokens.length; i++) {
|
|
2978
|
-
if (tokens[i].typ == 'Comment') {
|
|
2979
|
-
// @ts-ignore
|
|
2980
|
-
context.chi.push(tokens[i]);
|
|
2981
|
-
const position = map.get(tokens[i]);
|
|
2982
|
-
loc = {
|
|
2983
|
-
sta: position,
|
|
2984
|
-
src
|
|
2985
|
-
};
|
|
2986
|
-
if (options.sourcemap) {
|
|
2987
|
-
tokens[i].loc = loc;
|
|
2988
|
-
}
|
|
3351
|
+
if (isNewLine(value.charCodeAt(0))) {
|
|
3352
|
+
hasNewLine = true;
|
|
2989
3353
|
}
|
|
2990
|
-
|
|
3354
|
+
if (hasNewLine && value == ';') {
|
|
3355
|
+
yield pushToken(buffer, 'Bad-string');
|
|
3356
|
+
buffer = '';
|
|
2991
3357
|
break;
|
|
2992
3358
|
}
|
|
3359
|
+
buffer += value;
|
|
3360
|
+
// i += value.length;
|
|
3361
|
+
next();
|
|
2993
3362
|
}
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
let delim = tokens.at(-1);
|
|
2999
|
-
if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
|
|
3000
|
-
tokens.pop();
|
|
3363
|
+
}
|
|
3364
|
+
function peek(count = 1) {
|
|
3365
|
+
if (count == 1) {
|
|
3366
|
+
return iterator.charAt(ind + 1);
|
|
3001
3367
|
}
|
|
3002
|
-
|
|
3003
|
-
|
|
3368
|
+
return iterator.slice(ind + 1, ind + count + 1);
|
|
3369
|
+
}
|
|
3370
|
+
function prev(count = 1) {
|
|
3371
|
+
if (count == 1) {
|
|
3372
|
+
return ind == 0 ? '' : iterator.charAt(ind - 1);
|
|
3004
3373
|
}
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3374
|
+
return iterator.slice(ind - 1 - count, ind - 1);
|
|
3375
|
+
}
|
|
3376
|
+
function next(count = 1) {
|
|
3377
|
+
let char = '';
|
|
3378
|
+
while (count-- > 0 && ind < iterator.length) {
|
|
3379
|
+
const codepoint = iterator.charCodeAt(++ind);
|
|
3380
|
+
if (isNaN(codepoint)) {
|
|
3381
|
+
return char;
|
|
3382
|
+
}
|
|
3383
|
+
char += iterator.charAt(ind);
|
|
3384
|
+
if (isNewLine(codepoint)) {
|
|
3385
|
+
lin++;
|
|
3386
|
+
col = 0;
|
|
3387
|
+
}
|
|
3388
|
+
else {
|
|
3389
|
+
col++;
|
|
3390
|
+
}
|
|
3008
3391
|
}
|
|
3009
|
-
|
|
3010
|
-
|
|
3392
|
+
return char;
|
|
3393
|
+
}
|
|
3394
|
+
while (value = next()) {
|
|
3395
|
+
if (ind >= iterator.length) {
|
|
3396
|
+
if (buffer.length > 0) {
|
|
3397
|
+
yield pushToken(buffer);
|
|
3398
|
+
buffer = '';
|
|
3399
|
+
}
|
|
3400
|
+
break;
|
|
3011
3401
|
}
|
|
3012
|
-
if (
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
errors.push({ action: 'drop', message: 'invalid @charset', location: { src, ...position } });
|
|
3017
|
-
return null;
|
|
3402
|
+
if (isWhiteSpace(value.charCodeAt(0))) {
|
|
3403
|
+
if (buffer.length > 0) {
|
|
3404
|
+
yield pushToken(buffer);
|
|
3405
|
+
buffer = '';
|
|
3018
3406
|
}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3407
|
+
while (value = next()) {
|
|
3408
|
+
if (ind >= iterator.length) {
|
|
3409
|
+
break;
|
|
3410
|
+
}
|
|
3411
|
+
if (!isWhiteSpace(value.charCodeAt(0))) {
|
|
3412
|
+
break;
|
|
3413
|
+
}
|
|
3022
3414
|
}
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3415
|
+
yield pushToken('', 'Whitespace');
|
|
3416
|
+
buffer = '';
|
|
3417
|
+
if (ind >= iterator.length) {
|
|
3418
|
+
break;
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
switch (value) {
|
|
3422
|
+
case '/':
|
|
3423
|
+
if (buffer.length > 0) {
|
|
3424
|
+
yield pushToken(buffer);
|
|
3425
|
+
buffer = '';
|
|
3426
|
+
if (peek() != '*') {
|
|
3427
|
+
yield pushToken(value);
|
|
3428
|
+
break;
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
buffer += value;
|
|
3432
|
+
if (peek() == '*') {
|
|
3433
|
+
buffer += '*';
|
|
3434
|
+
// i++;
|
|
3435
|
+
next();
|
|
3436
|
+
while (value = next()) {
|
|
3437
|
+
if (ind >= iterator.length) {
|
|
3438
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
3439
|
+
break;
|
|
3440
|
+
}
|
|
3441
|
+
if (value == '\\') {
|
|
3442
|
+
buffer += value;
|
|
3443
|
+
value = next();
|
|
3444
|
+
if (ind >= iterator.length) {
|
|
3445
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
3446
|
+
break;
|
|
3447
|
+
}
|
|
3448
|
+
buffer += value;
|
|
3030
3449
|
continue;
|
|
3031
3450
|
}
|
|
3032
|
-
if (
|
|
3033
|
-
|
|
3034
|
-
|
|
3451
|
+
if (value == '*') {
|
|
3452
|
+
buffer += value;
|
|
3453
|
+
value = next();
|
|
3454
|
+
if (ind >= iterator.length) {
|
|
3455
|
+
yield pushToken(buffer, 'Bad-comment');
|
|
3456
|
+
break;
|
|
3457
|
+
}
|
|
3458
|
+
buffer += value;
|
|
3459
|
+
if (value == '/') {
|
|
3460
|
+
yield pushToken(buffer, 'Comment');
|
|
3461
|
+
buffer = '';
|
|
3462
|
+
break;
|
|
3463
|
+
}
|
|
3035
3464
|
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3039
|
-
return null;
|
|
3465
|
+
else {
|
|
3466
|
+
buffer += value;
|
|
3040
3467
|
}
|
|
3041
|
-
break;
|
|
3042
3468
|
}
|
|
3043
3469
|
}
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
// @ts-ignore
|
|
3050
|
-
if (tokens[0].typ == 'UrlFunc' && tokens[1]?.typ != 'Url-token' && tokens[1]?.typ != 'String') {
|
|
3051
|
-
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3052
|
-
return null;
|
|
3470
|
+
break;
|
|
3471
|
+
case '<':
|
|
3472
|
+
if (buffer.length > 0) {
|
|
3473
|
+
yield pushToken(buffer);
|
|
3474
|
+
buffer = '';
|
|
3053
3475
|
}
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
tokens.shift();
|
|
3059
|
-
// @ts-ignore
|
|
3060
|
-
tokens[0].typ = 'String';
|
|
3061
|
-
// @ts-ignore
|
|
3062
|
-
tokens[0].val = `"${tokens[0].val}"`;
|
|
3476
|
+
buffer += value;
|
|
3477
|
+
value = next();
|
|
3478
|
+
if (ind >= iterator.length) {
|
|
3479
|
+
break;
|
|
3063
3480
|
}
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
try {
|
|
3069
|
-
// @ts-ignore
|
|
3070
|
-
const root = await options.load(url, options.src).then((src) => {
|
|
3071
|
-
return parse$1(src, Object.assign({}, options, {
|
|
3072
|
-
compress: false,
|
|
3073
|
-
// @ts-ignore
|
|
3074
|
-
src: options.resolve(url, options.src).absolute
|
|
3075
|
-
}));
|
|
3076
|
-
});
|
|
3077
|
-
bytesIn += root.bytesIn;
|
|
3078
|
-
if (root.ast.chi.length > 0) {
|
|
3079
|
-
context.chi.push(...root.ast.chi);
|
|
3080
|
-
}
|
|
3081
|
-
if (root.errors.length > 0) {
|
|
3082
|
-
errors.push(...root.errors);
|
|
3083
|
-
}
|
|
3084
|
-
return null;
|
|
3481
|
+
if (peek(3) == '!--') {
|
|
3482
|
+
while (value = next()) {
|
|
3483
|
+
if (ind >= iterator.length) {
|
|
3484
|
+
break;
|
|
3085
3485
|
}
|
|
3086
|
-
|
|
3087
|
-
|
|
3486
|
+
buffer += value;
|
|
3487
|
+
if (value == '>' && prev(2) == '--') {
|
|
3488
|
+
yield pushToken(buffer, 'CDOCOMM');
|
|
3489
|
+
buffer = '';
|
|
3490
|
+
break;
|
|
3088
3491
|
}
|
|
3089
3492
|
}
|
|
3090
3493
|
}
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
// there must be a top level rule in the stack
|
|
3095
|
-
const raw = tokens.reduce((acc, curr, index, array) => {
|
|
3096
|
-
acc.push(renderToken(curr, { removeComments: true }));
|
|
3097
|
-
return acc;
|
|
3098
|
-
}, []);
|
|
3099
|
-
const node = {
|
|
3100
|
-
typ: 'AtRule',
|
|
3101
|
-
nam: renderToken(atRule, { removeComments: true }),
|
|
3102
|
-
val: raw.join('')
|
|
3103
|
-
};
|
|
3104
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable: false, value: raw });
|
|
3105
|
-
if (delim.typ == 'Block-start') {
|
|
3106
|
-
node.chi = [];
|
|
3107
|
-
}
|
|
3108
|
-
loc = {
|
|
3109
|
-
sta: position,
|
|
3110
|
-
src
|
|
3111
|
-
};
|
|
3112
|
-
if (options.sourcemap) {
|
|
3113
|
-
node.loc = loc;
|
|
3114
|
-
}
|
|
3115
|
-
// @ts-ignore
|
|
3116
|
-
context.chi.push(node);
|
|
3117
|
-
return delim.typ == 'Block-start' ? node : null;
|
|
3118
|
-
}
|
|
3119
|
-
else {
|
|
3120
|
-
// rule
|
|
3121
|
-
if (delim.typ == 'Block-start') {
|
|
3122
|
-
const position = map.get(tokens[0]);
|
|
3123
|
-
if (context.typ == 'Rule') {
|
|
3124
|
-
if (tokens[0]?.typ == 'Iden') {
|
|
3125
|
-
errors.push({ action: 'drop', message: 'invalid nesting rule', location: { src, ...position } });
|
|
3126
|
-
return null;
|
|
3127
|
-
}
|
|
3494
|
+
if (ind >= iterator.length) {
|
|
3495
|
+
yield pushToken(buffer, 'BADCDO');
|
|
3496
|
+
buffer = '';
|
|
3128
3497
|
}
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
return acc;
|
|
3139
|
-
}, [[]]).reduce((acc, curr) => {
|
|
3140
|
-
acc.set(curr.join(''), curr);
|
|
3141
|
-
return acc;
|
|
3142
|
-
}, uniq);
|
|
3143
|
-
const node = {
|
|
3144
|
-
typ: 'Rule',
|
|
3145
|
-
// @ts-ignore
|
|
3146
|
-
sel: [...uniq.keys()].join(','),
|
|
3147
|
-
chi: []
|
|
3148
|
-
};
|
|
3149
|
-
let raw = [...uniq.values()];
|
|
3150
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
3151
|
-
loc = {
|
|
3152
|
-
sta: position,
|
|
3153
|
-
src
|
|
3154
|
-
};
|
|
3155
|
-
if (options.sourcemap) {
|
|
3156
|
-
node.loc = loc;
|
|
3498
|
+
break;
|
|
3499
|
+
case '\\':
|
|
3500
|
+
value = next();
|
|
3501
|
+
// EOF
|
|
3502
|
+
if (ind + 1 >= iterator.length) {
|
|
3503
|
+
// end of stream ignore \\
|
|
3504
|
+
yield pushToken(buffer);
|
|
3505
|
+
buffer = '';
|
|
3506
|
+
break;
|
|
3157
3507
|
}
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
if (tokens[i].typ == 'Comment') {
|
|
3170
|
-
continue;
|
|
3171
|
-
}
|
|
3172
|
-
if (tokens[i].typ == 'Colon') {
|
|
3173
|
-
name = tokens.slice(0, i);
|
|
3174
|
-
value = parseTokens(tokens.slice(i + 1), {
|
|
3175
|
-
parseColor: true,
|
|
3176
|
-
src: options.src,
|
|
3177
|
-
resolveUrls: options.resolveUrls,
|
|
3178
|
-
resolve: options.resolve,
|
|
3179
|
-
cwd: options.cwd
|
|
3180
|
-
});
|
|
3181
|
-
}
|
|
3508
|
+
buffer += value;
|
|
3509
|
+
break;
|
|
3510
|
+
case '"':
|
|
3511
|
+
case "'":
|
|
3512
|
+
yield* consumeString(value);
|
|
3513
|
+
break;
|
|
3514
|
+
case '~':
|
|
3515
|
+
case '|':
|
|
3516
|
+
if (buffer.length > 0) {
|
|
3517
|
+
yield pushToken(buffer);
|
|
3518
|
+
buffer = '';
|
|
3182
3519
|
}
|
|
3183
|
-
|
|
3184
|
-
|
|
3520
|
+
buffer += value;
|
|
3521
|
+
value = next();
|
|
3522
|
+
if (ind >= iterator.length) {
|
|
3523
|
+
yield pushToken(buffer);
|
|
3524
|
+
buffer = '';
|
|
3525
|
+
break;
|
|
3185
3526
|
}
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
action: 'drop',
|
|
3192
|
-
message: 'invalid declaration',
|
|
3193
|
-
location: { src, ...position }
|
|
3194
|
-
});
|
|
3195
|
-
return null;
|
|
3196
|
-
}
|
|
3197
|
-
}
|
|
3527
|
+
if (value == '=') {
|
|
3528
|
+
buffer += value;
|
|
3529
|
+
yield pushToken(buffer, buffer[0] == '~' ? 'Includes' : 'Dash-matches');
|
|
3530
|
+
buffer = '';
|
|
3531
|
+
break;
|
|
3198
3532
|
}
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3533
|
+
yield pushToken(buffer);
|
|
3534
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
3535
|
+
value = next();
|
|
3202
3536
|
}
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3537
|
+
buffer = value;
|
|
3538
|
+
break;
|
|
3539
|
+
case '>':
|
|
3540
|
+
if (buffer !== '') {
|
|
3541
|
+
yield pushToken(buffer);
|
|
3542
|
+
buffer = '';
|
|
3206
3543
|
}
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3544
|
+
yield pushToken('', 'Gt');
|
|
3545
|
+
consumeWhiteSpace();
|
|
3546
|
+
break;
|
|
3547
|
+
case '.':
|
|
3548
|
+
const codepoint = peek().charCodeAt(0);
|
|
3549
|
+
if (!isDigit(codepoint) && buffer !== '') {
|
|
3550
|
+
yield pushToken(buffer);
|
|
3551
|
+
buffer = value;
|
|
3552
|
+
break;
|
|
3216
3553
|
}
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3554
|
+
buffer += value;
|
|
3555
|
+
break;
|
|
3556
|
+
case '+':
|
|
3557
|
+
case ':':
|
|
3558
|
+
case ',':
|
|
3559
|
+
case '=':
|
|
3560
|
+
if (buffer.length > 0) {
|
|
3561
|
+
yield pushToken(buffer);
|
|
3562
|
+
buffer = '';
|
|
3563
|
+
}
|
|
3564
|
+
if (value == ':' && ':' == peek()) {
|
|
3565
|
+
buffer += value + next();
|
|
3566
|
+
break;
|
|
3567
|
+
}
|
|
3568
|
+
yield pushToken(value);
|
|
3569
|
+
buffer = '';
|
|
3570
|
+
if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
|
|
3571
|
+
yield pushToken(next());
|
|
3572
|
+
}
|
|
3573
|
+
while (isWhiteSpace(peek().charCodeAt(0))) {
|
|
3574
|
+
next();
|
|
3220
3575
|
}
|
|
3221
|
-
// @ts-ignore
|
|
3222
|
-
context.chi.push(node);
|
|
3223
|
-
return null;
|
|
3224
|
-
}
|
|
3225
|
-
}
|
|
3226
|
-
}
|
|
3227
|
-
function peek(count = 1) {
|
|
3228
|
-
if (count == 1) {
|
|
3229
|
-
return iterator.charAt(ind + 1);
|
|
3230
|
-
}
|
|
3231
|
-
return iterator.slice(ind + 1, ind + count + 1);
|
|
3232
|
-
}
|
|
3233
|
-
function prev(count = 1) {
|
|
3234
|
-
if (count == 1) {
|
|
3235
|
-
return ind == 0 ? '' : iterator.charAt(ind - 1);
|
|
3236
|
-
}
|
|
3237
|
-
return iterator.slice(ind - 1 - count, ind - 1);
|
|
3238
|
-
}
|
|
3239
|
-
function next(count = 1) {
|
|
3240
|
-
let char = '';
|
|
3241
|
-
while (count-- > 0 && ind < total) {
|
|
3242
|
-
const codepoint = iterator.charCodeAt(++ind);
|
|
3243
|
-
if (isNaN(codepoint)) {
|
|
3244
|
-
return char;
|
|
3245
|
-
}
|
|
3246
|
-
char += iterator.charAt(ind);
|
|
3247
|
-
if (isNewLine(codepoint)) {
|
|
3248
|
-
lin++;
|
|
3249
|
-
col = 0;
|
|
3250
|
-
}
|
|
3251
|
-
else {
|
|
3252
|
-
col++;
|
|
3253
|
-
}
|
|
3254
|
-
}
|
|
3255
|
-
return char;
|
|
3256
|
-
}
|
|
3257
|
-
function pushToken(token) {
|
|
3258
|
-
tokens.push(token);
|
|
3259
|
-
map.set(token, { ...position });
|
|
3260
|
-
position.ind = ind;
|
|
3261
|
-
position.lin = lin;
|
|
3262
|
-
position.col = col == 0 ? 1 : col;
|
|
3263
|
-
// }
|
|
3264
|
-
}
|
|
3265
|
-
function consumeWhiteSpace() {
|
|
3266
|
-
let count = 0;
|
|
3267
|
-
while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
|
|
3268
|
-
count++;
|
|
3269
|
-
}
|
|
3270
|
-
next(count);
|
|
3271
|
-
return count;
|
|
3272
|
-
}
|
|
3273
|
-
function consumeString(quoteStr) {
|
|
3274
|
-
const quote = quoteStr;
|
|
3275
|
-
let value;
|
|
3276
|
-
let hasNewLine = false;
|
|
3277
|
-
if (buffer.length > 0) {
|
|
3278
|
-
pushToken(getType(buffer));
|
|
3279
|
-
buffer = '';
|
|
3280
|
-
}
|
|
3281
|
-
buffer += quoteStr;
|
|
3282
|
-
while (ind < total) {
|
|
3283
|
-
value = peek();
|
|
3284
|
-
if (ind >= total) {
|
|
3285
|
-
pushToken({ typ: hasNewLine ? 'Bad-string' : 'Unclosed-string', val: buffer });
|
|
3286
3576
|
break;
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
(codepoint >= 0x41 && codepoint <= 0x46) ||
|
|
3298
|
-
(codepoint >= 0x30 && codepoint <= 0x39)) {
|
|
3299
|
-
escapeSequence += sequence[i];
|
|
3300
|
-
if (codepoint == 0x20) {
|
|
3301
|
-
break;
|
|
3302
|
-
}
|
|
3303
|
-
continue;
|
|
3304
|
-
}
|
|
3577
|
+
case ')':
|
|
3578
|
+
if (buffer.length > 0) {
|
|
3579
|
+
yield pushToken(buffer);
|
|
3580
|
+
buffer = '';
|
|
3581
|
+
}
|
|
3582
|
+
yield pushToken('', 'End-parens');
|
|
3583
|
+
break;
|
|
3584
|
+
case '(':
|
|
3585
|
+
if (buffer.length == 0) {
|
|
3586
|
+
yield pushToken('', 'Start-parens');
|
|
3305
3587
|
break;
|
|
3306
3588
|
}
|
|
3307
|
-
|
|
3589
|
+
buffer += value;
|
|
3308
3590
|
// @ts-ignore
|
|
3309
|
-
if (
|
|
3310
|
-
buffer
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3591
|
+
if (buffer == 'url(') {
|
|
3592
|
+
yield pushToken(buffer);
|
|
3593
|
+
buffer = '';
|
|
3594
|
+
// consume either string or url token
|
|
3595
|
+
let whitespace = '';
|
|
3596
|
+
value = peek();
|
|
3597
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
3598
|
+
whitespace += value;
|
|
3599
|
+
}
|
|
3600
|
+
if (whitespace.length > 0) {
|
|
3601
|
+
next(whitespace.length);
|
|
3602
|
+
}
|
|
3603
|
+
value = peek();
|
|
3604
|
+
if (value == '"' || value == "'") {
|
|
3605
|
+
yield* consumeString(next());
|
|
3606
|
+
break;
|
|
3322
3607
|
}
|
|
3323
3608
|
else {
|
|
3324
|
-
buffer
|
|
3609
|
+
buffer = '';
|
|
3610
|
+
do {
|
|
3611
|
+
let cp = value.charCodeAt(0);
|
|
3612
|
+
// EOF -
|
|
3613
|
+
if (cp == null) {
|
|
3614
|
+
yield pushToken('', 'Bad-url-token');
|
|
3615
|
+
break;
|
|
3616
|
+
}
|
|
3617
|
+
// ')'
|
|
3618
|
+
if (cp == 0x29 || cp == null) {
|
|
3619
|
+
if (buffer.length == 0) {
|
|
3620
|
+
yield pushToken(buffer, 'Bad-url-token');
|
|
3621
|
+
}
|
|
3622
|
+
else {
|
|
3623
|
+
yield pushToken(buffer, 'Url-token');
|
|
3624
|
+
}
|
|
3625
|
+
if (cp != null) {
|
|
3626
|
+
yield pushToken(next());
|
|
3627
|
+
}
|
|
3628
|
+
break;
|
|
3629
|
+
}
|
|
3630
|
+
if (isWhiteSpace(cp)) {
|
|
3631
|
+
whitespace = next();
|
|
3632
|
+
while (true) {
|
|
3633
|
+
value = peek();
|
|
3634
|
+
cp = value.charCodeAt(0);
|
|
3635
|
+
if (isWhiteSpace(cp)) {
|
|
3636
|
+
whitespace += value;
|
|
3637
|
+
continue;
|
|
3638
|
+
}
|
|
3639
|
+
break;
|
|
3640
|
+
}
|
|
3641
|
+
if (cp == null || cp == 0x29) {
|
|
3642
|
+
continue;
|
|
3643
|
+
}
|
|
3644
|
+
// bad url token
|
|
3645
|
+
buffer += next(whitespace.length);
|
|
3646
|
+
do {
|
|
3647
|
+
value = peek();
|
|
3648
|
+
cp = value.charCodeAt(0);
|
|
3649
|
+
if (cp == null || cp == 0x29) {
|
|
3650
|
+
break;
|
|
3651
|
+
}
|
|
3652
|
+
buffer += next();
|
|
3653
|
+
} while (true);
|
|
3654
|
+
yield pushToken(buffer, 'Bad-url-token');
|
|
3655
|
+
continue;
|
|
3656
|
+
}
|
|
3657
|
+
buffer += next();
|
|
3658
|
+
value = peek();
|
|
3659
|
+
} while (true);
|
|
3660
|
+
buffer = '';
|
|
3325
3661
|
}
|
|
3326
|
-
|
|
3327
|
-
continue;
|
|
3662
|
+
break;
|
|
3328
3663
|
}
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3664
|
+
yield pushToken(buffer);
|
|
3665
|
+
buffer = '';
|
|
3666
|
+
break;
|
|
3667
|
+
case '[':
|
|
3668
|
+
case ']':
|
|
3669
|
+
case '{':
|
|
3670
|
+
case '}':
|
|
3671
|
+
case ';':
|
|
3672
|
+
if (buffer.length > 0) {
|
|
3673
|
+
yield pushToken(buffer);
|
|
3674
|
+
buffer = '';
|
|
3675
|
+
}
|
|
3676
|
+
yield pushToken(value);
|
|
3677
|
+
break;
|
|
3678
|
+
case '!':
|
|
3679
|
+
if (buffer.length > 0) {
|
|
3680
|
+
yield pushToken(buffer);
|
|
3681
|
+
buffer = '';
|
|
3682
|
+
}
|
|
3683
|
+
const important = peek(9);
|
|
3684
|
+
if (important == 'important') {
|
|
3685
|
+
yield pushToken('', 'Important');
|
|
3686
|
+
next(9);
|
|
3687
|
+
buffer = '';
|
|
3333
3688
|
break;
|
|
3334
3689
|
}
|
|
3335
|
-
buffer
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
if (value == quote) {
|
|
3690
|
+
buffer = '!';
|
|
3691
|
+
break;
|
|
3692
|
+
default:
|
|
3339
3693
|
buffer += value;
|
|
3340
|
-
pushToken({ typ: hasNewLine ? 'Bad-string' : 'String', val: buffer });
|
|
3341
|
-
next();
|
|
3342
|
-
// i += value.length;
|
|
3343
|
-
buffer = '';
|
|
3344
3694
|
break;
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
if (buffer.length > 0) {
|
|
3698
|
+
yield pushToken(buffer);
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3702
|
+
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
3703
|
+
const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
3704
|
+
/**
|
|
3705
|
+
*
|
|
3706
|
+
* @param iterator
|
|
3707
|
+
* @param opt
|
|
3708
|
+
*/
|
|
3709
|
+
async function parse$1(iterator, opt = {}) {
|
|
3710
|
+
const errors = [];
|
|
3711
|
+
const options = {
|
|
3712
|
+
src: '',
|
|
3713
|
+
sourcemap: false,
|
|
3714
|
+
minify: true,
|
|
3715
|
+
nestingRules: false,
|
|
3716
|
+
resolveImport: false,
|
|
3717
|
+
resolveUrls: false,
|
|
3718
|
+
removeEmpty: true,
|
|
3719
|
+
...opt
|
|
3720
|
+
};
|
|
3721
|
+
if (options.resolveImport) {
|
|
3722
|
+
options.resolveUrls = true;
|
|
3723
|
+
}
|
|
3724
|
+
const src = options.src;
|
|
3725
|
+
const stack = [];
|
|
3726
|
+
const ast = {
|
|
3727
|
+
typ: "StyleSheet",
|
|
3728
|
+
chi: []
|
|
3729
|
+
};
|
|
3730
|
+
let tokens = [];
|
|
3731
|
+
let map = new Map;
|
|
3732
|
+
let bytesIn = 0;
|
|
3733
|
+
let context = ast;
|
|
3734
|
+
if (options.sourcemap) {
|
|
3735
|
+
ast.loc = {
|
|
3736
|
+
sta: {
|
|
3737
|
+
ind: 0,
|
|
3738
|
+
lin: 1,
|
|
3739
|
+
col: 1
|
|
3740
|
+
},
|
|
3741
|
+
src: ''
|
|
3742
|
+
};
|
|
3743
|
+
}
|
|
3744
|
+
async function parseNode(results) {
|
|
3745
|
+
let tokens = results.map(mapToken);
|
|
3746
|
+
let i;
|
|
3747
|
+
let loc;
|
|
3748
|
+
for (i = 0; i < tokens.length; i++) {
|
|
3749
|
+
if (tokens[i].typ == 'Comment') {
|
|
3750
|
+
// @ts-ignore
|
|
3751
|
+
context.chi.push(tokens[i]);
|
|
3752
|
+
const position = map.get(tokens[i]);
|
|
3753
|
+
loc = {
|
|
3754
|
+
sta: position,
|
|
3755
|
+
src
|
|
3756
|
+
};
|
|
3757
|
+
if (options.sourcemap) {
|
|
3758
|
+
tokens[i].loc = loc;
|
|
3759
|
+
}
|
|
3345
3760
|
}
|
|
3346
|
-
if (
|
|
3347
|
-
hasNewLine = true;
|
|
3348
|
-
}
|
|
3349
|
-
if (hasNewLine && value == ';') {
|
|
3350
|
-
pushToken({ typ: 'Bad-string', val: buffer });
|
|
3351
|
-
buffer = '';
|
|
3761
|
+
else if (tokens[i].typ != 'Whitespace') {
|
|
3352
3762
|
break;
|
|
3353
3763
|
}
|
|
3354
|
-
buffer += value;
|
|
3355
|
-
// i += value.length;
|
|
3356
|
-
next();
|
|
3357
3764
|
}
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
if (ind >= total) {
|
|
3362
|
-
if (buffer.length > 0) {
|
|
3363
|
-
pushToken(getType(buffer));
|
|
3364
|
-
buffer = '';
|
|
3365
|
-
}
|
|
3366
|
-
break;
|
|
3765
|
+
tokens = tokens.slice(i);
|
|
3766
|
+
if (tokens.length == 0) {
|
|
3767
|
+
return null;
|
|
3367
3768
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3769
|
+
let delim = tokens.at(-1);
|
|
3770
|
+
if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
|
|
3771
|
+
tokens.pop();
|
|
3772
|
+
}
|
|
3773
|
+
else {
|
|
3774
|
+
delim = { typ: 'Semi-colon' };
|
|
3775
|
+
}
|
|
3776
|
+
// @ts-ignore
|
|
3777
|
+
while (['Whitespace', 'Bad-string', 'Bad-comment'].includes(tokens.at(-1)?.typ)) {
|
|
3778
|
+
tokens.pop();
|
|
3779
|
+
}
|
|
3780
|
+
if (tokens.length == 0) {
|
|
3781
|
+
return null;
|
|
3782
|
+
}
|
|
3783
|
+
if (tokens[0]?.typ == 'At-rule') {
|
|
3784
|
+
const atRule = tokens.shift();
|
|
3785
|
+
const position = map.get(atRule);
|
|
3786
|
+
if (atRule.val == 'charset' && position.ind > 0) {
|
|
3787
|
+
errors.push({ action: 'drop', message: 'invalid @charset', location: { src, ...position } });
|
|
3788
|
+
return null;
|
|
3381
3789
|
}
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
break;
|
|
3790
|
+
// @ts-ignore
|
|
3791
|
+
while (['Whitespace'].includes(tokens[0]?.typ)) {
|
|
3792
|
+
tokens.shift();
|
|
3386
3793
|
}
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
pushToken(getType(value));
|
|
3395
|
-
break;
|
|
3396
|
-
}
|
|
3397
|
-
}
|
|
3398
|
-
buffer += value;
|
|
3399
|
-
if (peek() == '*') {
|
|
3400
|
-
buffer += '*';
|
|
3401
|
-
// i++;
|
|
3402
|
-
next();
|
|
3403
|
-
while (ind < total) {
|
|
3404
|
-
value = next();
|
|
3405
|
-
if (ind >= total) {
|
|
3406
|
-
pushToken({
|
|
3407
|
-
typ: 'Bad-comment', val: buffer
|
|
3408
|
-
});
|
|
3409
|
-
break;
|
|
3410
|
-
}
|
|
3411
|
-
if (value == '\\') {
|
|
3412
|
-
buffer += value;
|
|
3413
|
-
value = next();
|
|
3414
|
-
if (ind >= total) {
|
|
3415
|
-
pushToken({
|
|
3416
|
-
typ: 'Bad-comment',
|
|
3417
|
-
val: buffer
|
|
3418
|
-
});
|
|
3419
|
-
break;
|
|
3420
|
-
}
|
|
3421
|
-
buffer += value;
|
|
3794
|
+
if (atRule.val == 'import') {
|
|
3795
|
+
// only @charset and @layer are accepted before @import
|
|
3796
|
+
if (context.chi.length > 0) {
|
|
3797
|
+
let i = context.chi.length;
|
|
3798
|
+
while (i--) {
|
|
3799
|
+
const type = context.chi[i].typ;
|
|
3800
|
+
if (type == 'Comment') {
|
|
3422
3801
|
continue;
|
|
3423
3802
|
}
|
|
3424
|
-
if (
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
if (ind >= total) {
|
|
3428
|
-
pushToken({
|
|
3429
|
-
typ: 'Bad-comment', val: buffer
|
|
3430
|
-
});
|
|
3431
|
-
break;
|
|
3432
|
-
}
|
|
3433
|
-
buffer += value;
|
|
3434
|
-
if (value == '/') {
|
|
3435
|
-
pushToken({ typ: 'Comment', val: buffer });
|
|
3436
|
-
buffer = '';
|
|
3437
|
-
break;
|
|
3438
|
-
}
|
|
3803
|
+
if (type != 'AtRule') {
|
|
3804
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3805
|
+
return null;
|
|
3439
3806
|
}
|
|
3440
|
-
|
|
3441
|
-
|
|
3807
|
+
const name = context.chi[i].nam;
|
|
3808
|
+
if (name != 'charset' && name != 'import' && name != 'layer') {
|
|
3809
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3810
|
+
return null;
|
|
3442
3811
|
}
|
|
3812
|
+
break;
|
|
3443
3813
|
}
|
|
3444
3814
|
}
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
buffer = '';
|
|
3815
|
+
// @ts-ignore
|
|
3816
|
+
if (tokens[0]?.typ != 'String' && tokens[0]?.typ != 'UrlFunc') {
|
|
3817
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3818
|
+
return null;
|
|
3450
3819
|
}
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3820
|
+
// @ts-ignore
|
|
3821
|
+
if (tokens[0].typ == 'UrlFunc' && tokens[1]?.typ != 'Url-token' && tokens[1]?.typ != 'String') {
|
|
3822
|
+
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
|
|
3823
|
+
return null;
|
|
3455
3824
|
}
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3825
|
+
}
|
|
3826
|
+
if (atRule.val == 'import') {
|
|
3827
|
+
// @ts-ignore
|
|
3828
|
+
if (tokens[0].typ == 'UrlFunc' && tokens[1].typ == 'Url-token') {
|
|
3829
|
+
tokens.shift();
|
|
3830
|
+
// @ts-ignore
|
|
3831
|
+
tokens[0].typ = 'String';
|
|
3832
|
+
// @ts-ignore
|
|
3833
|
+
tokens[0].val = `"${tokens[0].val}"`;
|
|
3834
|
+
}
|
|
3835
|
+
// @ts-ignore
|
|
3836
|
+
if (tokens[0].typ == 'String') {
|
|
3837
|
+
if (options.resolveImport) {
|
|
3838
|
+
const url = tokens[0].val.slice(1, -1);
|
|
3839
|
+
try {
|
|
3840
|
+
// @ts-ignore
|
|
3841
|
+
const root = await options.load(url, options.src).then((src) => {
|
|
3842
|
+
return parse$1(src, Object.assign({}, options, {
|
|
3843
|
+
minify: false,
|
|
3844
|
+
// @ts-ignore
|
|
3845
|
+
src: options.resolve(url, options.src).absolute
|
|
3846
|
+
}));
|
|
3467
3847
|
});
|
|
3468
|
-
|
|
3469
|
-
|
|
3848
|
+
bytesIn += root.bytesIn;
|
|
3849
|
+
if (root.ast.chi.length > 0) {
|
|
3850
|
+
context.chi.push(...root.ast.chi);
|
|
3851
|
+
}
|
|
3852
|
+
if (root.errors.length > 0) {
|
|
3853
|
+
errors.push(...root.errors);
|
|
3854
|
+
}
|
|
3855
|
+
return null;
|
|
3856
|
+
}
|
|
3857
|
+
catch (error) {
|
|
3858
|
+
console.error(error);
|
|
3470
3859
|
}
|
|
3471
3860
|
}
|
|
3472
3861
|
}
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3862
|
+
}
|
|
3863
|
+
// https://www.w3.org/TR/css-nesting-1/#conditionals
|
|
3864
|
+
// allowed nesting at-rules
|
|
3865
|
+
// there must be a top level rule in the stack
|
|
3866
|
+
const raw = tokens.reduce((acc, curr) => {
|
|
3867
|
+
acc.push(renderToken(curr, { removeComments: true }));
|
|
3868
|
+
return acc;
|
|
3869
|
+
}, []);
|
|
3870
|
+
const node = {
|
|
3871
|
+
typ: 'AtRule',
|
|
3872
|
+
nam: renderToken(atRule, { removeComments: true }),
|
|
3873
|
+
val: raw.join('')
|
|
3874
|
+
};
|
|
3875
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: false, value: raw });
|
|
3876
|
+
if (delim.typ == 'Block-start') {
|
|
3877
|
+
node.chi = [];
|
|
3878
|
+
}
|
|
3879
|
+
loc = {
|
|
3880
|
+
sta: position,
|
|
3881
|
+
src
|
|
3882
|
+
};
|
|
3883
|
+
if (options.sourcemap) {
|
|
3884
|
+
node.loc = loc;
|
|
3885
|
+
}
|
|
3886
|
+
// @ts-ignore
|
|
3887
|
+
context.chi.push(node);
|
|
3888
|
+
return delim.typ == 'Block-start' ? node : null;
|
|
3889
|
+
}
|
|
3890
|
+
else {
|
|
3891
|
+
// rule
|
|
3892
|
+
if (delim.typ == 'Block-start') {
|
|
3893
|
+
const position = map.get(tokens[0]);
|
|
3894
|
+
// if (context.typ == 'Rule') {
|
|
3895
|
+
//
|
|
3896
|
+
// if (tokens[0]?.typ == 'Iden') {
|
|
3897
|
+
// errors.push({action: 'drop', message: 'invalid nesting rule', location: {src, ...position}});
|
|
3898
|
+
// return null;
|
|
3899
|
+
// }
|
|
3900
|
+
// }
|
|
3901
|
+
const uniq = new Map;
|
|
3902
|
+
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
3903
|
+
if (curr.typ == 'Whitespace') {
|
|
3904
|
+
if (array[index - 1]?.typ == 'Gt' ||
|
|
3905
|
+
array[index + 1]?.typ == 'Gt' ||
|
|
3906
|
+
combinators.includes(array[index - 1]?.val) ||
|
|
3907
|
+
combinators.includes(array[index + 1]?.val)) {
|
|
3908
|
+
return acc;
|
|
3909
|
+
}
|
|
3910
|
+
}
|
|
3911
|
+
let t = renderToken(curr, { minify: true });
|
|
3912
|
+
if (t == ',') {
|
|
3913
|
+
acc.push([]);
|
|
3914
|
+
}
|
|
3915
|
+
else {
|
|
3916
|
+
acc[acc.length - 1].push(t);
|
|
3917
|
+
}
|
|
3918
|
+
return acc;
|
|
3919
|
+
}, [[]]).reduce((acc, curr) => {
|
|
3920
|
+
acc.set(curr.join(''), curr);
|
|
3921
|
+
return acc;
|
|
3922
|
+
}, uniq);
|
|
3923
|
+
const node = {
|
|
3924
|
+
typ: 'Rule',
|
|
3925
|
+
// @ts-ignore
|
|
3926
|
+
sel: [...uniq.keys()].join(','),
|
|
3927
|
+
chi: []
|
|
3928
|
+
};
|
|
3929
|
+
let raw = [...uniq.values()];
|
|
3930
|
+
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
3931
|
+
loc = {
|
|
3932
|
+
sta: position,
|
|
3933
|
+
src
|
|
3934
|
+
};
|
|
3935
|
+
if (options.sourcemap) {
|
|
3936
|
+
node.loc = loc;
|
|
3544
3937
|
}
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3938
|
+
// @ts-ignore
|
|
3939
|
+
context.chi.push(node);
|
|
3940
|
+
return node;
|
|
3941
|
+
}
|
|
3942
|
+
else {
|
|
3943
|
+
// declaration
|
|
3944
|
+
// @ts-ignore
|
|
3945
|
+
let name = null;
|
|
3946
|
+
// @ts-ignore
|
|
3947
|
+
let value = null;
|
|
3948
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
3949
|
+
if (tokens[i].typ == 'Comment') {
|
|
3950
|
+
continue;
|
|
3951
|
+
}
|
|
3952
|
+
if (tokens[i].typ == 'Colon') {
|
|
3953
|
+
name = tokens.slice(0, i);
|
|
3954
|
+
value = parseTokens(tokens.slice(i + 1), {
|
|
3955
|
+
parseColor: true,
|
|
3956
|
+
src: options.src,
|
|
3957
|
+
resolveUrls: options.resolveUrls,
|
|
3958
|
+
resolve: options.resolve,
|
|
3959
|
+
cwd: options.cwd
|
|
3960
|
+
});
|
|
3961
|
+
}
|
|
3550
3962
|
}
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
case '(':
|
|
3554
|
-
if (buffer.length == 0) {
|
|
3555
|
-
pushToken({ typ: 'Start-parens' });
|
|
3963
|
+
if (name == null) {
|
|
3964
|
+
name = tokens;
|
|
3556
3965
|
}
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
whitespace += value;
|
|
3568
|
-
}
|
|
3569
|
-
if (whitespace.length > 0) {
|
|
3570
|
-
next(whitespace.length);
|
|
3571
|
-
}
|
|
3572
|
-
value = peek();
|
|
3573
|
-
if (value == '"' || value == "'") {
|
|
3574
|
-
consumeString(next());
|
|
3575
|
-
let token = tokens[tokens.length - 1];
|
|
3576
|
-
if (['String', 'Literal'].includes(token.typ) && urlTokenMatcher.test(token.val)) {
|
|
3577
|
-
if (token.val.slice(1, 6) != 'data:') {
|
|
3578
|
-
if (token.typ == 'String') {
|
|
3579
|
-
token.val = token.val.slice(1, -1);
|
|
3580
|
-
}
|
|
3581
|
-
// @ts-ignore
|
|
3582
|
-
token.typ = 'Url-token';
|
|
3583
|
-
}
|
|
3584
|
-
}
|
|
3585
|
-
break;
|
|
3586
|
-
}
|
|
3587
|
-
else {
|
|
3588
|
-
buffer = '';
|
|
3589
|
-
do {
|
|
3590
|
-
let cp = value.charCodeAt(0);
|
|
3591
|
-
// EOF -
|
|
3592
|
-
if (cp == null) {
|
|
3593
|
-
pushToken({ typ: 'Bad-url-token', val: buffer });
|
|
3594
|
-
break;
|
|
3595
|
-
}
|
|
3596
|
-
// ')'
|
|
3597
|
-
if (cp == 0x29 || cp == null) {
|
|
3598
|
-
if (buffer.length == 0) {
|
|
3599
|
-
pushToken({ typ: 'Bad-url-token', val: '' });
|
|
3600
|
-
}
|
|
3601
|
-
else {
|
|
3602
|
-
pushToken({ typ: 'Url-token', val: buffer });
|
|
3603
|
-
}
|
|
3604
|
-
if (cp != null) {
|
|
3605
|
-
pushToken(getType(next()));
|
|
3606
|
-
}
|
|
3607
|
-
break;
|
|
3608
|
-
}
|
|
3609
|
-
if (isWhiteSpace(cp)) {
|
|
3610
|
-
whitespace = next();
|
|
3611
|
-
while (true) {
|
|
3612
|
-
value = peek();
|
|
3613
|
-
cp = value.charCodeAt(0);
|
|
3614
|
-
if (isWhiteSpace(cp)) {
|
|
3615
|
-
whitespace += value;
|
|
3616
|
-
continue;
|
|
3617
|
-
}
|
|
3618
|
-
break;
|
|
3619
|
-
}
|
|
3620
|
-
if (cp == null || cp == 0x29) {
|
|
3621
|
-
continue;
|
|
3622
|
-
}
|
|
3623
|
-
// bad url token
|
|
3624
|
-
buffer += next(whitespace.length);
|
|
3625
|
-
do {
|
|
3626
|
-
value = peek();
|
|
3627
|
-
cp = value.charCodeAt(0);
|
|
3628
|
-
if (cp == null || cp == 0x29) {
|
|
3629
|
-
break;
|
|
3630
|
-
}
|
|
3631
|
-
buffer += next();
|
|
3632
|
-
} while (true);
|
|
3633
|
-
pushToken({ typ: 'Bad-url-token', val: buffer });
|
|
3634
|
-
continue;
|
|
3635
|
-
}
|
|
3636
|
-
buffer += next();
|
|
3637
|
-
value = peek();
|
|
3638
|
-
} while (true);
|
|
3639
|
-
buffer = '';
|
|
3966
|
+
const position = map.get(name[0]);
|
|
3967
|
+
if (name.length > 0) {
|
|
3968
|
+
for (let i = 1; i < name.length; i++) {
|
|
3969
|
+
if (name[i].typ != 'Whitespace' && name[i].typ != 'Comment') {
|
|
3970
|
+
errors.push({
|
|
3971
|
+
action: 'drop',
|
|
3972
|
+
message: 'invalid declaration',
|
|
3973
|
+
location: { src, ...position }
|
|
3974
|
+
});
|
|
3975
|
+
return null;
|
|
3640
3976
|
}
|
|
3641
3977
|
}
|
|
3642
3978
|
}
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
pushToken(getType(buffer));
|
|
3651
|
-
buffer = '';
|
|
3979
|
+
if (value == null) {
|
|
3980
|
+
errors.push({
|
|
3981
|
+
action: 'drop',
|
|
3982
|
+
message: 'invalid declaration',
|
|
3983
|
+
location: { src, ...position }
|
|
3984
|
+
});
|
|
3985
|
+
return null;
|
|
3652
3986
|
}
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
context = node;
|
|
3661
|
-
}
|
|
3662
|
-
else if (value == '{') {
|
|
3663
|
-
// node == null
|
|
3664
|
-
// consume and throw away until the closing '}' or EOF
|
|
3665
|
-
consume('{', '}');
|
|
3666
|
-
}
|
|
3667
|
-
tokens.length = 0;
|
|
3668
|
-
map.clear();
|
|
3987
|
+
if (value.length == 0) {
|
|
3988
|
+
errors.push({
|
|
3989
|
+
action: 'drop',
|
|
3990
|
+
message: 'invalid declaration',
|
|
3991
|
+
location: { src, ...position }
|
|
3992
|
+
});
|
|
3993
|
+
return null;
|
|
3669
3994
|
}
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
const previousNode = stack.pop();
|
|
3995
|
+
const node = {
|
|
3996
|
+
typ: 'Declaration',
|
|
3673
3997
|
// @ts-ignore
|
|
3674
|
-
|
|
3998
|
+
nam: renderToken(name.shift(), { removeComments: true }),
|
|
3675
3999
|
// @ts-ignore
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
map.clear();
|
|
3681
|
-
buffer = '';
|
|
3682
|
-
}
|
|
3683
|
-
break;
|
|
3684
|
-
case '!':
|
|
3685
|
-
if (buffer.length > 0) {
|
|
3686
|
-
pushToken(getType(buffer));
|
|
3687
|
-
buffer = '';
|
|
4000
|
+
val: value
|
|
4001
|
+
};
|
|
4002
|
+
while (node.val[0]?.typ == 'Whitespace') {
|
|
4003
|
+
node.val.shift();
|
|
3688
4004
|
}
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
buffer = '';
|
|
3697
|
-
break;
|
|
4005
|
+
if (node.val.length == 0) {
|
|
4006
|
+
errors.push({
|
|
4007
|
+
action: 'drop',
|
|
4008
|
+
message: 'invalid declaration',
|
|
4009
|
+
location: { src, ...position }
|
|
4010
|
+
});
|
|
4011
|
+
return null;
|
|
3698
4012
|
}
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
break;
|
|
4013
|
+
// @ts-ignore
|
|
4014
|
+
context.chi.push(node);
|
|
4015
|
+
return null;
|
|
4016
|
+
}
|
|
3704
4017
|
}
|
|
3705
4018
|
}
|
|
3706
|
-
|
|
3707
|
-
|
|
4019
|
+
function mapToken(token) {
|
|
4020
|
+
const node = getTokenType(token.token, token.hint);
|
|
4021
|
+
map.set(node, token.position);
|
|
4022
|
+
return node;
|
|
4023
|
+
}
|
|
4024
|
+
const iter = tokenize(iterator);
|
|
4025
|
+
let item;
|
|
4026
|
+
while (true) {
|
|
4027
|
+
item = iter.next().value;
|
|
4028
|
+
if (item == null) {
|
|
4029
|
+
break;
|
|
4030
|
+
}
|
|
4031
|
+
tokens.push(item);
|
|
4032
|
+
bytesIn = item.bytesIn;
|
|
4033
|
+
if (item.token == ';' || item.token == '{') {
|
|
4034
|
+
let node = await parseNode(tokens);
|
|
4035
|
+
if (node != null) {
|
|
4036
|
+
stack.push(node);
|
|
4037
|
+
// @ts-ignore
|
|
4038
|
+
context = node;
|
|
4039
|
+
}
|
|
4040
|
+
else if (item.token == '{') {
|
|
4041
|
+
// node == null
|
|
4042
|
+
// consume and throw away until the closing '}' or EOF
|
|
4043
|
+
let inBlock = 1;
|
|
4044
|
+
do {
|
|
4045
|
+
item = iter.next().value;
|
|
4046
|
+
if (item == null) {
|
|
4047
|
+
break;
|
|
4048
|
+
}
|
|
4049
|
+
if (item.token == '{') {
|
|
4050
|
+
inBlock++;
|
|
4051
|
+
}
|
|
4052
|
+
else if (item.token == '}') {
|
|
4053
|
+
inBlock--;
|
|
4054
|
+
}
|
|
4055
|
+
} while (inBlock != 0);
|
|
4056
|
+
}
|
|
4057
|
+
tokens = [];
|
|
4058
|
+
map = new Map;
|
|
4059
|
+
}
|
|
4060
|
+
else if (item.token == '}') {
|
|
4061
|
+
await parseNode(tokens);
|
|
4062
|
+
const previousNode = stack.pop();
|
|
4063
|
+
// @ts-ignore
|
|
4064
|
+
context = stack[stack.length - 1] || ast;
|
|
4065
|
+
// @ts-ignore
|
|
4066
|
+
if (options.removeEmpty && previousNode != null && previousNode.chi.length == 0 && context.chi[context.chi.length - 1] == previousNode) {
|
|
4067
|
+
context.chi.pop();
|
|
4068
|
+
}
|
|
4069
|
+
tokens = [];
|
|
4070
|
+
map = new Map;
|
|
4071
|
+
}
|
|
3708
4072
|
}
|
|
3709
4073
|
if (tokens.length > 0) {
|
|
3710
4074
|
await parseNode(tokens);
|
|
3711
4075
|
}
|
|
3712
|
-
if (options.
|
|
4076
|
+
if (options.minify) {
|
|
3713
4077
|
if (ast.chi.length > 0) {
|
|
3714
|
-
|
|
4078
|
+
minify(ast, options, true);
|
|
3715
4079
|
}
|
|
3716
4080
|
}
|
|
3717
4081
|
return { ast, errors, bytesIn };
|
|
3718
4082
|
}
|
|
4083
|
+
function parseString(src, options = { location: false }) {
|
|
4084
|
+
return [...tokenize(src)].map(t => {
|
|
4085
|
+
const token = getTokenType(t.token, t.hint);
|
|
4086
|
+
if (options.location) {
|
|
4087
|
+
Object.assign(token, { loc: t.position });
|
|
4088
|
+
}
|
|
4089
|
+
return token;
|
|
4090
|
+
});
|
|
4091
|
+
}
|
|
4092
|
+
function getTokenType(val, hint) {
|
|
4093
|
+
if (val === '' && hint == null) {
|
|
4094
|
+
throw new Error('empty string?');
|
|
4095
|
+
}
|
|
4096
|
+
if (hint != null) {
|
|
4097
|
+
return ([
|
|
4098
|
+
'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
|
|
4099
|
+
'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
|
|
4100
|
+
'Comma', 'Gt', 'Lt'
|
|
4101
|
+
].includes(hint) ? { typ: hint } : { typ: hint, val });
|
|
4102
|
+
}
|
|
4103
|
+
if (val == ' ') {
|
|
4104
|
+
return { typ: 'Whitespace' };
|
|
4105
|
+
}
|
|
4106
|
+
if (val == ';') {
|
|
4107
|
+
return { typ: 'Semi-colon' };
|
|
4108
|
+
}
|
|
4109
|
+
if (val == '{') {
|
|
4110
|
+
return { typ: 'Block-start' };
|
|
4111
|
+
}
|
|
4112
|
+
if (val == '}') {
|
|
4113
|
+
return { typ: 'Block-end' };
|
|
4114
|
+
}
|
|
4115
|
+
if (val == '[') {
|
|
4116
|
+
return { typ: 'Attr-start' };
|
|
4117
|
+
}
|
|
4118
|
+
if (val == ']') {
|
|
4119
|
+
return { typ: 'Attr-end' };
|
|
4120
|
+
}
|
|
4121
|
+
if (val == ':') {
|
|
4122
|
+
return { typ: 'Colon' };
|
|
4123
|
+
}
|
|
4124
|
+
if (val == ')') {
|
|
4125
|
+
return { typ: 'End-parens' };
|
|
4126
|
+
}
|
|
4127
|
+
if (val == '(') {
|
|
4128
|
+
return { typ: 'Start-parens' };
|
|
4129
|
+
}
|
|
4130
|
+
if (val == '=') {
|
|
4131
|
+
return { typ: 'Delim', val };
|
|
4132
|
+
}
|
|
4133
|
+
if (val == ';') {
|
|
4134
|
+
return { typ: 'Semi-colon' };
|
|
4135
|
+
}
|
|
4136
|
+
if (val == ',') {
|
|
4137
|
+
return { typ: 'Comma' };
|
|
4138
|
+
}
|
|
4139
|
+
if (val == '<') {
|
|
4140
|
+
return { typ: 'Lt' };
|
|
4141
|
+
}
|
|
4142
|
+
if (val == '>') {
|
|
4143
|
+
return { typ: 'Gt' };
|
|
4144
|
+
}
|
|
4145
|
+
if (isPseudo(val)) {
|
|
4146
|
+
return val.endsWith('(') ? {
|
|
4147
|
+
typ: 'Pseudo-class-func',
|
|
4148
|
+
val: val.slice(0, -1),
|
|
4149
|
+
chi: []
|
|
4150
|
+
}
|
|
4151
|
+
: {
|
|
4152
|
+
typ: 'Pseudo-class',
|
|
4153
|
+
val
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4156
|
+
if (isAtKeyword(val)) {
|
|
4157
|
+
return {
|
|
4158
|
+
typ: 'At-rule',
|
|
4159
|
+
val: val.slice(1)
|
|
4160
|
+
};
|
|
4161
|
+
}
|
|
4162
|
+
if (isFunction(val)) {
|
|
4163
|
+
val = val.slice(0, -1);
|
|
4164
|
+
return {
|
|
4165
|
+
typ: val == 'url' ? 'UrlFunc' : 'Func',
|
|
4166
|
+
val,
|
|
4167
|
+
chi: []
|
|
4168
|
+
};
|
|
4169
|
+
}
|
|
4170
|
+
if (isNumber(val)) {
|
|
4171
|
+
return {
|
|
4172
|
+
typ: 'Number',
|
|
4173
|
+
val
|
|
4174
|
+
};
|
|
4175
|
+
}
|
|
4176
|
+
if (isDimension(val)) {
|
|
4177
|
+
return parseDimension(val);
|
|
4178
|
+
}
|
|
4179
|
+
if (isPercentage(val)) {
|
|
4180
|
+
return {
|
|
4181
|
+
typ: 'Perc',
|
|
4182
|
+
val: val.slice(0, -1)
|
|
4183
|
+
};
|
|
4184
|
+
}
|
|
4185
|
+
const v = val.toLowerCase();
|
|
4186
|
+
if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
|
|
4187
|
+
return {
|
|
4188
|
+
typ: 'Color',
|
|
4189
|
+
val,
|
|
4190
|
+
kin: 'lit'
|
|
4191
|
+
};
|
|
4192
|
+
}
|
|
4193
|
+
if (isIdent(val)) {
|
|
4194
|
+
return {
|
|
4195
|
+
typ: 'Iden',
|
|
4196
|
+
val
|
|
4197
|
+
};
|
|
4198
|
+
}
|
|
4199
|
+
if (val.charAt(0) == '#' && isHexColor(val)) {
|
|
4200
|
+
return {
|
|
4201
|
+
typ: 'Color',
|
|
4202
|
+
val,
|
|
4203
|
+
kin: 'hex'
|
|
4204
|
+
};
|
|
4205
|
+
}
|
|
4206
|
+
if (val.charAt(0) == '#' && isHash(val)) {
|
|
4207
|
+
return {
|
|
4208
|
+
typ: 'Hash',
|
|
4209
|
+
val
|
|
4210
|
+
};
|
|
4211
|
+
}
|
|
4212
|
+
if ('"\''.includes(val.charAt(0))) {
|
|
4213
|
+
return {
|
|
4214
|
+
typ: 'Unclosed-string',
|
|
4215
|
+
val
|
|
4216
|
+
};
|
|
4217
|
+
}
|
|
4218
|
+
return {
|
|
4219
|
+
typ: 'Literal',
|
|
4220
|
+
val
|
|
4221
|
+
};
|
|
4222
|
+
}
|
|
3719
4223
|
function parseTokens(tokens, options = {}) {
|
|
3720
4224
|
for (let i = 0; i < tokens.length; i++) {
|
|
3721
4225
|
const t = tokens[i];
|
|
@@ -3723,6 +4227,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
3723
4227
|
i + 1 == tokens.length ||
|
|
3724
4228
|
['Comma'].includes(tokens[i + 1].typ) ||
|
|
3725
4229
|
(i > 0 &&
|
|
4230
|
+
tokens[i + 1]?.typ != 'Literal' &&
|
|
3726
4231
|
funcLike.includes(tokens[i - 1].typ) &&
|
|
3727
4232
|
!['var', 'calc'].includes(tokens[i - 1].val))))) {
|
|
3728
4233
|
tokens.splice(i--, 1);
|
|
@@ -3769,7 +4274,7 @@ function parseTokens(tokens, options = {}) {
|
|
|
3769
4274
|
if (t.chi.length > 1) {
|
|
3770
4275
|
/*(<AttrToken>t).chi =*/
|
|
3771
4276
|
// @ts-ignore
|
|
3772
|
-
parseTokens(t.chi,
|
|
4277
|
+
parseTokens(t.chi, t.typ);
|
|
3773
4278
|
}
|
|
3774
4279
|
// @ts-ignore
|
|
3775
4280
|
t.chi.forEach(val => {
|
|
@@ -3881,8 +4386,8 @@ function parseTokens(tokens, options = {}) {
|
|
|
3881
4386
|
// @ts-ignore
|
|
3882
4387
|
if (t.chi.length > 0) {
|
|
3883
4388
|
// @ts-ignore
|
|
3884
|
-
parseTokens(t.chi,
|
|
3885
|
-
if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.
|
|
4389
|
+
parseTokens(t.chi, t.typ);
|
|
4390
|
+
if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.minify) {
|
|
3886
4391
|
//
|
|
3887
4392
|
const count = t.chi.filter(t => t.typ != 'Comment').length;
|
|
3888
4393
|
if (count == 1 ||
|
|
@@ -3920,40 +4425,9 @@ function parseTokens(tokens, options = {}) {
|
|
|
3920
4425
|
}
|
|
3921
4426
|
return tokens;
|
|
3922
4427
|
}
|
|
3923
|
-
function getBlockType(chr) {
|
|
3924
|
-
if (chr == ';') {
|
|
3925
|
-
return { typ: 'Semi-colon' };
|
|
3926
|
-
}
|
|
3927
|
-
if (chr == '{') {
|
|
3928
|
-
return { typ: 'Block-start' };
|
|
3929
|
-
}
|
|
3930
|
-
if (chr == '}') {
|
|
3931
|
-
return { typ: 'Block-end' };
|
|
3932
|
-
}
|
|
3933
|
-
if (chr == '[') {
|
|
3934
|
-
return { typ: 'Attr-start' };
|
|
3935
|
-
}
|
|
3936
|
-
if (chr == ']') {
|
|
3937
|
-
return { typ: 'Attr-end' };
|
|
3938
|
-
}
|
|
3939
|
-
throw new Error(`unhandled token: '${chr}'`);
|
|
3940
|
-
}
|
|
3941
|
-
|
|
3942
|
-
function* walk(node) {
|
|
3943
|
-
// @ts-ignore
|
|
3944
|
-
yield* doWalk(node, null, null);
|
|
3945
|
-
}
|
|
3946
|
-
function* doWalk(node, parent, root) {
|
|
3947
|
-
yield { node, parent, root };
|
|
3948
|
-
if ('chi' in node) {
|
|
3949
|
-
for (const child of node.chi) {
|
|
3950
|
-
yield* doWalk(child, node, (root == null ? node : root));
|
|
3951
|
-
}
|
|
3952
|
-
}
|
|
3953
|
-
}
|
|
3954
4428
|
|
|
3955
4429
|
async function transform$1(css, options = {}) {
|
|
3956
|
-
options = {
|
|
4430
|
+
options = { minify: true, removeEmpty: true, ...options };
|
|
3957
4431
|
const startTime = performance.now();
|
|
3958
4432
|
const parseResult = await parse$1(css, options);
|
|
3959
4433
|
const renderTime = performance.now();
|
|
@@ -4087,16 +4561,42 @@ function transform(css, options = {}) {
|
|
|
4087
4561
|
return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
|
|
4088
4562
|
}
|
|
4089
4563
|
|
|
4090
|
-
exports.
|
|
4091
|
-
exports.deduplicateRule = deduplicateRule;
|
|
4564
|
+
exports.combinators = combinators;
|
|
4092
4565
|
exports.dirname = dirname;
|
|
4566
|
+
exports.getConfig = getConfig;
|
|
4093
4567
|
exports.hasDeclaration = hasDeclaration;
|
|
4568
|
+
exports.isAngle = isAngle;
|
|
4569
|
+
exports.isAtKeyword = isAtKeyword;
|
|
4570
|
+
exports.isDigit = isDigit;
|
|
4571
|
+
exports.isDimension = isDimension;
|
|
4572
|
+
exports.isFrequency = isFrequency;
|
|
4573
|
+
exports.isFunction = isFunction;
|
|
4574
|
+
exports.isHash = isHash;
|
|
4575
|
+
exports.isHexColor = isHexColor;
|
|
4576
|
+
exports.isHexDigit = isHexDigit;
|
|
4577
|
+
exports.isIdent = isIdent;
|
|
4578
|
+
exports.isIdentCodepoint = isIdentCodepoint;
|
|
4579
|
+
exports.isIdentStart = isIdentStart;
|
|
4580
|
+
exports.isLength = isLength;
|
|
4581
|
+
exports.isNewLine = isNewLine;
|
|
4582
|
+
exports.isNumber = isNumber;
|
|
4583
|
+
exports.isPercentage = isPercentage;
|
|
4584
|
+
exports.isPseudo = isPseudo;
|
|
4585
|
+
exports.isResolution = isResolution;
|
|
4586
|
+
exports.isTime = isTime;
|
|
4587
|
+
exports.isWhiteSpace = isWhiteSpace;
|
|
4094
4588
|
exports.load = load;
|
|
4095
4589
|
exports.matchUrl = matchUrl;
|
|
4590
|
+
exports.minify = minify;
|
|
4591
|
+
exports.minifyRule = minifyRule;
|
|
4096
4592
|
exports.parse = parse;
|
|
4593
|
+
exports.parseDimension = parseDimension;
|
|
4594
|
+
exports.parseString = parseString;
|
|
4097
4595
|
exports.reduceSelector = reduceSelector;
|
|
4098
4596
|
exports.render = render;
|
|
4099
4597
|
exports.renderToken = renderToken;
|
|
4100
4598
|
exports.resolve = resolve;
|
|
4599
|
+
exports.tokenize = tokenize;
|
|
4101
4600
|
exports.transform = transform;
|
|
4601
|
+
exports.urlTokenMatcher = urlTokenMatcher;
|
|
4102
4602
|
exports.walk = walk;
|