@tbela99/css-parser 0.0.1-alpha5 → 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 +1 -0
- package/README.md +18 -6
- package/dist/config.json.js +95 -4
- package/dist/index-umd-web.js +1609 -1391
- package/dist/index.cjs +1609 -1391
- package/dist/index.d.ts +317 -9
- package/dist/index.js +6 -2
- package/dist/lib/{parser/deduplicate.js → ast/minify.js} +393 -414
- 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 +237 -683
- 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 +9 -6
- package/dist/lib/transform.js +1 -1
- package/dist/node/index.js +1 -0
- package/dist/web/index.js +6 -2
- package/package.json +11 -5
- /package/dist/lib/{walker → ast}/walk.js +0 -0
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",
|
|
@@ -1456,7 +1564,7 @@ function hsl2rgb(h, s, l, a = null) {
|
|
|
1456
1564
|
}
|
|
1457
1565
|
|
|
1458
1566
|
function render(data, opt = {}) {
|
|
1459
|
-
const options = Object.assign(opt.
|
|
1567
|
+
const options = Object.assign(opt.minify ?? true ? {
|
|
1460
1568
|
indent: '',
|
|
1461
1569
|
newLine: '',
|
|
1462
1570
|
removeComments: true
|
|
@@ -1541,8 +1649,11 @@ function doRender(data, options, reducer, level = 0, indents = []) {
|
|
|
1541
1649
|
function renderToken(token, options = {}) {
|
|
1542
1650
|
switch (token.typ) {
|
|
1543
1651
|
case 'Color':
|
|
1544
|
-
if (options.
|
|
1545
|
-
|
|
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()] : '');
|
|
1546
1657
|
if (token.val == 'rgb' || token.val == 'rgba') {
|
|
1547
1658
|
value = rgb2Hex(token);
|
|
1548
1659
|
}
|
|
@@ -1586,7 +1697,7 @@ function renderToken(token, options = {}) {
|
|
|
1586
1697
|
case 'UrlFunc':
|
|
1587
1698
|
case 'Pseudo-class-func':
|
|
1588
1699
|
// @ts-ignore
|
|
1589
|
-
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) => {
|
|
1590
1701
|
if (options.removeComments && curr.typ == 'Comment') {
|
|
1591
1702
|
if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
|
|
1592
1703
|
return acc;
|
|
@@ -1677,21 +1788,45 @@ function renderToken(token, options = {}) {
|
|
|
1677
1788
|
case 'String':
|
|
1678
1789
|
case 'Iden':
|
|
1679
1790
|
case 'Delim':
|
|
1680
|
-
return /* options.
|
|
1791
|
+
return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
|
1681
1792
|
}
|
|
1682
1793
|
throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`);
|
|
1683
1794
|
}
|
|
1684
1795
|
|
|
1685
1796
|
function eq(a, b) {
|
|
1686
|
-
if (
|
|
1797
|
+
if (a == null || b == null) {
|
|
1798
|
+
return a == b;
|
|
1799
|
+
}
|
|
1800
|
+
if (typeof a != 'object' || typeof b != 'object') {
|
|
1687
1801
|
return a === b;
|
|
1688
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
|
+
}
|
|
1689
1818
|
const k1 = Object.keys(a);
|
|
1690
1819
|
const k2 = Object.keys(b);
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
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;
|
|
1695
1830
|
}
|
|
1696
1831
|
|
|
1697
1832
|
class PropertySet {
|
|
@@ -1703,8 +1838,7 @@ class PropertySet {
|
|
|
1703
1838
|
}
|
|
1704
1839
|
add(declaration) {
|
|
1705
1840
|
if (declaration.nam == this.config.shorthand) {
|
|
1706
|
-
this.declarations
|
|
1707
|
-
this.declarations.set(declaration.nam, declaration);
|
|
1841
|
+
this.declarations = new Map;
|
|
1708
1842
|
}
|
|
1709
1843
|
else {
|
|
1710
1844
|
// expand shorthand
|
|
@@ -1727,6 +1861,10 @@ class PropertySet {
|
|
|
1727
1861
|
}
|
|
1728
1862
|
if (token.typ != 'Whitespace' && token.typ != 'Comment') {
|
|
1729
1863
|
if (token.typ == 'Iden' && this.config.keywords.includes(token.val)) {
|
|
1864
|
+
if (tokens.length == 0) {
|
|
1865
|
+
tokens.push([]);
|
|
1866
|
+
current++;
|
|
1867
|
+
}
|
|
1730
1868
|
tokens[current].push(token);
|
|
1731
1869
|
}
|
|
1732
1870
|
if (token.typ == 'Literal' && token.val == this.config.separator) {
|
|
@@ -1742,10 +1880,6 @@ class PropertySet {
|
|
|
1742
1880
|
this.declarations.delete(this.config.shorthand);
|
|
1743
1881
|
for (const values of tokens) {
|
|
1744
1882
|
this.config.properties.forEach((property, index) => {
|
|
1745
|
-
// if (property == declaration.nam) {
|
|
1746
|
-
//
|
|
1747
|
-
// return;
|
|
1748
|
-
// }
|
|
1749
1883
|
if (!this.declarations.has(property)) {
|
|
1750
1884
|
this.declarations.set(property, {
|
|
1751
1885
|
typ: 'Declaration',
|
|
@@ -1774,30 +1908,20 @@ class PropertySet {
|
|
|
1774
1908
|
this.declarations.set(declaration.nam, declaration);
|
|
1775
1909
|
return this;
|
|
1776
1910
|
}
|
|
1777
|
-
// declaration.chi = declaration.chi.reduce((acc: Token[], token: Token) => {
|
|
1778
|
-
//
|
|
1779
|
-
// if (this.config.types.includes(token.typ) || ('0' == (<DimensionToken>token).chi && (
|
|
1780
|
-
// this.config.types.includes('Length') ||
|
|
1781
|
-
// this.config.types.includes('Angle') ||
|
|
1782
|
-
// this.config.types.includes('Dimension'))) || (token.typ == 'Iden' && this.config.keywords.includes(token.chi))) {
|
|
1783
|
-
//
|
|
1784
|
-
// acc.push(token);
|
|
1785
|
-
// }
|
|
1786
|
-
//
|
|
1787
|
-
// return acc;
|
|
1788
|
-
// }, <Token[]>[]);
|
|
1789
|
-
this.declarations.set(declaration.nam, declaration);
|
|
1790
1911
|
}
|
|
1912
|
+
this.declarations.set(declaration.nam, declaration);
|
|
1791
1913
|
return this;
|
|
1792
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
|
+
}
|
|
1793
1921
|
[Symbol.iterator]() {
|
|
1794
1922
|
let iterator;
|
|
1795
1923
|
const declarations = this.declarations;
|
|
1796
|
-
if (declarations.size < this.config.properties.length
|
|
1797
|
-
return !declarations.has(property) || (index > 0 &&
|
|
1798
|
-
// @ts-ignore
|
|
1799
|
-
declarations.get(property).val.length != declarations.get(this.config.properties[Math.floor(index / 2)]).val.length);
|
|
1800
|
-
})) {
|
|
1924
|
+
if (declarations.size < this.config.properties.length) {
|
|
1801
1925
|
iterator = declarations.values();
|
|
1802
1926
|
}
|
|
1803
1927
|
else {
|
|
@@ -1855,17 +1979,20 @@ class PropertySet {
|
|
|
1855
1979
|
return acc;
|
|
1856
1980
|
}, [])
|
|
1857
1981
|
}][Symbol.iterator]();
|
|
1858
|
-
return {
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
}
|
|
1982
|
+
// return {
|
|
1983
|
+
// next() {
|
|
1984
|
+
//
|
|
1985
|
+
// return iterator.next();
|
|
1986
|
+
// }
|
|
1987
|
+
// }
|
|
1863
1988
|
}
|
|
1864
|
-
return
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1989
|
+
return iterator;
|
|
1990
|
+
// return {
|
|
1991
|
+
// next() {
|
|
1992
|
+
//
|
|
1993
|
+
// return iterator.next();
|
|
1994
|
+
// }
|
|
1995
|
+
// }
|
|
1869
1996
|
}
|
|
1870
1997
|
}
|
|
1871
1998
|
|
|
@@ -1880,34 +2007,7 @@ function matchType(val, properties) {
|
|
|
1880
2007
|
return false;
|
|
1881
2008
|
}
|
|
1882
2009
|
|
|
1883
|
-
|
|
1884
|
-
if (val == 'transparent' || val == 'currentcolor') {
|
|
1885
|
-
return {
|
|
1886
|
-
typ: 'Color',
|
|
1887
|
-
val,
|
|
1888
|
-
kin: 'lit'
|
|
1889
|
-
};
|
|
1890
|
-
}
|
|
1891
|
-
if (val.endsWith('%')) {
|
|
1892
|
-
return {
|
|
1893
|
-
typ: 'Perc',
|
|
1894
|
-
val: val.slice(0, -1)
|
|
1895
|
-
};
|
|
1896
|
-
}
|
|
1897
|
-
return {
|
|
1898
|
-
typ: isNumber(val) ? 'Number' : 'Iden',
|
|
1899
|
-
val
|
|
1900
|
-
};
|
|
1901
|
-
}
|
|
1902
|
-
function parseString(val) {
|
|
1903
|
-
return val.split(/\s/).map(getTokenType).reduce((acc, curr) => {
|
|
1904
|
-
if (acc.length > 0) {
|
|
1905
|
-
acc.push({ typ: 'Whitespace' });
|
|
1906
|
-
}
|
|
1907
|
-
acc.push(curr);
|
|
1908
|
-
return acc;
|
|
1909
|
-
}, []);
|
|
1910
|
-
}
|
|
2010
|
+
const propertiesConfig = getConfig();
|
|
1911
2011
|
class PropertyMap {
|
|
1912
2012
|
config;
|
|
1913
2013
|
declarations;
|
|
@@ -1922,7 +2022,7 @@ class PropertyMap {
|
|
|
1922
2022
|
}
|
|
1923
2023
|
add(declaration) {
|
|
1924
2024
|
if (declaration.nam == this.config.shorthand) {
|
|
1925
|
-
this.declarations
|
|
2025
|
+
this.declarations = new Map;
|
|
1926
2026
|
this.declarations.set(declaration.nam, declaration);
|
|
1927
2027
|
}
|
|
1928
2028
|
else {
|
|
@@ -1999,8 +2099,7 @@ class PropertyMap {
|
|
|
1999
2099
|
const defaults = parseString(props.default[0]);
|
|
2000
2100
|
if (!(property in tokens)) {
|
|
2001
2101
|
tokens[property] = [
|
|
2002
|
-
[...defaults
|
|
2003
|
-
]
|
|
2102
|
+
[...defaults]
|
|
2004
2103
|
];
|
|
2005
2104
|
}
|
|
2006
2105
|
else {
|
|
@@ -2034,145 +2133,229 @@ class PropertyMap {
|
|
|
2034
2133
|
}, new Map);
|
|
2035
2134
|
}
|
|
2036
2135
|
}
|
|
2037
|
-
|
|
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
|
+
}
|
|
2038
2156
|
}
|
|
2039
2157
|
return this;
|
|
2040
2158
|
}
|
|
2041
2159
|
[Symbol.iterator]() {
|
|
2042
|
-
let
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
return this.declarations.values();
|
|
2052
|
-
}
|
|
2053
|
-
let count = 0;
|
|
2054
|
-
const separator = this.config.separator;
|
|
2055
|
-
const tokens = {};
|
|
2056
|
-
// @ts-ignore
|
|
2057
|
-
const valid = Object.entries(this.config.properties).reduce((acc, curr) => {
|
|
2058
|
-
if (!this.declarations.has(curr[0])) {
|
|
2059
|
-
if (curr[1].required) {
|
|
2060
|
-
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;
|
|
2061
2169
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
for (const val of this.declarations.get(curr[0]).val) {
|
|
2068
|
-
if (separator != null && separator.typ == val.typ && eq(separator, val)) {
|
|
2069
|
-
current++;
|
|
2070
|
-
if (tokens[curr[0]].length == current) {
|
|
2071
|
-
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;
|
|
2072
2175
|
}
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2076
|
-
continue;
|
|
2077
|
-
}
|
|
2078
|
-
if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(val, props.separator)) {
|
|
2079
|
-
continue;
|
|
2080
|
-
}
|
|
2081
|
-
if (matchType(val, curr[1])) {
|
|
2082
|
-
if (!(curr[0] in tokens)) {
|
|
2083
|
-
tokens[curr[0]] = [[]];
|
|
2176
|
+
else {
|
|
2177
|
+
requiredCount++;
|
|
2084
2178
|
}
|
|
2085
|
-
// is default value
|
|
2086
|
-
tokens[curr[0]][current].push(val);
|
|
2087
|
-
continue;
|
|
2088
2179
|
}
|
|
2089
|
-
acc.push(curr[0]);
|
|
2090
|
-
break;
|
|
2091
2180
|
}
|
|
2092
|
-
if (count == 0) {
|
|
2093
|
-
count = current;
|
|
2094
|
-
}
|
|
2095
|
-
return acc;
|
|
2096
|
-
}, []);
|
|
2097
|
-
if (valid.length > 0 || Object.values(tokens).every(v => v.every(v => v.length == count))) {
|
|
2098
|
-
return this.declarations.values();
|
|
2099
2181
|
}
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
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]);
|
|
2109
2198
|
}
|
|
2110
|
-
acc.push(curr);
|
|
2111
2199
|
return acc;
|
|
2112
|
-
}, []);
|
|
2113
|
-
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
|
|
2114
|
-
continue;
|
|
2115
2200
|
}
|
|
2116
|
-
|
|
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
|
+
}
|
|
2117
2213
|
if (val.typ == 'Whitespace' || val.typ == 'Comment') {
|
|
2118
|
-
|
|
2214
|
+
continue;
|
|
2119
2215
|
}
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
if (
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
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) {
|
|
2128
2279
|
// @ts-ignore
|
|
2129
|
-
if (
|
|
2130
|
-
|
|
2131
|
-
|
|
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
|
+
}
|
|
2132
2289
|
}
|
|
2133
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
|
+
}, []));
|
|
2134
2307
|
}
|
|
2135
2308
|
}
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2309
|
+
return acc;
|
|
2310
|
+
}, []).reduce((acc, curr) => {
|
|
2311
|
+
if (acc.length > 0) {
|
|
2312
|
+
acc.push({ ...separator });
|
|
2139
2313
|
}
|
|
2140
|
-
|
|
2141
|
-
|
|
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
|
+
}, []));
|
|
2142
2322
|
}
|
|
2143
|
-
acc
|
|
2144
|
-
|
|
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) {
|
|
2145
2347
|
// @ts-ignore
|
|
2146
|
-
|
|
2348
|
+
iterable = iterators.pop();
|
|
2349
|
+
v = iterable.next();
|
|
2350
|
+
}
|
|
2351
|
+
if (v.done && iterators.length == 0) {
|
|
2352
|
+
break;
|
|
2147
2353
|
}
|
|
2148
|
-
// @ts-ignore
|
|
2149
|
-
acc.push(curr);
|
|
2150
|
-
return acc;
|
|
2151
|
-
}, []));
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
return acc;
|
|
2155
|
-
}, []).reduce((acc, curr) => {
|
|
2156
|
-
if (acc.length > 0) {
|
|
2157
|
-
acc.push({ ...separator });
|
|
2158
|
-
}
|
|
2159
|
-
if (curr.length == 0) {
|
|
2160
|
-
curr.push(...this.config.default[0].split(/\s/).map(getTokenType).reduce((acc, curr) => {
|
|
2161
|
-
if (acc.length > 0) {
|
|
2162
|
-
acc.push({ typ: 'Whitespace' });
|
|
2163
2354
|
}
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
}, []));
|
|
2355
|
+
}
|
|
2356
|
+
return v;
|
|
2167
2357
|
}
|
|
2168
|
-
|
|
2169
|
-
return acc;
|
|
2170
|
-
}, []);
|
|
2171
|
-
return [{
|
|
2172
|
-
typ: 'Declaration',
|
|
2173
|
-
nam: this.config.shorthand,
|
|
2174
|
-
val: values
|
|
2175
|
-
}][Symbol.iterator]();
|
|
2358
|
+
};
|
|
2176
2359
|
}
|
|
2177
2360
|
}
|
|
2178
2361
|
|
|
@@ -2182,33 +2365,61 @@ class PropertyList {
|
|
|
2182
2365
|
constructor() {
|
|
2183
2366
|
this.declarations = new Map;
|
|
2184
2367
|
}
|
|
2368
|
+
set(nam, value) {
|
|
2369
|
+
return this.add({ typ: 'Declaration', nam, val: Array.isArray(value) ? value : parseString(String(value)) });
|
|
2370
|
+
}
|
|
2185
2371
|
add(declaration) {
|
|
2186
2372
|
if (declaration.typ != 'Declaration') {
|
|
2187
2373
|
this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
|
|
2188
2374
|
return this;
|
|
2189
2375
|
}
|
|
2190
|
-
|
|
2376
|
+
let propertyName = declaration.nam;
|
|
2377
|
+
let shortHandType;
|
|
2378
|
+
let shorthand;
|
|
2191
2379
|
if (propertyName in config.properties) {
|
|
2192
2380
|
// @ts-ignore
|
|
2193
|
-
|
|
2194
|
-
|
|
2381
|
+
if ('map' in config.properties[propertyName]) {
|
|
2382
|
+
shortHandType = 'map';
|
|
2195
2383
|
// @ts-ignore
|
|
2196
|
-
|
|
2384
|
+
shorthand = config.properties[propertyName].map;
|
|
2197
2385
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
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;
|
|
2200
2396
|
}
|
|
2201
|
-
|
|
2397
|
+
// @ts-ignore
|
|
2398
|
+
if (shortHandType == 'map') {
|
|
2202
2399
|
// @ts-ignore
|
|
2203
|
-
const shorthand = config.map[propertyName].shorthand;
|
|
2204
2400
|
if (!this.declarations.has(shorthand)) {
|
|
2205
2401
|
// @ts-ignore
|
|
2206
2402
|
this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
|
|
2207
2403
|
}
|
|
2404
|
+
// @ts-ignore
|
|
2208
2405
|
this.declarations.get(shorthand).add(declaration);
|
|
2209
|
-
return this;
|
|
2406
|
+
// return this;
|
|
2407
|
+
}
|
|
2408
|
+
// @ts-ignore
|
|
2409
|
+
else if (shortHandType == 'set') {
|
|
2410
|
+
// @ts-ignore
|
|
2411
|
+
// const shorthand: string = <string>config.properties[propertyName].shorthand;
|
|
2412
|
+
if (!this.declarations.has(shorthand)) {
|
|
2413
|
+
// @ts-ignore
|
|
2414
|
+
this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
|
|
2415
|
+
}
|
|
2416
|
+
// @ts-ignore
|
|
2417
|
+
this.declarations.get(shorthand).add(declaration);
|
|
2418
|
+
// return this;
|
|
2419
|
+
}
|
|
2420
|
+
else {
|
|
2421
|
+
this.declarations.set(propertyName, declaration);
|
|
2210
2422
|
}
|
|
2211
|
-
this.declarations.set(propertyName, declaration);
|
|
2212
2423
|
return this;
|
|
2213
2424
|
}
|
|
2214
2425
|
[Symbol.iterator]() {
|
|
@@ -2237,56 +2448,300 @@ class PropertyList {
|
|
|
2237
2448
|
}
|
|
2238
2449
|
}
|
|
2239
2450
|
|
|
2240
|
-
const configuration = getConfig();
|
|
2241
2451
|
const combinators = ['+', '>', '~'];
|
|
2242
2452
|
const notEndingWith = ['(', '['].concat(combinators);
|
|
2243
|
-
function
|
|
2244
|
-
|
|
2245
|
-
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
2246
|
-
// @ts-ignore
|
|
2247
|
-
let nSel = match.selector2.reduce(reducer, []).join(',');
|
|
2248
|
-
// @ts-ignore
|
|
2249
|
-
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
2250
|
-
// @ts-ignore
|
|
2251
|
-
Object.defineProperty(wrapper, 'raw', {
|
|
2252
|
-
enumerable: false,
|
|
2253
|
-
writable: true,
|
|
2453
|
+
function minify(ast, options = {}, recursive = false) {
|
|
2454
|
+
function wrapNodes(previous, node, match, ast, i, nodeIndex) {
|
|
2254
2455
|
// @ts-ignore
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2456
|
+
let pSel = match.selector1.reduce(reducer, []).join(',');
|
|
2457
|
+
// @ts-ignore
|
|
2458
|
+
let nSel = match.selector2.reduce(reducer, []).join(',');
|
|
2258
2459
|
// @ts-ignore
|
|
2259
|
-
wrapper
|
|
2460
|
+
const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
|
|
2260
2461
|
// @ts-ignore
|
|
2261
|
-
|
|
2462
|
+
Object.defineProperty(wrapper, 'raw', {
|
|
2463
|
+
enumerable: false,
|
|
2464
|
+
writable: true,
|
|
2262
2465
|
// @ts-ignore
|
|
2263
|
-
|
|
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
|
+
}
|
|
2264
2480
|
}
|
|
2265
2481
|
else {
|
|
2266
2482
|
// @ts-ignore
|
|
2267
|
-
wrapper.chi.push(node);
|
|
2483
|
+
wrapper.chi.push(previous, node);
|
|
2268
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;
|
|
2269
2499
|
}
|
|
2270
|
-
|
|
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
|
+
}
|
|
2271
2571
|
// @ts-ignore
|
|
2272
|
-
|
|
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
|
+
};
|
|
2273
2744
|
}
|
|
2274
|
-
// @ts-ignore
|
|
2275
|
-
ast.chi.splice(i, 1, wrapper);
|
|
2276
|
-
// @ts-ignore
|
|
2277
|
-
ast.chi.splice(nodeIndex, 1);
|
|
2278
|
-
// @ts-ignore
|
|
2279
|
-
previous.sel = pSel;
|
|
2280
|
-
// @ts-ignore
|
|
2281
|
-
previous.raw = match.selector1;
|
|
2282
|
-
// @ts-ignore
|
|
2283
|
-
node.sel = nSel;
|
|
2284
|
-
// @ts-ignore
|
|
2285
|
-
node.raw = match.selector2;
|
|
2286
|
-
reduceRuleSelector(wrapper);
|
|
2287
|
-
return wrapper;
|
|
2288
|
-
}
|
|
2289
|
-
function deduplicate(ast, options = {}, recursive = false) {
|
|
2290
2745
|
// @ts-ignore
|
|
2291
2746
|
if (('chi' in ast) && ast.chi?.length > 0) {
|
|
2292
2747
|
let i = 0;
|
|
@@ -2326,7 +2781,8 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2326
2781
|
// @ts-ignore
|
|
2327
2782
|
if (options.nestingRules) {
|
|
2328
2783
|
// @ts-ignore
|
|
2329
|
-
if (previous
|
|
2784
|
+
if (previous?.typ == 'Rule') {
|
|
2785
|
+
// @ts-ignore
|
|
2330
2786
|
reduceRuleSelector(previous);
|
|
2331
2787
|
// @ts-ignore
|
|
2332
2788
|
match = matchSelectors(previous.raw, node.raw, ast.typ);
|
|
@@ -2365,7 +2821,7 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2365
2821
|
nodeIndex = --i;
|
|
2366
2822
|
// @ts-ignore
|
|
2367
2823
|
previous = ast.chi[nodeIndex];
|
|
2368
|
-
|
|
2824
|
+
minify(wrapper, options, recursive);
|
|
2369
2825
|
continue;
|
|
2370
2826
|
}
|
|
2371
2827
|
// @ts-ignore
|
|
@@ -2414,13 +2870,24 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2414
2870
|
}
|
|
2415
2871
|
else if (combinators.includes(curr[0])) {
|
|
2416
2872
|
curr.unshift('&');
|
|
2873
|
+
wrap = false;
|
|
2417
2874
|
}
|
|
2418
2875
|
// @ts-ignore
|
|
2419
|
-
acc.push(curr
|
|
2876
|
+
acc.push(curr);
|
|
2420
2877
|
return acc;
|
|
2421
2878
|
}, []);
|
|
2879
|
+
if (!wrap) {
|
|
2880
|
+
wrap = selector.some(s => s[0] != '&');
|
|
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(',');
|
|
2422
2889
|
// @ts-ignore
|
|
2423
|
-
node.sel =
|
|
2890
|
+
node.sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
|
|
2424
2891
|
}
|
|
2425
2892
|
}
|
|
2426
2893
|
// @ts-ignore
|
|
@@ -2451,10 +2918,10 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2451
2918
|
// @ts-ignore
|
|
2452
2919
|
if (hasDeclaration(node)) {
|
|
2453
2920
|
// @ts-ignore
|
|
2454
|
-
|
|
2921
|
+
minifyRule(node);
|
|
2455
2922
|
}
|
|
2456
2923
|
else {
|
|
2457
|
-
|
|
2924
|
+
minify(node, options, recursive);
|
|
2458
2925
|
}
|
|
2459
2926
|
i--;
|
|
2460
2927
|
previous = node;
|
|
@@ -2496,10 +2963,10 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2496
2963
|
// @ts-ignore
|
|
2497
2964
|
if (hasDeclaration(previous)) {
|
|
2498
2965
|
// @ts-ignore
|
|
2499
|
-
|
|
2966
|
+
minifyRule(previous);
|
|
2500
2967
|
}
|
|
2501
2968
|
else {
|
|
2502
|
-
|
|
2969
|
+
minify(previous, options, recursive);
|
|
2503
2970
|
}
|
|
2504
2971
|
}
|
|
2505
2972
|
}
|
|
@@ -2510,18 +2977,97 @@ function deduplicate(ast, options = {}, recursive = false) {
|
|
|
2510
2977
|
if (recursive && node != null && ('chi' in node)) {
|
|
2511
2978
|
// @ts-ignore
|
|
2512
2979
|
if (node.chi.some(n => n.typ == 'Declaration')) {
|
|
2513
|
-
|
|
2980
|
+
minifyRule(node);
|
|
2514
2981
|
}
|
|
2515
2982
|
else {
|
|
2516
2983
|
// @ts-ignore
|
|
2517
2984
|
if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
|
|
2518
|
-
|
|
2985
|
+
minify(node, options, recursive);
|
|
2519
2986
|
}
|
|
2520
2987
|
}
|
|
2521
2988
|
}
|
|
2522
2989
|
}
|
|
2523
2990
|
return ast;
|
|
2524
2991
|
}
|
|
2992
|
+
function reduceSelector(selector) {
|
|
2993
|
+
if (selector.length == 0) {
|
|
2994
|
+
return null;
|
|
2995
|
+
}
|
|
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
|
+
}
|
|
2525
3071
|
function hasOnlyDeclarations(node) {
|
|
2526
3072
|
let k = node.chi.length;
|
|
2527
3073
|
while (k--) {
|
|
@@ -2544,7 +3090,7 @@ function hasDeclaration(node) {
|
|
|
2544
3090
|
}
|
|
2545
3091
|
return true;
|
|
2546
3092
|
}
|
|
2547
|
-
function
|
|
3093
|
+
function minifyRule(ast) {
|
|
2548
3094
|
// @ts-ignore
|
|
2549
3095
|
if (!('chi' in ast) || ast.chi?.length <= 1) {
|
|
2550
3096
|
return ast;
|
|
@@ -2552,45 +3098,19 @@ function deduplicateRule(ast) {
|
|
|
2552
3098
|
// @ts-ignore
|
|
2553
3099
|
const j = ast.chi.length;
|
|
2554
3100
|
let k = 0;
|
|
2555
|
-
let
|
|
3101
|
+
let properties = new PropertyList();
|
|
2556
3102
|
// @ts-ignore
|
|
2557
3103
|
for (; k < j; k++) {
|
|
2558
3104
|
// @ts-ignore
|
|
2559
3105
|
const node = ast.chi[k];
|
|
2560
|
-
if (node.typ == 'Comment') {
|
|
2561
|
-
|
|
2562
|
-
map.set(node, node);
|
|
3106
|
+
if (node.typ == 'Comment' || node.typ == 'Declaration') {
|
|
3107
|
+
properties.add(node);
|
|
2563
3108
|
continue;
|
|
2564
3109
|
}
|
|
2565
|
-
|
|
2566
|
-
break;
|
|
2567
|
-
}
|
|
2568
|
-
if (node.nam in configuration.map ||
|
|
2569
|
-
node.nam in configuration.properties) {
|
|
2570
|
-
// @ts-ignore
|
|
2571
|
-
const shorthand = node.nam in configuration.map ? configuration.map[node.nam].shorthand : configuration.properties[node.nam].shorthand;
|
|
2572
|
-
if (!map.has(shorthand)) {
|
|
2573
|
-
map.set(shorthand, new PropertyList());
|
|
2574
|
-
}
|
|
2575
|
-
map.get(shorthand).add(node);
|
|
2576
|
-
}
|
|
2577
|
-
else {
|
|
2578
|
-
map.set(node.nam, node);
|
|
2579
|
-
}
|
|
2580
|
-
}
|
|
2581
|
-
const children = [];
|
|
2582
|
-
for (let child of map.values()) {
|
|
2583
|
-
if (child instanceof PropertyList) {
|
|
2584
|
-
// @ts-ignore
|
|
2585
|
-
children.push(...child);
|
|
2586
|
-
}
|
|
2587
|
-
else {
|
|
2588
|
-
// @ts-ignore
|
|
2589
|
-
children.push(child);
|
|
2590
|
-
}
|
|
3110
|
+
break;
|
|
2591
3111
|
}
|
|
2592
3112
|
// @ts-ignore
|
|
2593
|
-
ast.chi =
|
|
3113
|
+
ast.chi = [...properties].concat(ast.chi.slice(k));
|
|
2594
3114
|
return ast;
|
|
2595
3115
|
}
|
|
2596
3116
|
function splitRule(buffer) {
|
|
@@ -2716,345 +3236,482 @@ function reduceRuleSelector(node) {
|
|
|
2716
3236
|
}
|
|
2717
3237
|
// }
|
|
2718
3238
|
}
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
let node2 = n2;
|
|
2722
|
-
let exchanged = false;
|
|
2723
|
-
if (node1.chi.length > node2.chi.length) {
|
|
2724
|
-
const t = node1;
|
|
2725
|
-
node1 = node2;
|
|
2726
|
-
node2 = t;
|
|
2727
|
-
exchanged = true;
|
|
2728
|
-
}
|
|
2729
|
-
let i = node1.chi.length;
|
|
2730
|
-
let j = node2.chi.length;
|
|
2731
|
-
if (i == 0 || j == 0) {
|
|
2732
|
-
// @ts-ignore
|
|
2733
|
-
return null;
|
|
2734
|
-
}
|
|
2735
|
-
// @ts-ignore
|
|
2736
|
-
const raw1 = node1.raw;
|
|
2737
|
-
// @ts-ignore
|
|
2738
|
-
// const optimized1 = node1.optimized;
|
|
2739
|
-
// @ts-ignore
|
|
2740
|
-
const raw2 = node2.raw;
|
|
3239
|
+
|
|
3240
|
+
function* walk(node) {
|
|
2741
3241
|
// @ts-ignore
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
// Object.defineProperty(node1, 'optimized', {enumerable: false, writable: true, value: optimized1});
|
|
2750
|
-
// }
|
|
2751
|
-
if (raw2 != null) {
|
|
2752
|
-
Object.defineProperty(node2, 'raw', { enumerable: false, writable: true, value: raw2 });
|
|
2753
|
-
}
|
|
2754
|
-
// if (optimized2 != null) {
|
|
2755
|
-
// Object.defineProperty(node2, 'optimized', {enumerable: false, writable: true, value: optimized2});
|
|
2756
|
-
// }
|
|
2757
|
-
const intersect = [];
|
|
2758
|
-
while (i--) {
|
|
2759
|
-
if (node1.chi[i].typ == 'Comment') {
|
|
2760
|
-
continue;
|
|
2761
|
-
}
|
|
2762
|
-
j = node2.chi.length;
|
|
2763
|
-
if (j == 0) {
|
|
2764
|
-
break;
|
|
3242
|
+
yield* doWalk(node, null, null);
|
|
3243
|
+
}
|
|
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));
|
|
2765
3249
|
}
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
function* tokenize(iterator) {
|
|
3254
|
+
let ind = -1;
|
|
3255
|
+
let lin = 1;
|
|
3256
|
+
let col = 0;
|
|
3257
|
+
const position = {
|
|
3258
|
+
ind: Math.max(ind, 0),
|
|
3259
|
+
lin: lin,
|
|
3260
|
+
col: Math.max(col, 1)
|
|
3261
|
+
};
|
|
3262
|
+
let value;
|
|
3263
|
+
let buffer = '';
|
|
3264
|
+
function consumeWhiteSpace() {
|
|
3265
|
+
let count = 0;
|
|
3266
|
+
while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
|
|
3267
|
+
count++;
|
|
2778
3268
|
}
|
|
3269
|
+
next(count);
|
|
3270
|
+
return count;
|
|
2779
3271
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
});
|
|
2787
|
-
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)) {
|
|
2788
|
-
// @ts-ignore
|
|
2789
|
-
return null;
|
|
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;
|
|
2790
3278
|
}
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
for (; i < j; i++) {
|
|
2804
|
-
k = 0;
|
|
2805
|
-
token = selector1[0][i];
|
|
2806
|
-
for (; k < selector1.length; k++) {
|
|
2807
|
-
if (selector1[k][i] != token) {
|
|
2808
|
-
matching = false;
|
|
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 = '';
|
|
3286
|
+
}
|
|
3287
|
+
buffer += quoteStr;
|
|
3288
|
+
while (value = peek()) {
|
|
3289
|
+
if (ind >= iterator.length) {
|
|
3290
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string');
|
|
2809
3291
|
break;
|
|
2810
3292
|
}
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
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
|
+
}
|
|
2817
3310
|
break;
|
|
2818
3311
|
}
|
|
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);
|
|
3327
|
+
}
|
|
3328
|
+
else {
|
|
3329
|
+
buffer += String.fromCodePoint(codepoint);
|
|
3330
|
+
}
|
|
3331
|
+
next(escapeSequence.length + 1);
|
|
3332
|
+
continue;
|
|
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;
|
|
2819
3342
|
}
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
else {
|
|
2828
|
-
if (token.endsWith('(')) {
|
|
2829
|
-
matchFunction++;
|
|
2830
|
-
}
|
|
2831
|
-
if (token.endsWith('[')) {
|
|
2832
|
-
inAttr++;
|
|
3343
|
+
if (value == quote) {
|
|
3344
|
+
buffer += value;
|
|
3345
|
+
yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
|
|
3346
|
+
next();
|
|
3347
|
+
// i += value.length;
|
|
3348
|
+
buffer = '';
|
|
3349
|
+
break;
|
|
2833
3350
|
}
|
|
2834
|
-
|
|
2835
|
-
|
|
3351
|
+
if (isNewLine(value.charCodeAt(0))) {
|
|
3352
|
+
hasNewLine = true;
|
|
2836
3353
|
}
|
|
2837
|
-
|
|
2838
|
-
|
|
3354
|
+
if (hasNewLine && value == ';') {
|
|
3355
|
+
yield pushToken(buffer, 'Bad-string');
|
|
3356
|
+
buffer = '';
|
|
3357
|
+
break;
|
|
2839
3358
|
}
|
|
2840
|
-
|
|
3359
|
+
buffer += value;
|
|
3360
|
+
// i += value.length;
|
|
3361
|
+
next();
|
|
2841
3362
|
}
|
|
2842
3363
|
}
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
}
|
|
2847
|
-
if (parentType != 'Rule') {
|
|
2848
|
-
for (const part of match) {
|
|
2849
|
-
if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
|
|
2850
|
-
return null;
|
|
2851
|
-
}
|
|
3364
|
+
function peek(count = 1) {
|
|
3365
|
+
if (count == 1) {
|
|
3366
|
+
return iterator.charAt(ind + 1);
|
|
2852
3367
|
}
|
|
3368
|
+
return iterator.slice(ind + 1, ind + count + 1);
|
|
2853
3369
|
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
3370
|
+
function prev(count = 1) {
|
|
3371
|
+
if (count == 1) {
|
|
3372
|
+
return ind == 0 ? '' : iterator.charAt(ind - 1);
|
|
3373
|
+
}
|
|
3374
|
+
return iterator.slice(ind - 1 - count, ind - 1);
|
|
2858
3375
|
}
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
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++;
|
|
2865
3390
|
}
|
|
2866
|
-
break;
|
|
2867
3391
|
}
|
|
3392
|
+
return char;
|
|
2868
3393
|
}
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
}
|
|
2875
|
-
function reduce(acc, curr) {
|
|
2876
|
-
if (acc === null) {
|
|
2877
|
-
return null;
|
|
2878
|
-
}
|
|
2879
|
-
let hasCompoundSelector = true;
|
|
2880
|
-
curr = curr.slice(match[0].length);
|
|
2881
|
-
while (curr.length > 0) {
|
|
2882
|
-
if (curr[0] == ' ') {
|
|
2883
|
-
hasCompoundSelector = false;
|
|
2884
|
-
curr.unshift('&');
|
|
2885
|
-
continue;
|
|
3394
|
+
while (value = next()) {
|
|
3395
|
+
if (ind >= iterator.length) {
|
|
3396
|
+
if (buffer.length > 0) {
|
|
3397
|
+
yield pushToken(buffer);
|
|
3398
|
+
buffer = '';
|
|
2886
3399
|
}
|
|
2887
3400
|
break;
|
|
2888
3401
|
}
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
3402
|
+
if (isWhiteSpace(value.charCodeAt(0))) {
|
|
3403
|
+
if (buffer.length > 0) {
|
|
3404
|
+
yield pushToken(buffer);
|
|
3405
|
+
buffer = '';
|
|
3406
|
+
}
|
|
3407
|
+
while (value = next()) {
|
|
3408
|
+
if (ind >= iterator.length) {
|
|
3409
|
+
break;
|
|
3410
|
+
}
|
|
3411
|
+
if (!isWhiteSpace(value.charCodeAt(0))) {
|
|
3412
|
+
break;
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
yield pushToken('', 'Whitespace');
|
|
3416
|
+
buffer = '';
|
|
3417
|
+
if (ind >= iterator.length) {
|
|
3418
|
+
break;
|
|
3419
|
+
}
|
|
2898
3420
|
}
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
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
|
+
}
|
|
2906
3430
|
}
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
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;
|
|
3449
|
+
continue;
|
|
3450
|
+
}
|
|
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
|
+
}
|
|
3464
|
+
}
|
|
3465
|
+
else {
|
|
3466
|
+
buffer += value;
|
|
3467
|
+
}
|
|
2910
3468
|
}
|
|
2911
|
-
inFunction++;
|
|
2912
3469
|
}
|
|
2913
|
-
|
|
2914
|
-
|
|
3470
|
+
break;
|
|
3471
|
+
case '<':
|
|
3472
|
+
if (buffer.length > 0) {
|
|
3473
|
+
yield pushToken(buffer);
|
|
3474
|
+
buffer = '';
|
|
2915
3475
|
}
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
acc.push([]);
|
|
3476
|
+
buffer += value;
|
|
3477
|
+
value = next();
|
|
3478
|
+
if (ind >= iterator.length) {
|
|
3479
|
+
break;
|
|
2921
3480
|
}
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
3481
|
+
if (peek(3) == '!--') {
|
|
3482
|
+
while (value = next()) {
|
|
3483
|
+
if (ind >= iterator.length) {
|
|
3484
|
+
break;
|
|
3485
|
+
}
|
|
3486
|
+
buffer += value;
|
|
3487
|
+
if (value == '>' && prev(2) == '--') {
|
|
3488
|
+
yield pushToken(buffer, 'CDOCOMM');
|
|
3489
|
+
buffer = '';
|
|
3490
|
+
break;
|
|
3491
|
+
}
|
|
2933
3492
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
// @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
|
|
2940
|
-
acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
|
|
2941
|
-
return acc;
|
|
2942
|
-
}
|
|
2943
|
-
// @ts-ignore
|
|
2944
|
-
selector1 = selector1.reduce(reduce, []);
|
|
2945
|
-
// @ts-ignore
|
|
2946
|
-
selector2 = selector2.reduce(reduce, []);
|
|
2947
|
-
return selector1 == null || selector2 == null ? null : {
|
|
2948
|
-
eq: eq(selector1, selector2),
|
|
2949
|
-
match,
|
|
2950
|
-
selector1,
|
|
2951
|
-
selector2
|
|
2952
|
-
};
|
|
2953
|
-
}
|
|
2954
|
-
function reduceSelector(selector) {
|
|
2955
|
-
if (selector.length == 0) {
|
|
2956
|
-
return null;
|
|
2957
|
-
}
|
|
2958
|
-
const optimized = [];
|
|
2959
|
-
const k = selector.reduce((acc, curr) => acc == 0 ? curr.length : (curr.length == 0 ? acc : Math.min(acc, curr.length)), 0);
|
|
2960
|
-
let i = 0;
|
|
2961
|
-
let j;
|
|
2962
|
-
let match;
|
|
2963
|
-
for (; i < k; i++) {
|
|
2964
|
-
const item = selector[0][i];
|
|
2965
|
-
match = true;
|
|
2966
|
-
for (j = 1; j < selector.length; j++) {
|
|
2967
|
-
if (item != selector[j][i]) {
|
|
2968
|
-
match = false;
|
|
3493
|
+
}
|
|
3494
|
+
if (ind >= iterator.length) {
|
|
3495
|
+
yield pushToken(buffer, 'BADCDO');
|
|
3496
|
+
buffer = '';
|
|
3497
|
+
}
|
|
2969
3498
|
break;
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
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;
|
|
3507
|
+
}
|
|
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 = '';
|
|
3519
|
+
}
|
|
3520
|
+
buffer += value;
|
|
3521
|
+
value = next();
|
|
3522
|
+
if (ind >= iterator.length) {
|
|
3523
|
+
yield pushToken(buffer);
|
|
3524
|
+
buffer = '';
|
|
3525
|
+
break;
|
|
3526
|
+
}
|
|
3527
|
+
if (value == '=') {
|
|
3528
|
+
buffer += value;
|
|
3529
|
+
yield pushToken(buffer, buffer[0] == '~' ? 'Includes' : 'Dash-matches');
|
|
3530
|
+
buffer = '';
|
|
3531
|
+
break;
|
|
3532
|
+
}
|
|
3533
|
+
yield pushToken(buffer);
|
|
3534
|
+
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
3535
|
+
value = next();
|
|
3536
|
+
}
|
|
3537
|
+
buffer = value;
|
|
3538
|
+
break;
|
|
3539
|
+
case '>':
|
|
3540
|
+
if (buffer !== '') {
|
|
3541
|
+
yield pushToken(buffer);
|
|
3542
|
+
buffer = '';
|
|
3543
|
+
}
|
|
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;
|
|
3553
|
+
}
|
|
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();
|
|
3575
|
+
}
|
|
3576
|
+
break;
|
|
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');
|
|
3587
|
+
break;
|
|
3588
|
+
}
|
|
3589
|
+
buffer += value;
|
|
3024
3590
|
// @ts-ignore
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
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;
|
|
3607
|
+
}
|
|
3608
|
+
else {
|
|
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 = '';
|
|
3661
|
+
}
|
|
3662
|
+
break;
|
|
3663
|
+
}
|
|
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 = '';
|
|
3688
|
+
break;
|
|
3689
|
+
}
|
|
3690
|
+
buffer = '!';
|
|
3691
|
+
break;
|
|
3692
|
+
default:
|
|
3693
|
+
buffer += value;
|
|
3694
|
+
break;
|
|
3044
3695
|
}
|
|
3045
3696
|
}
|
|
3046
|
-
|
|
3047
|
-
|
|
3697
|
+
if (buffer.length > 0) {
|
|
3698
|
+
yield pushToken(buffer);
|
|
3699
|
+
}
|
|
3048
3700
|
}
|
|
3049
3701
|
|
|
3050
3702
|
const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
|
|
3051
3703
|
const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
|
|
3704
|
+
/**
|
|
3705
|
+
*
|
|
3706
|
+
* @param iterator
|
|
3707
|
+
* @param opt
|
|
3708
|
+
*/
|
|
3052
3709
|
async function parse$1(iterator, opt = {}) {
|
|
3053
3710
|
const errors = [];
|
|
3054
3711
|
const options = {
|
|
3055
3712
|
src: '',
|
|
3056
3713
|
sourcemap: false,
|
|
3057
|
-
|
|
3714
|
+
minify: true,
|
|
3058
3715
|
nestingRules: false,
|
|
3059
3716
|
resolveImport: false,
|
|
3060
3717
|
resolveUrls: false,
|
|
@@ -3064,208 +3721,64 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3064
3721
|
if (options.resolveImport) {
|
|
3065
3722
|
options.resolveUrls = true;
|
|
3066
3723
|
}
|
|
3067
|
-
let ind = -1;
|
|
3068
|
-
let lin = 1;
|
|
3069
|
-
let col = 0;
|
|
3070
|
-
const tokens = [];
|
|
3071
3724
|
const src = options.src;
|
|
3072
3725
|
const stack = [];
|
|
3073
3726
|
const ast = {
|
|
3074
3727
|
typ: "StyleSheet",
|
|
3075
3728
|
chi: []
|
|
3076
3729
|
};
|
|
3077
|
-
|
|
3078
|
-
ind: Math.max(ind, 0),
|
|
3079
|
-
lin: lin,
|
|
3080
|
-
col: Math.max(col, 1)
|
|
3081
|
-
};
|
|
3082
|
-
let value;
|
|
3083
|
-
let buffer = '';
|
|
3084
|
-
let total = iterator.length;
|
|
3085
|
-
let bytesIn = total;
|
|
3730
|
+
let tokens = [];
|
|
3086
3731
|
let map = new Map;
|
|
3732
|
+
let bytesIn = 0;
|
|
3087
3733
|
let context = ast;
|
|
3088
3734
|
if (options.sourcemap) {
|
|
3089
3735
|
ast.loc = {
|
|
3090
3736
|
sta: {
|
|
3091
|
-
ind:
|
|
3092
|
-
lin:
|
|
3093
|
-
col:
|
|
3737
|
+
ind: 0,
|
|
3738
|
+
lin: 1,
|
|
3739
|
+
col: 1
|
|
3094
3740
|
},
|
|
3095
3741
|
src: ''
|
|
3096
3742
|
};
|
|
3097
3743
|
}
|
|
3098
|
-
function
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
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
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
else if (tokens[i].typ != 'Whitespace') {
|
|
3762
|
+
break;
|
|
3763
|
+
}
|
|
3116
3764
|
}
|
|
3117
|
-
|
|
3118
|
-
|
|
3765
|
+
tokens = tokens.slice(i);
|
|
3766
|
+
if (tokens.length == 0) {
|
|
3767
|
+
return null;
|
|
3119
3768
|
}
|
|
3120
|
-
|
|
3121
|
-
|
|
3769
|
+
let delim = tokens.at(-1);
|
|
3770
|
+
if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
|
|
3771
|
+
tokens.pop();
|
|
3122
3772
|
}
|
|
3123
|
-
|
|
3124
|
-
|
|
3773
|
+
else {
|
|
3774
|
+
delim = { typ: 'Semi-colon' };
|
|
3125
3775
|
}
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
val: val.slice(0, -1),
|
|
3130
|
-
chi: []
|
|
3131
|
-
}
|
|
3132
|
-
: {
|
|
3133
|
-
typ: 'Pseudo-class',
|
|
3134
|
-
val
|
|
3135
|
-
};
|
|
3776
|
+
// @ts-ignore
|
|
3777
|
+
while (['Whitespace', 'Bad-string', 'Bad-comment'].includes(tokens.at(-1)?.typ)) {
|
|
3778
|
+
tokens.pop();
|
|
3136
3779
|
}
|
|
3137
|
-
if (
|
|
3138
|
-
return
|
|
3139
|
-
typ: 'At-rule',
|
|
3140
|
-
val: val.slice(1)
|
|
3141
|
-
};
|
|
3142
|
-
}
|
|
3143
|
-
if (isFunction(val)) {
|
|
3144
|
-
val = val.slice(0, -1);
|
|
3145
|
-
return {
|
|
3146
|
-
typ: val == 'url' ? 'UrlFunc' : 'Func',
|
|
3147
|
-
val,
|
|
3148
|
-
chi: []
|
|
3149
|
-
};
|
|
3150
|
-
}
|
|
3151
|
-
if (isNumber(val)) {
|
|
3152
|
-
return {
|
|
3153
|
-
typ: 'Number',
|
|
3154
|
-
val
|
|
3155
|
-
};
|
|
3156
|
-
}
|
|
3157
|
-
if (isDimension(val)) {
|
|
3158
|
-
return parseDimension(val);
|
|
3159
|
-
}
|
|
3160
|
-
if (isPercentage(val)) {
|
|
3161
|
-
return {
|
|
3162
|
-
typ: 'Perc',
|
|
3163
|
-
val: val.slice(0, -1)
|
|
3164
|
-
};
|
|
3165
|
-
}
|
|
3166
|
-
if (val == 'currentColor') {
|
|
3167
|
-
return {
|
|
3168
|
-
typ: 'Color',
|
|
3169
|
-
val,
|
|
3170
|
-
kin: 'lit'
|
|
3171
|
-
};
|
|
3172
|
-
}
|
|
3173
|
-
if (isIdent(val)) {
|
|
3174
|
-
return {
|
|
3175
|
-
typ: 'Iden',
|
|
3176
|
-
val
|
|
3177
|
-
};
|
|
3178
|
-
}
|
|
3179
|
-
if (val.charAt(0) == '#' && isHash(val)) {
|
|
3180
|
-
return {
|
|
3181
|
-
typ: 'Hash',
|
|
3182
|
-
val
|
|
3183
|
-
};
|
|
3184
|
-
}
|
|
3185
|
-
if ('"\''.includes(val.charAt(0))) {
|
|
3186
|
-
return {
|
|
3187
|
-
typ: 'Unclosed-string',
|
|
3188
|
-
val
|
|
3189
|
-
};
|
|
3190
|
-
}
|
|
3191
|
-
return {
|
|
3192
|
-
typ: 'Literal',
|
|
3193
|
-
val
|
|
3194
|
-
};
|
|
3195
|
-
}
|
|
3196
|
-
// consume and throw away
|
|
3197
|
-
function consume(open, close) {
|
|
3198
|
-
let count = 1;
|
|
3199
|
-
let chr;
|
|
3200
|
-
while (true) {
|
|
3201
|
-
chr = next();
|
|
3202
|
-
if (chr == '\\') {
|
|
3203
|
-
if (peek() === '') {
|
|
3204
|
-
break;
|
|
3205
|
-
}
|
|
3206
|
-
continue;
|
|
3207
|
-
}
|
|
3208
|
-
else if (chr == '/' && peek() == '*') {
|
|
3209
|
-
next();
|
|
3210
|
-
while (true) {
|
|
3211
|
-
chr = next();
|
|
3212
|
-
if (chr === '') {
|
|
3213
|
-
break;
|
|
3214
|
-
}
|
|
3215
|
-
if (chr == '*' && peek() == '/') {
|
|
3216
|
-
next();
|
|
3217
|
-
break;
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
|
-
}
|
|
3221
|
-
else if (chr == close) {
|
|
3222
|
-
count--;
|
|
3223
|
-
}
|
|
3224
|
-
else if (chr == open) {
|
|
3225
|
-
count++;
|
|
3226
|
-
}
|
|
3227
|
-
if (chr === '' || count == 0) {
|
|
3228
|
-
break;
|
|
3229
|
-
}
|
|
3230
|
-
}
|
|
3231
|
-
}
|
|
3232
|
-
async function parseNode(tokens) {
|
|
3233
|
-
let i;
|
|
3234
|
-
let loc;
|
|
3235
|
-
for (i = 0; i < tokens.length; i++) {
|
|
3236
|
-
if (tokens[i].typ == 'Comment') {
|
|
3237
|
-
// @ts-ignore
|
|
3238
|
-
context.chi.push(tokens[i]);
|
|
3239
|
-
const position = map.get(tokens[i]);
|
|
3240
|
-
loc = {
|
|
3241
|
-
sta: position,
|
|
3242
|
-
src
|
|
3243
|
-
};
|
|
3244
|
-
if (options.sourcemap) {
|
|
3245
|
-
tokens[i].loc = loc;
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
else if (tokens[i].typ != 'Whitespace') {
|
|
3249
|
-
break;
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
tokens = tokens.slice(i);
|
|
3253
|
-
if (tokens.length == 0) {
|
|
3254
|
-
return null;
|
|
3255
|
-
}
|
|
3256
|
-
let delim = tokens.at(-1);
|
|
3257
|
-
if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
|
|
3258
|
-
tokens.pop();
|
|
3259
|
-
}
|
|
3260
|
-
else {
|
|
3261
|
-
delim = { typ: 'Semi-colon' };
|
|
3262
|
-
}
|
|
3263
|
-
// @ts-ignore
|
|
3264
|
-
while (['Whitespace', 'Bad-string', 'Bad-comment'].includes(tokens.at(-1)?.typ)) {
|
|
3265
|
-
tokens.pop();
|
|
3266
|
-
}
|
|
3267
|
-
if (tokens.length == 0) {
|
|
3268
|
-
return null;
|
|
3780
|
+
if (tokens.length == 0) {
|
|
3781
|
+
return null;
|
|
3269
3782
|
}
|
|
3270
3783
|
if (tokens[0]?.typ == 'At-rule') {
|
|
3271
3784
|
const atRule = tokens.shift();
|
|
@@ -3327,7 +3840,7 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3327
3840
|
// @ts-ignore
|
|
3328
3841
|
const root = await options.load(url, options.src).then((src) => {
|
|
3329
3842
|
return parse$1(src, Object.assign({}, options, {
|
|
3330
|
-
|
|
3843
|
+
minify: false,
|
|
3331
3844
|
// @ts-ignore
|
|
3332
3845
|
src: options.resolve(url, options.src).absolute
|
|
3333
3846
|
}));
|
|
@@ -3378,626 +3891,336 @@ async function parse$1(iterator, opt = {}) {
|
|
|
3378
3891
|
// rule
|
|
3379
3892
|
if (delim.typ == 'Block-start') {
|
|
3380
3893
|
const position = map.get(tokens[0]);
|
|
3381
|
-
if (context.typ == 'Rule') {
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
}
|
|
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
|
+
// }
|
|
3387
3901
|
const uniq = new Map;
|
|
3388
|
-
parseTokens(tokens,
|
|
3902
|
+
parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
|
3389
3903
|
if (curr.typ == 'Whitespace') {
|
|
3390
|
-
if (array[index - 1]?.
|
|
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)) {
|
|
3391
3908
|
return acc;
|
|
3392
3909
|
}
|
|
3393
3910
|
}
|
|
3394
|
-
let t = renderToken(curr, {
|
|
3911
|
+
let t = renderToken(curr, { minify: true });
|
|
3395
3912
|
if (t == ',') {
|
|
3396
3913
|
acc.push([]);
|
|
3397
3914
|
}
|
|
3398
|
-
else {
|
|
3399
|
-
acc[acc.length - 1].push(t);
|
|
3400
|
-
}
|
|
3401
|
-
return acc;
|
|
3402
|
-
}, [[]]).reduce((acc, curr) => {
|
|
3403
|
-
acc.set(curr.join(''), curr);
|
|
3404
|
-
return acc;
|
|
3405
|
-
}, uniq);
|
|
3406
|
-
const node = {
|
|
3407
|
-
typ: 'Rule',
|
|
3408
|
-
// @ts-ignore
|
|
3409
|
-
sel: [...uniq.keys()].join(','),
|
|
3410
|
-
chi: []
|
|
3411
|
-
};
|
|
3412
|
-
let raw = [...uniq.values()];
|
|
3413
|
-
Object.defineProperty(node, 'raw', { enumerable: false, writable: true, value: raw });
|
|
3414
|
-
loc = {
|
|
3415
|
-
sta: position,
|
|
3416
|
-
src
|
|
3417
|
-
};
|
|
3418
|
-
if (options.sourcemap) {
|
|
3419
|
-
node.loc = loc;
|
|
3420
|
-
}
|
|
3421
|
-
// @ts-ignore
|
|
3422
|
-
context.chi.push(node);
|
|
3423
|
-
return node;
|
|
3424
|
-
}
|
|
3425
|
-
else {
|
|
3426
|
-
// declaration
|
|
3427
|
-
// @ts-ignore
|
|
3428
|
-
let name = null;
|
|
3429
|
-
// @ts-ignore
|
|
3430
|
-
let value = null;
|
|
3431
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
3432
|
-
if (tokens[i].typ == 'Comment') {
|
|
3433
|
-
continue;
|
|
3434
|
-
}
|
|
3435
|
-
if (tokens[i].typ == 'Colon') {
|
|
3436
|
-
name = tokens.slice(0, i);
|
|
3437
|
-
value = parseTokens(tokens.slice(i + 1), 'Declaration', {
|
|
3438
|
-
parseColor: true,
|
|
3439
|
-
src: options.src,
|
|
3440
|
-
resolveUrls: options.resolveUrls,
|
|
3441
|
-
resolve: options.resolve,
|
|
3442
|
-
cwd: options.cwd
|
|
3443
|
-
});
|
|
3444
|
-
}
|
|
3445
|
-
}
|
|
3446
|
-
if (name == null) {
|
|
3447
|
-
name = tokens;
|
|
3448
|
-
}
|
|
3449
|
-
const position = map.get(name[0]);
|
|
3450
|
-
if (name.length > 0) {
|
|
3451
|
-
for (let i = 1; i < name.length; i++) {
|
|
3452
|
-
if (name[i].typ != 'Whitespace' && name[i].typ != 'Comment') {
|
|
3453
|
-
errors.push({
|
|
3454
|
-
action: 'drop',
|
|
3455
|
-
message: 'invalid declaration',
|
|
3456
|
-
location: { src, ...position }
|
|
3457
|
-
});
|
|
3458
|
-
return null;
|
|
3459
|
-
}
|
|
3460
|
-
}
|
|
3461
|
-
}
|
|
3462
|
-
if (value == null) {
|
|
3463
|
-
errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
|
|
3464
|
-
return null;
|
|
3465
|
-
}
|
|
3466
|
-
if (value.length == 0) {
|
|
3467
|
-
errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
|
|
3468
|
-
return null;
|
|
3469
|
-
}
|
|
3470
|
-
const node = {
|
|
3471
|
-
typ: 'Declaration',
|
|
3472
|
-
// @ts-ignore
|
|
3473
|
-
nam: renderToken(name.shift(), { removeComments: true }),
|
|
3474
|
-
// @ts-ignore
|
|
3475
|
-
val: value
|
|
3476
|
-
};
|
|
3477
|
-
while (node.val[0]?.typ == 'Whitespace') {
|
|
3478
|
-
node.val.shift();
|
|
3479
|
-
}
|
|
3480
|
-
if (node.val.length == 0) {
|
|
3481
|
-
errors.push({ action: 'drop', message: 'invalid declaration', location: { src, ...position } });
|
|
3482
|
-
return null;
|
|
3483
|
-
}
|
|
3484
|
-
// @ts-ignore
|
|
3485
|
-
context.chi.push(node);
|
|
3486
|
-
return null;
|
|
3487
|
-
}
|
|
3488
|
-
}
|
|
3489
|
-
}
|
|
3490
|
-
function peek(count = 1) {
|
|
3491
|
-
if (count == 1) {
|
|
3492
|
-
return iterator.charAt(ind + 1);
|
|
3493
|
-
}
|
|
3494
|
-
return iterator.slice(ind + 1, ind + count + 1);
|
|
3495
|
-
}
|
|
3496
|
-
function prev(count = 1) {
|
|
3497
|
-
if (count == 1) {
|
|
3498
|
-
return ind == 0 ? '' : iterator.charAt(ind - 1);
|
|
3499
|
-
}
|
|
3500
|
-
return iterator.slice(ind - 1 - count, ind - 1);
|
|
3501
|
-
}
|
|
3502
|
-
function next(count = 1) {
|
|
3503
|
-
let char = '';
|
|
3504
|
-
while (count-- > 0 && ind < total) {
|
|
3505
|
-
const codepoint = iterator.charCodeAt(++ind);
|
|
3506
|
-
if (isNaN(codepoint)) {
|
|
3507
|
-
return char;
|
|
3508
|
-
}
|
|
3509
|
-
char += iterator.charAt(ind);
|
|
3510
|
-
if (isNewLine(codepoint)) {
|
|
3511
|
-
lin++;
|
|
3512
|
-
col = 0;
|
|
3513
|
-
}
|
|
3514
|
-
else {
|
|
3515
|
-
col++;
|
|
3516
|
-
}
|
|
3517
|
-
}
|
|
3518
|
-
return char;
|
|
3519
|
-
}
|
|
3520
|
-
function pushToken(token) {
|
|
3521
|
-
tokens.push(token);
|
|
3522
|
-
map.set(token, { ...position });
|
|
3523
|
-
position.ind = ind;
|
|
3524
|
-
position.lin = lin;
|
|
3525
|
-
position.col = col == 0 ? 1 : col;
|
|
3526
|
-
}
|
|
3527
|
-
function consumeWhiteSpace() {
|
|
3528
|
-
let count = 0;
|
|
3529
|
-
while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
|
|
3530
|
-
count++;
|
|
3531
|
-
}
|
|
3532
|
-
next(count);
|
|
3533
|
-
return count;
|
|
3534
|
-
}
|
|
3535
|
-
function consumeString(quoteStr) {
|
|
3536
|
-
const quote = quoteStr;
|
|
3537
|
-
let value;
|
|
3538
|
-
let hasNewLine = false;
|
|
3539
|
-
if (buffer.length > 0) {
|
|
3540
|
-
pushToken(getType(buffer));
|
|
3541
|
-
buffer = '';
|
|
3542
|
-
}
|
|
3543
|
-
buffer += quoteStr;
|
|
3544
|
-
while (ind < total) {
|
|
3545
|
-
value = peek();
|
|
3546
|
-
if (ind >= total) {
|
|
3547
|
-
pushToken({ typ: hasNewLine ? 'Bad-string' : 'Unclosed-string', val: buffer });
|
|
3548
|
-
break;
|
|
3549
|
-
}
|
|
3550
|
-
if (value == '\\') {
|
|
3551
|
-
const sequence = peek(6);
|
|
3552
|
-
let escapeSequence = '';
|
|
3553
|
-
let codepoint;
|
|
3554
|
-
let i;
|
|
3555
|
-
for (i = 1; i < sequence.length; i++) {
|
|
3556
|
-
codepoint = sequence.charCodeAt(i);
|
|
3557
|
-
if (codepoint == 0x20 ||
|
|
3558
|
-
(codepoint >= 0x61 && codepoint <= 0x66) ||
|
|
3559
|
-
(codepoint >= 0x41 && codepoint <= 0x46) ||
|
|
3560
|
-
(codepoint >= 0x30 && codepoint <= 0x39)) {
|
|
3561
|
-
escapeSequence += sequence[i];
|
|
3562
|
-
if (codepoint == 0x20) {
|
|
3563
|
-
break;
|
|
3564
|
-
}
|
|
3565
|
-
continue;
|
|
3566
|
-
}
|
|
3567
|
-
break;
|
|
3568
|
-
}
|
|
3569
|
-
// not hex or new line
|
|
3570
|
-
// @ts-ignore
|
|
3571
|
-
if (i == 1 && !isNewLine(codepoint)) {
|
|
3572
|
-
buffer += sequence[i];
|
|
3573
|
-
next(2);
|
|
3574
|
-
continue;
|
|
3575
|
-
}
|
|
3576
|
-
if (escapeSequence.trimEnd().length > 0) {
|
|
3577
|
-
const codepoint = Number(`0x${escapeSequence.trimEnd()}`);
|
|
3578
|
-
if (codepoint == 0 ||
|
|
3579
|
-
// leading surrogate
|
|
3580
|
-
(0xD800 <= codepoint && codepoint <= 0xDBFF) ||
|
|
3581
|
-
// trailing surrogate
|
|
3582
|
-
(0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
|
|
3583
|
-
buffer += String.fromCodePoint(0xFFFD);
|
|
3584
|
-
}
|
|
3585
|
-
else {
|
|
3586
|
-
buffer += String.fromCodePoint(codepoint);
|
|
3587
|
-
}
|
|
3588
|
-
next(escapeSequence.length + 1);
|
|
3589
|
-
continue;
|
|
3590
|
-
}
|
|
3591
|
-
// buffer += value;
|
|
3592
|
-
if (ind >= total) {
|
|
3593
|
-
// drop '\\' at the end
|
|
3594
|
-
pushToken(getType(buffer));
|
|
3595
|
-
break;
|
|
3596
|
-
}
|
|
3597
|
-
buffer += next(2);
|
|
3598
|
-
continue;
|
|
3599
|
-
}
|
|
3600
|
-
if (value == quote) {
|
|
3601
|
-
buffer += value;
|
|
3602
|
-
pushToken({ typ: hasNewLine ? 'Bad-string' : 'String', val: buffer });
|
|
3603
|
-
next();
|
|
3604
|
-
// i += value.length;
|
|
3605
|
-
buffer = '';
|
|
3606
|
-
break;
|
|
3607
|
-
}
|
|
3608
|
-
if (isNewLine(value.charCodeAt(0))) {
|
|
3609
|
-
hasNewLine = true;
|
|
3610
|
-
}
|
|
3611
|
-
if (hasNewLine && value == ';') {
|
|
3612
|
-
pushToken({ typ: 'Bad-string', val: buffer });
|
|
3613
|
-
buffer = '';
|
|
3614
|
-
break;
|
|
3615
|
-
}
|
|
3616
|
-
buffer += value;
|
|
3617
|
-
// i += value.length;
|
|
3618
|
-
next();
|
|
3619
|
-
}
|
|
3620
|
-
}
|
|
3621
|
-
while (ind < total) {
|
|
3622
|
-
value = next();
|
|
3623
|
-
if (ind >= total) {
|
|
3624
|
-
if (buffer.length > 0) {
|
|
3625
|
-
pushToken(getType(buffer));
|
|
3626
|
-
buffer = '';
|
|
3627
|
-
}
|
|
3628
|
-
break;
|
|
3629
|
-
}
|
|
3630
|
-
if (isWhiteSpace(value.charCodeAt(0))) {
|
|
3631
|
-
if (buffer.length > 0) {
|
|
3632
|
-
pushToken(getType(buffer));
|
|
3633
|
-
buffer = '';
|
|
3634
|
-
}
|
|
3635
|
-
while (ind < total) {
|
|
3636
|
-
value = next();
|
|
3637
|
-
if (ind >= total) {
|
|
3638
|
-
break;
|
|
3639
|
-
}
|
|
3640
|
-
if (!isWhiteSpace(value.charCodeAt(0))) {
|
|
3641
|
-
break;
|
|
3642
|
-
}
|
|
3643
|
-
}
|
|
3644
|
-
pushToken({ typ: 'Whitespace' });
|
|
3645
|
-
buffer = '';
|
|
3646
|
-
if (ind >= total) {
|
|
3647
|
-
break;
|
|
3648
|
-
}
|
|
3649
|
-
}
|
|
3650
|
-
switch (value) {
|
|
3651
|
-
case '/':
|
|
3652
|
-
if (buffer.length > 0 && tokens.at(-1)?.typ == 'Whitespace') {
|
|
3653
|
-
pushToken(getType(buffer));
|
|
3654
|
-
buffer = '';
|
|
3655
|
-
if (peek() != '*') {
|
|
3656
|
-
pushToken(getType(value));
|
|
3657
|
-
break;
|
|
3658
|
-
}
|
|
3659
|
-
}
|
|
3660
|
-
buffer += value;
|
|
3661
|
-
if (peek() == '*') {
|
|
3662
|
-
buffer += '*';
|
|
3663
|
-
// i++;
|
|
3664
|
-
next();
|
|
3665
|
-
while (ind < total) {
|
|
3666
|
-
value = next();
|
|
3667
|
-
if (ind >= total) {
|
|
3668
|
-
pushToken({
|
|
3669
|
-
typ: 'Bad-comment', val: buffer
|
|
3670
|
-
});
|
|
3671
|
-
break;
|
|
3672
|
-
}
|
|
3673
|
-
if (value == '\\') {
|
|
3674
|
-
buffer += value;
|
|
3675
|
-
value = next();
|
|
3676
|
-
if (ind >= total) {
|
|
3677
|
-
pushToken({
|
|
3678
|
-
typ: 'Bad-comment',
|
|
3679
|
-
val: buffer
|
|
3680
|
-
});
|
|
3681
|
-
break;
|
|
3682
|
-
}
|
|
3683
|
-
buffer += value;
|
|
3684
|
-
continue;
|
|
3685
|
-
}
|
|
3686
|
-
if (value == '*') {
|
|
3687
|
-
buffer += value;
|
|
3688
|
-
value = next();
|
|
3689
|
-
if (ind >= total) {
|
|
3690
|
-
pushToken({
|
|
3691
|
-
typ: 'Bad-comment', val: buffer
|
|
3692
|
-
});
|
|
3693
|
-
break;
|
|
3694
|
-
}
|
|
3695
|
-
buffer += value;
|
|
3696
|
-
if (value == '/') {
|
|
3697
|
-
pushToken({ typ: 'Comment', val: buffer });
|
|
3698
|
-
buffer = '';
|
|
3699
|
-
break;
|
|
3700
|
-
}
|
|
3701
|
-
}
|
|
3702
|
-
else {
|
|
3703
|
-
buffer += value;
|
|
3704
|
-
}
|
|
3705
|
-
}
|
|
3706
|
-
}
|
|
3707
|
-
break;
|
|
3708
|
-
case '<':
|
|
3709
|
-
if (buffer.length > 0) {
|
|
3710
|
-
pushToken(getType(buffer));
|
|
3711
|
-
buffer = '';
|
|
3712
|
-
}
|
|
3713
|
-
buffer += value;
|
|
3714
|
-
value = next();
|
|
3715
|
-
if (ind >= total) {
|
|
3716
|
-
break;
|
|
3717
|
-
}
|
|
3718
|
-
if (peek(3) == '!--') {
|
|
3719
|
-
while (ind < total) {
|
|
3720
|
-
value = next();
|
|
3721
|
-
if (ind >= total) {
|
|
3722
|
-
break;
|
|
3723
|
-
}
|
|
3724
|
-
buffer += value;
|
|
3725
|
-
if (value == '>' && prev(2) == '--') {
|
|
3726
|
-
pushToken({
|
|
3727
|
-
typ: 'CDOCOMM',
|
|
3728
|
-
val: buffer
|
|
3729
|
-
});
|
|
3730
|
-
buffer = '';
|
|
3731
|
-
break;
|
|
3732
|
-
}
|
|
3733
|
-
}
|
|
3734
|
-
}
|
|
3735
|
-
if (ind >= total) {
|
|
3736
|
-
pushToken({ typ: 'BADCDO', val: buffer });
|
|
3737
|
-
buffer = '';
|
|
3738
|
-
}
|
|
3739
|
-
break;
|
|
3740
|
-
case '\\':
|
|
3741
|
-
value = next();
|
|
3742
|
-
// EOF
|
|
3743
|
-
if (ind + 1 >= total) {
|
|
3744
|
-
// end of stream ignore \\
|
|
3745
|
-
pushToken(getType(buffer));
|
|
3746
|
-
buffer = '';
|
|
3747
|
-
break;
|
|
3748
|
-
}
|
|
3749
|
-
buffer += value;
|
|
3750
|
-
break;
|
|
3751
|
-
case '"':
|
|
3752
|
-
case "'":
|
|
3753
|
-
consumeString(value);
|
|
3754
|
-
break;
|
|
3755
|
-
case '~':
|
|
3756
|
-
case '|':
|
|
3757
|
-
if (tokens.at(-1)?.typ == 'Whitespace') {
|
|
3758
|
-
tokens.pop();
|
|
3759
|
-
}
|
|
3760
|
-
if (buffer.length > 0) {
|
|
3761
|
-
pushToken(getType(buffer));
|
|
3762
|
-
buffer = '';
|
|
3763
|
-
}
|
|
3764
|
-
buffer += value;
|
|
3765
|
-
value = next();
|
|
3766
|
-
if (ind >= total) {
|
|
3767
|
-
pushToken(getType(buffer));
|
|
3768
|
-
buffer = '';
|
|
3769
|
-
break;
|
|
3770
|
-
}
|
|
3771
|
-
if (value == '=') {
|
|
3772
|
-
buffer += value;
|
|
3773
|
-
pushToken({
|
|
3774
|
-
typ: buffer[0] == '~' ? 'Includes' : 'Dash-matches',
|
|
3775
|
-
val: buffer
|
|
3776
|
-
});
|
|
3777
|
-
buffer = '';
|
|
3778
|
-
break;
|
|
3779
|
-
}
|
|
3780
|
-
pushToken(getType(buffer));
|
|
3781
|
-
while (isWhiteSpace(value.charCodeAt(0))) {
|
|
3782
|
-
value = next();
|
|
3783
|
-
}
|
|
3784
|
-
buffer = value;
|
|
3785
|
-
break;
|
|
3786
|
-
case '>':
|
|
3787
|
-
if (buffer !== '') {
|
|
3788
|
-
pushToken(getType(buffer));
|
|
3789
|
-
buffer = '';
|
|
3790
|
-
}
|
|
3791
|
-
if (tokens[tokens.length - 1]?.typ == 'Whitespace') {
|
|
3792
|
-
tokens.pop();
|
|
3793
|
-
}
|
|
3794
|
-
pushToken({ typ: 'Gt' });
|
|
3795
|
-
consumeWhiteSpace();
|
|
3796
|
-
break;
|
|
3797
|
-
case '.':
|
|
3798
|
-
const codepoint = peek().charCodeAt(0);
|
|
3799
|
-
if (!isDigit(codepoint) && buffer !== '') {
|
|
3800
|
-
pushToken(getType(buffer));
|
|
3801
|
-
buffer = value;
|
|
3802
|
-
break;
|
|
3803
|
-
}
|
|
3804
|
-
buffer += value;
|
|
3805
|
-
break;
|
|
3806
|
-
case '+':
|
|
3807
|
-
case ':':
|
|
3808
|
-
case ',':
|
|
3809
|
-
case '=':
|
|
3810
|
-
if (buffer.length > 0) {
|
|
3811
|
-
pushToken(getType(buffer));
|
|
3812
|
-
buffer = '';
|
|
3813
|
-
}
|
|
3814
|
-
if (value == ':' && ':' == peek()) {
|
|
3815
|
-
buffer += value + next();
|
|
3816
|
-
break;
|
|
3817
|
-
}
|
|
3818
|
-
pushToken(getType(value));
|
|
3819
|
-
buffer = '';
|
|
3820
|
-
if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
|
|
3821
|
-
pushToken(getType(next()));
|
|
3822
|
-
}
|
|
3823
|
-
while (isWhiteSpace(peek().charCodeAt(0))) {
|
|
3824
|
-
next();
|
|
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;
|
|
3825
3937
|
}
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
|
|
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
|
+
}
|
|
3831
3962
|
}
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
case '(':
|
|
3835
|
-
if (buffer.length == 0) {
|
|
3836
|
-
pushToken({ typ: 'Start-parens' });
|
|
3963
|
+
if (name == null) {
|
|
3964
|
+
name = tokens;
|
|
3837
3965
|
}
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
whitespace += value;
|
|
3849
|
-
}
|
|
3850
|
-
if (whitespace.length > 0) {
|
|
3851
|
-
next(whitespace.length);
|
|
3852
|
-
}
|
|
3853
|
-
value = peek();
|
|
3854
|
-
if (value == '"' || value == "'") {
|
|
3855
|
-
consumeString(next());
|
|
3856
|
-
let token = tokens[tokens.length - 1];
|
|
3857
|
-
if (['String', 'Literal'].includes(token.typ) && urlTokenMatcher.test(token.val)) {
|
|
3858
|
-
if (token.val.slice(1, 6) != 'data:') {
|
|
3859
|
-
if (token.typ == 'String') {
|
|
3860
|
-
token.val = token.val.slice(1, -1);
|
|
3861
|
-
}
|
|
3862
|
-
// @ts-ignore
|
|
3863
|
-
token.typ = 'Url-token';
|
|
3864
|
-
}
|
|
3865
|
-
}
|
|
3866
|
-
break;
|
|
3867
|
-
}
|
|
3868
|
-
else {
|
|
3869
|
-
buffer = '';
|
|
3870
|
-
do {
|
|
3871
|
-
let cp = value.charCodeAt(0);
|
|
3872
|
-
// EOF -
|
|
3873
|
-
if (cp == null) {
|
|
3874
|
-
pushToken({ typ: 'Bad-url-token', val: buffer });
|
|
3875
|
-
break;
|
|
3876
|
-
}
|
|
3877
|
-
// ')'
|
|
3878
|
-
if (cp == 0x29 || cp == null) {
|
|
3879
|
-
if (buffer.length == 0) {
|
|
3880
|
-
pushToken({ typ: 'Bad-url-token', val: '' });
|
|
3881
|
-
}
|
|
3882
|
-
else {
|
|
3883
|
-
pushToken({ typ: 'Url-token', val: buffer });
|
|
3884
|
-
}
|
|
3885
|
-
if (cp != null) {
|
|
3886
|
-
pushToken(getType(next()));
|
|
3887
|
-
}
|
|
3888
|
-
break;
|
|
3889
|
-
}
|
|
3890
|
-
if (isWhiteSpace(cp)) {
|
|
3891
|
-
whitespace = next();
|
|
3892
|
-
while (true) {
|
|
3893
|
-
value = peek();
|
|
3894
|
-
cp = value.charCodeAt(0);
|
|
3895
|
-
if (isWhiteSpace(cp)) {
|
|
3896
|
-
whitespace += value;
|
|
3897
|
-
continue;
|
|
3898
|
-
}
|
|
3899
|
-
break;
|
|
3900
|
-
}
|
|
3901
|
-
if (cp == null || cp == 0x29) {
|
|
3902
|
-
continue;
|
|
3903
|
-
}
|
|
3904
|
-
// bad url token
|
|
3905
|
-
buffer += next(whitespace.length);
|
|
3906
|
-
do {
|
|
3907
|
-
value = peek();
|
|
3908
|
-
cp = value.charCodeAt(0);
|
|
3909
|
-
if (cp == null || cp == 0x29) {
|
|
3910
|
-
break;
|
|
3911
|
-
}
|
|
3912
|
-
buffer += next();
|
|
3913
|
-
} while (true);
|
|
3914
|
-
pushToken({ typ: 'Bad-url-token', val: buffer });
|
|
3915
|
-
continue;
|
|
3916
|
-
}
|
|
3917
|
-
buffer += next();
|
|
3918
|
-
value = peek();
|
|
3919
|
-
} while (true);
|
|
3920
|
-
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;
|
|
3921
3976
|
}
|
|
3922
3977
|
}
|
|
3923
3978
|
}
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
pushToken(getType(buffer));
|
|
3932
|
-
buffer = '';
|
|
3979
|
+
if (value == null) {
|
|
3980
|
+
errors.push({
|
|
3981
|
+
action: 'drop',
|
|
3982
|
+
message: 'invalid declaration',
|
|
3983
|
+
location: { src, ...position }
|
|
3984
|
+
});
|
|
3985
|
+
return null;
|
|
3933
3986
|
}
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
context = node;
|
|
3942
|
-
}
|
|
3943
|
-
else if (value == '{') {
|
|
3944
|
-
// node == null
|
|
3945
|
-
// consume and throw away until the closing '}' or EOF
|
|
3946
|
-
consume('{', '}');
|
|
3947
|
-
}
|
|
3948
|
-
tokens.length = 0;
|
|
3949
|
-
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;
|
|
3950
3994
|
}
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
const previousNode = stack.pop();
|
|
3995
|
+
const node = {
|
|
3996
|
+
typ: 'Declaration',
|
|
3954
3997
|
// @ts-ignore
|
|
3955
|
-
|
|
3998
|
+
nam: renderToken(name.shift(), { removeComments: true }),
|
|
3956
3999
|
// @ts-ignore
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
map.clear();
|
|
3962
|
-
buffer = '';
|
|
3963
|
-
}
|
|
3964
|
-
break;
|
|
3965
|
-
case '!':
|
|
3966
|
-
if (buffer.length > 0) {
|
|
3967
|
-
pushToken(getType(buffer));
|
|
3968
|
-
buffer = '';
|
|
4000
|
+
val: value
|
|
4001
|
+
};
|
|
4002
|
+
while (node.val[0]?.typ == 'Whitespace') {
|
|
4003
|
+
node.val.shift();
|
|
3969
4004
|
}
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
buffer = '';
|
|
3978
|
-
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;
|
|
3979
4012
|
}
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
break;
|
|
4013
|
+
// @ts-ignore
|
|
4014
|
+
context.chi.push(node);
|
|
4015
|
+
return null;
|
|
4016
|
+
}
|
|
3985
4017
|
}
|
|
3986
4018
|
}
|
|
3987
|
-
|
|
3988
|
-
|
|
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
|
+
}
|
|
3989
4072
|
}
|
|
3990
4073
|
if (tokens.length > 0) {
|
|
3991
4074
|
await parseNode(tokens);
|
|
3992
4075
|
}
|
|
3993
|
-
if (options.
|
|
4076
|
+
if (options.minify) {
|
|
3994
4077
|
if (ast.chi.length > 0) {
|
|
3995
|
-
|
|
4078
|
+
minify(ast, options, true);
|
|
3996
4079
|
}
|
|
3997
4080
|
}
|
|
3998
4081
|
return { ast, errors, bytesIn };
|
|
3999
4082
|
}
|
|
4000
|
-
function
|
|
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
|
+
}
|
|
4223
|
+
function parseTokens(tokens, options = {}) {
|
|
4001
4224
|
for (let i = 0; i < tokens.length; i++) {
|
|
4002
4225
|
const t = tokens[i];
|
|
4003
4226
|
if (t.typ == 'Whitespace' && ((i == 0 ||
|
|
@@ -4051,7 +4274,7 @@ function parseTokens(tokens, nodeType, options = {}) {
|
|
|
4051
4274
|
if (t.chi.length > 1) {
|
|
4052
4275
|
/*(<AttrToken>t).chi =*/
|
|
4053
4276
|
// @ts-ignore
|
|
4054
|
-
parseTokens(t.chi, t.typ
|
|
4277
|
+
parseTokens(t.chi, t.typ);
|
|
4055
4278
|
}
|
|
4056
4279
|
// @ts-ignore
|
|
4057
4280
|
t.chi.forEach(val => {
|
|
@@ -4163,8 +4386,8 @@ function parseTokens(tokens, nodeType, options = {}) {
|
|
|
4163
4386
|
// @ts-ignore
|
|
4164
4387
|
if (t.chi.length > 0) {
|
|
4165
4388
|
// @ts-ignore
|
|
4166
|
-
parseTokens(t.chi, t.typ
|
|
4167
|
-
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) {
|
|
4168
4391
|
//
|
|
4169
4392
|
const count = t.chi.filter(t => t.typ != 'Comment').length;
|
|
4170
4393
|
if (count == 1 ||
|
|
@@ -4202,40 +4425,9 @@ function parseTokens(tokens, nodeType, options = {}) {
|
|
|
4202
4425
|
}
|
|
4203
4426
|
return tokens;
|
|
4204
4427
|
}
|
|
4205
|
-
function getBlockType(chr) {
|
|
4206
|
-
if (chr == ';') {
|
|
4207
|
-
return { typ: 'Semi-colon' };
|
|
4208
|
-
}
|
|
4209
|
-
if (chr == '{') {
|
|
4210
|
-
return { typ: 'Block-start' };
|
|
4211
|
-
}
|
|
4212
|
-
if (chr == '}') {
|
|
4213
|
-
return { typ: 'Block-end' };
|
|
4214
|
-
}
|
|
4215
|
-
if (chr == '[') {
|
|
4216
|
-
return { typ: 'Attr-start' };
|
|
4217
|
-
}
|
|
4218
|
-
if (chr == ']') {
|
|
4219
|
-
return { typ: 'Attr-end' };
|
|
4220
|
-
}
|
|
4221
|
-
throw new Error(`unhandled token: '${chr}'`);
|
|
4222
|
-
}
|
|
4223
|
-
|
|
4224
|
-
function* walk(node) {
|
|
4225
|
-
// @ts-ignore
|
|
4226
|
-
yield* doWalk(node, null, null);
|
|
4227
|
-
}
|
|
4228
|
-
function* doWalk(node, parent, root) {
|
|
4229
|
-
yield { node, parent, root };
|
|
4230
|
-
if ('chi' in node) {
|
|
4231
|
-
for (const child of node.chi) {
|
|
4232
|
-
yield* doWalk(child, node, (root ?? node));
|
|
4233
|
-
}
|
|
4234
|
-
}
|
|
4235
|
-
}
|
|
4236
4428
|
|
|
4237
4429
|
async function transform$1(css, options = {}) {
|
|
4238
|
-
options = {
|
|
4430
|
+
options = { minify: true, removeEmpty: true, ...options };
|
|
4239
4431
|
const startTime = performance.now();
|
|
4240
4432
|
const parseResult = await parse$1(css, options);
|
|
4241
4433
|
const renderTime = performance.now();
|
|
@@ -4369,16 +4561,42 @@ function transform(css, options = {}) {
|
|
|
4369
4561
|
return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
|
|
4370
4562
|
}
|
|
4371
4563
|
|
|
4372
|
-
exports.
|
|
4373
|
-
exports.deduplicateRule = deduplicateRule;
|
|
4564
|
+
exports.combinators = combinators;
|
|
4374
4565
|
exports.dirname = dirname;
|
|
4566
|
+
exports.getConfig = getConfig;
|
|
4375
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;
|
|
4376
4588
|
exports.load = load;
|
|
4377
4589
|
exports.matchUrl = matchUrl;
|
|
4590
|
+
exports.minify = minify;
|
|
4591
|
+
exports.minifyRule = minifyRule;
|
|
4378
4592
|
exports.parse = parse;
|
|
4593
|
+
exports.parseDimension = parseDimension;
|
|
4594
|
+
exports.parseString = parseString;
|
|
4379
4595
|
exports.reduceSelector = reduceSelector;
|
|
4380
4596
|
exports.render = render;
|
|
4381
4597
|
exports.renderToken = renderToken;
|
|
4382
4598
|
exports.resolve = resolve;
|
|
4599
|
+
exports.tokenize = tokenize;
|
|
4383
4600
|
exports.transform = transform;
|
|
4601
|
+
exports.urlTokenMatcher = urlTokenMatcher;
|
|
4384
4602
|
exports.walk = walk;
|