@weapp-tailwindcss/postcss 3.3.4 → 3.3.5

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.js CHANGED
@@ -1,19 +1,22 @@
1
1
  import { CSS_MACRO_POSTCSS_PLUGIN_NAME, creator, ifdefAtRule, ifndefAtRule } from "./postcss-CICDAfoB.js";
2
2
  import postcssHtmlTransform from "./html-transform.js";
3
3
  import "./types.js";
4
+ import { createRequire } from "node:module";
4
5
  import { extractValidCandidates, resolveProjectSourceFiles, splitCandidateTokens } from "@tailwindcss-mangle/engine";
5
6
  import postcss, { Declaration, Rule, parse, rule, default as postcss$1 } from "postcss";
6
- import scssSyntax from "postcss-scss";
7
+ import scss, { default as scssSyntax } from "postcss-scss";
7
8
  import postcssCalc from "@weapp-tailwindcss/postcss-calc";
8
9
  import selectorParser from "postcss-selector-parser";
9
10
  import valueParser from "postcss-value-parser";
10
11
  import { color, serializeRGB } from "@csstools/css-color-parser";
11
12
  import { parseComponentValue } from "@csstools/css-parser-algorithms";
12
- import { tokenize } from "@csstools/css-tokenizer";
13
- import postcssPresetEnv from "postcss-preset-env";
13
+ import { TokenType, tokenize } from "@csstools/css-tokenizer";
14
+ import path, { resolve } from "node:path";
14
15
  import { MappingChars2String, escape } from "@weapp-core/escape";
15
- import path from "node:path";
16
+ import postcssPresetEnv from "postcss-preset-env";
16
17
  import process from "node:process";
18
+ import { pathToFileURL } from "node:url";
19
+ import postcssrc from "postcss-load-config";
17
20
  import { realpathSync } from "node:fs";
18
21
  import { readFile, stat } from "node:fs/promises";
19
22
  import micromatch from "micromatch";
@@ -25,12 +28,38 @@ import autoprefixerPlugin from "autoprefixer";
25
28
  import postcssPxtrans from "postcss-pxtrans";
26
29
  import postcssRem2rpx from "postcss-rem-to-responsive-pixel";
27
30
  import postcssUnitConverter, { composeRules as unitConversionComposeRules, presets, presets as unitConversionPresets } from "postcss-rule-unit-converter";
28
- import postcssrc from "postcss-load-config";
29
31
  //#region src/branches/mini-program/index.ts
30
32
  function postprocessMiniProgramCss(result, _options) {
31
33
  return result;
32
34
  }
33
35
  //#endregion
36
+ //#region src/syntax/parse.ts
37
+ /** 解析标准 CSS;调用方负责处理非法输入。 */
38
+ function parseCssSource(source, from) {
39
+ return postcss$1.parse(source, { from });
40
+ }
41
+ /**
42
+ * 解析 SCSS/Sass 风格源码。
43
+ * `postcss.parse` 不读取 syntax 选项,行注释和插值必须走 SCSS parser。
44
+ */
45
+ function parseScssSource(source, from) {
46
+ return scssSyntax.parse(source, { from });
47
+ }
48
+ function stringifyScssSource(root) {
49
+ return root.toString(scssSyntax.stringify);
50
+ }
51
+ /** Harmony 在 Sass 预处理前读取局部样式;必须识别行注释,避免将其并入选择器。 */
52
+ function parseUniAppXStyleSource(source) {
53
+ return parseScssSource(source);
54
+ }
55
+ function isUniAppXStyleSourceEmpty(source) {
56
+ try {
57
+ return parseUniAppXStyleSource(source).nodes.every((node) => node.type === "comment");
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ //#endregion
34
63
  //#region src/compat/uni-app-x.ts
35
64
  /** native Sass 可解析、PostCSS 阶段再还原的 important utility 标记。 */
36
65
  const UNI_APP_X_IMPORTANT_APPLY_MARKER = "__weapp_tw_important__";
@@ -45,7 +74,7 @@ const UNI_APP_X_BASE_CARRIER_SELECTORS = /* @__PURE__ */ new Set([
45
74
  "::backdrop"
46
75
  ]);
47
76
  const REQUIRED_TW_VAR_RE = /var\(\s*(--tw-[\w-]+)\s*\)/g;
48
- const CLASS_SELECTOR_RE$1 = /\.[\w-]+/;
77
+ const CLASS_SELECTOR_RE$2 = /\.[\w-]+/;
49
78
  const SELECTOR_WHITESPACE_RE = /\s+/g;
50
79
  function rewriteImportantApplyUtility(utility, marker) {
51
80
  if (utility.startsWith("!") && !utility.startsWith("\\!")) return `${utility.slice(1)}${marker}`;
@@ -65,7 +94,7 @@ function rewriteApplyParams(params, marker) {
65
94
  /** 将 Sass 不可直接解析的 important utility 改写成跨预处理器中间形式。 */
66
95
  function normalizeUniAppXImportantApplyForSass(css) {
67
96
  try {
68
- const root = scssSyntax.parse(css, { from: void 0 });
97
+ const root = parseScssSource(css);
69
98
  let changed = false;
70
99
  root.walkAtRules("apply", (rule) => {
71
100
  const params = rewriteApplyParams(rule.params, UNI_APP_X_IMPORTANT_APPLY_MARKER);
@@ -74,7 +103,7 @@ function normalizeUniAppXImportantApplyForSass(css) {
74
103
  changed = true;
75
104
  }
76
105
  });
77
- return changed ? root.toString(scssSyntax.stringify) : css;
106
+ return changed ? stringifyScssSource(root) : css;
78
107
  } catch {
79
108
  return css;
80
109
  }
@@ -98,17 +127,17 @@ function restoreUniAppXImportantApplyMarker(css) {
98
127
  function isUniAppXEnabled(options) {
99
128
  return Boolean(options?.uniAppX);
100
129
  }
101
- function normalizeSelector$3(selector) {
130
+ function normalizeSelector$4(selector) {
102
131
  return selector.replace(SELECTOR_WHITESPACE_RE, "").toLowerCase();
103
132
  }
104
133
  function isBaseCarrierSelector(selector) {
105
- return UNI_APP_X_BASE_CARRIER_SELECTORS.has(normalizeSelector$3(selector));
134
+ return UNI_APP_X_BASE_CARRIER_SELECTORS.has(normalizeSelector$4(selector));
106
135
  }
107
136
  function isBaseCarrierRule(rule) {
108
137
  return Array.isArray(rule.selectors) && rule.selectors.length > 0 && rule.selectors.every(isBaseCarrierSelector);
109
138
  }
110
- function hasClassSelector$2(rule) {
111
- return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE$1.test(selector));
139
+ function hasClassSelector$3(rule) {
140
+ return Array.isArray(rule.selectors) && rule.selectors.some((selector) => CLASS_SELECTOR_RE$2.test(selector));
112
141
  }
113
142
  function collectRequiredTwVars(value) {
114
143
  const result = /* @__PURE__ */ new Set();
@@ -137,7 +166,7 @@ function extractUniAppXBaseDefaults(result) {
137
166
  function injectUniAppXBaseDefaults(result, defaults) {
138
167
  if (defaults.size === 0) return;
139
168
  result.root.walkRules((rule) => {
140
- if (!hasClassSelector$2(rule)) return;
169
+ if (!hasClassSelector$3(rule)) return;
141
170
  const declaredProps = /* @__PURE__ */ new Set();
142
171
  const requiredProps = /* @__PURE__ */ new Set();
143
172
  rule.walkDecls((decl) => {
@@ -784,7 +813,7 @@ const MINI_PROGRAM_NATIVE_ELEMENT_SELECTORS = /* @__PURE__ */ new Set([
784
813
  "audio"
785
814
  ]);
786
815
  const MINI_PROGRAM_PREFLIGHT_SELECTORS$1 = /* @__PURE__ */ new Set(["*", ...MINI_PROGRAM_ELEMENT_SCOPE_SELECTORS]);
787
- const MINI_PROGRAM_THEME_SCOPE_SELECTORS = /* @__PURE__ */ new Set([
816
+ const MINI_PROGRAM_THEME_SCOPE_SELECTORS$1 = /* @__PURE__ */ new Set([
788
817
  ":host",
789
818
  ":root",
790
819
  "page",
@@ -867,11 +896,11 @@ const MINI_PROGRAM_UNSUPPORTED_BROWSER_TAG_SELECTORS = /* @__PURE__ */ new Set([
867
896
  "video"
868
897
  ]);
869
898
  const MINI_PROGRAM_UNSUPPORTED_BROWSER_PREFLIGHT_SELECTOR_PARTS = /* @__PURE__ */ new Set([...MINI_PROGRAM_UNSUPPORTED_BROWSER_TAG_SELECTORS, "::file-selector-button"]);
870
- function normalizeSelector$2(selector) {
899
+ function normalizeSelector$3(selector) {
871
900
  return selector.trim().replace(/\s+/g, "");
872
901
  }
873
902
  function normalizePseudoElementSelector(selector) {
874
- return normalizeSelector$2(selector).replace(/^:(before|after)$/, "::$1");
903
+ return normalizeSelector$3(selector).replace(/^:(before|after)$/, "::$1");
875
904
  }
876
905
  function getRuleSelectors(rule) {
877
906
  return rule.selector.split(",").map(normalizePseudoElementSelector).filter(Boolean);
@@ -880,11 +909,11 @@ function getSortedRuleSelectorKey(rule) {
880
909
  return getRuleSelectors(rule).sort().join(",");
881
910
  }
882
911
  function isUnsupportedBrowserSelector(selector) {
883
- const normalized = normalizeSelector$2(selector);
912
+ const normalized = normalizeSelector$3(selector);
884
913
  return MINI_PROGRAM_UNSUPPORTED_BROWSER_SELECTORS.has(normalized) || MINI_PROGRAM_UNSUPPORTED_BROWSER_TAG_SELECTORS.has(normalized) && !MINI_PROGRAM_NATIVE_ELEMENT_SELECTORS.has(normalized);
885
914
  }
886
915
  function isUnsupportedBrowserPreflightSelector(selector) {
887
- const normalizedParts = selector.split(",").map(normalizeSelector$2).filter(Boolean);
916
+ const normalizedParts = selector.split(",").map(normalizeSelector$3).filter(Boolean);
888
917
  return normalizedParts.length > 1 && normalizedParts.every((part) => MINI_PROGRAM_UNSUPPORTED_BROWSER_PREFLIGHT_SELECTOR_PARTS.has(part));
889
918
  }
890
919
  function isMiniProgramNativeElementSelector(selector) {
@@ -893,8 +922,8 @@ function isMiniProgramNativeElementSelector(selector) {
893
922
  function isMiniProgramPreflightSelector(selectors) {
894
923
  return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_PREFLIGHT_SELECTORS$1.has(selector)) && selectors.some((selector) => selector === "*" || selector === ":before" || selector === ":after" || selector === "::before" || selector === "::after");
895
924
  }
896
- function isMiniProgramThemeScopeSelector(selectors) {
897
- return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_THEME_SCOPE_SELECTORS.has(selector));
925
+ function isMiniProgramThemeScopeSelector$1(selectors) {
926
+ return selectors.length > 0 && selectors.every((selector) => MINI_PROGRAM_THEME_SCOPE_SELECTORS$1.has(selector));
898
927
  }
899
928
  //#endregion
900
929
  //#region src/compat/mini-program-css/predicates.ts
@@ -948,7 +977,7 @@ function isOnlyTwContentDeclarations$1(rule) {
948
977
  });
949
978
  return hasDeclaration && onlyContentVariable;
950
979
  }
951
- function isPseudoContentInitRule(rule) {
980
+ function isPseudoContentInitRule$1(rule) {
952
981
  const selector = rule.selector.replace(/\s+/g, "");
953
982
  return PSEUDO_CONTENT_SELECTOR_RE.test(selector) && isOnlyTwContentDeclarations$1(rule);
954
983
  }
@@ -985,7 +1014,7 @@ function isBrowserElementPreflightRule(node) {
985
1014
  }
986
1015
  function isMiniProgramThemeVariableRule(node) {
987
1016
  if (node.type !== "rule") return false;
988
- return isMiniProgramThemeScopeSelector(getRuleSelectors(node)) && isCustomPropertyRule(node);
1017
+ return isMiniProgramThemeScopeSelector$1(getRuleSelectors(node)) && isCustomPropertyRule(node);
989
1018
  }
990
1019
  //#endregion
991
1020
  //#region src/compat/mini-program-css/root-cleanups.ts
@@ -1017,7 +1046,7 @@ function removeRootSpecificityPlaceholders(root) {
1017
1046
  let changed = false;
1018
1047
  const selectors = rule.selectors.map((selector) => {
1019
1048
  let next = selector;
1020
- for (const scopeSelector of MINI_PROGRAM_THEME_SCOPE_SELECTORS) for (const suffix of ROOT_SPECIFICITY_PLACEHOLDER_SUFFIXES) {
1049
+ for (const scopeSelector of MINI_PROGRAM_THEME_SCOPE_SELECTORS$1) for (const suffix of ROOT_SPECIFICITY_PLACEHOLDER_SUFFIXES) {
1021
1050
  const target = `${scopeSelector}${suffix}`;
1022
1051
  if (next.includes(target)) next = next.split(target).join(scopeSelector);
1023
1052
  }
@@ -1595,6 +1624,151 @@ function isTailwindcssV4DisplayP3Declaration(decl) {
1595
1624
  return DISPLAY_P3_VALUE_RE$1.test(decl.value);
1596
1625
  }
1597
1626
  //#endregion
1627
+ //#region src/syntax/css-import.ts
1628
+ function significantTokens(params) {
1629
+ return tokenize({ css: params }).filter((token) => token[0] !== TokenType.Whitespace && token[0] !== TokenType.Comment);
1630
+ }
1631
+ function isCssWhitespace$2(char) {
1632
+ return char === " " || char === " " || char === "\n" || char === "\r" || char === "\f";
1633
+ }
1634
+ function skipCssWhitespace$1(params, index) {
1635
+ while (index < params.length && isCssWhitespace$2(params[index])) index++;
1636
+ return index;
1637
+ }
1638
+ function parseSimpleQuotedSpecifier(params, start) {
1639
+ const quote = params[start];
1640
+ if (quote !== "\"" && quote !== "'") return;
1641
+ let index = start + 1;
1642
+ while (index < params.length) {
1643
+ const char = params[index];
1644
+ if (char === "\\" || char === "\n" || char === "\r") return;
1645
+ if (char === quote) return {
1646
+ specifier: params.slice(start + 1, index),
1647
+ raw: params.slice(start, index + 1),
1648
+ quote
1649
+ };
1650
+ index++;
1651
+ }
1652
+ }
1653
+ function parseSimpleImportSpecifier(params) {
1654
+ let index = skipCssWhitespace$1(params, 0);
1655
+ const quoted = parseSimpleQuotedSpecifier(params, index);
1656
+ if (quoted) return quoted;
1657
+ if (params.slice(index, index + 4).toLowerCase() !== "url(") return;
1658
+ const urlStart = index;
1659
+ index = skipCssWhitespace$1(params, index + 4);
1660
+ const inner = parseSimpleQuotedSpecifier(params, index);
1661
+ if (!inner) return;
1662
+ index = skipCssWhitespace$1(params, index + inner.raw.length);
1663
+ if (params[index] !== ")") return;
1664
+ return {
1665
+ specifier: inner.specifier,
1666
+ raw: params.slice(urlStart, index + 1),
1667
+ quote: inner.quote
1668
+ };
1669
+ }
1670
+ /**
1671
+ * 解析 `@import` / `@use` / `@forward` 参数中的请求串。
1672
+ * 无 escape/注释的引号和 `url("...")` 走快路径;复杂输入才使用 CSS tokenizer。
1673
+ */
1674
+ function parseCssImportSpecifier(params) {
1675
+ const simple = parseSimpleImportSpecifier(params);
1676
+ if (simple) return simple;
1677
+ const tokens = significantTokens(params);
1678
+ const first = tokens[0];
1679
+ if (!first || first[0] === TokenType.EOF) return;
1680
+ if (first[0] === TokenType.String || first[0] === TokenType.URL || first[0] === TokenType.Ident) return {
1681
+ specifier: first[4].value,
1682
+ raw: first[1],
1683
+ quote: first[0] === TokenType.String ? first[1][0] : void 0
1684
+ };
1685
+ if (first[0] === TokenType.Function && first[4].value.toLowerCase() === "url" && (tokens[1]?.[0] === TokenType.String || tokens[1]?.[0] === TokenType.Ident) && tokens[2]?.[0] === TokenType.CloseParen) return {
1686
+ specifier: tokens[1][4].value,
1687
+ raw: params.slice(first[2], tokens[2][3] + 1),
1688
+ quote: tokens[1][0] === TokenType.String ? tokens[1][1][0] : void 0
1689
+ };
1690
+ }
1691
+ /** 把文件系统路径写成 CSS 请求串;缓存和读文件仍使用原始路径。 */
1692
+ function quoteCssImportSpecifier(file, quote = "\"") {
1693
+ return `${quote}${(path.sep === "\\" || /^[a-z]:[\\/]|^\\\\/i.test(file) ? file.replaceAll("\\", "/") : file).replaceAll("\\", "\\\\").replaceAll(quote, `\\${quote}`).replaceAll("\n", "\\a ").replaceAll("\r", "\\d ")}${quote}`;
1694
+ }
1695
+ /** 判断 import 参数是否指向 Tailwind CSS 包入口。 */
1696
+ function isTailwindCssImport(params) {
1697
+ const specifier = parseCssImportSpecifier(params)?.specifier;
1698
+ if (!specifier) return false;
1699
+ if (specifier === "tailwindcss" || specifier.startsWith("tailwindcss/")) return true;
1700
+ const paths = specifier.includes("\\") ? path.win32 : path.posix;
1701
+ return paths.basename(specifier) === "index.css" && paths.basename(paths.dirname(specifier)) === "tailwindcss";
1702
+ }
1703
+ /** 解析 `@import "..." source(...)` 中的 source 参数。 */
1704
+ function parseImportSourceParam(params) {
1705
+ const tokens = significantTokens(params);
1706
+ const index = tokens.findIndex((token) => token[0] === TokenType.Function && token[4].value === "source");
1707
+ const value = tokens[index + 1];
1708
+ if (index < 0 || tokens[index + 2]?.[0] !== TokenType.CloseParen) return;
1709
+ if (value?.[0] === TokenType.Ident && value[4].value === "none") return {
1710
+ none: true,
1711
+ sourcePath: void 0
1712
+ };
1713
+ return value?.[0] === TokenType.String ? {
1714
+ none: false,
1715
+ sourcePath: value[4].value
1716
+ } : void 0;
1717
+ }
1718
+ //#endregion
1719
+ //#region src/compat/tailwindcss-v4/theme-source.ts
1720
+ function isTailwindCssPreflightImport(params) {
1721
+ const specifier = parseCssImportSpecifier(params)?.specifier;
1722
+ return specifier === "tailwindcss/preflight.css" || specifier === "tailwindcss/preflight";
1723
+ }
1724
+ /** 从小程序入口 CSS 中移除 Tailwind v4 preflight import。 */
1725
+ function removeTailwindV4PreflightImports(css) {
1726
+ if (!css.includes("preflight")) return css;
1727
+ let root;
1728
+ try {
1729
+ root = postcss$1.parse(css);
1730
+ } catch {
1731
+ return css;
1732
+ }
1733
+ let changed = false;
1734
+ root.walkAtRules("import", (rule) => {
1735
+ if (isTailwindCssPreflightImport(rule.params)) {
1736
+ rule.remove();
1737
+ changed = true;
1738
+ }
1739
+ });
1740
+ return changed ? root.toString() : css;
1741
+ }
1742
+ function hasThemeParent(rule) {
1743
+ let parent = rule.parent;
1744
+ while (parent) {
1745
+ if (parent.type === "atrule" && parent.name === "theme") return true;
1746
+ parent = parent.parent;
1747
+ }
1748
+ return false;
1749
+ }
1750
+ function isVendorPrefixedKeyframes(rule) {
1751
+ return rule.name.startsWith("-") && rule.name.endsWith("keyframes");
1752
+ }
1753
+ /** 删除 `@theme` 内不被小程序接受的厂商前缀 keyframes。 */
1754
+ function removeUnsupportedThemeVendorKeyframes(css) {
1755
+ if (!css.includes("@theme") || !css.includes("@-")) return css;
1756
+ let root;
1757
+ try {
1758
+ root = postcss$1.parse(css);
1759
+ } catch {
1760
+ return css;
1761
+ }
1762
+ let changed = false;
1763
+ root.walkAtRules((rule) => {
1764
+ if (isVendorPrefixedKeyframes(rule) && hasThemeParent(rule)) {
1765
+ rule.remove();
1766
+ changed = true;
1767
+ }
1768
+ });
1769
+ return changed ? root.toString() : css;
1770
+ }
1771
+ //#endregion
1598
1772
  //#region src/compat/uni-app-x-uvue/scoped-style.ts
1599
1773
  const MINI_PROGRAM_PREFLIGHT_SELECTORS = /* @__PURE__ */ new Set([
1600
1774
  "view",
@@ -1798,7 +1972,7 @@ const SYSTEM_ROOT_SELECTORS = /* @__PURE__ */ new Set([
1798
1972
  "uni-page-body",
1799
1973
  "wx-root-portal-content"
1800
1974
  ]);
1801
- function normalizeSelector$1(selector) {
1975
+ function normalizeSelector$2(selector) {
1802
1976
  return selector.replace(/\s+/g, "").toLowerCase();
1803
1977
  }
1804
1978
  function isUniAppXSystemRootCarrierRule(rule) {
@@ -1806,7 +1980,7 @@ function isUniAppXSystemRootCarrierRule(rule) {
1806
1980
  if (selectors.length === 0) return false;
1807
1981
  let hasRootMarker = false;
1808
1982
  for (const selector of selectors) {
1809
- const normalized = normalizeSelector$1(selector);
1983
+ const normalized = normalizeSelector$2(selector);
1810
1984
  if (!SYSTEM_ROOT_SELECTORS.has(normalized)) return false;
1811
1985
  if (normalized === ":host" || normalized === ":root" || normalized === ".tw-root") hasRootMarker = true;
1812
1986
  }
@@ -1912,7 +2086,7 @@ function isUniAppXUvueTarget(options) {
1912
2086
  function normalizeUnsupportedMode(mode) {
1913
2087
  return mode ?? "warn";
1914
2088
  }
1915
- function normalizeValue(value) {
2089
+ function normalizeValue$1(value) {
1916
2090
  return value.trim().toLowerCase().replace(IMPORTANT_SUFFIX_RE, "");
1917
2091
  }
1918
2092
  function hasCalcFunction(value) {
@@ -1966,7 +2140,7 @@ function hasOnlyClassSelectors(rule) {
1966
2140
  }
1967
2141
  function getUnsupportedDeclarationReason(prop, value) {
1968
2142
  const normalizedProp = prop.trim().toLowerCase();
1969
- const normalizedValue = normalizeValue(value);
2143
+ const normalizedValue = normalizeValue$1(value);
1970
2144
  if (hasCalcFunction(value)) return `${normalizedProp}: ${value}`;
1971
2145
  if (normalizedProp === "display" && !ALLOWED_DISPLAY_VALUES.has(normalizedValue)) return `${normalizedProp}: ${value}`;
1972
2146
  if (normalizedProp === "min-height" && normalizedValue === "100vh") return `${normalizedProp}: ${value}`;
@@ -2168,6 +2342,395 @@ function resolvePostcssStyleBranchProfile(options) {
2168
2342
  return resolvePostcssFrameworkProfile(options);
2169
2343
  }
2170
2344
  //#endregion
2345
+ //#region src/compat/author-selector.ts
2346
+ /** 保留作者选择器在变体展开后增加前缀、伪类或主题条件的规则。 */
2347
+ function createAuthorSelectorMatcher(selectors) {
2348
+ const exact = /* @__PURE__ */ new Set();
2349
+ const compounds = [];
2350
+ for (const selector of selectors) {
2351
+ exact.add(selector.trim());
2352
+ selectorParser().astSync(selector).each((entry) => {
2353
+ if (!entry.nodes.some((node) => node.type === "combinator") && entry.nodes.some((node) => node.type === "class" || node.type === "id")) compounds.push(entry.nodes.map((node) => node.toString().trim()));
2354
+ });
2355
+ }
2356
+ return (selector) => {
2357
+ if (exact.has(selector.trim())) return true;
2358
+ const entries = selectorParser().astSync(selector).nodes;
2359
+ return entries.length > 0 && entries.every((entry) => {
2360
+ const lastCombinator = entry.nodes.findLastIndex((node) => node.type === "combinator");
2361
+ const subject = new Set(entry.nodes.slice(lastCombinator + 1).map((node) => node.toString().trim()));
2362
+ return compounds.some((nodes) => nodes.every((node) => subject.has(node)));
2363
+ });
2364
+ };
2365
+ }
2366
+ //#endregion
2367
+ //#region src/compat/legacy-css/apply.ts
2368
+ /** 删除兼容源中的 `@apply` 规则及其空包装 at-rule。 */
2369
+ function removeTailwindApplyRules(rawSource) {
2370
+ try {
2371
+ const root = postcss$1.parse(rawSource);
2372
+ let removed = false;
2373
+ root.walkAtRules("apply", (rule) => {
2374
+ const parent = rule.parent;
2375
+ if (parent?.type === "rule") parent.remove();
2376
+ else rule.remove();
2377
+ removed = true;
2378
+ });
2379
+ root.walkAtRules((rule) => {
2380
+ if (rule.nodes && rule.nodes.length === 0) rule.remove();
2381
+ });
2382
+ return removed ? root.toString() : rawSource;
2383
+ } catch {
2384
+ return rawSource;
2385
+ }
2386
+ }
2387
+ //#endregion
2388
+ //#region src/compat/legacy-css/selectors.ts
2389
+ const CLASS_SELECTOR_RE$1 = /(?:^|[^\w-])\.[_a-z\u00A0-\uFFFF\\-]/i;
2390
+ const MINI_PROGRAM_THEME_SCOPE_SELECTORS = /* @__PURE__ */ new Set([
2391
+ ":host",
2392
+ "page",
2393
+ ".tw-root",
2394
+ "wx-root-portal-content"
2395
+ ]);
2396
+ const SPECIFICITY_PLACEHOLDER_RE = /:not\(#(?:\\#|n)\)/g;
2397
+ const SELECTOR_CACHE_LIMIT = 64;
2398
+ const LEGACY_PSEUDO_ELEMENTS = [
2399
+ "before",
2400
+ "after",
2401
+ "first-letter",
2402
+ "first-line"
2403
+ ];
2404
+ const generatedSelectorCache = /* @__PURE__ */ new Map();
2405
+ function setGeneratedSelectorCache(css, selectors) {
2406
+ if (generatedSelectorCache.size >= SELECTOR_CACHE_LIMIT) {
2407
+ const firstKey = generatedSelectorCache.keys().next().value;
2408
+ if (firstKey !== void 0) generatedSelectorCache.delete(firstKey);
2409
+ }
2410
+ generatedSelectorCache.set(css, selectors);
2411
+ }
2412
+ function normalizeCompatSelector(selector) {
2413
+ return selector.replace(SPECIFICITY_PLACEHOLDER_RE, "").replace(/\s+/g, " ").trim();
2414
+ }
2415
+ function isLegacyPseudoElementAt(selector, index) {
2416
+ for (const name of LEGACY_PSEUDO_ELEMENTS) {
2417
+ if (!selector.startsWith(name, index)) continue;
2418
+ const next = selector[index + name.length];
2419
+ if (next === void 0 || !/[\w-]/.test(next)) return name;
2420
+ }
2421
+ }
2422
+ function normalizeLegacyPseudoElements(selector) {
2423
+ let result = "";
2424
+ let quote;
2425
+ let bracketDepth = 0;
2426
+ let index = 0;
2427
+ while (index < selector.length) {
2428
+ const char = selector[index];
2429
+ if (char === "\\") {
2430
+ result += selector.slice(index, index + 2);
2431
+ index += 2;
2432
+ continue;
2433
+ }
2434
+ if (quote !== void 0) {
2435
+ result += char;
2436
+ if (char === quote) quote = void 0;
2437
+ index += 1;
2438
+ continue;
2439
+ }
2440
+ if (char === "\"" || char === "'") {
2441
+ quote = char;
2442
+ result += char;
2443
+ index += 1;
2444
+ continue;
2445
+ }
2446
+ if (char === "[") {
2447
+ bracketDepth++;
2448
+ result += char;
2449
+ index += 1;
2450
+ continue;
2451
+ }
2452
+ if (char === "]") {
2453
+ bracketDepth = Math.max(0, bracketDepth - 1);
2454
+ result += char;
2455
+ index += 1;
2456
+ continue;
2457
+ }
2458
+ if (bracketDepth === 0 && char === ":" && selector[index + 1] === ":") {
2459
+ result += "::";
2460
+ index += 2;
2461
+ continue;
2462
+ }
2463
+ if (bracketDepth === 0 && char === ":") {
2464
+ const name = isLegacyPseudoElementAt(selector, index + 1);
2465
+ if (name) {
2466
+ result += `::${name}`;
2467
+ index += name.length + 1;
2468
+ continue;
2469
+ }
2470
+ }
2471
+ result += char;
2472
+ index += 1;
2473
+ }
2474
+ return result;
2475
+ }
2476
+ function isClassSelectorTerminator(char) {
2477
+ return /[\s>+~#,.:()[\]]/.test(char);
2478
+ }
2479
+ function unescapeSimpleCssIdent(value) {
2480
+ return value.replaceAll(/\\(.)/g, "$1");
2481
+ }
2482
+ function escapeCompatSelectorClasses(selector) {
2483
+ let result = "";
2484
+ let index = 0;
2485
+ let changed = false;
2486
+ while (index < selector.length) {
2487
+ const char = selector[index];
2488
+ if (char !== ".") {
2489
+ result += char;
2490
+ index += 1;
2491
+ continue;
2492
+ }
2493
+ let end = index + 1;
2494
+ let className = "";
2495
+ while (end < selector.length) {
2496
+ const current = selector[end];
2497
+ if (current === void 0) break;
2498
+ if (current === "\\" && end + 1 < selector.length) {
2499
+ const escaped = selector[end + 1];
2500
+ if (escaped === void 0) break;
2501
+ className += current + escaped;
2502
+ end += 2;
2503
+ continue;
2504
+ }
2505
+ if (isClassSelectorTerminator(current)) break;
2506
+ className += current;
2507
+ end += 1;
2508
+ }
2509
+ if (className.includes("\\")) {
2510
+ result += `.${escape(unescapeSimpleCssIdent(className))}`;
2511
+ changed = true;
2512
+ } else result += `.${className}`;
2513
+ index = end;
2514
+ }
2515
+ return changed ? result : selector;
2516
+ }
2517
+ function normalizeCompatSelectors(selector) {
2518
+ const normalized = normalizeCompatSelector(selector);
2519
+ if (!normalized) return [];
2520
+ const selectors = /* @__PURE__ */ new Set([normalized]);
2521
+ const escaped = normalizeCompatSelector(escapeCompatSelectorClasses(normalized));
2522
+ if (escaped) selectors.add(escaped);
2523
+ return [...selectors];
2524
+ }
2525
+ function normalizeCssSelector(selector) {
2526
+ return normalizeLegacyPseudoElements(selector).trim().replace(/\s+/g, "");
2527
+ }
2528
+ function getCompatSelectorKeys(selector) {
2529
+ return normalizeCompatSelectors(selector).map(normalizeCssSelector);
2530
+ }
2531
+ function getRuleCompatSelectorKeys(rule) {
2532
+ return (rule.selectors?.length ? rule.selectors : [rule.selector]).flatMap((selector) => getCompatSelectorKeys(selector));
2533
+ }
2534
+ function hasClassSelector$2(selector) {
2535
+ return CLASS_SELECTOR_RE$1.test(selector);
2536
+ }
2537
+ function getNormalizedSelectorList(selector) {
2538
+ return selector.split(",").map(normalizeCssSelector).filter(Boolean);
2539
+ }
2540
+ function isMiniProgramThemeScopeSelector(selector) {
2541
+ const selectors = getNormalizedSelectorList(selector);
2542
+ return selectors.length > 0 && selectors.every((item) => MINI_PROGRAM_THEME_SCOPE_SELECTORS.has(item));
2543
+ }
2544
+ function hasUtilityClassSelector(selector) {
2545
+ return hasClassSelector$2(selector) && !isMiniProgramThemeScopeSelector(selector);
2546
+ }
2547
+ function isCustomPropertyOnlyRule(rule) {
2548
+ let hasDeclaration = false;
2549
+ let allCustomProperties = true;
2550
+ rule.each((node) => {
2551
+ if (node.type !== "decl") return;
2552
+ hasDeclaration = true;
2553
+ if (!node.prop.startsWith("--")) allCustomProperties = false;
2554
+ });
2555
+ return hasDeclaration && allCustomProperties;
2556
+ }
2557
+ function isPseudoContentInitRule(rule) {
2558
+ let hasDeclaration = false;
2559
+ let onlyContentVariable = true;
2560
+ rule.each((node) => {
2561
+ if (node.type !== "decl") return;
2562
+ hasDeclaration = true;
2563
+ if (node.prop !== "--tw-content") onlyContentVariable = false;
2564
+ });
2565
+ return hasDeclaration && onlyContentVariable;
2566
+ }
2567
+ function collectGeneratedSelectors(css) {
2568
+ const cached = generatedSelectorCache.get(css);
2569
+ if (cached) return cached;
2570
+ const selectors = /* @__PURE__ */ new Set();
2571
+ try {
2572
+ postcss$1.parse(css).walkRules((rule) => {
2573
+ if (isCustomPropertyOnlyRule(rule) && !isPseudoContentInitRule(rule) && !hasUtilityClassSelector(rule.selector)) return;
2574
+ for (const selector of getRuleCompatSelectorKeys(rule)) selectors.add(selector);
2575
+ });
2576
+ } catch {
2577
+ return selectors;
2578
+ }
2579
+ setGeneratedSelectorCache(css, selectors);
2580
+ return selectors;
2581
+ }
2582
+ //#endregion
2583
+ //#region src/compat/legacy-css/dedupe.ts
2584
+ function collectGeneratedDeclarationPropsBySelector(generatedCss, selectors) {
2585
+ const propsBySelector = /* @__PURE__ */ new Map();
2586
+ try {
2587
+ postcss$1.parse(generatedCss).walkRules((rule) => {
2588
+ const matchedSelectors = getRuleCompatSelectorKeys(rule).filter((selector) => selectors.has(selector));
2589
+ if (matchedSelectors.length === 0) return;
2590
+ const props = /* @__PURE__ */ new Set();
2591
+ rule.walkDecls((decl) => {
2592
+ props.add(decl.prop);
2593
+ });
2594
+ for (const selector of matchedSelectors) {
2595
+ const existing = propsBySelector.get(selector);
2596
+ if (existing) for (const prop of props) existing.add(prop);
2597
+ else propsBySelector.set(selector, new Set(props));
2598
+ }
2599
+ });
2600
+ } catch {
2601
+ return propsBySelector;
2602
+ }
2603
+ return propsBySelector;
2604
+ }
2605
+ function isRuleCoveredByGeneratedProps(rule, generatedDeclarationPropsBySelector) {
2606
+ const nodeSelectors = getRuleCompatSelectorKeys(rule);
2607
+ if (nodeSelectors.length === 0) return false;
2608
+ const props = /* @__PURE__ */ new Set();
2609
+ rule.walkDecls((decl) => {
2610
+ props.add(decl.prop);
2611
+ });
2612
+ if (props.size === 0) return false;
2613
+ for (const selector of nodeSelectors) {
2614
+ const generatedProps = generatedDeclarationPropsBySelector.get(selector);
2615
+ if (!generatedProps) continue;
2616
+ if ([...props].every((prop) => generatedProps.has(prop))) return true;
2617
+ }
2618
+ return false;
2619
+ }
2620
+ function removeGeneratedSelectorCompatCss(css, generatedCss) {
2621
+ const generatedSelectors = collectGeneratedSelectors(generatedCss);
2622
+ if (generatedSelectors.size === 0) return css;
2623
+ try {
2624
+ const root = postcss$1.parse(css);
2625
+ let removed = false;
2626
+ root.walkRules((rule) => {
2627
+ if (isPseudoContentInitRule(rule)) {
2628
+ rule.remove();
2629
+ removed = true;
2630
+ return;
2631
+ }
2632
+ if (isCustomPropertyOnlyRule(rule) && !isPseudoContentInitRule(rule) && !hasUtilityClassSelector(rule.selector)) return;
2633
+ if (getRuleCompatSelectorKeys(rule).some((selector) => generatedSelectors.has(selector))) {
2634
+ rule.remove();
2635
+ removed = true;
2636
+ }
2637
+ });
2638
+ root.walkAtRules((atRule) => {
2639
+ if (atRule.nodes && atRule.nodes.length === 0) atRule.remove();
2640
+ });
2641
+ return removed ? root.toString() : css;
2642
+ } catch {
2643
+ return css;
2644
+ }
2645
+ }
2646
+ function collectDedupedPostTransformCompatCss(css, generatedCss) {
2647
+ const generatedSelectors = collectGeneratedSelectors(generatedCss);
2648
+ if (generatedSelectors.size === 0) return css;
2649
+ const generatedDeclarationPropsBySelector = collectGeneratedDeclarationPropsBySelector(generatedCss, generatedSelectors);
2650
+ const preservedNodes = [];
2651
+ try {
2652
+ const root = postcss$1.parse(css);
2653
+ root.each((node) => {
2654
+ if (node.type === "rule") {
2655
+ const nodeSelectors = getRuleCompatSelectorKeys(node);
2656
+ if (!nodeSelectors.some((selector) => generatedSelectors.has(selector))) {
2657
+ preservedNodes.push(node.clone());
2658
+ return;
2659
+ }
2660
+ if (isRuleCoveredByGeneratedProps(node, generatedDeclarationPropsBySelector)) return;
2661
+ if (isCustomPropertyOnlyRule(node) && !isPseudoContentInitRule(node) && !hasUtilityClassSelector(node.selector)) {
2662
+ const declarationProps = /* @__PURE__ */ new Set();
2663
+ node.walkDecls((decl) => {
2664
+ declarationProps.add(decl.prop);
2665
+ });
2666
+ for (const selector of nodeSelectors) {
2667
+ const generatedProps = generatedDeclarationPropsBySelector.get(selector);
2668
+ if (!generatedProps) continue;
2669
+ for (const prop of generatedProps) declarationProps.delete(prop);
2670
+ }
2671
+ const nextRule = node.clone();
2672
+ nextRule.walkDecls((decl) => {
2673
+ if (!declarationProps.has(decl.prop)) decl.remove();
2674
+ });
2675
+ if (nextRule.nodes.length > 0) preservedNodes.push(nextRule);
2676
+ }
2677
+ return;
2678
+ }
2679
+ preservedNodes.push(node.clone());
2680
+ });
2681
+ if (preservedNodes.length === root.nodes.length) return css;
2682
+ const nextRoot = postcss$1.root();
2683
+ nextRoot.append(preservedNodes);
2684
+ return nextRoot.toString();
2685
+ } catch {
2686
+ return css;
2687
+ }
2688
+ }
2689
+ //#endregion
2690
+ //#region src/compat/legacy-css/units.ts
2691
+ const CSS_LENGTH_UNIT_RE = /(?:^|[\s(,])[-+]?(?:\d+|\d*\.\d+)(?:px|rem)\b/i;
2692
+ const RPX_UNIT_RE = /(?:^|[\s(,])[-+]?(?:\d+|\d*\.\d+)rpx\b/i;
2693
+ function createLegacyDeclarationValueMap(css) {
2694
+ const values = /* @__PURE__ */ new Map();
2695
+ postcss$1.parse(css).walkRules((rule) => {
2696
+ if (!rule.selectors || rule.selectors.length === 0) return;
2697
+ for (const selector of rule.selectors) {
2698
+ const normalizedSelectors = normalizeCompatSelectors(selector);
2699
+ rule.walkDecls((decl) => {
2700
+ if (RPX_UNIT_RE.test(decl.value)) for (const normalizedSelector of normalizedSelectors) values.set(`${normalizedSelector}\n${decl.prop}`, decl.value);
2701
+ });
2702
+ }
2703
+ });
2704
+ return values;
2705
+ }
2706
+ function inheritLegacyUnitConvertedDeclarations(css, legacyCss) {
2707
+ try {
2708
+ const legacyValues = createLegacyDeclarationValueMap(legacyCss);
2709
+ if (legacyValues.size === 0) return css;
2710
+ const root = postcss$1.parse(css);
2711
+ let changed = false;
2712
+ root.walkRules((rule) => {
2713
+ if (!rule.selectors || rule.selectors.length === 0) return;
2714
+ const selectors = rule.selectors.flatMap((selector) => normalizeCompatSelectors(selector));
2715
+ if (selectors.length === 0) return;
2716
+ rule.walkDecls((decl) => {
2717
+ if (!CSS_LENGTH_UNIT_RE.test(decl.value)) return;
2718
+ for (const selector of selectors) {
2719
+ const legacyValue = legacyValues.get(`${selector}\n${decl.prop}`);
2720
+ if (legacyValue && legacyValue !== decl.value) {
2721
+ decl.value = legacyValue;
2722
+ changed = true;
2723
+ return;
2724
+ }
2725
+ }
2726
+ });
2727
+ });
2728
+ return changed ? root.toString() : css;
2729
+ } catch {
2730
+ return css;
2731
+ }
2732
+ }
2733
+ //#endregion
2171
2734
  //#region src/compat/lynx-css.ts
2172
2735
  const tailwindThemePropertyPatterns = [
2173
2736
  /^--aspect-/,
@@ -2479,15 +3042,33 @@ function unwrapUnsupportedCascadeLayers(css) {
2479
3042
  }
2480
3043
  }
2481
3044
  //#endregion
3045
+ //#region src/compat/mini-program-css/content-init.ts
3046
+ /** 移除候选裁剪后失去消费者的全局 content 初始化,保留用户类规则。 */
3047
+ function removeUnusedMiniProgramContentInit(root) {
3048
+ if (usesTwContentVariable(root)) return false;
3049
+ let changed = false;
3050
+ root.walkRules((rule) => {
3051
+ if (!isMiniProgramPreflightRule(rule) && !isPseudoContentInitRule$1(rule)) return;
3052
+ rule.walkDecls((decl) => {
3053
+ if (isEmptyTwContentDeclaration(decl)) {
3054
+ decl.remove();
3055
+ changed = true;
3056
+ }
3057
+ });
3058
+ if (rule.nodes.length === 0) rule.remove();
3059
+ });
3060
+ return changed;
3061
+ }
3062
+ //#endregion
2482
3063
  //#region src/compat/mini-program-css/directives.ts
2483
3064
  const TAILWIND_V4_BANNER_RE = /\/\*!\s*tailwindcss v4\./;
2484
3065
  const GENERATOR_PLACEHOLDER_COMMENT_RE = /^\s*(?:!\s*)?weapp-tailwindcss generator-placeholder\s*$/i;
2485
- function isCssWhitespace(code) {
3066
+ function isCssWhitespace$1(code) {
2486
3067
  return code === 9 || code === 10 || code === 12 || code === 13 || code === 32;
2487
3068
  }
2488
3069
  function skipCssWhitespace(css, start) {
2489
3070
  let index = start;
2490
- while (index < css.length && isCssWhitespace(css.charCodeAt(index))) index++;
3071
+ while (index < css.length && isCssWhitespace$1(css.charCodeAt(index))) index++;
2491
3072
  return index;
2492
3073
  }
2493
3074
  function findClosingParenthesis(css, openingIndex) {
@@ -2584,13 +3165,168 @@ function unwrapTailwindSourceMedia(root) {
2584
3165
  else atRule.remove();
2585
3166
  });
2586
3167
  }
2587
- function removeTailwindGenerationDirectives(root) {
2588
- root.walkComments((comment) => {
2589
- if (GENERATOR_PLACEHOLDER_COMMENT_RE.test(comment.text)) comment.remove();
2590
- });
2591
- root.walkAtRules((atRule) => {
2592
- if (atRule.name === "config" || atRule.name === "source" || atRule.name === "tailwind" || atRule.name === "reference" || atRule.name === "plugin") atRule.remove();
2593
- });
3168
+ function removeTailwindGenerationDirectives(root) {
3169
+ root.walkComments((comment) => {
3170
+ if (GENERATOR_PLACEHOLDER_COMMENT_RE.test(comment.text)) comment.remove();
3171
+ });
3172
+ root.walkAtRules((atRule) => {
3173
+ if (atRule.name === "config" || atRule.name === "source" || atRule.name === "tailwind" || atRule.name === "reference" || atRule.name === "plugin") atRule.remove();
3174
+ });
3175
+ }
3176
+ //#endregion
3177
+ //#region src/compat/mini-program-css/class-presence.ts
3178
+ /** 将已有类约束上的 class 存在条件等价改写为重复类,保留框架提权语义。 */
3179
+ function normalizeClassPresenceSelectors(root) {
3180
+ let changed = false;
3181
+ root.walkRules((rule) => {
3182
+ if (!rule.selector.includes("[")) return;
3183
+ let ruleChanged = false;
3184
+ const next = selectorParser((selectors) => {
3185
+ selectors.walkAttributes((attribute) => {
3186
+ if (attribute.attribute !== "class" || attribute.operator || attribute.namespace !== void 0) return;
3187
+ const siblings = attribute.parent?.nodes ?? [];
3188
+ const index = siblings.indexOf(attribute);
3189
+ let start = index;
3190
+ let end = index;
3191
+ while (start > 0 && siblings[start - 1].type !== "combinator") start--;
3192
+ while (end + 1 < siblings.length && siblings[end + 1].type !== "combinator") end++;
3193
+ const classNode = siblings.slice(start, end + 1).find((node) => node.type === "class");
3194
+ if (classNode) {
3195
+ attribute.replaceWith(classNode.clone({ spaces: attribute.spaces }));
3196
+ ruleChanged = true;
3197
+ }
3198
+ });
3199
+ }).processSync(rule.selector);
3200
+ if (ruleChanged) {
3201
+ rule.selector = next;
3202
+ changed = true;
3203
+ }
3204
+ });
3205
+ return changed;
3206
+ }
3207
+ //#endregion
3208
+ //#region src/compat/mini-program-css/empty-blocks.ts
3209
+ function isCssWhitespace(code) {
3210
+ return code === 9 || code === 10 || code === 12 || code === 13 || code === 32;
3211
+ }
3212
+ function isCssWordChar(code) {
3213
+ return code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || code === 95;
3214
+ }
3215
+ const EMPTY_CSS_BLOCK_RE = /\{(?:[\t\n\f\r ]|\/\*(?:[^*]|\*(?!\/))*\*\/)*\}/;
3216
+ function findCssPreludeStart(css, start, end) {
3217
+ let cursor = start;
3218
+ while (cursor < end) {
3219
+ while (cursor < end && isCssWhitespace(css.charCodeAt(cursor))) cursor++;
3220
+ if (css.charCodeAt(cursor) !== 47 || css.charCodeAt(cursor + 1) !== 42) return cursor;
3221
+ const commentEnd = css.indexOf("*/", cursor + 2);
3222
+ if (commentEnd < 0 || commentEnd + 2 > end) return end;
3223
+ cursor = commentEnd + 2;
3224
+ }
3225
+ return end;
3226
+ }
3227
+ function isKeyframesAtRule(css, start, end) {
3228
+ let cursor = start + 1;
3229
+ if (css.charCodeAt(cursor) === 45) {
3230
+ cursor++;
3231
+ const prefixStart = cursor;
3232
+ while (cursor < end && isCssWordChar(css.charCodeAt(cursor))) cursor++;
3233
+ if (cursor === prefixStart || css.charCodeAt(cursor) !== 45) return false;
3234
+ cursor++;
3235
+ }
3236
+ if (cursor + 9 > end || css.slice(cursor, cursor + 9).toLowerCase() !== "keyframes") return false;
3237
+ return !isCssWordChar(css.charCodeAt(cursor + 9));
3238
+ }
3239
+ function hasEmptyCssBlockCandidate(css) {
3240
+ if (!EMPTY_CSS_BLOCK_RE.test(css)) return false;
3241
+ const blocks = [];
3242
+ let parenthesisDepth = 0;
3243
+ let quote = 0;
3244
+ let squareBracketDepth = 0;
3245
+ let statementStart = 0;
3246
+ for (let index = 0; index < css.length; index++) {
3247
+ const code = css.charCodeAt(index);
3248
+ if (quote !== 0) {
3249
+ if (code === 92) index++;
3250
+ else if (code === quote) quote = 0;
3251
+ continue;
3252
+ }
3253
+ if (code === 34 || code === 39) {
3254
+ quote = code;
3255
+ if (blocks.length > 0) blocks[blocks.length - 1].hasContent = true;
3256
+ continue;
3257
+ }
3258
+ if (code === 92) {
3259
+ if (blocks.length > 0) blocks[blocks.length - 1].hasContent = true;
3260
+ index++;
3261
+ continue;
3262
+ }
3263
+ if (code === 47 && css.charCodeAt(index + 1) === 42) {
3264
+ const commentEnd = css.indexOf("*/", index + 2);
3265
+ if (commentEnd < 0) return false;
3266
+ index = commentEnd + 1;
3267
+ continue;
3268
+ }
3269
+ if (code === 40) {
3270
+ parenthesisDepth++;
3271
+ continue;
3272
+ }
3273
+ if (code === 41 && parenthesisDepth > 0) {
3274
+ parenthesisDepth--;
3275
+ continue;
3276
+ }
3277
+ if (code === 91) {
3278
+ squareBracketDepth++;
3279
+ continue;
3280
+ }
3281
+ if (code === 93 && squareBracketDepth > 0) {
3282
+ squareBracketDepth--;
3283
+ continue;
3284
+ }
3285
+ if (code === 123 && parenthesisDepth === 0 && squareBracketDepth === 0) {
3286
+ const preludeStart = findCssPreludeStart(css, statementStart, index);
3287
+ const isAtRule = css.charCodeAt(preludeStart) === 64;
3288
+ const isKeyframesContainer = isAtRule && isKeyframesAtRule(css, preludeStart, index);
3289
+ blocks.push({
3290
+ hasContent: false,
3291
+ isKeyframesContainer,
3292
+ isKeyframeStep: !isAtRule && blocks[blocks.length - 1]?.isKeyframesContainer === true
3293
+ });
3294
+ statementStart = index + 1;
3295
+ continue;
3296
+ }
3297
+ if (code === 125 && parenthesisDepth === 0 && squareBracketDepth === 0) {
3298
+ const block = blocks.pop();
3299
+ if (!block) continue;
3300
+ if (!block.hasContent && !block.isKeyframeStep) return true;
3301
+ if (blocks.length > 0) blocks[blocks.length - 1].hasContent = true;
3302
+ statementStart = index + 1;
3303
+ continue;
3304
+ }
3305
+ if (code === 59 && parenthesisDepth === 0 && squareBracketDepth === 0) {
3306
+ statementStart = index + 1;
3307
+ continue;
3308
+ }
3309
+ if (!isCssWhitespace(code) && blocks.length > 0) blocks[blocks.length - 1].hasContent = true;
3310
+ }
3311
+ return false;
3312
+ }
3313
+ /** 在小程序样式进入最终产物图时规范化等价选择器并递归清理空 CSS 块。 */
3314
+ function finalizeMiniProgramCssStructure(css) {
3315
+ const repaired = repairTrailingUnclosedTailwindSourceMedia(css);
3316
+ if (!/\[\s*class\s*\]/.test(repaired) && !hasEmptyCssBlockCandidate(repaired)) return repaired;
3317
+ try {
3318
+ const root = postcss$1.parse(repaired);
3319
+ const selectorsChanged = normalizeClassPresenceSelectors(root);
3320
+ let removed = 0;
3321
+ let passRemoved = 0;
3322
+ do {
3323
+ passRemoved = removeEmptyRules(root) + removeEmptyAtRules(root);
3324
+ removed += passRemoved;
3325
+ } while (passRemoved > 0);
3326
+ return removed > 0 || selectorsChanged ? root.toString() : repaired;
3327
+ } catch {
3328
+ return repaired;
3329
+ }
2594
3330
  }
2595
3331
  //#endregion
2596
3332
  //#region src/compat/mini-program-prefixes.ts
@@ -3079,7 +3815,7 @@ function pruneMiniProgramGeneratedCss(css, options = {}) {
3079
3815
  });
3080
3816
  root.walkRules((rule) => {
3081
3817
  if (isKeyframesRule(rule)) return;
3082
- if (isPseudoContentInitRule(rule)) {
3818
+ if (isPseudoContentInitRule$1(rule)) {
3083
3819
  if (!shouldPreserveContentInit) rule.remove();
3084
3820
  return;
3085
3821
  }
@@ -3211,6 +3947,80 @@ function normalizeTailwindcssWebRpxDeclarations(root, options) {
3211
3947
  return normalized || converted;
3212
3948
  }
3213
3949
  //#endregion
3950
+ //#region src/compat/tailwindcss-v4/author-functions.ts
3951
+ const functionNames = /* @__PURE__ */ new Set([
3952
+ "theme",
3953
+ "--theme",
3954
+ "--spacing",
3955
+ "--alpha"
3956
+ ]);
3957
+ const functionPattern = /(?:theme|--theme|--spacing|--alpha)\(/;
3958
+ function hasCompilerFunction(value) {
3959
+ if (!functionPattern.test(value)) return false;
3960
+ let found = false;
3961
+ valueParser(value).walk((node) => {
3962
+ if (node.type === "function" && functionNames.has(node.value)) {
3963
+ found = true;
3964
+ return false;
3965
+ }
3966
+ });
3967
+ return found;
3968
+ }
3969
+ /** 将编译期函数值交给当前 Tailwind 编译上下文处理,保留声明的顺序与作用域。 */
3970
+ async function compileTailwindAuthorFunctions(css, compileValues) {
3971
+ if (!functionPattern.test(css)) return css;
3972
+ const root = postcss$1.parse(css);
3973
+ const nodes = [];
3974
+ const values = [];
3975
+ root.walk((node) => {
3976
+ const value = node.type === "decl" ? node.value : node.type === "atrule" && [
3977
+ "media",
3978
+ "supports",
3979
+ "container"
3980
+ ].includes(node.name) ? node.params : void 0;
3981
+ if (value !== void 0 && hasCompilerFunction(value)) {
3982
+ nodes.push(node);
3983
+ values.push(value);
3984
+ }
3985
+ });
3986
+ if (values.length === 0) return css;
3987
+ const compiled = await compileValues(values);
3988
+ if (compiled.length !== values.length) throw new Error("Tailwind 作者样式函数编译结果数量不匹配。");
3989
+ nodes.forEach((node, index) => {
3990
+ const value = compiled[index];
3991
+ if (hasCompilerFunction(value)) throw new Error(`Tailwind 作者样式函数尚未编译:${value}`);
3992
+ if (node.type === "decl") node.value = value;
3993
+ else node.params = value;
3994
+ });
3995
+ return root.toString();
3996
+ }
3997
+ /** 用唯一选择器承载待编译的值,避免依靠作者选择器或属性名猜测对应关系。 */
3998
+ function createTailwindAuthorFunctionProbe(values, selector) {
3999
+ const root = postcss$1.root();
4000
+ const rule = postcss$1.rule({ selector });
4001
+ values.forEach((value, index) => rule.append(postcss$1.decl({
4002
+ prop: `--value-${index}`,
4003
+ value
4004
+ })));
4005
+ root.append(rule);
4006
+ return {
4007
+ css: root.toString(),
4008
+ read(compiledCss) {
4009
+ const resolved = /* @__PURE__ */ new Map();
4010
+ postcss$1.parse(compiledCss).walkRules(selector, (compiledRule) => {
4011
+ compiledRule.walkDecls((declaration) => {
4012
+ resolved.set(declaration.prop, declaration.value);
4013
+ });
4014
+ });
4015
+ return values.map((_, index) => {
4016
+ const value = resolved.get(`--value-${index}`);
4017
+ if (value === void 0) throw new Error(`Tailwind 作者样式函数编译结果缺少第 ${index} 个值。`);
4018
+ return value;
4019
+ });
4020
+ }
4021
+ };
4022
+ }
4023
+ //#endregion
3214
4024
  //#region src/compat/tailwindcss-v4/infinity-radius.ts
3215
4025
  const BORDER_RADIUS_PROPERTY_RE = /^border-(?:radius|(?:top-left|top-right|bottom-left|bottom-right|start-start|start-end|end-start|end-end)-radius)$/i;
3216
4026
  /** 在下游 PostCSS 解析前,仅将圆角声明中的完整正无限长度收敛为有限值。 */
@@ -3225,6 +4035,222 @@ function normalizeTailwindcssV4InfinityRadiusCss(css) {
3225
4035
  return root.toString();
3226
4036
  }
3227
4037
  //#endregion
4038
+ //#region src/compat/uni-app-x-author-apply.ts
4039
+ /** 判断 Tailwind 的元素级变量初始化,兼容 Vue 已注入的 scoped 属性。 */
4040
+ function isTailwindRuntimePropertyRule(rule) {
4041
+ if (!rule.nodes.some((node) => node.type === "decl") || !rule.nodes.every((node) => node.type === "comment" || node.type === "decl" && node.prop.startsWith("--tw-"))) return false;
4042
+ let valid = true;
4043
+ selectorParser((selectors) => {
4044
+ selectors.walk((node) => {
4045
+ if (node.type === "selector" || node.type === "universal" || node.type === "attribute" && node.attribute.startsWith("data-v-") || node.type === "pseudo" && [
4046
+ "::before",
4047
+ "::after",
4048
+ "::backdrop",
4049
+ ":before",
4050
+ ":after"
4051
+ ].includes(node.value)) return;
4052
+ valid = false;
4053
+ });
4054
+ }).processSync(rule.selector);
4055
+ return valid;
4056
+ }
4057
+ function normalizeSelector$1(selector) {
4058
+ return selector.replace(/\s+/g, " ").trim();
4059
+ }
4060
+ function atRuleKey(name, params) {
4061
+ return `${name.toLowerCase()}\0${params.replace(/\s+/g, " ").trim()}`;
4062
+ }
4063
+ /**
4064
+ * `@apply` 只应把声明带回作者样式,不能把 Tailwind 根入口的 preflight、
4065
+ * utilities 复制进 scoped style 模块;Web 保留实际使用的运行时变量初始化和注册。
4066
+ */
4067
+ function retainUniAppXAuthorApplyCss(generatedCss, authorCss, options = {}) {
4068
+ try {
4069
+ const authorRoot = postcss.parse(authorCss);
4070
+ const authorSelectors = /* @__PURE__ */ new Set();
4071
+ const authorAtRules = /* @__PURE__ */ new Set();
4072
+ authorRoot.walkRules((rule) => {
4073
+ for (const selector of rule.selectors ?? [rule.selector]) authorSelectors.add(normalizeSelector$1(selector));
4074
+ });
4075
+ authorRoot.walkAtRules((atRule) => {
4076
+ if (![
4077
+ "apply",
4078
+ "reference",
4079
+ "import",
4080
+ "tailwind",
4081
+ "theme",
4082
+ "source",
4083
+ "config",
4084
+ "plugin"
4085
+ ].includes(atRule.name)) authorAtRules.add(atRuleKey(atRule.name, atRule.params));
4086
+ });
4087
+ const matchesAuthorSelector = createAuthorSelectorMatcher(authorSelectors);
4088
+ const root = postcss.parse(generatedCss);
4089
+ const usedProperties = /* @__PURE__ */ new Set();
4090
+ if (options.preserveRuntimeProperties) {
4091
+ const retained = postcss.root();
4092
+ root.walkRules((rule) => {
4093
+ if (rule.selectors.every((selector) => matchesAuthorSelector(normalizeSelector$1(selector)))) retained.append(rule.clone());
4094
+ });
4095
+ for (const prop of collectUsedTailwindcssV4Variables(retained)) usedProperties.add(prop);
4096
+ }
4097
+ let changed = false;
4098
+ root.walkRules((rule) => {
4099
+ if ((rule.selectors ?? [rule.selector]).every((selector) => matchesAuthorSelector(normalizeSelector$1(selector)))) return;
4100
+ if (options.preserveRuntimeProperties && isTailwindRuntimePropertyRule(rule)) {
4101
+ rule.walkDecls((decl) => {
4102
+ if (!usedProperties.has(decl.prop)) {
4103
+ decl.remove();
4104
+ changed = true;
4105
+ }
4106
+ });
4107
+ if (rule.nodes.some((node) => node.type === "decl")) return;
4108
+ }
4109
+ rule.remove();
4110
+ changed = true;
4111
+ });
4112
+ root.walkAtRules((atRule) => {
4113
+ if (options.preserveRuntimeProperties && atRule.name === "property" && usedProperties.has(atRule.params.trim())) return;
4114
+ if (authorAtRules.has(atRuleKey(atRule.name, atRule.params))) return;
4115
+ if (atRule.nodes?.some((node) => node.type === "rule" || node.type === "atrule")) return;
4116
+ atRule.remove();
4117
+ changed = true;
4118
+ });
4119
+ root.walkComments((comment) => {
4120
+ if (/tailwindcss v\d|weapp-tailwindcss (?:vite-generated-css|layer|uni-app-x web preflight reset)/i.test(comment.text)) {
4121
+ comment.remove();
4122
+ changed = true;
4123
+ }
4124
+ });
4125
+ return changed ? root.toString().trim() : generatedCss;
4126
+ } catch {
4127
+ return generatedCss;
4128
+ }
4129
+ }
4130
+ //#endregion
4131
+ //#region src/preflight.ts
4132
+ function createInjectPreflight(options) {
4133
+ const result = [];
4134
+ if (options && typeof options === "object") {
4135
+ const entries = Object.entries(options);
4136
+ for (const [prop, value] of entries) if (value !== false) result.push({
4137
+ prop,
4138
+ value: value.toString()
4139
+ });
4140
+ }
4141
+ return () => {
4142
+ return result;
4143
+ };
4144
+ }
4145
+ //#endregion
4146
+ //#region src/compat/uni-app-x-border.ts
4147
+ const UNI_APP_X_BORDER_PREFLIGHT_CLASS = "weapp-tw-border";
4148
+ /** 框架回放组件样式后恢复基础规则的顺序,确保作者 class 可以覆盖重置。 */
4149
+ function hoistUniAppXBorderPreflight(css) {
4150
+ if (!css.includes("weapp-tw-border")) return css;
4151
+ const root = postcss$1.parse(css);
4152
+ const resets = root.nodes.filter((node) => node.type === "rule" && node.selector === `.weapp-tw-border`);
4153
+ const anchor = root.nodes.find((node) => !resets.includes(node) && node.type !== "comment" && !(node.type === "atrule" && ["charset", "import"].includes(node.name)));
4154
+ if (!anchor || resets.length === 0) return css;
4155
+ for (const reset of resets) {
4156
+ reset.remove();
4157
+ root.insertBefore(anchor, reset);
4158
+ }
4159
+ return root.toString();
4160
+ }
4161
+ /** uni-app x 移除通配符 preflight 后,用独立基础类承载用户配置的边框默认值。 */
4162
+ function createUniAppXBorderPreflight(options) {
4163
+ const declarations = createInjectPreflight(options)().filter(({ prop }) => prop === "border" || prop.startsWith("border-"));
4164
+ if (declarations.length === 0) return;
4165
+ const rule = postcss$1.rule({ selector: `.${UNI_APP_X_BORDER_PREFLIGHT_CLASS}` });
4166
+ for (const declaration of declarations) rule.append(postcss$1.decl(declaration));
4167
+ return rule.toString();
4168
+ }
4169
+ //#endregion
4170
+ //#region src/compat/uni-app-x-style-value.ts
4171
+ const CLASS_SELECTOR_PREFIX_RE = /^\.((?:\\[^\n\r\f]|[\w-])+)(?=$|[.:#[])/;
4172
+ const STRING_STYLE_PROPERTIES = /* @__PURE__ */ new Set(["lineHeight"]);
4173
+ function toCamelCase(prop) {
4174
+ return prop.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
4175
+ }
4176
+ function normalizeValue(prop, value) {
4177
+ const trimmed = value.trim();
4178
+ if (!STRING_STYLE_PROPERTIES.has(toCamelCase(prop)) && /^-?\d+(?:\.\d+)?px$/.test(trimmed)) return Number(trimmed.slice(0, -2));
4179
+ return trimmed.replace(/\s*,\s*/g, ",");
4180
+ }
4181
+ function unescapeCssClassSelector(className) {
4182
+ return className.replace(/\\([^\n\r\f0-9a-f])/gi, "$1");
4183
+ }
4184
+ function assignClassStyleValue(result, className, declarations) {
4185
+ const unescapedClassName = unescapeCssClassSelector(className);
4186
+ result[className] = { "": declarations };
4187
+ result[unescapedClassName] = { "": declarations };
4188
+ result[escape(unescapedClassName)] = { "": declarations };
4189
+ }
4190
+ /** 把 CSS 规则编译成 Harmony/UTS 可消费的 class -> 声明对象。 */
4191
+ function cssToClassStyleValue(source) {
4192
+ let root;
4193
+ try {
4194
+ root = postcss$1.parse(source);
4195
+ } catch {
4196
+ return;
4197
+ }
4198
+ const result = {};
4199
+ root.walkRules((rule) => {
4200
+ const selectors = rule.selectors ?? [];
4201
+ for (const selector of selectors) {
4202
+ const match = selector.trim().match(CLASS_SELECTOR_PREFIX_RE);
4203
+ if (!match?.[1]) continue;
4204
+ const declarations = {};
4205
+ rule.walkDecls((decl) => {
4206
+ declarations[toCamelCase(decl.prop)] = normalizeValue(decl.prop, decl.value);
4207
+ });
4208
+ if (Object.keys(declarations).length > 0) assignClassStyleValue(result, match[1], declarations);
4209
+ }
4210
+ });
4211
+ return Object.keys(result).length > 0 ? result : void 0;
4212
+ }
4213
+ /** 从 SCSS/CSS 源码收集 `@apply` 工具类。 */
4214
+ function collectCssApplyUtilities(source) {
4215
+ const utilities = /* @__PURE__ */ new Set();
4216
+ let root;
4217
+ try {
4218
+ root = parseUniAppXStyleSource(source);
4219
+ } catch {
4220
+ return utilities;
4221
+ }
4222
+ root.walkAtRules("apply", (rule) => {
4223
+ for (const utility of splitCandidateTokens(rule.params)) utilities.add(utility);
4224
+ });
4225
+ return utilities;
4226
+ }
4227
+ /** 把 `@apply` 规则展开成已有 utility 声明。 */
4228
+ function expandCssApplySourcesToStyleValue(source, utilityStyles) {
4229
+ let root;
4230
+ try {
4231
+ root = parseUniAppXStyleSource(source);
4232
+ } catch {
4233
+ return;
4234
+ }
4235
+ const result = {};
4236
+ root.walkRules((rule) => {
4237
+ const applyRules = rule.nodes?.filter((node) => node.type === "atrule" && node.name === "apply") ?? [];
4238
+ if (applyRules.length === 0) return;
4239
+ const selectors = rule.selectors ?? [rule.selector];
4240
+ for (const selector of selectors) {
4241
+ const className = selector.trim().match(CLASS_SELECTOR_PREFIX_RE)?.[1];
4242
+ if (!className) continue;
4243
+ const declarations = {};
4244
+ for (const applyRule of applyRules) for (const utility of splitCandidateTokens(applyRule.params)) {
4245
+ const utilityDeclarations = utilityStyles[utility]?.[""] ?? utilityStyles[escape(utility)]?.[""];
4246
+ if (utilityDeclarations) Object.assign(declarations, utilityDeclarations);
4247
+ }
4248
+ if (Object.keys(declarations).length > 0) assignClassStyleValue(result, className, declarations);
4249
+ }
4250
+ });
4251
+ return Object.keys(result).length > 0 ? result : void 0;
4252
+ }
4253
+ //#endregion
3228
4254
  //#region src/shared.ts
3229
4255
  const escapeOptionsCache = /* @__PURE__ */ new WeakMap();
3230
4256
  function getEscapeOptions(escapeMap) {
@@ -3286,7 +4312,7 @@ function normalizeWebCssCompatOptions(options) {
3286
4312
  function isWebCssCompatEnabled(options) {
3287
4313
  return Object.values(options.features).some(Boolean);
3288
4314
  }
3289
- function collectCustomPropertyValues(root) {
4315
+ function collectCustomPropertyValues$1(root) {
3290
4316
  const values = /* @__PURE__ */ new Map();
3291
4317
  root.walkRules((rule) => {
3292
4318
  if (!rule.selectors.some((selector) => selector.trim() === ":root" || selector.trim() === ":host")) return;
@@ -3388,7 +4414,7 @@ function usesResolvableTailwindColorVariable(value, customPropertyValues) {
3388
4414
  }
3389
4415
  function normalizeModernColorDeclarations(root, features) {
3390
4416
  if (!features.oklch && !features.colorFunctions) return;
3391
- const customPropertyValues = collectCustomPropertyValues(root);
4417
+ const customPropertyValues = collectCustomPropertyValues$1(root);
3392
4418
  root.walkDecls((decl) => {
3393
4419
  const value = resolveCustomPropertyVarValue(decl.value, customPropertyValues);
3394
4420
  const normalized = normalizeModernColorValue(value, customPropertyValues);
@@ -3825,6 +4851,93 @@ async function transformCssMacroCss(css, options) {
3825
4851
  return compileCssMacroConditionalComments(result, options);
3826
4852
  }
3827
4853
  //#endregion
4854
+ //#region src/postcss-config.ts
4855
+ const tailwindPostcssPluginNames = /* @__PURE__ */ new Set(["tailwindcss", "@tailwindcss/postcss"]);
4856
+ function getPostcssPluginName(plugin) {
4857
+ if (!plugin) return;
4858
+ if (typeof plugin === "function" && "postcss" in plugin) try {
4859
+ return getPostcssPluginName(plugin());
4860
+ } catch {
4861
+ return;
4862
+ }
4863
+ if (typeof plugin !== "object" || !("postcssPlugin" in plugin)) return;
4864
+ const { postcssPlugin } = plugin;
4865
+ return typeof postcssPlugin === "string" ? postcssPlugin : void 0;
4866
+ }
4867
+ function isTailwindPostcssPlugin(plugin) {
4868
+ const name = getPostcssPluginName(plugin);
4869
+ return typeof name === "string" && tailwindPostcssPluginNames.has(name);
4870
+ }
4871
+ function removeTailwindPostcssPlugins(plugins) {
4872
+ let removed = 0;
4873
+ for (let i = plugins.length - 1; i >= 0; i--) if (isTailwindPostcssPlugin(plugins[i])) {
4874
+ plugins.splice(i, 1);
4875
+ removed++;
4876
+ }
4877
+ return removed;
4878
+ }
4879
+ async function resolvePostcssConfig(root, ctx = {}) {
4880
+ try {
4881
+ const loaded = await postcssrc(ctx, root);
4882
+ return {
4883
+ options: loaded.options,
4884
+ plugins: Array.isArray(loaded.plugins) ? [...loaded.plugins] : []
4885
+ };
4886
+ } catch (error) {
4887
+ if ((error instanceof Error ? error.message : String(error)).includes("No PostCSS Config found")) return;
4888
+ throw error;
4889
+ }
4890
+ }
4891
+ async function resolveFilteredPostcssConfig(root) {
4892
+ const loaded = await resolvePostcssConfig(root);
4893
+ if (!loaded) return;
4894
+ const plugins = [...loaded.plugins];
4895
+ const removed = removeTailwindPostcssPlugins(plugins);
4896
+ if (removed === 0) return;
4897
+ return {
4898
+ options: loaded.options,
4899
+ plugins,
4900
+ removed
4901
+ };
4902
+ }
4903
+ //#endregion
4904
+ //#region src/framework-pipeline.ts
4905
+ function unwrapDefault(value) {
4906
+ if (typeof value === "object" && value !== null && "default" in value) return unwrapDefault(value.default);
4907
+ return value;
4908
+ }
4909
+ async function normalizePlugin(value, from) {
4910
+ if (value === false || value === null || value === void 0) return;
4911
+ const tuple = Array.isArray(value);
4912
+ const pluginOptions = tuple ? value[1] : void 0;
4913
+ if (pluginOptions === false) return;
4914
+ let plugin = unwrapDefault(tuple ? value[0] : value);
4915
+ if (typeof plugin === "string") {
4916
+ const require = createRequire(pathToFileURL(resolve(from)));
4917
+ plugin = unwrapDefault(await import(pathToFileURL(require.resolve(plugin)).href));
4918
+ }
4919
+ if (tuple && typeof plugin === "function") plugin = unwrapDefault(await plugin(pluginOptions === true ? void 0 : pluginOptions));
4920
+ return plugin;
4921
+ }
4922
+ async function normalizePlugins(configured, from) {
4923
+ const entries = Array.isArray(configured) ? configured : Object.values(configured ?? {});
4924
+ const plugins = [];
4925
+ for (const entry of entries) {
4926
+ const plugin = await normalizePlugin(entry, from);
4927
+ if (plugin !== void 0) plugins.push(plugin);
4928
+ }
4929
+ removeTailwindPostcssPlugins(plugins);
4930
+ return plugins;
4931
+ }
4932
+ /** 重放框架提供的管线,不附加小程序转换或默认插件。 */
4933
+ async function processFrameworkCss(css, options) {
4934
+ const plugins = await normalizePlugins(options.plugins, options.options?.from ?? resolve("postcss.config.js"));
4935
+ return postcss$1(plugins).process(css, {
4936
+ from: void 0,
4937
+ ...options.options
4938
+ });
4939
+ }
4940
+ //#endregion
3828
4941
  //#region src/source-scan/inline-source.ts
3829
4942
  const NUMERICAL_RANGE_RE = /^(-?\d+)\.\.(-?\d+)(?:\.\.(-?\d+))?$/;
3830
4943
  function segmentTopLevel(input, separator, options = {}) {
@@ -4304,7 +5417,7 @@ function createEmptyDirectiveAnalysis() {
4304
5417
  };
4305
5418
  }
4306
5419
  function parseTailwindCssDirectiveRequest(params) {
4307
- return /^(?:url\(\s*)?(["']?)([^"')\s]+)\1\s*\)?/.exec(params.trim())?.[2];
5420
+ return parseCssImportSpecifier(params)?.specifier;
4308
5421
  }
4309
5422
  function parseTailwindCssConfigRequest(params) {
4310
5423
  return /^(["'])(.+)\1\s*;?$/.exec(params.trim())?.[2];
@@ -4572,7 +5685,10 @@ function isTailwindSourceDirective(node, options = {}) {
4572
5685
  const atRule = node;
4573
5686
  if (isTailwindCssImportAtRule(atRule, options)) return true;
4574
5687
  if (atRule.name === "import" && isTailwindCssPackageJsonImportRequest(parseImportRequest(atRule.params))) return true;
4575
- if (atRule.name === "layer") return !atRule.nodes || atRule.nodes.length === 0;
5688
+ if (atRule.name === "layer") {
5689
+ if (options.preserveCssLayers) return false;
5690
+ return !atRule.nodes || atRule.nodes.length === 0;
5691
+ }
4576
5692
  return TAILWIND_REMOVABLE_SOURCE_DIRECTIVE_NAMES.has(atRule.name);
4577
5693
  }
4578
5694
  function removeTailwindSourceDirectivesRoot(root, options = {}) {
@@ -5153,21 +6269,6 @@ function createOptionsResolver(baseOptions) {
5153
6269
  return { resolve };
5154
6270
  }
5155
6271
  //#endregion
5156
- //#region src/preflight.ts
5157
- function createInjectPreflight(options) {
5158
- const result = [];
5159
- if (options && typeof options === "object") {
5160
- const entries = Object.entries(options);
5161
- for (const [prop, value] of entries) if (value !== false) result.push({
5162
- prop,
5163
- value: value.toString()
5164
- });
5165
- }
5166
- return () => {
5167
- return result;
5168
- };
5169
- }
5170
- //#endregion
5171
6272
  //#region src/autoprefixer.ts
5172
6273
  const WEAPP_AUTOPREFIXER_BROWSERS = [
5173
6274
  "iOS >= 8",
@@ -6612,7 +7713,7 @@ function removeLegacyFlexboxPrefix(decl) {
6612
7713
  }
6613
7714
  function removeThemeScopeTailwindcssV4Defaults(root, injectedProps) {
6614
7715
  root.walkRules((rule) => {
6615
- if (!isMiniProgramThemeScopeSelector(getRuleSelectors(rule))) return;
7716
+ if (!isMiniProgramThemeScopeSelector$1(getRuleSelectors(rule))) return;
6616
7717
  rule.walkDecls((decl) => {
6617
7718
  if (injectedProps.has(decl.prop)) decl.remove();
6618
7719
  });
@@ -7302,8 +8403,10 @@ function createStyleHandler(options) {
7302
8403
  const handler = ((rawSource, opt) => {
7303
8404
  return processSource(rawSource, void 0, false, opt);
7304
8405
  });
7305
- handler.transformRoot = (root, opt) => {
7306
- return processSource(root.toString(), root, true, opt);
8406
+ handler.transformRoot = async (root, opt) => {
8407
+ const result = await processSource(root.toString(), root, true, opt);
8408
+ assertRootResult(result);
8409
+ return result;
7307
8410
  };
7308
8411
  handler.getPipeline = (opt) => {
7309
8412
  const resolvedOptions = resolver.resolve(opt);
@@ -7311,56 +8414,48 @@ function createStyleHandler(options) {
7311
8414
  };
7312
8415
  return handler;
7313
8416
  }
8417
+ /** 单个 Root 的变换不得返回多文档结果,避免破坏调用方的产物归属。 */
8418
+ function assertRootResult(result) {
8419
+ if (result.root.type !== "root") throw new TypeError("StyleHandler.transformRoot must return a single PostCSS Root.");
8420
+ }
7314
8421
  //#endregion
7315
- //#region src/postcss-config.ts
7316
- const tailwindPostcssPluginNames = /* @__PURE__ */ new Set(["tailwindcss", "@tailwindcss/postcss"]);
7317
- function getPostcssPluginName(plugin) {
7318
- if (!plugin) return;
7319
- if (typeof plugin === "function" && "postcss" in plugin) try {
7320
- return getPostcssPluginName(plugin());
7321
- } catch {
7322
- return;
7323
- }
7324
- if (typeof plugin !== "object" || !("postcssPlugin" in plugin)) return;
7325
- const { postcssPlugin } = plugin;
7326
- return typeof postcssPlugin === "string" ? postcssPlugin : void 0;
8422
+ //#region src/plugins/applyConfiguredCssCalc.ts
8423
+ function resolveCssCalcOption(options) {
8424
+ return options.cssOptions?.cssCalc ?? options.cssCalc;
7327
8425
  }
7328
- function isTailwindPostcssPlugin(plugin) {
7329
- const name = getPostcssPluginName(plugin);
7330
- return typeof name === "string" && tailwindPostcssPluginNames.has(name);
8426
+ function collectCustomPropertyValues(css) {
8427
+ const values = /* @__PURE__ */ new Map();
8428
+ if (!css.includes("--")) return values;
8429
+ try {
8430
+ postcss.parse(css).walkDecls((decl) => {
8431
+ if (decl.prop.startsWith("--")) values.set(decl.prop, decl.value.trim());
8432
+ });
8433
+ } catch {}
8434
+ return values;
7331
8435
  }
7332
- function removeTailwindPostcssPlugins(plugins) {
7333
- let removed = 0;
7334
- for (let i = plugins.length - 1; i >= 0; i--) if (isTailwindPostcssPlugin(plugins[i])) {
7335
- plugins.splice(i, 1);
7336
- removed++;
7337
- }
7338
- return removed;
8436
+ function mergeCustomPropertyValues(css, options) {
8437
+ const values = collectCustomPropertyValues(options.contextCss ?? "");
8438
+ for (const [name, value] of collectCustomPropertyValues(css)) values.set(name, value);
8439
+ for (const [name, value] of options.customPropertyValues ?? []) values.set(name, value);
8440
+ return values;
7339
8441
  }
7340
- async function resolvePostcssConfig(root, ctx = {}) {
8442
+ /**
8443
+ * 仅按 `cssCalc` 配置预计算 `calc()` / `var()`,不跑小程序选择器替换或单位转换。
8444
+ */
8445
+ async function applyConfiguredCssCalc(css, options = {}) {
8446
+ const cssCalc = resolveCssCalcOption(options);
8447
+ if (!cssCalc || !css.includes("calc(")) return css;
8448
+ const plugin = getCalcPlugin({
8449
+ cssCalc,
8450
+ customPropertyValues: mergeCustomPropertyValues(css, options)
8451
+ });
8452
+ if (!plugin) return css;
7341
8453
  try {
7342
- const loaded = await postcssrc(ctx, root);
7343
- return {
7344
- options: loaded.options,
7345
- plugins: Array.isArray(loaded.plugins) ? [...loaded.plugins] : []
7346
- };
7347
- } catch (error) {
7348
- if ((error instanceof Error ? error.message : String(error)).includes("No PostCSS Config found")) return;
7349
- throw error;
8454
+ return (await postcss([plugin]).process(css, { from: void 0 })).css;
8455
+ } catch {
8456
+ return css;
7350
8457
  }
7351
8458
  }
7352
- async function resolveFilteredPostcssConfig(root) {
7353
- const loaded = await resolvePostcssConfig(root);
7354
- if (!loaded) return;
7355
- const plugins = [...loaded.plugins];
7356
- const removed = removeTailwindPostcssPlugins(plugins);
7357
- if (removed === 0) return;
7358
- return {
7359
- options: loaded.options,
7360
- plugins,
7361
- removed
7362
- };
7363
- }
7364
8459
  //#endregion
7365
8460
  //#region src/vite-css-rules/structure.ts
7366
8461
  const MINI_PROGRAM_PREFLIGHT_SELECTOR_KEY = "view,text,::after,::before";
@@ -7838,4 +8933,4 @@ function mergeMiniProgramThemeScopeRuleDeclarations(baseCss, css) {
7838
8933
  }
7839
8934
  }
7840
8935
  //#endregion
7841
- export { CSS_MACRO_POSTCSS_PLUGIN_NAME, CSS_MACRO_STYLE_OPTIONS_MARKER, FULL_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSION_RE, FULL_SOURCE_SCAN_PATTERN, UNI_APP_X_IMPORTANT_APPLY_MARKER, analyzeTailwindCssDirectives, cleanLocalCssImportWrapperTailwindDirectives, cleanLocalCssImportWrapperTailwindDirectivesRoot, collectApplyOnlyCssSelectors, collectApplyOnlyCssSelectorsRoot, collectCssImportRequestsRoot, collectCssInlineSourceCandidates, compileCssMacroConditionalComments, consumeCascadeLayers, containsCssAfterMinify, convertTailwindcssRpxDeclarationToRem, convertTailwindcssRpxDeclarationsToRem, convertTailwindcssRpxValueToRem, createCssRuleMatcher, createCssSourceOrderAppend, createFallbackPlaceholderReplacer, createInjectPreflight, createPostcssStyleTargetProfile, createSourceScanPattern, createStyleHandler, createStylePipeline, createTailwindSourceEntryMatcher, createWeappTailwindcssPostcssPlugin, creator as cssMacroPostcssPlugin, dedupeCoveredCssRules, expandInlineSourceCandidatePattern, expandTailwindSourceEntries, filterApplyOnlyGeneratedCss, filterApplyOnlyGeneratedCssRoot, filterExistingCssRules, finalizeMiniProgramCss, finalizeMiniProgramCssRoot, getPostcssPluginName, hasCssMacroStyleOptions, hasCssMacroTailwindV4CustomVariantConditionalComments, hasCssMacroTailwindV4Directive, hasCssMacroTailwindV4InternalAtRules, hasCssMacroTailwindV4Source, hasMiniProgramCssSpecificityPlaceholders, hoistTailwindPreflightBase, internalCssSelectorReplacer, isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, isLocalCssImportRequest, isMiniProgramLocalCssImportRequest, isPureLocalCssImportWrapper, isPureLocalCssImportWrapperRoot, isTailwindCssGenerationDirective, isTailwindCssImportAtRule, isTailwindCssImportRequest, isTailwindCssPackageJsonImportRequest, isWeappTailwindcssImportRequest, mergeCoveredCssRuleDeclarations, mergeMiniProgramPreflightRuleDeclarations, mergeMiniProgramThemeScopeRuleDeclarations, normalizeLegacyContentEntries, normalizeMiniProgramGeneratedCssForPostcss, normalizeMiniProgramPrefixedDeclaration, normalizeModernColorValue, normalizeOutputImportRequest, normalizeTailwindCssImportRequest, normalizeTailwindcssRpxDeclaration, normalizeTailwindcssRpxDeclarations, normalizeTailwindcssV4InfinityCalcCss, normalizeTailwindcssV4InfinityRadiusCss, normalizeTailwindcssWebRpxDeclarations, normalizeUniAppXImportantApplyForSass, normalizeWebCssCompatOptions, parseConfigParam, parseSourceFileParam, parseTailwindCssConfigRequest, parseTailwindCssDirectiveRequest, postcss, postcssHtmlTransform, prefixLocalCssImportsWithWebpackIgnoreRoot, protectDynamicColorMixAlpha, protectDynamicVarFallbacks, pruneMiniProgramGeneratedCss, removeEmptyAtRules, removeEmptyRules, removeMatchingLocalCssImports, removeMatchingLocalCssImportsRoot, removeTailwindPostcssPlugins, removeTailwindSourceDirectivesRoot, removeUnsupportedAtSupports, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, removeUnsupportedMiniProgramCssImportsRoot, removeUnsupportedMiniProgramPrefixedAtRule, repairTrailingUnclosedTailwindSourceMedia, resolveCssSourceEntries, resolveFilteredPostcssConfig, resolvePostcssConfig, resolvePostcssFrameworkProfile, resolvePostcssFrameworkStrategy, resolvePostcssStyleBranch, resolvePostcssStyleBranchProfile, resolvePostcssStyleTarget, resolveSourceScanPath, resolveTailwindSourceEntry, restoreLocalCssImports, restoreUniAppXImportantApplyMarker, rewriteLocalCssImportRequestsForOutput, rewriteLocalCssImportRequestsForOutputRoot, selectorContainsPseudoClass, splitLocalCssImports, splitLocalCssImportsRoot, stripMiniProgramCssSpecificityPlaceholders, toPosixPath, transformCssMacroCss, transformCssMacroTailwindV4Source, transformLynxCssCompat, transformWebCssCompat, transformWebCssSafeSelectors, unitConversionComposeRules, unitConversionPresets, unwrapUnsupportedCascadeLayers, withCssMacroStyleOptions };
8936
+ export { CSS_MACRO_POSTCSS_PLUGIN_NAME, CSS_MACRO_STYLE_OPTIONS_MARKER, FULL_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSION_RE, FULL_SOURCE_SCAN_PATTERN, UNI_APP_X_BORDER_PREFLIGHT_CLASS, UNI_APP_X_IMPORTANT_APPLY_MARKER, analyzeTailwindCssDirectives, applyConfiguredCssCalc, cleanLocalCssImportWrapperTailwindDirectives, cleanLocalCssImportWrapperTailwindDirectivesRoot, collectApplyOnlyCssSelectors, collectApplyOnlyCssSelectorsRoot, collectCssApplyUtilities, collectCssImportRequestsRoot, collectCssInlineSourceCandidates, collectDedupedPostTransformCompatCss, collectGeneratedSelectors, compileCssMacroConditionalComments, compileTailwindAuthorFunctions, consumeCascadeLayers, containsCssAfterMinify, convertTailwindcssRpxDeclarationToRem, convertTailwindcssRpxDeclarationsToRem, convertTailwindcssRpxValueToRem, createAuthorSelectorMatcher, createCssRuleMatcher, createCssSourceOrderAppend, createFallbackPlaceholderReplacer, createInjectPreflight, createPostcssStyleTargetProfile, createSourceScanPattern, createStyleHandler, createStylePipeline, createTailwindAuthorFunctionProbe, createTailwindSourceEntryMatcher, createUniAppXBorderPreflight, createWeappTailwindcssPostcssPlugin, creator as cssMacroPostcssPlugin, cssToClassStyleValue, dedupeCoveredCssRules, expandCssApplySourcesToStyleValue, expandInlineSourceCandidatePattern, expandTailwindSourceEntries, filterApplyOnlyGeneratedCss, filterApplyOnlyGeneratedCssRoot, filterExistingCssRules, finalizeMiniProgramCss, finalizeMiniProgramCssRoot, finalizeMiniProgramCssStructure, getPostcssPluginName, hasCssMacroStyleOptions, hasCssMacroTailwindV4CustomVariantConditionalComments, hasCssMacroTailwindV4Directive, hasCssMacroTailwindV4InternalAtRules, hasCssMacroTailwindV4Source, hasEmptyCssBlockCandidate, hasMiniProgramCssSpecificityPlaceholders, hoistTailwindPreflightBase, hoistUniAppXBorderPreflight, inheritLegacyUnitConvertedDeclarations, internalCssSelectorReplacer, isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, isLocalCssImportRequest, isMiniProgramLocalCssImportRequest, isPureLocalCssImportWrapper, isPureLocalCssImportWrapperRoot, isTailwindCssGenerationDirective, isTailwindCssImport, isTailwindCssImportAtRule, isTailwindCssImportRequest, isTailwindCssPackageJsonImportRequest, isTailwindRuntimePropertyRule, isUniAppXStyleSourceEmpty, isWeappTailwindcssImportRequest, mergeCoveredCssRuleDeclarations, mergeMiniProgramPreflightRuleDeclarations, mergeMiniProgramThemeScopeRuleDeclarations, normalizeCompatSelectors, normalizeLegacyContentEntries, normalizeMiniProgramGeneratedCssForPostcss, normalizeMiniProgramPrefixedDeclaration, normalizeModernColorValue, normalizeOutputImportRequest, normalizeTailwindCssImportRequest, normalizeTailwindcssRpxDeclaration, normalizeTailwindcssRpxDeclarations, normalizeTailwindcssV4InfinityCalcCss, normalizeTailwindcssV4InfinityRadiusCss, normalizeTailwindcssWebRpxDeclarations, normalizeUniAppXImportantApplyForSass, normalizeWebCssCompatOptions, parseConfigParam, parseCssImportSpecifier, parseCssSource, parseImportSourceParam, parseScssSource, parseSourceFileParam, parseTailwindCssConfigRequest, parseTailwindCssDirectiveRequest, parseUniAppXStyleSource, postcss, postcssHtmlTransform, prefixLocalCssImportsWithWebpackIgnoreRoot, processFrameworkCss, protectDynamicColorMixAlpha, protectDynamicVarFallbacks, pruneMiniProgramGeneratedCss, quoteCssImportSpecifier, removeEmptyAtRules, removeEmptyRules, removeGeneratedSelectorCompatCss, removeMatchingLocalCssImports, removeMatchingLocalCssImportsRoot, removeTailwindApplyRules, removeTailwindPostcssPlugins, removeTailwindSourceDirectivesRoot, removeTailwindV4PreflightImports, removeUnsupportedAtSupports, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, removeUnsupportedMiniProgramCssImportsRoot, removeUnsupportedMiniProgramPrefixedAtRule, removeUnsupportedThemeVendorKeyframes, removeUnusedMiniProgramContentInit, repairTrailingUnclosedTailwindSourceMedia, resolveCssSourceEntries, resolveFilteredPostcssConfig, resolvePostcssConfig, resolvePostcssFrameworkProfile, resolvePostcssFrameworkStrategy, resolvePostcssStyleBranch, resolvePostcssStyleBranchProfile, resolvePostcssStyleTarget, resolveSourceScanPath, resolveTailwindSourceEntry, restoreLocalCssImports, restoreUniAppXImportantApplyMarker, retainUniAppXAuthorApplyCss, rewriteLocalCssImportRequestsForOutput, rewriteLocalCssImportRequestsForOutputRoot, scss, selectorContainsPseudoClass, splitLocalCssImports, splitLocalCssImportsRoot, stringifyScssSource, stripMiniProgramCssSpecificityPlaceholders, toPosixPath, transformCssMacroCss, transformCssMacroTailwindV4Source, transformLynxCssCompat, transformWebCssCompat, transformWebCssSafeSelectors, unitConversionComposeRules, unitConversionPresets, unwrapUnsupportedCascadeLayers, withCssMacroStyleOptions };