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