@tbela99/css-parser 0.0.1-rc7 → 0.1.0

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