@tbela99/css-parser 0.0.1 → 0.1.0

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/dist/index.cjs CHANGED
@@ -2,6 +2,93 @@
2
2
 
3
3
  var promises = require('fs/promises');
4
4
 
5
+ exports.NodeType = void 0;
6
+ (function (NodeType) {
7
+ NodeType[NodeType["CommentNodeType"] = 0] = "CommentNodeType";
8
+ NodeType[NodeType["CDOCOMMNodeType"] = 1] = "CDOCOMMNodeType";
9
+ NodeType[NodeType["StyleSheetNodeType"] = 2] = "StyleSheetNodeType";
10
+ NodeType[NodeType["AtRuleNodeType"] = 3] = "AtRuleNodeType";
11
+ NodeType[NodeType["RuleNodeType"] = 4] = "RuleNodeType";
12
+ NodeType[NodeType["DeclarationNodeType"] = 5] = "DeclarationNodeType";
13
+ })(exports.NodeType || (exports.NodeType = {}));
14
+ exports.EnumToken = void 0;
15
+ (function (EnumToken) {
16
+ EnumToken[EnumToken["CommentTokenType"] = 0] = "CommentTokenType";
17
+ EnumToken[EnumToken["CDOCOMMTokenType"] = 1] = "CDOCOMMTokenType";
18
+ EnumToken[EnumToken["LiteralTokenType"] = 2] = "LiteralTokenType";
19
+ EnumToken[EnumToken["IdenTokenType"] = 3] = "IdenTokenType";
20
+ EnumToken[EnumToken["CommaTokenType"] = 4] = "CommaTokenType";
21
+ EnumToken[EnumToken["ColonTokenType"] = 5] = "ColonTokenType";
22
+ EnumToken[EnumToken["SemiColonTokenType"] = 6] = "SemiColonTokenType";
23
+ EnumToken[EnumToken["NumberTokenType"] = 7] = "NumberTokenType";
24
+ EnumToken[EnumToken["AtRuleTokenType"] = 8] = "AtRuleTokenType";
25
+ EnumToken[EnumToken["PercentageTokenType"] = 9] = "PercentageTokenType";
26
+ EnumToken[EnumToken["FunctionTokenType"] = 10] = "FunctionTokenType";
27
+ EnumToken[EnumToken["UrlFunctionTokenType"] = 11] = "UrlFunctionTokenType";
28
+ EnumToken[EnumToken["StringTokenType"] = 12] = "StringTokenType";
29
+ EnumToken[EnumToken["UnclosedStringTokenType"] = 13] = "UnclosedStringTokenType";
30
+ EnumToken[EnumToken["DimensionTokenType"] = 14] = "DimensionTokenType";
31
+ EnumToken[EnumToken["LengthTokenType"] = 15] = "LengthTokenType";
32
+ EnumToken[EnumToken["AngleTokenType"] = 16] = "AngleTokenType";
33
+ EnumToken[EnumToken["TimeTokenType"] = 17] = "TimeTokenType";
34
+ EnumToken[EnumToken["FrequencyTokenType"] = 18] = "FrequencyTokenType";
35
+ EnumToken[EnumToken["ResolutionTokenType"] = 19] = "ResolutionTokenType";
36
+ EnumToken[EnumToken["HashTokenType"] = 20] = "HashTokenType";
37
+ EnumToken[EnumToken["BlockStartTokenType"] = 21] = "BlockStartTokenType";
38
+ EnumToken[EnumToken["BlockEndTokenType"] = 22] = "BlockEndTokenType";
39
+ EnumToken[EnumToken["AttrStartTokenType"] = 23] = "AttrStartTokenType";
40
+ EnumToken[EnumToken["AttrEndTokenType"] = 24] = "AttrEndTokenType";
41
+ EnumToken[EnumToken["StartParensTokenType"] = 25] = "StartParensTokenType";
42
+ EnumToken[EnumToken["EndParensTokenType"] = 26] = "EndParensTokenType";
43
+ EnumToken[EnumToken["ParensTokenType"] = 27] = "ParensTokenType";
44
+ EnumToken[EnumToken["WhitespaceTokenType"] = 28] = "WhitespaceTokenType";
45
+ EnumToken[EnumToken["IncludesTokenType"] = 29] = "IncludesTokenType";
46
+ EnumToken[EnumToken["DashMatchTokenType"] = 30] = "DashMatchTokenType";
47
+ EnumToken[EnumToken["LtTokenType"] = 31] = "LtTokenType";
48
+ EnumToken[EnumToken["LteTokenType"] = 32] = "LteTokenType";
49
+ EnumToken[EnumToken["GtTokenType"] = 33] = "GtTokenType";
50
+ EnumToken[EnumToken["GteTokenType"] = 34] = "GteTokenType";
51
+ EnumToken[EnumToken["PseudoClassTokenType"] = 35] = "PseudoClassTokenType";
52
+ EnumToken[EnumToken["PseudoClassFuncTokenType"] = 36] = "PseudoClassFuncTokenType";
53
+ EnumToken[EnumToken["DelimTokenType"] = 37] = "DelimTokenType";
54
+ EnumToken[EnumToken["UrlTokenTokenType"] = 38] = "UrlTokenTokenType";
55
+ EnumToken[EnumToken["EOFTokenType"] = 39] = "EOFTokenType";
56
+ EnumToken[EnumToken["ImportantTokenType"] = 40] = "ImportantTokenType";
57
+ EnumToken[EnumToken["ColorTokenType"] = 41] = "ColorTokenType";
58
+ EnumToken[EnumToken["AttrTokenType"] = 42] = "AttrTokenType";
59
+ EnumToken[EnumToken["BadCommentTokenType"] = 43] = "BadCommentTokenType";
60
+ EnumToken[EnumToken["BadCdoTokenType"] = 44] = "BadCdoTokenType";
61
+ EnumToken[EnumToken["BadUrlTokenType"] = 45] = "BadUrlTokenType";
62
+ EnumToken[EnumToken["BadStringTokenType"] = 46] = "BadStringTokenType";
63
+ EnumToken[EnumToken["BinaryExpressionTokenType"] = 47] = "BinaryExpressionTokenType";
64
+ EnumToken[EnumToken["UnaryExpressionTokenType"] = 48] = "UnaryExpressionTokenType";
65
+ /* catch all */
66
+ EnumToken[EnumToken["ListToken"] = 49] = "ListToken";
67
+ /* arithmetic tokens */
68
+ EnumToken[EnumToken["Add"] = 50] = "Add";
69
+ EnumToken[EnumToken["Mul"] = 51] = "Mul";
70
+ EnumToken[EnumToken["Div"] = 52] = "Div";
71
+ EnumToken[EnumToken["Sub"] = 53] = "Sub";
72
+ /* aliases */
73
+ EnumToken[EnumToken["Time"] = 17] = "Time";
74
+ EnumToken[EnumToken["Iden"] = 3] = "Iden";
75
+ EnumToken[EnumToken["Hash"] = 20] = "Hash";
76
+ EnumToken[EnumToken["Angle"] = 16] = "Angle";
77
+ EnumToken[EnumToken["Color"] = 41] = "Color";
78
+ EnumToken[EnumToken["Comma"] = 4] = "Comma";
79
+ EnumToken[EnumToken["String"] = 12] = "String";
80
+ EnumToken[EnumToken["Length"] = 15] = "Length";
81
+ EnumToken[EnumToken["Number"] = 7] = "Number";
82
+ EnumToken[EnumToken["Perc"] = 9] = "Perc";
83
+ EnumToken[EnumToken["Literal"] = 2] = "Literal";
84
+ EnumToken[EnumToken["Comment"] = 0] = "Comment";
85
+ EnumToken[EnumToken["UrlFunc"] = 11] = "UrlFunc";
86
+ EnumToken[EnumToken["Dimension"] = 14] = "Dimension";
87
+ EnumToken[EnumToken["Frequency"] = 18] = "Frequency";
88
+ EnumToken[EnumToken["Resolution"] = 19] = "Resolution";
89
+ EnumToken[EnumToken["Whitespace"] = 28] = "Whitespace";
90
+ })(exports.EnumToken || (exports.EnumToken = {}));
91
+
5
92
  // name to color
6
93
  const COLORS_NAMES = Object.seal({
7
94
  'aliceblue': '#f0f8ff',
@@ -314,18 +401,18 @@ function rgb2Hex(token) {
314
401
  // @ts-ignore
315
402
  t = token.chi[i];
316
403
  // @ts-ignore
317
- value += Math.round(t.typ == 'Perc' ? 255 * t.val / 100 : t.val).toString(16).padStart(2, '0');
404
+ value += Math.round(t.typ == exports.EnumToken.PercentageTokenType ? 255 * t.val / 100 : t.val).toString(16).padStart(2, '0');
318
405
  }
319
406
  // @ts-ignore
320
407
  if (token.chi.length == 7) {
321
408
  // @ts-ignore
322
409
  t = token.chi[6];
323
410
  // @ts-ignore
324
- if ((t.typ == 'Number' && t.val < 1) ||
411
+ if ((t.typ == exports.EnumToken.NumberTokenType && t.val < 1) ||
325
412
  // @ts-ignore
326
- (t.typ == 'Perc' && t.val < 100)) {
413
+ (t.typ == exports.EnumToken.PercentageTokenType && t.val < 100)) {
327
414
  // @ts-ignore
328
- value += Math.round(255 * (t.typ == 'Perc' ? t.val / 100 : t.val)).toString(16).padStart(2, '0');
415
+ value += Math.round(255 * (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val)).toString(16).padStart(2, '0');
329
416
  }
330
417
  }
331
418
  return value;
@@ -337,21 +424,21 @@ function hsl2Hex(token) {
337
424
  // @ts-ignore
338
425
  t = token.chi[2];
339
426
  // @ts-ignore
340
- let s = t.typ == 'Perc' ? t.val / 100 : t.val;
427
+ let s = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
341
428
  // @ts-ignore
342
429
  t = token.chi[4];
343
430
  // @ts-ignore
344
- let l = t.typ == 'Perc' ? t.val / 100 : t.val;
431
+ let l = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
345
432
  let a = null;
346
433
  if (token.chi?.length == 7) {
347
434
  // @ts-ignore
348
435
  t = token.chi[6];
349
436
  // @ts-ignore
350
- if ((t.typ == 'Perc' && t.val < 100) ||
437
+ if ((t.typ == exports.EnumToken.PercentageTokenType && t.val < 100) ||
351
438
  // @ts-ignore
352
- (t.typ == 'Number' && t.val < 1)) {
439
+ (t.typ == exports.EnumToken.NumberTokenType && t.val < 1)) {
353
440
  // @ts-ignore
354
- a = (t.typ == 'Perc' ? t.val / 100 : t.val);
441
+ a = (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val);
355
442
  }
356
443
  }
357
444
  return `#${hsl2rgb(h, s, l, a).reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
@@ -363,21 +450,21 @@ function hwb2hex(token) {
363
450
  // @ts-ignore
364
451
  t = token.chi[2];
365
452
  // @ts-ignore
366
- let white = t.typ == 'Perc' ? t.val / 100 : t.val;
453
+ let white = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
367
454
  // @ts-ignore
368
455
  t = token.chi[4];
369
456
  // @ts-ignore
370
- let black = t.typ == 'Perc' ? t.val / 100 : t.val;
457
+ let black = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
371
458
  let a = null;
372
459
  if (token.chi?.length == 7) {
373
460
  // @ts-ignore
374
461
  t = token.chi[6];
375
462
  // @ts-ignore
376
- if ((t.typ == 'Perc' && t.val < 100) ||
463
+ if ((t.typ == exports.EnumToken.PercentageTokenType && t.val < 100) ||
377
464
  // @ts-ignore
378
- (t.typ == 'Number' && t.val < 1)) {
465
+ (t.typ == exports.EnumToken.NumberTokenType && t.val < 1)) {
379
466
  // @ts-ignore
380
- a = (t.typ == 'Perc' ? t.val / 100 : t.val);
467
+ a = (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val);
381
468
  }
382
469
  }
383
470
  const rgb = hsl2rgb(h, 1, .5, a);
@@ -394,19 +481,19 @@ function cmyk2hex(token) {
394
481
  // @ts-ignore
395
482
  let t = token.chi[0];
396
483
  // @ts-ignore
397
- const c = t.typ == 'Perc' ? t.val / 100 : t.val;
484
+ const c = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
398
485
  // @ts-ignore
399
486
  t = token.chi[2];
400
487
  // @ts-ignore
401
- const m = t.typ == 'Perc' ? t.val / 100 : t.val;
488
+ const m = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
402
489
  // @ts-ignore
403
490
  t = token.chi[4];
404
491
  // @ts-ignore
405
- const y = t.typ == 'Perc' ? t.val / 100 : t.val;
492
+ const y = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
406
493
  // @ts-ignore
407
494
  t = token.chi[6];
408
495
  // @ts-ignore
409
- const k = t.typ == 'Perc' ? t.val / 100 : t.val;
496
+ const k = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
410
497
  const rgb = [
411
498
  Math.round(255 * (1 - Math.min(1, c * (1 - k) + k))),
412
499
  Math.round(255 * (1 - Math.min(1, m * (1 - k) + k))),
@@ -417,12 +504,12 @@ function cmyk2hex(token) {
417
504
  // @ts-ignore
418
505
  t = token.chi[8];
419
506
  // @ts-ignore
420
- rgb.push(Math.round(255 * (t.typ == 'Perc' ? t.val / 100 : t.val)));
507
+ rgb.push(Math.round(255 * (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val)));
421
508
  }
422
509
  return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
423
510
  }
424
511
  function getAngle(token) {
425
- if (token.typ == 'Angle') {
512
+ if (token.typ == exports.EnumToken.AngleTokenType) {
426
513
  switch (token.unit) {
427
514
  case 'deg':
428
515
  // @ts-ignore
@@ -495,6 +582,97 @@ function hsl2rgb(h, s, l, a = null) {
495
582
  return values;
496
583
  }
497
584
 
585
+ // from https://github.com/Rich-Harris/vlq/tree/master
586
+ // credit: Rich Harris
587
+ const integer_to_char = {};
588
+ let i = 0;
589
+ for (const char of 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=') {
590
+ integer_to_char[i++] = char;
591
+ }
592
+ function encode(value) {
593
+ if (typeof value === 'number') {
594
+ return encode_integer(value);
595
+ }
596
+ let result = '';
597
+ for (let i = 0; i < value.length; i += 1) {
598
+ result += encode_integer(value[i]);
599
+ }
600
+ return result;
601
+ }
602
+ function encode_integer(num) {
603
+ let result = '';
604
+ if (num < 0) {
605
+ num = (-num << 1) | 1;
606
+ }
607
+ else {
608
+ num <<= 1;
609
+ }
610
+ do {
611
+ let clamped = num & 31;
612
+ num >>>= 5;
613
+ if (num > 0) {
614
+ clamped |= 32;
615
+ }
616
+ result += integer_to_char[clamped];
617
+ } while (num > 0);
618
+ return result;
619
+ }
620
+
621
+ class SourceMap {
622
+ #version = 3;
623
+ #sources = [];
624
+ #map = new Map;
625
+ #line = -1;
626
+ lastLocation = null;
627
+ add(source, original) {
628
+ if (original.src !== '') {
629
+ if (!this.#sources.includes(original.src)) {
630
+ this.#sources.push(original.src);
631
+ }
632
+ const line = source.sta.lin - 1;
633
+ let record;
634
+ if (line > this.#line) {
635
+ this.#line = line;
636
+ }
637
+ if (!this.#map.has(line)) {
638
+ record = [Math.max(0, source.sta.col - 1), this.#sources.indexOf(original.src), original.sta.lin - 1, original.sta.col - 1];
639
+ this.#map.set(line, [record]);
640
+ }
641
+ else {
642
+ const arr = this.#map.get(line);
643
+ record = [Math.max(0, source.sta.col - 1 - arr[0][0]), this.#sources.indexOf(original.src) - arr[0][1], original.sta.lin - 1, original.sta.col - 1];
644
+ arr.push(record);
645
+ }
646
+ if (this.lastLocation != null) {
647
+ record[2] -= this.lastLocation.sta.lin - 1;
648
+ record[3] -= this.lastLocation.sta.col - 1;
649
+ }
650
+ this.lastLocation = original;
651
+ }
652
+ }
653
+ toUrl() {
654
+ // /*# sourceMappingURL = ${url} */
655
+ return `data:application/json,${encodeURIComponent(JSON.stringify(this.toJSON()))}`;
656
+ }
657
+ toJSON() {
658
+ const mappings = [];
659
+ let i = 0;
660
+ for (; i <= this.#line; i++) {
661
+ if (!this.#map.has(i)) {
662
+ mappings.push('');
663
+ }
664
+ else {
665
+ mappings.push(this.#map.get(i).reduce((acc, curr) => acc + (acc === '' ? '' : ',') + encode(curr), ''));
666
+ }
667
+ }
668
+ return {
669
+ version: this.#version,
670
+ sources: this.#sources.slice(),
671
+ mappings: mappings.join(';')
672
+ };
673
+ }
674
+ }
675
+
498
676
  const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'];
499
677
  function reduceNumber(val) {
500
678
  val = (+val).toString();
@@ -513,35 +691,88 @@ function reduceNumber(val) {
513
691
  }
514
692
  return val;
515
693
  }
516
- function render(data, opt = {}) {
694
+ function update(position, str) {
695
+ let i = 0;
696
+ for (; i < str.length; i++) {
697
+ if (isNewLine(str[i].charCodeAt(0))) {
698
+ position.lin++;
699
+ position.col = 0;
700
+ }
701
+ else {
702
+ position.col++;
703
+ }
704
+ }
705
+ }
706
+ function doRender(data, options = {}) {
707
+ options = {
708
+ ...(options.minify ?? true ? {
709
+ indent: '',
710
+ newLine: '',
711
+ removeComments: true
712
+ } : {
713
+ indent: ' ',
714
+ newLine: '\n',
715
+ compress: false,
716
+ removeComments: false,
717
+ }), sourcemap: false, colorConvert: true, expandNestingRules: false, preserveLicense: false, ...options
718
+ };
517
719
  const startTime = performance.now();
518
720
  const errors = [];
519
- const options = Object.assign(opt.minify ?? true ? {
520
- indent: '',
521
- newLine: '',
522
- removeComments: true
523
- } : {
524
- indent: ' ',
525
- newLine: '\n',
526
- compress: false,
527
- removeComments: false,
528
- }, { colorConvert: true, expandNestingRules: false, preserveLicense: false }, opt);
529
- return {
530
- code: doRender(options.expandNestingRules ? expand(data) : data, options, errors, function reducer(acc, curr) {
531
- if (curr.typ == 'Comment' && options.removeComments) {
721
+ const sourcemap = options.sourcemap ? new SourceMap : null;
722
+ const cache = Object.create(null);
723
+ const result = {
724
+ code: renderAstNode(options.expandNestingRules ? expand(data) : data, options, sourcemap, {
725
+ ind: 0,
726
+ lin: 1,
727
+ col: 1
728
+ }, errors, function reducer(acc, curr) {
729
+ if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
532
730
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
533
731
  return acc;
534
732
  }
535
733
  return acc + curr.val;
536
734
  }
537
- return acc + renderToken(curr, options, reducer, errors);
538
- }, 0), errors, stats: {
735
+ return acc + renderToken(curr, options, cache, reducer, errors);
736
+ }, cache), errors, stats: {
539
737
  total: `${(performance.now() - startTime).toFixed(2)}ms`
540
738
  }
541
739
  };
740
+ if (options.output != null) {
741
+ // @ts-ignore
742
+ options.output = options.resolve(options.output, options.cwd).absolute;
743
+ }
744
+ if (sourcemap != null) {
745
+ result.map = sourcemap.toJSON();
746
+ // @ts-ignore
747
+ // result.map.sources = result.map.sources?.map(s => <string>options?.resolve(s, <string>options?.cwd)?.relative)
748
+ }
749
+ return result;
750
+ }
751
+ function updateSourceMap(node, options, cache, sourcemap, position, str) {
752
+ if ([4 /* NodeType.RuleNodeType */, 3 /* NodeType.AtRuleNodeType */].includes(node.typ)) {
753
+ let src = node.loc?.src ?? '';
754
+ let output = options.output ?? '';
755
+ if (src !== '') {
756
+ if (!(src in cache)) {
757
+ // @ts-ignore
758
+ cache[src] = options.resolve(src, options.cwd ?? '').relative;
759
+ }
760
+ }
761
+ if (!(output in cache)) {
762
+ // @ts-ignore
763
+ cache[output] = options.resolve(output, options.cwd).relative;
764
+ }
765
+ // @ts-ignore
766
+ sourcemap.add({ src: cache[output], sta: { ...position } }, {
767
+ ...node.loc,
768
+ // @ts-ignore
769
+ src: options.resolve(cache[src], options.cwd).relative
770
+ });
771
+ }
772
+ update(position, str);
542
773
  }
543
774
  // @ts-ignore
544
- function doRender(data, options, errors, reducer, level = 0, indents = []) {
775
+ function renderAstNode(data, options, sourcemap, position, errors, reducer, cache, level = 0, indents = []) {
545
776
  if (indents.length < level + 1) {
546
777
  indents.push(options.indent.repeat(level));
547
778
  }
@@ -551,46 +782,61 @@ function doRender(data, options, errors, reducer, level = 0, indents = []) {
551
782
  const indent = indents[level];
552
783
  const indentSub = indents[level + 1];
553
784
  switch (data.typ) {
554
- case 'Declaration':
785
+ case 5 /* NodeType.DeclarationNodeType */:
555
786
  return `${data.nam}:${options.indent}${data.val.reduce(reducer, '')}`;
556
- case 'Comment':
557
- case 'CDOCOMM':
787
+ case 0 /* NodeType.CommentNodeType */:
788
+ case 1 /* NodeType.CDOCOMMNodeType */:
789
+ if (data.val.startsWith('# sourceMappingURL=')) {
790
+ // ignore sourcemap
791
+ return '';
792
+ }
558
793
  return !options.removeComments || (options.preserveLicense && data.val.startsWith('/*!')) ? data.val : '';
559
- case 'StyleSheet':
794
+ case 2 /* NodeType.StyleSheetNodeType */:
560
795
  return data.chi.reduce((css, node) => {
561
- const str = doRender(node, options, errors, reducer, level, indents);
796
+ const str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level, indents);
562
797
  if (str === '') {
563
798
  return css;
564
799
  }
565
800
  if (css === '') {
801
+ if (sourcemap != null) {
802
+ updateSourceMap(node, options, cache, sourcemap, position, str);
803
+ }
566
804
  return str;
567
805
  }
806
+ if (sourcemap != null) {
807
+ update(position, options.newLine);
808
+ updateSourceMap(node, options, cache, sourcemap, position, str);
809
+ }
568
810
  return `${css}${options.newLine}${str}`;
569
811
  }, '');
570
- case 'AtRule':
571
- case 'Rule':
572
- if (data.typ == 'AtRule' && !('chi' in data)) {
812
+ case 3 /* NodeType.AtRuleNodeType */:
813
+ case 4 /* NodeType.RuleNodeType */:
814
+ if (data.typ == 3 /* NodeType.AtRuleNodeType */ && !('chi' in data)) {
573
815
  return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`;
574
816
  }
575
817
  // @ts-ignore
576
818
  let children = data.chi.reduce((css, node) => {
577
819
  let str;
578
- if (node.typ == 'Comment') {
820
+ if (node.typ == 0 /* NodeType.CommentNodeType */) {
579
821
  str = options.removeComments && (!options.preserveLicense || !node.val.startsWith('/*!')) ? '' : node.val;
580
822
  }
581
- else if (node.typ == 'Declaration') {
823
+ else if (node.typ == 5 /* NodeType.DeclarationNodeType */) {
582
824
  if (node.val.length == 0) {
583
825
  // @ts-ignore
584
- errors.push({ action: 'ignore', message: `render: invalid declaration ${JSON.stringify(node)}`, location: node.loc });
826
+ errors.push({
827
+ action: 'ignore',
828
+ message: `render: invalid declaration ${JSON.stringify(node)}`,
829
+ location: node.loc
830
+ });
585
831
  return '';
586
832
  }
587
833
  str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
588
834
  }
589
- else if (node.typ == 'AtRule' && !('chi' in node)) {
835
+ else if (node.typ == 3 /* NodeType.AtRuleNodeType */ && !('chi' in node)) {
590
836
  str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`;
591
837
  }
592
838
  else {
593
- str = doRender(node, options, errors, reducer, level + 1, indents);
839
+ str = renderAstNode(node, options, sourcemap, { ...position }, errors, reducer, cache, level + 1, indents);
594
840
  }
595
841
  if (css === '') {
596
842
  return str;
@@ -603,28 +849,40 @@ function doRender(data, options, errors, reducer, level = 0, indents = []) {
603
849
  if (children.endsWith(';')) {
604
850
  children = children.slice(0, -1);
605
851
  }
606
- if (data.typ == 'AtRule') {
852
+ if (data.typ == 3 /* NodeType.AtRuleNodeType */) {
607
853
  return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
608
854
  }
609
855
  return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
610
856
  }
611
857
  return '';
612
858
  }
613
- function renderToken(token, options = {}, reducer, errors) {
859
+ function renderToken(token, options = {}, cache = Object.create(null), reducer, errors) {
614
860
  if (reducer == null) {
615
861
  reducer = function (acc, curr) {
616
- if (curr.typ == 'Comment' && options.removeComments) {
862
+ if (curr.typ == exports.EnumToken.CommentTokenType && options.removeComments) {
617
863
  if (!options.preserveLicense || !curr.val.startsWith('/*!')) {
618
864
  return acc;
619
865
  }
620
866
  return acc + curr.val;
621
867
  }
622
- return acc + renderToken(curr, options, reducer, errors);
868
+ return acc + renderToken(curr, options, cache, reducer, errors);
623
869
  };
624
870
  }
625
871
  switch (token.typ) {
626
- case 'Color':
627
- if (options.minify || options.colorConvert) {
872
+ case exports.EnumToken.ListToken:
873
+ return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
874
+ case exports.EnumToken.BinaryExpressionTokenType:
875
+ return renderToken(token.l, options, cache) + (token.op == exports.EnumToken.Add ? ' + ' : (token.op == exports.EnumToken.Sub ? ' - ' : (token.op == exports.EnumToken.Mul ? '*' : '/'))) + renderToken(token.r, options, cache);
876
+ case exports.EnumToken.Add:
877
+ return ' + ';
878
+ case exports.EnumToken.Sub:
879
+ return ' - ';
880
+ case exports.EnumToken.Mul:
881
+ return '*';
882
+ case exports.EnumToken.Div:
883
+ return '/';
884
+ case exports.EnumToken.ColorTokenType:
885
+ if (options.colorConvert) {
628
886
  if (token.kin == 'lit' && token.val.toLowerCase() == 'currentcolor') {
629
887
  return 'currentcolor';
630
888
  }
@@ -664,54 +922,69 @@ function renderToken(token, options = {}, reducer, errors) {
664
922
  if (token.kin == 'hex' || token.kin == 'lit') {
665
923
  return token.val;
666
924
  }
667
- case 'Start-parens':
668
- if (!('chi' in token)) {
669
- return '(';
925
+ case exports.EnumToken.ParensTokenType:
926
+ case exports.EnumToken.FunctionTokenType:
927
+ case exports.EnumToken.UrlFunctionTokenType:
928
+ case exports.EnumToken.PseudoClassFuncTokenType:
929
+ if (token.typ == exports.EnumToken.FunctionTokenType &&
930
+ token.val == 'calc' &&
931
+ token.chi.length == 1) {
932
+ // calc(200px) => 200px
933
+ return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache, reducer), '');
670
934
  }
671
- case 'Func':
672
- case 'UrlFunc':
673
- case 'Pseudo-class-func':
674
935
  // @ts-ignore
675
936
  return ( /* options.minify && 'Pseudo-class-func' == token.typ && token.val.slice(0, 2) == '::' ? token.val.slice(1) :*/token.val ?? '') + '(' + token.chi.reduce(reducer, '') + ')';
676
- case 'Includes':
937
+ case exports.EnumToken.StartParensTokenType:
938
+ return '(';
939
+ case exports.EnumToken.IncludesTokenType:
677
940
  return '~=';
678
- case 'Dash-match':
941
+ case exports.EnumToken.DashMatchTokenType:
679
942
  return '|=';
680
- case 'Lt':
943
+ case exports.EnumToken.LtTokenType:
681
944
  return '<';
682
- case 'Lte':
945
+ case exports.EnumToken.LteTokenType:
683
946
  return '<=';
684
- case 'Gt':
947
+ case exports.EnumToken.GtTokenType:
685
948
  return '>';
686
- case 'Gte':
949
+ case exports.EnumToken.GteTokenType:
687
950
  return '>=';
688
- case 'End-parens':
951
+ case exports.EnumToken.EndParensTokenType:
689
952
  return ')';
690
- case 'Attr-start':
953
+ case exports.EnumToken.AttrStartTokenType:
691
954
  return '[';
692
- case 'Attr-end':
955
+ case exports.EnumToken.AttrEndTokenType:
693
956
  return ']';
694
- case 'Whitespace':
957
+ case exports.EnumToken.WhitespaceTokenType:
695
958
  return ' ';
696
- case 'Colon':
959
+ case exports.EnumToken.ColonTokenType:
697
960
  return ':';
698
- case 'Semi-colon':
961
+ case exports.EnumToken.SemiColonTokenType:
699
962
  return ';';
700
- case 'Comma':
963
+ case exports.EnumToken.CommaTokenType:
701
964
  return ',';
702
- case 'Important':
965
+ case exports.EnumToken.ImportantTokenType:
703
966
  return '!important';
704
- case 'Attr':
967
+ case exports.EnumToken.AttrTokenType:
705
968
  return '[' + token.chi.reduce(reducer, '') + ']';
706
- case 'Time':
707
- case 'Angle':
708
- case 'Length':
709
- case 'Dimension':
710
- case 'Frequency':
711
- case 'Resolution':
969
+ case exports.EnumToken.TimeTokenType:
970
+ case exports.EnumToken.AngleTokenType:
971
+ case exports.EnumToken.LengthTokenType:
972
+ case exports.EnumToken.DimensionTokenType:
973
+ case exports.EnumToken.FrequencyTokenType:
974
+ case exports.EnumToken.ResolutionTokenType:
975
+ if (token.val.typ == exports.EnumToken.BinaryExpressionTokenType) {
976
+ const result = renderToken(token.val, options, cache);
977
+ if (!('unit' in token)) {
978
+ return result;
979
+ }
980
+ if (!result.includes(' ')) {
981
+ return result + token.unit;
982
+ }
983
+ return `(${result})*1${token.unit}`;
984
+ }
712
985
  let val = reduceNumber(token.val);
713
986
  let unit = token.unit;
714
- if (token.typ == 'Angle') {
987
+ if (token.typ == exports.EnumToken.AngleTokenType) {
715
988
  const angle = getAngle(token);
716
989
  let v;
717
990
  let value = val + unit;
@@ -756,36 +1029,58 @@ function renderToken(token, options = {}, reducer, errors) {
756
1029
  }
757
1030
  }
758
1031
  if (val === '0') {
759
- if (token.typ == 'Time') {
1032
+ if (token.typ == exports.EnumToken.TimeTokenType) {
760
1033
  return '0s';
761
1034
  }
762
- if (token.typ == 'Frequency') {
1035
+ if (token.typ == exports.EnumToken.FrequencyTokenType) {
763
1036
  return '0Hz';
764
1037
  }
765
1038
  // @ts-ignore
766
- if (token.typ == 'Resolution') {
1039
+ if (token.typ == exports.EnumToken.ResolutionTokenType) {
767
1040
  return '0x';
768
1041
  }
769
1042
  return '0';
770
1043
  }
771
1044
  return val + unit;
772
- case 'Perc':
1045
+ case exports.EnumToken.PercentageTokenType:
773
1046
  const perc = reduceNumber(token.val);
774
1047
  return options.minify && perc == '0' ? '0' : perc + '%';
775
- case 'Number':
1048
+ case exports.EnumToken.NumberTokenType:
776
1049
  return reduceNumber(token.val);
777
- case 'Comment':
1050
+ case exports.EnumToken.CommentTokenType:
778
1051
  if (options.removeComments && (!options.preserveLicense || !token.val.startsWith('/*!'))) {
779
1052
  return '';
780
1053
  }
781
- case 'Url-token':
782
- case 'At-rule':
783
- case 'Hash':
784
- case 'Pseudo-class':
785
- case 'Literal':
786
- case 'String':
787
- case 'Iden':
788
- case 'Delim':
1054
+ case exports.EnumToken.UrlTokenTokenType:
1055
+ if (token.typ == exports.EnumToken.UrlTokenTokenType) {
1056
+ if (options.output != null) {
1057
+ if (!('original' in token)) {
1058
+ // do not modify original token
1059
+ token = { ...token };
1060
+ Object.defineProperty(token, 'original', { enumerable: false, writable: false, value: token.val });
1061
+ }
1062
+ // @ts-ignore
1063
+ if (!(token.original in cache)) {
1064
+ let output = options.output ?? '';
1065
+ const key = output + 'abs';
1066
+ if (!(key in cache)) {
1067
+ // @ts-ignore
1068
+ cache[key] = options.dirname(options.resolve(output, options.cwd).absolute);
1069
+ }
1070
+ // @ts-ignore
1071
+ cache[token.original] = options.resolve(token.original, cache[key]).relative;
1072
+ }
1073
+ // @ts-ignore
1074
+ token.val = cache[token.original];
1075
+ }
1076
+ }
1077
+ case exports.EnumToken.AtRuleTokenType:
1078
+ case exports.EnumToken.HashTokenType:
1079
+ case exports.EnumToken.PseudoClassTokenType:
1080
+ case exports.EnumToken.LiteralTokenType:
1081
+ case exports.EnumToken.StringTokenType:
1082
+ case exports.EnumToken.IdenTokenType:
1083
+ case exports.EnumToken.DelimTokenType:
789
1084
  return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
790
1085
  }
791
1086
  errors?.push({ action: 'ignore', message: `render: unexpected token ${JSON.stringify(token, null, 1)}` });
@@ -818,17 +1113,17 @@ function isFrequency(dimension) {
818
1113
  return 'unit' in dimension && ['hz', 'khz'].includes(dimension.unit.toLowerCase());
819
1114
  }
820
1115
  function isColor(token) {
821
- if (token.typ == 'Color') {
1116
+ if (token.typ == exports.EnumToken.ColorTokenType) {
822
1117
  return true;
823
1118
  }
824
- if (token.typ == 'Iden') {
1119
+ if (token.typ == exports.EnumToken.IdenTokenType) {
825
1120
  // named color
826
1121
  return token.val.toLowerCase() in COLORS_NAMES;
827
1122
  }
828
- if (token.typ == 'Func' && token.chi.length > 0 && colorsFunc.includes(token.val)) {
1123
+ if (token.typ == exports.EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
829
1124
  // @ts-ignore
830
1125
  for (const v of token.chi) {
831
- if (!['Number', 'Angle', 'Perc', 'Comma', 'Whitespace', 'Literal'].includes(v.typ)) {
1126
+ if (![exports.EnumToken.NumberTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.LiteralTokenType].includes(v.typ)) {
832
1127
  return false;
833
1128
  }
834
1129
  }
@@ -997,29 +1292,29 @@ function parseDimension(name) {
997
1292
  index++;
998
1293
  break;
999
1294
  }
1000
- const dimension = { typ: 'Dimension', val: name.slice(0, index), unit: name.slice(index) };
1295
+ const dimension = { typ: exports.EnumToken.DimensionTokenType, val: name.slice(0, index), unit: name.slice(index) };
1001
1296
  if (isAngle(dimension)) {
1002
1297
  // @ts-ignore
1003
- dimension.typ = 'Angle';
1298
+ dimension.typ = exports.EnumToken.AngleTokenType;
1004
1299
  }
1005
1300
  else if (isLength(dimension)) {
1006
1301
  // @ts-ignore
1007
- dimension.typ = 'Length';
1302
+ dimension.typ = exports.EnumToken.LengthTokenType;
1008
1303
  }
1009
1304
  else if (isTime(dimension)) {
1010
1305
  // @ts-ignore
1011
- dimension.typ = 'Time';
1306
+ dimension.typ = exports.EnumToken.TimeTokenType;
1012
1307
  }
1013
1308
  else if (isResolution(dimension)) {
1014
1309
  // @ts-ignore
1015
- dimension.typ = 'Resolution';
1310
+ dimension.typ = exports.EnumToken.ResolutionTokenType;
1016
1311
  if (dimension.unit == 'dppx') {
1017
1312
  dimension.unit = 'x';
1018
1313
  }
1019
1314
  }
1020
1315
  else if (isFrequency(dimension)) {
1021
1316
  // @ts-ignore
1022
- dimension.typ = 'Frequency';
1317
+ dimension.typ = exports.EnumToken.FrequencyTokenType;
1023
1318
  }
1024
1319
  return dimension;
1025
1320
  }
@@ -1906,340 +2201,144 @@ const getConfig = () => config$1;
1906
2201
 
1907
2202
  const funcList = ['clamp', 'calc'];
1908
2203
  function matchType(val, properties) {
1909
- if (val.typ == 'Iden' && properties.keywords.includes(val.val) ||
1910
- (properties.types.includes(val.typ))) {
2204
+ if (val.typ == exports.EnumToken.IdenTokenType && properties.keywords.includes(val.val) ||
2205
+ // @ts-ignore
2206
+ (properties.types.some((t) => exports.EnumToken[t] == val.typ))) {
1911
2207
  return true;
1912
2208
  }
1913
- if (val.typ == 'Number' && val.val == '0') {
1914
- return properties.types.some(type => type == 'Length' || type == 'Angle');
2209
+ if (val.typ == exports.EnumToken.NumberTokenType && val.val == '0') {
2210
+ // @ts-ignore
2211
+ return properties.types.some((type) => {
2212
+ // @ts-ignore
2213
+ const typ = exports.EnumToken[type];
2214
+ return typ == exports.EnumToken.LengthTokenType || typ == exports.EnumToken.AngleTokenType;
2215
+ });
1915
2216
  }
1916
- if (val.typ == 'Func' && funcList.includes(val.val)) {
1917
- return val.chi.every((t => ['Literal', 'Comma', 'Whitespace', 'Start-parens', 'End-parens'].includes(t.typ) || matchType(t, properties)));
2217
+ if (val.typ == exports.EnumToken.FunctionTokenType && funcList.includes(val.val)) {
2218
+ return val.chi.every((t => [exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.StartParensTokenType, exports.EnumToken.EndParensTokenType].includes(t.typ) || matchType(t, properties)));
1918
2219
  }
1919
2220
  return false;
1920
2221
  }
1921
2222
 
1922
- function eq(a, b) {
1923
- if (a == null || b == null) {
1924
- return a == b;
1925
- }
1926
- if (typeof a != 'object' || typeof b != 'object') {
1927
- return a === b;
1928
- }
1929
- if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
1930
- return false;
1931
- }
1932
- if (Array.isArray(a)) {
1933
- if (a.length != b.length) {
1934
- return false;
1935
- }
1936
- let i = 0;
1937
- for (; i < a.length; i++) {
1938
- if (!eq(a[i], b[i])) {
1939
- return false;
1940
- }
1941
- }
1942
- return true;
1943
- }
1944
- const k1 = Object.keys(a);
1945
- const k2 = Object.keys(b);
1946
- if (k1.length != k2.length) {
1947
- return false;
1948
- }
1949
- let key;
1950
- for (key of k1) {
1951
- if (!(key in b) || !eq(a[key], b[key])) {
1952
- return false;
2223
+ function* tokenize(stream) {
2224
+ let ind = -1;
2225
+ let lin = 1;
2226
+ let col = 0;
2227
+ const position = {
2228
+ ind: Math.max(ind, 0),
2229
+ lin: lin,
2230
+ col: Math.max(col, 1)
2231
+ };
2232
+ let value;
2233
+ let buffer = '';
2234
+ // let input: string = '';
2235
+ function consumeWhiteSpace() {
2236
+ let count = 0;
2237
+ while (isWhiteSpace(stream.charAt(count + ind + 1).charCodeAt(0))) {
2238
+ count++;
1953
2239
  }
2240
+ next(count);
2241
+ return count;
1954
2242
  }
1955
- return true;
1956
- }
1957
-
1958
- class PropertySet {
1959
- config;
1960
- declarations;
1961
- constructor(config) {
1962
- this.config = config;
1963
- this.declarations = new Map;
2243
+ function pushToken(token, hint) {
2244
+ const result = { token, hint, position: { ...position }, bytesIn: ind };
2245
+ position.ind = ind;
2246
+ position.lin = lin;
2247
+ position.col = col == 0 ? 1 : col;
2248
+ return result;
1964
2249
  }
1965
- add(declaration) {
1966
- if (declaration.nam == this.config.shorthand) {
1967
- this.declarations = new Map;
2250
+ function* consumeString(quoteStr) {
2251
+ const quote = quoteStr;
2252
+ let value;
2253
+ let hasNewLine = false;
2254
+ if (buffer.length > 0) {
2255
+ yield pushToken(buffer);
2256
+ buffer = '';
1968
2257
  }
1969
- else {
1970
- // expand shorthand
1971
- if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
1972
- let isValid = true;
1973
- let current = -1;
1974
- const tokens = [];
1975
- // @ts-ignore
1976
- for (let token of this.declarations.get(this.config.shorthand).val) {
1977
- if (this.config.types.includes(token.typ) || (token.typ == 'Number' && token.val == '0' &&
1978
- (this.config.types.includes('Length') ||
1979
- this.config.types.includes('Angle') ||
1980
- this.config.types.includes('Dimension')))) {
1981
- if (tokens.length == 0) {
1982
- tokens.push([]);
1983
- current++;
2258
+ buffer += quoteStr;
2259
+ while (value = peek()) {
2260
+ if (value == '\\') {
2261
+ const sequence = peek(6);
2262
+ let escapeSequence = '';
2263
+ let codepoint;
2264
+ let i;
2265
+ for (i = 1; i < sequence.length; i++) {
2266
+ codepoint = sequence.charCodeAt(i);
2267
+ if (codepoint == 0x20 ||
2268
+ (codepoint >= 0x61 && codepoint <= 0x66) ||
2269
+ (codepoint >= 0x41 && codepoint <= 0x46) ||
2270
+ (codepoint >= 0x30 && codepoint <= 0x39)) {
2271
+ escapeSequence += sequence[i];
2272
+ if (codepoint == 0x20) {
2273
+ break;
1984
2274
  }
1985
- tokens[current].push(token);
1986
2275
  continue;
1987
2276
  }
1988
- if (token.typ != 'Whitespace' && token.typ != 'Comment') {
1989
- if (token.typ == 'Iden' && this.config.keywords.includes(token.val)) {
1990
- if (tokens.length == 0) {
1991
- tokens.push([]);
1992
- current++;
1993
- }
1994
- tokens[current].push(token);
1995
- }
1996
- if (token.typ == 'Literal' && token.val == this.config.separator) {
1997
- tokens.push([]);
1998
- current++;
1999
- continue;
2000
- }
2001
- isValid = false;
2002
- break;
2003
- }
2277
+ break;
2004
2278
  }
2005
- if (isValid && tokens.length > 0) {
2006
- this.declarations.delete(this.config.shorthand);
2007
- for (const values of tokens) {
2008
- this.config.properties.forEach((property, index) => {
2009
- if (!this.declarations.has(property)) {
2010
- this.declarations.set(property, {
2011
- typ: 'Declaration',
2012
- nam: property,
2013
- val: []
2014
- });
2015
- }
2016
- while (index > 0 && index >= values.length) {
2017
- if (index > 1) {
2018
- index %= 2;
2019
- }
2020
- else {
2021
- index = 0;
2022
- break;
2023
- }
2024
- }
2025
- // @ts-ignore
2026
- const val = this.declarations.get(property).val;
2027
- if (val.length > 0) {
2028
- val.push({ typ: 'Whitespace' });
2029
- }
2030
- val.push({ ...values[index] });
2031
- });
2279
+ if (i == 1) {
2280
+ buffer += value + sequence[i];
2281
+ next(2);
2282
+ continue;
2283
+ }
2284
+ if (escapeSequence.trimEnd().length > 0) {
2285
+ const codepoint = Number(`0x${escapeSequence.trimEnd()}`);
2286
+ if (codepoint == 0 ||
2287
+ // leading surrogate
2288
+ (0xD800 <= codepoint && codepoint <= 0xDBFF) ||
2289
+ // trailing surrogate
2290
+ (0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
2291
+ buffer += String.fromCodePoint(0xFFFD);
2032
2292
  }
2293
+ else {
2294
+ buffer += String.fromCodePoint(codepoint);
2295
+ }
2296
+ next(escapeSequence.length + 1 + (isWhiteSpace(peek()?.charCodeAt(0)) ? 1 : 0));
2297
+ continue;
2033
2298
  }
2034
- this.declarations.set(declaration.nam, declaration);
2035
- return this;
2299
+ buffer += next(2);
2300
+ continue;
2301
+ }
2302
+ if (value == quote) {
2303
+ buffer += value;
2304
+ yield pushToken(buffer, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
2305
+ next();
2306
+ // i += value.length;
2307
+ buffer = '';
2308
+ return;
2309
+ }
2310
+ if (isNewLine(value.charCodeAt(0))) {
2311
+ hasNewLine = true;
2312
+ }
2313
+ if (hasNewLine && value == ';') {
2314
+ yield pushToken(buffer + value, exports.EnumToken.BadStringTokenType);
2315
+ buffer = '';
2316
+ next();
2317
+ break;
2036
2318
  }
2037
- }
2038
- this.declarations.set(declaration.nam, declaration);
2039
- return this;
2040
- }
2041
- isShortHand() {
2042
- if (this.declarations.has(this.config.shorthand)) {
2043
- return this.declarations.size == 1;
2044
- }
2045
- return this.config.properties.length == this.declarations.size;
2046
- }
2047
- [Symbol.iterator]() {
2048
- let iterator;
2049
- const declarations = this.declarations;
2050
- if (declarations.size < this.config.properties.length) {
2051
- iterator = declarations.values();
2052
- }
2053
- else {
2054
- const values = [];
2055
- this.config.properties.forEach((property) => {
2056
- let index = 0;
2057
- // @ts-ignore
2058
- for (const token of this.declarations.get(property).val) {
2059
- if (token.typ == 'Whitespace') {
2060
- continue;
2061
- }
2062
- if (values.length == index) {
2063
- values.push([]);
2064
- }
2065
- values[index].push(token);
2066
- index++;
2067
- }
2068
- });
2069
- for (const value of values) {
2070
- let i = value.length;
2071
- while (i-- > 1) {
2072
- const t = value[i];
2073
- const k = value[i == 1 ? 0 : i % 2];
2074
- if (t.val == k.val && t.val == '0') {
2075
- if ((t.typ == 'Number' && isLength(k)) ||
2076
- (k.typ == 'Number' && isLength(t)) ||
2077
- (isLength(k) || isLength(t))) {
2078
- value.splice(i, 1);
2079
- continue;
2080
- }
2081
- }
2082
- if (eq(t, k)) {
2083
- value.splice(i, 1);
2084
- continue;
2085
- }
2086
- break;
2087
- }
2088
- }
2089
- iterator = [{
2090
- typ: 'Declaration',
2091
- nam: this.config.shorthand,
2092
- val: values.reduce((acc, curr) => {
2093
- if (curr.length > 1) {
2094
- const k = curr.length * 2 - 1;
2095
- let i = 1;
2096
- while (i < k) {
2097
- curr.splice(i, 0, { typ: 'Whitespace' });
2098
- i += 2;
2099
- }
2100
- }
2101
- if (acc.length > 0) {
2102
- acc.push({ typ: 'Literal', val: this.config.separator });
2103
- }
2104
- acc.push(...curr);
2105
- return acc;
2106
- }, [])
2107
- }][Symbol.iterator]();
2108
- // return {
2109
- // next() {
2110
- //
2111
- // return iterator.next();
2112
- // }
2113
- // }
2114
- }
2115
- return iterator;
2116
- // return {
2117
- // next() {
2118
- //
2119
- // return iterator.next();
2120
- // }
2121
- // }
2122
- }
2123
- }
2124
-
2125
- function* tokenize(iterator) {
2126
- let ind = -1;
2127
- let lin = 1;
2128
- let col = 0;
2129
- const position = {
2130
- ind: Math.max(ind, 0),
2131
- lin: lin,
2132
- col: Math.max(col, 1)
2133
- };
2134
- let value;
2135
- let buffer = '';
2136
- function consumeWhiteSpace() {
2137
- let count = 0;
2138
- while (isWhiteSpace(iterator.charAt(count + ind + 1).charCodeAt(0))) {
2139
- count++;
2140
- }
2141
- next(count);
2142
- return count;
2143
- }
2144
- function pushToken(token, hint) {
2145
- const result = { token, hint, position: { ...position }, bytesIn: ind };
2146
- position.ind = ind;
2147
- position.lin = lin;
2148
- position.col = col == 0 ? 1 : col;
2149
- return result;
2150
- }
2151
- function* consumeString(quoteStr) {
2152
- const quote = quoteStr;
2153
- let value;
2154
- let hasNewLine = false;
2155
- if (buffer.length > 0) {
2156
- yield pushToken(buffer);
2157
- buffer = '';
2158
- }
2159
- buffer += quoteStr;
2160
- while (value = peek()) {
2161
- if (value == '\\') {
2162
- const sequence = peek(6);
2163
- let escapeSequence = '';
2164
- let codepoint;
2165
- let i;
2166
- for (i = 1; i < sequence.length; i++) {
2167
- codepoint = sequence.charCodeAt(i);
2168
- if (codepoint == 0x20 ||
2169
- (codepoint >= 0x61 && codepoint <= 0x66) ||
2170
- (codepoint >= 0x41 && codepoint <= 0x46) ||
2171
- (codepoint >= 0x30 && codepoint <= 0x39)) {
2172
- escapeSequence += sequence[i];
2173
- if (codepoint == 0x20) {
2174
- break;
2175
- }
2176
- continue;
2177
- }
2178
- break;
2179
- }
2180
- if (i == 1) {
2181
- buffer += value + sequence[i];
2182
- next(2);
2183
- continue;
2184
- }
2185
- if (escapeSequence.trimEnd().length > 0) {
2186
- const codepoint = Number(`0x${escapeSequence.trimEnd()}`);
2187
- if (codepoint == 0 ||
2188
- // leading surrogate
2189
- (0xD800 <= codepoint && codepoint <= 0xDBFF) ||
2190
- // trailing surrogate
2191
- (0xDC00 <= codepoint && codepoint <= 0xDFFF)) {
2192
- buffer += String.fromCodePoint(0xFFFD);
2193
- }
2194
- else {
2195
- buffer += String.fromCodePoint(codepoint);
2196
- }
2197
- next(escapeSequence.length + 1 + (isWhiteSpace(peek()?.charCodeAt(0)) ? 1 : 0));
2198
- continue;
2199
- }
2200
- buffer += next(2);
2201
- continue;
2202
- }
2203
- if (value == quote) {
2204
- buffer += value;
2205
- yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
2206
- next();
2207
- // i += value.length;
2208
- buffer = '';
2209
- return;
2210
- }
2211
- if (isNewLine(value.charCodeAt(0))) {
2212
- hasNewLine = true;
2213
- }
2214
- if (hasNewLine && value == ';') {
2215
- yield pushToken(buffer + value, 'Bad-string');
2216
- buffer = '';
2217
- next();
2218
- break;
2219
- }
2220
- buffer += value;
2221
- next();
2319
+ buffer += value;
2320
+ next();
2222
2321
  }
2223
2322
  if (hasNewLine) {
2224
- yield pushToken(buffer, 'Bad-string');
2323
+ yield pushToken(buffer, exports.EnumToken.BadStringTokenType);
2225
2324
  }
2226
2325
  else {
2227
2326
  // EOF - 'Unclosed-string' fixed
2228
- yield pushToken(buffer + quote, 'String');
2327
+ yield pushToken(buffer + quote, exports.EnumToken.StringTokenType);
2229
2328
  }
2230
2329
  buffer = '';
2231
2330
  }
2232
2331
  function peek(count = 1) {
2233
2332
  if (count == 1) {
2234
- return iterator.charAt(ind + 1);
2333
+ return stream.charAt(ind + 1);
2235
2334
  }
2236
- return iterator.slice(ind + 1, ind + count + 1);
2335
+ return stream.slice(ind + 1, ind + count + 1);
2237
2336
  }
2238
2337
  function prev(count = 1) {
2239
2338
  if (count == 1) {
2240
- return ind == 0 ? '' : iterator.charAt(ind - 1);
2339
+ return ind == 0 ? '' : stream.charAt(ind - 1);
2241
2340
  }
2242
- return iterator.slice(ind - 1 - count, ind - 1);
2341
+ return stream.slice(ind - 1 - count, ind - 1);
2243
2342
  }
2244
2343
  function next(count = 1) {
2245
2344
  let char = '';
@@ -2247,9 +2346,9 @@ function* tokenize(iterator) {
2247
2346
  if (count < 0) {
2248
2347
  return '';
2249
2348
  }
2250
- while (count-- && (chr = iterator.charAt(ind + 1))) {
2349
+ while (count-- && (chr = stream.charAt(ind + 1))) {
2251
2350
  char += chr;
2252
- const codepoint = iterator.charCodeAt(++ind);
2351
+ const codepoint = stream.charCodeAt(++ind);
2253
2352
  if (isNaN(codepoint)) {
2254
2353
  return char;
2255
2354
  }
@@ -2274,7 +2373,7 @@ function* tokenize(iterator) {
2274
2373
  break;
2275
2374
  }
2276
2375
  }
2277
- yield pushToken('', 'Whitespace');
2376
+ yield pushToken('', exports.EnumToken.WhitespaceTokenType);
2278
2377
  buffer = '';
2279
2378
  }
2280
2379
  switch (value) {
@@ -2294,7 +2393,7 @@ function* tokenize(iterator) {
2294
2393
  if (value == '*') {
2295
2394
  buffer += value;
2296
2395
  if (peek() == '/') {
2297
- yield pushToken(buffer + next(), 'Comment');
2396
+ yield pushToken(buffer + next(), exports.EnumToken.CommentTokenType);
2298
2397
  buffer = '';
2299
2398
  break;
2300
2399
  }
@@ -2303,7 +2402,7 @@ function* tokenize(iterator) {
2303
2402
  buffer += value;
2304
2403
  }
2305
2404
  }
2306
- yield pushToken(buffer, 'Bad-comment');
2405
+ yield pushToken(buffer, exports.EnumToken.BadCommentTokenType);
2307
2406
  buffer = '';
2308
2407
  }
2309
2408
  break;
@@ -2313,7 +2412,7 @@ function* tokenize(iterator) {
2313
2412
  buffer = '';
2314
2413
  }
2315
2414
  if (peek() == '=') {
2316
- yield pushToken('', 'Lte');
2415
+ yield pushToken('', exports.EnumToken.LteTokenType);
2317
2416
  next();
2318
2417
  break;
2319
2418
  }
@@ -2327,10 +2426,10 @@ function* tokenize(iterator) {
2327
2426
  }
2328
2427
  }
2329
2428
  if (value === '') {
2330
- yield pushToken(buffer, 'Bad-cdo');
2429
+ yield pushToken(buffer, exports.EnumToken.BadCdoTokenType);
2331
2430
  }
2332
2431
  else {
2333
- yield pushToken(buffer + next(2), 'CDOCOMM');
2432
+ yield pushToken(buffer + next(2), exports.EnumToken.CDOCOMMTokenType);
2334
2433
  }
2335
2434
  buffer = '';
2336
2435
  }
@@ -2363,7 +2462,7 @@ function* tokenize(iterator) {
2363
2462
  }
2364
2463
  if (value == '=') {
2365
2464
  buffer += value;
2366
- yield pushToken(buffer, buffer[0] == '~' ? 'Includes' : 'Dash-matches');
2465
+ yield pushToken(buffer, buffer[0] == '~' ? exports.EnumToken.IncludesTokenType : exports.EnumToken.DashMatchTokenType);
2367
2466
  buffer = '';
2368
2467
  break;
2369
2468
  }
@@ -2379,11 +2478,11 @@ function* tokenize(iterator) {
2379
2478
  buffer = '';
2380
2479
  }
2381
2480
  if (peek() == '=') {
2382
- yield pushToken('', 'Gte');
2481
+ yield pushToken('', exports.EnumToken.GteTokenType);
2383
2482
  next();
2384
2483
  }
2385
2484
  else {
2386
- yield pushToken('', 'Gt');
2485
+ yield pushToken('', exports.EnumToken.GtTokenType);
2387
2486
  }
2388
2487
  consumeWhiteSpace();
2389
2488
  break;
@@ -2397,6 +2496,7 @@ function* tokenize(iterator) {
2397
2496
  buffer += value;
2398
2497
  break;
2399
2498
  case '+':
2499
+ case '*':
2400
2500
  case ':':
2401
2501
  case ',':
2402
2502
  case '=':
@@ -2410,7 +2510,7 @@ function* tokenize(iterator) {
2410
2510
  }
2411
2511
  yield pushToken(value);
2412
2512
  buffer = '';
2413
- if (value == '+' && isWhiteSpace(peek().charCodeAt(0))) {
2513
+ if (['+', '*', '/'].includes(value) && isWhiteSpace(peek().charCodeAt(0))) {
2414
2514
  yield pushToken(next());
2415
2515
  }
2416
2516
  while (isWhiteSpace(peek().charCodeAt(0))) {
@@ -2422,7 +2522,7 @@ function* tokenize(iterator) {
2422
2522
  yield pushToken(buffer);
2423
2523
  buffer = '';
2424
2524
  }
2425
- yield pushToken('', 'End-parens');
2525
+ yield pushToken('', exports.EnumToken.EndParensTokenType);
2426
2526
  break;
2427
2527
  case '(':
2428
2528
  if (buffer.length == 0) {
@@ -2460,7 +2560,7 @@ function* tokenize(iterator) {
2460
2560
  }
2461
2561
  }
2462
2562
  if (value === '') {
2463
- yield pushToken(buffer, 'Bad-string');
2563
+ yield pushToken(buffer, exports.EnumToken.BadUrlTokenType);
2464
2564
  buffer = '';
2465
2565
  break;
2466
2566
  }
@@ -2487,7 +2587,7 @@ function* tokenize(iterator) {
2487
2587
  break;
2488
2588
  }
2489
2589
  if (!(value = next())) {
2490
- yield pushToken(buffer, hasNewLine ? 'Bad-url-token' : 'Url-token');
2590
+ yield pushToken(buffer, hasNewLine ? exports.EnumToken.BadUrlTokenType : exports.EnumToken.UrlTokenTokenType);
2491
2591
  buffer = '';
2492
2592
  break;
2493
2593
  }
@@ -2495,8 +2595,8 @@ function* tokenize(iterator) {
2495
2595
  cp = value.charCodeAt(0);
2496
2596
  // ')'
2497
2597
  if (cp == 0x29) {
2498
- yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'String');
2499
- yield pushToken('', 'End-parens');
2598
+ yield pushToken(buffer, hasNewLine ? exports.EnumToken.BadStringTokenType : exports.EnumToken.StringTokenType);
2599
+ yield pushToken('', exports.EnumToken.EndParensTokenType);
2500
2600
  buffer = '';
2501
2601
  break;
2502
2602
  }
@@ -2507,15 +2607,15 @@ function* tokenize(iterator) {
2507
2607
  continue;
2508
2608
  }
2509
2609
  if (cp == 0x29) {
2510
- yield pushToken(buffer, 'Bad-string');
2511
- yield pushToken('', 'End-parens');
2610
+ yield pushToken(buffer, exports.EnumToken.BadStringTokenType);
2611
+ yield pushToken('', exports.EnumToken.EndParensTokenType);
2512
2612
  buffer = '';
2513
2613
  break;
2514
2614
  }
2515
2615
  buffer += value;
2516
2616
  }
2517
2617
  if (hasNewLine) {
2518
- yield pushToken(buffer, 'Bad-string');
2618
+ yield pushToken(buffer, exports.EnumToken.BadStringTokenType);
2519
2619
  buffer = '';
2520
2620
  }
2521
2621
  break;
@@ -2530,8 +2630,8 @@ function* tokenize(iterator) {
2530
2630
  cp = value.charCodeAt(0);
2531
2631
  // ')'
2532
2632
  if (cp == 0x29) {
2533
- yield pushToken(buffer, 'Url-token');
2534
- yield pushToken('', 'End-parens');
2633
+ yield pushToken(buffer, exports.EnumToken.UrlTokenTokenType);
2634
+ yield pushToken('', exports.EnumToken.EndParensTokenType);
2535
2635
  buffer = '';
2536
2636
  break;
2537
2637
  }
@@ -2567,7 +2667,7 @@ function* tokenize(iterator) {
2567
2667
  }
2568
2668
  buffer += next();
2569
2669
  }
2570
- yield pushToken(buffer, 'Bad-url-token');
2670
+ yield pushToken(buffer, exports.EnumToken.BadUrlTokenType);
2571
2671
  buffer = '';
2572
2672
  break;
2573
2673
  }
@@ -2575,7 +2675,7 @@ function* tokenize(iterator) {
2575
2675
  }
2576
2676
  }
2577
2677
  if (buffer !== '') {
2578
- yield pushToken(buffer, 'Url-token');
2678
+ yield pushToken(buffer, exports.EnumToken.UrlTokenTokenType);
2579
2679
  buffer = '';
2580
2680
  break;
2581
2681
  }
@@ -2601,7 +2701,7 @@ function* tokenize(iterator) {
2601
2701
  buffer = '';
2602
2702
  }
2603
2703
  if (peek(9) == 'important') {
2604
- yield pushToken('', 'Important');
2704
+ yield pushToken('', exports.EnumToken.ImportantTokenType);
2605
2705
  next(9);
2606
2706
  buffer = '';
2607
2707
  break;
@@ -2620,33 +2720,40 @@ function* tokenize(iterator) {
2620
2720
  }
2621
2721
 
2622
2722
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
2623
- const trimWhiteSpace = ['Gt', 'Gte', 'Lt', 'Lte'];
2624
- const funcLike = ['Start-parens', 'Func', 'UrlFunc', 'Pseudo-class-func'];
2625
- /**
2626
- *
2627
- * @param iterator
2628
- * @param opt
2629
- */
2630
- async function parse$1(iterator, opt = {}) {
2631
- const startTime = performance.now();
2632
- const errors = [];
2633
- const options = {
2723
+ const trimWhiteSpace = [exports.EnumToken.GtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.LteTokenType];
2724
+ const funcLike = [exports.EnumToken.ParensTokenType, exports.EnumToken.StartParensTokenType, exports.EnumToken.FunctionTokenType, exports.EnumToken.UrlFunctionTokenType, exports.EnumToken.PseudoClassFuncTokenType];
2725
+ const BadTokensTypes = [exports.EnumToken.BadCommentTokenType,
2726
+ exports.EnumToken.BadCdoTokenType,
2727
+ exports.EnumToken.BadUrlTokenType,
2728
+ exports.EnumToken.BadStringTokenType];
2729
+ async function doParse(iterator, options = {}) {
2730
+ options = {
2634
2731
  src: '',
2635
2732
  sourcemap: false,
2636
2733
  minify: true,
2637
2734
  nestingRules: false,
2638
2735
  resolveImport: false,
2639
2736
  resolveUrls: false,
2737
+ removeCharset: false,
2640
2738
  removeEmpty: true,
2641
- ...opt
2739
+ removeDuplicateDeclarations: true,
2740
+ computeShorthand: true,
2741
+ computeCalcExpression: true,
2742
+ inlineCssVariables: false,
2743
+ ...options
2642
2744
  };
2745
+ if (options.expandNestingRules) {
2746
+ options.nestingRules = false;
2747
+ }
2643
2748
  if (options.resolveImport) {
2644
2749
  options.resolveUrls = true;
2645
2750
  }
2751
+ const startTime = performance.now();
2752
+ const errors = [];
2646
2753
  const src = options.src;
2647
2754
  const stack = [];
2648
- const ast = {
2649
- typ: "StyleSheet",
2755
+ let ast = {
2756
+ typ: 2 /* NodeType.StyleSheetNodeType */,
2650
2757
  chi: []
2651
2758
  };
2652
2759
  let tokens = [];
@@ -2668,10 +2775,14 @@ async function parse$1(iterator, opt = {}) {
2668
2775
  let i;
2669
2776
  let loc;
2670
2777
  for (i = 0; i < tokens.length; i++) {
2671
- if (tokens[i].typ == 'Comment' || tokens[i].typ == 'CDOCOMM') {
2778
+ if (tokens[i].typ == exports.EnumToken.CommentTokenType || tokens[i].typ == exports.EnumToken.CDOCOMMTokenType) {
2672
2779
  const position = map.get(tokens[i]);
2673
- if (tokens[i].typ == 'CDOCOMM' && context.typ != 'StyleSheet') {
2674
- errors.push({ action: 'drop', message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`, location: { src, ...position } });
2780
+ if (tokens[i].typ == exports.EnumToken.CDOCOMMTokenType && context.typ != 2 /* NodeType.StyleSheetNodeType */) {
2781
+ errors.push({
2782
+ action: 'drop',
2783
+ message: `CDOCOMM not allowed here ${JSON.stringify(tokens[i], null, 1)}`,
2784
+ location: { src, ...position }
2785
+ });
2675
2786
  continue;
2676
2787
  }
2677
2788
  loc = {
@@ -2684,7 +2795,7 @@ async function parse$1(iterator, opt = {}) {
2684
2795
  tokens[i].loc = loc;
2685
2796
  }
2686
2797
  }
2687
- else if (tokens[i].typ != 'Whitespace') {
2798
+ else if (tokens[i].typ != exports.EnumToken.WhitespaceTokenType) {
2688
2799
  break;
2689
2800
  }
2690
2801
  }
@@ -2693,28 +2804,33 @@ async function parse$1(iterator, opt = {}) {
2693
2804
  return null;
2694
2805
  }
2695
2806
  let delim = tokens.at(-1);
2696
- if (delim.typ == 'Semi-colon' || delim.typ == 'Block-start' || delim.typ == 'Block-end') {
2807
+ if (delim.typ == exports.EnumToken.SemiColonTokenType || delim.typ == exports.EnumToken.BlockStartTokenType || delim.typ == exports.EnumToken.BlockEndTokenType) {
2697
2808
  tokens.pop();
2698
2809
  }
2699
2810
  else {
2700
- delim = { typ: 'Semi-colon' };
2811
+ delim = { typ: exports.EnumToken.SemiColonTokenType };
2701
2812
  }
2702
2813
  // @ts-ignore
2703
- while (['Whitespace', 'Bad-string', 'Bad-comment'].includes(tokens.at(-1)?.typ)) {
2814
+ while ([exports.EnumToken.WhitespaceTokenType, exports.EnumToken.BadStringTokenType, exports.EnumToken.BadCommentTokenType].includes(tokens.at(-1)?.typ)) {
2704
2815
  tokens.pop();
2705
2816
  }
2706
2817
  if (tokens.length == 0) {
2707
2818
  return null;
2708
2819
  }
2709
- if (tokens[0]?.typ == 'At-rule') {
2820
+ if (tokens[0]?.typ == exports.EnumToken.AtRuleTokenType) {
2710
2821
  const atRule = tokens.shift();
2711
2822
  const position = map.get(atRule);
2712
- if (atRule.val == 'charset' && position.ind > 0) {
2713
- errors.push({ action: 'drop', message: 'parse: invalid @charset', location: { src, ...position } });
2714
- return null;
2823
+ if (atRule.val == 'charset') {
2824
+ if (position.ind > 0) {
2825
+ errors.push({ action: 'drop', message: 'doParse: invalid @charset', location: { src, ...position } });
2826
+ return null;
2827
+ }
2828
+ if (options.removeCharset) {
2829
+ return null;
2830
+ }
2715
2831
  }
2716
2832
  // @ts-ignore
2717
- while (['Whitespace'].includes(tokens[0]?.typ)) {
2833
+ while ([exports.EnumToken.WhitespaceTokenType].includes(tokens[0]?.typ)) {
2718
2834
  tokens.shift();
2719
2835
  }
2720
2836
  if (atRule.val == 'import') {
@@ -2723,10 +2839,10 @@ async function parse$1(iterator, opt = {}) {
2723
2839
  let i = context.chi.length;
2724
2840
  while (i--) {
2725
2841
  const type = context.chi[i].typ;
2726
- if (type == 'Comment') {
2842
+ if (type == 0 /* NodeType.CommentNodeType */) {
2727
2843
  continue;
2728
2844
  }
2729
- if (type != 'AtRule') {
2845
+ if (type != 3 /* NodeType.AtRuleNodeType */) {
2730
2846
  errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
2731
2847
  return null;
2732
2848
  }
@@ -2739,33 +2855,33 @@ async function parse$1(iterator, opt = {}) {
2739
2855
  }
2740
2856
  }
2741
2857
  // @ts-ignore
2742
- if (tokens[0]?.typ != 'String' && tokens[0]?.typ != 'UrlFunc') {
2743
- errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
2858
+ if (tokens[0]?.typ != exports.EnumToken.StringTokenType && tokens[0]?.typ != exports.EnumToken.UrlFunctionTokenType) {
2859
+ errors.push({ action: 'drop', message: 'doParse: invalid @import', location: { src, ...position } });
2744
2860
  return null;
2745
2861
  }
2746
2862
  // @ts-ignore
2747
- if (tokens[0].typ == 'UrlFunc' && tokens[1]?.typ != 'Url-token' && tokens[1]?.typ != 'String') {
2748
- errors.push({ action: 'drop', message: 'parse: invalid @import', location: { src, ...position } });
2863
+ if (tokens[0].typ == exports.EnumToken.UrlFunctionTokenType && tokens[1]?.typ != exports.EnumToken.UrlTokenTokenType && tokens[1]?.typ != exports.EnumToken.StringTokenType) {
2864
+ errors.push({ action: 'drop', message: 'doParse: invalid @import', location: { src, ...position } });
2749
2865
  return null;
2750
2866
  }
2751
2867
  }
2752
2868
  if (atRule.val == 'import') {
2753
2869
  // @ts-ignore
2754
- if (tokens[0].typ == 'UrlFunc' && tokens[1].typ == 'Url-token') {
2870
+ if (tokens[0].typ == exports.EnumToken.UrlFunctionTokenType && tokens[1].typ == exports.EnumToken.UrlTokenTokenType) {
2755
2871
  tokens.shift();
2756
2872
  // @ts-ignore
2757
- tokens[0].typ = 'String';
2873
+ tokens[0].typ = exports.EnumToken.StringTokenType;
2758
2874
  // @ts-ignore
2759
2875
  tokens[0].val = `"${tokens[0].val}"`;
2760
2876
  }
2761
2877
  // @ts-ignore
2762
- if (tokens[0].typ == 'String') {
2878
+ if (tokens[0].typ == exports.EnumToken.StringTokenType) {
2763
2879
  if (options.resolveImport) {
2764
2880
  const url = tokens[0].val.slice(1, -1);
2765
2881
  try {
2766
2882
  // @ts-ignore
2767
2883
  const root = await options.load(url, options.src).then((src) => {
2768
- return parse$1(src, Object.assign({}, options, {
2884
+ return doParse(src, Object.assign({}, options, {
2769
2885
  minify: false,
2770
2886
  // @ts-ignore
2771
2887
  src: options.resolve(url, options.src).absolute
@@ -2773,6 +2889,7 @@ async function parse$1(iterator, opt = {}) {
2773
2889
  });
2774
2890
  bytesIn += root.stats.bytesIn;
2775
2891
  if (root.ast.chi.length > 0) {
2892
+ // @todo - filter charset, layer and scope
2776
2893
  context.chi.push(...root.ast.chi);
2777
2894
  }
2778
2895
  if (root.errors.length > 0) {
@@ -2782,7 +2899,7 @@ async function parse$1(iterator, opt = {}) {
2782
2899
  }
2783
2900
  catch (error) {
2784
2901
  // @ts-ignore
2785
- errors.push({ action: 'ignore', message: 'parse: ' + error.message, error });
2902
+ errors.push({ action: 'ignore', message: 'doParse: ' + error.message, error });
2786
2903
  }
2787
2904
  }
2788
2905
  }
@@ -2795,12 +2912,12 @@ async function parse$1(iterator, opt = {}) {
2795
2912
  return acc;
2796
2913
  }, []);
2797
2914
  const node = {
2798
- typ: 'AtRule',
2915
+ typ: 3 /* NodeType.AtRuleNodeType */,
2799
2916
  nam: renderToken(atRule, { removeComments: true }),
2800
2917
  val: raw.join('')
2801
2918
  };
2802
2919
  Object.defineProperty(node, 'raw', { enumerable: false, configurable: true, writable: true, value: raw });
2803
- if (delim.typ == 'Block-start') {
2920
+ if (delim.typ == exports.EnumToken.BlockStartTokenType) {
2804
2921
  node.chi = [];
2805
2922
  }
2806
2923
  loc = {
@@ -2812,15 +2929,15 @@ async function parse$1(iterator, opt = {}) {
2812
2929
  }
2813
2930
  // @ts-ignore
2814
2931
  context.chi.push(node);
2815
- return delim.typ == 'Block-start' ? node : null;
2932
+ return delim.typ == exports.EnumToken.BlockStartTokenType ? node : null;
2816
2933
  }
2817
2934
  else {
2818
2935
  // rule
2819
- if (delim.typ == 'Block-start') {
2936
+ if (delim.typ == exports.EnumToken.BlockStartTokenType) {
2820
2937
  const position = map.get(tokens[0]);
2821
2938
  const uniq = new Map;
2822
2939
  parseTokens(tokens, { minify: true }).reduce((acc, curr, index, array) => {
2823
- if (curr.typ == 'Whitespace') {
2940
+ if (curr.typ == exports.EnumToken.WhitespaceTokenType) {
2824
2941
  if (trimWhiteSpace.includes(array[index - 1]?.typ) ||
2825
2942
  trimWhiteSpace.includes(array[index + 1]?.typ) ||
2826
2943
  combinators.includes(array[index - 1]?.val) ||
@@ -2841,7 +2958,7 @@ async function parse$1(iterator, opt = {}) {
2841
2958
  return acc;
2842
2959
  }, uniq);
2843
2960
  const node = {
2844
- typ: 'Rule',
2961
+ typ: 4 /* NodeType.RuleNodeType */,
2845
2962
  // @ts-ignore
2846
2963
  sel: [...uniq.keys()].join(','),
2847
2964
  chi: []
@@ -2866,10 +2983,10 @@ async function parse$1(iterator, opt = {}) {
2866
2983
  // @ts-ignore
2867
2984
  let value = null;
2868
2985
  for (let i = 0; i < tokens.length; i++) {
2869
- if (tokens[i].typ == 'Comment') {
2986
+ if (tokens[i].typ == exports.EnumToken.CommentTokenType) {
2870
2987
  continue;
2871
2988
  }
2872
- if (tokens[i].typ == 'Colon') {
2989
+ if (tokens[i].typ == exports.EnumToken.ColonTokenType) {
2873
2990
  name = tokens.slice(0, i);
2874
2991
  value = parseTokens(tokens.slice(i + 1), {
2875
2992
  parseColor: true,
@@ -2886,46 +3003,38 @@ async function parse$1(iterator, opt = {}) {
2886
3003
  const position = map.get(name[0]);
2887
3004
  if (name.length > 0) {
2888
3005
  for (let i = 1; i < name.length; i++) {
2889
- if (name[i].typ != 'Whitespace' && name[i].typ != 'Comment') {
3006
+ if (name[i].typ != exports.EnumToken.WhitespaceTokenType && name[i].typ != exports.EnumToken.CommentTokenType) {
2890
3007
  errors.push({
2891
3008
  action: 'drop',
2892
- message: 'parse: invalid declaration',
3009
+ message: 'doParse: invalid declaration',
2893
3010
  location: { src, ...position }
2894
3011
  });
2895
3012
  return null;
2896
3013
  }
2897
3014
  }
2898
3015
  }
2899
- if (value == null) {
2900
- errors.push({
2901
- action: 'drop',
2902
- message: 'parse: invalid declaration',
2903
- location: { src, ...position }
2904
- });
2905
- return null;
2906
- }
2907
- if (value.length == 0) {
3016
+ if (value == null || value.length == 0) {
2908
3017
  errors.push({
2909
3018
  action: 'drop',
2910
- message: 'parse: invalid declaration',
3019
+ message: 'doParse: invalid declaration',
2911
3020
  location: { src, ...position }
2912
3021
  });
2913
3022
  return null;
2914
3023
  }
2915
3024
  const node = {
2916
- typ: 'Declaration',
3025
+ typ: 5 /* NodeType.DeclarationNodeType */,
2917
3026
  // @ts-ignore
2918
3027
  nam: renderToken(name.shift(), { removeComments: true }),
2919
3028
  // @ts-ignore
2920
3029
  val: value
2921
3030
  };
2922
- while (node.val[0]?.typ == 'Whitespace') {
3031
+ while (node.val[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
2923
3032
  node.val.shift();
2924
3033
  }
2925
3034
  if (node.val.length == 0) {
2926
3035
  errors.push({
2927
3036
  action: 'drop',
2928
- message: 'parse: invalid declaration',
3037
+ message: 'doParse: invalid declaration',
2929
3038
  location: { src, ...position }
2930
3039
  });
2931
3040
  return null;
@@ -2945,8 +3054,8 @@ async function parse$1(iterator, opt = {}) {
2945
3054
  let item;
2946
3055
  while (item = iter.next().value) {
2947
3056
  bytesIn = item.bytesIn;
2948
- // parse error
2949
- if (item.hint != null && item.hint.startsWith('Bad-')) {
3057
+ // doParse error
3058
+ if (item.hint != null && BadTokensTypes.includes(item.hint)) {
2950
3059
  // bad token
2951
3060
  continue;
2952
3061
  }
@@ -3006,9 +3115,12 @@ async function parse$1(iterator, opt = {}) {
3006
3115
  break;
3007
3116
  }
3008
3117
  const endParseTime = performance.now();
3118
+ if (options.expandNestingRules) {
3119
+ ast = expand(ast);
3120
+ }
3009
3121
  if (options.minify) {
3010
3122
  if (ast.chi.length > 0) {
3011
- minify(ast, options, true, errors);
3123
+ minify(ast, options, true, errors, false);
3012
3124
  }
3013
3125
  }
3014
3126
  const endTime = performance.now();
@@ -3038,81 +3150,81 @@ function getTokenType(val, hint) {
3038
3150
  }
3039
3151
  if (hint != null) {
3040
3152
  return ([
3041
- 'Whitespace', 'Semi-colon', 'Colon', 'Block-start',
3042
- 'Block-start', 'Attr-start', 'Attr-end', 'Start-parens', 'End-parens',
3043
- 'Comma', 'Gt', 'Lt', 'Gte', 'Lte', 'EOF'
3153
+ exports.EnumToken.WhitespaceTokenType, exports.EnumToken.SemiColonTokenType, exports.EnumToken.ColonTokenType, exports.EnumToken.BlockStartTokenType,
3154
+ exports.EnumToken.BlockStartTokenType, exports.EnumToken.AttrStartTokenType, exports.EnumToken.AttrEndTokenType, exports.EnumToken.StartParensTokenType, exports.EnumToken.EndParensTokenType,
3155
+ exports.EnumToken.CommaTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.EOFTokenType
3044
3156
  ].includes(hint) ? { typ: hint } : { typ: hint, val });
3045
3157
  }
3046
3158
  if (val == ' ') {
3047
- return { typ: 'Whitespace' };
3159
+ return { typ: exports.EnumToken.WhitespaceTokenType };
3048
3160
  }
3049
3161
  if (val == ';') {
3050
- return { typ: 'Semi-colon' };
3162
+ return { typ: exports.EnumToken.SemiColonTokenType };
3051
3163
  }
3052
3164
  if (val == '{') {
3053
- return { typ: 'Block-start' };
3165
+ return { typ: exports.EnumToken.BlockStartTokenType };
3054
3166
  }
3055
3167
  if (val == '}') {
3056
- return { typ: 'Block-end' };
3168
+ return { typ: exports.EnumToken.BlockEndTokenType };
3057
3169
  }
3058
3170
  if (val == '[') {
3059
- return { typ: 'Attr-start' };
3171
+ return { typ: exports.EnumToken.AttrStartTokenType };
3060
3172
  }
3061
3173
  if (val == ']') {
3062
- return { typ: 'Attr-end' };
3174
+ return { typ: exports.EnumToken.AttrEndTokenType };
3063
3175
  }
3064
3176
  if (val == ':') {
3065
- return { typ: 'Colon' };
3177
+ return { typ: exports.EnumToken.ColonTokenType };
3066
3178
  }
3067
3179
  if (val == ')') {
3068
- return { typ: 'End-parens' };
3180
+ return { typ: exports.EnumToken.EndParensTokenType };
3069
3181
  }
3070
3182
  if (val == '(') {
3071
- return { typ: 'Start-parens' };
3183
+ return { typ: exports.EnumToken.StartParensTokenType };
3072
3184
  }
3073
3185
  if (val == '=') {
3074
- return { typ: 'Delim', val };
3186
+ return { typ: exports.EnumToken.DelimTokenType, val };
3075
3187
  }
3076
3188
  if (val == ';') {
3077
- return { typ: 'Semi-colon' };
3189
+ return { typ: exports.EnumToken.SemiColonTokenType };
3078
3190
  }
3079
3191
  if (val == ',') {
3080
- return { typ: 'Comma' };
3192
+ return { typ: exports.EnumToken.CommaTokenType };
3081
3193
  }
3082
3194
  if (val == '<') {
3083
- return { typ: 'Lt' };
3195
+ return { typ: exports.EnumToken.LtTokenType };
3084
3196
  }
3085
3197
  if (val == '>') {
3086
- return { typ: 'Gt' };
3198
+ return { typ: exports.EnumToken.GtTokenType };
3087
3199
  }
3088
3200
  if (isPseudo(val)) {
3089
3201
  return val.endsWith('(') ? {
3090
- typ: 'Pseudo-class-func',
3202
+ typ: exports.EnumToken.PseudoClassFuncTokenType,
3091
3203
  val: val.slice(0, -1),
3092
3204
  chi: []
3093
3205
  }
3094
3206
  : {
3095
- typ: 'Pseudo-class',
3207
+ typ: exports.EnumToken.PseudoClassTokenType,
3096
3208
  val
3097
3209
  };
3098
3210
  }
3099
3211
  if (isAtKeyword(val)) {
3100
3212
  return {
3101
- typ: 'At-rule',
3213
+ typ: exports.EnumToken.AtRuleTokenType,
3102
3214
  val: val.slice(1)
3103
3215
  };
3104
3216
  }
3105
3217
  if (isFunction(val)) {
3106
3218
  val = val.slice(0, -1);
3107
3219
  return {
3108
- typ: val == 'url' ? 'UrlFunc' : 'Func',
3220
+ typ: val == 'url' ? exports.EnumToken.UrlFunctionTokenType : exports.EnumToken.FunctionTokenType,
3109
3221
  val,
3110
3222
  chi: []
3111
3223
  };
3112
3224
  }
3113
3225
  if (isNumber(val)) {
3114
3226
  return {
3115
- typ: 'Number',
3227
+ typ: exports.EnumToken.NumberTokenType,
3116
3228
  val
3117
3229
  };
3118
3230
  }
@@ -3121,97 +3233,97 @@ function getTokenType(val, hint) {
3121
3233
  }
3122
3234
  if (isPercentage(val)) {
3123
3235
  return {
3124
- typ: 'Perc',
3236
+ typ: exports.EnumToken.PercentageTokenType,
3125
3237
  val: val.slice(0, -1)
3126
3238
  };
3127
3239
  }
3128
3240
  const v = val.toLowerCase();
3129
3241
  if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
3130
3242
  return {
3131
- typ: 'Color',
3243
+ typ: exports.EnumToken.ColorTokenType,
3132
3244
  val,
3133
3245
  kin: 'lit'
3134
3246
  };
3135
3247
  }
3136
3248
  if (isIdent(val)) {
3137
3249
  return {
3138
- typ: 'Iden',
3250
+ typ: exports.EnumToken.IdenTokenType,
3139
3251
  val
3140
3252
  };
3141
3253
  }
3142
3254
  if (val.charAt(0) == '#' && isHexColor(val)) {
3143
3255
  return {
3144
- typ: 'Color',
3256
+ typ: exports.EnumToken.ColorTokenType,
3145
3257
  val,
3146
3258
  kin: 'hex'
3147
3259
  };
3148
3260
  }
3149
3261
  if (val.charAt(0) == '#' && isHash(val)) {
3150
3262
  return {
3151
- typ: 'Hash',
3263
+ typ: exports.EnumToken.HashTokenType,
3152
3264
  val
3153
3265
  };
3154
3266
  }
3155
3267
  if ('"\''.includes(val.charAt(0))) {
3156
3268
  return {
3157
- typ: 'Unclosed-string',
3269
+ typ: exports.EnumToken.UnclosedStringTokenType,
3158
3270
  val
3159
3271
  };
3160
3272
  }
3161
3273
  return {
3162
- typ: 'Literal',
3274
+ typ: exports.EnumToken.LiteralTokenType,
3163
3275
  val
3164
3276
  };
3165
3277
  }
3166
3278
  function parseTokens(tokens, options = {}) {
3167
3279
  for (let i = 0; i < tokens.length; i++) {
3168
3280
  const t = tokens[i];
3169
- if (t.typ == 'Whitespace' && ((i == 0 ||
3281
+ if (t.typ == exports.EnumToken.WhitespaceTokenType && ((i == 0 ||
3170
3282
  i + 1 == tokens.length ||
3171
- ['Comma', 'Gte', 'Lte'].includes(tokens[i + 1].typ)) ||
3283
+ [exports.EnumToken.CommaTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LteTokenType].includes(tokens[i + 1].typ)) ||
3172
3284
  (i > 0 &&
3173
- // tokens[i + 1]?.typ != 'Literal' ||
3285
+ // tokens[i + 1]?.typ != Literal ||
3174
3286
  // funcLike.includes(tokens[i - 1].typ) &&
3175
3287
  // !['var', 'calc'].includes((<FunctionToken>tokens[i - 1]).val)))) &&
3176
3288
  trimWhiteSpace.includes(tokens[i - 1].typ)))) {
3177
3289
  tokens.splice(i--, 1);
3178
3290
  continue;
3179
3291
  }
3180
- if (t.typ == 'Colon') {
3292
+ if (t.typ == exports.EnumToken.ColonTokenType) {
3181
3293
  const typ = tokens[i + 1]?.typ;
3182
3294
  if (typ != null) {
3183
- if (typ == 'Func') {
3295
+ if (typ == exports.EnumToken.FunctionTokenType) {
3184
3296
  tokens[i + 1].val = ':' + tokens[i + 1].val;
3185
- tokens[i + 1].typ = 'Pseudo-class-func';
3297
+ tokens[i + 1].typ = exports.EnumToken.PseudoClassFuncTokenType;
3186
3298
  }
3187
- else if (typ == 'Iden') {
3299
+ else if (typ == exports.EnumToken.IdenTokenType) {
3188
3300
  tokens[i + 1].val = ':' + tokens[i + 1].val;
3189
- tokens[i + 1].typ = 'Pseudo-class';
3301
+ tokens[i + 1].typ = exports.EnumToken.PseudoClassTokenType;
3190
3302
  }
3191
- if (typ == 'Func' || typ == 'Iden') {
3303
+ if (typ == exports.EnumToken.FunctionTokenType || typ == exports.EnumToken.IdenTokenType) {
3192
3304
  tokens.splice(i, 1);
3193
3305
  i--;
3194
3306
  continue;
3195
3307
  }
3196
3308
  }
3197
3309
  }
3198
- if (t.typ == 'Attr-start') {
3310
+ if (t.typ == exports.EnumToken.AttrStartTokenType) {
3199
3311
  let k = i;
3200
3312
  let inAttr = 1;
3201
3313
  while (++k < tokens.length) {
3202
- if (tokens[k].typ == 'Attr-end') {
3314
+ if (tokens[k].typ == exports.EnumToken.AttrEndTokenType) {
3203
3315
  inAttr--;
3204
3316
  }
3205
- else if (tokens[k].typ == 'Attr-start') {
3317
+ else if (tokens[k].typ == exports.EnumToken.AttrStartTokenType) {
3206
3318
  inAttr++;
3207
3319
  }
3208
3320
  if (inAttr == 0) {
3209
3321
  break;
3210
3322
  }
3211
3323
  }
3212
- Object.assign(t, { typ: 'Attr', chi: tokens.splice(i + 1, k - i) });
3324
+ Object.assign(t, { typ: exports.EnumToken.AttrTokenType, chi: tokens.splice(i + 1, k - i) });
3213
3325
  // @ts-ignore
3214
- if (t.chi.at(-1).typ == 'Attr-end') {
3326
+ if (t.chi.at(-1).typ == exports.EnumToken.AttrEndTokenType) {
3215
3327
  // @ts-ignore
3216
3328
  t.chi.pop();
3217
3329
  // @ts-ignore
@@ -3222,10 +3334,10 @@ function parseTokens(tokens, options = {}) {
3222
3334
  }
3223
3335
  // @ts-ignore
3224
3336
  t.chi.forEach(val => {
3225
- if (val.typ == 'String') {
3337
+ if (val.typ == exports.EnumToken.StringTokenType) {
3226
3338
  const slice = val.val.slice(1, -1);
3227
3339
  if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
3228
- Object.assign(val, { typ: 'Iden', val: slice });
3340
+ Object.assign(val, { typ: exports.EnumToken.IdenTokenType, val: slice });
3229
3341
  }
3230
3342
  }
3231
3343
  });
@@ -3236,18 +3348,18 @@ function parseTokens(tokens, options = {}) {
3236
3348
  let parens = 1;
3237
3349
  let k = i;
3238
3350
  while (++k < tokens.length) {
3239
- if (tokens[k].typ == 'Colon') {
3351
+ if (tokens[k].typ == exports.EnumToken.ColonTokenType) {
3240
3352
  const typ = tokens[k + 1]?.typ;
3241
3353
  if (typ != null) {
3242
- if (typ == 'Iden') {
3243
- tokens[k + 1].typ = 'Pseudo-class';
3354
+ if (typ == exports.EnumToken.IdenTokenType) {
3355
+ tokens[k + 1].typ = exports.EnumToken.PseudoClassTokenType;
3244
3356
  tokens[k + 1].val = ':' + tokens[k + 1].val;
3245
3357
  }
3246
- else if (typ == 'Func') {
3247
- tokens[k + 1].typ = 'Pseudo-class-func';
3358
+ else if (typ == exports.EnumToken.FunctionTokenType) {
3359
+ tokens[k + 1].typ = exports.EnumToken.PseudoClassFuncTokenType;
3248
3360
  tokens[k + 1].val = ':' + tokens[k + 1].val;
3249
3361
  }
3250
- if (typ == 'Func' || typ == 'Iden') {
3362
+ if (typ == exports.EnumToken.FunctionTokenType || typ == exports.EnumToken.IdenTokenType) {
3251
3363
  tokens.splice(k, 1);
3252
3364
  k--;
3253
3365
  continue;
@@ -3257,7 +3369,7 @@ function parseTokens(tokens, options = {}) {
3257
3369
  if (funcLike.includes(tokens[k].typ)) {
3258
3370
  parens++;
3259
3371
  }
3260
- else if (tokens[k].typ == 'End-parens') {
3372
+ else if (tokens[k].typ == exports.EnumToken.EndParensTokenType) {
3261
3373
  parens--;
3262
3374
  }
3263
3375
  if (parens == 0) {
@@ -3267,29 +3379,55 @@ function parseTokens(tokens, options = {}) {
3267
3379
  // @ts-ignore
3268
3380
  t.chi = tokens.splice(i + 1, k - i);
3269
3381
  // @ts-ignore
3270
- if (t.chi.at(-1)?.typ == 'End-parens') {
3382
+ if (t.chi.at(-1)?.typ == exports.EnumToken.EndParensTokenType) {
3271
3383
  // @ts-ignore
3272
3384
  t.chi.pop();
3273
3385
  }
3386
+ if (t.typ == exports.EnumToken.FunctionTokenType && t.val == 'calc') {
3387
+ for (const { value, parent } of walkValues(t.chi)) {
3388
+ if (value.typ == exports.EnumToken.WhitespaceTokenType) {
3389
+ const p = (parent ?? t);
3390
+ for (let i = 0; i < (p).chi.length; i++) {
3391
+ // @ts-ignore
3392
+ if (p.chi[i] == value) {
3393
+ // @ts-ignore
3394
+ (p).chi.splice(i, 1);
3395
+ i--;
3396
+ break;
3397
+ }
3398
+ }
3399
+ }
3400
+ else if (value.typ == exports.EnumToken.LiteralTokenType && ['+', '-', '/', '*'].includes(value.val)) {
3401
+ // @ts-ignore
3402
+ value.typ = value.val == '+' ? exports.EnumToken.Add : (value.val == '-' ? exports.EnumToken.Sub : (value.val == '*' ? exports.EnumToken.Mul : exports.EnumToken.Div));
3403
+ // @ts-ignore
3404
+ delete value.val;
3405
+ }
3406
+ }
3407
+ }
3408
+ else if (t.typ == exports.EnumToken.StartParensTokenType) {
3409
+ // @ts-ignore
3410
+ t.typ = exports.EnumToken.ParensTokenType;
3411
+ }
3274
3412
  // @ts-ignore
3275
- if (options.parseColor && t.typ == 'Func' && isColor(t)) {
3413
+ if (options.parseColor && t.typ == exports.EnumToken.FunctionTokenType && isColor(t)) {
3276
3414
  // if (isColor) {
3277
3415
  // @ts-ignore
3278
- t.typ = 'Color';
3416
+ t.typ = exports.EnumToken.ColorTokenType;
3279
3417
  // @ts-ignore
3280
3418
  t.kin = t.val;
3281
3419
  // @ts-ignore
3282
3420
  let m = t.chi.length;
3283
3421
  while (m-- > 0) {
3284
3422
  // @ts-ignore
3285
- if (['Literal'].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
3423
+ if ([exports.EnumToken.LiteralTokenType].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
3286
3424
  // @ts-ignore
3287
- if (t.chi[m + 1]?.typ == 'Whitespace') {
3425
+ if (t.chi[m + 1]?.typ == exports.EnumToken.WhitespaceTokenType) {
3288
3426
  // @ts-ignore
3289
3427
  t.chi.splice(m + 1, 1);
3290
3428
  }
3291
3429
  // @ts-ignore
3292
- if (t.chi[m - 1]?.typ == 'Whitespace') {
3430
+ if (t.chi[m - 1]?.typ == exports.EnumToken.WhitespaceTokenType) {
3293
3431
  // @ts-ignore
3294
3432
  t.chi.splice(m - 1, 1);
3295
3433
  m--;
@@ -3297,22 +3435,21 @@ function parseTokens(tokens, options = {}) {
3297
3435
  }
3298
3436
  }
3299
3437
  continue;
3300
- // }
3301
3438
  }
3302
- if (t.typ == 'UrlFunc') {
3439
+ if (t.typ == exports.EnumToken.UrlFunctionTokenType) {
3303
3440
  // @ts-ignore
3304
- if (t.chi[0]?.typ == 'String') {
3441
+ if (t.chi[0]?.typ == exports.EnumToken.StringTokenType) {
3305
3442
  // @ts-ignore
3306
3443
  const value = t.chi[0].val.slice(1, -1);
3307
3444
  // @ts-ignore
3308
3445
  if (t.chi[0].val.slice(1, 5) != 'data:' && urlTokenMatcher.test(value)) {
3309
3446
  // @ts-ignore
3310
- t.chi[0].typ = 'Url-token';
3447
+ t.chi[0].typ = exports.EnumToken.UrlTokenTokenType;
3311
3448
  // @ts-ignore
3312
3449
  t.chi[0].val = options.src !== '' && options.resolveUrls ? options.resolve(value, options.src).absolute : value;
3313
3450
  }
3314
3451
  }
3315
- if (t.chi[0]?.typ == 'Url-token') {
3452
+ if (t.chi[0]?.typ == exports.EnumToken.UrlTokenTokenType) {
3316
3453
  if (options.src !== '' && options.resolveUrls) {
3317
3454
  // @ts-ignore
3318
3455
  t.chi[0].val = options.resolve(t.chi[0].val, options.src, options.cwd).relative;
@@ -3323,13 +3460,13 @@ function parseTokens(tokens, options = {}) {
3323
3460
  if (t.chi.length > 0) {
3324
3461
  // @ts-ignore
3325
3462
  parseTokens(t.chi, options);
3326
- if (t.typ == 'Pseudo-class-func' && t.val == ':is' && options.minify) {
3463
+ if (t.typ == exports.EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
3327
3464
  //
3328
- const count = t.chi.filter(t => t.typ != 'Comment').length;
3465
+ const count = t.chi.filter(t => t.typ != exports.EnumToken.CommentTokenType).length;
3329
3466
  if (count == 1 ||
3330
3467
  (i == 0 &&
3331
- (tokens[i + 1]?.typ == 'Comma' || tokens.length == i + 1)) ||
3332
- (tokens[i - 1]?.typ == 'Comma' && (tokens[i + 1]?.typ == 'Comma' || tokens.length == i + 1))) {
3468
+ (tokens[i + 1]?.typ == exports.EnumToken.CommaTokenType || tokens.length == i + 1)) ||
3469
+ (tokens[i - 1]?.typ == exports.EnumToken.CommaTokenType && (tokens[i + 1]?.typ == exports.EnumToken.CommaTokenType || tokens.length == i + 1))) {
3333
3470
  tokens.splice(i, 1, ...t.chi);
3334
3471
  i = Math.max(0, i - t.chi.length);
3335
3472
  }
@@ -3338,22 +3475,22 @@ function parseTokens(tokens, options = {}) {
3338
3475
  continue;
3339
3476
  }
3340
3477
  if (options.parseColor) {
3341
- if (t.typ == 'Iden') {
3478
+ if (t.typ == exports.EnumToken.IdenTokenType) {
3342
3479
  // named color
3343
3480
  const value = t.val.toLowerCase();
3344
3481
  if (value in COLORS_NAMES) {
3345
3482
  Object.assign(t, {
3346
- typ: 'Color',
3483
+ typ: exports.EnumToken.ColorTokenType,
3347
3484
  val: COLORS_NAMES[value].length < value.length ? COLORS_NAMES[value] : value,
3348
3485
  kin: 'hex'
3349
3486
  });
3350
3487
  }
3351
3488
  continue;
3352
3489
  }
3353
- if (t.typ == 'Hash' && isHexColor(t.val)) {
3490
+ if (t.typ == exports.EnumToken.HashTokenType && isHexColor(t.val)) {
3354
3491
  // hex color
3355
3492
  // @ts-ignore
3356
- t.typ = 'Color';
3493
+ t.typ = exports.EnumToken.ColorTokenType;
3357
3494
  // @ts-ignore
3358
3495
  t.kin = 'hex';
3359
3496
  }
@@ -3362,43 +3499,544 @@ function parseTokens(tokens, options = {}) {
3362
3499
  return tokens;
3363
3500
  }
3364
3501
 
3365
- const propertiesConfig = getConfig();
3366
- class PropertyMap {
3367
- config;
3368
- declarations;
3369
- requiredCount;
3370
- pattern;
3371
- constructor(config) {
3372
- const values = Object.values(config.properties);
3373
- this.requiredCount = values.reduce((acc, curr) => curr.required ? ++acc : acc, 0) || values.length;
3374
- this.config = config;
3375
- this.declarations = new Map;
3376
- this.pattern = config.pattern.split(/\s/);
3502
+ function eq(a, b) {
3503
+ if (a == null || b == null) {
3504
+ return a == b;
3377
3505
  }
3378
- add(declaration) {
3379
- for (const val of declaration.val) {
3380
- Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
3506
+ if (typeof a != 'object' || typeof b != 'object') {
3507
+ return a === b;
3508
+ }
3509
+ if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) {
3510
+ return false;
3511
+ }
3512
+ if (Array.isArray(a)) {
3513
+ if (a.length != b.length) {
3514
+ return false;
3381
3515
  }
3382
- if (declaration.nam == this.config.shorthand) {
3383
- this.declarations = new Map;
3384
- this.declarations.set(declaration.nam, declaration);
3516
+ let i = 0;
3517
+ for (; i < a.length; i++) {
3518
+ if (!eq(a[i], b[i])) {
3519
+ return false;
3520
+ }
3385
3521
  }
3386
- else {
3387
- const separator = this.config.separator;
3388
- // expand shorthand
3389
- if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
3390
- const tokens = {};
3391
- const values = [];
3392
- // @ts-ignore
3393
- this.declarations.get(this.config.shorthand).val.slice().reduce((acc, curr) => {
3394
- if (separator != null && separator.typ == curr.typ && eq(separator, curr)) {
3395
- acc.push([]);
3396
- return acc;
3522
+ return true;
3523
+ }
3524
+ const k1 = Object.keys(a);
3525
+ const k2 = Object.keys(b);
3526
+ if (k1.length != k2.length) {
3527
+ return false;
3528
+ }
3529
+ let key;
3530
+ for (key of k1) {
3531
+ if (!(key in b) || !eq(a[key], b[key])) {
3532
+ return false;
3533
+ }
3534
+ }
3535
+ return true;
3536
+ }
3537
+
3538
+ function* walk(node) {
3539
+ const parents = [node];
3540
+ const root = node;
3541
+ const weakMap = new WeakMap;
3542
+ while (parents.length > 0) {
3543
+ node = parents.shift();
3544
+ // @ts-ignore
3545
+ yield { node, parent: weakMap.get(node), root };
3546
+ if ('chi' in node) {
3547
+ for (const child of node.chi) {
3548
+ weakMap.set(child, node);
3549
+ }
3550
+ parents.unshift(...node.chi);
3551
+ }
3552
+ }
3553
+ }
3554
+ function* walkValues(values) {
3555
+ const stack = values.slice();
3556
+ const weakMap = new WeakMap;
3557
+ let value;
3558
+ while (stack.length > 0) {
3559
+ value = stack.shift();
3560
+ // @ts-ignore
3561
+ yield { value, parent: weakMap.get(value) };
3562
+ if ('chi' in value) {
3563
+ for (const child of value.chi) {
3564
+ weakMap.set(child, value);
3565
+ }
3566
+ stack.unshift(...value.chi);
3567
+ }
3568
+ }
3569
+ }
3570
+
3571
+ function expand(ast) {
3572
+ //
3573
+ if (![4 /* NodeType.RuleNodeType */, 2 /* NodeType.StyleSheetNodeType */, 3 /* NodeType.AtRuleNodeType */].includes(ast.typ)) {
3574
+ return ast;
3575
+ }
3576
+ if (4 /* NodeType.RuleNodeType */ == ast.typ) {
3577
+ return {
3578
+ typ: 2 /* NodeType.StyleSheetNodeType */,
3579
+ chi: expandRule(ast)
3580
+ };
3581
+ }
3582
+ if (!('chi' in ast)) {
3583
+ return ast;
3584
+ }
3585
+ const result = { ...ast, chi: [] };
3586
+ // @ts-ignore
3587
+ for (let i = 0; i < ast.chi.length; i++) {
3588
+ // @ts-ignore
3589
+ const node = ast.chi[i];
3590
+ if (node.typ == 4 /* NodeType.RuleNodeType */) {
3591
+ // @ts-ignore
3592
+ result.chi.push(...expandRule(node));
3593
+ // i += expanded.length - 1;
3594
+ }
3595
+ else if (node.typ == 3 /* NodeType.AtRuleNodeType */ && 'chi' in node) {
3596
+ let hasRule = false;
3597
+ let j = node.chi.length;
3598
+ while (j--) {
3599
+ if (node.chi[j].typ == 4 /* NodeType.RuleNodeType */ || node.chi[j].typ == 3 /* NodeType.AtRuleNodeType */) {
3600
+ hasRule = true;
3601
+ break;
3602
+ }
3603
+ }
3604
+ // @ts-ignore
3605
+ result.chi.push({ ...(hasRule ? expand(node) : node) });
3606
+ }
3607
+ else {
3608
+ // @ts-ignore
3609
+ result.chi.push(node);
3610
+ }
3611
+ }
3612
+ return result;
3613
+ }
3614
+ function expandRule(node) {
3615
+ const ast = { ...node, chi: node.chi.slice() };
3616
+ const result = [];
3617
+ if (ast.typ == 4 /* NodeType.RuleNodeType */) {
3618
+ let i = 0;
3619
+ for (; i < ast.chi.length; i++) {
3620
+ if (ast.chi[i].typ == 4 /* NodeType.RuleNodeType */) {
3621
+ const rule = ast.chi[i];
3622
+ if (!rule.sel.includes('&')) {
3623
+ const selRule = splitRule(rule.sel);
3624
+ selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
3625
+ rule.sel = selRule.reduce((acc, curr) => {
3626
+ acc.push(curr.join(''));
3627
+ return acc;
3628
+ }, []).join(',');
3629
+ }
3630
+ else {
3631
+ rule.sel = replaceCompound(rule.sel, ast.sel);
3632
+ }
3633
+ ast.chi.splice(i--, 1);
3634
+ result.push(...expandRule(rule));
3635
+ }
3636
+ else if (ast.chi[i].typ == 3 /* NodeType.AtRuleNodeType */) {
3637
+ let astAtRule = ast.chi[i];
3638
+ const values = [];
3639
+ if (astAtRule.nam == 'scope') {
3640
+ if (astAtRule.val.includes('&')) {
3641
+ astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
3642
+ }
3643
+ astAtRule = expand(astAtRule);
3644
+ }
3645
+ else {
3646
+ // @ts-ignore
3647
+ const clone = { ...ast, chi: astAtRule.chi.slice() };
3648
+ // @ts-ignore
3649
+ astAtRule.chi.length = 0;
3650
+ for (const r of expandRule(clone)) {
3651
+ if (r.typ == 3 /* NodeType.AtRuleNodeType */ && 'chi' in r) {
3652
+ if (astAtRule.val !== '' && r.val !== '') {
3653
+ if (astAtRule.nam == 'media' && r.nam == 'media') {
3654
+ r.val = astAtRule.val + ' and ' + r.val;
3655
+ }
3656
+ else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
3657
+ r.val = astAtRule.val + '.' + r.val;
3658
+ }
3659
+ }
3660
+ // @ts-ignore
3661
+ values.push(r);
3662
+ }
3663
+ else if (r.typ == 4 /* NodeType.RuleNodeType */) {
3664
+ // @ts-ignore
3665
+ astAtRule.chi.push(...expandRule(r));
3666
+ }
3667
+ else {
3668
+ // @ts-ignore
3669
+ astAtRule.chi.push(r);
3670
+ }
3671
+ }
3672
+ }
3673
+ // @ts-ignore
3674
+ result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
3675
+ ast.chi.splice(i--, 1);
3676
+ }
3677
+ }
3678
+ }
3679
+ // @ts-ignore
3680
+ return ast.chi.length > 0 ? [ast].concat(result) : result;
3681
+ }
3682
+ function replaceCompound(input, replace) {
3683
+ const tokens = parseString(input);
3684
+ for (const t of walkValues(tokens)) {
3685
+ if (t.value.typ == exports.EnumToken.LiteralTokenType) {
3686
+ if (t.value.val == '&') {
3687
+ t.value.val = replace;
3688
+ }
3689
+ else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
3690
+ t.value.val = replaceCompoundLiteral(t.value.val, replace);
3691
+ }
3692
+ }
3693
+ }
3694
+ return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
3695
+ }
3696
+ function replaceCompoundLiteral(selector, replace) {
3697
+ const tokens = [''];
3698
+ let i = 0;
3699
+ for (; i < selector.length; i++) {
3700
+ if (selector.charAt(i) == '&') {
3701
+ tokens.push('&');
3702
+ tokens.push('');
3703
+ }
3704
+ else {
3705
+ tokens[tokens.length - 1] += selector.charAt(i);
3706
+ }
3707
+ }
3708
+ return tokens.sort((a, b) => {
3709
+ if (a == '&') {
3710
+ return 1;
3711
+ }
3712
+ return b == '&' ? -1 : 0;
3713
+ }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
3714
+ }
3715
+
3716
+ class MinifyFeature {
3717
+ static get ordering() { return 10000; }
3718
+ register(options) { }
3719
+ run(ast, options = {}, parent, context) {
3720
+ }
3721
+ }
3722
+
3723
+ class InlineCssVariables extends MinifyFeature {
3724
+ static get ordering() {
3725
+ return 0;
3726
+ }
3727
+ static register(options) {
3728
+ if (options.inlineCssVariables) {
3729
+ for (const feature of options.features) {
3730
+ if (feature instanceof InlineCssVariables) {
3731
+ return;
3732
+ }
3733
+ }
3734
+ // @ts-ignore
3735
+ options.features.push(new InlineCssVariables());
3736
+ }
3737
+ }
3738
+ run(ast, options = {}, parent, context) {
3739
+ if (!('variableScope' in context)) {
3740
+ context.variableScope = new Map;
3741
+ }
3742
+ const isRoot = parent.typ == 2 /* NodeType.StyleSheetNodeType */ && ast.typ == 4 /* NodeType.RuleNodeType */ && ast.sel == ':root';
3743
+ const variableScope = context.variableScope;
3744
+ // @ts-ignore
3745
+ for (const node of ast.chi) {
3746
+ if (node.typ == 1 /* NodeType.CDOCOMMNodeType */ || node.typ == 0 /* NodeType.CommentNodeType */) {
3747
+ continue;
3748
+ }
3749
+ if (node.typ != 5 /* NodeType.DeclarationNodeType */) {
3750
+ break;
3751
+ }
3752
+ // css variable
3753
+ if (node.nam.startsWith('--')) {
3754
+ if (!variableScope.has(node.nam)) {
3755
+ const info = {
3756
+ globalScope: isRoot,
3757
+ // @ts-ignore
3758
+ parent: new Set(),
3759
+ declarationCount: 1,
3760
+ replaceable: isRoot,
3761
+ node: node
3762
+ };
3763
+ info.parent.add(ast);
3764
+ variableScope.set(node.nam, info);
3765
+ }
3766
+ else {
3767
+ const info = variableScope.get(node.nam);
3768
+ info.globalScope = isRoot;
3769
+ if (!isRoot) {
3770
+ ++info.declarationCount;
3771
+ }
3772
+ if (info.replaceable) {
3773
+ info.replaceable = isRoot && info.declarationCount == 1;
3774
+ }
3775
+ info.parent.add(ast);
3776
+ info.node = node;
3777
+ }
3778
+ }
3779
+ else {
3780
+ for (const { value, parent: parentValue } of walkValues(node.val)) {
3781
+ if (value?.typ == exports.EnumToken.FunctionTokenType && value.val == 'var') {
3782
+ if (value.chi.length == 1 && value.chi[0].typ == exports.EnumToken.IdenTokenType) {
3783
+ const info = variableScope.get(value.chi[0].val);
3784
+ if (info?.replaceable) {
3785
+ if (parentValue != null) {
3786
+ let i = 0;
3787
+ for (; i < parentValue.chi.length; i++) {
3788
+ if (parentValue.chi[i] == value) {
3789
+ parentValue.chi.splice(i, 1, ...info.node.val);
3790
+ break;
3791
+ }
3792
+ }
3793
+ }
3794
+ else {
3795
+ node.val = info.node.val.slice();
3796
+ }
3797
+ }
3798
+ }
3799
+ }
3800
+ }
3801
+ }
3802
+ }
3803
+ }
3804
+ cleanup(ast, options = {}, context) {
3805
+ const variableScope = context.variableScope;
3806
+ for (const info of variableScope.values()) {
3807
+ if (info.replaceable) {
3808
+ let i;
3809
+ for (const parent of info.parent) {
3810
+ i = parent.chi?.length ?? 0;
3811
+ while (i--) {
3812
+ if (parent.chi[i].typ == 5 /* NodeType.DeclarationNodeType */ && parent.chi[i].nam == info.node.nam) {
3813
+ parent.chi.splice(i, 1);
3814
+ }
3815
+ }
3816
+ if (parent.chi?.length == 0 && 'parent' in parent) {
3817
+ // @ts-ignore
3818
+ for (i = 0; i < parent.parent.chi?.length; i++) {
3819
+ // @ts-ignore
3820
+ if (parent.parent.chi[i] == parent) {
3821
+ // @ts-ignore
3822
+ parent.parent.chi.splice(i, 1);
3823
+ break;
3824
+ }
3825
+ }
3826
+ }
3827
+ }
3828
+ }
3829
+ }
3830
+ }
3831
+ }
3832
+
3833
+ class PropertySet {
3834
+ config;
3835
+ declarations;
3836
+ constructor(config) {
3837
+ this.config = config;
3838
+ this.declarations = new Map;
3839
+ }
3840
+ add(declaration) {
3841
+ if (declaration.nam == this.config.shorthand) {
3842
+ this.declarations = new Map;
3843
+ }
3844
+ else {
3845
+ // expand shorthand
3846
+ if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
3847
+ let isValid = true;
3848
+ let current = -1;
3849
+ const tokens = [];
3850
+ // @ts-ignore
3851
+ for (let token of this.declarations.get(this.config.shorthand).val) {
3852
+ // @ts-ignore
3853
+ if (this.config.types.some(t => token.typ == exports.EnumToken[t]) || (token.typ == exports.EnumToken.NumberTokenType && token.val == '0' &&
3854
+ (this.config.types.includes('Length') ||
3855
+ this.config.types.includes('Angle') ||
3856
+ this.config.types.includes('Dimension')))) {
3857
+ if (tokens.length == 0) {
3858
+ tokens.push([]);
3859
+ current++;
3860
+ }
3861
+ tokens[current].push(token);
3862
+ continue;
3863
+ }
3864
+ if (token.typ != exports.EnumToken.WhitespaceTokenType && token.typ != exports.EnumToken.CommentTokenType) {
3865
+ if (token.typ == exports.EnumToken.IdenTokenType && this.config.keywords.includes(token.val)) {
3866
+ if (tokens.length == 0) {
3867
+ tokens.push([]);
3868
+ current++;
3869
+ }
3870
+ tokens[current].push(token);
3871
+ }
3872
+ if (token.typ == exports.EnumToken.LiteralTokenType && token.val == this.config.separator) {
3873
+ tokens.push([]);
3874
+ current++;
3875
+ continue;
3876
+ }
3877
+ isValid = false;
3878
+ break;
3879
+ }
3880
+ }
3881
+ if (isValid && tokens.length > 0) {
3882
+ this.declarations.delete(this.config.shorthand);
3883
+ for (const values of tokens) {
3884
+ this.config.properties.forEach((property, index) => {
3885
+ if (!this.declarations.has(property)) {
3886
+ this.declarations.set(property, {
3887
+ typ: 5 /* NodeType.DeclarationNodeType */,
3888
+ nam: property,
3889
+ val: []
3890
+ });
3891
+ }
3892
+ while (index > 0 && index >= values.length) {
3893
+ if (index > 1) {
3894
+ index %= 2;
3895
+ }
3896
+ else {
3897
+ index = 0;
3898
+ break;
3899
+ }
3900
+ }
3901
+ // @ts-ignore
3902
+ const val = this.declarations.get(property).val;
3903
+ if (val.length > 0) {
3904
+ val.push({ typ: exports.EnumToken.WhitespaceTokenType });
3905
+ }
3906
+ val.push({ ...values[index] });
3907
+ });
3908
+ }
3909
+ }
3910
+ this.declarations.set(declaration.nam, declaration);
3911
+ return this;
3912
+ }
3913
+ }
3914
+ this.declarations.set(declaration.nam, declaration);
3915
+ return this;
3916
+ }
3917
+ isShortHand() {
3918
+ if (this.declarations.has(this.config.shorthand)) {
3919
+ return this.declarations.size == 1;
3920
+ }
3921
+ return this.config.properties.length == this.declarations.size;
3922
+ }
3923
+ [Symbol.iterator]() {
3924
+ let iterator;
3925
+ const declarations = this.declarations;
3926
+ if (declarations.size < this.config.properties.length) {
3927
+ iterator = declarations.values();
3928
+ }
3929
+ else {
3930
+ const values = [];
3931
+ this.config.properties.forEach((property) => {
3932
+ let index = 0;
3933
+ // @ts-ignore
3934
+ for (const token of this.declarations.get(property).val) {
3935
+ if (token.typ == exports.EnumToken.WhitespaceTokenType) {
3936
+ continue;
3937
+ }
3938
+ if (values.length == index) {
3939
+ values.push([]);
3940
+ }
3941
+ values[index].push(token);
3942
+ index++;
3943
+ }
3944
+ });
3945
+ for (const value of values) {
3946
+ let i = value.length;
3947
+ while (i-- > 1) {
3948
+ const t = value[i];
3949
+ const k = value[i == 1 ? 0 : i % 2];
3950
+ if (t.val == k.val && t.val == '0') {
3951
+ if ((t.typ == exports.EnumToken.NumberTokenType && isLength(k)) ||
3952
+ (k.typ == exports.EnumToken.NumberTokenType && isLength(t)) ||
3953
+ (isLength(k) || isLength(t))) {
3954
+ value.splice(i, 1);
3955
+ continue;
3956
+ }
3957
+ }
3958
+ if (eq(t, k)) {
3959
+ value.splice(i, 1);
3960
+ continue;
3961
+ }
3962
+ break;
3963
+ }
3964
+ }
3965
+ iterator = [{
3966
+ typ: 5 /* NodeType.DeclarationNodeType */,
3967
+ nam: this.config.shorthand,
3968
+ val: values.reduce((acc, curr) => {
3969
+ if (curr.length > 1) {
3970
+ const k = curr.length * 2 - 1;
3971
+ let i = 1;
3972
+ while (i < k) {
3973
+ curr.splice(i, 0, { typ: exports.EnumToken.WhitespaceTokenType });
3974
+ i += 2;
3975
+ }
3976
+ }
3977
+ if (acc.length > 0) {
3978
+ acc.push({ typ: exports.EnumToken.LiteralTokenType, val: this.config.separator });
3979
+ }
3980
+ acc.push(...curr);
3981
+ return acc;
3982
+ }, [])
3983
+ }][Symbol.iterator]();
3984
+ // return {
3985
+ // next() {
3986
+ //
3987
+ // return iterator.next();
3988
+ // }
3989
+ // }
3990
+ }
3991
+ return iterator;
3992
+ // return {
3993
+ // next() {
3994
+ //
3995
+ // return iterator.next();
3996
+ // }
3997
+ // }
3998
+ }
3999
+ }
4000
+
4001
+ const propertiesConfig = getConfig();
4002
+ class PropertyMap {
4003
+ config;
4004
+ declarations;
4005
+ requiredCount;
4006
+ pattern;
4007
+ constructor(config) {
4008
+ const values = Object.values(config.properties);
4009
+ this.requiredCount = values.reduce((acc, curr) => curr.required ? ++acc : acc, 0) || values.length;
4010
+ this.config = config;
4011
+ this.declarations = new Map;
4012
+ this.pattern = config.pattern.split(/\s/);
4013
+ }
4014
+ add(declaration) {
4015
+ for (const val of declaration.val) {
4016
+ Object.defineProperty(val, 'propertyName', { enumerable: false, writable: true, value: declaration.nam });
4017
+ }
4018
+ if (declaration.nam == this.config.shorthand) {
4019
+ this.declarations = new Map;
4020
+ this.declarations.set(declaration.nam, declaration);
4021
+ }
4022
+ else {
4023
+ const separator = this.config.separator != null ? {
4024
+ ...this.config.separator,
4025
+ typ: exports.EnumToken[this.config.separator.typ]
4026
+ } : null;
4027
+ // expand shorthand
4028
+ if (declaration.nam != this.config.shorthand && this.declarations.has(this.config.shorthand)) {
4029
+ const tokens = {};
4030
+ const values = [];
4031
+ // @ts-ignore
4032
+ this.declarations.get(this.config.shorthand).val.slice().reduce((acc, curr) => {
4033
+ // @ts-ignore
4034
+ if (separator != null && separator.typ == curr.typ && eq(separator, curr)) {
4035
+ acc.push([]);
4036
+ return acc;
3397
4037
  }
3398
- // else {
3399
4038
  // @ts-ignore
3400
4039
  acc.at(-1).push(curr);
3401
- // }
3402
4040
  return acc;
3403
4041
  }, [[]]).
3404
4042
  // @ts-ignore
@@ -3407,7 +4045,7 @@ class PropertyMap {
3407
4045
  // let current: number = 0;
3408
4046
  const props = this.config.properties[property];
3409
4047
  for (let i = 0; i < acc.length; i++) {
3410
- if (acc[i].typ == 'Comment' || acc[i].typ == 'Whitespace') {
4048
+ if (acc[i].typ == exports.EnumToken.CommentTokenType || acc[i].typ == exports.EnumToken.WhitespaceTokenType) {
3411
4049
  acc.splice(i, 1);
3412
4050
  i--;
3413
4051
  continue;
@@ -3423,18 +4061,20 @@ class PropertyMap {
3423
4061
  else {
3424
4062
  if (current == tokens[property].length) {
3425
4063
  tokens[property].push([acc[i]]);
3426
- // tokens[property][current].push();
3427
4064
  }
3428
4065
  else {
3429
- tokens[property][current].push({ typ: 'Whitespace' }, acc[i]);
4066
+ tokens[property][current].push({ typ: exports.EnumToken.WhitespaceTokenType }, acc[i]);
3430
4067
  }
3431
4068
  }
3432
4069
  acc.splice(i, 1);
3433
4070
  i--;
3434
4071
  // @ts-ignore
3435
- if ('prefix' in props && acc[i]?.typ == props.prefix.typ) {
3436
- // @ts-ignore
3437
- if (eq(acc[i], this.config.properties[property].prefix)) {
4072
+ if ('prefix' in props && acc[i]?.typ == exports.EnumToken[props.prefix.typ]) {
4073
+ if (eq(acc[i], {
4074
+ ...this.config.properties[property].prefix,
4075
+ // @ts-ignore
4076
+ typ: exports.EnumToken[props.prefix.typ]
4077
+ })) {
3438
4078
  acc.splice(i, 1);
3439
4079
  i--;
3440
4080
  }
@@ -3467,7 +4107,7 @@ class PropertyMap {
3467
4107
  tokens[property][current].push(...defaults);
3468
4108
  }
3469
4109
  else {
3470
- tokens[property][current].push({ typ: 'Whitespace' }, ...defaults);
4110
+ tokens[property][current].push({ typ: exports.EnumToken.WhitespaceTokenType }, ...defaults);
3471
4111
  }
3472
4112
  }
3473
4113
  }
@@ -3478,7 +4118,7 @@ class PropertyMap {
3478
4118
  if (values.length == 0) {
3479
4119
  this.declarations = Object.entries(tokens).reduce((acc, curr) => {
3480
4120
  acc.set(curr[0], {
3481
- typ: 'Declaration',
4121
+ typ: 5 /* NodeType.DeclarationNodeType */,
3482
4122
  nam: curr[0],
3483
4123
  val: curr[1].reduce((acc, curr) => {
3484
4124
  if (acc.length > 0) {
@@ -3548,7 +4188,10 @@ class PropertyMap {
3548
4188
  else {
3549
4189
  let count = 0;
3550
4190
  let match;
3551
- const separator = this.config.separator;
4191
+ const separator = this.config.separator != null ? {
4192
+ ...this.config.separator,
4193
+ typ: exports.EnumToken[this.config.separator.typ]
4194
+ } : null;
3552
4195
  const tokens = {};
3553
4196
  // @ts-ignore
3554
4197
  /* const valid: string[] =*/
@@ -3572,14 +4215,18 @@ class PropertyMap {
3572
4215
  }
3573
4216
  continue;
3574
4217
  }
3575
- if (val.typ == 'Whitespace' || val.typ == 'Comment') {
4218
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
3576
4219
  continue;
3577
4220
  }
3578
- if (props.multiple && props.separator != null && props.separator.typ == val.typ && eq(props.separator, val)) {
4221
+ // @ts-ignore
4222
+ if (props.multiple && props.separator != null && exports.EnumToken[props.separator.typ] == val.typ && eq({
4223
+ ...props.separator,
4224
+ typ: exports.EnumToken[props.separator.typ]
4225
+ }, val)) {
3579
4226
  continue;
3580
4227
  }
3581
4228
  // @ts-ignore
3582
- match = val.typ == 'Comment' || matchType(val, curr[1]);
4229
+ match = val.typ == exports.EnumToken.CommentTokenType || matchType(val, curr[1]);
3583
4230
  if (isShorthand) {
3584
4231
  isShorthand = match;
3585
4232
  }
@@ -3608,7 +4255,7 @@ class PropertyMap {
3608
4255
  return entry[1].required && !(entry[0] in tokens);
3609
4256
  }) ||
3610
4257
  // @ts-ignore
3611
- !Object.values(tokens).every(v => v.filter(t => t.typ != 'Comment').length == count)) {
4258
+ !Object.values(tokens).every(v => v.filter(t => t.typ != exports.EnumToken.CommentTokenType).length == count)) {
3612
4259
  // @ts-ignore
3613
4260
  iterable = this.declarations.values();
3614
4261
  }
@@ -3621,7 +4268,7 @@ class PropertyMap {
3621
4268
  }
3622
4269
  let values = curr[1][i].reduce((acc, curr) => {
3623
4270
  if (acc.length > 0) {
3624
- acc.push({ typ: 'Whitespace' });
4271
+ acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
3625
4272
  }
3626
4273
  acc.push(curr);
3627
4274
  return acc;
@@ -3633,8 +4280,8 @@ class PropertyMap {
3633
4280
  let doFilterDefault = true;
3634
4281
  if (curr[0] in propertiesConfig.properties) {
3635
4282
  for (let v of values) {
3636
- if (!['Whitespace', 'Comment', 'Iden'].includes(v.typ)
3637
- || (v.typ == 'Iden' && !this.config.properties[curr[0]].default.includes(v.val))) {
4283
+ if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType, exports.EnumToken.IdenTokenType].includes(v.typ)
4284
+ || (v.typ == exports.EnumToken.IdenTokenType && !this.config.properties[curr[0]].default.includes(v.val))) {
3638
4285
  doFilterDefault = false;
3639
4286
  break;
3640
4287
  }
@@ -3642,10 +4289,10 @@ class PropertyMap {
3642
4289
  }
3643
4290
  // remove default values
3644
4291
  values = values.filter((val) => {
3645
- if (val.typ == 'Whitespace' || val.typ == 'Comment') {
4292
+ if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
3646
4293
  return false;
3647
4294
  }
3648
- return !doFilterDefault || !(val.typ == 'Iden' && props.default.includes(val.val));
4295
+ return !doFilterDefault || !(val.typ == exports.EnumToken.IdenTokenType && props.default.includes(val.val));
3649
4296
  });
3650
4297
  if (values.length > 0) {
3651
4298
  if ('mapping' in props) {
@@ -3654,7 +4301,7 @@ class PropertyMap {
3654
4301
  let i = values.length;
3655
4302
  while (i--) {
3656
4303
  // @ts-ignore
3657
- if (values[i].typ == 'Iden' && values[i].val in props.mapping) {
4304
+ if (values[i].typ == exports.EnumToken.IdenTokenType && values[i].val in props.mapping) {
3658
4305
  // @ts-ignore
3659
4306
  values.splice(i, 1, ...parseString(props.mapping[values[i].val]));
3660
4307
  }
@@ -3663,15 +4310,20 @@ class PropertyMap {
3663
4310
  }
3664
4311
  if ('prefix' in props) {
3665
4312
  // @ts-ignore
3666
- acc[i].push({ ...props.prefix });
4313
+ acc[i].push({ ...props.prefix, typ: exports.EnumToken[props.prefix.typ] });
3667
4314
  }
3668
4315
  else if (acc[i].length > 0) {
3669
- acc[i].push({ typ: 'Whitespace' });
4316
+ acc[i].push({ typ: exports.EnumToken.WhitespaceTokenType });
3670
4317
  }
3671
4318
  acc[i].push(...values.reduce((acc, curr) => {
3672
4319
  if (acc.length > 0) {
3673
4320
  // @ts-ignore
3674
- acc.push({ ...(props.separator ?? { typ: 'Whitespace' }) });
4321
+ acc.push({
4322
+ ...((props.separator && {
4323
+ ...props.separator,
4324
+ typ: exports.EnumToken[props.separator.typ]
4325
+ }) ?? { typ: exports.EnumToken.WhitespaceTokenType })
4326
+ });
3675
4327
  }
3676
4328
  // @ts-ignore
3677
4329
  acc.push(curr);
@@ -3687,7 +4339,7 @@ class PropertyMap {
3687
4339
  if (curr.length == 0 && this.config.default.length > 0) {
3688
4340
  curr.push(...parseString(this.config.default[0]).reduce((acc, curr) => {
3689
4341
  if (acc.length > 0) {
3690
- acc.push({ typ: 'Whitespace' });
4342
+ acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
3691
4343
  }
3692
4344
  acc.push(curr);
3693
4345
  return acc;
@@ -3700,12 +4352,15 @@ class PropertyMap {
3700
4352
  const val = values.reduce((acc, curr) => acc + renderToken(curr, { removeComments: true }), '');
3701
4353
  if (val in this.config.mapping) {
3702
4354
  values.length = 0;
3703
- // @ts-ignore
3704
- values.push({ typ: ['"', "'"].includes(val.charAt(0)) ? 'String' : 'Iden', val: this.config.mapping[val] });
4355
+ values.push({
4356
+ typ: ['"', "'"].includes(val.charAt(0)) ? exports.EnumToken.StringTokenType : exports.EnumToken.IdenTokenType,
4357
+ // @ts-ignore
4358
+ val: this.config.mapping[val]
4359
+ });
3705
4360
  }
3706
4361
  }
3707
4362
  iterable = [{
3708
- typ: 'Declaration',
4363
+ typ: 5 /* NodeType.DeclarationNodeType */,
3709
4364
  nam: this.config.shorthand,
3710
4365
  val: values
3711
4366
  }][Symbol.iterator]();
@@ -3742,570 +4397,442 @@ class PropertyMap {
3742
4397
 
3743
4398
  const config = getConfig();
3744
4399
  class PropertyList {
4400
+ options = { removeDuplicateDeclarations: true, computeShorthand: true };
3745
4401
  declarations;
3746
- constructor() {
3747
- this.declarations = new Map;
3748
- }
3749
- set(nam, value) {
3750
- return this.add({ typ: 'Declaration', nam, val: Array.isArray(value) ? value : parseString(String(value)) });
3751
- }
3752
- add(declaration) {
3753
- if (declaration.typ != 'Declaration') {
3754
- this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
3755
- return this;
3756
- }
3757
- let propertyName = declaration.nam;
3758
- let shortHandType;
3759
- let shorthand;
3760
- if (propertyName in config.properties) {
3761
- // @ts-ignore
3762
- if ('map' in config.properties[propertyName]) {
3763
- shortHandType = 'map';
3764
- // @ts-ignore
3765
- shorthand = config.properties[propertyName].map;
3766
- }
3767
- else {
3768
- shortHandType = 'set';
3769
- // @ts-ignore
3770
- shorthand = config.properties[propertyName].shorthand;
3771
- }
3772
- }
3773
- else if (propertyName in config.map) {
3774
- shortHandType = 'map';
3775
- // @ts-ignore
3776
- shorthand = config.map[propertyName].shorthand;
3777
- }
3778
- // @ts-ignore
3779
- if (shortHandType == 'map') {
3780
- // @ts-ignore
3781
- if (!this.declarations.has(shorthand)) {
3782
- // @ts-ignore
3783
- this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
3784
- }
3785
- // @ts-ignore
3786
- this.declarations.get(shorthand).add(declaration);
3787
- // return this;
3788
- }
3789
- // @ts-ignore
3790
- else if (shortHandType == 'set') {
3791
- // @ts-ignore
3792
- // const shorthand: string = <string>config.properties[propertyName].shorthand;
3793
- if (!this.declarations.has(shorthand)) {
3794
- // @ts-ignore
3795
- this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
3796
- }
3797
- // @ts-ignore
3798
- this.declarations.get(shorthand).add(declaration);
3799
- // return this;
3800
- }
3801
- else {
3802
- this.declarations.set(propertyName, declaration);
3803
- }
3804
- return this;
3805
- }
3806
- [Symbol.iterator]() {
3807
- let iterator = this.declarations.values();
3808
- const iterators = [];
3809
- return {
3810
- next() {
3811
- let value = iterator.next();
3812
- while ((value.done && iterators.length > 0) ||
3813
- value.value instanceof PropertySet ||
3814
- value.value instanceof PropertyMap) {
3815
- if (value.value instanceof PropertySet || value.value instanceof PropertyMap) {
3816
- iterators.unshift(iterator);
3817
- // @ts-ignore
3818
- iterator = value.value[Symbol.iterator]();
3819
- value = iterator.next();
3820
- }
3821
- if (value.done && iterators.length > 0) {
3822
- iterator = iterators.shift();
3823
- value = iterator.next();
3824
- }
3825
- }
3826
- return value;
3827
- }
3828
- };
3829
- }
3830
- }
3831
-
3832
- function* walk(node, parent, root) {
3833
- yield { node, parent, root };
3834
- if ('chi' in node) {
3835
- for (const child of node.chi) {
3836
- yield* walk(child, node, (root ?? node));
3837
- }
3838
- }
3839
- }
3840
- function* walkValues(values, parent) {
3841
- for (const value of values) {
3842
- // @ts-ignore
3843
- yield { value, parent };
3844
- if ('chi' in value) {
3845
- yield* walkValues(value.chi, value);
3846
- }
3847
- }
3848
- }
3849
-
3850
- function expand(ast) {
3851
- //
3852
- if (!['Rule', 'StyleSheet', 'AtRule'].includes(ast.typ)) {
3853
- return ast;
3854
- }
3855
- if ('Rule' == ast.typ) {
3856
- return {
3857
- typ: 'StyleSheet',
3858
- chi: expandRule(ast)
3859
- };
3860
- }
3861
- if (!('chi' in ast)) {
3862
- return { ...ast };
3863
- }
3864
- const result = { ...ast, chi: [] };
3865
- // @ts-ignore
3866
- for (let i = 0; i < ast.chi.length; i++) {
3867
- // @ts-ignore
3868
- const node = ast.chi[i];
3869
- if (node.typ == 'Rule') {
3870
- // @ts-ignore
3871
- result.chi.push(...expandRule(node));
3872
- // i += expanded.length - 1;
3873
- }
3874
- else if (node.typ == 'AtRule' && 'chi' in node) {
3875
- let hasRule = false;
3876
- let j = node.chi.length;
3877
- while (j--) {
3878
- if (node.chi[j].typ == 'Rule' || node.chi[j].typ == 'AtRule') {
3879
- hasRule = true;
3880
- break;
3881
- }
3882
- }
3883
- // @ts-ignore
3884
- result.chi.push({ ...(hasRule ? expand(node) : node) });
3885
- }
3886
- else {
3887
- // @ts-ignore
3888
- result.chi.push(node);
3889
- }
3890
- }
3891
- return result;
3892
- }
3893
- function expandRule(node) {
3894
- const ast = { ...node, chi: node.chi.slice() };
3895
- const result = [];
3896
- if (ast.typ == 'Rule') {
3897
- let i = 0;
3898
- for (; i < ast.chi.length; i++) {
3899
- if (ast.chi[i].typ == 'Rule') {
3900
- const rule = ast.chi[i];
3901
- if (!rule.sel.includes('&')) {
3902
- const selRule = splitRule(rule.sel);
3903
- selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
3904
- rule.sel = selRule.reduce((acc, curr) => {
3905
- acc.push(curr.join(''));
3906
- return acc;
3907
- }, []).join(',');
3908
- }
3909
- else {
3910
- rule.sel = replaceCompound(rule.sel, ast.sel);
3911
- }
3912
- ast.chi.splice(i--, 1);
3913
- result.push(...expandRule(rule));
3914
- }
3915
- else if (ast.chi[i].typ == 'AtRule') {
3916
- let astAtRule = ast.chi[i];
3917
- const values = [];
3918
- if (astAtRule.nam == 'scope') {
3919
- if (astAtRule.val.includes('&')) {
3920
- astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
3921
- }
3922
- // @ts-ignore
3923
- astAtRule = expand(astAtRule);
3924
- }
3925
- else {
3926
- // @ts-ignore
3927
- const clone = { ...ast, chi: astAtRule.chi.slice() };
3928
- // @ts-ignore
3929
- astAtRule.chi.length = 0;
3930
- for (const r of expandRule(clone)) {
3931
- if (r.typ == 'AtRule' && 'chi' in r) {
3932
- if (astAtRule.val !== '' && r.val !== '') {
3933
- if (astAtRule.nam == 'media' && r.nam == 'media') {
3934
- r.val = astAtRule.val + ' and ' + r.val;
3935
- }
3936
- else if (astAtRule.nam == 'layer' && r.nam == 'layer') {
3937
- r.val = astAtRule.val + '.' + r.val;
3938
- }
3939
- }
3940
- // @ts-ignore
3941
- values.push(r);
3942
- }
3943
- else if (r.typ == 'Rule') {
3944
- // @ts-ignore
3945
- astAtRule.chi.push(...expandRule(r));
3946
- }
3947
- else {
3948
- // @ts-ignore
3949
- astAtRule.chi.push(r);
3950
- }
3951
- }
3952
- }
3953
- // @ts-ignore
3954
- result.push(...(astAtRule.chi.length > 0 ? [astAtRule].concat(values) : values));
3955
- ast.chi.splice(i--, 1);
3956
- }
3957
- }
3958
- }
3959
- // @ts-ignore
3960
- return ast.chi.length > 0 ? [ast].concat(result) : result;
3961
- }
3962
- function replaceCompound(input, replace) {
3963
- const tokens = parseString(input);
3964
- for (const t of walkValues(tokens)) {
3965
- if (t.value.typ == 'Literal') {
3966
- if (t.value.val == '&') {
3967
- t.value.val = replace;
3968
- }
3969
- else if (t.value.val.length > 1 && t.value.val.charAt(0) == '&') {
3970
- t.value.val = replaceCompoundLiteral(t.value.val, replace);
4402
+ constructor(options = {}) {
4403
+ for (const key of Object.keys(this.options)) {
4404
+ if (key in options) {
4405
+ // @ts-ignore
4406
+ this.options[key] = options[key];
3971
4407
  }
3972
4408
  }
4409
+ this.declarations = new Map;
3973
4410
  }
3974
- return tokens.reduce((acc, curr) => acc + renderToken(curr), '');
3975
- }
3976
- function replaceCompoundLiteral(selector, replace) {
3977
- const tokens = [''];
3978
- let i = 0;
3979
- for (; i < selector.length; i++) {
3980
- if (selector.charAt(i) == '&') {
3981
- tokens.push('&');
3982
- tokens.push('');
3983
- }
3984
- else {
3985
- tokens[tokens.length - 1] += selector.charAt(i);
3986
- }
4411
+ set(nam, value) {
4412
+ return this.add({ typ: 5 /* NodeType.DeclarationNodeType */, nam, val: Array.isArray(value) ? value : parseString(String(value)) });
3987
4413
  }
3988
- return tokens.sort((a, b) => {
3989
- if (a == '&') {
3990
- return 1;
4414
+ add(declaration) {
4415
+ if (declaration.typ != 5 /* NodeType.DeclarationNodeType */ || !this.options.removeDuplicateDeclarations) {
4416
+ this.declarations.set(Number(Math.random().toString().slice(2)).toString(36), declaration);
4417
+ return this;
3991
4418
  }
3992
- return b == '&' ? -1 : 0;
3993
- }).reduce((acc, curr) => acc + (curr == '&' ? replace : curr), '');
3994
- }
3995
-
3996
- const combinators = ['+', '>', '~'];
3997
- const notEndingWith = ['(', '['].concat(combinators);
3998
- const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
3999
- function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4000
- function wrapNodes(previous, node, match, ast, i, nodeIndex) {
4001
- // @ts-ignore
4002
- let pSel = match.selector1.reduce(reducer, []).join(',');
4003
- // @ts-ignore
4004
- let nSel = match.selector2.reduce(reducer, []).join(',');
4005
- // @ts-ignore
4006
- const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
4007
- // @ts-ignore
4008
- Object.defineProperty(wrapper, 'raw', { ...definedPropertySettings,
4009
- // @ts-ignore
4010
- value: match.match.map(t => t.slice())
4011
- });
4012
- if (pSel == '&' || pSel === '') {
4013
- // @ts-ignore
4014
- wrapper.chi.push(...previous.chi);
4419
+ if (!this.options.computeShorthand) {
4420
+ this.declarations.set(declaration.nam, declaration);
4421
+ return this;
4422
+ }
4423
+ let propertyName = declaration.nam;
4424
+ let shortHandType;
4425
+ let shorthand;
4426
+ if (propertyName in config.properties) {
4015
4427
  // @ts-ignore
4016
- if ((nSel == '&' || nSel === '')) {
4428
+ if ('map' in config.properties[propertyName]) {
4429
+ shortHandType = 'map';
4017
4430
  // @ts-ignore
4018
- wrapper.chi.push(...node.chi);
4431
+ shorthand = config.properties[propertyName].map;
4019
4432
  }
4020
4433
  else {
4434
+ shortHandType = 'set';
4021
4435
  // @ts-ignore
4022
- wrapper.chi.push(node);
4436
+ shorthand = config.properties[propertyName].shorthand;
4023
4437
  }
4024
4438
  }
4025
- else {
4439
+ else if (propertyName in config.map) {
4440
+ shortHandType = 'map';
4026
4441
  // @ts-ignore
4027
- wrapper.chi.push(previous, node);
4442
+ shorthand = config.map[propertyName].shorthand;
4028
4443
  }
4029
4444
  // @ts-ignore
4030
- ast.chi.splice(i, 1, wrapper);
4031
- // @ts-ignore
4032
- ast.chi.splice(nodeIndex, 1);
4033
- // @ts-ignore
4034
- previous.sel = pSel;
4035
- // @ts-ignore
4036
- previous.raw = match.selector1;
4037
- // @ts-ignore
4038
- node.sel = nSel;
4039
- // @ts-ignore
4040
- node.raw = match.selector2;
4041
- reduceRuleSelector(wrapper);
4042
- return wrapper;
4043
- }
4044
- function reducer(acc, curr, index, array) {
4045
- // trim :is()
4046
- if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
4047
- curr = curr.slice(1, -1);
4048
- }
4049
- if (curr[0] == '&') {
4050
- if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
4051
- curr.splice(0, 2);
4445
+ if (shortHandType == 'map') {
4446
+ // @ts-ignore
4447
+ if (!this.declarations.has(shorthand)) {
4448
+ // @ts-ignore
4449
+ this.declarations.set(shorthand, new PropertyMap(config.map[shorthand]));
4052
4450
  }
4053
- else if (combinators.includes(curr[1])) {
4054
- curr.splice(0, 1);
4451
+ // @ts-ignore
4452
+ this.declarations.get(shorthand).add(declaration);
4453
+ // return this;
4454
+ }
4455
+ // @ts-ignore
4456
+ else if (shortHandType == 'set') {
4457
+ // @ts-ignore
4458
+ // const shorthand: string = <string>config.properties[propertyName].shorthand;
4459
+ if (!this.declarations.has(shorthand)) {
4460
+ // @ts-ignore
4461
+ this.declarations.set(shorthand, new PropertySet(config.properties[shorthand]));
4055
4462
  }
4463
+ // @ts-ignore
4464
+ this.declarations.get(shorthand).add(declaration);
4465
+ // return this;
4056
4466
  }
4057
- else if (ast.typ == 'Rule' && (isIdent(curr[0]) || isFunction(curr[0]))) {
4058
- curr.unshift('&', ' ');
4467
+ else {
4468
+ this.declarations.set(propertyName, declaration);
4059
4469
  }
4060
- acc.push(curr.join(''));
4061
- return acc;
4470
+ return this;
4471
+ }
4472
+ [Symbol.iterator]() {
4473
+ let iterator = this.declarations.values();
4474
+ const iterators = [];
4475
+ return {
4476
+ next() {
4477
+ let value = iterator.next();
4478
+ while ((value.done && iterators.length > 0) ||
4479
+ value.value instanceof PropertySet ||
4480
+ value.value instanceof PropertyMap) {
4481
+ if (value.value instanceof PropertySet || value.value instanceof PropertyMap) {
4482
+ iterators.unshift(iterator);
4483
+ // @ts-ignore
4484
+ iterator = value.value[Symbol.iterator]();
4485
+ value = iterator.next();
4486
+ }
4487
+ if (value.done && iterators.length > 0) {
4488
+ iterator = iterators.shift();
4489
+ value = iterator.next();
4490
+ }
4491
+ }
4492
+ return value;
4493
+ }
4494
+ };
4495
+ }
4496
+ }
4497
+
4498
+ class ComputeShorthand extends MinifyFeature {
4499
+ static get ordering() {
4500
+ return 2;
4062
4501
  }
4063
- function diff(n1, n2, options = {}) {
4064
- let node1 = n1;
4065
- let node2 = n2;
4066
- let exchanged = false;
4067
- if (node1.chi.length > node2.chi.length) {
4068
- const t = node1;
4069
- node1 = node2;
4070
- node2 = t;
4071
- exchanged = true;
4072
- }
4073
- let i = node1.chi.length;
4074
- let j = node2.chi.length;
4075
- if (i == 0 || j == 0) {
4502
+ static register(options) {
4503
+ if (options.computeShorthand) {
4504
+ for (const feature of options.features) {
4505
+ if (feature instanceof ComputeShorthand) {
4506
+ return;
4507
+ }
4508
+ }
4076
4509
  // @ts-ignore
4077
- return null;
4510
+ options.features.push(new ComputeShorthand());
4078
4511
  }
4512
+ }
4513
+ run(ast, options = {}, parent, context) {
4079
4514
  // @ts-ignore
4080
- const raw1 = node1.raw;
4515
+ const j = ast.chi.length;
4516
+ let k = 0;
4517
+ let properties = new PropertyList(options);
4081
4518
  // @ts-ignore
4082
- const raw2 = node2.raw;
4519
+ for (; k < j; k++) {
4520
+ // @ts-ignore
4521
+ const node = ast.chi[k];
4522
+ if (node.typ == 0 /* NodeType.CommentNodeType */ || node.typ == 5 /* NodeType.DeclarationNodeType */) {
4523
+ properties.add(node);
4524
+ continue;
4525
+ }
4526
+ break;
4527
+ }
4083
4528
  // @ts-ignore
4084
- node1 = { ...node1, chi: node1.chi.slice() };
4085
- node2 = { ...node2, chi: node2.chi.slice() };
4086
- if (raw1 != null) {
4087
- Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
4529
+ ast.chi = [...properties].concat(ast.chi.slice(k));
4530
+ return ast;
4531
+ }
4532
+ }
4533
+
4534
+ class ComputeCalcExpression extends MinifyFeature {
4535
+ static get ordering() {
4536
+ return 1;
4537
+ }
4538
+ static register(options) {
4539
+ if (options.computeCalcExpression) {
4540
+ for (const feature of options.features) {
4541
+ if (feature instanceof ComputeCalcExpression) {
4542
+ return;
4543
+ }
4544
+ }
4545
+ // @ts-ignore
4546
+ options.features.push(new ComputeCalcExpression());
4088
4547
  }
4089
- if (raw2 != null) {
4090
- Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
4548
+ }
4549
+ run(ast) {
4550
+ if (!('chi' in ast)) {
4551
+ return ast;
4091
4552
  }
4092
- const intersect = [];
4093
- while (i--) {
4094
- if (node1.chi[i].typ == 'Comment') {
4553
+ // @ts-ignore
4554
+ for (const node of ast.chi) {
4555
+ if (node.typ != 5 /* NodeType.DeclarationNodeType */) {
4095
4556
  continue;
4096
4557
  }
4097
- j = node2.chi.length;
4098
- if (j == 0) {
4099
- break;
4100
- }
4101
- while (j--) {
4102
- if (node2.chi[j].typ == 'Comment') {
4103
- continue;
4104
- }
4105
- if (node1.chi[i].nam == node2.chi[j].nam) {
4106
- if (eq(node1.chi[i], node2.chi[j])) {
4107
- intersect.push(node1.chi[i]);
4108
- node1.chi.splice(i, 1);
4109
- node2.chi.splice(j, 1);
4110
- break;
4558
+ const set = new Set;
4559
+ for (const { parent } of walkValues(node.val)) {
4560
+ if (parent != null && parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') {
4561
+ if (!set.has(parent)) {
4562
+ set.add(parent);
4563
+ parent.chi = evaluate(parent.chi);
4111
4564
  }
4112
4565
  }
4113
4566
  }
4114
4567
  }
4568
+ return ast;
4569
+ }
4570
+ }
4571
+ /**
4572
+ * evaluate arithmetic operation
4573
+ * @param l
4574
+ * @param r
4575
+ * @param op
4576
+ */
4577
+ function doEvaluate(l, r, op) {
4578
+ const defaultReturn = {
4579
+ typ: exports.EnumToken.BinaryExpressionTokenType,
4580
+ op,
4581
+ l,
4582
+ r
4583
+ };
4584
+ if (!isScalarToken(l) || !isScalarToken(r)) {
4585
+ return defaultReturn;
4586
+ }
4587
+ if ((op == exports.EnumToken.Add || op == exports.EnumToken.Sub)) {
4588
+ // @ts-ignore
4589
+ if (l.typ != r.typ || Number.isNaN(+l.val) || Number.isNaN(r.val)) {
4590
+ return defaultReturn;
4591
+ }
4592
+ // @ts-ignore
4593
+ return { ...l, val: reduceNumber(+l.val + (op == exports.EnumToken.Add ? +r.val : -1 * r.val)) };
4594
+ }
4595
+ else {
4115
4596
  // @ts-ignore
4116
- const result = (intersect.length == 0 ? null : {
4117
- ...node1,
4597
+ let val;
4598
+ if (op == exports.EnumToken.Div) {
4599
+ if (r.typ != exports.EnumToken.NumberTokenType || r.val == '0') {
4600
+ return defaultReturn;
4601
+ }
4118
4602
  // @ts-ignore
4119
- sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
4120
- chi: intersect.reverse()
4121
- });
4122
- 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)) {
4603
+ val = reduceNumber(l.val / r.val);
4604
+ }
4605
+ else {
4123
4606
  // @ts-ignore
4124
- return null;
4607
+ val = reduceNumber(r.val * l.val);
4608
+ }
4609
+ let result;
4610
+ if (r.typ == exports.EnumToken.NumberTokenType || op == exports.EnumToken.Div) {
4611
+ result = { ...l, val };
4612
+ }
4613
+ else {
4614
+ // @ts-ignore
4615
+ result = { ...r, val };
4616
+ }
4617
+ if (renderToken(result).length <= renderToken(defaultReturn).length) {
4618
+ return result;
4125
4619
  }
4126
- return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
4127
4620
  }
4128
- function matchSelectors(selector1, selector2, parentType) {
4129
- let match = [[]];
4130
- 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));
4131
- let i = 0;
4132
- let k;
4133
- let l;
4134
- let token;
4135
- let matching = true;
4136
- let matchFunction = 0;
4137
- let inAttr = 0;
4138
- for (; i < j; i++) {
4139
- k = 0;
4140
- token = selector1[0][i];
4141
- for (; k < selector1.length; k++) {
4142
- if (selector1[k][i] != token) {
4143
- matching = false;
4144
- break;
4145
- }
4146
- }
4147
- if (matching) {
4148
- l = 0;
4149
- for (; l < selector2.length; l++) {
4150
- if (selector2[l][i] != token) {
4151
- matching = false;
4152
- break;
4153
- }
4154
- }
4155
- }
4156
- if (!matching) {
4157
- break;
4158
- }
4159
- if (token == ',') {
4160
- match.push([]);
4621
+ return defaultReturn;
4622
+ }
4623
+ /**
4624
+ * evaluate an array of tokens
4625
+ * @param tokens
4626
+ */
4627
+ function evaluate(tokens) {
4628
+ const nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
4629
+ if (nodes.length <= 1) {
4630
+ return nodes;
4631
+ }
4632
+ const map = new Map;
4633
+ let token;
4634
+ let i;
4635
+ for (i = 0; i < nodes.length; i++) {
4636
+ token = nodes[i];
4637
+ if (token.typ == exports.EnumToken.Add) {
4638
+ continue;
4639
+ }
4640
+ if (token.typ == exports.EnumToken.Sub) {
4641
+ if (!isScalarToken(nodes[i + 1])) {
4642
+ token = { typ: exports.EnumToken.ListToken, chi: [nodes[i], nodes[i + 1]] };
4161
4643
  }
4162
4644
  else {
4163
- if (token.endsWith('(')) {
4164
- matchFunction++;
4165
- }
4166
- if (token.endsWith('[')) {
4167
- inAttr++;
4168
- }
4169
- else if (token == ')') {
4170
- matchFunction--;
4171
- }
4172
- else if (token == ']') {
4173
- inAttr--;
4174
- }
4175
- match.at(-1).push(token);
4645
+ token = doEvaluate(nodes[i + 1], { typ: exports.EnumToken.NumberTokenType, val: '-1' }, exports.EnumToken.Mul);
4176
4646
  }
4647
+ i++;
4177
4648
  }
4178
- // invalid function
4179
- if (matchFunction != 0 || inAttr != 0) {
4180
- return null;
4649
+ if (!map.has(token.typ)) {
4650
+ map.set(token.typ, [token]);
4181
4651
  }
4182
- if (parentType != 'Rule') {
4183
- for (const part of match) {
4184
- if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
4185
- return null;
4186
- }
4652
+ else {
4653
+ map.get(token.typ).push(token);
4654
+ }
4655
+ }
4656
+ return [...map].reduce((acc, curr) => {
4657
+ const token = curr[1].reduce((acc, curr) => doEvaluate(acc, curr, exports.EnumToken.Add));
4658
+ if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
4659
+ if ('val' in token && +token.val < 0) {
4660
+ acc.push({ typ: exports.EnumToken.Sub }, { ...token, val: String(-token.val) });
4661
+ return acc;
4187
4662
  }
4188
4663
  }
4189
- if (match.length > 1) {
4190
- errors?.push({ action: 'ignore', message: `minify: unsupported multilevel matching\n${JSON.stringify({ match, selector1, selector2 }, null, 1)}` });
4191
- return null;
4664
+ if (acc.length > 0 && curr[0] != exports.EnumToken.ListToken) {
4665
+ acc.push({ typ: exports.EnumToken.Add });
4192
4666
  }
4193
- for (const part of match) {
4194
- while (part.length > 0) {
4195
- const token = part.at(-1);
4196
- if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
4197
- part.pop();
4198
- continue;
4199
- }
4200
- break;
4201
- }
4667
+ acc.push(token);
4668
+ return acc;
4669
+ }, []);
4670
+ }
4671
+ /**
4672
+ * convert BinaryExpression into an array
4673
+ * @param token
4674
+ */
4675
+ function inlineExpression(token) {
4676
+ const result = [];
4677
+ if (token.typ == exports.EnumToken.BinaryExpressionTokenType) {
4678
+ if ([exports.EnumToken.Mul, exports.EnumToken.Div].includes(token.op)) {
4679
+ result.push(token);
4202
4680
  }
4203
- if (match.every(t => t.length == 0)) {
4204
- return null;
4681
+ else {
4682
+ result.push(...inlineExpression(token.l), { typ: token.op }, ...inlineExpression(token.r));
4205
4683
  }
4206
- if (eq([['&']], match)) {
4207
- return null;
4684
+ }
4685
+ else {
4686
+ result.push(token);
4687
+ }
4688
+ return result;
4689
+ }
4690
+ /**
4691
+ * evaluate expression
4692
+ * @param token
4693
+ */
4694
+ function evaluateExpression(token) {
4695
+ if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
4696
+ return token;
4697
+ }
4698
+ if (token.r.typ == exports.EnumToken.BinaryExpressionTokenType) {
4699
+ token.r = evaluateExpression(token.r);
4700
+ }
4701
+ if (token.l.typ == exports.EnumToken.BinaryExpressionTokenType) {
4702
+ token.l = evaluateExpression(token.l);
4703
+ }
4704
+ const result = doEvaluate(token.l, token.r, token.op);
4705
+ if (result.typ == exports.EnumToken.BinaryExpressionTokenType &&
4706
+ [exports.EnumToken.Mul, exports.EnumToken.Div].includes(result.op)) {
4707
+ // wrap expression
4708
+ if (result.l.typ == exports.EnumToken.BinaryExpressionTokenType && [exports.EnumToken.Sub, exports.EnumToken.Add].includes(result.l.op)) {
4709
+ result.l = { typ: exports.EnumToken.ParensTokenType, chi: [result.l] };
4208
4710
  }
4209
- function reduce(acc, curr) {
4210
- if (acc === null) {
4211
- return null;
4212
- }
4213
- let hasCompoundSelector = true;
4214
- curr = curr.slice(match[0].length);
4215
- while (curr.length > 0) {
4216
- if (curr[0] == ' ') {
4217
- hasCompoundSelector = false;
4218
- curr.unshift('&');
4219
- continue;
4220
- }
4221
- break;
4222
- }
4223
- // invalid function match
4224
- if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
4225
- return null;
4226
- }
4227
- if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
4228
- return null;
4229
- }
4230
- if (hasCompoundSelector && curr.length > 0) {
4231
- hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
4232
- }
4233
- if (curr[0] == ':is(') {
4234
- let inFunction = 0;
4235
- let canReduce = true;
4236
- const isCompound = curr.reduce((acc, token, index) => {
4237
- if (index == 0) {
4238
- inFunction++;
4239
- canReduce = curr[1] == '&';
4240
- }
4241
- else if (token.endsWith('(')) {
4242
- if (inFunction == 0) {
4243
- canReduce = false;
4244
- }
4245
- inFunction++;
4246
- }
4247
- else if (token == ')') {
4248
- inFunction--;
4249
- }
4250
- else if (token == ',') {
4251
- if (!canReduce) {
4252
- canReduce = curr[index + 1] == '&';
4253
- }
4254
- acc.push([]);
4255
- }
4256
- else
4257
- acc.at(-1)?.push(token);
4258
- return acc;
4259
- }, [[]]);
4260
- if (inFunction > 0) {
4261
- canReduce = false;
4262
- }
4263
- if (canReduce) {
4264
- curr = isCompound.reduce((acc, curr) => {
4265
- if (acc.length > 0) {
4266
- acc.push(',');
4267
- }
4268
- acc.push(...curr);
4269
- return acc;
4270
- }, []);
4271
- }
4272
- }
4273
- // @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
4274
- acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
4275
- return acc;
4711
+ else if (result.r.typ == exports.EnumToken.BinaryExpressionTokenType && [exports.EnumToken.Sub, exports.EnumToken.Add].includes(result.r.op)) {
4712
+ result.r = { typ: exports.EnumToken.ParensTokenType, chi: [result.r] };
4713
+ }
4714
+ }
4715
+ return result;
4716
+ }
4717
+ function isScalarToken(token) {
4718
+ return token.typ != exports.EnumToken.BinaryExpressionTokenType && token.typ != exports.EnumToken.ParensTokenType && token.typ != exports.EnumToken.FunctionTokenType;
4719
+ }
4720
+ /**
4721
+ *
4722
+ * generate binary expression tree
4723
+ * @param tokens
4724
+ */
4725
+ function buildExpression(tokens) {
4726
+ return factor(factor(tokens.filter(t => t.typ != exports.EnumToken.WhitespaceTokenType), ['/', '*']), ['+', '-'])[0];
4727
+ }
4728
+ function getArithmeticOperation(op) {
4729
+ if (op == '+') {
4730
+ return exports.EnumToken.Add;
4731
+ }
4732
+ if (op == '-') {
4733
+ return exports.EnumToken.Sub;
4734
+ }
4735
+ if (op == '/') {
4736
+ return exports.EnumToken.Div;
4737
+ }
4738
+ return exports.EnumToken.Mul;
4739
+ }
4740
+ /**
4741
+ *
4742
+ * generate binary expression tree
4743
+ * @param token
4744
+ */
4745
+ function factorToken(token) {
4746
+ if (token.typ == exports.EnumToken.ParensTokenType || (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc')) {
4747
+ if (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc') {
4748
+ token = { ...token, typ: exports.EnumToken.ParensTokenType };
4749
+ // @ts-ignore
4750
+ delete token.val;
4751
+ }
4752
+ return buildExpression(token.chi);
4753
+ }
4754
+ return token;
4755
+ }
4756
+ /**
4757
+ * generate binary expression tree
4758
+ * @param tokens
4759
+ * @param ops
4760
+ */
4761
+ function factor(tokens, ops) {
4762
+ let isOp;
4763
+ const opList = [exports.EnumToken.Add, exports.EnumToken.Sub, exports.EnumToken.Div, exports.EnumToken.Mul];
4764
+ if (tokens.length == 1) {
4765
+ return [factorToken(tokens[0])];
4766
+ }
4767
+ for (let i = 0; i < tokens.length; i++) {
4768
+ isOp = opList.includes(tokens[i].typ);
4769
+ if (isOp ||
4770
+ // @ts-ignore
4771
+ (tokens[i].typ == exports.EnumToken.LiteralTokenType && ops.includes(tokens[i].val))) {
4772
+ tokens.splice(i - 1, 3, {
4773
+ typ: exports.EnumToken.BinaryExpressionTokenType,
4774
+ op: isOp ? tokens[i].typ : getArithmeticOperation(tokens[i].val),
4775
+ l: factorToken(tokens[i - 1]),
4776
+ r: factorToken(tokens[i + 1])
4777
+ });
4778
+ i--;
4276
4779
  }
4780
+ }
4781
+ return tokens;
4782
+ }
4783
+
4784
+ var allFeatures = /*#__PURE__*/Object.freeze({
4785
+ __proto__: null,
4786
+ ComputeCalcExpression: ComputeCalcExpression,
4787
+ ComputeShorthand: ComputeShorthand,
4788
+ InlineCssVariables: InlineCssVariables
4789
+ });
4790
+
4791
+ const combinators = ['+', '>', '~'];
4792
+ const notEndingWith = ['(', '['].concat(combinators);
4793
+ const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
4794
+ // @ts-ignore
4795
+ const features = Object.values(allFeatures).sort((a, b) => a.ordering - b.ordering);
4796
+ function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
4797
+ if (!('nodes' in context)) {
4798
+ context.nodes = new WeakSet;
4799
+ }
4800
+ if (context.nodes.has(ast)) {
4801
+ // console.error('skipped', ast.typ);
4802
+ return ast;
4803
+ }
4804
+ context.nodes.add(ast);
4805
+ if (!('features' in options)) {
4277
4806
  // @ts-ignore
4278
- selector1 = selector1.reduce(reduce, []);
4807
+ options = { removeDuplicateDeclarations: true, computeShorthand: true, computeCalcExpression: true, features: [], ...options };
4279
4808
  // @ts-ignore
4280
- selector2 = selector2.reduce(reduce, []);
4281
- return selector1 == null || selector2 == null ? null : {
4282
- eq: eq(selector1, selector2),
4283
- match,
4284
- selector1,
4285
- selector2
4286
- };
4809
+ for (const feature of features) {
4810
+ feature.register(options);
4811
+ }
4287
4812
  }
4288
- function fixSelector(node) {
4289
- // @ts-ignore
4290
- if (node.sel.includes('&')) {
4291
- const attributes = parseString(node.sel);
4292
- for (const attr of walkValues(attributes)) {
4293
- if (attr.value.typ == 'Pseudo-class-func' && attr.value.val == ':is') {
4294
- let i = attr.value.chi.length;
4295
- while (i--) {
4296
- if (attr.value.chi[i].typ == 'Literal' && attr.value.chi[i].val == '&') {
4297
- attr.value.chi.splice(i, 1);
4298
- }
4299
- }
4300
- }
4813
+ function reducer(acc, curr, index, array) {
4814
+ // trim :is()
4815
+ if (array.length == 1 && array[0][0] == ':is(' && array[0].at(-1) == ')') {
4816
+ curr = curr.slice(1, -1);
4817
+ }
4818
+ if (curr[0] == '&') {
4819
+ if (curr[1] == ' ' && !isIdent(curr[2]) && !isFunction(curr[2])) {
4820
+ curr.splice(0, 2);
4821
+ }
4822
+ else if (combinators.includes(curr[1])) {
4823
+ curr.splice(0, 1);
4301
4824
  }
4302
- node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
4303
4825
  }
4826
+ else if (ast.typ == 4 /* NodeType.RuleNodeType */ && (isIdent(curr[0]) || isFunction(curr[0]))) {
4827
+ curr.unshift('&', ' ');
4828
+ }
4829
+ acc.push(curr.join(''));
4830
+ return acc;
4304
4831
  }
4305
4832
  // @ts-ignore
4306
- if (('chi' in ast) && ast.chi?.length > 0) {
4833
+ if ('chi' in ast && ast.chi.length > 0) {
4307
4834
  if (!nestingContent) {
4308
- nestingContent = options.nestingRules && ast.typ == 'Rule';
4835
+ nestingContent = options.nestingRules && ast.typ == 4 /* NodeType.RuleNodeType */;
4309
4836
  }
4310
4837
  let i = 0;
4311
4838
  let previous;
@@ -4314,7 +4841,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4314
4841
  // @ts-ignore
4315
4842
  for (; i < ast.chi.length; i++) {
4316
4843
  // @ts-ignore
4317
- if (ast.chi[i].typ == 'Comment') {
4844
+ if (ast.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
4318
4845
  continue;
4319
4846
  }
4320
4847
  // @ts-ignore
@@ -4326,10 +4853,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4326
4853
  i--;
4327
4854
  continue;
4328
4855
  }
4329
- if (node.typ == 'AtRule' && node.nam == 'font-face') {
4856
+ if (node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam == 'font-face') {
4330
4857
  continue;
4331
4858
  }
4332
- if (node.typ == 'AtRule') {
4859
+ if (node.typ == 3 /* NodeType.AtRuleNodeType */) {
4333
4860
  if (node.nam == 'media' && node.val == 'all') {
4334
4861
  // @ts-ignore
4335
4862
  ast.chi?.splice(i, 1, ...node.chi);
@@ -4337,47 +4864,41 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4337
4864
  continue;
4338
4865
  }
4339
4866
  // @ts-ignore
4340
- if (previous?.typ == 'AtRule' &&
4867
+ if (previous?.typ == 3 /* NodeType.AtRuleNodeType */ &&
4341
4868
  previous.nam == node.nam &&
4342
4869
  previous.val == node.val) {
4343
4870
  if ('chi' in node) {
4344
4871
  // @ts-ignore
4345
4872
  previous.chi.push(...node.chi);
4346
4873
  }
4347
- // else {
4348
4874
  ast?.chi?.splice(i--, 1);
4349
4875
  continue;
4350
- // }
4351
4876
  }
4352
4877
  // @ts-ignore
4353
- if (hasDeclaration(node)) {
4354
- // @ts-ignore
4355
- minifyRule(node);
4356
- }
4357
- else {
4358
- minify(node, options, recursive, errors, nestingContent);
4878
+ if (!hasDeclaration(node)) {
4879
+ minify(node, options, recursive, errors, nestingContent, context);
4359
4880
  }
4360
4881
  previous = node;
4361
4882
  nodeIndex = i;
4362
4883
  continue;
4363
4884
  }
4364
4885
  // @ts-ignore
4365
- if (node.typ == 'Rule') {
4886
+ if (node.typ == 4 /* NodeType.RuleNodeType */) {
4366
4887
  reduceRuleSelector(node);
4367
4888
  let wrapper;
4368
4889
  let match;
4369
4890
  // @ts-ignore
4370
4891
  if (options.nestingRules) {
4371
4892
  // @ts-ignore
4372
- if (previous?.typ == 'Rule') {
4893
+ if (previous?.typ == 4 /* NodeType.RuleNodeType */) {
4373
4894
  // @ts-ignore
4374
4895
  reduceRuleSelector(previous);
4375
4896
  // @ts-ignore
4376
- match = matchSelectors(previous.raw, node.raw, ast.typ);
4897
+ match = matchSelectors(previous.raw, node.raw, ast.typ, errors);
4377
4898
  // @ts-ignore
4378
4899
  if (match != null) {
4379
4900
  // @ts-ignore
4380
- wrapper = wrapNodes(previous, node, match, ast, i, nodeIndex);
4901
+ wrapper = wrapNodes(previous, node, match, ast, reducer, i, nodeIndex);
4381
4902
  nodeIndex = i - 1;
4382
4903
  // @ts-ignore
4383
4904
  previous = ast.chi[nodeIndex];
@@ -4390,26 +4911,23 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4390
4911
  // @ts-ignore
4391
4912
  const nextNode = ast.chi[i];
4392
4913
  // @ts-ignore
4393
- if (nextNode.typ != 'Rule') {
4394
- // i--;
4395
- // previous = wrapper;
4396
- // nodeIndex = i;
4914
+ if (nextNode.typ != 4 /* NodeType.RuleNodeType */) {
4397
4915
  break;
4398
4916
  }
4399
4917
  reduceRuleSelector(nextNode);
4400
4918
  // @ts-ignore
4401
- match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ);
4919
+ match = matchSelectors(wrapper.raw, nextNode.raw, ast.typ, errors);
4402
4920
  // @ts-ignore
4403
4921
  if (match == null) {
4404
4922
  break;
4405
4923
  }
4406
4924
  // @ts-ignore
4407
- wrapper = wrapNodes(wrapper, nextNode, match, ast, i, nodeIndex);
4925
+ wrapper = wrapNodes(wrapper, nextNode, match, ast, reducer, i, nodeIndex);
4408
4926
  }
4409
4927
  nodeIndex = --i;
4410
4928
  // @ts-ignore
4411
4929
  previous = ast.chi[nodeIndex];
4412
- minify(wrapper, options, recursive, errors, nestingContent);
4930
+ minify(wrapper, options, recursive, errors, nestingContent, context);
4413
4931
  continue;
4414
4932
  }
4415
4933
  // @ts-ignore
@@ -4447,7 +4965,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4447
4965
  curr.splice(0, 2);
4448
4966
  }
4449
4967
  else {
4450
- if (ast.typ != 'Rule' && combinators.includes(curr[1])) {
4968
+ if (ast.typ != 4 /* NodeType.RuleNodeType */ && combinators.includes(curr[1])) {
4451
4969
  wrap = false;
4452
4970
  }
4453
4971
  else {
@@ -4464,7 +4982,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4464
4982
  return acc;
4465
4983
  }, []);
4466
4984
  if (!wrap) {
4467
- wrap = selector.some(s => s[0] != '&');
4985
+ wrap = selector.some((s) => s[0] != '&');
4468
4986
  }
4469
4987
  let rule = selector.map(s => {
4470
4988
  if (s[0] == '&') {
@@ -4495,37 +5013,36 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4495
5013
  let k = previous.chi.length;
4496
5014
  while (k-- > 0) {
4497
5015
  // @ts-ignore
4498
- if (previous.chi[k].typ == 'Comment') {
5016
+ if (previous.chi[k].typ == 0 /* NodeType.CommentNodeType */) {
4499
5017
  continue;
4500
5018
  }
4501
5019
  // @ts-ignore
4502
- shouldMerge = previous.chi[k].typ == 'Declaration';
5020
+ shouldMerge = previous.chi[k].typ == 5 /* NodeType.DeclarationNodeType */;
4503
5021
  break;
4504
5022
  }
4505
5023
  if (shouldMerge) {
4506
5024
  // @ts-ignore
4507
- if ((node.typ == 'Rule' && node.sel == previous.sel) ||
5025
+ if ((node.typ == 4 /* NodeType.RuleNodeType */ && node.sel == previous.sel) ||
4508
5026
  // @ts-ignore
4509
- (node.typ == 'AtRule') && node.val != 'font-face' && node.val == previous.val) {
5027
+ (node.typ == 3 /* NodeType.AtRuleNodeType */) && node.val != 'font-face' && node.val == previous.val) {
4510
5028
  // @ts-ignore
4511
5029
  node.chi.unshift(...previous.chi);
4512
5030
  // @ts-ignore
4513
5031
  ast.chi.splice(nodeIndex, 1);
4514
5032
  // @ts-ignore
4515
- if (hasDeclaration(node)) {
5033
+ if (!hasDeclaration(node)) {
4516
5034
  // @ts-ignore
4517
- minifyRule(node);
4518
- }
4519
- else {
4520
- minify(node, options, recursive, errors, nestingContent);
5035
+ // minifyRule(node, <MinifyOptions>options, ast, context);
5036
+ // } else {
5037
+ minify(node, options, recursive, errors, nestingContent, context);
4521
5038
  }
4522
5039
  i--;
4523
5040
  previous = node;
4524
5041
  nodeIndex = i;
4525
5042
  continue;
4526
5043
  }
4527
- else if (node.typ == 'Rule' && previous?.typ == 'Rule') {
4528
- const intersect = diff(previous, node, options);
5044
+ else if (node.typ == 4 /* NodeType.RuleNodeType */ && previous?.typ == 4 /* NodeType.RuleNodeType */) {
5045
+ const intersect = diff(previous, node, reducer, options);
4529
5046
  if (intersect != null) {
4530
5047
  if (intersect.node1.chi.length == 0) {
4531
5048
  // @ts-ignore
@@ -4557,24 +5074,22 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4557
5074
  // @ts-ignore
4558
5075
  if (recursive && previous != node) {
4559
5076
  // @ts-ignore
4560
- if (hasDeclaration(previous)) {
5077
+ if (!hasDeclaration(previous)) {
4561
5078
  // @ts-ignore
4562
- minifyRule(previous);
4563
- }
4564
- else {
4565
- minify(previous, options, recursive, errors, nestingContent);
5079
+ // minifyRule(previous, <MinifyOptions>options, ast, context);
5080
+ // } else {
5081
+ minify(previous, options, recursive, errors, nestingContent, context);
4566
5082
  }
4567
5083
  }
4568
5084
  }
4569
5085
  else {
4570
5086
  if ('chi' in previous) {
4571
5087
  // @ts-ignore
4572
- if (hasDeclaration(previous)) {
5088
+ if (!hasDeclaration(previous)) {
4573
5089
  // @ts-ignore
4574
- minifyRule(previous);
4575
- }
4576
- else {
4577
- minify(previous, options, recursive, errors, nestingContent);
5090
+ // minifyRule(previous, <MinifyOptions>options, ast, context);
5091
+ // } else {
5092
+ minify(previous, options, recursive, errors, nestingContent, context);
4578
5093
  }
4579
5094
  }
4580
5095
  }
@@ -4583,7 +5098,7 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4583
5098
  // @ts-ignore
4584
5099
  previous != null &&
4585
5100
  // previous.optimized != null &&
4586
- previous.typ == 'Rule' &&
5101
+ previous.typ == 4 /* NodeType.RuleNodeType */ &&
4587
5102
  previous.sel.includes('&')) {
4588
5103
  fixSelector(previous);
4589
5104
  }
@@ -4593,13 +5108,10 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4593
5108
  // @ts-ignore
4594
5109
  if (recursive && node != null && ('chi' in node)) {
4595
5110
  // @ts-ignore
4596
- if (node.chi.some(n => n.typ == 'Declaration')) {
4597
- minifyRule(node);
4598
- }
4599
- else {
5111
+ if (!node.chi.some(n => n.typ == 5 /* NodeType.DeclarationNodeType */)) {
4600
5112
  // @ts-ignore
4601
- if (!(node.typ == 'AtRule' && node.nam != 'font-face')) {
4602
- minify(node, options, recursive, errors, nestingContent);
5113
+ if (!(node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam != 'font-face')) {
5114
+ minify(node, options, recursive, errors, nestingContent, context);
4603
5115
  }
4604
5116
  }
4605
5117
  }
@@ -4607,11 +5119,46 @@ function minify(ast, options = {}, recursive = false, errors, nestingContent) {
4607
5119
  // @ts-ignore
4608
5120
  node != null &&
4609
5121
  // previous.optimized != null &&
4610
- node.typ == 'Rule' &&
5122
+ node.typ == 4 /* NodeType.RuleNodeType */ &&
4611
5123
  node.sel.includes('&')) {
4612
5124
  fixSelector(node);
4613
5125
  }
4614
5126
  }
5127
+ if (ast.typ == 2 /* NodeType.StyleSheetNodeType */) {
5128
+ let parent;
5129
+ let parents = [ast];
5130
+ while (parents.length > 0) {
5131
+ parent = parents.shift();
5132
+ // @ts-ignore
5133
+ for (let k = 0; k < parent.chi.length; k++) {
5134
+ // @ts-ignore
5135
+ const node = parent.chi[k];
5136
+ if (!('chi' in node) || node.typ == 2 /* NodeType.StyleSheetNodeType */ || (node.typ == 3 /* NodeType.AtRuleNodeType */ && node.nam == 'font-face')) {
5137
+ continue;
5138
+ }
5139
+ // @ts-ignore
5140
+ if (node.chi.length > 0) {
5141
+ parents.push(node);
5142
+ Object.defineProperty(node, 'parent', { ...definedPropertySettings, value: parent });
5143
+ for (const feature of options.features) {
5144
+ feature.run(node, options, parent, context);
5145
+ }
5146
+ }
5147
+ // @ts-ignore
5148
+ if (options.removeEmpty && node.chi.length == 0) {
5149
+ // @ts-ignore
5150
+ parent.chi.splice(k, 1);
5151
+ k--;
5152
+ }
5153
+ }
5154
+ }
5155
+ for (const feature of options.features) {
5156
+ if ('cleanup' in feature) {
5157
+ // @ts-ignore
5158
+ feature.cleanup(ast, options, context);
5159
+ }
5160
+ }
5161
+ }
4615
5162
  return ast;
4616
5163
  }
4617
5164
  function reduceSelector(selector) {
@@ -4697,37 +5244,14 @@ function hasDeclaration(node) {
4697
5244
  // @ts-ignore
4698
5245
  for (let i = 0; i < node.chi?.length; i++) {
4699
5246
  // @ts-ignore
4700
- if (node.chi[i].typ == 'Comment') {
5247
+ if (node.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
4701
5248
  continue;
4702
5249
  }
4703
5250
  // @ts-ignore
4704
- return node.chi[i].typ == 'Declaration';
5251
+ return node.chi[i].typ == 5 /* NodeType.DeclarationNodeType */;
4705
5252
  }
4706
5253
  return true;
4707
5254
  }
4708
- function minifyRule(ast) {
4709
- // @ts-ignore
4710
- if (!('chi' in ast) || ast.chi?.length <= 1) {
4711
- return ast;
4712
- }
4713
- // @ts-ignore
4714
- const j = ast.chi.length;
4715
- let k = 0;
4716
- let properties = new PropertyList();
4717
- // @ts-ignore
4718
- for (; k < j; k++) {
4719
- // @ts-ignore
4720
- const node = ast.chi[k];
4721
- if (node.typ == 'Comment' || node.typ == 'Declaration') {
4722
- properties.add(node);
4723
- continue;
4724
- }
4725
- break;
4726
- }
4727
- // @ts-ignore
4728
- ast.chi = [...properties].concat(ast.chi.slice(k));
4729
- return ast;
4730
- }
4731
5255
  function splitRule(buffer) {
4732
5256
  const result = [[]];
4733
5257
  let str = '';
@@ -4816,6 +5340,300 @@ function splitRule(buffer) {
4816
5340
  }
4817
5341
  return result;
4818
5342
  }
5343
+ function matchSelectors(selector1, selector2, parentType, errors) {
5344
+ let match = [[]];
5345
+ 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));
5346
+ let i = 0;
5347
+ let k;
5348
+ let l;
5349
+ let token;
5350
+ let matching = true;
5351
+ let matchFunction = 0;
5352
+ let inAttr = 0;
5353
+ for (; i < j; i++) {
5354
+ k = 0;
5355
+ token = selector1[0][i];
5356
+ for (; k < selector1.length; k++) {
5357
+ if (selector1[k][i] != token) {
5358
+ matching = false;
5359
+ break;
5360
+ }
5361
+ }
5362
+ if (matching) {
5363
+ l = 0;
5364
+ for (; l < selector2.length; l++) {
5365
+ if (selector2[l][i] != token) {
5366
+ matching = false;
5367
+ break;
5368
+ }
5369
+ }
5370
+ }
5371
+ if (!matching) {
5372
+ break;
5373
+ }
5374
+ if (token == ',') {
5375
+ match.push([]);
5376
+ }
5377
+ else {
5378
+ if (token.endsWith('(')) {
5379
+ matchFunction++;
5380
+ }
5381
+ if (token.endsWith('[')) {
5382
+ inAttr++;
5383
+ }
5384
+ else if (token == ')') {
5385
+ matchFunction--;
5386
+ }
5387
+ else if (token == ']') {
5388
+ inAttr--;
5389
+ }
5390
+ match.at(-1).push(token);
5391
+ }
5392
+ }
5393
+ // invalid function
5394
+ if (matchFunction != 0 || inAttr != 0) {
5395
+ return null;
5396
+ }
5397
+ if (parentType != 4 /* NodeType.RuleNodeType */) {
5398
+ for (const part of match) {
5399
+ if (part.length > 0 && combinators.includes(part[0].charAt(0))) {
5400
+ return null;
5401
+ }
5402
+ }
5403
+ }
5404
+ if (match.length > 1) {
5405
+ errors?.push({
5406
+ action: 'ignore',
5407
+ message: `minify: unsupported multilevel matching\n${JSON.stringify({
5408
+ match,
5409
+ selector1,
5410
+ selector2
5411
+ }, null, 1)}`
5412
+ });
5413
+ return null;
5414
+ }
5415
+ for (const part of match) {
5416
+ while (part.length > 0) {
5417
+ const token = part.at(-1);
5418
+ if (token == ' ' || combinators.includes(token) || notEndingWith.includes(token.at(-1))) {
5419
+ part.pop();
5420
+ continue;
5421
+ }
5422
+ break;
5423
+ }
5424
+ }
5425
+ if (match.every(t => t.length == 0)) {
5426
+ return null;
5427
+ }
5428
+ if (eq([['&']], match)) {
5429
+ return null;
5430
+ }
5431
+ function reduce(acc, curr) {
5432
+ if (acc === null) {
5433
+ return null;
5434
+ }
5435
+ let hasCompoundSelector = true;
5436
+ curr = curr.slice(match[0].length);
5437
+ while (curr.length > 0) {
5438
+ if (curr[0] == ' ') {
5439
+ hasCompoundSelector = false;
5440
+ curr.unshift('&');
5441
+ continue;
5442
+ }
5443
+ break;
5444
+ }
5445
+ // invalid function match
5446
+ if (curr.length > 0 && curr[0].endsWith('(') && curr.at(-1) != ')') {
5447
+ return null;
5448
+ }
5449
+ if (curr.length == 1 && combinators.includes(curr[0].charAt(0))) {
5450
+ return null;
5451
+ }
5452
+ if (hasCompoundSelector && curr.length > 0) {
5453
+ hasCompoundSelector = !['&'].concat(combinators).includes(curr[0].charAt(0));
5454
+ }
5455
+ if (curr[0] == ':is(') {
5456
+ let inFunction = 0;
5457
+ let canReduce = true;
5458
+ const isCompound = curr.reduce((acc, token, index) => {
5459
+ if (index == 0) {
5460
+ inFunction++;
5461
+ canReduce = curr[1] == '&';
5462
+ }
5463
+ else if (token.endsWith('(')) {
5464
+ if (inFunction == 0) {
5465
+ canReduce = false;
5466
+ }
5467
+ inFunction++;
5468
+ }
5469
+ else if (token == ')') {
5470
+ inFunction--;
5471
+ }
5472
+ else if (token == ',') {
5473
+ if (!canReduce) {
5474
+ canReduce = curr[index + 1] == '&';
5475
+ }
5476
+ acc.push([]);
5477
+ }
5478
+ else
5479
+ acc.at(-1)?.push(token);
5480
+ return acc;
5481
+ }, [[]]);
5482
+ if (inFunction > 0) {
5483
+ canReduce = false;
5484
+ }
5485
+ if (canReduce) {
5486
+ curr = isCompound.reduce((acc, curr) => {
5487
+ if (acc.length > 0) {
5488
+ acc.push(',');
5489
+ }
5490
+ acc.push(...curr);
5491
+ return acc;
5492
+ }, []);
5493
+ }
5494
+ }
5495
+ // @todo: check hasCompoundSelector && curr[0] == '&' && curr[1] == ' '
5496
+ acc.push(match.length == 0 ? ['&'] : (hasCompoundSelector && curr[0] != '&' && (curr.length == 0 || !combinators.includes(curr[0].charAt(0))) ? ['&'].concat(curr) : curr));
5497
+ return acc;
5498
+ }
5499
+ // @ts-ignore
5500
+ selector1 = selector1.reduce(reduce, []);
5501
+ // @ts-ignore
5502
+ selector2 = selector2.reduce(reduce, []);
5503
+ return selector1 == null || selector2 == null ? null : {
5504
+ eq: eq(selector1, selector2),
5505
+ match,
5506
+ selector1,
5507
+ selector2
5508
+ };
5509
+ }
5510
+ function fixSelector(node) {
5511
+ // @ts-ignore
5512
+ if (node.sel.includes('&')) {
5513
+ const attributes = parseString(node.sel);
5514
+ for (const attr of walkValues(attributes)) {
5515
+ if (attr.value.typ == exports.EnumToken.PseudoClassFuncTokenType && attr.value.val == ':is') {
5516
+ let i = attr.value.chi.length;
5517
+ while (i--) {
5518
+ if (attr.value.chi[i].typ == exports.EnumToken.LiteralTokenType && attr.value.chi[i].val == '&') {
5519
+ attr.value.chi.splice(i, 1);
5520
+ }
5521
+ }
5522
+ }
5523
+ }
5524
+ node.sel = attributes.reduce((acc, curr) => acc + renderToken(curr), '');
5525
+ }
5526
+ }
5527
+ function wrapNodes(previous, node, match, ast, reducer, i, nodeIndex) {
5528
+ // @ts-ignore
5529
+ let pSel = match.selector1.reduce(reducer, []).join(',');
5530
+ // @ts-ignore
5531
+ let nSel = match.selector2.reduce(reducer, []).join(',');
5532
+ // @ts-ignore
5533
+ const wrapper = { ...previous, chi: [], sel: match.match.reduce(reducer, []).join(',') };
5534
+ // @ts-ignore
5535
+ Object.defineProperty(wrapper, 'raw', {
5536
+ ...definedPropertySettings,
5537
+ // @ts-ignore
5538
+ value: match.match.map(t => t.slice())
5539
+ });
5540
+ if (pSel == '&' || pSel === '') {
5541
+ // @ts-ignore
5542
+ wrapper.chi.push(...previous.chi);
5543
+ // @ts-ignore
5544
+ if ((nSel == '&' || nSel === '')) {
5545
+ // @ts-ignore
5546
+ wrapper.chi.push(...node.chi);
5547
+ }
5548
+ else {
5549
+ // @ts-ignore
5550
+ wrapper.chi.push(node);
5551
+ }
5552
+ }
5553
+ else {
5554
+ // @ts-ignore
5555
+ wrapper.chi.push(previous, node);
5556
+ }
5557
+ // @ts-ignore
5558
+ ast.chi.splice(i, 1, wrapper);
5559
+ // @ts-ignore
5560
+ ast.chi.splice(nodeIndex, 1);
5561
+ // @ts-ignore
5562
+ previous.sel = pSel;
5563
+ // @ts-ignore
5564
+ previous.raw = match.selector1;
5565
+ // @ts-ignore
5566
+ node.sel = nSel;
5567
+ // @ts-ignore
5568
+ node.raw = match.selector2;
5569
+ reduceRuleSelector(wrapper);
5570
+ return wrapper;
5571
+ }
5572
+ function diff(n1, n2, reducer, options = {}) {
5573
+ let node1 = n1;
5574
+ let node2 = n2;
5575
+ let exchanged = false;
5576
+ if (node1.chi.length > node2.chi.length) {
5577
+ const t = node1;
5578
+ node1 = node2;
5579
+ node2 = t;
5580
+ exchanged = true;
5581
+ }
5582
+ let i = node1.chi.length;
5583
+ let j = node2.chi.length;
5584
+ if (i == 0 || j == 0) {
5585
+ // @ts-ignore
5586
+ return null;
5587
+ }
5588
+ // @ts-ignore
5589
+ const raw1 = node1.raw;
5590
+ // @ts-ignore
5591
+ const raw2 = node2.raw;
5592
+ // @ts-ignore
5593
+ node1 = { ...node1, chi: node1.chi.slice() };
5594
+ node2 = { ...node2, chi: node2.chi.slice() };
5595
+ if (raw1 != null) {
5596
+ Object.defineProperty(node1, 'raw', { ...definedPropertySettings, value: raw1 });
5597
+ }
5598
+ if (raw2 != null) {
5599
+ Object.defineProperty(node2, 'raw', { ...definedPropertySettings, value: raw2 });
5600
+ }
5601
+ const intersect = [];
5602
+ while (i--) {
5603
+ if (node1.chi[i].typ == 0 /* NodeType.CommentNodeType */) {
5604
+ continue;
5605
+ }
5606
+ j = node2.chi.length;
5607
+ if (j == 0) {
5608
+ break;
5609
+ }
5610
+ while (j--) {
5611
+ if (node2.chi[j].typ == 0 /* NodeType.CommentNodeType */) {
5612
+ continue;
5613
+ }
5614
+ if (node1.chi[i].nam == node2.chi[j].nam) {
5615
+ if (eq(node1.chi[i], node2.chi[j])) {
5616
+ intersect.push(node1.chi[i]);
5617
+ node1.chi.splice(i, 1);
5618
+ node2.chi.splice(j, 1);
5619
+ break;
5620
+ }
5621
+ }
5622
+ }
5623
+ }
5624
+ // @ts-ignore
5625
+ const result = (intersect.length == 0 ? null : {
5626
+ ...node1,
5627
+ // @ts-ignore
5628
+ sel: [...new Set([...(n1?.raw?.reduce(reducer, []) || splitRule(n1.sel)).concat(n2?.raw?.reduce(reducer, []) || splitRule(n2.sel))])].join(','),
5629
+ chi: intersect.reverse()
5630
+ });
5631
+ if (result == null || [n1, n2].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0) <= [node1, node2, result].reduce((acc, curr) => curr.chi.length == 0 ? acc : acc + doRender(curr, options).code.length, 0)) {
5632
+ // @ts-ignore
5633
+ return null;
5634
+ }
5635
+ return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 };
5636
+ }
4819
5637
  function reduceRuleSelector(node) {
4820
5638
  if (node.raw == null) {
4821
5639
  Object.defineProperty(node, 'raw', { ...definedPropertySettings, value: splitRule(node.sel) });
@@ -4851,25 +5669,6 @@ function reduceRuleSelector(node) {
4851
5669
  }
4852
5670
  }
4853
5671
 
4854
- async function transform$1(css, options = {}) {
4855
- options = { minify: true, removeEmpty: true, ...options };
4856
- const startTime = performance.now();
4857
- return parse$1(css, options).then((parseResult) => {
4858
- const rendered = render(parseResult.ast, options);
4859
- return {
4860
- ...parseResult,
4861
- ...rendered,
4862
- errors: parseResult.errors.concat(rendered.errors),
4863
- stats: {
4864
- bytesOut: rendered.code.length,
4865
- ...parseResult.stats,
4866
- render: rendered.stats.total,
4867
- total: `${(performance.now() - startTime).toFixed(2)}ms`
4868
- }
4869
- };
4870
- });
4871
- }
4872
-
4873
5672
  const matchUrl = /^(https?:)?\/\//;
4874
5673
  function dirname(path) {
4875
5674
  if (path == '/' || path === '') {
@@ -4980,16 +5779,36 @@ async function load(url, currentFile) {
4980
5779
  return matchUrl.test(resolved.absolute) ? fetch(resolved.absolute).then(parseResponse) : promises.readFile(resolved.absolute, { encoding: 'utf-8' });
4981
5780
  }
4982
5781
 
5782
+ function render(data, options = {}) {
5783
+ return doRender(data, Object.assign(options, { load, resolve, dirname, cwd: options.cwd ?? process.cwd() }));
5784
+ }
4983
5785
  async function parse(iterator, opt = {}) {
4984
- return parse$1(iterator, Object.assign(opt, { load, resolve, cwd: opt.cwd ?? process.cwd() }));
5786
+ return doParse(iterator, Object.assign(opt, { load, resolve, dirname, cwd: opt.cwd ?? process.cwd() }));
4985
5787
  }
4986
5788
  async function transform(css, options = {}) {
4987
- return transform$1(css, Object.assign(options, { load, resolve, cwd: options.cwd ?? process.cwd() }));
5789
+ options = { minify: true, removeEmpty: true, removeCharset: true, ...options };
5790
+ const startTime = performance.now();
5791
+ return parse(css, options).then((parseResult) => {
5792
+ const rendered = render(parseResult.ast, options);
5793
+ return {
5794
+ ...parseResult,
5795
+ ...rendered,
5796
+ errors: parseResult.errors.concat(rendered.errors),
5797
+ stats: {
5798
+ bytesOut: rendered.code.length,
5799
+ ...parseResult.stats,
5800
+ render: rendered.stats.total,
5801
+ total: `${(performance.now() - startTime).toFixed(2)}ms`
5802
+ }
5803
+ };
5804
+ });
4988
5805
  }
4989
5806
 
4990
5807
  exports.colorsFunc = colorsFunc;
4991
5808
  exports.combinators = combinators;
4992
5809
  exports.dirname = dirname;
5810
+ exports.doParse = doParse;
5811
+ exports.doRender = doRender;
4993
5812
  exports.expand = expand;
4994
5813
  exports.funcList = funcList;
4995
5814
  exports.getConfig = getConfig;
@@ -5019,10 +5838,11 @@ exports.load = load;
5019
5838
  exports.matchType = matchType;
5020
5839
  exports.matchUrl = matchUrl;
5021
5840
  exports.minify = minify;
5022
- exports.minifyRule = minifyRule;
5023
5841
  exports.parse = parse;
5024
5842
  exports.parseDimension = parseDimension;
5025
5843
  exports.parseString = parseString;
5844
+ exports.parseTokens = parseTokens;
5845
+ exports.reduceNumber = reduceNumber;
5026
5846
  exports.reduceSelector = reduceSelector;
5027
5847
  exports.render = render;
5028
5848
  exports.renderToken = renderToken;