@weapp-tailwindcss/postcss 3.3.1 → 3.3.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.
package/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  This package is the CSS processing core of weapp-tailwindcss. It handles PostCSS AST transforms, selector compatibility, platform differences, and Tailwind output post-processing for mini programs.
6
6
 
7
+ ## Repeated CSS Comparisons
8
+
9
+ For repeated comparisons against one CSS string, `createCssRuleMatcher(baseCss)` provides `contains(css)` and `filter(css)` with reusable, lazy comparison indexes. It preserves the semantics of `containsCssAfterMinify` and `filterExistingCssRules`. Create a new matcher when the base CSS changes; release it after the batch.
10
+
7
11
  ## Website
8
12
 
9
13
  For setup guides, configuration references, and framework examples, see the [official weapp-tailwindcss documentation](https://tw.weapp.dev).
package/README.zh-CN.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  这个包是 weapp-tailwindcss 的 CSS 处理核心,负责小程序端的 PostCSS AST 转换、选择器兼容、平台差异处理和 Tailwind 输出后处理。
6
6
 
7
+ ## 批量 CSS 比较
8
+
9
+ 对同一份 CSS 连续比较时,`createCssRuleMatcher(baseCss)` 提供 `contains(css)` 和 `filter(css)`,按需构建并复用比较索引,语义与 `containsCssAfterMinify`、`filterExistingCssRules` 相同。主样式变化后应创建新的 matcher,批量比较结束后释放引用。
10
+
7
11
  ## 官网
8
12
 
9
13
  更多接入方式、配置说明和框架示例见 [weapp-tailwindcss 官方文档](https://tw.weapp.dev)。
@@ -3,4 +3,4 @@ export { consumeCascadeLayers } from './cascade-layers.js';
3
3
  export { repairTrailingUnclosedTailwindSourceMedia } from './directives.js';
4
4
  export { finalizeMiniProgramCss, type FinalizeMiniProgramCssOptions, finalizeMiniProgramCssRoot, hoistTailwindPreflightBase, } from './finalize.js';
5
5
  export { normalizeMiniProgramGeneratedCssForPostcss, pruneMiniProgramGeneratedCss, type PruneMiniProgramGeneratedCssOptions, } from './prune-generated.js';
6
- export { hasMiniProgramCssSpecificityPlaceholders, removeEmptyAtRules, stripMiniProgramCssSpecificityPlaceholders, } from './root-cleanups.js';
6
+ export { hasMiniProgramCssSpecificityPlaceholders, removeEmptyAtRules, removeEmptyRules, stripMiniProgramCssSpecificityPlaceholders, } from './root-cleanups.js';
@@ -6,6 +6,7 @@ export declare const removeSpecificityPlaceholdersFromSource: typeof stripMiniPr
6
6
  export declare function removeRootSpecificityPlaceholders(root: postcss.Root): void;
7
7
  export declare function removeEmptyAtRules(root: postcss.Root): number;
8
8
  export declare function removeEmptyBlockAtRules(root: postcss.Root): number;
9
+ export declare function removeEmptyRules(root: postcss.Root): number;
9
10
  export declare function removeUnsupportedBrowserSelectors(root: postcss.Root): void;
10
11
  export declare function removeEmptyStandardDeclarations(root: postcss.Root): void;
11
12
  export declare function removeDisplayP3Declarations(root: postcss.Root): void;
@@ -0,0 +1,2 @@
1
+ /** 在下游 PostCSS 解析前,仅将圆角声明中的完整正无限长度收敛为有限值。 */
2
+ export declare function normalizeTailwindcssV4InfinityRadiusCss(css: string): string;
package/dist/index.cjs CHANGED
@@ -81,10 +81,7 @@ function rewriteApplyParams(params, marker) {
81
81
  /** 将 Sass 不可直接解析的 important utility 改写成跨预处理器中间形式。 */
82
82
  function normalizeUniAppXImportantApplyForSass(css) {
83
83
  try {
84
- const root = postcss.default.parse(css, {
85
- from: void 0,
86
- syntax: postcss_scss.default
87
- });
84
+ const root = postcss_scss.default.parse(css, { from: void 0 });
88
85
  let changed = false;
89
86
  root.walkAtRules("apply", (rule) => {
90
87
  const params = rewriteApplyParams(rule.params, UNI_APP_X_IMPORTANT_APPLY_MARKER);
@@ -93,7 +90,7 @@ function normalizeUniAppXImportantApplyForSass(css) {
93
90
  changed = true;
94
91
  }
95
92
  });
96
- return changed ? root.toString() : css;
93
+ return changed ? root.toString(postcss_scss.default.stringify) : css;
97
94
  } catch {
98
95
  return css;
99
96
  }
@@ -521,7 +518,7 @@ function createCssVarNodes(definitions) {
521
518
  }));
522
519
  }
523
520
  const CLAMP_PX = 9999;
524
- const INFINITY_CALC_VALUE_REGEXP = /^calc\(\s*infinity\s*\*\s*(?:\d+(?:\.\d*)?|\.\d+)r?px\s*\)$/i;
521
+ const INFINITY_CALC_VALUE_REGEXP = /^calc\(\s*infinity\s*\*\s*(\d+(?:\.\d*)?|\.\d+)r?px\s*\)$/i;
525
522
  const MODERN_CHECK_WEBKIT_HYPHENS_RE = /-webkit-hyphens\s*:\s*none/;
526
523
  const MODERN_CHECK_MARGIN_TRIM_RE = /margin-trim\s*:\s*inline/;
527
524
  const MODERN_CHECK_MOZ_ORIENT_RE = /-moz-orient\s*:\s*inline/;
@@ -1049,6 +1046,9 @@ function removeRootSpecificityPlaceholders(root) {
1049
1046
  function isEffectivelyEmptyContainer(container) {
1050
1047
  return container.nodes !== void 0 && container.nodes.every((node) => node.type === "comment");
1051
1048
  }
1049
+ function isKeyframeStepRule(rule) {
1050
+ return rule.parent?.type === "atrule" && rule.parent.name.toLowerCase().endsWith("keyframes");
1051
+ }
1052
1052
  function removeEmptyAtRules(root) {
1053
1053
  let removed = 0;
1054
1054
  const visit = (container) => {
@@ -1081,6 +1081,17 @@ function removeEmptyAtRuleAncestors(parent) {
1081
1081
  parent = nextParent?.type === "atrule" ? nextParent : void 0;
1082
1082
  }
1083
1083
  }
1084
+ function removeEmptyRules(root) {
1085
+ let removed = 0;
1086
+ root.walkRules((rule) => {
1087
+ if (isKeyframeStepRule(rule) || !rule.parent || !isEffectivelyEmptyContainer(rule)) return;
1088
+ const parent = rule.parent;
1089
+ rule.remove();
1090
+ removeEmptyAtRuleAncestors(parent);
1091
+ removed++;
1092
+ });
1093
+ return removed;
1094
+ }
1084
1095
  function removeUnsupportedBrowserSelectors(root) {
1085
1096
  root.walkRules((rule) => {
1086
1097
  if (!rule.selectors || rule.selectors.length === 0) return;
@@ -2906,8 +2917,10 @@ function finalizeMiniProgramCssRoot(root, options = {}) {
2906
2917
  }));
2907
2918
  const themeRule = collectThemeVariableRule(root, options);
2908
2919
  insertHoistedRules(root, mergeEquivalentHoistedRules(themeRule ? [...preflightRules, themeRule] : preflightRules), hoistAnchor);
2909
- if (options.removeEmptyAtRuleAncestors !== false) removeEmptyAtRules(root);
2910
- else root.walkAtRules((atRule) => {
2920
+ if (options.removeEmptyAtRuleAncestors !== false) {
2921
+ removeEmptyRules(root);
2922
+ removeEmptyAtRules(root);
2923
+ } else root.walkAtRules((atRule) => {
2911
2924
  if (atRule.nodes?.length === 0) atRule.remove();
2912
2925
  });
2913
2926
  }
@@ -3214,6 +3227,20 @@ function normalizeTailwindcssWebRpxDeclarations(root, options) {
3214
3227
  return normalized || converted;
3215
3228
  }
3216
3229
  //#endregion
3230
+ //#region src/compat/tailwindcss-v4/infinity-radius.ts
3231
+ 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;
3232
+ /** 在下游 PostCSS 解析前,仅将圆角声明中的完整正无限长度收敛为有限值。 */
3233
+ function normalizeTailwindcssV4InfinityRadiusCss(css) {
3234
+ if (!/infinity/i.test(css)) return css;
3235
+ const root = (0, postcss.parse)(css);
3236
+ root.walkDecls((decl) => {
3237
+ if (!BORDER_RADIUS_PROPERTY_RE.test(decl.prop) && decl.prop !== "--radius" && !decl.prop.startsWith("--radius-")) return;
3238
+ const match = INFINITY_CALC_VALUE_REGEXP.exec(decl.value.trim());
3239
+ if (match && Number.parseFloat(match[1]) > 0) decl.value = `${CLAMP_PX}px`;
3240
+ });
3241
+ return root.toString();
3242
+ }
3243
+ //#endregion
3217
3244
  //#region src/shared.ts
3218
3245
  const escapeOptionsCache = /* @__PURE__ */ new WeakMap();
3219
3246
  function getEscapeOptions(escapeMap) {
@@ -7352,17 +7379,24 @@ function getCssRuleStructuralKey(rule) {
7352
7379
  function getCssRuleStructuralKeyWithSelectorKey(rule, selectorKey) {
7353
7380
  return [...getRuleAtRuleChain(rule), selectorKey].join("|");
7354
7381
  }
7355
- function getCssRuleContentKey(rule) {
7382
+ function getCssRuleContentKey(rule, content = normalizeCssForContainment(rule.toString())) {
7356
7383
  const structuralKey = getCssRuleStructuralKey(rule);
7357
7384
  if (!structuralKey) return;
7358
- return [structuralKey, normalizeCssForContainment(rule.toString())].join("|");
7385
+ return [structuralKey, content].join("|");
7359
7386
  }
7360
- function collectCssRuleContentKeys(css) {
7387
+ function collectCssRuleContentKeys(css, requiredBaseContent) {
7361
7388
  const keys = /* @__PURE__ */ new Set();
7362
7389
  try {
7363
7390
  postcss.default.parse(css).walkRules((rule) => {
7364
- const key = getCssRuleContentKey(rule);
7365
- if (key) keys.add(key);
7391
+ const content = normalizeCssForContainment(rule.toString());
7392
+ const key = getCssRuleContentKey(rule, content);
7393
+ if (key) {
7394
+ if (requiredBaseContent !== void 0 && !requiredBaseContent.includes(content)) {
7395
+ keys.clear();
7396
+ return false;
7397
+ }
7398
+ keys.add(key);
7399
+ }
7366
7400
  });
7367
7401
  } catch {}
7368
7402
  return keys;
@@ -7574,12 +7608,12 @@ function removeEmptyAtRules$1(root) {
7574
7608
  }
7575
7609
  //#endregion
7576
7610
  //#region src/vite-css-rules/containment.ts
7577
- function filterExistingCssRules(baseCss, css) {
7578
- const baseRuleKeys = collectCssRuleContentKeys(baseCss);
7611
+ function filterCssRules(base, css) {
7612
+ const baseRuleKeys = base.ruleKeys();
7579
7613
  if (baseRuleKeys.size === 0) return css;
7580
7614
  try {
7581
7615
  const root = postcss.default.parse(css);
7582
- const baseRuleDeclarationKeys = collectCssRuleDeclarationKeyMap(baseCss);
7616
+ const baseRuleDeclarationKeys = base.declarations();
7583
7617
  let changed = false;
7584
7618
  root.walkRules((rule) => {
7585
7619
  const key = getCssRuleContentKey(rule);
@@ -7595,16 +7629,40 @@ function filterExistingCssRules(baseCss, css) {
7595
7629
  return css;
7596
7630
  }
7597
7631
  }
7598
- function containsCssAfterMinify(baseCss, css) {
7599
- if (baseCss.includes(css)) return true;
7600
- const normalizedBaseCss = normalizeCssForContainment(baseCss);
7632
+ function containsCss(base, css) {
7633
+ if (base.css.includes(css)) return true;
7634
+ const normalizedBaseCss = base.normalized();
7601
7635
  const normalizedCss = normalizeCssForContainment(css);
7602
7636
  if (normalizedCss.length > 0 && normalizedBaseCss.includes(normalizedCss)) return true;
7603
7637
  const normalizedNodes = collectNormalizedCssNodes(css);
7604
7638
  if (normalizedNodes.length > 0 && normalizedNodes.every((node) => normalizedBaseCss.includes(node))) return true;
7605
- const baseRuleKeys = collectCssRuleContentKeys(baseCss);
7606
- const ruleKeys = collectCssRuleContentKeys(css);
7607
- return ruleKeys.size > 0 && [...ruleKeys].every((key) => baseRuleKeys.has(key));
7639
+ const ruleKeys = collectCssRuleContentKeys(css, normalizedBaseCss);
7640
+ return ruleKeys.size > 0 && [...ruleKeys].every((key) => base.ruleKeys().has(key));
7641
+ }
7642
+ function prepareCssBase(css) {
7643
+ let normalized;
7644
+ let ruleKeys;
7645
+ let declarations;
7646
+ return {
7647
+ css,
7648
+ normalized: () => normalized ??= normalizeCssForContainment(css),
7649
+ ruleKeys: () => ruleKeys ??= collectCssRuleContentKeys(css),
7650
+ declarations: () => declarations ??= collectCssRuleDeclarationKeyMap(css)
7651
+ };
7652
+ }
7653
+ /** 对同一份不可变主样式复用比较索引;调用方在主样式更新后创建新的 matcher。 */
7654
+ function createCssRuleMatcher(baseCss) {
7655
+ const base = prepareCssBase(baseCss);
7656
+ return {
7657
+ contains: (css) => containsCss(base, css),
7658
+ filter: (css) => filterCssRules(base, css)
7659
+ };
7660
+ }
7661
+ function filterExistingCssRules(baseCss, css) {
7662
+ return filterCssRules(prepareCssBase(baseCss), css);
7663
+ }
7664
+ function containsCssAfterMinify(baseCss, css) {
7665
+ return containsCss(prepareCssBase(baseCss), css);
7608
7666
  }
7609
7667
  //#endregion
7610
7668
  //#region src/vite-css-rules/mini-program.ts
@@ -7770,6 +7828,7 @@ exports.containsCssAfterMinify = containsCssAfterMinify;
7770
7828
  exports.convertTailwindcssRpxDeclarationToRem = convertTailwindcssRpxDeclarationToRem;
7771
7829
  exports.convertTailwindcssRpxDeclarationsToRem = convertTailwindcssRpxDeclarationsToRem;
7772
7830
  exports.convertTailwindcssRpxValueToRem = convertTailwindcssRpxValueToRem;
7831
+ exports.createCssRuleMatcher = createCssRuleMatcher;
7773
7832
  exports.createCssSourceOrderAppend = createCssSourceOrderAppend;
7774
7833
  exports.createFallbackPlaceholderReplacer = createFallbackPlaceholderReplacer;
7775
7834
  exports.createInjectPreflight = createInjectPreflight;
@@ -7820,6 +7879,7 @@ exports.normalizeTailwindCssImportRequest = normalizeTailwindCssImportRequest;
7820
7879
  exports.normalizeTailwindcssRpxDeclaration = normalizeTailwindcssRpxDeclaration;
7821
7880
  exports.normalizeTailwindcssRpxDeclarations = normalizeTailwindcssRpxDeclarations;
7822
7881
  exports.normalizeTailwindcssV4InfinityCalcCss = normalizeTailwindcssV4InfinityCalcCss;
7882
+ exports.normalizeTailwindcssV4InfinityRadiusCss = normalizeTailwindcssV4InfinityRadiusCss;
7823
7883
  exports.normalizeTailwindcssWebRpxDeclarations = normalizeTailwindcssWebRpxDeclarations;
7824
7884
  exports.normalizeUniAppXImportantApplyForSass = normalizeUniAppXImportantApplyForSass;
7825
7885
  exports.normalizeWebCssCompatOptions = normalizeWebCssCompatOptions;
@@ -7839,6 +7899,7 @@ exports.protectDynamicColorMixAlpha = protectDynamicColorMixAlpha;
7839
7899
  exports.protectDynamicVarFallbacks = protectDynamicVarFallbacks;
7840
7900
  exports.pruneMiniProgramGeneratedCss = pruneMiniProgramGeneratedCss;
7841
7901
  exports.removeEmptyAtRules = removeEmptyAtRules;
7902
+ exports.removeEmptyRules = removeEmptyRules;
7842
7903
  exports.removeMatchingLocalCssImports = removeMatchingLocalCssImports;
7843
7904
  exports.removeMatchingLocalCssImportsRoot = removeMatchingLocalCssImportsRoot;
7844
7905
  exports.removeTailwindPostcssPlugins = removeTailwindPostcssPlugins;
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export { type PostcssAppType, type PostcssStyleBranch, type PostcssStyleBranchProfile, resolvePostcssStyleBranch, type ResolvePostcssStyleBranchOptions, resolvePostcssStyleBranchProfile, } from './branches/index.js';
2
2
  export { type DynamicColorMixAlphaProtection, type DynamicColorMixAlphaProtectionOptions, type ModernColorValueNormalization, normalizeModernColorValue, protectDynamicColorMixAlpha, protectDynamicVarFallbacks, } from './compat/color-mix.js';
3
3
  export { transformLynxCssCompat } from './compat/lynx-css.js';
4
- export { consumeCascadeLayers, finalizeMiniProgramCss, type FinalizeMiniProgramCssOptions, finalizeMiniProgramCssRoot, hasMiniProgramCssSpecificityPlaceholders, hoistTailwindPreflightBase, normalizeMiniProgramGeneratedCssForPostcss, pruneMiniProgramGeneratedCss, removeEmptyAtRules, removeUnsupportedAtSupports, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, repairTrailingUnclosedTailwindSourceMedia, stripMiniProgramCssSpecificityPlaceholders, unwrapUnsupportedCascadeLayers, } from './compat/mini-program-css/index.js';
4
+ export { consumeCascadeLayers, finalizeMiniProgramCss, type FinalizeMiniProgramCssOptions, finalizeMiniProgramCssRoot, hasMiniProgramCssSpecificityPlaceholders, hoistTailwindPreflightBase, normalizeMiniProgramGeneratedCssForPostcss, pruneMiniProgramGeneratedCss, removeEmptyAtRules, removeEmptyRules, removeUnsupportedAtSupports, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, repairTrailingUnclosedTailwindSourceMedia, stripMiniProgramCssSpecificityPlaceholders, unwrapUnsupportedCascadeLayers, } from './compat/mini-program-css/index.js';
5
5
  export { normalizeMiniProgramPrefixedDeclaration, removeUnsupportedMiniProgramPrefixedAtRule, } from './compat/mini-program-prefixes.js';
6
6
  export { convertTailwindcssRpxDeclarationsToRem, convertTailwindcssRpxDeclarationToRem, convertTailwindcssRpxValueToRem, normalizeTailwindcssRpxDeclaration, normalizeTailwindcssRpxDeclarations, normalizeTailwindcssWebRpxDeclarations, type TailwindcssRpxToRemOptions, } from './compat/tailwindcss-rpx.js';
7
7
  export { normalizeTailwindcssV4InfinityCalcCss } from './compat/tailwindcss-v4.js';
8
+ export { normalizeTailwindcssV4InfinityRadiusCss } from './compat/tailwindcss-v4/infinity-radius.js';
8
9
  export { normalizeUniAppXImportantApplyForSass, restoreUniAppXImportantApplyMarker, UNI_APP_X_IMPORTANT_APPLY_MARKER, } from './compat/uni-app-x.js';
9
10
  export { type NormalizedWebCssCompatOptions, normalizeWebCssCompatOptions, transformWebCssCompat, transformWebCssSafeSelectors, } from './compat/web-css.js';
10
11
  export { compileCssMacroConditionalComments, CSS_MACRO_STYLE_OPTIONS_MARKER, hasCssMacroStyleOptions, hasCssMacroTailwindV4CustomVariantConditionalComments, hasCssMacroTailwindV4Directive, hasCssMacroTailwindV4InternalAtRules, hasCssMacroTailwindV4Source, transformCssMacroCss, transformCssMacroTailwindV4Source, withCssMacroStyleOptions, } from './css-macro/auto.js';
@@ -28,5 +29,5 @@ export { internalCssSelectorReplacer } from './shared.js';
28
29
  export { collectCssInlineSourceCandidates, createSourceScanPattern, createTailwindSourceEntryMatcher, expandInlineSourceCandidatePattern, expandTailwindSourceEntries, FULL_SOURCE_SCAN_EXTENSION_RE, FULL_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_PATTERN, isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, normalizeLegacyContentEntries, parseConfigParam, parseSourceFileParam, resolveCssSourceEntries, resolveSourceScanPath, resolveTailwindSourceEntry, type TailwindInlineSourceCandidates, type TailwindSourceEntry, toPosixPath, } from './source-scan.js';
29
30
  export { createPostcssStyleTargetProfile, type PostcssStyleTarget, type PostcssStyleTargetProfile, } from './style-targets/index.js';
30
31
  export * from './types.js';
31
- export { containsCssAfterMinify, dedupeCoveredCssRules, filterExistingCssRules, mergeCoveredCssRuleDeclarations, mergeMiniProgramPreflightRuleDeclarations, mergeMiniProgramThemeScopeRuleDeclarations, } from './vite-css-rules.js';
32
+ export { containsCssAfterMinify, createCssRuleMatcher, dedupeCoveredCssRules, filterExistingCssRules, mergeCoveredCssRuleDeclarations, mergeMiniProgramPreflightRuleDeclarations, mergeMiniProgramThemeScopeRuleDeclarations, } from './vite-css-rules.js';
32
33
  export { composeRules as unitConversionComposeRules, presets as unitConversionPresets, } from 'postcss-rule-unit-converter';
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ import { CSS_MACRO_POSTCSS_PLUGIN_NAME, creator, ifdefAtRule, ifndefAtRule } fro
2
2
  import postcssHtmlTransform from "./html-transform.js";
3
3
  import "./types.js";
4
4
  import { extractValidCandidates, resolveProjectSourceFiles, splitCandidateTokens } from "@tailwindcss-mangle/engine";
5
- import postcss, { Declaration, Rule, rule, default as postcss$1 } from "postcss";
5
+ import postcss, { Declaration, Rule, parse, rule, default as postcss$1 } from "postcss";
6
6
  import scssSyntax from "postcss-scss";
7
7
  import postcssCalc from "@weapp-tailwindcss/postcss-calc";
8
8
  import selectorParser from "postcss-selector-parser";
@@ -65,10 +65,7 @@ function rewriteApplyParams(params, marker) {
65
65
  /** 将 Sass 不可直接解析的 important utility 改写成跨预处理器中间形式。 */
66
66
  function normalizeUniAppXImportantApplyForSass(css) {
67
67
  try {
68
- const root = postcss$1.parse(css, {
69
- from: void 0,
70
- syntax: scssSyntax
71
- });
68
+ const root = scssSyntax.parse(css, { from: void 0 });
72
69
  let changed = false;
73
70
  root.walkAtRules("apply", (rule) => {
74
71
  const params = rewriteApplyParams(rule.params, UNI_APP_X_IMPORTANT_APPLY_MARKER);
@@ -77,7 +74,7 @@ function normalizeUniAppXImportantApplyForSass(css) {
77
74
  changed = true;
78
75
  }
79
76
  });
80
- return changed ? root.toString() : css;
77
+ return changed ? root.toString(scssSyntax.stringify) : css;
81
78
  } catch {
82
79
  return css;
83
80
  }
@@ -505,7 +502,7 @@ function createCssVarNodes(definitions) {
505
502
  }));
506
503
  }
507
504
  const CLAMP_PX = 9999;
508
- const INFINITY_CALC_VALUE_REGEXP = /^calc\(\s*infinity\s*\*\s*(?:\d+(?:\.\d*)?|\.\d+)r?px\s*\)$/i;
505
+ const INFINITY_CALC_VALUE_REGEXP = /^calc\(\s*infinity\s*\*\s*(\d+(?:\.\d*)?|\.\d+)r?px\s*\)$/i;
509
506
  const MODERN_CHECK_WEBKIT_HYPHENS_RE = /-webkit-hyphens\s*:\s*none/;
510
507
  const MODERN_CHECK_MARGIN_TRIM_RE = /margin-trim\s*:\s*inline/;
511
508
  const MODERN_CHECK_MOZ_ORIENT_RE = /-moz-orient\s*:\s*inline/;
@@ -1033,6 +1030,9 @@ function removeRootSpecificityPlaceholders(root) {
1033
1030
  function isEffectivelyEmptyContainer(container) {
1034
1031
  return container.nodes !== void 0 && container.nodes.every((node) => node.type === "comment");
1035
1032
  }
1033
+ function isKeyframeStepRule(rule) {
1034
+ return rule.parent?.type === "atrule" && rule.parent.name.toLowerCase().endsWith("keyframes");
1035
+ }
1036
1036
  function removeEmptyAtRules(root) {
1037
1037
  let removed = 0;
1038
1038
  const visit = (container) => {
@@ -1065,6 +1065,17 @@ function removeEmptyAtRuleAncestors(parent) {
1065
1065
  parent = nextParent?.type === "atrule" ? nextParent : void 0;
1066
1066
  }
1067
1067
  }
1068
+ function removeEmptyRules(root) {
1069
+ let removed = 0;
1070
+ root.walkRules((rule) => {
1071
+ if (isKeyframeStepRule(rule) || !rule.parent || !isEffectivelyEmptyContainer(rule)) return;
1072
+ const parent = rule.parent;
1073
+ rule.remove();
1074
+ removeEmptyAtRuleAncestors(parent);
1075
+ removed++;
1076
+ });
1077
+ return removed;
1078
+ }
1068
1079
  function removeUnsupportedBrowserSelectors(root) {
1069
1080
  root.walkRules((rule) => {
1070
1081
  if (!rule.selectors || rule.selectors.length === 0) return;
@@ -2890,8 +2901,10 @@ function finalizeMiniProgramCssRoot(root, options = {}) {
2890
2901
  }));
2891
2902
  const themeRule = collectThemeVariableRule(root, options);
2892
2903
  insertHoistedRules(root, mergeEquivalentHoistedRules(themeRule ? [...preflightRules, themeRule] : preflightRules), hoistAnchor);
2893
- if (options.removeEmptyAtRuleAncestors !== false) removeEmptyAtRules(root);
2894
- else root.walkAtRules((atRule) => {
2904
+ if (options.removeEmptyAtRuleAncestors !== false) {
2905
+ removeEmptyRules(root);
2906
+ removeEmptyAtRules(root);
2907
+ } else root.walkAtRules((atRule) => {
2895
2908
  if (atRule.nodes?.length === 0) atRule.remove();
2896
2909
  });
2897
2910
  }
@@ -3198,6 +3211,20 @@ function normalizeTailwindcssWebRpxDeclarations(root, options) {
3198
3211
  return normalized || converted;
3199
3212
  }
3200
3213
  //#endregion
3214
+ //#region src/compat/tailwindcss-v4/infinity-radius.ts
3215
+ 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
+ /** 在下游 PostCSS 解析前,仅将圆角声明中的完整正无限长度收敛为有限值。 */
3217
+ function normalizeTailwindcssV4InfinityRadiusCss(css) {
3218
+ if (!/infinity/i.test(css)) return css;
3219
+ const root = parse(css);
3220
+ root.walkDecls((decl) => {
3221
+ if (!BORDER_RADIUS_PROPERTY_RE.test(decl.prop) && decl.prop !== "--radius" && !decl.prop.startsWith("--radius-")) return;
3222
+ const match = INFINITY_CALC_VALUE_REGEXP.exec(decl.value.trim());
3223
+ if (match && Number.parseFloat(match[1]) > 0) decl.value = `${CLAMP_PX}px`;
3224
+ });
3225
+ return root.toString();
3226
+ }
3227
+ //#endregion
3201
3228
  //#region src/shared.ts
3202
3229
  const escapeOptionsCache = /* @__PURE__ */ new WeakMap();
3203
3230
  function getEscapeOptions(escapeMap) {
@@ -7336,17 +7363,24 @@ function getCssRuleStructuralKey(rule) {
7336
7363
  function getCssRuleStructuralKeyWithSelectorKey(rule, selectorKey) {
7337
7364
  return [...getRuleAtRuleChain(rule), selectorKey].join("|");
7338
7365
  }
7339
- function getCssRuleContentKey(rule) {
7366
+ function getCssRuleContentKey(rule, content = normalizeCssForContainment(rule.toString())) {
7340
7367
  const structuralKey = getCssRuleStructuralKey(rule);
7341
7368
  if (!structuralKey) return;
7342
- return [structuralKey, normalizeCssForContainment(rule.toString())].join("|");
7369
+ return [structuralKey, content].join("|");
7343
7370
  }
7344
- function collectCssRuleContentKeys(css) {
7371
+ function collectCssRuleContentKeys(css, requiredBaseContent) {
7345
7372
  const keys = /* @__PURE__ */ new Set();
7346
7373
  try {
7347
7374
  postcss.parse(css).walkRules((rule) => {
7348
- const key = getCssRuleContentKey(rule);
7349
- if (key) keys.add(key);
7375
+ const content = normalizeCssForContainment(rule.toString());
7376
+ const key = getCssRuleContentKey(rule, content);
7377
+ if (key) {
7378
+ if (requiredBaseContent !== void 0 && !requiredBaseContent.includes(content)) {
7379
+ keys.clear();
7380
+ return false;
7381
+ }
7382
+ keys.add(key);
7383
+ }
7350
7384
  });
7351
7385
  } catch {}
7352
7386
  return keys;
@@ -7558,12 +7592,12 @@ function removeEmptyAtRules$1(root) {
7558
7592
  }
7559
7593
  //#endregion
7560
7594
  //#region src/vite-css-rules/containment.ts
7561
- function filterExistingCssRules(baseCss, css) {
7562
- const baseRuleKeys = collectCssRuleContentKeys(baseCss);
7595
+ function filterCssRules(base, css) {
7596
+ const baseRuleKeys = base.ruleKeys();
7563
7597
  if (baseRuleKeys.size === 0) return css;
7564
7598
  try {
7565
7599
  const root = postcss.parse(css);
7566
- const baseRuleDeclarationKeys = collectCssRuleDeclarationKeyMap(baseCss);
7600
+ const baseRuleDeclarationKeys = base.declarations();
7567
7601
  let changed = false;
7568
7602
  root.walkRules((rule) => {
7569
7603
  const key = getCssRuleContentKey(rule);
@@ -7579,16 +7613,40 @@ function filterExistingCssRules(baseCss, css) {
7579
7613
  return css;
7580
7614
  }
7581
7615
  }
7582
- function containsCssAfterMinify(baseCss, css) {
7583
- if (baseCss.includes(css)) return true;
7584
- const normalizedBaseCss = normalizeCssForContainment(baseCss);
7616
+ function containsCss(base, css) {
7617
+ if (base.css.includes(css)) return true;
7618
+ const normalizedBaseCss = base.normalized();
7585
7619
  const normalizedCss = normalizeCssForContainment(css);
7586
7620
  if (normalizedCss.length > 0 && normalizedBaseCss.includes(normalizedCss)) return true;
7587
7621
  const normalizedNodes = collectNormalizedCssNodes(css);
7588
7622
  if (normalizedNodes.length > 0 && normalizedNodes.every((node) => normalizedBaseCss.includes(node))) return true;
7589
- const baseRuleKeys = collectCssRuleContentKeys(baseCss);
7590
- const ruleKeys = collectCssRuleContentKeys(css);
7591
- return ruleKeys.size > 0 && [...ruleKeys].every((key) => baseRuleKeys.has(key));
7623
+ const ruleKeys = collectCssRuleContentKeys(css, normalizedBaseCss);
7624
+ return ruleKeys.size > 0 && [...ruleKeys].every((key) => base.ruleKeys().has(key));
7625
+ }
7626
+ function prepareCssBase(css) {
7627
+ let normalized;
7628
+ let ruleKeys;
7629
+ let declarations;
7630
+ return {
7631
+ css,
7632
+ normalized: () => normalized ??= normalizeCssForContainment(css),
7633
+ ruleKeys: () => ruleKeys ??= collectCssRuleContentKeys(css),
7634
+ declarations: () => declarations ??= collectCssRuleDeclarationKeyMap(css)
7635
+ };
7636
+ }
7637
+ /** 对同一份不可变主样式复用比较索引;调用方在主样式更新后创建新的 matcher。 */
7638
+ function createCssRuleMatcher(baseCss) {
7639
+ const base = prepareCssBase(baseCss);
7640
+ return {
7641
+ contains: (css) => containsCss(base, css),
7642
+ filter: (css) => filterCssRules(base, css)
7643
+ };
7644
+ }
7645
+ function filterExistingCssRules(baseCss, css) {
7646
+ return filterCssRules(prepareCssBase(baseCss), css);
7647
+ }
7648
+ function containsCssAfterMinify(baseCss, css) {
7649
+ return containsCss(prepareCssBase(baseCss), css);
7592
7650
  }
7593
7651
  //#endregion
7594
7652
  //#region src/vite-css-rules/mini-program.ts
@@ -7735,4 +7793,4 @@ function mergeMiniProgramThemeScopeRuleDeclarations(baseCss, css) {
7735
7793
  }
7736
7794
  }
7737
7795
  //#endregion
7738
- 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, 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, normalizeTailwindcssWebRpxDeclarations, normalizeUniAppXImportantApplyForSass, normalizeWebCssCompatOptions, parseConfigParam, parseSourceFileParam, parseTailwindCssConfigRequest, parseTailwindCssDirectiveRequest, postcss, postcssHtmlTransform, prefixLocalCssImportsWithWebpackIgnoreRoot, protectDynamicColorMixAlpha, protectDynamicVarFallbacks, pruneMiniProgramGeneratedCss, removeEmptyAtRules, 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 };
7796
+ 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 };
@@ -1,2 +1,7 @@
1
+ /** 对同一份不可变主样式复用比较索引;调用方在主样式更新后创建新的 matcher。 */
2
+ export declare function createCssRuleMatcher(baseCss: string): {
3
+ contains: (css: string) => boolean;
4
+ filter: (css: string) => string;
5
+ };
1
6
  export declare function filterExistingCssRules(baseCss: string, css: string): string;
2
7
  export declare function containsCssAfterMinify(baseCss: string, css: string): boolean;
@@ -7,8 +7,8 @@ export declare function normalizeCssForContainment(css: string): string;
7
7
  export declare function collectNormalizedCssNodes(css: string): string[];
8
8
  export declare function getCssRuleStructuralKey(rule: postcss.Rule): string | undefined;
9
9
  export declare function getCssRuleStructuralKeyWithSelectorKey(rule: postcss.Rule, selectorKey: string): string;
10
- export declare function getCssRuleContentKey(rule: postcss.Rule): string | undefined;
11
- export declare function collectCssRuleContentKeys(css: string): Set<string>;
10
+ export declare function getCssRuleContentKey(rule: postcss.Rule, content?: string): string | undefined;
11
+ export declare function collectCssRuleContentKeys(css: string, requiredBaseContent?: string): Set<string>;
12
12
  export declare function normalizeCssDeclarationKey(decl: postcss.Declaration): string;
13
13
  export declare function parseVarReferenceValue(value: string): string | undefined;
14
14
  export declare function isEquivalentVarFallbackDeclaration(incoming: postcss.Declaration, baseDeclarations: Set<string>): boolean;
@@ -1,3 +1,3 @@
1
- export { containsCssAfterMinify, filterExistingCssRules } from './vite-css-rules/containment.js';
1
+ export { containsCssAfterMinify, createCssRuleMatcher, filterExistingCssRules } from './vite-css-rules/containment.js';
2
2
  export { dedupeCoveredCssRules, mergeCoveredCssRuleDeclarations } from './vite-css-rules/coverage.js';
3
3
  export { mergeMiniProgramPreflightRuleDeclarations, mergeMiniProgramThemeScopeRuleDeclarations } from './vite-css-rules/mini-program.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@weapp-tailwindcss/postcss",
3
3
  "type": "module",
4
- "version": "3.3.1",
4
+ "version": "3.3.3",
5
5
  "description": "PostCSS transforms that bring Tailwind CSS compatibility to every platform. 将 Tailwind CSS 兼容能力带到全端的 PostCSS 转换工具。",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",
@@ -71,20 +71,20 @@
71
71
  "@csstools/css-tokenizer": "^4.0.0",
72
72
  "@tailwindcss-mangle/engine": "0.2.0",
73
73
  "@weapp-core/escape": "~8.0.0",
74
- "@weapp-tailwindcss/postcss-calc": "1.0.5",
74
+ "@weapp-tailwindcss/postcss-calc": "1.0.6",
75
75
  "@weapp-tailwindcss/shared": "2.0.3",
76
- "autoprefixer": "^10.5.4",
76
+ "autoprefixer": "^10.5.5",
77
77
  "es-toolkit": "^1.52.0",
78
78
  "lru-cache": "11.5.2",
79
79
  "micromatch": "^4.0.8",
80
- "postcss": "^8.5.26",
80
+ "postcss": "^8.5.28",
81
81
  "postcss-load-config": "^6.0.1",
82
- "postcss-preset-env": "^11.5.0",
82
+ "postcss-preset-env": "^11.5.1",
83
83
  "postcss-pxtrans": "^1.0.4",
84
84
  "postcss-rem-to-responsive-pixel": "^7.0.5",
85
85
  "postcss-rule-unit-converter": "^0.2.3",
86
86
  "postcss-scss": "^4.0.9",
87
- "postcss-selector-parser": "^7.1.5",
87
+ "postcss-selector-parser": "^7.1.6",
88
88
  "postcss-value-parser": "^4.2.0",
89
89
  "tailwindcss-config": "2.0.4"
90
90
  },