@weapp-tailwindcss/postcss 1.3.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -34,7 +34,7 @@ function getDefaultOptions(options) {
34
34
  };
35
35
  }
36
36
 
37
- // src/plugins/index.ts
37
+ // src/pipeline.ts
38
38
  import postcssPresetEnv from "postcss-preset-env";
39
39
 
40
40
  // src/plugins/ctx.ts
@@ -56,7 +56,7 @@ function createContext() {
56
56
  // src/plugins/getCalcPlugin.ts
57
57
  import postcssCalc from "@weapp-tailwindcss/postcss-calc";
58
58
 
59
- // ../../node_modules/.pnpm/es-toolkit@1.40.0/node_modules/es-toolkit/dist/object/omit.mjs
59
+ // ../../node_modules/.pnpm/es-toolkit@1.41.0/node_modules/es-toolkit/dist/object/omit.mjs
60
60
  function omit(obj, keys) {
61
61
  const result = { ...obj };
62
62
  for (let i = 0; i < keys.length; i++) {
@@ -80,32 +80,41 @@ import { regExpTest } from "@weapp-tailwindcss/shared";
80
80
  import valueParser from "postcss-value-parser";
81
81
  function getCustomPropertyCleaner(options) {
82
82
  const includeCustomProperties = Array.isArray(options.cssCalc) ? options.cssCalc : typeof options.cssCalc === "object" ? options.cssCalc.includeCustomProperties : [];
83
- if (!includeCustomProperties || includeCustomProperties.length === 0) {
83
+ const shouldMatchCustomProperties = Array.isArray(includeCustomProperties) && includeCustomProperties.length > 0;
84
+ if (!shouldMatchCustomProperties) {
84
85
  return null;
85
86
  }
86
87
  return {
87
88
  postcssPlugin: "postcss-remove-include-custom-properties",
88
89
  OnceExit(root) {
89
- root.walkDecls((decl, idx) => {
90
- if (idx === 0 || !/--/.test(decl.value)) {
90
+ root.walkDecls((decl) => {
91
+ const prevNode = decl.prev();
92
+ if (!prevNode || prevNode.type !== "decl" || prevNode.prop !== decl.prop) {
91
93
  return;
92
94
  }
93
- const prevNode = decl.parent?.nodes[idx - 1];
94
- if (!prevNode || prevNode.prop !== decl.prop) {
95
+ if (prevNode.value === decl.value) {
96
+ decl.remove();
97
+ return;
98
+ }
99
+ if (!shouldMatchCustomProperties || !/--/.test(decl.value)) {
95
100
  return;
96
101
  }
97
102
  const parsed = valueParser(decl.value);
103
+ let containsIncludedCustomProperty = false;
98
104
  parsed.walk((node) => {
99
- if (node.type !== "function" || node.value !== "var") {
105
+ if (node.type !== "function" || node.value !== "var" || containsIncludedCustomProperty) {
100
106
  return;
101
107
  }
102
108
  const match = node.nodes.find((x) => {
103
109
  return x.type === "word" && regExpTest(includeCustomProperties, x.value);
104
110
  });
105
111
  if (match) {
106
- decl.remove();
112
+ containsIncludedCustomProperty = true;
107
113
  }
108
114
  });
115
+ if (containsIncludedCustomProperty) {
116
+ decl.remove();
117
+ }
109
118
  });
110
119
  }
111
120
  };
@@ -357,10 +366,7 @@ import { escape, MappingChars2String } from "@weapp-core/escape";
357
366
  function internalCssSelectorReplacer(selectors, options = {
358
367
  escapeMap: MappingChars2String
359
368
  }) {
360
- const { mangleContext, escapeMap } = options;
361
- if (mangleContext) {
362
- selectors = mangleContext.cssHandler(selectors);
363
- }
369
+ const { escapeMap } = options;
364
370
  return escape(selectors, {
365
371
  map: escapeMap
366
372
  });
@@ -377,129 +383,306 @@ function composeIsPseudo(strs) {
377
383
 
378
384
  // src/selectorParser/rule-transformer.ts
379
385
  var ruleTransformCache = /* @__PURE__ */ new WeakMap();
380
- function createRuleTransformer(options) {
381
- let currentRule;
382
- const { escapeMap, mangleContext, cssSelectorReplacement, cssRemoveHoverPseudoClass, uniAppX } = options;
383
- const transform = (selectors) => {
384
- const rule = currentRule;
385
- if (!rule) {
386
- return;
386
+ var MIRROR_PROP_PAIRS = [
387
+ ["margin-top", "margin-bottom"],
388
+ ["margin-left", "margin-right"],
389
+ ["margin-inline-start", "margin-inline-end"],
390
+ ["margin-block-start", "margin-block-end"],
391
+ ["border-top-width", "border-bottom-width"],
392
+ ["border-left-width", "border-right-width"],
393
+ ["border-inline-start-width", "border-inline-end-width"],
394
+ ["border-block-start-width", "border-block-end-width"]
395
+ ];
396
+ var MIRROR_PROP_MAP = /* @__PURE__ */ new Map();
397
+ var SPACING_PROP_SET = /* @__PURE__ */ new Set();
398
+ for (const [a, b] of MIRROR_PROP_PAIRS) {
399
+ MIRROR_PROP_MAP.set(a, b);
400
+ MIRROR_PROP_MAP.set(b, a);
401
+ SPACING_PROP_SET.add(a);
402
+ SPACING_PROP_SET.add(b);
403
+ }
404
+ var LEGACY_WEBKIT_SPACING_PROPS = /* @__PURE__ */ new Set([
405
+ "-webkit-margin-start",
406
+ "-webkit-margin-end",
407
+ "-webkit-margin-before",
408
+ "-webkit-margin-after"
409
+ ]);
410
+ var VAR_REFERENCE_PATTERN = /var\(/i;
411
+ function dedupeSpacingProps(rule) {
412
+ const grouped = /* @__PURE__ */ new Map();
413
+ for (const node of rule.nodes) {
414
+ if (node.type !== "decl") {
415
+ continue;
387
416
  }
388
- selectors.walk((selector, index) => {
389
- if (selector.type === "class") {
390
- selector.value = internalCssSelectorReplacer(selector.value, {
391
- escapeMap,
392
- mangleContext
393
- });
394
- } else if (selector.type === "universal") {
395
- if (cssSelectorReplacement?.universal) {
396
- selector.value = composeIsPseudo(cssSelectorReplacement.universal);
397
- }
398
- } else if (selector.type === "selector") {
399
- if (cssRemoveHoverPseudoClass) {
400
- const node = selector.nodes.find((x) => x.type === "pseudo" && x.value === ":hover");
401
- if (node) {
402
- selector.remove();
403
- }
404
- }
405
- } else if (selector.type === "pseudo") {
406
- if (selector.value === ":root" && cssSelectorReplacement?.root) {
407
- selector.value = composeIsPseudo(cssSelectorReplacement.root);
408
- } else if (selector.value === ":where") {
409
- if (uniAppX) {
410
- selector.value = ":is";
411
- }
412
- if (index === 0 && selector.length === 1) {
413
- selector.walk((node, idx) => {
414
- if (idx === 0 && node.type === "class") {
415
- const nodes2 = node.parent?.nodes;
416
- if (nodes2) {
417
- const first = nodes2[idx + 1];
418
- if (first && first.type === "combinator" && first.value === ">") {
419
- const second = nodes2[idx + 2];
420
- if (second && second.type === "pseudo" && second.value === ":not" && second.first.first.type === "pseudo" && second.first.first.value === ":last-child") {
421
- const ast = getCombinatorSelectorAst(options);
422
- second.replaceWith(
423
- ...ast
424
- );
425
- }
426
- }
427
- }
428
- }
429
- });
430
- selector.replaceWith(...selector.nodes);
431
- for (const node of rule.nodes) {
432
- if (node.type === "decl") {
433
- if (node.prop === "margin-block-start") {
434
- node.prop = "margin-block-end";
435
- } else if (node.prop === "margin-block-end") {
436
- node.prop = "margin-block-start";
437
- } else if (node.prop === "margin-inline-start") {
438
- node.prop = "margin-inline-end";
439
- } else if (node.prop === "margin-inline-end") {
440
- node.prop = "margin-inline-start";
441
- } else if (node.prop === "margin-top") {
442
- node.prop = "margin-bottom";
443
- } else if (node.prop === "margin-bottom") {
444
- node.prop = "margin-top";
445
- } else if (node.prop === "margin-left") {
446
- node.prop = "margin-right";
447
- } else if (node.prop === "margin-right") {
448
- node.prop = "margin-left";
449
- } else if (node.prop === "-webkit-margin-start" || node.prop === "-webkit-margin-end" || node.prop === "-webkit-margin-before" || node.prop === "-webkit-margin-after") {
450
- node.remove();
451
- }
452
- }
453
- }
454
- }
455
- }
456
- } else if (selector.type === "combinator") {
457
- if (selector.value === ">") {
458
- const nodes2 = selector.parent?.nodes;
459
- if (nodes2) {
460
- const first = nodes2[index + 1];
461
- if (first && first.type === "pseudo" && first.value === ":not" && (first.first.first.type === "attribute" && first.first.first.attribute === "hidden" || first.first.first.type === "tag" && first.first.first.value === "template")) {
462
- const second = nodes2[index + 2];
463
- if (second && second.type === "combinator" && (second.value === "~" || second.value === "+")) {
464
- const third = nodes2[index + 3];
465
- if (third && third.type === "pseudo" && third.value === ":not" && (third.first.first.type === "attribute" && third.first.first.attribute === "hidden" || third.first.first.type === "tag" && third.first.first.value === "template")) {
466
- const ast = getCombinatorSelectorAst(options);
467
- selector.parent?.nodes.splice(
468
- index + 1,
469
- 3,
470
- ...ast
471
- );
472
- }
473
- }
474
- }
475
- }
476
- }
477
- } else if (selector.type === "tag") {
478
- if (uniAppX) {
479
- selector.remove();
480
- }
481
- } else if (selector.type === "attribute") {
482
- if (uniAppX) {
483
- selector.remove();
484
- }
417
+ if (!SPACING_PROP_SET.has(node.prop)) {
418
+ continue;
419
+ }
420
+ const list = grouped.get(node.prop);
421
+ if (list) {
422
+ list.push(node);
423
+ } else {
424
+ grouped.set(node.prop, [node]);
425
+ }
426
+ }
427
+ for (const [, declarations] of grouped) {
428
+ if (declarations.length <= 1) {
429
+ continue;
430
+ }
431
+ const unique = [];
432
+ const seenValues = /* @__PURE__ */ new Set();
433
+ for (const decl of declarations) {
434
+ if (decl.parent !== rule) {
435
+ continue;
485
436
  }
486
- });
487
- selectors.walk((selector) => {
488
- if (selector.type === "selector") {
489
- selector.length === 0 && selector.remove();
437
+ const key = `${decl.important ? "!important@@" : ""}${decl.value}`;
438
+ if (seenValues.has(key)) {
439
+ decl.remove();
440
+ continue;
490
441
  }
491
- });
492
- if (selectors.length === 0) {
493
- rule.remove();
442
+ seenValues.add(key);
443
+ unique.push(decl);
444
+ }
445
+ if (unique.length <= 1) {
446
+ continue;
447
+ }
448
+ const literals = unique.filter((decl) => !VAR_REFERENCE_PATTERN.test(decl.value));
449
+ const variables = unique.filter((decl) => VAR_REFERENCE_PATTERN.test(decl.value));
450
+ if (variables.length === 0 || literals.length === 0) {
451
+ continue;
452
+ }
453
+ const ordered = [...literals, ...variables];
454
+ const alreadyOrdered = ordered.every((decl, index) => decl === unique[index]);
455
+ if (alreadyOrdered) {
456
+ continue;
457
+ }
458
+ const anchor = unique[unique.length - 1]?.next() ?? void 0;
459
+ for (const decl of unique) {
460
+ decl.remove();
461
+ }
462
+ for (const decl of ordered) {
463
+ if (anchor) {
464
+ rule.insertBefore(anchor, decl);
465
+ } else {
466
+ rule.append(decl);
467
+ }
468
+ }
469
+ }
470
+ }
471
+ function isNotLastChildPseudo(node) {
472
+ if (!node || node.type !== "pseudo" || node.value !== ":not") {
473
+ return false;
474
+ }
475
+ const selectors = node.nodes;
476
+ if (!selectors || selectors.length !== 1) {
477
+ return false;
478
+ }
479
+ const firstSelector = selectors[0];
480
+ if (firstSelector.type !== "selector") {
481
+ return false;
482
+ }
483
+ const target = firstSelector.nodes?.[0];
484
+ return Boolean(target && target.type === "pseudo" && target.value === ":last-child");
485
+ }
486
+ function transformSpacingSelector(nodes2, options) {
487
+ if (!nodes2 || nodes2.length === 0) {
488
+ return false;
489
+ }
490
+ for (let idx = 0; idx < nodes2.length; idx++) {
491
+ const current = nodes2[idx];
492
+ if (current.type !== "class" && current.type !== "nesting") {
493
+ continue;
494
+ }
495
+ const combinator = nodes2[idx + 1];
496
+ if (!combinator || combinator.type !== "combinator" || combinator.value !== ">") {
497
+ continue;
494
498
  }
499
+ const candidate = nodes2[idx + 2];
500
+ if (!isNotLastChildPseudo(candidate)) {
501
+ continue;
502
+ }
503
+ const ast = getCombinatorSelectorAst(options);
504
+ candidate.replaceWith(...ast);
505
+ return true;
506
+ }
507
+ return false;
508
+ }
509
+ function normalizeSpacingDeclarations(rule) {
510
+ for (const node of [...rule.nodes]) {
511
+ if (node.type !== "decl") {
512
+ continue;
513
+ }
514
+ if (LEGACY_WEBKIT_SPACING_PROPS.has(node.prop)) {
515
+ node.remove();
516
+ continue;
517
+ }
518
+ const mirror = MIRROR_PROP_MAP.get(node.prop);
519
+ if (mirror) {
520
+ node.prop = mirror;
521
+ }
522
+ }
523
+ dedupeSpacingProps(rule);
524
+ }
525
+ function flattenWherePseudo(node, context, index, parent) {
526
+ if (context.options.uniAppX) {
527
+ node.value = ":is";
528
+ }
529
+ if (index === 0 && node.length === 1) {
530
+ const targetSelector = node.nodes?.[0];
531
+ if (targetSelector && targetSelector.type === "selector" && transformSpacingSelector(targetSelector.nodes, context.options)) {
532
+ context.requiresSpacingNormalization = true;
533
+ }
534
+ node.replaceWith(...node.nodes);
535
+ if (parent && parent.type === "selector" && parent.length === 0) {
536
+ parent.remove();
537
+ }
538
+ }
539
+ }
540
+ function handleClassNode(node, context) {
541
+ if (node.type !== "class") {
542
+ return;
543
+ }
544
+ node.value = internalCssSelectorReplacer(node.value, { escapeMap: context.options.escapeMap });
545
+ }
546
+ function handleUniversalNode(node, context) {
547
+ if (node.type !== "universal") {
548
+ return;
549
+ }
550
+ const replacement = context.options.cssSelectorReplacement?.universal;
551
+ if (replacement) {
552
+ node.value = composeIsPseudo(replacement);
553
+ }
554
+ }
555
+ function shouldRemoveHoverSelector(selector, options) {
556
+ if (!options.cssRemoveHoverPseudoClass) {
557
+ return false;
558
+ }
559
+ return selector.nodes.some((node) => node.type === "pseudo" && node.value === ":hover");
560
+ }
561
+ function isHiddenOrTemplateNotPseudo(node) {
562
+ if (!node || node.type !== "pseudo" || node.value !== ":not") {
563
+ return false;
564
+ }
565
+ const selector = node.first;
566
+ if (!selector || selector.type !== "selector") {
567
+ return false;
568
+ }
569
+ const first = selector.first;
570
+ if (!first) {
571
+ return false;
572
+ }
573
+ if (first.type === "attribute") {
574
+ return first.attribute === "hidden";
575
+ }
576
+ if (first.type === "tag") {
577
+ return first.value === "template";
578
+ }
579
+ return false;
580
+ }
581
+ function handleCombinatorNode(node, index, context) {
582
+ if (node.type !== "combinator" || node.value !== ">") {
583
+ return;
584
+ }
585
+ const nodes2 = node.parent?.nodes;
586
+ if (!nodes2) {
587
+ return;
588
+ }
589
+ const first = nodes2[index + 1];
590
+ const second = nodes2[index + 2];
591
+ const third = nodes2[index + 3];
592
+ if (isHiddenOrTemplateNotPseudo(first) && second && second.type === "combinator" && (second.value === "~" || second.value === "+") && isHiddenOrTemplateNotPseudo(third)) {
593
+ const ast = getCombinatorSelectorAst(context.options);
594
+ nodes2.splice(index + 1, 3, ...ast);
595
+ }
596
+ }
597
+ function handlePseudoNode(node, index, context, parent) {
598
+ if (node.type !== "pseudo") {
599
+ return;
600
+ }
601
+ if (node.value === ":root" && context.options.cssSelectorReplacement?.root) {
602
+ node.value = composeIsPseudo(context.options.cssSelectorReplacement.root);
603
+ return;
604
+ }
605
+ if (node.value === ":where") {
606
+ flattenWherePseudo(node, context, index, parent);
607
+ }
608
+ }
609
+ function handleTagOrAttribute(node, context) {
610
+ if (!context.options.uniAppX) {
611
+ return;
612
+ }
613
+ if (node.type === "tag" || node.type === "attribute") {
614
+ node.remove();
615
+ }
616
+ }
617
+ function handleSelectorNode(selector, context) {
618
+ if (shouldRemoveHoverSelector(selector, context.options)) {
619
+ selector.remove();
620
+ return;
621
+ }
622
+ if (transformSpacingSelector(selector.nodes, context.options)) {
623
+ context.requiresSpacingNormalization = true;
624
+ }
625
+ }
626
+ function transformSelectors(selectors, context) {
627
+ selectors.walk((node, index) => {
628
+ const parent = node.parent?.type === "selector" ? node.parent : void 0;
629
+ switch (node.type) {
630
+ case "class":
631
+ handleClassNode(node, context);
632
+ break;
633
+ case "universal":
634
+ handleUniversalNode(node, context);
635
+ break;
636
+ case "selector":
637
+ handleSelectorNode(node, context);
638
+ break;
639
+ case "pseudo":
640
+ if (!isNotLastChildPseudo(node)) {
641
+ handlePseudoNode(node, index, context, parent);
642
+ }
643
+ break;
644
+ case "combinator":
645
+ handleCombinatorNode(node, index, context);
646
+ break;
647
+ case "tag":
648
+ case "attribute":
649
+ handleTagOrAttribute(node, context);
650
+ break;
651
+ default:
652
+ break;
653
+ }
654
+ });
655
+ if (context.requiresSpacingNormalization) {
656
+ normalizeSpacingDeclarations(context.rule);
657
+ }
658
+ selectors.walk((node) => {
659
+ if (node.type === "selector" && node.length === 0) {
660
+ node.remove();
661
+ }
662
+ });
663
+ if (selectors.length === 0) {
664
+ context.rule.remove();
665
+ }
666
+ }
667
+ function createRuleTransformer(options) {
668
+ let context;
669
+ const transform = (selectors) => {
670
+ if (!context) {
671
+ return;
672
+ }
673
+ transformSelectors(selectors, context);
495
674
  };
496
675
  const parser = psp4(transform);
497
676
  return (rule) => {
498
- currentRule = rule;
677
+ context = {
678
+ options,
679
+ requiresSpacingNormalization: false,
680
+ rule
681
+ };
499
682
  try {
500
683
  parser.transformSync(rule, normalizeTransformOptions());
501
684
  } finally {
502
- currentRule = void 0;
685
+ context = void 0;
503
686
  }
504
687
  };
505
688
  }
@@ -513,16 +696,83 @@ function ruleTransformSync(rule, options) {
513
696
  }
514
697
 
515
698
  // src/plugins/post.ts
699
+ function normalizeSelectorList(value) {
700
+ if (value === void 0 || value === false) {
701
+ return [];
702
+ }
703
+ return Array.isArray(value) ? value.filter(Boolean) : [value];
704
+ }
705
+ function getSpecificityMatchingName(options) {
706
+ const feature = options.cssPresetEnv?.features?.["is-pseudo-class"];
707
+ if (feature && typeof feature === "object" && "specificityMatchingName" in feature) {
708
+ const specificityName = feature.specificityMatchingName;
709
+ return typeof specificityName === "string" && specificityName.length > 0 ? specificityName : void 0;
710
+ }
711
+ return void 0;
712
+ }
713
+ function createRootSpecificityCleaner(options) {
714
+ const specificityMatchingName = getSpecificityMatchingName(options);
715
+ const selectors = normalizeSelectorList(options.cssSelectorReplacement?.root);
716
+ if (!specificityMatchingName || selectors.length === 0) {
717
+ return void 0;
718
+ }
719
+ const suffix = `:not(.${specificityMatchingName})`;
720
+ const targets = selectors.map((selector) => selector?.trim()).filter((selector) => Boolean(selector?.length)).map((selector) => ({
721
+ match: `${selector}${suffix}`,
722
+ spacedMatch: `${selector} ${suffix}`,
723
+ replacement: selector
724
+ }));
725
+ if (!targets.length) {
726
+ return void 0;
727
+ }
728
+ return (rule) => {
729
+ if (!rule.selectors || rule.selectors.length === 0) {
730
+ return;
731
+ }
732
+ const next = rule.selectors.map((selector) => {
733
+ let updated = selector;
734
+ for (const target of targets) {
735
+ if (updated.includes(target.match)) {
736
+ updated = updated.split(target.match).join(target.replacement);
737
+ }
738
+ if (updated.includes(target.spacedMatch)) {
739
+ updated = updated.split(target.spacedMatch).join(target.replacement);
740
+ }
741
+ }
742
+ return updated;
743
+ });
744
+ rule.selectors = next;
745
+ };
746
+ }
516
747
  var OklabSuffix = "in oklab";
517
748
  var logicalPropMap = /* @__PURE__ */ new Map([
749
+ // margin
518
750
  ["margin-inline-start", "margin-left"],
519
751
  ["margin-inline-end", "margin-right"],
520
752
  ["margin-block-start", "margin-top"],
521
753
  ["margin-block-end", "margin-bottom"],
754
+ // padding
522
755
  ["padding-inline-start", "padding-left"],
523
756
  ["padding-inline-end", "padding-right"],
524
757
  ["padding-block-start", "padding-top"],
525
- ["padding-block-end", "padding-bottom"]
758
+ ["padding-block-end", "padding-bottom"],
759
+ // border
760
+ ["border-inline-start", "border-left"],
761
+ ["border-inline-end", "border-right"],
762
+ ["border-block-start", "border-top"],
763
+ ["border-block-end", "border-bottom"],
764
+ ["border-inline-start-width", "border-left-width"],
765
+ ["border-inline-end-width", "border-right-width"]
766
+ ]);
767
+ var variablePriorityProps = /* @__PURE__ */ new Set([
768
+ "margin-left",
769
+ "margin-right",
770
+ "margin-top",
771
+ "margin-bottom",
772
+ "border-left-width",
773
+ "border-right-width",
774
+ "border-top-width",
775
+ "border-bottom-width"
526
776
  ]);
527
777
  function getCanonicalProp(prop) {
528
778
  return logicalPropMap.get(prop) ?? prop;
@@ -539,6 +789,9 @@ function normalizeCalcValue(value) {
539
789
  } while (next !== prev);
540
790
  return next.replace(/calc\(\s*(1\s*-\s*var\([^()]+\))\s*\)/gi, "($1)");
541
791
  }
792
+ function hasVariableReference(value) {
793
+ return value.includes("var(");
794
+ }
542
795
  function dedupeDeclarations(rule) {
543
796
  const entries = [];
544
797
  for (const node of [...rule.nodes]) {
@@ -574,6 +827,73 @@ function dedupeDeclarations(rule) {
574
827
  entry.decl.remove();
575
828
  }
576
829
  }
830
+ const reorderGroups = /* @__PURE__ */ new Map();
831
+ for (const node of rule.nodes) {
832
+ if (node.type !== "decl") {
833
+ continue;
834
+ }
835
+ const canonical = getCanonicalProp(node.prop);
836
+ if (!variablePriorityProps.has(canonical)) {
837
+ continue;
838
+ }
839
+ const existing = reorderGroups.get(canonical);
840
+ if (existing) {
841
+ existing.push(node);
842
+ } else {
843
+ reorderGroups.set(canonical, [node]);
844
+ }
845
+ }
846
+ for (const declarations of reorderGroups.values()) {
847
+ if (declarations.length <= 1) {
848
+ continue;
849
+ }
850
+ const literals = declarations.filter((decl) => !hasVariableReference(decl.value));
851
+ const variables = declarations.filter((decl) => hasVariableReference(decl.value));
852
+ if (literals.length === 0 || variables.length === 0) {
853
+ continue;
854
+ }
855
+ const ordered = [...literals, ...variables];
856
+ let needReorder = false;
857
+ for (let index = 0; index < ordered.length; index++) {
858
+ if (ordered[index] !== declarations[index]) {
859
+ needReorder = true;
860
+ break;
861
+ }
862
+ }
863
+ if (!needReorder) {
864
+ continue;
865
+ }
866
+ const anchor = declarations[declarations.length - 1]?.next() ?? void 0;
867
+ for (const decl of declarations) {
868
+ decl.remove();
869
+ }
870
+ for (const decl of ordered) {
871
+ if (anchor) {
872
+ rule.insertBefore(anchor, decl);
873
+ } else {
874
+ rule.append(decl);
875
+ }
876
+ }
877
+ }
878
+ const literalSeen = /* @__PURE__ */ new Map();
879
+ for (const node of [...rule.nodes]) {
880
+ if (node.type !== "decl") {
881
+ continue;
882
+ }
883
+ const canonical = getCanonicalProp(node.prop);
884
+ if (!variablePriorityProps.has(canonical)) {
885
+ continue;
886
+ }
887
+ if (hasVariableReference(node.value)) {
888
+ continue;
889
+ }
890
+ const existing = literalSeen.get(canonical);
891
+ if (existing) {
892
+ node.remove();
893
+ } else {
894
+ literalSeen.set(canonical, node);
895
+ }
896
+ }
577
897
  }
578
898
  var postcssWeappTailwindcssPostPlugin = (options) => {
579
899
  const opts = defu(options, {
@@ -582,20 +902,27 @@ var postcssWeappTailwindcssPostPlugin = (options) => {
582
902
  const p = {
583
903
  postcssPlugin
584
904
  };
585
- if (opts.isMainChunk) {
586
- const fallbackRemove = getFallbackRemove(void 0, opts);
905
+ const cleanRootSpecificity = createRootSpecificityCleaner(opts);
906
+ const enableMainChunkTransforms = opts.isMainChunk !== false;
907
+ if (enableMainChunkTransforms || cleanRootSpecificity) {
908
+ const fallbackRemove = enableMainChunkTransforms ? getFallbackRemove(void 0, opts) : void 0;
587
909
  p.RuleExit = (rule) => {
588
- fallbackRemove.transformSync(rule);
589
- dedupeDeclarations(rule);
590
- if (rule.selectors.length === 0 || rule.selectors.length === 1 && rule.selector.trim() === "") {
591
- rule.remove();
910
+ if (enableMainChunkTransforms) {
911
+ fallbackRemove?.transformSync(rule);
592
912
  }
593
- if (opts.uniAppX) {
594
- if (rule.nodes.length === 0) {
913
+ cleanRootSpecificity?.(rule);
914
+ if (enableMainChunkTransforms) {
915
+ dedupeDeclarations(rule);
916
+ if (rule.selectors.length === 0 || rule.selectors.length === 1 && rule.selector.trim() === "") {
917
+ rule.remove();
918
+ }
919
+ if (opts.uniAppX && rule.nodes.length === 0) {
595
920
  rule.remove();
596
921
  }
597
922
  }
598
923
  };
924
+ }
925
+ if (enableMainChunkTransforms) {
599
926
  p.DeclarationExit = (decl) => {
600
927
  if (decl.prop === "--tw-gradient-position" && decl.value.endsWith(OklabSuffix)) {
601
928
  decl.value = decl.value.slice(0, decl.value.length - OklabSuffix.length);
@@ -1146,39 +1473,163 @@ var postcssWeappTailwindcssPrePlugin = (options) => {
1146
1473
  };
1147
1474
  postcssWeappTailwindcssPrePlugin.postcss = true;
1148
1475
 
1149
- // src/plugins/index.ts
1150
- import { default as default2 } from "postcss-rem-to-responsive-pixel";
1151
- function normalizePlugins(options) {
1152
- const plugins = [];
1153
- const pxPlugin = getPxTransformPlugin(options);
1154
- if (pxPlugin) {
1155
- plugins.push(pxPlugin);
1156
- }
1157
- const remPlugin = getRemTransformPlugin(options);
1158
- if (remPlugin) {
1159
- plugins.push(remPlugin);
1160
- }
1161
- const calcPlugin = getCalcPlugin(options);
1162
- if (calcPlugin) {
1163
- plugins.push(calcPlugin);
1164
- }
1165
- const customPropertyCleaner = getCustomPropertyCleaner(options);
1166
- if (customPropertyCleaner) {
1167
- plugins.push(customPropertyCleaner);
1168
- }
1169
- return plugins;
1476
+ // src/pipeline.ts
1477
+ var STAGE_ORDER = ["pre", "normal", "post"];
1478
+ function normalizeUserPlugins(plugins) {
1479
+ if (!plugins) {
1480
+ return [];
1481
+ }
1482
+ if (Array.isArray(plugins)) {
1483
+ return plugins.filter(Boolean);
1484
+ }
1485
+ if (typeof plugins === "object") {
1486
+ return Object.values(plugins).filter(Boolean);
1487
+ }
1488
+ return [];
1489
+ }
1490
+ function createStaticDefinition(id, stage, plugin) {
1491
+ return {
1492
+ id,
1493
+ stage,
1494
+ prepare: () => ({
1495
+ id,
1496
+ stage,
1497
+ createPlugin: () => plugin
1498
+ })
1499
+ };
1500
+ }
1501
+ function createPipelineDefinitions(options) {
1502
+ const stages = {
1503
+ pre: [],
1504
+ normal: [],
1505
+ post: []
1506
+ };
1507
+ const userPlugins = normalizeUserPlugins(options.postcssOptions?.plugins);
1508
+ userPlugins.forEach((plugin, index) => {
1509
+ stages.pre.push(createStaticDefinition(`pre:user-${index}`, "pre", plugin));
1510
+ });
1511
+ stages.pre.push({
1512
+ id: "pre:core",
1513
+ stage: "pre",
1514
+ prepare: () => ({
1515
+ id: "pre:core",
1516
+ stage: "pre",
1517
+ createPlugin: () => postcssWeappTailwindcssPrePlugin(options)
1518
+ })
1519
+ });
1520
+ stages.normal.push({
1521
+ id: "normal:preset-env",
1522
+ stage: "normal",
1523
+ prepare: () => ({
1524
+ id: "normal:preset-env",
1525
+ stage: "normal",
1526
+ createPlugin: () => postcssPresetEnv(options.cssPresetEnv)
1527
+ })
1528
+ });
1529
+ stages.normal.push({
1530
+ id: "normal:px-transform",
1531
+ stage: "normal",
1532
+ prepare: () => {
1533
+ const plugin = getPxTransformPlugin(options);
1534
+ return plugin ? {
1535
+ id: "normal:px-transform",
1536
+ stage: "normal",
1537
+ createPlugin: () => plugin
1538
+ } : void 0;
1539
+ }
1540
+ });
1541
+ stages.normal.push({
1542
+ id: "normal:rem-transform",
1543
+ stage: "normal",
1544
+ prepare: () => {
1545
+ const plugin = getRemTransformPlugin(options);
1546
+ return plugin ? {
1547
+ id: "normal:rem-transform",
1548
+ stage: "normal",
1549
+ createPlugin: () => plugin
1550
+ } : void 0;
1551
+ }
1552
+ });
1553
+ stages.normal.push({
1554
+ id: "normal:calc",
1555
+ stage: "normal",
1556
+ prepare: () => {
1557
+ const plugin = getCalcPlugin(options);
1558
+ return plugin ? {
1559
+ id: "normal:calc",
1560
+ stage: "normal",
1561
+ createPlugin: () => plugin
1562
+ } : void 0;
1563
+ }
1564
+ });
1565
+ stages.normal.push({
1566
+ id: "normal:custom-property-cleaner",
1567
+ stage: "normal",
1568
+ prepare: () => {
1569
+ const plugin = getCustomPropertyCleaner(options);
1570
+ return plugin ? {
1571
+ id: "normal:custom-property-cleaner",
1572
+ stage: "normal",
1573
+ createPlugin: () => plugin
1574
+ } : void 0;
1575
+ }
1576
+ });
1577
+ stages.post.push({
1578
+ id: "post:core",
1579
+ stage: "post",
1580
+ prepare: () => ({
1581
+ id: "post:core",
1582
+ stage: "post",
1583
+ createPlugin: () => postcssWeappTailwindcssPostPlugin(options)
1584
+ })
1585
+ });
1586
+ return STAGE_ORDER.flatMap((stage) => stages[stage]);
1170
1587
  }
1171
- function getPlugins(options) {
1172
- const ctx = createContext();
1173
- options.ctx = ctx;
1174
- const plugins = [
1175
- ...options.postcssOptions?.plugins ?? [],
1176
- postcssWeappTailwindcssPrePlugin(options),
1177
- postcssPresetEnv(options.cssPresetEnv),
1178
- ...normalizePlugins(options),
1179
- postcssWeappTailwindcssPostPlugin(options)
1180
- ].filter(Boolean);
1181
- return plugins;
1588
+ function createStylePipeline(options) {
1589
+ options.ctx = createContext();
1590
+ const preparedNodes = createPipelineDefinitions(options).map((definition) => definition.prepare(options)).filter(Boolean);
1591
+ if (preparedNodes.length === 0) {
1592
+ return {
1593
+ nodes: [],
1594
+ plugins: []
1595
+ };
1596
+ }
1597
+ const stageSizes = /* @__PURE__ */ new Map();
1598
+ preparedNodes.forEach((node) => {
1599
+ stageSizes.set(node.stage, (stageSizes.get(node.stage) ?? 0) + 1);
1600
+ });
1601
+ const stageIndices = /* @__PURE__ */ new Map();
1602
+ const nodes2 = [];
1603
+ const size = preparedNodes.length;
1604
+ preparedNodes.forEach((node, index) => {
1605
+ const stageIndex = stageIndices.get(node.stage) ?? 0;
1606
+ const context = {
1607
+ stage: node.stage,
1608
+ index,
1609
+ size,
1610
+ stageIndex,
1611
+ stageSize: stageSizes.get(node.stage) ?? 0,
1612
+ previous: index > 0 ? {
1613
+ id: preparedNodes[index - 1].id,
1614
+ stage: preparedNodes[index - 1].stage
1615
+ } : void 0,
1616
+ next: index < size - 1 ? {
1617
+ id: preparedNodes[index + 1].id,
1618
+ stage: preparedNodes[index + 1].stage
1619
+ } : void 0
1620
+ };
1621
+ stageIndices.set(node.stage, stageIndex + 1);
1622
+ nodes2.push({
1623
+ id: node.id,
1624
+ stage: node.stage,
1625
+ plugin: node.createPlugin(context),
1626
+ context
1627
+ });
1628
+ });
1629
+ return {
1630
+ nodes: nodes2,
1631
+ plugins: nodes2.map((node) => node.plugin)
1632
+ };
1182
1633
  }
1183
1634
 
1184
1635
  // src/preflight.ts
@@ -1207,16 +1658,16 @@ function createProcessOptions(options) {
1207
1658
  ...options.postcssOptions?.options ?? {}
1208
1659
  };
1209
1660
  }
1210
- var pluginCache = /* @__PURE__ */ new WeakMap();
1661
+ var pipelineCache = /* @__PURE__ */ new WeakMap();
1211
1662
  var processOptionsCache = /* @__PURE__ */ new WeakMap();
1212
1663
  var processOptionsSourceCache = /* @__PURE__ */ new WeakMap();
1213
- function getCachedPlugins(options) {
1214
- let plugins = pluginCache.get(options);
1215
- if (!plugins) {
1216
- plugins = getPlugins(options);
1217
- pluginCache.set(options, plugins);
1664
+ function getCachedPipeline(options) {
1665
+ let pipeline = pipelineCache.get(options);
1666
+ if (!pipeline) {
1667
+ pipeline = createStylePipeline(options);
1668
+ pipelineCache.set(options, pipeline);
1218
1669
  }
1219
- return plugins;
1670
+ return pipeline;
1220
1671
  }
1221
1672
  function getCachedProcessOptions(options) {
1222
1673
  const source = options.postcssOptions?.options;
@@ -1230,7 +1681,7 @@ function getCachedProcessOptions(options) {
1230
1681
  return { ...cached };
1231
1682
  }
1232
1683
  function styleHandler(rawSource, options) {
1233
- const plugins = getCachedPlugins(options);
1684
+ const plugins = getCachedPipeline(options).plugins;
1234
1685
  const processOptions = getCachedProcessOptions(options);
1235
1686
  return postcss(plugins).process(
1236
1687
  rawSource,
@@ -1243,18 +1694,27 @@ function createStyleHandler(options) {
1243
1694
  getDefaultOptions(options)
1244
1695
  );
1245
1696
  cachedOptions.cssInjectPreflight = createInjectPreflight(cachedOptions.cssPreflight);
1246
- getCachedPlugins(cachedOptions);
1697
+ getCachedPipeline(cachedOptions);
1247
1698
  getCachedProcessOptions(cachedOptions);
1248
- return (rawSource, opt) => {
1699
+ const handler = ((rawSource, opt) => {
1249
1700
  const resolvedOptions = defuOverrideArray3(opt, cachedOptions);
1250
1701
  return styleHandler(
1251
1702
  rawSource,
1252
1703
  resolvedOptions
1253
1704
  );
1705
+ });
1706
+ handler.getPipeline = (opt) => {
1707
+ if (!opt) {
1708
+ return getCachedPipeline(cachedOptions);
1709
+ }
1710
+ const resolvedOptions = defuOverrideArray3(opt, cachedOptions);
1711
+ return getCachedPipeline(resolvedOptions);
1254
1712
  };
1713
+ return handler;
1255
1714
  }
1256
1715
  export {
1257
1716
  createInjectPreflight,
1258
1717
  createStyleHandler,
1718
+ createStylePipeline,
1259
1719
  internalCssSelectorReplacer
1260
1720
  };