@weapp-tailwindcss/postcss 2.2.1-next.5 → 3.0.0-next.7

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
@@ -13,7 +13,8 @@ import autoprefixerPlugin from "autoprefixer";
13
13
  import postcssCalc from "@weapp-tailwindcss/postcss-calc";
14
14
  import postcssPxtrans from "postcss-pxtrans";
15
15
  import postcssRem2rpx from "postcss-rem-to-responsive-pixel";
16
- import postcssUnitConverter, { presets } from "postcss-rule-unit-converter";
16
+ import process from "node:process";
17
+ import postcssUnitConverter, { composeRules as unitConversionComposeRules, presets, presets as unitConversionPresets } from "postcss-rule-unit-converter";
17
18
  import { MappingChars2String, escape } from "@weapp-core/escape";
18
19
  //#region src/compat/color-mix.ts
19
20
  const COLOR_MIX_NAME = "color-mix";
@@ -264,6 +265,72 @@ function protectDynamicColorMixAlpha(css, options = {}) {
264
265
  };
265
266
  }
266
267
  //#endregion
268
+ //#region src/compat/mini-program-css/at-rules.ts
269
+ const MINI_PROGRAM_UNSUPPORTED_AT_RULES = new Set(["property", "supports"]);
270
+ function removeAtRulesByScan(css, names) {
271
+ let index = 0;
272
+ let result = "";
273
+ const atRulePattern = new RegExp(`@(?:${[...names].join("|")})\\b`, "i");
274
+ while (index < css.length) {
275
+ const match = atRulePattern.exec(css.slice(index));
276
+ if (!match || match.index === void 0) {
277
+ result += css.slice(index);
278
+ break;
279
+ }
280
+ const start = index + match.index;
281
+ result += css.slice(index, start);
282
+ const blockStart = css.indexOf("{", start);
283
+ if (blockStart === -1) {
284
+ result += css.slice(start);
285
+ break;
286
+ }
287
+ let depth = 0;
288
+ let cursor = blockStart;
289
+ for (; cursor < css.length; cursor++) {
290
+ const char = css[cursor];
291
+ if (char === "{") depth++;
292
+ else if (char === "}") {
293
+ depth--;
294
+ if (depth === 0) {
295
+ cursor++;
296
+ break;
297
+ }
298
+ }
299
+ }
300
+ index = cursor;
301
+ }
302
+ return result;
303
+ }
304
+ function removeUnsupportedMiniProgramAtRules(css) {
305
+ try {
306
+ const root = postcss.parse(css);
307
+ root.walkAtRules((atRule) => {
308
+ if (MINI_PROGRAM_UNSUPPORTED_AT_RULES.has(atRule.name)) atRule.remove();
309
+ });
310
+ root.walkAtRules((atRule) => {
311
+ if (atRule.nodes && atRule.nodes.length === 0) atRule.remove();
312
+ });
313
+ return root.toString();
314
+ } catch {
315
+ return removeAtRulesByScan(css, MINI_PROGRAM_UNSUPPORTED_AT_RULES);
316
+ }
317
+ }
318
+ function removeUnsupportedAtSupports(css) {
319
+ return removeUnsupportedMiniProgramAtRules(css);
320
+ }
321
+ /**
322
+ * 移除小程序不支持的 cascade layer 语法,同时保留 layer 内的实际规则。
323
+ */
324
+ function removeUnsupportedCascadeLayers(root) {
325
+ root.walkAtRules("layer", (atRule) => {
326
+ if (!atRule.nodes || atRule.nodes.length === 0) {
327
+ atRule.remove();
328
+ return;
329
+ }
330
+ atRule.replaceWith(...atRule.nodes);
331
+ });
332
+ }
333
+ //#endregion
267
334
  //#region src/compat/mini-program-prefixes.ts
268
335
  const PRESERVED_WEBKIT_DECLARATION_PROPS = new Set([
269
336
  "-webkit-box-orient",
@@ -276,7 +343,7 @@ const PRESERVED_WEBKIT_DECLARATION_PROPS = new Set([
276
343
  ]);
277
344
  const PRESERVED_WEBKIT_VALUE_DECLARATIONS = new Map([["display", new Set(["-webkit-box"])], ["-webkit-background-clip", new Set(["text"])]]);
278
345
  const TRANSITION_PROPS = new Set(["transition", "transition-property"]);
279
- function splitTopLevelCommaList(value) {
346
+ function splitTopLevelCommaList$1(value) {
280
347
  const parts = [];
281
348
  let start = 0;
282
349
  let depth = 0;
@@ -323,7 +390,7 @@ function isPreservedWebkitDeclaration(decl) {
323
390
  return PRESERVED_WEBKIT_VALUE_DECLARATIONS.get(prop)?.has(decl.value.trim().toLowerCase()) ?? false;
324
391
  }
325
392
  function normalizeTransitionValue(value) {
326
- return splitTopLevelCommaList(value).map((part) => part.trim()).filter((part) => part.length > 0 && !part.toLowerCase().startsWith("-webkit-")).join(", ");
393
+ return splitTopLevelCommaList$1(value).map((part) => part.trim()).filter((part) => part.length > 0 && !part.toLowerCase().startsWith("-webkit-")).join(", ");
327
394
  }
328
395
  function hasUnsupportedWebkitKeywordValue(decl) {
329
396
  const value = decl.value.trim().toLowerCase();
@@ -354,6 +421,506 @@ function removeUnsupportedMiniProgramPrefixedAtRule(atRule) {
354
421
  if (atRule.name.toLowerCase() === "-webkit-keyframes") atRule.remove();
355
422
  }
356
423
  //#endregion
424
+ //#region src/compat/mini-program-css/color-gamut.ts
425
+ const DISPLAY_P3_VALUE_RE$1 = /color\(\s*display-p3\b/i;
426
+ const COLOR_GAMUT_P3_RE$1 = /\(\s*color-gamut\s*:\s*p3\s*\)/i;
427
+ function isDisplayP3MediaRule(atRule) {
428
+ return atRule.name === "media" && COLOR_GAMUT_P3_RE$1.test(atRule.params);
429
+ }
430
+ function isDisplayP3Declaration(decl) {
431
+ return DISPLAY_P3_VALUE_RE$1.test(decl.value);
432
+ }
433
+ //#endregion
434
+ //#region src/compat/mini-program-css/selectors.ts
435
+ const MINI_PROGRAM_THEME_SCOPE_SELECTOR = ":host,page,.tw-root,wx-root-portal-content";
436
+ const MINI_PROGRAM_PREFLIGHT_SELECTORS = new Set([
437
+ "*",
438
+ "view",
439
+ "text",
440
+ ":before",
441
+ ":after",
442
+ "::before",
443
+ "::after"
444
+ ]);
445
+ const MINI_PROGRAM_THEME_SCOPE_SELECTORS = new Set([
446
+ ":host",
447
+ ":root",
448
+ "page",
449
+ ".tw-root",
450
+ "wx-root-portal-content"
451
+ ]);
452
+ const SPECIFICITY_PLACEHOLDER_SUFFIXES = [":not(#n)", ":not(#\\#)"];
453
+ const MINI_PROGRAM_UNSUPPORTED_BROWSER_SELECTORS = new Set([
454
+ ":-moz-focusring",
455
+ ":-moz-ui-invalid",
456
+ "::-webkit-calendar-picker-indicator",
457
+ "::-webkit-date-and-time-value",
458
+ "::-webkit-datetime-edit",
459
+ "::-webkit-datetime-edit-day-field",
460
+ "::-webkit-datetime-edit-fields-wrapper",
461
+ "::-webkit-datetime-edit-hour-field",
462
+ "::-webkit-datetime-edit-meridiem-field",
463
+ "::-webkit-datetime-edit-millisecond-field",
464
+ "::-webkit-datetime-edit-minute-field",
465
+ "::-webkit-datetime-edit-month-field",
466
+ "::-webkit-datetime-edit-second-field",
467
+ "::-webkit-datetime-edit-year-field",
468
+ "::-webkit-inner-spin-button",
469
+ "::-webkit-input-placeholder",
470
+ "::-webkit-outer-spin-button",
471
+ "::-webkit-search-decoration",
472
+ "::placeholder",
473
+ "[hidden]:where(:not([hidden='until-found']))"
474
+ ]);
475
+ const MINI_PROGRAM_UNSUPPORTED_BROWSER_TAG_SELECTORS = new Set([
476
+ "a",
477
+ "abbr:where([title])",
478
+ "audio",
479
+ "b",
480
+ "button",
481
+ "canvas",
482
+ "code",
483
+ "embed",
484
+ "h1",
485
+ "h2",
486
+ "h3",
487
+ "h4",
488
+ "h5",
489
+ "h6",
490
+ "hr",
491
+ "html",
492
+ "iframe",
493
+ "img",
494
+ "input",
495
+ "input:where([type='button'],[type='reset'],[type='submit'])",
496
+ "kbd",
497
+ "menu",
498
+ "object",
499
+ "ol",
500
+ "optgroup",
501
+ "pre",
502
+ "progress",
503
+ "samp",
504
+ "select",
505
+ "select[multiple]optgroup",
506
+ "select[multiple]optgroupoption",
507
+ "select[size]optgroup",
508
+ "select[size]optgroupoption",
509
+ "small",
510
+ "strong",
511
+ "sub",
512
+ "summary",
513
+ "sup",
514
+ "svg",
515
+ "table",
516
+ "textarea",
517
+ "ul",
518
+ "video"
519
+ ]);
520
+ function normalizeSelector$1(selector) {
521
+ return selector.trim().replace(/\s+/g, "");
522
+ }
523
+ function getRuleSelectors(rule) {
524
+ return rule.selector.split(",").map(normalizeSelector$1).filter(Boolean);
525
+ }
526
+ function isUnsupportedBrowserSelector(selector) {
527
+ const normalized = normalizeSelector$1(selector);
528
+ return MINI_PROGRAM_UNSUPPORTED_BROWSER_SELECTORS.has(normalized) || MINI_PROGRAM_UNSUPPORTED_BROWSER_TAG_SELECTORS.has(normalized);
529
+ }
530
+ function isMiniProgramPreflightSelector(selectors) {
531
+ return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_PREFLIGHT_SELECTORS.has(selector)) && selectors.some((selector) => selector === "*" || selector === ":before" || selector === ":after" || selector === "::before" || selector === "::after");
532
+ }
533
+ function isMiniProgramThemeScopeSelector(selectors) {
534
+ return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_THEME_SCOPE_SELECTORS.has(selector));
535
+ }
536
+ //#endregion
537
+ //#region src/compat/mini-program-css/predicates.ts
538
+ const PREFLIGHT_RESET_PROPS = new Set([
539
+ "box-sizing",
540
+ "border",
541
+ "border-width",
542
+ "border-style",
543
+ "border-color",
544
+ "margin",
545
+ "padding"
546
+ ]);
547
+ const PSEUDO_CONTENT_SELECTOR_RE = /^(?:::before|::after|:before|:after)(?:,(?:::before|::after|:before|:after))*$/;
548
+ const TW_CONTENT_VAR_RE$1 = /var\(\s*--tw-content\b/;
549
+ function hasTailwindPreflightDeclaration(rule) {
550
+ let hasTailwindVar = false;
551
+ let hasResetProp = false;
552
+ rule.walkDecls((decl) => {
553
+ if (decl.prop.startsWith("--tw-")) hasTailwindVar = true;
554
+ if (PREFLIGHT_RESET_PROPS.has(decl.prop)) hasResetProp = true;
555
+ });
556
+ return hasTailwindVar || hasResetProp;
557
+ }
558
+ function hasTwContentDeclaration(rule) {
559
+ let hasContentInit = false;
560
+ rule.walkDecls("--tw-content", () => {
561
+ hasContentInit = true;
562
+ });
563
+ return hasContentInit;
564
+ }
565
+ function isCustomPropertyRule(rule) {
566
+ let hasDeclaration = false;
567
+ let allCustomProperties = true;
568
+ rule.each((node) => {
569
+ if (node.type !== "decl") return;
570
+ hasDeclaration = true;
571
+ if (!node.prop.startsWith("--")) allCustomProperties = false;
572
+ });
573
+ return hasDeclaration && allCustomProperties;
574
+ }
575
+ function isEmptyTwContentDeclaration(decl) {
576
+ return decl.prop === "--tw-content" && (decl.value === "\"\"" || decl.value === "''");
577
+ }
578
+ function isOnlyTwContentDeclarations(rule) {
579
+ let hasDeclaration = false;
580
+ let onlyContentVariable = true;
581
+ rule.walkDecls((decl) => {
582
+ hasDeclaration = true;
583
+ if (decl.prop !== "--tw-content") onlyContentVariable = false;
584
+ });
585
+ return hasDeclaration && onlyContentVariable;
586
+ }
587
+ function isPseudoContentInitRule(rule) {
588
+ const selector = rule.selector.replace(/\s+/g, "");
589
+ return PSEUDO_CONTENT_SELECTOR_RE.test(selector) && isOnlyTwContentDeclarations(rule);
590
+ }
591
+ function usesTwContentVariable(root) {
592
+ let used = false;
593
+ root.walkDecls((decl) => {
594
+ if (TW_CONTENT_VAR_RE$1.test(decl.value)) used = true;
595
+ });
596
+ return used;
597
+ }
598
+ function isMiniProgramPreflightRule(node) {
599
+ if (node.type !== "rule") return false;
600
+ return isMiniProgramPreflightSelector(getRuleSelectors(node)) && hasTailwindPreflightDeclaration(node);
601
+ }
602
+ function isMiniProgramThemeVariableRule(node) {
603
+ if (node.type !== "rule") return false;
604
+ return isMiniProgramThemeScopeSelector(getRuleSelectors(node)) && isCustomPropertyRule(node);
605
+ }
606
+ //#endregion
607
+ //#region src/compat/mini-program-css/root-cleanups.ts
608
+ function removeSpecificityPlaceholders(root) {
609
+ root.walkRules((rule) => {
610
+ if (!rule.selectors || rule.selectors.length === 0) return;
611
+ let changed = false;
612
+ const selectors = rule.selectors.map((selector) => {
613
+ let next = selector;
614
+ for (const suffix of SPECIFICITY_PLACEHOLDER_SUFFIXES) if (next.includes(suffix)) next = next.split(suffix).join("");
615
+ if (next !== selector) changed = true;
616
+ return next;
617
+ });
618
+ if (changed) rule.selectors = selectors;
619
+ });
620
+ }
621
+ function removeEmptyAtRuleAncestors(parent) {
622
+ while (parent?.type === "atrule" && (!parent.nodes || parent.nodes.length === 0)) {
623
+ const nextParent = parent.parent;
624
+ parent.remove();
625
+ parent = nextParent?.type === "atrule" ? nextParent : void 0;
626
+ }
627
+ }
628
+ function removeUnsupportedBrowserSelectors(root) {
629
+ root.walkRules((rule) => {
630
+ if (!rule.selectors || rule.selectors.length === 0) return;
631
+ const selectors = rule.selectors.filter((selector) => !isUnsupportedBrowserSelector(selector));
632
+ if (selectors.length === rule.selectors.length) return;
633
+ if (selectors.length === 0) {
634
+ const parent = rule.parent;
635
+ rule.remove();
636
+ removeEmptyAtRuleAncestors(parent);
637
+ return;
638
+ }
639
+ rule.selectors = selectors;
640
+ });
641
+ }
642
+ function removeDeclarationAndEmptyRule$1(decl) {
643
+ const parent = decl.parent;
644
+ decl.remove();
645
+ if (parent?.type === "rule" && parent.nodes.length === 0) {
646
+ const ruleParent = parent.parent;
647
+ parent.remove();
648
+ removeEmptyAtRuleAncestors(ruleParent);
649
+ }
650
+ }
651
+ function removeDisplayP3Declarations(root) {
652
+ root.walkAtRules((atRule) => {
653
+ if (isDisplayP3MediaRule(atRule)) {
654
+ const parent = atRule.parent;
655
+ atRule.remove();
656
+ removeEmptyAtRuleAncestors(parent);
657
+ }
658
+ });
659
+ }
660
+ function removeUnsupportedModernColorDeclarations(root) {
661
+ const customPropertyValues = /* @__PURE__ */ new Map();
662
+ root.walkDecls((decl) => {
663
+ if (decl.prop.startsWith("--")) customPropertyValues.set(decl.prop, decl.value.trim());
664
+ });
665
+ root.walkDecls((decl) => {
666
+ const normalized = normalizeModernColorValue(decl.value, customPropertyValues);
667
+ if (normalized.changed) {
668
+ decl.value = normalized.value;
669
+ if (decl.prop.startsWith("--")) customPropertyValues.set(decl.prop, decl.value.trim());
670
+ }
671
+ if (normalized.hasUnsupported) removeDeclarationAndEmptyRule$1(decl);
672
+ });
673
+ }
674
+ //#endregion
675
+ //#region src/compat/mini-program-css/finalize.ts
676
+ const HOIST_ANCHOR_COMMENT = "__weapp_tailwindcss_base_anchor__";
677
+ function createPseudoContentInitRule() {
678
+ const rule = postcss.rule({ selector: "::before,\n::after" });
679
+ rule.append({
680
+ prop: "--tw-content",
681
+ value: "''"
682
+ });
683
+ return rule;
684
+ }
685
+ function collectPreflightRules(root, options = {}) {
686
+ const preflightNodes = [];
687
+ let hasContentInit = false;
688
+ for (const node of root.nodes ?? []) if (isMiniProgramPreflightRule(node)) {
689
+ preflightNodes.push(node);
690
+ if (hasTwContentDeclaration(node)) hasContentInit = true;
691
+ }
692
+ if (preflightNodes.length === 0) return [];
693
+ const clonedPreflightRules = preflightNodes.map((node) => node.clone());
694
+ const contentInitRules = options.preservePseudoContentInit ? clonedPreflightRules.filter((rule) => hasTwContentDeclaration(rule)) : [];
695
+ const otherPreflightRules = clonedPreflightRules.filter((rule) => !hasTwContentDeclaration(rule));
696
+ const preflightRules = hasContentInit ? [...contentInitRules, ...otherPreflightRules] : [...options.preservePseudoContentInit ? [createPseudoContentInitRule()] : [], ...otherPreflightRules];
697
+ for (const node of preflightNodes) node.remove();
698
+ return preflightRules;
699
+ }
700
+ function createPreflightResetRule(cssPreflight) {
701
+ if (!cssPreflight || typeof cssPreflight !== "object") return;
702
+ const rule = postcss.rule({ selector: "view,text,:after,:before" });
703
+ for (const [prop, value] of Object.entries(cssPreflight)) {
704
+ if (value === false) continue;
705
+ rule.append({
706
+ prop,
707
+ value: value.toString()
708
+ });
709
+ }
710
+ return rule.nodes?.length ? rule : void 0;
711
+ }
712
+ function collectThemeVariableRule(root, options = {}) {
713
+ const themeRules = [];
714
+ const declarations = /* @__PURE__ */ new Map();
715
+ const shouldPreserveContentInit = options.preservePseudoContentInit || usesTwContentVariable(root);
716
+ for (const node of root.nodes ?? []) {
717
+ if (!isMiniProgramThemeVariableRule(node)) continue;
718
+ themeRules.push(node);
719
+ node.walkDecls((decl) => {
720
+ if (isDisplayP3Declaration(decl)) return;
721
+ if (!shouldPreserveContentInit && isEmptyTwContentDeclaration(decl)) return;
722
+ declarations.set(decl.prop, decl.clone());
723
+ });
724
+ }
725
+ for (const rule of themeRules) rule.remove();
726
+ if (declarations.size === 0) return;
727
+ const rule = postcss.rule({ selector: MINI_PROGRAM_THEME_SCOPE_SELECTOR });
728
+ for (const decl of declarations.values()) rule.append(decl);
729
+ return rule;
730
+ }
731
+ function getTopDirectiveTail(root) {
732
+ let tail;
733
+ for (const node of root.nodes ?? []) {
734
+ if (node.type === "atrule" && (node.name === "charset" || node.name === "import")) {
735
+ tail = node;
736
+ continue;
737
+ }
738
+ break;
739
+ }
740
+ return tail;
741
+ }
742
+ function createHoistInsertionAnchor(root) {
743
+ for (const node of root.nodes ?? []) if (isMiniProgramPreflightRule(node) || isMiniProgramThemeVariableRule(node)) {
744
+ const anchor = postcss.comment({ text: HOIST_ANCHOR_COMMENT });
745
+ node.before(anchor);
746
+ return anchor;
747
+ }
748
+ }
749
+ function insertHoistedRules(root, rules, anchor) {
750
+ if (anchor && !anchor.parent) anchor = void 0;
751
+ if (rules.length === 0) {
752
+ anchor?.remove();
753
+ return;
754
+ }
755
+ const topDirectiveTail = getTopDirectiveTail(root);
756
+ const firstRule = rules[0];
757
+ if (!firstRule) return;
758
+ if (anchor) {
759
+ if (anchor.raws.before === void 0) delete firstRule.raws.before;
760
+ else firstRule.raws.before = anchor.raws.before;
761
+ anchor.replaceWith(rules);
762
+ return;
763
+ }
764
+ firstRule.raws.before = topDirectiveTail ? "\n" : "";
765
+ if (topDirectiveTail) topDirectiveTail.after(rules);
766
+ else root.prepend(rules);
767
+ }
768
+ function unwrapTailwindSourceMedia(root) {
769
+ root.walkAtRules("media", (atRule) => {
770
+ if (atRule.params.startsWith("source(") && atRule.nodes && atRule.nodes.length > 0) atRule.replaceWith(...atRule.nodes);
771
+ });
772
+ }
773
+ function finalizeMiniProgramCssRoot(root, options = {}) {
774
+ removeUnsupportedCascadeLayers(root);
775
+ unwrapTailwindSourceMedia(root);
776
+ root.walkAtRules("property", (atRule) => {
777
+ atRule.remove();
778
+ });
779
+ removeSpecificityPlaceholders(root);
780
+ removeUnsupportedBrowserSelectors(root);
781
+ removeDisplayP3Declarations(root);
782
+ removeUnsupportedModernColorDeclarations(root);
783
+ root.walkDecls((decl) => {
784
+ normalizeMiniProgramPrefixedDeclaration(decl);
785
+ });
786
+ root.walkAtRules((atRule) => {
787
+ removeUnsupportedMiniProgramPrefixedAtRule(atRule);
788
+ });
789
+ const hoistAnchor = createHoistInsertionAnchor(root);
790
+ const preflightRules = collectPreflightRules(root, options);
791
+ if (preflightRules.length === 0) {
792
+ const resetRule = createPreflightResetRule(options.cssPreflight);
793
+ if (resetRule) preflightRules.push(resetRule);
794
+ }
795
+ const themeRule = collectThemeVariableRule(root, options);
796
+ insertHoistedRules(root, themeRule ? [...preflightRules, themeRule] : preflightRules, hoistAnchor);
797
+ }
798
+ function hoistTailwindPreflightBase(css) {
799
+ try {
800
+ const root = postcss.parse(css);
801
+ insertHoistedRules(root, collectPreflightRules(root, { preservePseudoContentInit: true }));
802
+ return root.toString();
803
+ } catch {
804
+ return css;
805
+ }
806
+ }
807
+ function finalizeMiniProgramCss(css, options = {}) {
808
+ const cleanedCss = removeUnsupportedMiniProgramAtRules(css);
809
+ try {
810
+ const root = postcss.parse(cleanedCss);
811
+ finalizeMiniProgramCssRoot(root, options);
812
+ return root.toString();
813
+ } catch {
814
+ return cleanedCss;
815
+ }
816
+ }
817
+ //#endregion
818
+ //#region src/compat/mini-program-css/prune-generated.ts
819
+ const DEFAULT_WEAPP_VARIABLE_SCOPE = "page,.tw-root,wx-root-portal-content,:host";
820
+ const DEFAULT_WEAPP_ELEMENT_VARIABLE_SCOPE = "view,text,:before,:after";
821
+ const CLASS_SELECTOR_RE$1 = /(?:^|[^\w-])\.[_a-z\u00A0-\uFFFF\\-]/i;
822
+ const MINI_PROGRAM_ELEMENT_VARIABLE_SCOPE_SELECTORS = new Set([
823
+ "view",
824
+ "text",
825
+ ":before",
826
+ ":after",
827
+ "::before",
828
+ "::after"
829
+ ]);
830
+ function isConditionalCompilationComment(text) {
831
+ return /#(?:ifn?def|endif)\b/.test(text);
832
+ }
833
+ function hasClassSelector$2(selector) {
834
+ return CLASS_SELECTOR_RE$1.test(selector);
835
+ }
836
+ function removeEmptyContentInitDeclarations(rule) {
837
+ rule.walkDecls((decl) => {
838
+ if (isEmptyTwContentDeclaration(decl)) decl.remove();
839
+ });
840
+ }
841
+ function isMiniProgramElementVariableScopeRule(rule) {
842
+ const selectors = getRuleSelectors(rule);
843
+ return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_ELEMENT_VARIABLE_SCOPE_SELECTORS.has(selector));
844
+ }
845
+ function isTailwindV4GradientRuntimeDeclaration(decl) {
846
+ return decl.prop.startsWith("--tw-gradient-");
847
+ }
848
+ function moveTailwindV4GradientRuntimeDeclarations(rule) {
849
+ const gradientDeclarations = [];
850
+ rule.walkDecls((decl) => {
851
+ if (isTailwindV4GradientRuntimeDeclaration(decl)) {
852
+ gradientDeclarations.push(decl.clone());
853
+ decl.remove();
854
+ }
855
+ });
856
+ if (gradientDeclarations.length > 0) rule.before(new postcss.Rule({
857
+ selector: DEFAULT_WEAPP_ELEMENT_VARIABLE_SCOPE,
858
+ nodes: gradientDeclarations
859
+ }));
860
+ if (rule.nodes.length === 0) rule.remove();
861
+ }
862
+ function isKeyframesRule(rule) {
863
+ let parent = rule.parent;
864
+ while (parent) {
865
+ if (parent.type === "atrule" && parent.name.endsWith("keyframes")) return true;
866
+ parent = parent.parent;
867
+ }
868
+ return false;
869
+ }
870
+ /**
871
+ * 裁剪 Tailwind 生成 CSS 中面向浏览器的 classless 规则。
872
+ */
873
+ function pruneMiniProgramGeneratedCss(css, options = {}) {
874
+ const root = postcss.parse(css);
875
+ const shouldPreserveContentInit = options.preservePreflight || usesTwContentVariable(root);
876
+ root.walkComments((comment) => {
877
+ if (options.preserveConditionalComments && isConditionalCompilationComment(comment.text)) return;
878
+ comment.remove();
879
+ });
880
+ removeUnsupportedCascadeLayers(root);
881
+ removeUnsupportedModernColorDeclarations(root);
882
+ root.walkAtRules("supports", (atRule) => {
883
+ atRule.remove();
884
+ });
885
+ root.walkAtRules((atRule) => {
886
+ removeUnsupportedMiniProgramPrefixedAtRule(atRule);
887
+ });
888
+ root.walkDecls((decl) => {
889
+ normalizeMiniProgramPrefixedDeclaration(decl);
890
+ });
891
+ root.walkRules((rule) => {
892
+ if (isKeyframesRule(rule)) return;
893
+ if (isCustomPropertyRule(rule) && isMiniProgramElementVariableScopeRule(rule)) {
894
+ rule.selector = DEFAULT_WEAPP_ELEMENT_VARIABLE_SCOPE;
895
+ return;
896
+ }
897
+ if (isMiniProgramThemeVariableRule(rule)) {
898
+ moveTailwindV4GradientRuntimeDeclarations(rule);
899
+ if (!rule.parent) return;
900
+ rule.selector = DEFAULT_WEAPP_VARIABLE_SCOPE;
901
+ return;
902
+ }
903
+ if (hasClassSelector$2(rule.selector)) return;
904
+ if (!shouldPreserveContentInit) removeEmptyContentInitDeclarations(rule);
905
+ if (isPseudoContentInitRule(rule)) {
906
+ if (!shouldPreserveContentInit) rule.remove();
907
+ return;
908
+ }
909
+ if (options.preservePreflight && isMiniProgramPreflightRule(rule)) return;
910
+ if (isCustomPropertyRule(rule)) {
911
+ moveTailwindV4GradientRuntimeDeclarations(rule);
912
+ if (!rule.parent) return;
913
+ rule.selector = DEFAULT_WEAPP_VARIABLE_SCOPE;
914
+ return;
915
+ }
916
+ rule.remove();
917
+ });
918
+ root.walkAtRules((atRule) => {
919
+ if (!atRule.nodes || atRule.nodes.length === 0) atRule.remove();
920
+ });
921
+ return root.toString();
922
+ }
923
+ //#endregion
357
924
  //#region src/compat/uni-app-x.ts
358
925
  const UNI_APP_X_BASE_CARRIER_SELECTORS = new Set([
359
926
  "*",
@@ -630,6 +1197,8 @@ function getSimpleOverrideCacheKey(options) {
630
1197
  let rem2rpx = SIMPLE_OVERRIDE_UNSET;
631
1198
  let px2rpx = SIMPLE_OVERRIDE_UNSET;
632
1199
  let unitsToPx = SIMPLE_OVERRIDE_UNSET;
1200
+ let unitConversion = SIMPLE_OVERRIDE_UNSET;
1201
+ let platform = SIMPLE_OVERRIDE_UNSET;
633
1202
  let cssCalc = SIMPLE_OVERRIDE_UNSET;
634
1203
  let cssChildCombinatorReplaceValue = SIMPLE_OVERRIDE_UNSET;
635
1204
  let cssPreflight = SIMPLE_OVERRIDE_UNSET;
@@ -677,6 +1246,14 @@ function getSimpleOverrideCacheKey(options) {
677
1246
  if (typeof value !== "boolean") return;
678
1247
  unitsToPx = value ? "1" : "0";
679
1248
  break;
1249
+ case "unitConversion":
1250
+ if (value !== false) return;
1251
+ unitConversion = "0";
1252
+ break;
1253
+ case "platform":
1254
+ if (typeof value !== "string") return;
1255
+ platform = value;
1256
+ break;
680
1257
  case "cssCalc":
681
1258
  if (typeof value !== "boolean") return;
682
1259
  cssCalc = value ? "1" : "0";
@@ -708,6 +1285,8 @@ function getSimpleOverrideCacheKey(options) {
708
1285
  rem2rpx,
709
1286
  px2rpx,
710
1287
  unitsToPx,
1288
+ unitConversion,
1289
+ platform,
711
1290
  cssCalc,
712
1291
  cssChildCombinatorReplaceValue,
713
1292
  cssPreflight,
@@ -896,7 +1475,24 @@ function getCalcDuplicateCleaner(options) {
896
1475
  return calcDuplicateCleanerPlugin;
897
1476
  }
898
1477
  //#endregion
899
- //#region ../../node_modules/.pnpm/es-toolkit@1.46.1/node_modules/es-toolkit/dist/object/omit.mjs
1478
+ //#region ../../node_modules/.pnpm/es-toolkit@1.47.0/node_modules/es-toolkit/dist/object/omit.mjs
1479
+ /**
1480
+ * Creates a new object with specified keys omitted.
1481
+ *
1482
+ * This function takes an object and an array of keys, and returns a new object that
1483
+ * excludes the properties corresponding to the specified keys.
1484
+ *
1485
+ * @template T - The type of object.
1486
+ * @template K - The type of keys in object.
1487
+ * @param {T} obj - The object to omit keys from.
1488
+ * @param {K[]} keys - An array of keys to be omitted from the object.
1489
+ * @returns {Omit<T, K>} A new object with the specified keys omitted.
1490
+ *
1491
+ * @example
1492
+ * const obj = { a: 1, b: 2, c: 3 };
1493
+ * const result = omit(obj, ['b', 'c']);
1494
+ * // result will be { a: 1 }
1495
+ */
900
1496
  function omit(obj, keys) {
901
1497
  const result = { ...obj };
902
1498
  for (let i = 0; i < keys.length; i++) {
@@ -985,6 +1581,110 @@ function getRemTransformPlugin(options) {
985
1581
  return postcssRem2rpx(defuOverrideArray(options.rem2rpx, defaultStage));
986
1582
  }
987
1583
  //#endregion
1584
+ //#region src/plugins/getUnitConversionPlugin.ts
1585
+ const DEFAULT_PLATFORM_KEYS = ["default", "*"];
1586
+ const PLATFORM_ENV_KEYS = [
1587
+ "WEAPP_TW_TARGET",
1588
+ "WEAPP_TAILWINDCSS_TARGET",
1589
+ "UNI_PLATFORM",
1590
+ "UNI_UTS_PLATFORM",
1591
+ "TARO_ENV",
1592
+ "MPX_CLI_MODE",
1593
+ "MPX_CURRENT_TARGET_MODE"
1594
+ ];
1595
+ const PLATFORM_ALIASES = {
1596
+ "weapp": [
1597
+ "mp-weixin",
1598
+ "weixin",
1599
+ "wechat",
1600
+ "wx",
1601
+ "mp"
1602
+ ],
1603
+ "mp-weixin": [
1604
+ "weapp",
1605
+ "weixin",
1606
+ "wechat",
1607
+ "wx",
1608
+ "mp"
1609
+ ],
1610
+ "wx": [
1611
+ "weapp",
1612
+ "mp-weixin",
1613
+ "weixin",
1614
+ "wechat",
1615
+ "mp"
1616
+ ],
1617
+ "h5": ["web"],
1618
+ "web": ["h5"],
1619
+ "app": [
1620
+ "app-plus",
1621
+ "app-android",
1622
+ "app-ios",
1623
+ "android",
1624
+ "ios"
1625
+ ],
1626
+ "app-plus": ["app"],
1627
+ "app-android": ["app", "android"],
1628
+ "app-ios": ["app", "ios"],
1629
+ "android": ["app", "app-android"],
1630
+ "ios": ["app", "app-ios"]
1631
+ };
1632
+ function normalizePlatform(value) {
1633
+ return value?.trim().toLowerCase() || void 0;
1634
+ }
1635
+ function readEnvValue(key) {
1636
+ return typeof process === "undefined" ? void 0 : process.env[key];
1637
+ }
1638
+ function resolveUnitConversionPlatform(options) {
1639
+ const explicit = normalizePlatform(options.platform);
1640
+ if (explicit) return explicit;
1641
+ for (const key of PLATFORM_ENV_KEYS) {
1642
+ const value = normalizePlatform(readEnvValue(key));
1643
+ if (value) return value;
1644
+ }
1645
+ }
1646
+ function isPlatformUnitConversionOptions(options) {
1647
+ return Boolean(options && typeof options === "object" && "platforms" in options);
1648
+ }
1649
+ function hasRules(config) {
1650
+ return Array.isArray(config.rules) && config.rules.length > 0;
1651
+ }
1652
+ function getPlatformCandidateKeys(platform) {
1653
+ if (!platform) return [];
1654
+ const normalized = normalizePlatform(platform);
1655
+ if (!normalized) return [];
1656
+ return [normalized, ...PLATFORM_ALIASES[normalized] ?? []];
1657
+ }
1658
+ function getPlatformConfig(platforms, key) {
1659
+ if (Object.hasOwn(platforms, key)) return platforms[key];
1660
+ for (const [platform, config] of Object.entries(platforms)) if (normalizePlatform(platform) === key) return config;
1661
+ }
1662
+ function resolvePlatformConfig(options, platform) {
1663
+ if (!isPlatformUnitConversionOptions(options)) return options;
1664
+ const platforms = options.platforms;
1665
+ for (const key of getPlatformCandidateKeys(platform)) {
1666
+ const config = getPlatformConfig(platforms, key);
1667
+ if (config !== void 0) return config;
1668
+ }
1669
+ if (options.default !== void 0) return options.default;
1670
+ for (const key of DEFAULT_PLATFORM_KEYS) {
1671
+ const config = getPlatformConfig(platforms, key);
1672
+ if (config !== void 0) return config;
1673
+ }
1674
+ }
1675
+ function resolveUnitConversionConfig(options) {
1676
+ const unitConversion = options.unitConversion;
1677
+ if (!unitConversion || unitConversion === false) return;
1678
+ const config = resolvePlatformConfig(unitConversion, resolveUnitConversionPlatform(options));
1679
+ if (!config || config === false || config.disabled || !hasRules(config)) return;
1680
+ return config;
1681
+ }
1682
+ function getUnitConversionPlugin(options) {
1683
+ const config = resolveUnitConversionConfig(options);
1684
+ if (!config) return null;
1685
+ return postcssUnitConverter(config);
1686
+ }
1687
+ //#endregion
988
1688
  //#region src/plugins/getUnitsToPxPlugin.ts
989
1689
  function getUnitsToPxPlugin(options) {
990
1690
  if (!options.unitsToPx) return null;
@@ -1925,6 +2625,78 @@ function normalizeCalcValue(value) {
1925
2625
  function hasVariableReference(value) {
1926
2626
  return value.includes("var(");
1927
2627
  }
2628
+ function splitTopLevelCommaList(value) {
2629
+ const parts = [];
2630
+ let start = 0;
2631
+ let depth = 0;
2632
+ let quote;
2633
+ let escaped = false;
2634
+ for (let i = 0; i < value.length; i++) {
2635
+ const char = value[i];
2636
+ if (escaped) {
2637
+ escaped = false;
2638
+ continue;
2639
+ }
2640
+ if (char === "\\") {
2641
+ escaped = true;
2642
+ continue;
2643
+ }
2644
+ if (quote) {
2645
+ if (char === quote) quote = void 0;
2646
+ continue;
2647
+ }
2648
+ if (char === "\"" || char === "'") {
2649
+ quote = char;
2650
+ continue;
2651
+ }
2652
+ if (char === "(") {
2653
+ depth++;
2654
+ continue;
2655
+ }
2656
+ if (char === ")") {
2657
+ depth = Math.max(0, depth - 1);
2658
+ continue;
2659
+ }
2660
+ if (char === "," && depth === 0) {
2661
+ parts.push(value.slice(start, i));
2662
+ start = i + 1;
2663
+ }
2664
+ }
2665
+ parts.push(value.slice(start));
2666
+ return parts;
2667
+ }
2668
+ function getTransitionPropertySet(value) {
2669
+ const items = splitTopLevelCommaList(value).map((item) => item.trim().toLowerCase()).filter(Boolean);
2670
+ return items.length > 0 ? new Set(items) : void 0;
2671
+ }
2672
+ function isSubsetOfSet(subset, superset) {
2673
+ for (const item of subset) if (!superset.has(item)) return false;
2674
+ return true;
2675
+ }
2676
+ function removeRedundantTransitionPropertyFallbacks(rule) {
2677
+ const entries = rule.nodes.filter((node) => node.type === "decl" && node.prop.toLowerCase() === "transition-property").map((decl) => ({
2678
+ decl,
2679
+ items: getTransitionPropertySet(decl.value)
2680
+ }));
2681
+ for (let i = 0; i < entries.length; i++) {
2682
+ const entry = entries[i];
2683
+ if (!entry?.items) continue;
2684
+ for (let j = i + 1; j < entries.length; j++) {
2685
+ const next = entries[j];
2686
+ if (!next?.items) continue;
2687
+ if (next.items.size === entry.items.size && isSubsetOfSet(entry.items, next.items)) {
2688
+ next.decl.remove();
2689
+ entries.splice(j, 1);
2690
+ j--;
2691
+ continue;
2692
+ }
2693
+ if (next.items.size > entry.items.size && isSubsetOfSet(entry.items, next.items)) {
2694
+ entry.decl.remove();
2695
+ break;
2696
+ }
2697
+ }
2698
+ }
2699
+ }
1928
2700
  function dedupeDeclarations(rule) {
1929
2701
  const entries = [];
1930
2702
  for (const node of [...rule.nodes]) {
@@ -1976,6 +2748,7 @@ function dedupeDeclarations(rule) {
1976
2748
  if (literalSeen.get(canonical)) node.remove();
1977
2749
  else literalSeen.set(canonical, node);
1978
2750
  }
2751
+ removeRedundantTransitionPropertyFallbacks(rule);
1979
2752
  }
1980
2753
  //#endregion
1981
2754
  //#region src/plugins/post/specificity-cleaner.ts
@@ -2125,6 +2898,9 @@ const postcssWeappTailwindcssPostPlugin = (options) => {
2125
2898
  root.walkDecls((decl) => {
2126
2899
  normalizeMiniProgramPrefixedDeclaration(decl);
2127
2900
  });
2901
+ root.walkRules((rule) => {
2902
+ removeRedundantTransitionPropertyFallbacks(rule);
2903
+ });
2128
2904
  root.walkAtRules((atRule) => {
2129
2905
  removeUnsupportedMiniProgramPrefixedAtRule(atRule);
2130
2906
  });
@@ -2605,6 +3381,8 @@ function createPreparedNodes(options, signal) {
2605
3381
  if (pxTransformPlugin) preparedNodes.push(createPreparedNode("normal:px-transform", "normal", () => pxTransformPlugin));
2606
3382
  const remTransformPlugin = getRemTransformPlugin(options);
2607
3383
  if (remTransformPlugin) preparedNodes.push(createPreparedNode("normal:rem-transform", "normal", () => remTransformPlugin));
3384
+ const unitConversionPlugin = getUnitConversionPlugin(options);
3385
+ if (unitConversionPlugin) preparedNodes.push(createPreparedNode("normal:unit-conversion", "normal", () => unitConversionPlugin));
2608
3386
  const calcPlugin = getCalcPlugin(options);
2609
3387
  if (calcPlugin) preparedNodes.push(createPreparedNode("normal:calc", "normal", () => calcPlugin));
2610
3388
  const calcDuplicateCleaner = getCalcDuplicateCleaner(options);
@@ -2850,4 +3628,4 @@ function createStyleHandler(options) {
2850
3628
  return handler;
2851
3629
  }
2852
3630
  //#endregion
2853
- export { createFallbackPlaceholderReplacer, createInjectPreflight, createStyleHandler, createStylePipeline, internalCssSelectorReplacer, normalizeMiniProgramPrefixedDeclaration, normalizeModernColorValue, postcssHtmlTransform, protectDynamicColorMixAlpha, removeUnsupportedMiniProgramPrefixedAtRule };
3631
+ export { createFallbackPlaceholderReplacer, createInjectPreflight, createStyleHandler, createStylePipeline, finalizeMiniProgramCss, hoistTailwindPreflightBase, internalCssSelectorReplacer, normalizeMiniProgramPrefixedDeclaration, normalizeModernColorValue, postcssHtmlTransform, protectDynamicColorMixAlpha, pruneMiniProgramGeneratedCss, removeUnsupportedAtSupports, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, removeUnsupportedMiniProgramPrefixedAtRule, unitConversionComposeRules, unitConversionPresets };