@weapp-tailwindcss/postcss 2.1.6-alpha.1 → 2.1.6-alpha.3

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.
Files changed (3) hide show
  1. package/dist/index.js +260 -53
  2. package/dist/index.mjs +245 -38
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,6 +3,135 @@
3
3
  // src/handler.ts
4
4
  var _shared = require('@weapp-tailwindcss/shared');
5
5
 
6
+ // src/compat/uni-app-x.ts
7
+ var _postcss = require('postcss'); var _postcss2 = _interopRequireDefault(_postcss);
8
+ var UNI_APP_X_BASE_CARRIER_SELECTORS = /* @__PURE__ */ new Set([
9
+ "*",
10
+ "view",
11
+ "text",
12
+ "::before",
13
+ "::after",
14
+ ":before",
15
+ ":after",
16
+ "::backdrop"
17
+ ]);
18
+ var REQUIRED_TW_VAR_RE = /var\(\s*(--tw-[\w-]+)\s*\)/g;
19
+ var CLASS_SELECTOR_RE = /\.[\w-]+/;
20
+ var SELECTOR_WHITESPACE_RE = /\s+/g;
21
+ function isUniAppXEnabled(options) {
22
+ return Boolean(_optionalChain([options, 'optionalAccess', _ => _.uniAppX]));
23
+ }
24
+ function normalizeSelector(selector) {
25
+ return selector.replace(SELECTOR_WHITESPACE_RE, "").toLowerCase();
26
+ }
27
+ function isBaseCarrierSelector(selector) {
28
+ return UNI_APP_X_BASE_CARRIER_SELECTORS.has(normalizeSelector(selector));
29
+ }
30
+ function isBaseCarrierRule(rule) {
31
+ return Array.isArray(rule.selectors) && rule.selectors.length > 0 && rule.selectors.every(isBaseCarrierSelector);
32
+ }
33
+ function hasClassSelector(rule) {
34
+ return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE.test(selector));
35
+ }
36
+ function collectRequiredTwVars(value) {
37
+ const result = /* @__PURE__ */ new Set();
38
+ for (const match of value.matchAll(REQUIRED_TW_VAR_RE)) {
39
+ const variableName = match[1];
40
+ if (variableName) {
41
+ result.add(variableName);
42
+ }
43
+ }
44
+ return result;
45
+ }
46
+ function extractUniAppXBaseDefaults(result) {
47
+ const defaults = /* @__PURE__ */ new Map();
48
+ result.root.walkRules((rule) => {
49
+ if (!isBaseCarrierRule(rule)) {
50
+ return;
51
+ }
52
+ rule.walkDecls((decl) => {
53
+ if (!decl.prop.startsWith("--tw-") || defaults.has(decl.prop)) {
54
+ return;
55
+ }
56
+ defaults.set(decl.prop, {
57
+ prop: decl.prop,
58
+ value: decl.value,
59
+ important: decl.important
60
+ });
61
+ });
62
+ rule.remove();
63
+ });
64
+ return defaults;
65
+ }
66
+ function injectUniAppXBaseDefaults(result, defaults) {
67
+ if (defaults.size === 0) {
68
+ return;
69
+ }
70
+ result.root.walkRules((rule) => {
71
+ if (!hasClassSelector(rule)) {
72
+ return;
73
+ }
74
+ const declaredProps = /* @__PURE__ */ new Set();
75
+ const requiredProps = /* @__PURE__ */ new Set();
76
+ rule.walkDecls((decl) => {
77
+ declaredProps.add(decl.prop);
78
+ for (const variableName of collectRequiredTwVars(decl.value)) {
79
+ requiredProps.add(variableName);
80
+ }
81
+ });
82
+ const prependDecls = [];
83
+ for (const variableName of requiredProps) {
84
+ if (declaredProps.has(variableName)) {
85
+ continue;
86
+ }
87
+ const declaration = defaults.get(variableName);
88
+ if (declaration) {
89
+ prependDecls.push(declaration);
90
+ }
91
+ }
92
+ for (const declaration of prependDecls.reverse()) {
93
+ rule.prepend(_postcss2.default.decl({
94
+ prop: declaration.prop,
95
+ value: declaration.value,
96
+ important: declaration.important
97
+ }));
98
+ }
99
+ });
100
+ }
101
+ function applyUniAppXBaseCompatibility(result, options) {
102
+ if (!isUniAppXEnabled(options)) {
103
+ return result;
104
+ }
105
+ const defaults = extractUniAppXBaseDefaults(result);
106
+ injectUniAppXBaseDefaults(result, defaults);
107
+ if (defaults.size === 0) {
108
+ return result;
109
+ }
110
+ return result.root.toResult(result.opts);
111
+ }
112
+ function stripUnsupportedPseudoForUniAppX(node, enabled) {
113
+ if (!enabled) {
114
+ return;
115
+ }
116
+ if (node.value === ":host") {
117
+ return;
118
+ }
119
+ node.remove();
120
+ }
121
+ function stripUnsupportedNodeForUniAppX(node, options) {
122
+ if (!isUniAppXEnabled(options)) {
123
+ return false;
124
+ }
125
+ if (node.type === "attribute" || node.type === "pseudo") {
126
+ node.remove();
127
+ return true;
128
+ }
129
+ return false;
130
+ }
131
+ function shouldRemoveEmptyRuleForUniAppX(rule, options) {
132
+ return isUniAppXEnabled(options) && rule.nodes.length === 0;
133
+ }
134
+
6
135
  // src/defaults.ts
7
136
  function getDefaultOptions(options) {
8
137
  return {
@@ -15,9 +144,9 @@ function getDefaultOptions(options) {
15
144
  },
16
145
  "oklab-function": true,
17
146
  "color-mix": true,
18
- "color-functional-notation": _nullishCoalesce(_optionalChain([options, 'optionalAccess', _ => _.cssPresetEnv, 'optionalAccess', _2 => _2.features, 'optionalAccess', _3 => _3["color-functional-notation"]]), () => ( { preserve: false })),
147
+ "color-functional-notation": _nullishCoalesce(_optionalChain([options, 'optionalAccess', _2 => _2.cssPresetEnv, 'optionalAccess', _3 => _3.features, 'optionalAccess', _4 => _4["color-functional-notation"]]), () => ( { preserve: false })),
19
148
  // 在 calc 下,这个需要开启
20
- "custom-properties": _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.cssPresetEnv, 'optionalAccess', _5 => _5.features, 'optionalAccess', _6 => _6["custom-properties"]]), () => ( _optionalChain([options, 'optionalAccess', _7 => _7.cssCalc]))) ? { preserve: true } : false
149
+ "custom-properties": _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.cssPresetEnv, 'optionalAccess', _6 => _6.features, 'optionalAccess', _7 => _7["custom-properties"]]), () => ( _optionalChain([options, 'optionalAccess', _8 => _8.cssCalc]))) ? { preserve: true } : false
21
150
  },
22
151
  autoprefixer: {
23
152
  add: false
@@ -253,7 +382,7 @@ function createInjectPreflight(options) {
253
382
  }
254
383
 
255
384
  // src/processor-cache.ts
256
- var _postcss = require('postcss'); var _postcss2 = _interopRequireDefault(_postcss);
385
+
257
386
 
258
387
  // src/pipeline.ts
259
388
  var _postcsspresetenv = require('postcss-preset-env'); var _postcsspresetenv2 = _interopRequireDefault(_postcsspresetenv);
@@ -265,10 +394,10 @@ var isSlashDiv = (node) => node.type === "div" && node.value === "/";
265
394
  function trimNodes(nodes2) {
266
395
  let start = 0;
267
396
  let end = nodes2.length;
268
- while (start < end && _optionalChain([nodes2, 'access', _8 => _8[start], 'optionalAccess', _9 => _9.type]) === "space") {
397
+ while (start < end && _optionalChain([nodes2, 'access', _9 => _9[start], 'optionalAccess', _10 => _10.type]) === "space") {
269
398
  start += 1;
270
399
  }
271
- while (end > start && _optionalChain([nodes2, 'access', _10 => _10[end - 1], 'optionalAccess', _11 => _11.type]) === "space") {
400
+ while (end > start && _optionalChain([nodes2, 'access', _11 => _11[end - 1], 'optionalAccess', _12 => _12.type]) === "space") {
272
401
  end -= 1;
273
402
  }
274
403
  return nodes2.slice(start, end);
@@ -553,7 +682,7 @@ function getUnitsToPxPlugin(options) {
553
682
  // src/compat/tailwindcss-rpx.ts
554
683
  var LENGTH_VALUE_REGEXP = /^[+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?rpx$/i;
555
684
  function normalizeTailwindcssRpxDeclaration(decl, options) {
556
- const majorVersion = _optionalChain([options, 'optionalAccess', _12 => _12.majorVersion]);
685
+ const majorVersion = _optionalChain([options, 'optionalAccess', _13 => _13.majorVersion]);
557
686
  const normalizedValue = decl.value.trim();
558
687
  if (LENGTH_VALUE_REGEXP.test(normalizedValue) && (majorVersion === void 0 || majorVersion === 2 || majorVersion === 3 || majorVersion === 4)) {
559
688
  const lowerProp = decl.prop.toLowerCase();
@@ -740,7 +869,7 @@ var MODERN_CHECK_COLOR_RGB_RE = /color\s*:\s*rgb\(\s*from\s+red\s+r\s+g\s+b\s*\)
740
869
  var RADIUS_VALUE_RE = /\b([+-]?(?:\d+(?:\.\d+)?|\.\d+)(?:e[+-]?\d+)?)\s*(r?px)\b/gi;
741
870
  var SCIENTIFIC_NOTATION_RE = /e/i;
742
871
  function isTailwindcssV4(options) {
743
- return _optionalChain([options, 'optionalAccess', _13 => _13.majorVersion]) === 4;
872
+ return _optionalChain([options, 'optionalAccess', _14 => _14.majorVersion]) === 4;
744
873
  }
745
874
  function testIfRootHostForV4(node) {
746
875
  return node.type === "rule" && node.selector.includes(":root") && node.selector.includes(":host");
@@ -786,30 +915,6 @@ function normalizeTailwindcssV4Declaration(decl) {
786
915
  return false;
787
916
  }
788
917
 
789
- // src/compat/uni-app-x.ts
790
- function isUniAppXEnabled(options) {
791
- return Boolean(_optionalChain([options, 'optionalAccess', _14 => _14.uniAppX]));
792
- }
793
- function stripUnsupportedPseudoForUniAppX(node, enabled) {
794
- if (!enabled) {
795
- return;
796
- }
797
- node.remove();
798
- }
799
- function stripUnsupportedNodeForUniAppX(node, options) {
800
- if (!isUniAppXEnabled(options)) {
801
- return false;
802
- }
803
- if (node.type === "tag" || node.type === "attribute" || node.type === "pseudo") {
804
- node.remove();
805
- return true;
806
- }
807
- return false;
808
- }
809
- function shouldRemoveEmptyRuleForUniAppX(rule, options) {
810
- return isUniAppXEnabled(options) && rule.nodes.length === 0;
811
- }
812
-
813
918
  // src/constants.ts
814
919
  var postcssPlugin = "postcss-weapp-tailwindcss-rename-plugin";
815
920
 
@@ -1307,10 +1412,17 @@ function shouldRemoveHoverSelector(selector, options) {
1307
1412
  return selector.nodes.some((node) => node.type === "pseudo" && node.value === ":hover");
1308
1413
  }
1309
1414
  var UNSUPPORTED_PSEUDO_ELEMENT_SELECTOR_SET = /* @__PURE__ */ new Set([
1415
+ ":after",
1416
+ ":before",
1417
+ "::after",
1418
+ "::before",
1310
1419
  "::backdrop",
1311
1420
  "::file-selector-button"
1312
1421
  ]);
1313
- function shouldRemoveUnsupportedPseudoElementSelector(selector) {
1422
+ function shouldRemoveUnsupportedPseudoElementSelector(selector, options) {
1423
+ if (!isUniAppXEnabled(options)) {
1424
+ return selector.nodes.some((node) => node.type === "pseudo" && (node.value === "::backdrop" || node.value === "::file-selector-button"));
1425
+ }
1314
1426
  return selector.nodes.some((node) => node.type === "pseudo" && UNSUPPORTED_PSEUDO_ELEMENT_SELECTOR_SET.has(node.value));
1315
1427
  }
1316
1428
  function isHiddenOrTemplateNotPseudo(node) {
@@ -1369,7 +1481,7 @@ function handleTagOrAttribute(node, context) {
1369
1481
  stripUnsupportedNodeForUniAppX(node, context.options);
1370
1482
  }
1371
1483
  function handleSelectorNode(selector, context) {
1372
- if (shouldRemoveUnsupportedPseudoElementSelector(selector)) {
1484
+ if (shouldRemoveUnsupportedPseudoElementSelector(selector, context.options)) {
1373
1485
  selector.remove();
1374
1486
  return;
1375
1487
  }
@@ -1516,6 +1628,65 @@ function ruleTransformSync(rule, options) {
1516
1628
  transformer(rule);
1517
1629
  }
1518
1630
 
1631
+ // src/utils/selector-guard.ts
1632
+ var ruleSelectorMutationStateMap = /* @__PURE__ */ new WeakMap();
1633
+ var DEFAULT_SELECTOR_MUTATION_LIMIT = 24;
1634
+ function toSelectorSignature(selectors) {
1635
+ return selectors.join(",");
1636
+ }
1637
+ function getRuleSelectorMutationState(rule) {
1638
+ let state = ruleSelectorMutationStateMap.get(rule);
1639
+ if (!state) {
1640
+ state = {
1641
+ count: 0,
1642
+ seen: /* @__PURE__ */ new Set(),
1643
+ trace: []
1644
+ };
1645
+ const current = _nullishCoalesce(rule.selectors, () => ( []));
1646
+ state.seen.add(toSelectorSignature(current));
1647
+ ruleSelectorMutationStateMap.set(rule, state);
1648
+ }
1649
+ return state;
1650
+ }
1651
+ function pushTrace(state, meta, selectors) {
1652
+ state.trace.push(`${meta.phase}:${meta.reason}:${toSelectorSignature(selectors)}`);
1653
+ if (state.trace.length > DEFAULT_SELECTOR_MUTATION_LIMIT) {
1654
+ state.trace.shift();
1655
+ }
1656
+ }
1657
+ function createSelectorCycleError(meta, state, selectors) {
1658
+ const next = toSelectorSignature(selectors);
1659
+ const trace = [...state.trace, `${meta.phase}:${meta.reason}:${next}`].join(" -> ");
1660
+ return new Error(`[postcss-selector-guard] \u68C0\u6D4B\u5230\u53EF\u80FD\u7684\u9009\u62E9\u5668\u6B7B\u5FAA\u73AF: ${trace}`);
1661
+ }
1662
+ function assignRuleSelectors(rule, selectors, meta) {
1663
+ const current = _nullishCoalesce(rule.selectors, () => ( []));
1664
+ const currentSignature = toSelectorSignature(current);
1665
+ const nextSignature = toSelectorSignature(selectors);
1666
+ if (currentSignature === nextSignature) {
1667
+ return false;
1668
+ }
1669
+ const state = getRuleSelectorMutationState(rule);
1670
+ if (state.seen.has(nextSignature)) {
1671
+ throw createSelectorCycleError(meta, state, selectors);
1672
+ }
1673
+ state.count += 1;
1674
+ if (state.count > DEFAULT_SELECTOR_MUTATION_LIMIT) {
1675
+ throw createSelectorCycleError(meta, state, selectors);
1676
+ }
1677
+ pushTrace(state, meta, selectors);
1678
+ state.seen.add(nextSignature);
1679
+ rule.selectors = selectors;
1680
+ return true;
1681
+ }
1682
+ function appendRuleSelector(rule, selector, meta) {
1683
+ const current = _nullishCoalesce(rule.selectors, () => ( []));
1684
+ if (current.includes(selector)) {
1685
+ return false;
1686
+ }
1687
+ return assignRuleSelectors(rule, [...current, selector], meta);
1688
+ }
1689
+
1519
1690
  // src/plugins/post/decl-dedupe.ts
1520
1691
  var logicalPropMap = /* @__PURE__ */ new Map([
1521
1692
  // margin 方向映射
@@ -1684,6 +1855,7 @@ function createRootSpecificityCleaner(options) {
1684
1855
  if (!rule.selectors || rule.selectors.length === 0) {
1685
1856
  return;
1686
1857
  }
1858
+ let changed = false;
1687
1859
  const next = rule.selectors.map((selector) => {
1688
1860
  let updated = selector;
1689
1861
  for (const target of targets) {
@@ -1694,9 +1866,15 @@ function createRootSpecificityCleaner(options) {
1694
1866
  updated = updated.split(target.spacedMatch).join(target.replacement);
1695
1867
  }
1696
1868
  }
1869
+ if (updated !== selector) {
1870
+ changed = true;
1871
+ }
1697
1872
  return updated;
1698
1873
  });
1699
- rule.selectors = next;
1874
+ changed && assignRuleSelectors(rule, next, {
1875
+ phase: "post",
1876
+ reason: "clean-root-specificity"
1877
+ });
1700
1878
  };
1701
1879
  }
1702
1880
 
@@ -1741,7 +1919,10 @@ var postcssWeappTailwindcssPostPlugin = (options) => {
1741
1919
  _optionalChain([cleanRootSpecificity, 'optionalCall', _58 => _58(rule)]);
1742
1920
  if (enableMainChunkTransforms) {
1743
1921
  if (_optionalChain([shouldAppendHostSelector, 'optionalCall', _59 => _59(rule)])) {
1744
- rule.selectors = [...rule.selectors, ":host"];
1922
+ appendRuleSelector(rule, ":host", {
1923
+ phase: "post",
1924
+ reason: "append-host-selector"
1925
+ });
1745
1926
  }
1746
1927
  dedupeDeclarations(rule);
1747
1928
  if (rule.selectors.length === 0 || rule.selectors.length === 1 && rule.selector.trim() === "") {
@@ -2047,20 +2228,39 @@ function remakeCssVarSelector(selectors, options) {
2047
2228
  }
2048
2229
  return selectors;
2049
2230
  }
2231
+ function resolveUniAppXVariableScopeSelectors(options) {
2232
+ const universal = _optionalChain([options, 'access', _62 => _62.cssSelectorReplacement, 'optionalAccess', _63 => _63.universal]);
2233
+ if (Array.isArray(universal) && universal.length > 0) {
2234
+ return [...universal];
2235
+ }
2236
+ if (typeof universal === "string" && universal.length > 0) {
2237
+ return [universal];
2238
+ }
2239
+ return ["view", "text"];
2240
+ }
2050
2241
  function commonChunkPreflight(node, options) {
2051
2242
  const { ctx, cssInjectPreflight, injectAdditionalCssVarScope } = options;
2052
- const rootOption = _optionalChain([options, 'access', _62 => _62.cssSelectorReplacement, 'optionalAccess', _63 => _63.root]);
2243
+ const uniAppXEnabled = isUniAppXEnabled(options);
2244
+ const rootOption = _optionalChain([options, 'access', _64 => _64.cssSelectorReplacement, 'optionalAccess', _65 => _65.root]);
2053
2245
  const rootSelectors = rootOption === false || rootOption === void 0 ? [] : Array.isArray(rootOption) ? rootOption.filter(Boolean) : [rootOption];
2054
2246
  const hasHostSelector = node.selectors.some((selector) => selector.includes(":host"));
2055
2247
  const hasRootPseudoSelector = node.selectors.some((selector) => selector.includes(":root"));
2056
2248
  const hasAllDefaultRootSelectors = DEFAULT_ROOT_SELECTORS2.every((selector) => node.selectors.includes(selector));
2057
2249
  if (!hasHostSelector && !rootSelectors.includes(":host") && (hasRootPseudoSelector || rootSelectors.length === DEFAULT_ROOT_SELECTORS2.length && rootSelectors.every((selector, index) => selector === DEFAULT_ROOT_SELECTORS2[index]) && hasAllDefaultRootSelectors)) {
2058
- node.selectors = [...node.selectors, ":host"];
2250
+ appendRuleSelector(node, ":host", {
2251
+ phase: "pre",
2252
+ reason: "append-host-selector"
2253
+ });
2059
2254
  }
2060
- if (testIfVariablesScope(node)) {
2061
- _optionalChain([ctx, 'optionalAccess', _64 => _64.markVariablesScope, 'call', _65 => _65(node)]);
2062
- node.selectors = remakeCssVarSelector(node.selectors, options);
2063
- node.before(makePseudoVarRule());
2255
+ if (testIfVariablesScope(node) || uniAppXEnabled && node.selectors.includes("*") && hasTwVars(node, 2)) {
2256
+ _optionalChain([ctx, 'optionalAccess', _66 => _66.markVariablesScope, 'call', _67 => _67(node)]);
2257
+ assignRuleSelectors(node, uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : remakeCssVarSelector(node.selectors, options), {
2258
+ phase: "pre",
2259
+ reason: "rewrite-variable-scope"
2260
+ });
2261
+ if (!uniAppXEnabled) {
2262
+ node.before(makePseudoVarRule());
2263
+ }
2064
2264
  if (typeof cssInjectPreflight === "function") {
2065
2265
  node.append(...cssInjectPreflight());
2066
2266
  }
@@ -2068,12 +2268,19 @@ function commonChunkPreflight(node, options) {
2068
2268
  const isTailwindcss4 = isTailwindcssV4(options);
2069
2269
  if (injectAdditionalCssVarScope && (isTailwindcss4 ? testIfRootHostForV4(node) : testIfTwBackdrop(node))) {
2070
2270
  const syntheticRule = new (0, _postcss.Rule)({
2071
- selectors: ["*", "::after", "::before"],
2271
+ selectors: uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : ["*", "::after", "::before"],
2072
2272
  nodes: isTailwindcss4 ? cssVarsV4Nodes : cssVarsV3Nodes
2073
2273
  });
2074
- syntheticRule.selectors = remakeCssVarSelector(syntheticRule.selectors, options);
2274
+ if (!uniAppXEnabled) {
2275
+ assignRuleSelectors(syntheticRule, remakeCssVarSelector(syntheticRule.selectors, options), {
2276
+ phase: "pre",
2277
+ reason: "rewrite-synthetic-variable-scope"
2278
+ });
2279
+ }
2075
2280
  node.before(syntheticRule);
2076
- node.before(makePseudoVarRule());
2281
+ if (!uniAppXEnabled) {
2282
+ node.before(makePseudoVarRule());
2283
+ }
2077
2284
  if (typeof cssInjectPreflight === "function") {
2078
2285
  syntheticRule.append(...cssInjectPreflight());
2079
2286
  }
@@ -2118,9 +2325,9 @@ var postcssWeappTailwindcssPrePlugin = (options) => {
2118
2325
  root.walkAtRules((atRule) => {
2119
2326
  if (atRule.name === "layer") {
2120
2327
  if (atRule.params === "properties") {
2121
- if (atRule.nodes === void 0 || _optionalChain([atRule, 'access', _66 => _66.nodes, 'optionalAccess', _67 => _67.length]) === 0) {
2328
+ if (atRule.nodes === void 0 || _optionalChain([atRule, 'access', _68 => _68.nodes, 'optionalAccess', _69 => _69.length]) === 0) {
2122
2329
  layerProperties = atRule;
2123
- } else if (_optionalChain([atRule, 'access', _68 => _68.first, 'optionalAccess', _69 => _69.type]) === "atrule" && isTailwindcssV4ModernCheck(atRule.first)) {
2330
+ } else if (_optionalChain([atRule, 'access', _70 => _70.first, 'optionalAccess', _71 => _71.type]) === "atrule" && isTailwindcssV4ModernCheck(atRule.first)) {
2124
2331
  if (layerProperties) {
2125
2332
  layerProperties.replaceWith(atRule.first.nodes);
2126
2333
  atRule.remove();
@@ -2132,7 +2339,7 @@ var postcssWeappTailwindcssPrePlugin = (options) => {
2132
2339
  atRule.replaceWith(atRule.nodes);
2133
2340
  }
2134
2341
  } else if (isTailwindcssV4ModernCheck(atRule)) {
2135
- if (_optionalChain([atRule, 'access', _70 => _70.first, 'optionalAccess', _71 => _71.type]) === "atrule" && atRule.first.name === "layer") {
2342
+ if (_optionalChain([atRule, 'access', _72 => _72.first, 'optionalAccess', _73 => _73.type]) === "atrule" && atRule.first.name === "layer") {
2136
2343
  atRule.replaceWith(atRule.first.nodes);
2137
2344
  }
2138
2345
  }
@@ -2168,7 +2375,7 @@ function createPreparedNode(id, stage, createPlugin) {
2168
2375
  }
2169
2376
  function createPreparedNodes(options) {
2170
2377
  const preparedNodes = [];
2171
- const userPlugins = normalizeUserPlugins(_optionalChain([options, 'access', _72 => _72.postcssOptions, 'optionalAccess', _73 => _73.plugins]));
2378
+ const userPlugins = normalizeUserPlugins(_optionalChain([options, 'access', _74 => _74.postcssOptions, 'optionalAccess', _75 => _75.plugins]));
2172
2379
  const presetEnvOptions = options.cssPresetEnv;
2173
2380
  userPlugins.forEach((plugin, index) => {
2174
2381
  preparedNodes.push(createPreparedNode(`pre:user-${index}`, "pre", () => plugin));
@@ -2264,7 +2471,7 @@ function createStylePipeline(options) {
2264
2471
  function createProcessOptions(options) {
2265
2472
  return {
2266
2473
  from: void 0,
2267
- ..._nullishCoalesce(_optionalChain([options, 'access', _74 => _74.postcssOptions, 'optionalAccess', _75 => _75.options]), () => ( {}))
2474
+ ..._nullishCoalesce(_optionalChain([options, 'access', _76 => _76.postcssOptions, 'optionalAccess', _77 => _77.options]), () => ( {}))
2268
2475
  };
2269
2476
  }
2270
2477
  function getSimpleProcessOptionsCacheKey(options) {
@@ -2303,7 +2510,7 @@ var StyleProcessorCache = (_class = class {constructor() { _class.prototype.__in
2303
2510
  __init4() {this.processorCacheByKey = /* @__PURE__ */ new Map()}
2304
2511
  __init5() {this.processorKeyCache = /* @__PURE__ */ new WeakMap()}
2305
2512
  createProcessorCacheKey(options) {
2306
- const from = _optionalChain([options, 'access', _76 => _76.postcssOptions, 'optionalAccess', _77 => _77.options, 'optionalAccess', _78 => _78.from]);
2513
+ const from = _optionalChain([options, 'access', _78 => _78.postcssOptions, 'optionalAccess', _79 => _79.options, 'optionalAccess', _80 => _80.from]);
2307
2514
  if (from == null) {
2308
2515
  return fingerprintOptions(options);
2309
2516
  }
@@ -2312,7 +2519,7 @@ var StyleProcessorCache = (_class = class {constructor() { _class.prototype.__in
2312
2519
  postcssOptions: {
2313
2520
  ..._nullishCoalesce(options.postcssOptions, () => ( {})),
2314
2521
  options: {
2315
- ..._nullishCoalesce(_optionalChain([options, 'access', _79 => _79.postcssOptions, 'optionalAccess', _80 => _80.options]), () => ( {})),
2522
+ ..._nullishCoalesce(_optionalChain([options, 'access', _81 => _81.postcssOptions, 'optionalAccess', _82 => _82.options]), () => ( {})),
2316
2523
  from: void 0
2317
2524
  }
2318
2525
  }
@@ -2327,7 +2534,7 @@ var StyleProcessorCache = (_class = class {constructor() { _class.prototype.__in
2327
2534
  return pipeline;
2328
2535
  }
2329
2536
  getProcessOptions(options) {
2330
- const source = _optionalChain([options, 'access', _81 => _81.postcssOptions, 'optionalAccess', _82 => _82.options]);
2537
+ const source = _optionalChain([options, 'access', _83 => _83.postcssOptions, 'optionalAccess', _84 => _84.options]);
2331
2538
  const cacheKey = source ? _nullishCoalesce(getSimpleProcessOptionsCacheKey(source), () => ( fingerprintOptions(source))) : void 0;
2332
2539
  const cached = this.processOptionsCache.get(options);
2333
2540
  if (!cached || cached.cacheKey !== cacheKey) {
@@ -2376,7 +2583,7 @@ function createStyleHandler(options) {
2376
2583
  return processor.process(
2377
2584
  rawSource,
2378
2585
  processOptions
2379
- ).async();
2586
+ ).async().then((result) => applyUniAppXBaseCompatibility(result, resolvedOptions));
2380
2587
  });
2381
2588
  handler.getPipeline = (opt) => {
2382
2589
  const resolvedOptions = resolver.resolve(opt);
package/dist/index.mjs CHANGED
@@ -3,6 +3,135 @@ import "./chunk-WAXGOBY2.mjs";
3
3
  // src/handler.ts
4
4
  import { defuOverrideArray as defuOverrideArray4 } from "@weapp-tailwindcss/shared";
5
5
 
6
+ // src/compat/uni-app-x.ts
7
+ import postcss from "postcss";
8
+ var UNI_APP_X_BASE_CARRIER_SELECTORS = /* @__PURE__ */ new Set([
9
+ "*",
10
+ "view",
11
+ "text",
12
+ "::before",
13
+ "::after",
14
+ ":before",
15
+ ":after",
16
+ "::backdrop"
17
+ ]);
18
+ var REQUIRED_TW_VAR_RE = /var\(\s*(--tw-[\w-]+)\s*\)/g;
19
+ var CLASS_SELECTOR_RE = /\.[\w-]+/;
20
+ var SELECTOR_WHITESPACE_RE = /\s+/g;
21
+ function isUniAppXEnabled(options) {
22
+ return Boolean(options?.uniAppX);
23
+ }
24
+ function normalizeSelector(selector) {
25
+ return selector.replace(SELECTOR_WHITESPACE_RE, "").toLowerCase();
26
+ }
27
+ function isBaseCarrierSelector(selector) {
28
+ return UNI_APP_X_BASE_CARRIER_SELECTORS.has(normalizeSelector(selector));
29
+ }
30
+ function isBaseCarrierRule(rule) {
31
+ return Array.isArray(rule.selectors) && rule.selectors.length > 0 && rule.selectors.every(isBaseCarrierSelector);
32
+ }
33
+ function hasClassSelector(rule) {
34
+ return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE.test(selector));
35
+ }
36
+ function collectRequiredTwVars(value) {
37
+ const result = /* @__PURE__ */ new Set();
38
+ for (const match of value.matchAll(REQUIRED_TW_VAR_RE)) {
39
+ const variableName = match[1];
40
+ if (variableName) {
41
+ result.add(variableName);
42
+ }
43
+ }
44
+ return result;
45
+ }
46
+ function extractUniAppXBaseDefaults(result) {
47
+ const defaults = /* @__PURE__ */ new Map();
48
+ result.root.walkRules((rule) => {
49
+ if (!isBaseCarrierRule(rule)) {
50
+ return;
51
+ }
52
+ rule.walkDecls((decl) => {
53
+ if (!decl.prop.startsWith("--tw-") || defaults.has(decl.prop)) {
54
+ return;
55
+ }
56
+ defaults.set(decl.prop, {
57
+ prop: decl.prop,
58
+ value: decl.value,
59
+ important: decl.important
60
+ });
61
+ });
62
+ rule.remove();
63
+ });
64
+ return defaults;
65
+ }
66
+ function injectUniAppXBaseDefaults(result, defaults) {
67
+ if (defaults.size === 0) {
68
+ return;
69
+ }
70
+ result.root.walkRules((rule) => {
71
+ if (!hasClassSelector(rule)) {
72
+ return;
73
+ }
74
+ const declaredProps = /* @__PURE__ */ new Set();
75
+ const requiredProps = /* @__PURE__ */ new Set();
76
+ rule.walkDecls((decl) => {
77
+ declaredProps.add(decl.prop);
78
+ for (const variableName of collectRequiredTwVars(decl.value)) {
79
+ requiredProps.add(variableName);
80
+ }
81
+ });
82
+ const prependDecls = [];
83
+ for (const variableName of requiredProps) {
84
+ if (declaredProps.has(variableName)) {
85
+ continue;
86
+ }
87
+ const declaration = defaults.get(variableName);
88
+ if (declaration) {
89
+ prependDecls.push(declaration);
90
+ }
91
+ }
92
+ for (const declaration of prependDecls.reverse()) {
93
+ rule.prepend(postcss.decl({
94
+ prop: declaration.prop,
95
+ value: declaration.value,
96
+ important: declaration.important
97
+ }));
98
+ }
99
+ });
100
+ }
101
+ function applyUniAppXBaseCompatibility(result, options) {
102
+ if (!isUniAppXEnabled(options)) {
103
+ return result;
104
+ }
105
+ const defaults = extractUniAppXBaseDefaults(result);
106
+ injectUniAppXBaseDefaults(result, defaults);
107
+ if (defaults.size === 0) {
108
+ return result;
109
+ }
110
+ return result.root.toResult(result.opts);
111
+ }
112
+ function stripUnsupportedPseudoForUniAppX(node, enabled) {
113
+ if (!enabled) {
114
+ return;
115
+ }
116
+ if (node.value === ":host") {
117
+ return;
118
+ }
119
+ node.remove();
120
+ }
121
+ function stripUnsupportedNodeForUniAppX(node, options) {
122
+ if (!isUniAppXEnabled(options)) {
123
+ return false;
124
+ }
125
+ if (node.type === "attribute" || node.type === "pseudo") {
126
+ node.remove();
127
+ return true;
128
+ }
129
+ return false;
130
+ }
131
+ function shouldRemoveEmptyRuleForUniAppX(rule, options) {
132
+ return isUniAppXEnabled(options) && rule.nodes.length === 0;
133
+ }
134
+
6
135
  // src/defaults.ts
7
136
  function getDefaultOptions(options) {
8
137
  return {
@@ -253,7 +382,7 @@ function createInjectPreflight(options) {
253
382
  }
254
383
 
255
384
  // src/processor-cache.ts
256
- import postcss from "postcss";
385
+ import postcss2 from "postcss";
257
386
 
258
387
  // src/pipeline.ts
259
388
  import postcssPresetEnv from "postcss-preset-env";
@@ -786,30 +915,6 @@ function normalizeTailwindcssV4Declaration(decl) {
786
915
  return false;
787
916
  }
788
917
 
789
- // src/compat/uni-app-x.ts
790
- function isUniAppXEnabled(options) {
791
- return Boolean(options?.uniAppX);
792
- }
793
- function stripUnsupportedPseudoForUniAppX(node, enabled) {
794
- if (!enabled) {
795
- return;
796
- }
797
- node.remove();
798
- }
799
- function stripUnsupportedNodeForUniAppX(node, options) {
800
- if (!isUniAppXEnabled(options)) {
801
- return false;
802
- }
803
- if (node.type === "tag" || node.type === "attribute" || node.type === "pseudo") {
804
- node.remove();
805
- return true;
806
- }
807
- return false;
808
- }
809
- function shouldRemoveEmptyRuleForUniAppX(rule, options) {
810
- return isUniAppXEnabled(options) && rule.nodes.length === 0;
811
- }
812
-
813
918
  // src/constants.ts
814
919
  var postcssPlugin = "postcss-weapp-tailwindcss-rename-plugin";
815
920
 
@@ -1307,10 +1412,17 @@ function shouldRemoveHoverSelector(selector, options) {
1307
1412
  return selector.nodes.some((node) => node.type === "pseudo" && node.value === ":hover");
1308
1413
  }
1309
1414
  var UNSUPPORTED_PSEUDO_ELEMENT_SELECTOR_SET = /* @__PURE__ */ new Set([
1415
+ ":after",
1416
+ ":before",
1417
+ "::after",
1418
+ "::before",
1310
1419
  "::backdrop",
1311
1420
  "::file-selector-button"
1312
1421
  ]);
1313
- function shouldRemoveUnsupportedPseudoElementSelector(selector) {
1422
+ function shouldRemoveUnsupportedPseudoElementSelector(selector, options) {
1423
+ if (!isUniAppXEnabled(options)) {
1424
+ return selector.nodes.some((node) => node.type === "pseudo" && (node.value === "::backdrop" || node.value === "::file-selector-button"));
1425
+ }
1314
1426
  return selector.nodes.some((node) => node.type === "pseudo" && UNSUPPORTED_PSEUDO_ELEMENT_SELECTOR_SET.has(node.value));
1315
1427
  }
1316
1428
  function isHiddenOrTemplateNotPseudo(node) {
@@ -1369,7 +1481,7 @@ function handleTagOrAttribute(node, context) {
1369
1481
  stripUnsupportedNodeForUniAppX(node, context.options);
1370
1482
  }
1371
1483
  function handleSelectorNode(selector, context) {
1372
- if (shouldRemoveUnsupportedPseudoElementSelector(selector)) {
1484
+ if (shouldRemoveUnsupportedPseudoElementSelector(selector, context.options)) {
1373
1485
  selector.remove();
1374
1486
  return;
1375
1487
  }
@@ -1516,6 +1628,65 @@ function ruleTransformSync(rule, options) {
1516
1628
  transformer(rule);
1517
1629
  }
1518
1630
 
1631
+ // src/utils/selector-guard.ts
1632
+ var ruleSelectorMutationStateMap = /* @__PURE__ */ new WeakMap();
1633
+ var DEFAULT_SELECTOR_MUTATION_LIMIT = 24;
1634
+ function toSelectorSignature(selectors) {
1635
+ return selectors.join(",");
1636
+ }
1637
+ function getRuleSelectorMutationState(rule) {
1638
+ let state = ruleSelectorMutationStateMap.get(rule);
1639
+ if (!state) {
1640
+ state = {
1641
+ count: 0,
1642
+ seen: /* @__PURE__ */ new Set(),
1643
+ trace: []
1644
+ };
1645
+ const current = rule.selectors ?? [];
1646
+ state.seen.add(toSelectorSignature(current));
1647
+ ruleSelectorMutationStateMap.set(rule, state);
1648
+ }
1649
+ return state;
1650
+ }
1651
+ function pushTrace(state, meta, selectors) {
1652
+ state.trace.push(`${meta.phase}:${meta.reason}:${toSelectorSignature(selectors)}`);
1653
+ if (state.trace.length > DEFAULT_SELECTOR_MUTATION_LIMIT) {
1654
+ state.trace.shift();
1655
+ }
1656
+ }
1657
+ function createSelectorCycleError(meta, state, selectors) {
1658
+ const next = toSelectorSignature(selectors);
1659
+ const trace = [...state.trace, `${meta.phase}:${meta.reason}:${next}`].join(" -> ");
1660
+ return new Error(`[postcss-selector-guard] \u68C0\u6D4B\u5230\u53EF\u80FD\u7684\u9009\u62E9\u5668\u6B7B\u5FAA\u73AF: ${trace}`);
1661
+ }
1662
+ function assignRuleSelectors(rule, selectors, meta) {
1663
+ const current = rule.selectors ?? [];
1664
+ const currentSignature = toSelectorSignature(current);
1665
+ const nextSignature = toSelectorSignature(selectors);
1666
+ if (currentSignature === nextSignature) {
1667
+ return false;
1668
+ }
1669
+ const state = getRuleSelectorMutationState(rule);
1670
+ if (state.seen.has(nextSignature)) {
1671
+ throw createSelectorCycleError(meta, state, selectors);
1672
+ }
1673
+ state.count += 1;
1674
+ if (state.count > DEFAULT_SELECTOR_MUTATION_LIMIT) {
1675
+ throw createSelectorCycleError(meta, state, selectors);
1676
+ }
1677
+ pushTrace(state, meta, selectors);
1678
+ state.seen.add(nextSignature);
1679
+ rule.selectors = selectors;
1680
+ return true;
1681
+ }
1682
+ function appendRuleSelector(rule, selector, meta) {
1683
+ const current = rule.selectors ?? [];
1684
+ if (current.includes(selector)) {
1685
+ return false;
1686
+ }
1687
+ return assignRuleSelectors(rule, [...current, selector], meta);
1688
+ }
1689
+
1519
1690
  // src/plugins/post/decl-dedupe.ts
1520
1691
  var logicalPropMap = /* @__PURE__ */ new Map([
1521
1692
  // margin 方向映射
@@ -1684,6 +1855,7 @@ function createRootSpecificityCleaner(options) {
1684
1855
  if (!rule.selectors || rule.selectors.length === 0) {
1685
1856
  return;
1686
1857
  }
1858
+ let changed = false;
1687
1859
  const next = rule.selectors.map((selector) => {
1688
1860
  let updated = selector;
1689
1861
  for (const target of targets) {
@@ -1694,9 +1866,15 @@ function createRootSpecificityCleaner(options) {
1694
1866
  updated = updated.split(target.spacedMatch).join(target.replacement);
1695
1867
  }
1696
1868
  }
1869
+ if (updated !== selector) {
1870
+ changed = true;
1871
+ }
1697
1872
  return updated;
1698
1873
  });
1699
- rule.selectors = next;
1874
+ changed && assignRuleSelectors(rule, next, {
1875
+ phase: "post",
1876
+ reason: "clean-root-specificity"
1877
+ });
1700
1878
  };
1701
1879
  }
1702
1880
 
@@ -1741,7 +1919,10 @@ var postcssWeappTailwindcssPostPlugin = (options) => {
1741
1919
  cleanRootSpecificity?.(rule);
1742
1920
  if (enableMainChunkTransforms) {
1743
1921
  if (shouldAppendHostSelector?.(rule)) {
1744
- rule.selectors = [...rule.selectors, ":host"];
1922
+ appendRuleSelector(rule, ":host", {
1923
+ phase: "post",
1924
+ reason: "append-host-selector"
1925
+ });
1745
1926
  }
1746
1927
  dedupeDeclarations(rule);
1747
1928
  if (rule.selectors.length === 0 || rule.selectors.length === 1 && rule.selector.trim() === "") {
@@ -2047,20 +2228,39 @@ function remakeCssVarSelector(selectors, options) {
2047
2228
  }
2048
2229
  return selectors;
2049
2230
  }
2231
+ function resolveUniAppXVariableScopeSelectors(options) {
2232
+ const universal = options.cssSelectorReplacement?.universal;
2233
+ if (Array.isArray(universal) && universal.length > 0) {
2234
+ return [...universal];
2235
+ }
2236
+ if (typeof universal === "string" && universal.length > 0) {
2237
+ return [universal];
2238
+ }
2239
+ return ["view", "text"];
2240
+ }
2050
2241
  function commonChunkPreflight(node, options) {
2051
2242
  const { ctx, cssInjectPreflight, injectAdditionalCssVarScope } = options;
2243
+ const uniAppXEnabled = isUniAppXEnabled(options);
2052
2244
  const rootOption = options.cssSelectorReplacement?.root;
2053
2245
  const rootSelectors = rootOption === false || rootOption === void 0 ? [] : Array.isArray(rootOption) ? rootOption.filter(Boolean) : [rootOption];
2054
2246
  const hasHostSelector = node.selectors.some((selector) => selector.includes(":host"));
2055
2247
  const hasRootPseudoSelector = node.selectors.some((selector) => selector.includes(":root"));
2056
2248
  const hasAllDefaultRootSelectors = DEFAULT_ROOT_SELECTORS2.every((selector) => node.selectors.includes(selector));
2057
2249
  if (!hasHostSelector && !rootSelectors.includes(":host") && (hasRootPseudoSelector || rootSelectors.length === DEFAULT_ROOT_SELECTORS2.length && rootSelectors.every((selector, index) => selector === DEFAULT_ROOT_SELECTORS2[index]) && hasAllDefaultRootSelectors)) {
2058
- node.selectors = [...node.selectors, ":host"];
2250
+ appendRuleSelector(node, ":host", {
2251
+ phase: "pre",
2252
+ reason: "append-host-selector"
2253
+ });
2059
2254
  }
2060
- if (testIfVariablesScope(node)) {
2255
+ if (testIfVariablesScope(node) || uniAppXEnabled && node.selectors.includes("*") && hasTwVars(node, 2)) {
2061
2256
  ctx?.markVariablesScope(node);
2062
- node.selectors = remakeCssVarSelector(node.selectors, options);
2063
- node.before(makePseudoVarRule());
2257
+ assignRuleSelectors(node, uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : remakeCssVarSelector(node.selectors, options), {
2258
+ phase: "pre",
2259
+ reason: "rewrite-variable-scope"
2260
+ });
2261
+ if (!uniAppXEnabled) {
2262
+ node.before(makePseudoVarRule());
2263
+ }
2064
2264
  if (typeof cssInjectPreflight === "function") {
2065
2265
  node.append(...cssInjectPreflight());
2066
2266
  }
@@ -2068,12 +2268,19 @@ function commonChunkPreflight(node, options) {
2068
2268
  const isTailwindcss4 = isTailwindcssV4(options);
2069
2269
  if (injectAdditionalCssVarScope && (isTailwindcss4 ? testIfRootHostForV4(node) : testIfTwBackdrop(node))) {
2070
2270
  const syntheticRule = new Rule({
2071
- selectors: ["*", "::after", "::before"],
2271
+ selectors: uniAppXEnabled ? resolveUniAppXVariableScopeSelectors(options) : ["*", "::after", "::before"],
2072
2272
  nodes: isTailwindcss4 ? cssVarsV4Nodes : cssVarsV3Nodes
2073
2273
  });
2074
- syntheticRule.selectors = remakeCssVarSelector(syntheticRule.selectors, options);
2274
+ if (!uniAppXEnabled) {
2275
+ assignRuleSelectors(syntheticRule, remakeCssVarSelector(syntheticRule.selectors, options), {
2276
+ phase: "pre",
2277
+ reason: "rewrite-synthetic-variable-scope"
2278
+ });
2279
+ }
2075
2280
  node.before(syntheticRule);
2076
- node.before(makePseudoVarRule());
2281
+ if (!uniAppXEnabled) {
2282
+ node.before(makePseudoVarRule());
2283
+ }
2077
2284
  if (typeof cssInjectPreflight === "function") {
2078
2285
  syntheticRule.append(...cssInjectPreflight());
2079
2286
  }
@@ -2348,7 +2555,7 @@ var StyleProcessorCache = class {
2348
2555
  processor = this.processorCacheByKey.get(cacheKey);
2349
2556
  if (!processor) {
2350
2557
  const pipeline = this.getPipeline(options);
2351
- processor = postcss(pipeline.plugins);
2558
+ processor = postcss2(pipeline.plugins);
2352
2559
  this.processorCacheByKey.set(cacheKey, processor);
2353
2560
  }
2354
2561
  this.processorCache.set(options, processor);
@@ -2376,7 +2583,7 @@ function createStyleHandler(options) {
2376
2583
  return processor.process(
2377
2584
  rawSource,
2378
2585
  processOptions
2379
- ).async();
2586
+ ).async().then((result) => applyUniAppXBaseCompatibility(result, resolvedOptions));
2380
2587
  });
2381
2588
  handler.getPipeline = (opt) => {
2382
2589
  const resolvedOptions = resolver.resolve(opt);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weapp-tailwindcss/postcss",
3
- "version": "2.1.6-alpha.1",
3
+ "version": "2.1.6-alpha.3",
4
4
  "description": "@weapp-tailwindcss/postcss",
5
5
  "author": "ice breaker <1324318532@qq.com>",
6
6
  "license": "MIT",