@weapp-tailwindcss/postcss 3.3.4 → 3.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +10 -0
  2. package/README.zh-CN.md +6 -0
  3. package/dist/compat/author-selector.d.ts +2 -0
  4. package/dist/compat/index.d.ts +57 -0
  5. package/dist/compat/legacy-css/apply.d.ts +2 -0
  6. package/dist/compat/legacy-css/dedupe.d.ts +2 -0
  7. package/dist/compat/legacy-css/index.d.ts +4 -0
  8. package/dist/compat/legacy-css/selectors.d.ts +7 -0
  9. package/dist/compat/legacy-css/source-cleanup.d.ts +2 -0
  10. package/dist/compat/legacy-css/units.d.ts +1 -0
  11. package/dist/compat/mini-program-css/class-presence.d.ts +3 -0
  12. package/dist/compat/mini-program-css/content-init.d.ts +3 -0
  13. package/dist/compat/mini-program-css/empty-blocks.d.ts +3 -0
  14. package/dist/compat/mini-program-css/index.d.ts +2 -0
  15. package/dist/compat/mini-program-css/output-import-shell.d.ts +8 -0
  16. package/dist/compat/native/compile.d.ts +2 -0
  17. package/dist/compat/native/properties.d.ts +15 -0
  18. package/dist/compat/native/selectors.d.ts +8 -0
  19. package/dist/compat/native/types.d.ts +23 -0
  20. package/dist/compat/processed-css/cleanup.d.ts +4 -0
  21. package/dist/compat/processed-css/composition.d.ts +6 -0
  22. package/dist/compat/processed-css/entry-directives.d.ts +1 -0
  23. package/dist/compat/processed-css/imports.d.ts +8 -0
  24. package/dist/compat/scoped-css/cleanup.d.ts +4 -0
  25. package/dist/compat/scoped-css/coverage.d.ts +10 -0
  26. package/dist/compat/scoped-css/covered-rules.d.ts +4 -0
  27. package/dist/compat/scoped-css/predicates.d.ts +13 -0
  28. package/dist/compat/tailwind-directive-injection.d.ts +8 -0
  29. package/dist/compat/tailwindcss-v4/author-functions.d.ts +7 -0
  30. package/dist/compat/tailwindcss-v4/generated-output.d.ts +5 -0
  31. package/dist/compat/tailwindcss-v4/package-import-statements.d.ts +1 -0
  32. package/dist/compat/tailwindcss-v4/preflight-imports.d.ts +3 -0
  33. package/dist/compat/tailwindcss-v4/rpx-candidates.d.ts +6 -0
  34. package/dist/compat/tailwindcss-v4/theme-injection.d.ts +1 -0
  35. package/dist/compat/tailwindcss-v4/theme-source.d.ts +9 -0
  36. package/dist/compat/tailwindcss-v4/user-css/apply-only.d.ts +6 -0
  37. package/dist/compat/tailwindcss-v4/user-css/apply-reference.d.ts +4 -0
  38. package/dist/compat/tailwindcss-v4/user-css/at-rules.d.ts +3 -0
  39. package/dist/compat/tailwindcss-v4/user-css/class-selectors.d.ts +2 -0
  40. package/dist/compat/tailwindcss-v4/user-css/directives/entry-source.d.ts +9 -0
  41. package/dist/compat/tailwindcss-v4/user-css/directives/fallback.d.ts +11 -0
  42. package/dist/compat/tailwindcss-v4/user-css/directives/index.d.ts +2 -0
  43. package/dist/compat/tailwindcss-v4/user-css/directives/shared.d.ts +26 -0
  44. package/dist/compat/tailwindcss-v4/user-css/framework-composition.d.ts +2 -0
  45. package/dist/compat/tailwindcss-v4/user-css/framework-source.d.ts +1 -0
  46. package/dist/compat/tailwindcss-v4/user-css/generated-cleanup.d.ts +7 -0
  47. package/dist/compat/tailwindcss-v4/user-css/identity.d.ts +1 -0
  48. package/dist/compat/tailwindcss-v4/user-css/markers.d.ts +32 -0
  49. package/dist/compat/tailwindcss-v4/user-css/rule-deduplication.d.ts +1 -0
  50. package/dist/compat/tailwindcss-v4/user-css/scoped-rules.d.ts +4 -0
  51. package/dist/compat/tailwindcss-v4/user-css/source-fragments.d.ts +15 -0
  52. package/dist/compat/tailwindcss-v4/user-css/transform.d.ts +14 -0
  53. package/dist/compat/tailwindcss-v4/user-css/user-layer-order.d.ts +10 -0
  54. package/dist/compat/tailwindcss-v4/user-css/user-layers.d.ts +15 -0
  55. package/dist/compat/tailwindcss-v4.d.ts +1 -0
  56. package/dist/compat/uni-app-x/apply-source.d.ts +2 -0
  57. package/dist/compat/uni-app-x/harmony-apply.d.ts +2 -0
  58. package/dist/compat/uni-app-x/reference-paths.d.ts +2 -0
  59. package/dist/compat/uni-app-x-author-apply.d.ts +10 -0
  60. package/dist/compat/uni-app-x-border.d.ts +6 -0
  61. package/dist/compat/uni-app-x-style-value.d.ts +11 -0
  62. package/dist/compat/webpack-css/bare-selectors.d.ts +1 -0
  63. package/dist/compat/webpack-css/generated-cleanup.d.ts +4 -0
  64. package/dist/compat/webpack-css/identity.d.ts +5 -0
  65. package/dist/compat/webpack-css/preflight.d.ts +5 -0
  66. package/dist/compat/webpack-css/user-source.d.ts +6 -0
  67. package/dist/diagnostics/rpx-theme.d.ts +9 -0
  68. package/dist/directives-DTKFO5Hv.js +2630 -0
  69. package/dist/experimental/lightningcss/index.cjs +256 -0
  70. package/dist/experimental/lightningcss/index.d.ts +3 -0
  71. package/dist/experimental/lightningcss/index.js +245 -0
  72. package/dist/experimental/lightningcss/options.d.ts +3 -0
  73. package/dist/experimental/lightningcss/selector-transform.d.ts +10 -0
  74. package/dist/experimental/lightningcss/selector-utils.d.ts +10 -0
  75. package/dist/framework-pipeline.d.ts +4 -0
  76. package/dist/generator-plugin/config-directive.d.ts +5 -0
  77. package/dist/generator-plugin/local-imports.d.ts +6 -1
  78. package/dist/generator-plugin/source-files.d.ts +5 -5
  79. package/dist/generator-plugin/types.d.ts +5 -0
  80. package/dist/index.cjs +388 -7960
  81. package/dist/index.d.ts +2 -33
  82. package/dist/index.js +10 -7840
  83. package/dist/native.cjs +425 -0
  84. package/dist/native.d.ts +3 -0
  85. package/dist/native.js +419 -0
  86. package/dist/plugin-BWDgxMn5.cjs +194 -0
  87. package/dist/plugin-CpkRzMhp.js +185 -0
  88. package/dist/plugin.cjs +3 -0
  89. package/dist/plugin.d.ts +2 -0
  90. package/dist/plugin.js +2 -0
  91. package/dist/plugins/applyConfiguredCssCalc.d.ts +9 -0
  92. package/dist/postcss-runtime-i5rHe_mj.js +2 -0
  93. package/dist/postcss-runtime.d.ts +1 -1
  94. package/dist/preflight-BTZL2nvC.cjs +21 -0
  95. package/dist/preflight-DVg4eehD.js +16 -0
  96. package/dist/resolve-DQiOQfoY.js +354 -0
  97. package/dist/resolve-EBh65bS8.cjs +3556 -0
  98. package/dist/rewrite-imports-CdZQE6CI.js +146 -0
  99. package/dist/selectorParser/utils.d.ts +1 -1
  100. package/dist/shared-CELzerNo.cjs +34 -0
  101. package/dist/shared-CfQUwapA.js +23 -0
  102. package/dist/source-scan/candidates.d.ts +4 -0
  103. package/dist/source-scan/description.d.ts +15 -0
  104. package/dist/source-scan/params.d.ts +5 -0
  105. package/dist/source-scan/resolve.d.ts +30 -0
  106. package/dist/source-scan/tailwind-v4/entry-source.d.ts +16 -0
  107. package/dist/source-scan/tailwind-v4/fingerprint.d.ts +5 -0
  108. package/dist/source-scan.d.ts +3 -24
  109. package/dist/syntax/css-import.d.ts +20 -0
  110. package/dist/syntax/index.d.ts +3 -0
  111. package/dist/syntax/location-dependencies.d.ts +2 -0
  112. package/dist/syntax/parse.d.ts +13 -0
  113. package/dist/syntax/rewrite-imports.d.ts +5 -0
  114. package/dist/syntax/runtime-signature.d.ts +2 -0
  115. package/dist/syntax/source-style.d.ts +1 -0
  116. package/dist/syntax.cjs +547 -0
  117. package/dist/syntax.d.ts +6 -0
  118. package/dist/syntax.js +3 -0
  119. package/dist/transform-Djx5HILQ.js +9239 -0
  120. package/dist/transform-Xb48e-Wk.cjs +10957 -0
  121. package/dist/transform.cjs +421 -0
  122. package/dist/transform.d.ts +40 -0
  123. package/dist/transform.js +10 -0
  124. package/dist/types.d.ts +1 -1
  125. package/dist/utils/apply-source.d.ts +11 -0
  126. package/dist/utils/css-source-trace.d.ts +6 -0
  127. package/dist/utils/custom-property-values.d.ts +4 -0
  128. package/dist/utils/generated-css-marker.d.ts +12 -0
  129. package/package.json +48 -8
@@ -0,0 +1,185 @@
1
+ import { collectApplyOnlyCssSelectorsRoot, filterApplyOnlyGeneratedCss, finalizeMiniProgramCss, hasTailwindApplyDirective, hasTailwindRootDirectives, prependConfigDirective, transformLynxCssCompat, transformWebCssCompat } from "./directives-DTKFO5Hv.js";
2
+ import { DEFAULT_SOURCE_SCAN_EXTENSIONS, createSourceScanPattern, expandTailwindSourceEntries, resolveCssScanSources, resolveCssSourceEntries } from "./resolve-DQiOQfoY.js";
3
+ import postcss from "postcss";
4
+ import path from "node:path";
5
+ import { extractValidCandidates } from "@weapp-tailwindcss/engine";
6
+ import process from "node:process";
7
+ import { readFile } from "node:fs/promises";
8
+ //#region src/generator-plugin/context.ts
9
+ const PLUGIN_NAME$1 = "weapp-tailwindcss";
10
+ function resolveInputFile(result) {
11
+ const from = result.opts.from;
12
+ if (typeof from !== "string" || from.length === 0) return;
13
+ return path.isAbsolute(from) ? from : path.resolve(process.cwd(), from);
14
+ }
15
+ function resolvePostcssBase(result, options) {
16
+ if (options.base) return options.base;
17
+ const inputFile = resolveInputFile(result);
18
+ return inputFile ? path.dirname(inputFile) : process.cwd();
19
+ }
20
+ function resolvePostcssProjectRoot(result, options) {
21
+ if (options.projectRoot) return options.projectRoot;
22
+ const inputFile = resolveInputFile(result);
23
+ return inputFile ? path.dirname(inputFile) : process.cwd();
24
+ }
25
+ function replaceRootCss(root, css, result) {
26
+ root.removeAll();
27
+ try {
28
+ const nextRoot = postcss.parse(css, { from: resolveInputFile(result) });
29
+ root.append(nextRoot.nodes);
30
+ } catch {
31
+ root.raws = { after: css };
32
+ }
33
+ }
34
+ function addDependencyMessages(result, generated) {
35
+ for (const file of generated.dependencies) result.messages.push({
36
+ type: "dependency",
37
+ plugin: PLUGIN_NAME$1,
38
+ file
39
+ });
40
+ }
41
+ function addSourceDependencyMessages(result, files) {
42
+ for (const file of files) result.messages.push({
43
+ type: "dependency",
44
+ plugin: PLUGIN_NAME$1,
45
+ file
46
+ });
47
+ }
48
+ //#endregion
49
+ //#region src/generator-plugin/source-files.ts
50
+ const POSTCSS_SOURCE_PATTERN$1 = createSourceScanPattern(DEFAULT_SOURCE_SCAN_EXTENSIONS);
51
+ function resolveCompatibilityScan(root, result, options, context, local) {
52
+ const css = context.css ?? root.toString();
53
+ const applyOnly = hasTailwindApplyDirective(css) && !hasTailwindRootDirectives(root, { importFallback: true });
54
+ const base = resolvePostcssBase(result, options);
55
+ return resolveCssScanSources([{
56
+ root,
57
+ base
58
+ }], {
59
+ base,
60
+ automatic: local || applyOnly || options.scanSources === false ? "disabled" : "auto",
61
+ pattern: POSTCSS_SOURCE_PATTERN$1,
62
+ config: options.config,
63
+ configResolution: "path",
64
+ sourceEntries: context.sourceEntries,
65
+ loadConfigContent: local
66
+ });
67
+ }
68
+ async function collectAutoTailwindCandidates(root, result, options, context = {}) {
69
+ if (options.scanSources === false) return /* @__PURE__ */ new Set();
70
+ const scan = await resolveCompatibilityScan(root, result, options, context, false);
71
+ const candidates = !scan.entries.some((entry) => !entry.negated) ? [] : await extractValidCandidates({
72
+ base: resolvePostcssBase(result, options),
73
+ css: context.css ?? root.toString(),
74
+ cwd: resolvePostcssProjectRoot(result, options),
75
+ sources: scan.entries
76
+ });
77
+ return /* @__PURE__ */ new Set([...[...candidates].filter((candidate) => !scan.inlineCandidates.excluded.has(candidate)), ...scan.inlineCandidates.included]);
78
+ }
79
+ async function collectPostcssLocalSources(root, result, options, context = {}) {
80
+ const scan = await resolveCompatibilityScan(root, result, options, context, true);
81
+ const files = [.../* @__PURE__ */ new Set([...await expandTailwindSourceEntries(scan.explicitEntries), ...(await Promise.all(scan.configGroups.map((entries) => expandTailwindSourceEntries(entries)))).flat()])];
82
+ const sources = await Promise.all(files.map(async (file) => {
83
+ const extension = path.extname(file).slice(1);
84
+ return {
85
+ content: await readFile(file, "utf8"),
86
+ ...extension ? { extension } : {}
87
+ };
88
+ }));
89
+ return {
90
+ files: [...files, ...scan.configPaths],
91
+ sources
92
+ };
93
+ }
94
+ //#endregion
95
+ //#region src/generator-plugin/index.ts
96
+ const PLUGIN_NAME = "weapp-tailwindcss";
97
+ const POSTCSS_SOURCE_PATTERN = createSourceScanPattern(DEFAULT_SOURCE_SCAN_EXTENSIONS);
98
+ function isTailwindV4ApplyOnlyCss(css, root) {
99
+ return hasTailwindApplyDirective(css) && !hasTailwindRootDirectives(root, { importFallback: true });
100
+ }
101
+ function resolveTailwindV4PostcssSourceCss(css, sourceOptions, root) {
102
+ const packageName = sourceOptions.packageName ?? "tailwindcss";
103
+ return isTailwindV4ApplyOnlyCss(css, root) ? `@import "${packageName}" source(none);\n@reference "${packageName}";\n${css}` : css;
104
+ }
105
+ function isMiniProgramGeneratorTarget(target) {
106
+ return target !== "web";
107
+ }
108
+ function finalizeGeneratedCss(css, target, styleOptions, webCompat) {
109
+ if (target === "web") {
110
+ const webCss = transformWebCssCompat(css, webCompat);
111
+ return (styleOptions?.cssOptions?.platform ?? styleOptions?.platform) === "lynx" ? transformLynxCssCompat(webCss) : webCss;
112
+ }
113
+ if (!isMiniProgramGeneratorTarget(target)) return css;
114
+ return finalizeMiniProgramCss(css, {
115
+ cssSelectorReplacement: styleOptions?.cssOptions?.cssSelectorReplacement ?? styleOptions?.cssSelectorReplacement,
116
+ isTailwindcssV4: true,
117
+ tailwindcssV4GradientFallback: styleOptions?.cssOptions?.tailwindcssV4GradientFallback ?? styleOptions?.tailwindcssV4GradientFallback
118
+ });
119
+ }
120
+ function createWeappTailwindcssPostcssPlugin(adapters) {
121
+ const plugin = (options = {}) => {
122
+ return {
123
+ postcssPlugin: PLUGIN_NAME,
124
+ async Once(root, { result }) {
125
+ const { candidates, generator: userGeneratorOptions, scanSources, sources, styleOptions, ...sourceOptions } = options;
126
+ const generatorOptions = adapters.normalizeGeneratorOptions(userGeneratorOptions);
127
+ const rawCss = sourceOptions.css ?? root.toString();
128
+ const base = resolvePostcssBase(result, options);
129
+ const projectRoot = resolvePostcssProjectRoot(result, options);
130
+ const compiledScan = adapters.compiledSourceScan && scanSources !== false;
131
+ const sourceEntries = compiledScan ? [] : await resolveCssSourceEntries(root, base, POSTCSS_SOURCE_PATTERN);
132
+ const [collectedSources, autoCandidates] = await Promise.all([compiledScan ? {
133
+ files: [],
134
+ sources: []
135
+ } : collectPostcssLocalSources(root, result, options, { sourceEntries }), compiledScan ? /* @__PURE__ */ new Set() : collectAutoTailwindCandidates(root, result, options, {
136
+ css: rawCss,
137
+ sourceEntries
138
+ })]);
139
+ const generatorConfig = generatorOptions.config ?? options.config;
140
+ const isApplyOnlyTailwindV4Css = isTailwindV4ApplyOnlyCss(rawCss, root);
141
+ const applyOnlyCssSelectors = isApplyOnlyTailwindV4Css ? collectApplyOnlyCssSelectorsRoot(root) : void 0;
142
+ const source = await adapters.resolveTailwindV4Source({
143
+ ...sourceOptions,
144
+ css: prependConfigDirective(resolveTailwindV4PostcssSourceCss(rawCss, sourceOptions, root), generatorConfig),
145
+ base,
146
+ projectRoot
147
+ });
148
+ const generator = adapters.createGenerator(source);
149
+ const generatorStyleOptions = {
150
+ ...generatorOptions.styleOptions,
151
+ ...styleOptions
152
+ };
153
+ try {
154
+ const generated = await generator.generate({
155
+ candidates: /* @__PURE__ */ new Set([...autoCandidates, ...candidates ?? []]),
156
+ scanSources: compiledScan ? true : scanSources ?? false,
157
+ ...compiledScan ? {
158
+ scanMode: "compiled",
159
+ excludeFiles: result.opts.to ? [result.opts.to] : []
160
+ } : {},
161
+ sources: [...collectedSources.sources, ...sources ?? []],
162
+ styleOptions: generatorStyleOptions,
163
+ target: generatorOptions.target
164
+ });
165
+ replaceRootCss(root, finalizeGeneratedCss(isApplyOnlyTailwindV4Css ? filterApplyOnlyGeneratedCss(generated.css, applyOnlyCssSelectors ?? /* @__PURE__ */ new Set()) : generated.css, generated.target, generatorStyleOptions, generatorOptions.webCompat), result);
166
+ addDependencyMessages(result, generated);
167
+ addSourceDependencyMessages(result, collectedSources.files);
168
+ result.messages.push({
169
+ type: "weapp-tailwindcss:generated",
170
+ plugin: PLUGIN_NAME,
171
+ target: generated.target,
172
+ classSet: generated.classSet,
173
+ rawCss: generated.rawCss
174
+ });
175
+ } finally {
176
+ generator.dispose?.();
177
+ }
178
+ }
179
+ };
180
+ };
181
+ plugin.postcss = true;
182
+ return plugin;
183
+ }
184
+ //#endregion
185
+ export { createWeappTailwindcssPostcssPlugin };
@@ -0,0 +1,3 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_plugin = require("./plugin-BWDgxMn5.cjs");
3
+ exports.createWeappTailwindcssPostcssPlugin = require_plugin.createWeappTailwindcssPostcssPlugin;
@@ -0,0 +1,2 @@
1
+ export * from './generator-plugin/index.js';
2
+ export type { PluginCreator } from './postcss-runtime.js';
package/dist/plugin.js ADDED
@@ -0,0 +1,2 @@
1
+ import { createWeappTailwindcssPostcssPlugin } from "./plugin-CpkRzMhp.js";
2
+ export { createWeappTailwindcssPostcssPlugin };
@@ -0,0 +1,9 @@
1
+ import type { IStyleHandlerOptions } from '../types.js';
2
+ export type ApplyConfiguredCssCalcOptions = Pick<IStyleHandlerOptions, 'cssCalc' | 'cssOptions' | 'customPropertyValues'> & {
3
+ /** 额外用于收集自定义属性的 CSS,例如生成器完整产物。 */
4
+ contextCss?: string | undefined;
5
+ };
6
+ /**
7
+ * 仅按 `cssCalc` 配置预计算 `calc()` / `var()`,不跑小程序选择器替换或单位转换。
8
+ */
9
+ export declare function applyConfiguredCssCalc(css: string, options?: ApplyConfiguredCssCalcOptions): Promise<string>;
@@ -0,0 +1,2 @@
1
+ import postcss$1 from "postcss";
2
+ export { postcss$1 as postcss };
@@ -1,2 +1,2 @@
1
- export type { AcceptedPlugin, AtRule, Container, Declaration, Document, Helpers, Node, Plugin, PluginCreator, ProcessOptions, Processor, Result, Root, Rule, } from 'postcss';
1
+ export type { AcceptedPlugin, AtRule, ChildNode, Container, Declaration, Document, Helpers, Node, Plugin, PluginCreator, ProcessOptions, Processor, Result, Root, Rule, } from 'postcss';
2
2
  export { default as postcss } from 'postcss';
@@ -0,0 +1,21 @@
1
+ //#region src/preflight.ts
2
+ function createInjectPreflight(options) {
3
+ const result = [];
4
+ if (options && typeof options === "object") {
5
+ const entries = Object.entries(options);
6
+ for (const [prop, value] of entries) if (value !== false) result.push({
7
+ prop,
8
+ value: value.toString()
9
+ });
10
+ }
11
+ return () => {
12
+ return result;
13
+ };
14
+ }
15
+ //#endregion
16
+ Object.defineProperty(exports, "createInjectPreflight", {
17
+ enumerable: true,
18
+ get: function() {
19
+ return createInjectPreflight;
20
+ }
21
+ });
@@ -0,0 +1,16 @@
1
+ //#region src/preflight.ts
2
+ function createInjectPreflight(options) {
3
+ const result = [];
4
+ if (options && typeof options === "object") {
5
+ const entries = Object.entries(options);
6
+ for (const [prop, value] of entries) if (value !== false) result.push({
7
+ prop,
8
+ value: value.toString()
9
+ });
10
+ }
11
+ return () => {
12
+ return result;
13
+ };
14
+ }
15
+ //#endregion
16
+ export { createInjectPreflight };
@@ -0,0 +1,354 @@
1
+ import { createRequire } from "node:module";
2
+ import { TokenType, tokenize } from "@csstools/css-tokenizer";
3
+ import path from "node:path";
4
+ import { resolveProjectSourceFiles } from "@weapp-tailwindcss/engine";
5
+ import { DEFAULT_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSION_RE, FULL_SOURCE_SCAN_PATTERN, createSourceScanPattern, createSourceScanPattern as createSourceScanPattern$1, createSourceScanPlan, createTailwindSourceEntryMatcher, expandSourceEntries, isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, normalizeGlobPattern, normalizeLegacyContentEntries, normalizeLegacyContentEntries as normalizeLegacyContentEntries$1, resolveSourceScanPath, resolveTailwindSourceEntry, resolveTailwindSourceEntry as resolveTailwindSourceEntry$1, sourcePathApi, toPosixPath } from "@weapp-tailwindcss/source-scan";
6
+ import { loadConfig } from "tailwindcss-config";
7
+ //#region src/syntax/css-import.ts
8
+ function significantTokens(params) {
9
+ return tokenize({ css: params }).filter((token) => token[0] !== TokenType.Whitespace && token[0] !== TokenType.Comment);
10
+ }
11
+ function isCssWhitespace(char) {
12
+ return char === " " || char === " " || char === "\n" || char === "\r" || char === "\f";
13
+ }
14
+ function skipCssWhitespace(params, index) {
15
+ while (index < params.length && isCssWhitespace(params[index])) index++;
16
+ return index;
17
+ }
18
+ function parseSimpleQuotedSpecifier(params, start) {
19
+ const quote = params[start];
20
+ if (quote !== "\"" && quote !== "'") return;
21
+ let index = start + 1;
22
+ while (index < params.length) {
23
+ const char = params[index];
24
+ if (char === "\\" || char === "\n" || char === "\r") return;
25
+ if (char === quote) return {
26
+ specifier: params.slice(start + 1, index),
27
+ raw: params.slice(start, index + 1),
28
+ quote
29
+ };
30
+ index++;
31
+ }
32
+ }
33
+ function parseSimpleImportSpecifier(params) {
34
+ let index = skipCssWhitespace(params, 0);
35
+ const quoted = parseSimpleQuotedSpecifier(params, index);
36
+ if (quoted) return quoted;
37
+ if (params.slice(index, index + 4).toLowerCase() !== "url(") return;
38
+ const urlStart = index;
39
+ index = skipCssWhitespace(params, index + 4);
40
+ const inner = parseSimpleQuotedSpecifier(params, index);
41
+ if (!inner) return;
42
+ index = skipCssWhitespace(params, index + inner.raw.length);
43
+ if (params[index] !== ")") return;
44
+ return {
45
+ specifier: inner.specifier,
46
+ raw: params.slice(urlStart, index + 1),
47
+ quote: inner.quote
48
+ };
49
+ }
50
+ /**
51
+ * 解析 `@import` / `@use` / `@forward` 参数中的请求串。
52
+ * 无 escape/注释的引号和 `url("...")` 走快路径;复杂输入才使用 CSS tokenizer。
53
+ */
54
+ function parseCssImportSpecifier(params) {
55
+ const simple = parseSimpleImportSpecifier(params);
56
+ if (simple) return simple;
57
+ const tokens = significantTokens(params);
58
+ const first = tokens[0];
59
+ if (!first || first[0] === TokenType.EOF) return;
60
+ if (first[0] === TokenType.String || first[0] === TokenType.URL || first[0] === TokenType.Ident) return {
61
+ specifier: first[4].value,
62
+ raw: first[1],
63
+ quote: first[0] === TokenType.String ? first[1][0] : void 0
64
+ };
65
+ 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 {
66
+ specifier: tokens[1][4].value,
67
+ raw: params.slice(first[2], tokens[2][3] + 1),
68
+ quote: tokens[1][0] === TokenType.String ? tokens[1][1][0] : void 0
69
+ };
70
+ }
71
+ /** 把文件系统路径写成 CSS 请求串;缓存和读文件仍使用原始路径。 */
72
+ function quoteCssImportSpecifier(file, quote = "\"") {
73
+ return `${quote}${(path.sep === "\\" || /^[a-z]:[\\/]|^\\\\/i.test(file) ? file.replaceAll("\\", "/") : file).replaceAll("\\", "\\\\").replaceAll(quote, `\\${quote}`).replaceAll("\n", "\\a ").replaceAll("\r", "\\d ")}${quote}`;
74
+ }
75
+ /** 判断 import 参数是否指向 Tailwind CSS 包入口。 */
76
+ function isTailwindCssImport(params) {
77
+ const specifier = parseCssImportSpecifier(params)?.specifier;
78
+ if (!specifier) return false;
79
+ if (specifier === "tailwindcss" || specifier.startsWith("tailwindcss/")) return true;
80
+ const paths = specifier.includes("\\") ? path.win32 : path.posix;
81
+ return paths.basename(specifier) === "index.css" && paths.basename(paths.dirname(specifier)) === "tailwindcss";
82
+ }
83
+ /** 解析 `@import "..." source(...)` 中的 source 参数。 */
84
+ function parseImportSourceParam(params) {
85
+ const tokens = significantTokens(params);
86
+ const index = tokens.findIndex((token) => token[0] === TokenType.Function && token[4].value === "source");
87
+ const value = tokens[index + 1];
88
+ if (index < 0 || tokens[index + 2]?.[0] !== TokenType.CloseParen) return;
89
+ if (value?.[0] === TokenType.Ident && value[4].value === "none") return {
90
+ none: true,
91
+ sourcePath: void 0
92
+ };
93
+ return value?.[0] === TokenType.String ? {
94
+ none: false,
95
+ sourcePath: value[4].value
96
+ } : void 0;
97
+ }
98
+ //#endregion
99
+ //#region src/source-scan/params.ts
100
+ function parseConfigParam(params) {
101
+ const value = params.trim();
102
+ return /^(['"])(.+)\1$/.exec(value)?.[2];
103
+ }
104
+ function parseSourceFileParam(params) {
105
+ const value = params.trim();
106
+ if (!value || value === "none" || value.startsWith("inline(")) return;
107
+ const negated = value.startsWith("not ");
108
+ const sourceValue = negated ? value.slice(4).trim() : value;
109
+ if (sourceValue.startsWith("inline(")) return;
110
+ const match = /^(['"])(.+)\1$/.exec(sourceValue);
111
+ return match?.[2] ? {
112
+ negated,
113
+ sourcePath: match[2]
114
+ } : void 0;
115
+ }
116
+ //#endregion
117
+ //#region src/source-scan/inline-source.ts
118
+ const NUMERICAL_RANGE_RE = /^(-?\d+)\.\.(-?\d+)(?:\.\.(-?\d+))?$/;
119
+ function segmentTopLevel(input, separator, options = {}) {
120
+ const parts = [];
121
+ const stack = [];
122
+ let lastPos = 0;
123
+ let quote;
124
+ for (let index = 0; index < input.length; index++) {
125
+ const char = input[index];
126
+ if (char === "\\") {
127
+ index += 1;
128
+ continue;
129
+ }
130
+ if (quote) {
131
+ if (char === quote) quote = void 0;
132
+ continue;
133
+ }
134
+ if (char === "\"" || char === "'") {
135
+ quote = char;
136
+ continue;
137
+ }
138
+ if (char === "(") {
139
+ stack.push(")");
140
+ continue;
141
+ }
142
+ if (char === "[") {
143
+ stack.push("]");
144
+ continue;
145
+ }
146
+ if (char === "{") {
147
+ stack.push("}");
148
+ continue;
149
+ }
150
+ if (stack.length > 0 && char === stack[stack.length - 1]) {
151
+ stack.pop();
152
+ continue;
153
+ }
154
+ if (stack.length === 0 && char === separator) {
155
+ const part = input.slice(lastPos, index);
156
+ if (part || options.keepEmpty) parts.push(part);
157
+ lastPos = index + 1;
158
+ }
159
+ }
160
+ const part = input.slice(lastPos);
161
+ if (part || options.keepEmpty) parts.push(part);
162
+ return parts;
163
+ }
164
+ function isSequence(value) {
165
+ return NUMERICAL_RANGE_RE.test(value);
166
+ }
167
+ function expandSequence(value) {
168
+ const match = value.match(NUMERICAL_RANGE_RE);
169
+ if (!match) return [value];
170
+ const [, start, end, stepValue] = match;
171
+ if (start === void 0 || end === void 0) return [value];
172
+ let step = stepValue ? Number.parseInt(stepValue, 10) : void 0;
173
+ const startNumber = Number.parseInt(start, 10);
174
+ const endNumber = Number.parseInt(end, 10);
175
+ const increasing = startNumber < endNumber;
176
+ if (step === void 0) step = increasing ? 1 : -1;
177
+ if (step === 0) return [];
178
+ if (increasing && step < 0) step = -step;
179
+ if (!increasing && step > 0) step = -step;
180
+ const result = [];
181
+ for (let value = startNumber; increasing ? value <= endNumber : value >= endNumber; value += step) result.push(String(value));
182
+ return result;
183
+ }
184
+ function expandInlineSourceCandidatePattern(pattern) {
185
+ const index = pattern.indexOf("{");
186
+ if (index === -1) return [pattern];
187
+ const prefix = pattern.slice(0, index);
188
+ const rest = pattern.slice(index);
189
+ let depth = 0;
190
+ let endIndex = -1;
191
+ for (let index = 0; index < rest.length; index++) {
192
+ const char = rest[index];
193
+ if (char === "{") depth += 1;
194
+ else if (char === "}") {
195
+ depth -= 1;
196
+ if (depth === 0) {
197
+ endIndex = index;
198
+ break;
199
+ }
200
+ }
201
+ }
202
+ if (endIndex === -1) return [pattern];
203
+ const inner = rest.slice(1, endIndex);
204
+ const suffix = rest.slice(endIndex + 1);
205
+ const parts = (isSequence(inner) ? expandSequence(inner) : segmentTopLevel(inner, ",", { keepEmpty: true })).flatMap((part) => expandInlineSourceCandidatePattern(part));
206
+ return expandInlineSourceCandidatePattern(suffix).flatMap((suffix) => parts.map((part) => `${prefix}${part}${suffix}`));
207
+ }
208
+ function parseSourceInlineParam(params) {
209
+ let value = params.trim();
210
+ const negated = value.startsWith("not ");
211
+ if (negated) value = value.slice(4).trim();
212
+ if (!value.startsWith("inline(") || !value.endsWith(")")) return;
213
+ const inlineValue = value.slice(7, -1).trim();
214
+ const match = /^(['"])([\s\S]*)\1$/.exec(inlineValue);
215
+ if (!match) return;
216
+ const source = match[2];
217
+ if (source === void 0) return;
218
+ return {
219
+ negated,
220
+ source
221
+ };
222
+ }
223
+ function collectCssInlineSourceCandidates(root) {
224
+ const included = /* @__PURE__ */ new Set();
225
+ const excluded = /* @__PURE__ */ new Set();
226
+ root.walkAtRules("source", (rule) => {
227
+ const parsed = parseSourceInlineParam(rule.params);
228
+ if (!parsed) return;
229
+ const target = parsed.negated ? excluded : included;
230
+ for (const source of segmentTopLevel(parsed.source, " ")) {
231
+ const trimmed = source.trim();
232
+ if (!trimmed) continue;
233
+ for (const candidate of expandInlineSourceCandidatePattern(trimmed)) {
234
+ const normalized = candidate.trim();
235
+ if (normalized) target.add(normalized);
236
+ }
237
+ }
238
+ });
239
+ for (const candidate of excluded) included.delete(candidate);
240
+ return {
241
+ included,
242
+ excluded
243
+ };
244
+ }
245
+ //#endregion
246
+ //#region src/source-scan.ts
247
+ async function resolveCssSourceEntries(root, base, defaultPattern = createSourceScanPattern()) {
248
+ const entries = [];
249
+ const tasks = [];
250
+ root.walkAtRules("source", (rule) => {
251
+ const parsed = parseSourceFileParam(rule.params);
252
+ if (!parsed) return;
253
+ tasks.push(resolveTailwindSourceEntry(parsed.sourcePath, base, parsed.negated, defaultPattern));
254
+ });
255
+ entries.push(...await Promise.all(tasks));
256
+ return entries;
257
+ }
258
+ async function expandTailwindSourceEntries(entries, options = {}) {
259
+ return expandSourceEntries(entries, ({ cwd, sources }) => resolveProjectSourceFiles({
260
+ cwd,
261
+ sources,
262
+ ...options.ignore ? { ignoredSources: options.ignore.map((pattern) => ({
263
+ base: cwd,
264
+ pattern: normalizeGlobPattern(pattern),
265
+ negated: true
266
+ })) } : {}
267
+ }));
268
+ }
269
+ //#endregion
270
+ //#region src/source-scan/description.ts
271
+ /** 只提取来源指令;默认扫描策略与配置加载由调用层决定。 */
272
+ function describeCssSources(root, isSourceImport = isTailwindCssImport) {
273
+ const imports = [];
274
+ const sources = [];
275
+ const configs = [];
276
+ root.walkAtRules((rule) => {
277
+ if (rule.name === "import" && isSourceImport(rule.params)) imports.push(parseImportSourceParam(rule.params) ?? {});
278
+ else if (rule.name === "source") {
279
+ const source = parseSourceFileParam(rule.params);
280
+ if (source) sources.push(source);
281
+ } else if (rule.name === "config") {
282
+ const config = parseConfigParam(rule.params);
283
+ if (config) configs.push(config);
284
+ }
285
+ });
286
+ return {
287
+ imports,
288
+ sources,
289
+ configs,
290
+ inlineCandidates: collectCssInlineSourceCandidates(root)
291
+ };
292
+ }
293
+ //#endregion
294
+ //#region src/source-scan/resolve.ts
295
+ /** 将 AST 描述与配置 content 合并,再交给共享扫描策略生成执行计划。 */
296
+ async function resolveCssScanSources(definitions, policy) {
297
+ const entries = [];
298
+ const configEntries = [];
299
+ const configGroups = [];
300
+ const configPaths = /* @__PURE__ */ new Set();
301
+ const included = /* @__PURE__ */ new Set();
302
+ const excluded = /* @__PURE__ */ new Set();
303
+ let automaticBase;
304
+ let sourceNone = false;
305
+ let hasImport = false;
306
+ for (const { root, base } of definitions) {
307
+ const descriptor = describeCssSources(root);
308
+ hasImport ||= descriptor.imports.length > 0;
309
+ sourceNone ||= descriptor.imports.some((item) => item.none);
310
+ for (const item of descriptor.imports) if (item.sourcePath) automaticBase = sourcePathApi(base, item.sourcePath).resolve(base, item.sourcePath);
311
+ for (const source of descriptor.sources) entries.push(await resolveTailwindSourceEntry(source.sourcePath, base, source.negated, policy.pattern));
312
+ for (const value of descriptor.inlineCandidates.included) included.add(value);
313
+ for (const value of descriptor.inlineCandidates.excluded) excluded.add(value);
314
+ for (const request of descriptor.configs) configPaths.add(policy.configResolution === "module" ? createRequire(path.join(base, "package.json")).resolve(request) : sourcePathApi(base, request).resolve(base, request));
315
+ }
316
+ if (policy.config) configPaths.add(sourcePathApi(policy.base, policy.config).resolve(policy.base, policy.config));
317
+ for (const config of policy.loadConfigContent === false ? [] : configPaths) {
318
+ const base = path.dirname(config);
319
+ const loaded = await loadConfig({
320
+ config,
321
+ cwd: base
322
+ });
323
+ const group = normalizeLegacyContentEntries(loaded?.config.content, base, { relativeBase: base });
324
+ configGroups.push(group);
325
+ configEntries.push(...group);
326
+ }
327
+ const explicitEntries = policy.sourceEntries ?? entries;
328
+ const combinedEntries = [...explicitEntries, ...configEntries];
329
+ let mode = policy.automatic;
330
+ if (mode !== "disabled") {
331
+ if (automaticBase) mode = "auto";
332
+ else if (sourceNone || policy.requireImport && !hasImport && combinedEntries.length === 0) mode = "disabled";
333
+ }
334
+ const base = automaticBase ?? (combinedEntries.length > 0 ? policy.base : policy.defaultBase ?? policy.base);
335
+ return {
336
+ entries: createSourceScanPlan({
337
+ base,
338
+ mode,
339
+ entries: combinedEntries,
340
+ pattern: policy.pattern,
341
+ ...policy.ignoredPatterns ? { ignoredPatterns: policy.ignoredPatterns } : {}
342
+ }),
343
+ explicitEntries,
344
+ configEntries,
345
+ configGroups,
346
+ configPaths: [...configPaths],
347
+ inlineCandidates: {
348
+ included,
349
+ excluded
350
+ }
351
+ };
352
+ }
353
+ //#endregion
354
+ export { DEFAULT_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSIONS, FULL_SOURCE_SCAN_EXTENSION_RE, FULL_SOURCE_SCAN_PATTERN, collectCssInlineSourceCandidates, createSourceScanPattern$1 as createSourceScanPattern, createTailwindSourceEntryMatcher, describeCssSources, expandInlineSourceCandidatePattern, expandTailwindSourceEntries, isFileExcludedByTailwindSourceEntries, isFileMatchedByTailwindSourceEntries, isTailwindCssImport, normalizeLegacyContentEntries$1 as normalizeLegacyContentEntries, parseConfigParam, parseCssImportSpecifier, parseImportSourceParam, parseSourceFileParam, quoteCssImportSpecifier, resolveCssScanSources, resolveCssSourceEntries, resolveSourceScanPath, resolveTailwindSourceEntry$1 as resolveTailwindSourceEntry, toPosixPath };