@tbela99/css-parser 0.2.0 → 0.3.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
@@ -61,25 +61,29 @@ exports.EnumToken = void 0;
61
61
  EnumToken[EnumToken["BadStringTokenType"] = 54] = "BadStringTokenType";
62
62
  EnumToken[EnumToken["BinaryExpressionTokenType"] = 55] = "BinaryExpressionTokenType";
63
63
  EnumToken[EnumToken["UnaryExpressionTokenType"] = 56] = "UnaryExpressionTokenType";
64
+ EnumToken[EnumToken["FlexTokenType"] = 57] = "FlexTokenType";
64
65
  /* catch all */
65
- EnumToken[EnumToken["ListToken"] = 57] = "ListToken";
66
+ EnumToken[EnumToken["ListToken"] = 58] = "ListToken";
66
67
  /* arithmetic tokens */
67
- EnumToken[EnumToken["Add"] = 58] = "Add";
68
- EnumToken[EnumToken["Mul"] = 59] = "Mul";
69
- EnumToken[EnumToken["Div"] = 60] = "Div";
70
- EnumToken[EnumToken["Sub"] = 61] = "Sub";
68
+ EnumToken[EnumToken["Add"] = 59] = "Add";
69
+ EnumToken[EnumToken["Mul"] = 60] = "Mul";
70
+ EnumToken[EnumToken["Div"] = 61] = "Div";
71
+ EnumToken[EnumToken["Sub"] = 62] = "Sub";
71
72
  /* new tokens */
72
- EnumToken[EnumToken["ColumnCombinatorTokenType"] = 62] = "ColumnCombinatorTokenType";
73
- EnumToken[EnumToken["ContainMatchTokenType"] = 63] = "ContainMatchTokenType";
74
- EnumToken[EnumToken["StartMatchTokenType"] = 64] = "StartMatchTokenType";
75
- EnumToken[EnumToken["EndMatchTokenType"] = 65] = "EndMatchTokenType";
76
- EnumToken[EnumToken["MatchExpressionTokenType"] = 66] = "MatchExpressionTokenType";
77
- EnumToken[EnumToken["NameSpaceAttributeTokenType"] = 67] = "NameSpaceAttributeTokenType";
78
- EnumToken[EnumToken["FractionTokenType"] = 68] = "FractionTokenType";
73
+ EnumToken[EnumToken["ColumnCombinatorTokenType"] = 63] = "ColumnCombinatorTokenType";
74
+ EnumToken[EnumToken["ContainMatchTokenType"] = 64] = "ContainMatchTokenType";
75
+ EnumToken[EnumToken["StartMatchTokenType"] = 65] = "StartMatchTokenType";
76
+ EnumToken[EnumToken["EndMatchTokenType"] = 66] = "EndMatchTokenType";
77
+ EnumToken[EnumToken["MatchExpressionTokenType"] = 67] = "MatchExpressionTokenType";
78
+ EnumToken[EnumToken["NameSpaceAttributeTokenType"] = 68] = "NameSpaceAttributeTokenType";
79
+ EnumToken[EnumToken["FractionTokenType"] = 69] = "FractionTokenType";
80
+ EnumToken[EnumToken["IdenListTokenType"] = 70] = "IdenListTokenType";
81
+ EnumToken[EnumToken["GridTemplateFuncTokenType"] = 71] = "GridTemplateFuncTokenType";
79
82
  /* aliases */
80
83
  EnumToken[EnumToken["Time"] = 25] = "Time";
81
84
  EnumToken[EnumToken["Iden"] = 7] = "Iden";
82
85
  EnumToken[EnumToken["Hash"] = 28] = "Hash";
86
+ EnumToken[EnumToken["Flex"] = 57] = "Flex";
83
87
  EnumToken[EnumToken["Angle"] = 24] = "Angle";
84
88
  EnumToken[EnumToken["Color"] = 49] = "Color";
85
89
  EnumToken[EnumToken["Comma"] = 9] = "Comma";
@@ -94,13 +98,26 @@ exports.EnumToken = void 0;
94
98
  EnumToken[EnumToken["Frequency"] = 26] = "Frequency";
95
99
  EnumToken[EnumToken["Resolution"] = 27] = "Resolution";
96
100
  EnumToken[EnumToken["Whitespace"] = 36] = "Whitespace";
101
+ EnumToken[EnumToken["IdenList"] = 70] = "IdenList";
97
102
  EnumToken[EnumToken["DashedIden"] = 8] = "DashedIden";
103
+ EnumToken[EnumToken["GridTemplateFunc"] = 71] = "GridTemplateFunc";
98
104
  EnumToken[EnumToken["ImageFunc"] = 19] = "ImageFunc";
99
105
  EnumToken[EnumToken["CommentNodeType"] = 0] = "CommentNodeType";
100
106
  EnumToken[EnumToken["CDOCOMMNodeType"] = 1] = "CDOCOMMNodeType";
101
107
  EnumToken[EnumToken["TimingFunction"] = 17] = "TimingFunction";
102
108
  EnumToken[EnumToken["TimelineFunction"] = 16] = "TimelineFunction";
103
109
  })(exports.EnumToken || (exports.EnumToken = {}));
110
+ const funcLike = [
111
+ exports.EnumToken.ParensTokenType,
112
+ exports.EnumToken.FunctionTokenType,
113
+ exports.EnumToken.UrlFunctionTokenType,
114
+ exports.EnumToken.StartParensTokenType,
115
+ exports.EnumToken.ImageFunctionTokenType,
116
+ exports.EnumToken.TimingFunctionTokenType,
117
+ exports.EnumToken.TimingFunctionTokenType,
118
+ exports.EnumToken.PseudoClassFuncTokenType,
119
+ exports.EnumToken.GridTemplateFuncTokenType
120
+ ];
104
121
 
105
122
  // name to color
106
123
  const COLORS_NAMES = Object.seal({
@@ -406,26 +423,152 @@ const NAMES_COLORS = Object.seal({
406
423
  '#663399': 'rebeccapurple',
407
424
  '#00000000': 'transparent'
408
425
  });
426
+ /**
427
+ * clamp color values
428
+ * @param token
429
+ */
430
+ function clamp(token) {
431
+ if (token.kin == 'rgb' || token.kin == 'rgba') {
432
+ token.chi.filter((token) => ![exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType].includes(token.typ)).
433
+ forEach((token, index) => {
434
+ if (index <= 2) {
435
+ if (token.typ == exports.EnumToken.NumberTokenType) {
436
+ token.val = String(Math.min(255, Math.max(0, +token.val)));
437
+ }
438
+ else if (token.typ == exports.EnumToken.PercentageTokenType) {
439
+ token.val = String(Math.min(100, Math.max(0, +token.val)));
440
+ }
441
+ }
442
+ else {
443
+ if (token.typ == exports.EnumToken.NumberTokenType) {
444
+ token.val = String(Math.min(1, Math.max(0, +token.val)));
445
+ }
446
+ else if (token.typ == exports.EnumToken.PercentageTokenType) {
447
+ token.val = String(Math.min(100, Math.max(0, +token.val)));
448
+ }
449
+ }
450
+ });
451
+ }
452
+ return token;
453
+ }
454
+ function getNumber(token) {
455
+ if (token.typ == exports.EnumToken.IdenTokenType && token.val == 'none') {
456
+ return 0;
457
+ }
458
+ // @ts-ignore
459
+ return token.typ == exports.EnumToken.PercentageTokenType ? token.val / 100 : +token.val;
460
+ }
461
+ function getAngle(token) {
462
+ if (token.typ == exports.EnumToken.IdenTokenType) {
463
+ if (token.val == 'none') {
464
+ return 0;
465
+ }
466
+ }
467
+ if (token.typ == exports.EnumToken.AngleTokenType) {
468
+ switch (token.unit) {
469
+ case 'deg':
470
+ // @ts-ignore
471
+ return token.val / 360;
472
+ case 'rad':
473
+ // @ts-ignore
474
+ return token.val / (2 * Math.PI);
475
+ case 'grad':
476
+ // @ts-ignore
477
+ return token.val / 400;
478
+ case 'turn':
479
+ // @ts-ignore
480
+ return +token.val;
481
+ }
482
+ }
483
+ // @ts-ignore
484
+ return token.val / 360;
485
+ }
486
+
487
+ function hwb2rgb(hue, white, black, alpha = null) {
488
+ const rgb = hsl2rgb(hue, 1, .5);
489
+ for (let i = 0; i < 3; i++) {
490
+ rgb[i] *= (1 - white - black);
491
+ rgb[i] = Math.round(rgb[i] + white);
492
+ }
493
+ if (alpha != null && alpha != 1) {
494
+ rgb.push(alpha);
495
+ }
496
+ return rgb;
497
+ }
498
+ function hsl2rgb(h, s, l, a = null) {
499
+ let v = l <= .5 ? l * (1.0 + s) : l + s - l * s;
500
+ let r = l;
501
+ let g = l;
502
+ let b = l;
503
+ if (v > 0) {
504
+ let m = l + l - v;
505
+ let sv = (v - m) / v;
506
+ h *= 6.0;
507
+ let sextant = Math.floor(h);
508
+ let fract = h - sextant;
509
+ let vsf = v * sv * fract;
510
+ let mid1 = m + vsf;
511
+ let mid2 = v - vsf;
512
+ switch (sextant) {
513
+ case 0:
514
+ r = v;
515
+ g = mid1;
516
+ b = m;
517
+ break;
518
+ case 1:
519
+ r = mid2;
520
+ g = v;
521
+ b = m;
522
+ break;
523
+ case 2:
524
+ r = m;
525
+ g = v;
526
+ b = mid1;
527
+ break;
528
+ case 3:
529
+ r = m;
530
+ g = mid2;
531
+ b = v;
532
+ break;
533
+ case 4:
534
+ r = mid1;
535
+ g = m;
536
+ b = v;
537
+ break;
538
+ case 5:
539
+ r = v;
540
+ g = m;
541
+ b = mid2;
542
+ break;
543
+ }
544
+ }
545
+ const values = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
546
+ if (a != null && a != 1) {
547
+ values.push(Math.round(a * 255));
548
+ }
549
+ return values;
550
+ }
551
+
409
552
  function rgb2Hex(token) {
410
553
  let value = '#';
411
554
  let t;
412
555
  // @ts-ignore
413
- for (let i = 0; i < 6; i += 2) {
556
+ for (let i = 0; i < 3; i++) {
414
557
  // @ts-ignore
415
558
  t = token.chi[i];
416
559
  // @ts-ignore
417
- value += Math.round(t.typ == exports.EnumToken.PercentageTokenType ? 255 * t.val / 100 : t.val).toString(16).padStart(2, '0');
560
+ value += (t.val == 'none' ? '0' : Math.round(t.typ == exports.EnumToken.PercentageTokenType ? 255 * t.val / 100 : t.val)).toString(16).padStart(2, '0');
418
561
  }
419
562
  // @ts-ignore
420
- if (token.chi.length == 7) {
563
+ if (token.chi.length == 4) {
421
564
  // @ts-ignore
422
- t = token.chi[6];
565
+ t = token.chi[3];
423
566
  // @ts-ignore
424
- if ((t.typ == exports.EnumToken.NumberTokenType && t.val < 1) ||
425
- // @ts-ignore
426
- (t.typ == exports.EnumToken.PercentageTokenType && t.val < 100)) {
567
+ if ((t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ||
568
+ (t.typ == exports.EnumToken.NumberTokenType && +t.val < 1) ||
569
+ (t.typ == exports.EnumToken.PercentageTokenType && +t.val < 100)) {
427
570
  // @ts-ignore
428
- value += Math.round(255 * (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val)).toString(16).padStart(2, '0');
571
+ value += Math.round(255 * getNumber(t)).toString(16).padStart(2, '0');
429
572
  }
430
573
  }
431
574
  return value;
@@ -435,23 +578,23 @@ function hsl2Hex(token) {
435
578
  // @ts-ignore
436
579
  let h = getAngle(token.chi[0]);
437
580
  // @ts-ignore
438
- t = token.chi[2];
581
+ t = token.chi[1];
439
582
  // @ts-ignore
440
- let s = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
583
+ let s = getNumber(t);
441
584
  // @ts-ignore
442
- t = token.chi[4];
585
+ t = token.chi[2];
443
586
  // @ts-ignore
444
- let l = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
587
+ let l = getNumber(t);
445
588
  let a = null;
446
- if (token.chi?.length == 7) {
589
+ if (token.chi?.length == 4) {
447
590
  // @ts-ignore
448
- t = token.chi[6];
591
+ t = token.chi[3];
449
592
  // @ts-ignore
450
- if ((t.typ == exports.EnumToken.PercentageTokenType && t.val < 100) ||
593
+ if ((t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') || (t.typ == exports.EnumToken.PercentageTokenType && +t.val < 100) ||
451
594
  // @ts-ignore
452
595
  (t.typ == exports.EnumToken.NumberTokenType && t.val < 1)) {
453
596
  // @ts-ignore
454
- a = (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val);
597
+ a = getNumber(t);
455
598
  }
456
599
  }
457
600
  return `#${hsl2rgb(h, s, l, a).reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
@@ -461,23 +604,23 @@ function hwb2hex(token) {
461
604
  // @ts-ignore
462
605
  let h = getAngle(token.chi[0]);
463
606
  // @ts-ignore
464
- t = token.chi[2];
607
+ t = token.chi[1];
465
608
  // @ts-ignore
466
- let white = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
609
+ let white = getNumber(t);
467
610
  // @ts-ignore
468
- t = token.chi[4];
611
+ t = token.chi[2];
469
612
  // @ts-ignore
470
- let black = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
613
+ let black = getNumber(t);
471
614
  let a = null;
472
- if (token.chi?.length == 7) {
615
+ if (token.chi?.length == 4) {
473
616
  // @ts-ignore
474
- t = token.chi[6];
617
+ t = token.chi[3];
475
618
  // @ts-ignore
476
- if ((t.typ == exports.EnumToken.PercentageTokenType && t.val < 100) ||
619
+ if ((t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') ||
620
+ (t.typ == exports.EnumToken.PercentageTokenType && +t.val < 100) ||
621
+ (t.typ == exports.EnumToken.NumberTokenType && +t.val < 1)) {
477
622
  // @ts-ignore
478
- (t.typ == exports.EnumToken.NumberTokenType && t.val < 1)) {
479
- // @ts-ignore
480
- a = (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val);
623
+ a = getNumber(t);
481
624
  }
482
625
  }
483
626
  const rgb = hsl2rgb(h, 1, .5, a);
@@ -494,19 +637,19 @@ function cmyk2hex(token) {
494
637
  // @ts-ignore
495
638
  let t = token.chi[0];
496
639
  // @ts-ignore
497
- const c = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
640
+ const c = getNumber(t);
498
641
  // @ts-ignore
499
- t = token.chi[2];
642
+ t = token.chi[1];
500
643
  // @ts-ignore
501
- const m = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
644
+ const m = getNumber(t);
502
645
  // @ts-ignore
503
- t = token.chi[4];
646
+ t = token.chi[2];
504
647
  // @ts-ignore
505
- const y = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
648
+ const y = getNumber(t);
506
649
  // @ts-ignore
507
- t = token.chi[6];
650
+ t = token.chi[3];
508
651
  // @ts-ignore
509
- const k = t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val;
652
+ const k = getNumber(t);
510
653
  const rgb = [
511
654
  Math.round(255 * (1 - Math.min(1, c * (1 - k) + k))),
512
655
  Math.round(255 * (1 - Math.min(1, m * (1 - k) + k))),
@@ -517,82 +660,116 @@ function cmyk2hex(token) {
517
660
  // @ts-ignore
518
661
  t = token.chi[8];
519
662
  // @ts-ignore
520
- rgb.push(Math.round(255 * (t.typ == exports.EnumToken.PercentageTokenType ? t.val / 100 : t.val)));
663
+ rgb.push(Math.round(255 * getNumber(t)));
521
664
  }
522
665
  return `#${rgb.reduce((acc, curr) => acc + curr.toString(16).padStart(2, '0'), '')}`;
523
666
  }
524
- function getAngle(token) {
525
- if (token.typ == exports.EnumToken.AngleTokenType) {
526
- switch (token.unit) {
527
- case 'deg':
528
- // @ts-ignore
529
- return token.val / 360;
530
- case 'rad':
531
- // @ts-ignore
532
- return token.val / (2 * Math.PI);
533
- case 'grad':
534
- // @ts-ignore
535
- return token.val / 400;
536
- case 'turn':
537
- // @ts-ignore
538
- return +token.val;
539
- }
667
+
668
+ function hwb2hsv(h, w, b) {
669
+ return [h, 1 - w / (1 - b), 1 - b];
670
+ }
671
+ // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
672
+ function hsl2hsv(h, s, l) {
673
+ s *= l < .5 ? l : 1 - l;
674
+ return [
675
+ //Range should be between 0 - 1
676
+ h,
677
+ 2 * s / (l + s),
678
+ l + s //Value
679
+ ];
680
+ }
681
+
682
+ function rgb2hue(r, g, b, fallback = 0) {
683
+ let value = rgb2value(r, g, b);
684
+ let whiteness = rgb2whiteness(r, g, b);
685
+ let delta = value - whiteness;
686
+ if (delta > 0) {
687
+ // calculate segment
688
+ let segment = value === r ? (g - b) / delta : (value === g
689
+ ? (b - r) / delta
690
+ : (r - g) / delta);
691
+ // calculate shift
692
+ let shift = value === r ? segment < 0
693
+ ? 360 / 60
694
+ : 0 / 60 : (value === g
695
+ ? 120 / 60
696
+ : 240 / 60);
697
+ // calculate hue
698
+ return (segment + shift) * 60;
699
+ }
700
+ return fallback;
701
+ }
702
+ function rgb2value(r, g, b) {
703
+ return Math.max(r, g, b);
704
+ }
705
+ function rgb2whiteness(r, g, b) {
706
+ return Math.min(r, g, b);
707
+ }
708
+ function rgb2hwb(r, g, b, a = null, fallback = 0) {
709
+ r *= 100 / 255;
710
+ g *= 100 / 255;
711
+ b *= 100 / 255;
712
+ let hue = rgb2hue(r, g, b, fallback);
713
+ let whiteness = rgb2whiteness(r, g, b);
714
+ let value = Math.round(rgb2value(r, g, b));
715
+ let blackness = 100 - value;
716
+ const result = [hue / 360, whiteness / 100, blackness / 100];
717
+ if (a != null) {
718
+ result.push(a);
540
719
  }
541
- // @ts-ignore
542
- return token.val / 360;
720
+ return result;
543
721
  }
544
- function hsl2rgb(h, s, l, a = null) {
545
- let v = l <= .5 ? l * (1.0 + s) : l + s - l * s;
546
- let r = l;
547
- let g = l;
548
- let b = l;
549
- if (v > 0) {
550
- let m = l + l - v;
551
- let sv = (v - m) / v;
552
- h *= 6.0;
553
- let sextant = Math.floor(h);
554
- let fract = h - sextant;
555
- let vsf = v * sv * fract;
556
- let mid1 = m + vsf;
557
- let mid2 = v - vsf;
558
- switch (sextant) {
559
- case 0:
560
- r = v;
561
- g = mid1;
562
- b = m;
563
- break;
564
- case 1:
565
- r = mid2;
566
- g = v;
567
- b = m;
568
- break;
569
- case 2:
570
- r = m;
571
- g = v;
572
- b = mid1;
573
- break;
574
- case 3:
575
- r = m;
576
- g = mid2;
577
- b = v;
722
+ function hsv2hwb(h, s, v) {
723
+ return [h, (1 - s) * v, 1 - v];
724
+ }
725
+ function hsl2hwb(h, s, l) {
726
+ return hsv2hwb(...hsl2hsv(h, s, l));
727
+ }
728
+
729
+ function rgb2hsl(r, g, b, a) {
730
+ r /= 255;
731
+ g /= 255;
732
+ b /= 255;
733
+ let max = Math.max(r, g, b);
734
+ let min = Math.min(r, g, b);
735
+ let h = 0;
736
+ let s = 0;
737
+ let l = (max + min) / 2;
738
+ if (max != min) {
739
+ let d = max - min;
740
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
741
+ switch (max) {
742
+ case r:
743
+ h = (g - b) / d + (g < b ? 6 : 0);
578
744
  break;
579
- case 4:
580
- r = mid1;
581
- g = m;
582
- b = v;
745
+ case g:
746
+ h = (b - r) / d + 2;
583
747
  break;
584
- case 5:
585
- r = v;
586
- g = m;
587
- b = mid2;
748
+ case b:
749
+ h = (r - g) / d + 4;
588
750
  break;
589
751
  }
752
+ h /= 6;
590
753
  }
591
- const values = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
592
- if (a != null && a != 1) {
593
- values.push(Math.round(a * 255));
594
- }
595
- return values;
754
+ return [h, s, l, a == 1 ? null : a ?? null];
755
+ }
756
+ // https://gist.github.com/defims/0ca2ef8832833186ed396a2f8a204117#file-annotated-js
757
+ function hsv2hsl(h, s, v) {
758
+ return [
759
+ //[hue, saturation, lightness]
760
+ //Range should be between 0 - 1
761
+ h,
762
+ //Saturation is very different between the two color spaces
763
+ //If (2-sat)*val < 1 set it to sat*val/((2-sat)*val)
764
+ //Otherwise sat*val/(2-(2-sat)*val)
765
+ //Conditional is not operating with hue, it is reassigned!
766
+ s * v / ((h = (2 - s) * v) < 1 ? h : 2 - h),
767
+ h / 2 //Lightness is (2-sat)*val/2
768
+ //See reassignment of hue above
769
+ ];
770
+ }
771
+ function hwb2hsl(h, w, b) {
772
+ return hsv2hsl(...hwb2hsv(h, w, b));
596
773
  }
597
774
 
598
775
  // from https://github.com/Rich-Harris/vlq/tree/master
@@ -686,33 +863,530 @@ class SourceMap {
686
863
  }
687
864
  }
688
865
 
689
- const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'];
690
- function reduceNumber(val) {
691
- val = (+val).toString();
692
- if (val === '0') {
693
- return '0';
694
- }
695
- const chr = val.charAt(0);
696
- if (chr == '-') {
697
- const slice = val.slice(0, 2);
698
- if (slice == '-0') {
699
- return val.length == 2 ? '0' : '-' + val.slice(2);
700
- }
866
+ const gcd = (x, y) => {
867
+ x = Math.abs(x);
868
+ y = Math.abs(y);
869
+ let t;
870
+ if (x == 0 || y == 0) {
871
+ return 1;
701
872
  }
702
- if (chr == '0') {
703
- return val.slice(1);
873
+ while (y) {
874
+ t = y;
875
+ y = x % y;
876
+ x = t;
704
877
  }
705
- return val;
706
- }
707
- function update(position, str) {
708
- let i = 0;
709
- for (; i < str.length; i++) {
710
- if (isNewLine(str[i].charCodeAt(0))) {
711
- position.lin++;
712
- position.col = 0;
878
+ return x;
879
+ };
880
+ function compute(a, b, op) {
881
+ if (typeof a == 'number' && typeof b == 'number') {
882
+ switch (op) {
883
+ case exports.EnumToken.Add:
884
+ return a + b;
885
+ case exports.EnumToken.Sub:
886
+ return a - b;
887
+ case exports.EnumToken.Mul:
888
+ return a * b;
889
+ case exports.EnumToken.Div:
890
+ const r = simplify(a, b);
891
+ if (r[1] == 1) {
892
+ return r[0];
893
+ }
894
+ const result = a / b;
895
+ const r2 = reduceNumber(r[0]) + '/' + reduceNumber(r[1]);
896
+ return reduceNumber(result).length <= r2.length ? result : {
897
+ typ: exports.EnumToken.FractionTokenType,
898
+ l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[0]) },
899
+ r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[1]) }
900
+ };
713
901
  }
714
- else {
715
- position.col++;
902
+ }
903
+ let l1 = typeof a == 'number' ? {
904
+ typ: exports.EnumToken.FractionTokenType,
905
+ l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a) },
906
+ r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
907
+ } : a;
908
+ let r1 = typeof b == 'number' ? {
909
+ typ: exports.EnumToken.FractionTokenType,
910
+ l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(b) },
911
+ r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
912
+ } : b;
913
+ let l2;
914
+ let r2;
915
+ switch (op) {
916
+ case exports.EnumToken.Add:
917
+ // @ts-ignore
918
+ l2 = l1.l.val * r1.r.val + l1.r.val * r1.l.val;
919
+ // @ts-ignore
920
+ r2 = l1.r.val * r1.r.val;
921
+ break;
922
+ case exports.EnumToken.Sub:
923
+ // @ts-ignore
924
+ l2 = l1.l.val * r1.r.val - l1.r.val * r1.l.val;
925
+ // @ts-ignore
926
+ r2 = l1.r.val * r1.r.val;
927
+ break;
928
+ case exports.EnumToken.Mul:
929
+ // @ts-ignore
930
+ l2 = l1.l.val * r1.l.val;
931
+ // @ts-ignore
932
+ r2 = l1.r.val * r1.r.val;
933
+ break;
934
+ case exports.EnumToken.Div:
935
+ // @ts-ignore
936
+ l2 = l1.l.val * r1.r.val;
937
+ // @ts-ignore
938
+ r2 = l1.r.val * r1.l.val;
939
+ break;
940
+ }
941
+ const a2 = simplify(l2, r2);
942
+ if (a2[1] == 1) {
943
+ return a2[0];
944
+ }
945
+ const result = a2[0] / a2[1];
946
+ return reduceNumber(result).length <= reduceNumber(a2[0]).length + 1 + reduceNumber(a2[1]).length ? result : {
947
+ typ: exports.EnumToken.FractionTokenType,
948
+ l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[0]) },
949
+ r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[1]) }
950
+ };
951
+ }
952
+ function simplify(a, b) {
953
+ const g = gcd(a, b);
954
+ return g > 1 ? [a / g, b / g] : [a, b];
955
+ }
956
+
957
+ /**
958
+ * evaluate an array of tokens
959
+ * @param tokens
960
+ */
961
+ function evaluate(tokens) {
962
+ const nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
963
+ if (nodes.length <= 1) {
964
+ return nodes;
965
+ }
966
+ const map = new Map;
967
+ let token;
968
+ let i;
969
+ for (i = 0; i < nodes.length; i++) {
970
+ token = nodes[i];
971
+ if (token.typ == exports.EnumToken.Add) {
972
+ continue;
973
+ }
974
+ if (token.typ == exports.EnumToken.Sub) {
975
+ if (!isScalarToken(nodes[i + 1])) {
976
+ token = { typ: exports.EnumToken.ListToken, chi: [nodes[i], nodes[i + 1]] };
977
+ }
978
+ else {
979
+ token = doEvaluate(nodes[i + 1], { typ: exports.EnumToken.NumberTokenType, val: '-1' }, exports.EnumToken.Mul);
980
+ }
981
+ i++;
982
+ }
983
+ if (!map.has(token.typ)) {
984
+ map.set(token.typ, [token]);
985
+ }
986
+ else {
987
+ map.get(token.typ).push(token);
988
+ }
989
+ }
990
+ return [...map].reduce((acc, curr) => {
991
+ const token = curr[1].reduce((acc, curr) => doEvaluate(acc, curr, exports.EnumToken.Add));
992
+ if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
993
+ if ('val' in token && +token.val < 0) {
994
+ acc.push({ typ: exports.EnumToken.Sub }, { ...token, val: String(-token.val) });
995
+ return acc;
996
+ }
997
+ }
998
+ if (acc.length > 0 && curr[0] != exports.EnumToken.ListToken) {
999
+ acc.push({ typ: exports.EnumToken.Add });
1000
+ }
1001
+ acc.push(token);
1002
+ return acc;
1003
+ }, []);
1004
+ }
1005
+ /**
1006
+ * evaluate arithmetic operation
1007
+ * @param l
1008
+ * @param r
1009
+ * @param op
1010
+ */
1011
+ function doEvaluate(l, r, op) {
1012
+ const defaultReturn = {
1013
+ typ: exports.EnumToken.BinaryExpressionTokenType,
1014
+ op,
1015
+ l,
1016
+ r
1017
+ };
1018
+ if (!isScalarToken(l) || !isScalarToken(r)) {
1019
+ return defaultReturn;
1020
+ }
1021
+ if ((op == exports.EnumToken.Add || op == exports.EnumToken.Sub)) {
1022
+ // @ts-ignore
1023
+ if (l.typ != r.typ) {
1024
+ return defaultReturn;
1025
+ }
1026
+ }
1027
+ const typ = l.typ == exports.EnumToken.NumberTokenType ? r.typ : l.typ;
1028
+ // @ts-ignore
1029
+ const val = compute(typeof l.val == 'string' ? +l.val : l.val, typeof r.val == 'string' ? +r.val : r.val, op);
1030
+ return { ...(l.typ == exports.EnumToken.NumberTokenType ? r : l), typ, val: typeof val == 'number' ? reduceNumber(val) : val };
1031
+ }
1032
+ /**
1033
+ * convert BinaryExpression into an array
1034
+ * @param token
1035
+ */
1036
+ function inlineExpression(token) {
1037
+ const result = [];
1038
+ if (token.typ == exports.EnumToken.ParensTokenType && token.chi.length == 1) {
1039
+ result.push(token.chi[0]);
1040
+ }
1041
+ else if (token.typ == exports.EnumToken.BinaryExpressionTokenType) {
1042
+ if ([exports.EnumToken.Mul, exports.EnumToken.Div].includes(token.op)) {
1043
+ result.push(token);
1044
+ }
1045
+ else {
1046
+ result.push(...inlineExpression(token.l), { typ: token.op }, ...inlineExpression(token.r));
1047
+ }
1048
+ }
1049
+ else {
1050
+ result.push(token);
1051
+ }
1052
+ return result;
1053
+ }
1054
+ /**
1055
+ * evaluate expression
1056
+ * @param token
1057
+ */
1058
+ function evaluateExpression(token) {
1059
+ if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
1060
+ return token;
1061
+ }
1062
+ if (token.r.typ == exports.EnumToken.BinaryExpressionTokenType) {
1063
+ token.r = evaluateExpression(token.r);
1064
+ }
1065
+ if (token.l.typ == exports.EnumToken.BinaryExpressionTokenType) {
1066
+ token.l = evaluateExpression(token.l);
1067
+ }
1068
+ return doEvaluate(token.l, token.r, token.op);
1069
+ }
1070
+ function isScalarToken(token) {
1071
+ return 'unit' in token || [exports.EnumToken.NumberTokenType, exports.EnumToken.FractionTokenType, exports.EnumToken.PercentageTokenType].includes(token.typ);
1072
+ }
1073
+ /**
1074
+ *
1075
+ * generate binary expression tree
1076
+ * @param tokens
1077
+ */
1078
+ function buildExpression(tokens) {
1079
+ return factor(factor(tokens.filter(t => t.typ != exports.EnumToken.WhitespaceTokenType), ['/', '*']), ['+', '-'])[0];
1080
+ }
1081
+ function getArithmeticOperation(op) {
1082
+ if (op == '+') {
1083
+ return exports.EnumToken.Add;
1084
+ }
1085
+ if (op == '-') {
1086
+ return exports.EnumToken.Sub;
1087
+ }
1088
+ if (op == '/') {
1089
+ return exports.EnumToken.Div;
1090
+ }
1091
+ return exports.EnumToken.Mul;
1092
+ }
1093
+ /**
1094
+ *
1095
+ * generate binary expression tree
1096
+ * @param token
1097
+ */
1098
+ function factorToken(token) {
1099
+ if (token.typ == exports.EnumToken.ParensTokenType || (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc')) {
1100
+ if (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc') {
1101
+ token = { ...token, typ: exports.EnumToken.ParensTokenType };
1102
+ // @ts-ignore
1103
+ delete token.val;
1104
+ }
1105
+ return buildExpression(token.chi);
1106
+ }
1107
+ return token;
1108
+ }
1109
+ /**
1110
+ * generate binary expression tree
1111
+ * @param tokens
1112
+ * @param ops
1113
+ */
1114
+ function factor(tokens, ops) {
1115
+ let isOp;
1116
+ const opList = ops.map(x => getArithmeticOperation(x));
1117
+ if (tokens.length == 1) {
1118
+ return [factorToken(tokens[0])];
1119
+ }
1120
+ for (let i = 0; i < tokens.length; i++) {
1121
+ isOp = opList.includes(tokens[i].typ);
1122
+ if (isOp ||
1123
+ // @ts-ignore
1124
+ (tokens[i].typ == exports.EnumToken.LiteralTokenType && ops.includes(tokens[i].val))) {
1125
+ tokens.splice(i - 1, 3, {
1126
+ typ: exports.EnumToken.BinaryExpressionTokenType,
1127
+ op: isOp ? tokens[i].typ : getArithmeticOperation(tokens[i].val),
1128
+ l: factorToken(tokens[i - 1]),
1129
+ r: factorToken(tokens[i + 1])
1130
+ });
1131
+ i--;
1132
+ }
1133
+ }
1134
+ return tokens;
1135
+ }
1136
+
1137
+ function parseRelativeColor(relativeKeys, original, rExp, gExp, bExp, aExp) {
1138
+ const type = relativeKeys.join('');
1139
+ let r;
1140
+ let g;
1141
+ let b;
1142
+ let alpha = null;
1143
+ let keys = {};
1144
+ let values = {};
1145
+ let children;
1146
+ switch (original.kin) {
1147
+ case 'lit':
1148
+ case 'hex':
1149
+ let value = original.val.toLowerCase();
1150
+ if (original.kin == 'lit') {
1151
+ if (original.val.toLowerCase() in COLORS_NAMES) {
1152
+ value = COLORS_NAMES[original.val.toLowerCase()];
1153
+ }
1154
+ else {
1155
+ return null;
1156
+ }
1157
+ }
1158
+ if (value.length == 4) {
1159
+ value = '#' + value[1] + value[1] + value[2] + value[2] + value[3] + value[3];
1160
+ }
1161
+ else if (value.length == 5) {
1162
+ value = '#' + value[1] + value[1] + value[2] + value[2] + value[3] + value[3] + value[4] + value[4];
1163
+ }
1164
+ r = parseInt(value.slice(1, 3), 16);
1165
+ g = parseInt(value.slice(3, 5), 16);
1166
+ b = parseInt(value.slice(5, 7), 16);
1167
+ alpha = value.length == 9 ? parseInt(value.slice(7, 9), 16) : null;
1168
+ break;
1169
+ case 'rgb':
1170
+ case 'rgba':
1171
+ children = original.chi.filter((t) => t.typ == exports.EnumToken.NumberTokenType || t.typ == exports.EnumToken.IdenTokenType || t.typ == exports.EnumToken.PercentageTokenType);
1172
+ if (children.every((t) => (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') || t.typ == exports.EnumToken.NumberTokenType)) {
1173
+ r = children[0].typ == exports.EnumToken.IdenTokenType && children[0].val == 'none' ? 0 : +children[0].val;
1174
+ g = children[1].typ == exports.EnumToken.IdenTokenType && children[1].val == 'none' ? 0 : +children[1].val;
1175
+ b = children[2].typ == exports.EnumToken.IdenTokenType && children[2].val == 'none' ? 0 : +children[2].val;
1176
+ alpha = children.length < 4 ? null : children[3].typ == exports.EnumToken.IdenTokenType && children[3].val == 'none' ? 0 : +children[3].val;
1177
+ }
1178
+ else if (children.every((t) => t.typ == exports.EnumToken.PercentageTokenType || (t.typ == exports.EnumToken.IdenTokenType && t.val == 'none') || (t.typ == exports.EnumToken.NumberTokenType && t.val == '0'))) {
1179
+ // @ts-ignore
1180
+ r = children[0].typ == exports.EnumToken.IdenTokenType && children[0].val == 'none' ? 0 : children[0].val * 255 / 100;
1181
+ // @ts-ignore
1182
+ g = children[1].typ == exports.EnumToken.IdenTokenType && children[1].val == 'none' ? 0 : children[1].val * 255 / 100;
1183
+ // @ts-ignore
1184
+ b = children[2].typ == exports.EnumToken.IdenTokenType && children[2].val == 'none' ? 0 : children[2].val * 255 / 100;
1185
+ alpha = children.length < 4 ? null : children[3].typ == exports.EnumToken.IdenTokenType && children[3].val == 'none' ? 0 : +children[3].val / 100;
1186
+ }
1187
+ else {
1188
+ return null;
1189
+ }
1190
+ break;
1191
+ case 'hsl':
1192
+ case 'hsla':
1193
+ case 'hwb':
1194
+ children = original.chi.filter((t) => t.typ == exports.EnumToken.AngleTokenType || t.typ == exports.EnumToken.NumberTokenType || t.typ == exports.EnumToken.IdenTokenType || t.typ == exports.EnumToken.PercentageTokenType);
1195
+ if (children.length == 3 || children.length == 4) {
1196
+ [r, g, b, alpha] = children;
1197
+ }
1198
+ else {
1199
+ return null;
1200
+ }
1201
+ break;
1202
+ default:
1203
+ return null;
1204
+ }
1205
+ const from = ['rgb', 'rgba', 'hex', 'lit'].includes(original.kin) ? 'rgb' : original.kin;
1206
+ if (from != type) {
1207
+ if (type == 'hsl' || type == 'hwb') {
1208
+ if (from == 'rgb') {
1209
+ [r, g, b] = (type == 'hwb' ? rgb2hwb : rgb2hsl)(r, g, b);
1210
+ // @ts-ignore
1211
+ r *= 360;
1212
+ // @ts-ignore
1213
+ g *= 100;
1214
+ // @ts-ignore
1215
+ b *= 100;
1216
+ values = {
1217
+ [relativeKeys[0]]: { typ: exports.EnumToken.AngleTokenType, val: r, unit: 'deg' },
1218
+ [relativeKeys[1]]: { typ: exports.EnumToken.PercentageTokenType, val: g },
1219
+ [relativeKeys[2]]: { typ: exports.EnumToken.PercentageTokenType, val: b }
1220
+ };
1221
+ }
1222
+ else if (from == 'hwb' || from == 'hsl') {
1223
+ if (type == 'hsl') {
1224
+ if (from == 'hwb') {
1225
+ [r, g, b] = hwb2hsl(getAngle(r), getNumber(g), getNumber(b));
1226
+ // @ts-ignore
1227
+ r *= 360;
1228
+ // @ts-ignore
1229
+ g *= 100;
1230
+ // @ts-ignore
1231
+ b *= 100;
1232
+ // @ts-ignore
1233
+ values = {
1234
+ [relativeKeys[0]]: { typ: exports.EnumToken.AngleTokenType, val: r, unit: 'deg' },
1235
+ [relativeKeys[1]]: { typ: exports.EnumToken.PercentageTokenType, val: g },
1236
+ [relativeKeys[2]]: { typ: exports.EnumToken.PercentageTokenType, val: b }
1237
+ };
1238
+ }
1239
+ }
1240
+ else if (type == 'hwb') {
1241
+ if (from == 'hsl') {
1242
+ [r, g, b] = hsl2hwb(getAngle(r), getNumber(g), getNumber(b));
1243
+ // @ts-ignore
1244
+ r *= 360;
1245
+ // @ts-ignore
1246
+ g *= 100;
1247
+ // @ts-ignore
1248
+ b *= 100;
1249
+ // @ts-ignore
1250
+ values = {
1251
+ [relativeKeys[0]]: { typ: exports.EnumToken.AngleTokenType, val: r, unit: 'deg' },
1252
+ [relativeKeys[1]]: { typ: exports.EnumToken.PercentageTokenType, val: g },
1253
+ [relativeKeys[2]]: { typ: exports.EnumToken.PercentageTokenType, val: b }
1254
+ };
1255
+ }
1256
+ }
1257
+ }
1258
+ else {
1259
+ return null;
1260
+ }
1261
+ }
1262
+ else if (type == 'rgb') {
1263
+ if (from == 'hsl' || from == 'hwb') {
1264
+ [r, g, b] = (from == 'hwb' ? hwb2rgb : hsl2rgb)(getAngle(r), getNumber(g), getNumber(b));
1265
+ // @ts-ignore
1266
+ values = {
1267
+ [relativeKeys[0]]: { typ: exports.EnumToken.NumberTokenType, val: r },
1268
+ [relativeKeys[1]]: { typ: exports.EnumToken.NumberTokenType, val: g },
1269
+ [relativeKeys[2]]: { typ: exports.EnumToken.NumberTokenType, val: b }
1270
+ };
1271
+ }
1272
+ else {
1273
+ return null;
1274
+ }
1275
+ }
1276
+ }
1277
+ else {
1278
+ values = {
1279
+ [relativeKeys[0]]: r,
1280
+ [relativeKeys[1]]: g,
1281
+ [relativeKeys[2]]: b
1282
+ };
1283
+ }
1284
+ if (aExp != null && aExp.typ == exports.EnumToken.IdenTokenType && aExp.val == 'none') {
1285
+ aExp = null;
1286
+ }
1287
+ keys = {
1288
+ [relativeKeys[0]]: rExp,
1289
+ [relativeKeys[1]]: gExp,
1290
+ [relativeKeys[2]]: bExp,
1291
+ alpha: aExp ?? { typ: exports.EnumToken.IdenTokenType, val: 'alpha' }
1292
+ };
1293
+ // @ts-ignore
1294
+ values.alpha = alpha != null && typeof alpha == 'object' ? alpha : b.typ == exports.EnumToken.PercentageTokenType ? { typ: exports.EnumToken.PercentageTokenType, val: String(alpha ?? 100) } : { typ: exports.EnumToken.NumberTokenType, val: String(alpha ?? 1) };
1295
+ return computeComponentValue(keys, values);
1296
+ }
1297
+ function computeComponentValue(expr, values) {
1298
+ for (const [key, exp] of Object.entries(expr)) {
1299
+ if (exp == null) {
1300
+ if (key in values) {
1301
+ if (typeof values[key] == 'number') {
1302
+ expr[key] = {
1303
+ typ: exports.EnumToken.NumberTokenType,
1304
+ val: reduceNumber(values[key])
1305
+ };
1306
+ }
1307
+ else {
1308
+ expr[key] = values[key];
1309
+ }
1310
+ }
1311
+ }
1312
+ else if ([exports.EnumToken.NumberTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.LengthTokenType].includes(exp.typ)) ;
1313
+ else if (exp.typ == exports.EnumToken.IdenTokenType && exp.val in values) {
1314
+ if (typeof values[exp.val] == 'number') {
1315
+ expr[key] = {
1316
+ typ: exports.EnumToken.NumberTokenType,
1317
+ val: reduceNumber(values[exp.val])
1318
+ };
1319
+ }
1320
+ else {
1321
+ expr[key] = values[exp.val];
1322
+ }
1323
+ }
1324
+ else if (exp.typ == exports.EnumToken.FunctionTokenType && exp.val == 'calc') {
1325
+ for (let { value, parent } of walkValues(exp.chi)) {
1326
+ if (value.typ == exports.EnumToken.IdenTokenType) {
1327
+ if (!(value.val in values)) {
1328
+ return null;
1329
+ }
1330
+ if (parent == null) {
1331
+ parent = exp;
1332
+ }
1333
+ if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
1334
+ if (parent.l == value) {
1335
+ parent.l = values[value.val];
1336
+ }
1337
+ else {
1338
+ parent.r = values[value.val];
1339
+ }
1340
+ }
1341
+ else {
1342
+ for (let i = 0; i < parent.chi.length; i++) {
1343
+ if (parent.chi[i] == value) {
1344
+ parent.chi.splice(i, 1, values[value.val]);
1345
+ break;
1346
+ }
1347
+ }
1348
+ }
1349
+ }
1350
+ }
1351
+ const result = evaluate(exp.chi);
1352
+ if (result.length == 1 && result[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
1353
+ expr[key] = result[0];
1354
+ }
1355
+ else {
1356
+ return null;
1357
+ }
1358
+ }
1359
+ }
1360
+ return expr;
1361
+ }
1362
+
1363
+ const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk'];
1364
+ function reduceNumber(val) {
1365
+ val = String(+val);
1366
+ if (val === '0') {
1367
+ return '0';
1368
+ }
1369
+ const chr = val.charAt(0);
1370
+ if (chr == '-') {
1371
+ const slice = val.slice(0, 2);
1372
+ if (slice == '-0') {
1373
+ return val.length == 2 ? '0' : '-' + val.slice(2);
1374
+ }
1375
+ }
1376
+ if (chr == '0') {
1377
+ return val.slice(1);
1378
+ }
1379
+ return val;
1380
+ }
1381
+ function update(position, str) {
1382
+ let i = 0;
1383
+ for (; i < str.length; i++) {
1384
+ if (isNewLine(str[i].charCodeAt(0))) {
1385
+ position.lin++;
1386
+ position.col = 0;
1387
+ }
1388
+ else {
1389
+ position.col++;
716
1390
  }
717
1391
  }
718
1392
  }
@@ -727,7 +1401,7 @@ function doRender(data, options = {}) {
727
1401
  newLine: '\n',
728
1402
  compress: false,
729
1403
  removeComments: false,
730
- }), sourcemap: false, colorConvert: true, expandNestingRules: false, preserveLicense: false, ...options
1404
+ }), sourcemap: false, convertColor: true, expandNestingRules: false, preserveLicense: false, ...options
731
1405
  };
732
1406
  const startTime = performance.now();
733
1407
  const errors = [];
@@ -879,6 +1553,19 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
879
1553
  return acc + renderToken(curr, options, cache, reducer, errors);
880
1554
  };
881
1555
  }
1556
+ if (token.typ == exports.EnumToken.FunctionTokenType && colorsFunc.includes(token.val)) {
1557
+ if (isColor(token)) {
1558
+ // @ts-ignore
1559
+ token.typ = exports.EnumToken.ColorTokenType;
1560
+ if (token.chi[0].typ == exports.EnumToken.IdenTokenType && token.chi[0].val == 'from') {
1561
+ // @ts-ignore
1562
+ token.cal = 'rel';
1563
+ }
1564
+ else {
1565
+ token.chi = token.chi.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
1566
+ }
1567
+ }
1568
+ }
882
1569
  switch (token.typ) {
883
1570
  case exports.EnumToken.ListToken:
884
1571
  return token.chi.reduce((acc, curr) => acc + renderToken(curr, options, cache), '');
@@ -921,10 +1608,46 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
921
1608
  case exports.EnumToken.Div:
922
1609
  return '/';
923
1610
  case exports.EnumToken.ColorTokenType:
924
- if (options.colorConvert) {
925
- if (token.kin == 'lit' && token.val.toLowerCase() == 'currentcolor') {
1611
+ if (options.convertColor) {
1612
+ if (token.cal == 'rel' && ['rgb', 'hsl', 'hwb'].includes(token.val)) {
1613
+ const chi = token.chi.filter(x => ![
1614
+ exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType
1615
+ ].includes(x.typ));
1616
+ const components = parseRelativeColor(token.val.split(''), chi[1], chi[2], chi[3], chi[4], chi[5]);
1617
+ if (components != null) {
1618
+ token.chi = Object.values(components);
1619
+ delete token.cal;
1620
+ }
1621
+ }
1622
+ if (token.cal) {
1623
+ let slice = false;
1624
+ if (token.cal == 'rel') {
1625
+ const last = token.chi.at(-1);
1626
+ if ((last.typ == exports.EnumToken.NumberTokenType && last.val == '1') || (last.typ == exports.EnumToken.IdenTokenType && last.val == 'none')) {
1627
+ const prev = token.chi.at(-2);
1628
+ if (prev.typ == exports.EnumToken.LiteralTokenType && prev.val == '/') {
1629
+ slice = true;
1630
+ }
1631
+ }
1632
+ }
1633
+ return clamp(token).val + '(' + (slice ? token.chi.slice(0, -2) : token.chi).reduce((acc, curr) => {
1634
+ const val = renderToken(curr, options, cache);
1635
+ if ([exports.EnumToken.LiteralTokenType, exports.EnumToken.CommaTokenType].includes(curr.typ)) {
1636
+ return acc + val;
1637
+ }
1638
+ if (acc.length > 0) {
1639
+ return acc + (['/', ','].includes(acc.at(-1)) ? '' : ' ') + val;
1640
+ }
1641
+ return val;
1642
+ }, '') + ')';
1643
+ }
1644
+ if (token.kin == 'lit' && token.val.localeCompare('currentcolor', undefined, { sensitivity: 'base' }) == 0) {
926
1645
  return 'currentcolor';
927
1646
  }
1647
+ clamp(token);
1648
+ if (Array.isArray(token.chi) && token.chi.some((t) => t.typ == exports.EnumToken.FunctionTokenType || (t.typ == exports.EnumToken.ColorTokenType && Array.isArray(t.chi)))) {
1649
+ return (token.val.endsWith('a') ? token.val.slice(0, -1) : token.val) + '(' + token.chi.reduce((acc, curr) => acc + (acc.length > 0 && !(acc.endsWith('/') || curr.typ == exports.EnumToken.LiteralTokenType) ? ' ' : '') + renderToken(curr, options, cache), '') + ')';
1650
+ }
928
1651
  let value = token.kin == 'hex' ? token.val.toLowerCase() : (token.kin == 'lit' ? COLORS_NAMES[token.val.toLowerCase()] : '');
929
1652
  if (token.val == 'rgb' || token.val == 'rgba') {
930
1653
  value = rgb2Hex(token);
@@ -961,13 +1684,17 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
961
1684
  if (token.kin == 'hex' || token.kin == 'lit') {
962
1685
  return token.val;
963
1686
  }
1687
+ if (Array.isArray(token.chi)) {
1688
+ return (token.val.endsWith('a') ? token.val.slice(0, -1) : token.val) + '(' + token.chi.reduce((acc, curr) => acc + (acc.length > 0 && !(acc.endsWith('/') || curr.typ == exports.EnumToken.LiteralTokenType) ? ' ' : '') + renderToken(curr, options, cache), '') + ')';
1689
+ }
964
1690
  case exports.EnumToken.ParensTokenType:
965
1691
  case exports.EnumToken.FunctionTokenType:
966
1692
  case exports.EnumToken.UrlFunctionTokenType:
967
1693
  case exports.EnumToken.ImageFunctionTokenType:
968
- case exports.EnumToken.PseudoClassFuncTokenType:
969
1694
  case exports.EnumToken.TimingFunctionTokenType:
1695
+ case exports.EnumToken.PseudoClassFuncTokenType:
970
1696
  case exports.EnumToken.TimelineFunctionTokenType:
1697
+ case exports.EnumToken.GridTemplateFuncTokenType:
971
1698
  if (token.typ == exports.EnumToken.FunctionTokenType &&
972
1699
  token.val == 'calc' &&
973
1700
  token.chi.length == 1 &&
@@ -1030,6 +1757,7 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
1030
1757
  case exports.EnumToken.ImportantTokenType:
1031
1758
  return '!important';
1032
1759
  case exports.EnumToken.AttrTokenType:
1760
+ case exports.EnumToken.IdenListTokenType:
1033
1761
  return '[' + token.chi.reduce(reducer, '') + ']';
1034
1762
  case exports.EnumToken.TimeTokenType:
1035
1763
  case exports.EnumToken.AngleTokenType:
@@ -1096,10 +1824,23 @@ function renderToken(token, options = {}, cache = Object.create(null), reducer,
1096
1824
  }
1097
1825
  return '0';
1098
1826
  }
1827
+ if (token.typ == exports.EnumToken.TimeTokenType) {
1828
+ if (unit == 'ms') {
1829
+ // @ts-ignore
1830
+ const v = reduceNumber(val / 1000);
1831
+ if (v.length + 1 <= val.length) {
1832
+ return v + 's';
1833
+ }
1834
+ return val + 'ms';
1835
+ }
1836
+ return val + 's';
1837
+ }
1099
1838
  return val.includes('/') ? val.replace('/', unit + '/') : val + unit;
1839
+ case exports.EnumToken.FlexTokenType:
1100
1840
  case exports.EnumToken.PercentageTokenType:
1841
+ const uni = token.typ == exports.EnumToken.PercentageTokenType ? '%' : 'fr';
1101
1842
  const perc = token.val.typ == exports.EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
1102
- return options.minify && perc == '0' ? '0' : (perc.includes('/') ? perc.replace('/', '%/') : perc + '%');
1843
+ return options.minify && perc == '0' ? '0' : (perc.includes('/') ? perc.replace('/', uni + '/') : perc + uni);
1103
1844
  case exports.EnumToken.NumberTokenType:
1104
1845
  return token.val.typ == exports.EnumToken.FractionTokenType ? renderToken(token.val, options, cache) : reduceNumber(token.val);
1105
1846
  case exports.EnumToken.CommentTokenType:
@@ -1180,10 +1921,37 @@ function isColor(token) {
1180
1921
  // named color
1181
1922
  return token.val.toLowerCase() in COLORS_NAMES;
1182
1923
  }
1924
+ let isLegacySyntax = false;
1183
1925
  if (token.typ == exports.EnumToken.FunctionTokenType && token.chi.length > 0 && colorsFunc.includes(token.val)) {
1926
+ const keywords = ['from', 'none'];
1927
+ if (['rgb', 'hsl', 'hwb'].includes(token.val)) {
1928
+ keywords.push('a', ...token.val.split(''));
1929
+ }
1930
+ // console.debug(JSON.stringify({token}, null, 1));
1184
1931
  // @ts-ignore
1185
1932
  for (const v of token.chi) {
1186
- if (![exports.EnumToken.NumberTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.LiteralTokenType].includes(v.typ)) {
1933
+ // console.debug(JSON.stringify({v}, null, 1));
1934
+ if (v.typ == exports.EnumToken.CommaTokenType) {
1935
+ isLegacySyntax = true;
1936
+ }
1937
+ if (v.typ == exports.EnumToken.IdenTokenType) {
1938
+ if (!(keywords.includes(v.val) || v.val.toLowerCase() in COLORS_NAMES)) {
1939
+ return false;
1940
+ }
1941
+ if (keywords.includes(v.val)) {
1942
+ if (isLegacySyntax) {
1943
+ return false;
1944
+ }
1945
+ if (v.val == 'from' && ['rgba', 'hsla'].includes(token.val)) {
1946
+ return false;
1947
+ }
1948
+ }
1949
+ continue;
1950
+ }
1951
+ if (v.typ == exports.EnumToken.FunctionTokenType && (v.val == 'calc' || colorsFunc.includes(v.val))) {
1952
+ continue;
1953
+ }
1954
+ if (![exports.EnumToken.ColorTokenType, exports.EnumToken.IdenTokenType, exports.EnumToken.NumberTokenType, exports.EnumToken.AngleTokenType, exports.EnumToken.PercentageTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.LiteralTokenType].includes(v.typ)) {
1187
1955
  return false;
1188
1956
  }
1189
1957
  }
@@ -1343,6 +2111,9 @@ function isDimension(name) {
1343
2111
  function isPercentage(name) {
1344
2112
  return name.endsWith('%') && isNumber(name.slice(0, -1));
1345
2113
  }
2114
+ function isFlex(name) {
2115
+ return name.endsWith('fr') && isNumber(name.slice(0, -2));
2116
+ }
1346
2117
  function parseDimension(name) {
1347
2118
  let index = name.length;
1348
2119
  while (index--) {
@@ -1411,6 +2182,28 @@ function isWhiteSpace(codepoint) {
1411
2182
  }
1412
2183
 
1413
2184
  var properties = {
2185
+ gap: {
2186
+ shorthand: "gap",
2187
+ properties: [
2188
+ "row-gap",
2189
+ "column-gap"
2190
+ ],
2191
+ types: [
2192
+ "Length",
2193
+ "Perc"
2194
+ ],
2195
+ multiple: false,
2196
+ separator: null,
2197
+ keywords: [
2198
+ "normal"
2199
+ ]
2200
+ },
2201
+ "row-gap": {
2202
+ shorthand: "gap"
2203
+ },
2204
+ "column-gap": {
2205
+ shorthand: "gap"
2206
+ },
1414
2207
  inset: {
1415
2208
  shorthand: "inset",
1416
2209
  properties: [
@@ -1630,20 +2423,215 @@ var properties = {
1630
2423
  map: "border",
1631
2424
  shorthand: "border-color"
1632
2425
  },
1633
- "border-right-color": {
1634
- map: "border",
1635
- shorthand: "border-color"
2426
+ "border-right-color": {
2427
+ map: "border",
2428
+ shorthand: "border-color"
2429
+ },
2430
+ "border-bottom-color": {
2431
+ map: "border",
2432
+ shorthand: "border-color"
2433
+ },
2434
+ "border-left-color": {
2435
+ map: "border",
2436
+ shorthand: "border-color"
2437
+ }
2438
+ };
2439
+ var map = {
2440
+ "flex-flow": {
2441
+ shorthand: "flex-flow",
2442
+ pattern: "flex-direction flex-wrap",
2443
+ keywords: [
2444
+ ],
2445
+ "default": [
2446
+ "row",
2447
+ "nowrap"
2448
+ ],
2449
+ properties: {
2450
+ "flex-direction": {
2451
+ keywords: [
2452
+ "row",
2453
+ "row-reverse",
2454
+ "column",
2455
+ "column-reverse"
2456
+ ],
2457
+ "default": [
2458
+ "row"
2459
+ ],
2460
+ types: [
2461
+ ]
2462
+ },
2463
+ "flex-wrap": {
2464
+ keywords: [
2465
+ "wrap",
2466
+ "nowrap",
2467
+ "wrap-reverse"
2468
+ ],
2469
+ "default": [
2470
+ "nowrap"
2471
+ ],
2472
+ types: [
2473
+ ]
2474
+ }
2475
+ }
2476
+ },
2477
+ "flex-direction": {
2478
+ shorthand: "flex-flow"
2479
+ },
2480
+ "flex-wrap": {
2481
+ shorthand: "flex-flow"
2482
+ },
2483
+ container: {
2484
+ shorthand: "container",
2485
+ pattern: "container-name container-type",
2486
+ keywords: [
2487
+ ],
2488
+ "default": [
2489
+ ],
2490
+ properties: {
2491
+ "container-name": {
2492
+ required: true,
2493
+ multiple: true,
2494
+ keywords: [
2495
+ "none"
2496
+ ],
2497
+ "default": [
2498
+ "none"
2499
+ ],
2500
+ types: [
2501
+ "Iden",
2502
+ "DashedIden"
2503
+ ]
2504
+ },
2505
+ "container-type": {
2506
+ previous: "container-name",
2507
+ prefix: {
2508
+ typ: "Literal",
2509
+ val: "/"
2510
+ },
2511
+ keywords: [
2512
+ "size",
2513
+ "inline-size",
2514
+ "normal"
2515
+ ],
2516
+ "default": [
2517
+ "normal"
2518
+ ],
2519
+ types: [
2520
+ ]
2521
+ }
2522
+ }
2523
+ },
2524
+ "container-name": {
2525
+ shorthand: "container"
2526
+ },
2527
+ "container-type": {
2528
+ shorthand: "container"
2529
+ },
2530
+ flex: {
2531
+ shorthand: "flex",
2532
+ pattern: "flex-grow flex-shrink flex-basis",
2533
+ keywords: [
2534
+ "auto",
2535
+ "none",
2536
+ "initial"
2537
+ ],
2538
+ "default": [
2539
+ "0",
2540
+ "0 1",
2541
+ "0 auto",
2542
+ "0 1 auto"
2543
+ ],
2544
+ properties: {
2545
+ "flex-grow": {
2546
+ required: true,
2547
+ keywords: [
2548
+ ],
2549
+ "default": [
2550
+ "0"
2551
+ ],
2552
+ types: [
2553
+ "Number"
2554
+ ]
2555
+ },
2556
+ "flex-shrink": {
2557
+ keywords: [
2558
+ ],
2559
+ "default": [
2560
+ "1"
2561
+ ],
2562
+ types: [
2563
+ "Number"
2564
+ ]
2565
+ },
2566
+ "flex-basis": {
2567
+ keywords: [
2568
+ "max-content",
2569
+ "min-content",
2570
+ "fit-content",
2571
+ "fit-content",
2572
+ "content",
2573
+ "auto"
2574
+ ],
2575
+ "default": [
2576
+ "auto"
2577
+ ],
2578
+ types: [
2579
+ "Length",
2580
+ "Perc"
2581
+ ]
2582
+ }
2583
+ }
2584
+ },
2585
+ "flex-grow": {
2586
+ shorthand: "flex"
2587
+ },
2588
+ "flex-shrink": {
2589
+ shorthand: "flex"
2590
+ },
2591
+ "flex-basis": {
2592
+ shorthand: "flex"
2593
+ },
2594
+ columns: {
2595
+ shorthand: "columns",
2596
+ pattern: "column-count column-width",
2597
+ keywords: [
2598
+ "auto"
2599
+ ],
2600
+ "default": [
2601
+ "auto",
2602
+ "auto auto"
2603
+ ],
2604
+ properties: {
2605
+ "column-count": {
2606
+ keywords: [
2607
+ "auto"
2608
+ ],
2609
+ "default": [
2610
+ "auto"
2611
+ ],
2612
+ types: [
2613
+ "Number"
2614
+ ]
2615
+ },
2616
+ "column-width": {
2617
+ keywords: [
2618
+ "auto"
2619
+ ],
2620
+ "default": [
2621
+ "auto"
2622
+ ],
2623
+ types: [
2624
+ "Length"
2625
+ ]
2626
+ }
2627
+ }
2628
+ },
2629
+ "column-count": {
2630
+ shorthand: "columns"
1636
2631
  },
1637
- "border-bottom-color": {
1638
- map: "border",
1639
- shorthand: "border-color"
2632
+ "column-width": {
2633
+ shorthand: "columns"
1640
2634
  },
1641
- "border-left-color": {
1642
- map: "border",
1643
- shorthand: "border-color"
1644
- }
1645
- };
1646
- var map = {
1647
2635
  transition: {
1648
2636
  shorthand: "transition",
1649
2637
  multiple: true,
@@ -1661,6 +2649,13 @@ var map = {
1661
2649
  "none",
1662
2650
  "normal"
1663
2651
  ],
2652
+ mapping: {
2653
+ "cubic-bezier(.25,.1,.25,1)": "ease",
2654
+ "cubic-bezier(0,0,1,1)": "linear",
2655
+ "cubic-bezier(.42,0,1,1)": "ease-in",
2656
+ "cubic-bezier(0,0,.58,1)": "ease-out",
2657
+ "cubic-bezier(.42,0,.58,.42)": "ease-in-out"
2658
+ },
1664
2659
  properties: {
1665
2660
  "transition-property": {
1666
2661
  keywords: [
@@ -1668,6 +2663,7 @@ var map = {
1668
2663
  "all"
1669
2664
  ],
1670
2665
  "default": [
2666
+ "all"
1671
2667
  ],
1672
2668
  types: [
1673
2669
  "Iden"
@@ -2667,6 +3663,64 @@ function matchType(val, properties) {
2667
3663
  return false;
2668
3664
  }
2669
3665
 
3666
+ function parseDeclaration(node, errors, src, position) {
3667
+ while (node.val[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
3668
+ node.val.shift();
3669
+ }
3670
+ if (node.val.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ)).length == 0) {
3671
+ errors.push({
3672
+ action: 'drop',
3673
+ message: 'doParse: invalid declaration',
3674
+ location: { src, ...position }
3675
+ });
3676
+ return null;
3677
+ }
3678
+ for (const { value: val, parent } of walkValues(node.val, node)) {
3679
+ if (val.typ == exports.EnumToken.AttrTokenType && val.chi.every((t) => [exports.EnumToken.IdenTokenType, exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(t.typ))) {
3680
+ // @ts-ignore
3681
+ val.typ = exports.EnumToken.IdenListTokenType;
3682
+ }
3683
+ else if (val.typ == exports.EnumToken.StringTokenType && (node.nam == 'grid' || node.nam == 'grid-template-areas' || node.nam == 'grid-template-rows' || node.nam == 'grid-template-columns')) {
3684
+ val.val = val.val.at(0) + parseGridTemplate(val.val.slice(1, -1)) + val.val.at(-1);
3685
+ // @ts-ignore
3686
+ const array = parent?.chi ?? node.val;
3687
+ const index = array.indexOf(val);
3688
+ if (index > 0 && array[index - 1].typ == exports.EnumToken.WhitespaceTokenType) {
3689
+ array.splice(index - 1, 1);
3690
+ }
3691
+ }
3692
+ }
3693
+ return node;
3694
+ }
3695
+ function parseGridTemplate(template) {
3696
+ let result = '';
3697
+ let buffer = '';
3698
+ for (let i = 0; i < template.length; i++) {
3699
+ const char = template[i];
3700
+ if (isWhiteSpace(char.codePointAt(0))) {
3701
+ while (i + 1 < template.length && isWhiteSpace(template[i + 1].codePointAt(0))) {
3702
+ i++;
3703
+ }
3704
+ result += buffer + ' ';
3705
+ buffer = '';
3706
+ }
3707
+ else if (char == '.') {
3708
+ while (i + 1 < template.length && template[i + 1] == '.') {
3709
+ i++;
3710
+ }
3711
+ if (isWhiteSpace((result.at(-1)?.codePointAt(0)))) {
3712
+ result = result.slice(0, -1);
3713
+ }
3714
+ result += buffer + char;
3715
+ buffer = '';
3716
+ }
3717
+ else {
3718
+ buffer += char;
3719
+ }
3720
+ }
3721
+ return buffer.length > 0 ? result + buffer : result;
3722
+ }
3723
+
2670
3724
  function* tokenize(stream) {
2671
3725
  let ind = -1;
2672
3726
  let lin = 1;
@@ -3197,16 +4251,6 @@ function* tokenize(stream) {
3197
4251
 
3198
4252
  const urlTokenMatcher = /^(["']?)[a-zA-Z0-9_/.-][a-zA-Z0-9_/:.#?-]+(\1)$/;
3199
4253
  const trimWhiteSpace = [exports.EnumToken.CommentTokenType, exports.EnumToken.GtTokenType, exports.EnumToken.GteTokenType, exports.EnumToken.LtTokenType, exports.EnumToken.LteTokenType, exports.EnumToken.ColumnCombinatorTokenType];
3200
- const funcLike = [
3201
- exports.EnumToken.ParensTokenType,
3202
- exports.EnumToken.FunctionTokenType,
3203
- exports.EnumToken.UrlFunctionTokenType,
3204
- exports.EnumToken.StartParensTokenType,
3205
- exports.EnumToken.ImageFunctionTokenType,
3206
- exports.EnumToken.PseudoClassFuncTokenType,
3207
- exports.EnumToken.TimingFunctionTokenType,
3208
- exports.EnumToken.TimingFunctionTokenType
3209
- ];
3210
4254
  const BadTokensTypes = [
3211
4255
  exports.EnumToken.BadCommentTokenType,
3212
4256
  exports.EnumToken.BadCdoTokenType,
@@ -3225,6 +4269,7 @@ async function doParse(iterator, options = {}) {
3225
4269
  src: '',
3226
4270
  sourcemap: false,
3227
4271
  minify: true,
4272
+ parseColor: true,
3228
4273
  nestingRules: false,
3229
4274
  resolveImport: false,
3230
4275
  resolveUrls: false,
@@ -3500,7 +4545,7 @@ async function doParse(iterator, options = {}) {
3500
4545
  if (tokens[i].typ == exports.EnumToken.ColonTokenType) {
3501
4546
  name = tokens.slice(0, i);
3502
4547
  value = parseTokens(tokens.slice(i + 1), {
3503
- parseColor: true,
4548
+ parseColor: options.parseColor,
3504
4549
  src: options.src,
3505
4550
  resolveUrls: options.resolveUrls,
3506
4551
  resolve: options.resolve,
@@ -3539,19 +4584,11 @@ async function doParse(iterator, options = {}) {
3539
4584
  // @ts-ignore
3540
4585
  val: value
3541
4586
  };
3542
- while (node.val[0]?.typ == exports.EnumToken.WhitespaceTokenType) {
3543
- node.val.shift();
3544
- }
3545
- if (node.val.length == 0) {
3546
- errors.push({
3547
- action: 'drop',
3548
- message: 'doParse: invalid declaration',
3549
- location: { src, ...position }
3550
- });
3551
- return null;
4587
+ const result = parseDeclaration(node, errors, src, position);
4588
+ if (result != null) {
4589
+ // @ts-ignore
4590
+ context.chi.push(node);
3552
4591
  }
3553
- // @ts-ignore
3554
- context.chi.push(node);
3555
4592
  return null;
3556
4593
  }
3557
4594
  }
@@ -3808,15 +4845,21 @@ function getTokenType(val, hint) {
3808
4845
  val
3809
4846
  };
3810
4847
  }
3811
- if (isDimension(val)) {
3812
- return parseDimension(val);
3813
- }
3814
4848
  if (isPercentage(val)) {
3815
4849
  return {
3816
4850
  typ: exports.EnumToken.PercentageTokenType,
3817
4851
  val: val.slice(0, -1)
3818
4852
  };
3819
4853
  }
4854
+ if (isFlex(val)) {
4855
+ return {
4856
+ typ: exports.EnumToken.FlexTokenType,
4857
+ val: val.slice(0, -2)
4858
+ };
4859
+ }
4860
+ if (isDimension(val)) {
4861
+ return parseDimension(val);
4862
+ }
3820
4863
  const v = val.toLowerCase();
3821
4864
  if (v == 'currentcolor' || val == 'transparent' || v in COLORS_NAMES) {
3822
4865
  return {
@@ -3916,15 +4959,6 @@ function parseTokens(tokens, options = {}) {
3916
4959
  // @ts-ignore
3917
4960
  parseTokens(t.chi, t.typ);
3918
4961
  }
3919
- // @ts-ignore
3920
- // t.chi.forEach(val => {
3921
- // if (val.typ == EnumToken.StringTokenType) {
3922
- // const slice = val.val.slice(1, -1);
3923
- // if ((slice.charAt(0) != '-' || (slice.charAt(0) == '-' && isIdentStart(slice.charCodeAt(1)))) && isIdent(slice)) {
3924
- // Object.assign(val, {typ: EnumToken.IdenTokenType, val: slice});
3925
- // }
3926
- // }
3927
- // });
3928
4962
  let m = t.chi.length;
3929
4963
  let val;
3930
4964
  for (m = 0; m < t.chi.length; m++) {
@@ -4059,6 +5093,11 @@ function parseTokens(tokens, options = {}) {
4059
5093
  // @ts-ignore
4060
5094
  t.chi.pop();
4061
5095
  }
5096
+ // @ts-ignore
5097
+ if (t.chi.length > 0) {
5098
+ // @ts-ignore
5099
+ parseTokens(t.chi, options);
5100
+ }
4062
5101
  if (t.typ == exports.EnumToken.FunctionTokenType && t.val == 'calc') {
4063
5102
  for (const { value, parent } of walkValues(t.chi)) {
4064
5103
  if (value.typ == exports.EnumToken.WhitespaceTokenType) {
@@ -4081,35 +5120,25 @@ function parseTokens(tokens, options = {}) {
4081
5120
  }
4082
5121
  }
4083
5122
  }
5123
+ else if (t.typ == exports.EnumToken.FunctionTokenType && ['minmax', 'fit-content', 'repeat'].includes(t.val)) {
5124
+ // @ts-ignore
5125
+ t.typ = exports.EnumToken.GridTemplateFuncTokenType;
5126
+ }
4084
5127
  else if (t.typ == exports.EnumToken.StartParensTokenType) {
4085
5128
  // @ts-ignore
4086
5129
  t.typ = exports.EnumToken.ParensTokenType;
4087
5130
  }
4088
5131
  // @ts-ignore
4089
5132
  if (options.parseColor && t.typ == exports.EnumToken.FunctionTokenType && isColor(t)) {
4090
- // if (isColor) {
4091
5133
  // @ts-ignore
4092
5134
  t.typ = exports.EnumToken.ColorTokenType;
4093
5135
  // @ts-ignore
4094
5136
  t.kin = t.val;
4095
- // @ts-ignore
4096
- let m = t.chi.length;
4097
- while (m-- > 0) {
5137
+ if (t.chi[0].typ == exports.EnumToken.IdenTokenType && t.chi[0].val == 'from') {
4098
5138
  // @ts-ignore
4099
- if ([exports.EnumToken.LiteralTokenType].concat(trimWhiteSpace).includes(t.chi[m].typ)) {
4100
- // @ts-ignore
4101
- if (t.chi[m + 1]?.typ == exports.EnumToken.WhitespaceTokenType) {
4102
- // @ts-ignore
4103
- t.chi.splice(m + 1, 1);
4104
- }
4105
- // @ts-ignore
4106
- if (t.chi[m - 1]?.typ == exports.EnumToken.WhitespaceTokenType) {
4107
- // @ts-ignore
4108
- t.chi.splice(m - 1, 1);
4109
- m--;
4110
- }
4111
- }
5139
+ t.cal = 'rel';
4112
5140
  }
5141
+ t.chi = t.chi.filter((t) => ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommaTokenType, exports.EnumToken.CommentTokenType].includes(t.typ));
4113
5142
  continue;
4114
5143
  }
4115
5144
  if (t.typ == exports.EnumToken.UrlFunctionTokenType) {
@@ -4134,8 +5163,6 @@ function parseTokens(tokens, options = {}) {
4134
5163
  }
4135
5164
  // @ts-ignore
4136
5165
  if (t.chi.length > 0) {
4137
- // @ts-ignore
4138
- parseTokens(t.chi, options);
4139
5166
  if (t.typ == exports.EnumToken.PseudoClassFuncTokenType && t.val == ':is' && options.minify) {
4140
5167
  //
4141
5168
  const count = t.chi.filter(t => t.typ != exports.EnumToken.CommentTokenType).length;
@@ -4240,20 +5267,38 @@ function* walk(node, filter) {
4240
5267
  }
4241
5268
  }
4242
5269
  }
4243
- function* walkValues(values) {
5270
+ function* walkValues(values, root = null, filter) {
4244
5271
  const stack = values.slice();
4245
5272
  const weakMap = new WeakMap;
4246
5273
  let value;
4247
5274
  while (stack.length > 0) {
4248
5275
  value = stack.shift();
5276
+ let option = null;
5277
+ if (filter != null) {
5278
+ option = filter(value);
5279
+ if (option === 'ignore') {
5280
+ continue;
5281
+ }
5282
+ if (option === 'stop') {
5283
+ break;
5284
+ }
5285
+ }
4249
5286
  // @ts-ignore
4250
- yield { value, parent: weakMap.get(value) };
4251
- if ('chi' in value) {
4252
- for (const child of value.chi) {
5287
+ if (option !== 'children') {
5288
+ // @ts-ignore
5289
+ yield { value, parent: weakMap.get(value), root };
5290
+ }
5291
+ if (option !== 'ignore-children' && 'chi' in value) {
5292
+ for (const child of value.chi.slice()) {
4253
5293
  weakMap.set(child, value);
4254
5294
  }
4255
5295
  stack.unshift(...value.chi);
4256
5296
  }
5297
+ else if (value.typ == exports.EnumToken.BinaryExpressionTokenType) {
5298
+ weakMap.set(value.l, value);
5299
+ weakMap.set(value.r, value);
5300
+ stack.unshift(value.l, value.r);
5301
+ }
4257
5302
  }
4258
5303
  }
4259
5304
 
@@ -4456,58 +5501,6 @@ class IterableWeakSet {
4456
5501
  }
4457
5502
  }
4458
5503
 
4459
- class IterableWeakMap {
4460
- #map;
4461
- #set;
4462
- constructor(iterable) {
4463
- this.#map = new WeakMap;
4464
- this.#set = new Set;
4465
- if (iterable) {
4466
- for (const [key, value] of iterable) {
4467
- const ref = new WeakRef(key);
4468
- this.#set.add(ref);
4469
- this.#map.set(key, value);
4470
- }
4471
- }
4472
- }
4473
- has(key) {
4474
- return this.#map.has(key);
4475
- }
4476
- set(key, value) {
4477
- if (!this.#map.has(key)) {
4478
- this.#set.add(new WeakRef(key));
4479
- }
4480
- this.#map.set(key, value);
4481
- return this;
4482
- }
4483
- get(key) {
4484
- return this.#map.get(key);
4485
- }
4486
- delete(key) {
4487
- if (this.#map.has(key)) {
4488
- for (const ref of this.#set) {
4489
- if (ref.deref() === key) {
4490
- this.#set.delete(ref);
4491
- break;
4492
- }
4493
- }
4494
- return this.#map.delete(key);
4495
- }
4496
- return false;
4497
- }
4498
- *[Symbol.iterator]() {
4499
- for (const ref of new Set(this.#set)) {
4500
- const key = ref.deref();
4501
- if (key == null) {
4502
- this.#set.delete(ref);
4503
- continue;
4504
- }
4505
- // @ts-ignore
4506
- yield [key, this.#map.get(key)];
4507
- }
4508
- }
4509
- }
4510
-
4511
5504
  function replace(node, variableScope) {
4512
5505
  for (const { value, parent: parentValue } of walkValues(node.val)) {
4513
5506
  if (value?.typ == exports.EnumToken.FunctionTokenType && value.val == 'var') {
@@ -4531,19 +5524,19 @@ function replace(node, variableScope) {
4531
5524
  }
4532
5525
  }
4533
5526
  }
4534
- class InlineCssVariables extends MinifyFeature {
5527
+ class InlineCssVariablesFeature extends MinifyFeature {
4535
5528
  static get ordering() {
4536
5529
  return 0;
4537
5530
  }
4538
5531
  static register(options) {
4539
5532
  if (options.inlineCssVariables) {
4540
5533
  for (const feature of options.features) {
4541
- if (feature instanceof InlineCssVariables) {
5534
+ if (feature instanceof InlineCssVariablesFeature) {
4542
5535
  return;
4543
5536
  }
4544
5537
  }
4545
5538
  // @ts-ignore
4546
- options.features.push(new InlineCssVariables());
5539
+ options.features.push(new InlineCssVariablesFeature());
4547
5540
  }
4548
5541
  }
4549
5542
  run(ast, options = {}, parent, context) {
@@ -4632,6 +5625,29 @@ class InlineCssVariables extends MinifyFeature {
4632
5625
  }
4633
5626
  }
4634
5627
 
5628
+ function dedup(values) {
5629
+ for (const value of values) {
5630
+ let i = value.length;
5631
+ while (i-- > 1) {
5632
+ const t = value[i];
5633
+ const k = value[i == 1 ? 0 : i % 2];
5634
+ if (t.val == k.val && t.val == '0') {
5635
+ if ((t.typ == exports.EnumToken.NumberTokenType && isLength(k)) ||
5636
+ (k.typ == exports.EnumToken.NumberTokenType && isLength(t)) ||
5637
+ (isLength(k) || isLength(t))) {
5638
+ value.splice(i, 1);
5639
+ continue;
5640
+ }
5641
+ }
5642
+ if (eq(t, k)) {
5643
+ value.splice(i, 1);
5644
+ continue;
5645
+ }
5646
+ break;
5647
+ }
5648
+ }
5649
+ return values;
5650
+ }
4635
5651
  class PropertySet {
4636
5652
  config;
4637
5653
  declarations;
@@ -4726,7 +5742,23 @@ class PropertySet {
4726
5742
  let iterator;
4727
5743
  const declarations = this.declarations;
4728
5744
  if (declarations.size < this.config.properties.length) {
4729
- iterator = declarations.values();
5745
+ const values = [...declarations.values()];
5746
+ if (this.isShortHand()) {
5747
+ const val = values[0].val.reduce((acc, curr) => {
5748
+ if (![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.CommentTokenType].includes(curr.typ)) {
5749
+ acc.push(curr);
5750
+ }
5751
+ return acc;
5752
+ }, []);
5753
+ values[0].val = val.reduce((acc, curr) => {
5754
+ if (acc.length > 0) {
5755
+ acc.push({ typ: exports.EnumToken.WhitespaceTokenType });
5756
+ }
5757
+ acc.push(curr);
5758
+ return acc;
5759
+ }, []);
5760
+ }
5761
+ return values[Symbol.iterator]();
4730
5762
  }
4731
5763
  else {
4732
5764
  const values = [];
@@ -4744,26 +5776,7 @@ class PropertySet {
4744
5776
  index++;
4745
5777
  }
4746
5778
  });
4747
- for (const value of values) {
4748
- let i = value.length;
4749
- while (i-- > 1) {
4750
- const t = value[i];
4751
- const k = value[i == 1 ? 0 : i % 2];
4752
- if (t.val == k.val && t.val == '0') {
4753
- if ((t.typ == exports.EnumToken.NumberTokenType && isLength(k)) ||
4754
- (k.typ == exports.EnumToken.NumberTokenType && isLength(t)) ||
4755
- (isLength(k) || isLength(t))) {
4756
- value.splice(i, 1);
4757
- continue;
4758
- }
4759
- }
4760
- if (eq(t, k)) {
4761
- value.splice(i, 1);
4762
- continue;
4763
- }
4764
- break;
4765
- }
4766
- }
5779
+ dedup(values);
4767
5780
  iterator = [{
4768
5781
  typ: exports.EnumToken.DeclarationNodeType,
4769
5782
  nam: this.config.shorthand,
@@ -4800,7 +5813,6 @@ class PropertySet {
4800
5813
  }
4801
5814
  }
4802
5815
 
4803
- const cache = new IterableWeakMap();
4804
5816
  const propertiesConfig = getConfig();
4805
5817
  class PropertyMap {
4806
5818
  config;
@@ -4986,15 +5998,29 @@ class PropertyMap {
4986
5998
  }
4987
5999
  if (!isShorthand || requiredCount < this.requiredCount) {
4988
6000
  if (isShorthand && this.declarations.has(this.config.shorthand)) {
4989
- // console.debug(...this.declarations.values());
6001
+ const cache = new Map();
4990
6002
  const removeDefaults = (declaration) => {
4991
- // const dec: AstDeclaration = {...declaration};
4992
- const config = this.config.shorthand == declaration.nam ? this.config : this.config.properties[declaration.nam];
4993
- declaration.val = declaration.val.filter((val) => {
4994
- if (!cache.has(val)) {
4995
- cache.set(val, renderToken(val, { minify: true }));
6003
+ let config = this.config.shorthand == declaration.nam ? this.config : this.config.properties[declaration.nam];
6004
+ if (config == null && declaration.nam in propertiesConfig.properties) {
6005
+ // @ts-ignore
6006
+ const shorthand = propertiesConfig.properties[declaration.nam].shorthand;
6007
+ // @ts-ignore
6008
+ config = propertiesConfig.properties[shorthand];
6009
+ }
6010
+ declaration.val = declaration.val.map((t) => {
6011
+ if (!cache.has(t)) {
6012
+ cache.set(t, renderToken(t, { minify: true }));
6013
+ }
6014
+ const value = cache.get(t);
6015
+ // @ts-ignore
6016
+ if (config?.mapping?.[value] != null) {
6017
+ // @ts-ignore
6018
+ t = parseString(config.mapping[value])[0];
6019
+ cache.set(t, renderToken(t, { minify: true }));
4996
6020
  }
4997
- return !config.default.includes(cache.get(val));
6021
+ return t;
6022
+ }).filter((val) => {
6023
+ return !config?.default?.includes(cache.get(val));
4998
6024
  })
4999
6025
  .filter((val, index, array) => !(index > 0 &&
5000
6026
  val.typ == exports.EnumToken.WhitespaceTokenType &&
@@ -5013,13 +6039,24 @@ class PropertyMap {
5013
6039
  }
5014
6040
  return acc;
5015
6041
  }, []);
5016
- const filtered = values.map(removeDefaults).filter((x) => x.val.length > 0);
6042
+ let isImportant = false;
6043
+ const filtered = values.map(removeDefaults).filter((x) => x.val.filter((t) => {
6044
+ if (t.typ == exports.EnumToken.ImportantTokenType) {
6045
+ isImportant = true;
6046
+ }
6047
+ return ![exports.EnumToken.WhitespaceTokenType, exports.EnumToken.ImportantTokenType].includes(t.typ);
6048
+ }).length > 0);
5017
6049
  if (filtered.length == 0 && this.config.default.length > 0) {
5018
6050
  filtered.push({
5019
6051
  typ: exports.EnumToken.DeclarationNodeType,
5020
6052
  nam: this.config.shorthand,
5021
6053
  val: parseString(this.config.default[0])
5022
6054
  });
6055
+ if (isImportant) {
6056
+ filtered[0].val.push({
6057
+ typ: exports.EnumToken.ImportantTokenType
6058
+ });
6059
+ }
5023
6060
  }
5024
6061
  return (filtered.length > 0 ? filtered : values)[Symbol.iterator]();
5025
6062
  }
@@ -5115,7 +6152,9 @@ class PropertyMap {
5115
6152
  }, []);
5116
6153
  // @todo remove renderToken call
5117
6154
  if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
5118
- continue;
6155
+ if (!this.config.properties[curr[0]].required) {
6156
+ continue;
6157
+ }
5119
6158
  }
5120
6159
  // remove default values
5121
6160
  let doFilterDefault = true;
@@ -5129,12 +6168,15 @@ class PropertyMap {
5129
6168
  }
5130
6169
  }
5131
6170
  // remove default values
5132
- values = values.filter((val) => {
6171
+ const filtered = values.filter((val) => {
5133
6172
  if (val.typ == exports.EnumToken.WhitespaceTokenType || val.typ == exports.EnumToken.CommentTokenType) {
5134
6173
  return false;
5135
6174
  }
5136
6175
  return !doFilterDefault || !(val.typ == exports.EnumToken.IdenTokenType && props.default.includes(val.val));
5137
6176
  });
6177
+ if (filtered.length > 0 || !(this.requiredCount == requiredCount && this.config.properties[curr[0]].required)) {
6178
+ values = filtered;
6179
+ }
5138
6180
  if (values.length > 0) {
5139
6181
  if ('mapping' in props) {
5140
6182
  // @ts-ignore
@@ -5190,7 +6232,10 @@ class PropertyMap {
5190
6232
  return acc;
5191
6233
  }, []);
5192
6234
  if (this.config.mapping != null) {
5193
- const val = values.reduce((acc, curr) => acc + renderToken(curr, { removeComments: true, minify: true }), '');
6235
+ const val = values.reduce((acc, curr) => acc + renderToken(curr, {
6236
+ removeComments: true,
6237
+ minify: true
6238
+ }), '');
5194
6239
  if (val in this.config.mapping) {
5195
6240
  values.length = 0;
5196
6241
  values.push({
@@ -5258,7 +6303,11 @@ class PropertyList {
5258
6303
  this.declarations = new Map;
5259
6304
  }
5260
6305
  set(nam, value) {
5261
- return this.add({ typ: exports.EnumToken.DeclarationNodeType, nam, val: Array.isArray(value) ? value : parseString(String(value)) });
6306
+ return this.add({
6307
+ typ: exports.EnumToken.DeclarationNodeType,
6308
+ nam,
6309
+ val: Array.isArray(value) ? value : parseString(String(value))
6310
+ });
5262
6311
  }
5263
6312
  add(declaration) {
5264
6313
  if (declaration.typ != exports.EnumToken.DeclarationNodeType || !this.options.removeDuplicateDeclarations) {
@@ -5344,146 +6393,55 @@ class PropertyList {
5344
6393
  }
5345
6394
  }
5346
6395
 
5347
- class ComputeShorthand extends MinifyFeature {
6396
+ class ComputeShorthandFeature extends MinifyFeature {
5348
6397
  static get ordering() {
5349
6398
  return 2;
5350
6399
  }
5351
6400
  static register(options) {
5352
6401
  if (options.computeShorthand) {
5353
6402
  for (const feature of options.features) {
5354
- if (feature instanceof ComputeShorthand) {
6403
+ if (feature instanceof ComputeShorthandFeature) {
5355
6404
  return;
5356
6405
  }
5357
- }
5358
- // @ts-ignore
5359
- options.features.push(new ComputeShorthand());
5360
- }
5361
- }
5362
- run(ast, options = {}, parent, context) {
5363
- // @ts-ignore
5364
- const j = ast.chi.length;
5365
- let k = 0;
5366
- let properties = new PropertyList(options);
5367
- // @ts-ignore
5368
- for (; k < j; k++) {
5369
- // @ts-ignore
5370
- const node = ast.chi[k];
5371
- if (node.typ == exports.EnumToken.CommentNodeType || node.typ == exports.EnumToken.DeclarationNodeType) {
5372
- properties.add(node);
5373
- continue;
5374
- }
5375
- break;
5376
- }
5377
- // @ts-ignore
5378
- ast.chi = [...properties].concat(ast.chi.slice(k));
5379
- return ast;
5380
- }
5381
- }
5382
-
5383
- const gcd = (x, y) => {
5384
- x = Math.abs(x);
5385
- y = Math.abs(y);
5386
- let t;
5387
- if (x == 0 || y == 0) {
5388
- return 1;
5389
- }
5390
- while (y) {
5391
- t = y;
5392
- y = x % y;
5393
- x = t;
5394
- }
5395
- return x;
5396
- };
5397
- function compute(a, b, op) {
5398
- if (typeof a == 'number' && typeof b == 'number') {
5399
- switch (op) {
5400
- case exports.EnumToken.Add:
5401
- return a + b;
5402
- case exports.EnumToken.Sub:
5403
- return a - b;
5404
- case exports.EnumToken.Mul:
5405
- return a * b;
5406
- case exports.EnumToken.Div:
5407
- const r = simplify(a, b);
5408
- if (r[1] == 1) {
5409
- return r[0];
5410
- }
5411
- const result = a / b;
5412
- const r2 = reduceNumber(r[0]) + '/' + reduceNumber(r[1]);
5413
- return reduceNumber(result).length <= r2.length ? result : {
5414
- typ: exports.EnumToken.FractionTokenType,
5415
- l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[0]) },
5416
- r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(r[1]) }
5417
- };
6406
+ }
6407
+ // @ts-ignore
6408
+ options.features.push(new ComputeShorthandFeature());
5418
6409
  }
5419
6410
  }
5420
- let l1 = typeof a == 'number' ? {
5421
- typ: exports.EnumToken.FractionTokenType,
5422
- l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a) },
5423
- r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
5424
- } : a;
5425
- let r1 = typeof b == 'number' ? {
5426
- typ: exports.EnumToken.FractionTokenType,
5427
- l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(b) },
5428
- r: { typ: exports.EnumToken.NumberTokenType, val: '1' }
5429
- } : b;
5430
- let l2;
5431
- let r2;
5432
- switch (op) {
5433
- case exports.EnumToken.Add:
5434
- // @ts-ignore
5435
- l2 = l1.l.val * r1.r.val + l1.r.val * r1.l.val;
5436
- // @ts-ignore
5437
- r2 = l1.r.val * r1.r.val;
5438
- break;
5439
- case exports.EnumToken.Sub:
5440
- // @ts-ignore
5441
- l2 = l1.l.val * r1.r.val - l1.r.val * r1.l.val;
5442
- // @ts-ignore
5443
- r2 = l1.r.val * r1.r.val;
5444
- break;
5445
- case exports.EnumToken.Mul:
5446
- // @ts-ignore
5447
- l2 = l1.l.val * r1.l.val;
5448
- // @ts-ignore
5449
- r2 = l1.r.val * r1.r.val;
5450
- break;
5451
- case exports.EnumToken.Div:
5452
- // @ts-ignore
5453
- l2 = l1.l.val * r1.r.val;
6411
+ run(ast, options = {}, parent, context) {
6412
+ // @ts-ignore
6413
+ const j = ast.chi.length;
6414
+ let k = 0;
6415
+ let properties = new PropertyList(options);
6416
+ // @ts-ignore
6417
+ for (; k < j; k++) {
5454
6418
  // @ts-ignore
5455
- r2 = l1.r.val * r1.l.val;
6419
+ const node = ast.chi[k];
6420
+ if (node.typ == exports.EnumToken.CommentNodeType || node.typ == exports.EnumToken.DeclarationNodeType) {
6421
+ properties.add(node);
6422
+ continue;
6423
+ }
5456
6424
  break;
6425
+ }
6426
+ // @ts-ignore
6427
+ ast.chi = [...properties].concat(ast.chi.slice(k));
6428
+ return ast;
5457
6429
  }
5458
- const a2 = simplify(l2, r2);
5459
- if (a2[1] == 1) {
5460
- return a2[0];
5461
- }
5462
- const result = a2[0] / a2[1];
5463
- return reduceNumber(result).length <= reduceNumber(a2[0]).length + 1 + reduceNumber(a2[1]).length ? result : {
5464
- typ: exports.EnumToken.FractionTokenType,
5465
- l: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[0]) },
5466
- r: { typ: exports.EnumToken.NumberTokenType, val: reduceNumber(a2[1]) }
5467
- };
5468
- }
5469
- function simplify(a, b) {
5470
- const g = gcd(a, b);
5471
- return g > 1 ? [a / g, b / g] : [a, b];
5472
6430
  }
5473
6431
 
5474
- class ComputeCalcExpression extends MinifyFeature {
6432
+ class ComputeCalcExpressionFeature extends MinifyFeature {
5475
6433
  static get ordering() {
5476
6434
  return 1;
5477
6435
  }
5478
6436
  static register(options) {
5479
6437
  if (options.computeCalcExpression) {
5480
6438
  for (const feature of options.features) {
5481
- if (feature instanceof ComputeCalcExpression) {
6439
+ if (feature instanceof ComputeCalcExpressionFeature) {
5482
6440
  return;
5483
6441
  }
5484
6442
  }
5485
6443
  // @ts-ignore
5486
- options.features.push(new ComputeCalcExpression());
6444
+ options.features.push(new ComputeCalcExpressionFeature());
5487
6445
  }
5488
6446
  }
5489
6447
  run(ast) {
@@ -5496,11 +6454,31 @@ class ComputeCalcExpression extends MinifyFeature {
5496
6454
  continue;
5497
6455
  }
5498
6456
  const set = new IterableWeakSet;
5499
- for (const { parent } of walkValues(node.val)) {
5500
- if (parent != null && parent.typ == exports.EnumToken.FunctionTokenType && parent.val == 'calc') {
6457
+ for (const { value, parent } of walkValues(node.val)) {
6458
+ if (value != null && value.typ == exports.EnumToken.FunctionTokenType && value.val == 'calc') {
5501
6459
  if (!set.has(parent)) {
5502
- set.add(parent);
5503
- parent.chi = evaluate(parent.chi);
6460
+ set.add(value);
6461
+ value.chi = evaluate(value.chi);
6462
+ if (value.chi.length == 1 && value.chi[0].typ != exports.EnumToken.BinaryExpressionTokenType) {
6463
+ if (parent != null) {
6464
+ if (parent.typ == exports.EnumToken.BinaryExpressionTokenType) {
6465
+ if (parent.l == value) {
6466
+ parent.l = value.chi[0];
6467
+ }
6468
+ else {
6469
+ parent.r = value.chi[0];
6470
+ }
6471
+ }
6472
+ else {
6473
+ for (let i = 0; i < parent.chi.length; i++) {
6474
+ if (parent.chi[i] == value) {
6475
+ parent.chi.splice(i, 1, value.chi[0]);
6476
+ break;
6477
+ }
6478
+ }
6479
+ }
6480
+ }
6481
+ }
5504
6482
  }
5505
6483
  }
5506
6484
  }
@@ -5508,191 +6486,12 @@ class ComputeCalcExpression extends MinifyFeature {
5508
6486
  return ast;
5509
6487
  }
5510
6488
  }
5511
- /**
5512
- * evaluate arithmetic operation
5513
- * @param l
5514
- * @param r
5515
- * @param op
5516
- */
5517
- function doEvaluate(l, r, op) {
5518
- const defaultReturn = {
5519
- typ: exports.EnumToken.BinaryExpressionTokenType,
5520
- op,
5521
- l,
5522
- r
5523
- };
5524
- if (!isScalarToken(l) || !isScalarToken(r)) {
5525
- return defaultReturn;
5526
- }
5527
- if ((op == exports.EnumToken.Add || op == exports.EnumToken.Sub)) {
5528
- // @ts-ignore
5529
- if (l.typ != r.typ) {
5530
- return defaultReturn;
5531
- }
5532
- }
5533
- const typ = l.typ == exports.EnumToken.NumberTokenType ? r.typ : l.typ;
5534
- // @ts-ignore
5535
- const val = compute(typeof l.val == 'string' ? +l.val : l.val, typeof r.val == 'string' ? +r.val : r.val, op);
5536
- return { ...(l.typ == exports.EnumToken.NumberTokenType ? r : l), typ, val: typeof val == 'number' ? reduceNumber(val) : val };
5537
- }
5538
- /**
5539
- * evaluate an array of tokens
5540
- * @param tokens
5541
- */
5542
- function evaluate(tokens) {
5543
- const nodes = inlineExpression(evaluateExpression(buildExpression(tokens)));
5544
- if (nodes.length <= 1) {
5545
- return nodes;
5546
- }
5547
- const map = new Map;
5548
- let token;
5549
- let i;
5550
- for (i = 0; i < nodes.length; i++) {
5551
- token = nodes[i];
5552
- if (token.typ == exports.EnumToken.Add) {
5553
- continue;
5554
- }
5555
- if (token.typ == exports.EnumToken.Sub) {
5556
- if (!isScalarToken(nodes[i + 1])) {
5557
- token = { typ: exports.EnumToken.ListToken, chi: [nodes[i], nodes[i + 1]] };
5558
- }
5559
- else {
5560
- token = doEvaluate(nodes[i + 1], { typ: exports.EnumToken.NumberTokenType, val: '-1' }, exports.EnumToken.Mul);
5561
- }
5562
- i++;
5563
- }
5564
- if (!map.has(token.typ)) {
5565
- map.set(token.typ, [token]);
5566
- }
5567
- else {
5568
- map.get(token.typ).push(token);
5569
- }
5570
- }
5571
- return [...map].reduce((acc, curr) => {
5572
- const token = curr[1].reduce((acc, curr) => doEvaluate(acc, curr, exports.EnumToken.Add));
5573
- if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
5574
- if ('val' in token && +token.val < 0) {
5575
- acc.push({ typ: exports.EnumToken.Sub }, { ...token, val: String(-token.val) });
5576
- return acc;
5577
- }
5578
- }
5579
- if (acc.length > 0 && curr[0] != exports.EnumToken.ListToken) {
5580
- acc.push({ typ: exports.EnumToken.Add });
5581
- }
5582
- acc.push(token);
5583
- return acc;
5584
- }, []);
5585
- }
5586
- /**
5587
- * convert BinaryExpression into an array
5588
- * @param token
5589
- */
5590
- function inlineExpression(token) {
5591
- const result = [];
5592
- if (token.typ == exports.EnumToken.ParensTokenType && token.chi.length == 1) {
5593
- result.push(token.chi[0]);
5594
- }
5595
- else if (token.typ == exports.EnumToken.BinaryExpressionTokenType) {
5596
- if ([exports.EnumToken.Mul, exports.EnumToken.Div].includes(token.op)) {
5597
- result.push(token);
5598
- }
5599
- else {
5600
- result.push(...inlineExpression(token.l), { typ: token.op }, ...inlineExpression(token.r));
5601
- }
5602
- }
5603
- else {
5604
- result.push(token);
5605
- }
5606
- return result;
5607
- }
5608
- /**
5609
- * evaluate expression
5610
- * @param token
5611
- */
5612
- function evaluateExpression(token) {
5613
- if (token.typ != exports.EnumToken.BinaryExpressionTokenType) {
5614
- return token;
5615
- }
5616
- if (token.r.typ == exports.EnumToken.BinaryExpressionTokenType) {
5617
- token.r = evaluateExpression(token.r);
5618
- }
5619
- if (token.l.typ == exports.EnumToken.BinaryExpressionTokenType) {
5620
- token.l = evaluateExpression(token.l);
5621
- }
5622
- return doEvaluate(token.l, token.r, token.op);
5623
- }
5624
- function isScalarToken(token) {
5625
- return token.typ != exports.EnumToken.BinaryExpressionTokenType && token.typ != exports.EnumToken.ParensTokenType && token.typ != exports.EnumToken.FunctionTokenType;
5626
- }
5627
- /**
5628
- *
5629
- * generate binary expression tree
5630
- * @param tokens
5631
- */
5632
- function buildExpression(tokens) {
5633
- return factor(factor(tokens.filter(t => t.typ != exports.EnumToken.WhitespaceTokenType), ['/', '*']), ['+', '-'])[0];
5634
- }
5635
- function getArithmeticOperation(op) {
5636
- if (op == '+') {
5637
- return exports.EnumToken.Add;
5638
- }
5639
- if (op == '-') {
5640
- return exports.EnumToken.Sub;
5641
- }
5642
- if (op == '/') {
5643
- return exports.EnumToken.Div;
5644
- }
5645
- return exports.EnumToken.Mul;
5646
- }
5647
- /**
5648
- *
5649
- * generate binary expression tree
5650
- * @param token
5651
- */
5652
- function factorToken(token) {
5653
- if (token.typ == exports.EnumToken.ParensTokenType || (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc')) {
5654
- if (token.typ == exports.EnumToken.FunctionTokenType && token.val == 'calc') {
5655
- token = { ...token, typ: exports.EnumToken.ParensTokenType };
5656
- // @ts-ignore
5657
- delete token.val;
5658
- }
5659
- return buildExpression(token.chi);
5660
- }
5661
- return token;
5662
- }
5663
- /**
5664
- * generate binary expression tree
5665
- * @param tokens
5666
- * @param ops
5667
- */
5668
- function factor(tokens, ops) {
5669
- let isOp;
5670
- const opList = ops.map(x => getArithmeticOperation(x));
5671
- if (tokens.length == 1) {
5672
- return [factorToken(tokens[0])];
5673
- }
5674
- for (let i = 0; i < tokens.length; i++) {
5675
- isOp = opList.includes(tokens[i].typ);
5676
- if (isOp ||
5677
- // @ts-ignore
5678
- (tokens[i].typ == exports.EnumToken.LiteralTokenType && ops.includes(tokens[i].val))) {
5679
- tokens.splice(i - 1, 3, {
5680
- typ: exports.EnumToken.BinaryExpressionTokenType,
5681
- op: isOp ? tokens[i].typ : getArithmeticOperation(tokens[i].val),
5682
- l: factorToken(tokens[i - 1]),
5683
- r: factorToken(tokens[i + 1])
5684
- });
5685
- i--;
5686
- }
5687
- }
5688
- return tokens;
5689
- }
5690
6489
 
5691
6490
  var allFeatures = /*#__PURE__*/Object.freeze({
5692
6491
  __proto__: null,
5693
- ComputeCalcExpression: ComputeCalcExpression,
5694
- ComputeShorthand: ComputeShorthand,
5695
- InlineCssVariables: InlineCssVariables
6492
+ ComputeCalcExpressionFeature: ComputeCalcExpressionFeature,
6493
+ ComputeShorthandFeature: ComputeShorthandFeature,
6494
+ InlineCssVariablesFeature: InlineCssVariablesFeature
5696
6495
  });
5697
6496
 
5698
6497
  const combinators = ['+', '>', '~', '||'];
@@ -6618,13 +7417,14 @@ function splitPath(result) {
6618
7417
  parts[parts.length - 1] += chr;
6619
7418
  }
6620
7419
  }
6621
- let k = parts.length;
6622
- while (k--) {
7420
+ let k = -1;
7421
+ while (++k < parts.length) {
6623
7422
  if (parts[k] == '.') {
6624
- parts.splice(k, 1);
7423
+ parts.splice(k--, 1);
6625
7424
  }
6626
7425
  else if (parts[k] == '..') {
6627
7426
  parts.splice(k - 1, 2);
7427
+ k -= 2;
6628
7428
  }
6629
7429
  }
6630
7430
  return { parts, i };