weapp-tailwindcss
Version:
把 tailwindcss 原子化样式思想,带给小程序开发者们! bring tailwindcss to miniprogram developers!
1,520 lines • 118 kB
JavaScript
import { resolveUniUtsPlatform as resolveUniUtsPlatform$1 } from "./framework.js";
import { c as withCssMacroStyleOptions, i as hasCssMacroTailwindV4Source, o as transformCssMacroCss, s as transformCssMacroTailwindV4Source, t as hasCssMacroStyleOptions } from "./auto-2dg_uhEJ.js";
import { n as _defineProperty, t as omitUndefined } from "./object-Bvy6-w9r.js";
import "./utils-MVwpU07P.js";
import { createRequire } from "node:module";
import fs, { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
import path from "node:path";
import process from "node:process";
import { createTailwindGenerationSession, createTailwindV4Engine, extractRawCandidates, loadTailwindV4DesignSystem, resolveProjectSourceFiles, resolveTailwindV4Source, resolveValidTailwindV4Candidates as resolveValidTailwindV4Candidates$1 } from "@tailwindcss-mangle/engine";
import { analyzeTailwindCssDirectives, createStyleHandler, filterExistingCssRules, finalizeMiniProgramCss, hasMiniProgramCssSpecificityPlaceholders, isTailwindCssGenerationDirective, isTailwindCssImportAtRule, isTailwindCssPackageJsonImportRequest, normalizeTailwindCssImportRequest, normalizeTailwindcssWebRpxDeclarations, parseTailwindCssConfigRequest, parseTailwindCssDirectiveRequest, postcss, protectDynamicColorMixAlpha, pruneMiniProgramGeneratedCss, pruneMiniProgramGeneratedCss as pruneMiniProgramGeneratedCss$1, removeUnsupportedCascadeLayers, removeUnsupportedMiniProgramAtRules, stripMiniProgramCssSpecificityPlaceholders } from "@weapp-tailwindcss/postcss";
import { LRUCache } from "lru-cache";
import { stat } from "node:fs/promises";
import micromatch from "micromatch";
//#region src/runtime-branch/generator-target-env.ts
const explicitGeneratorTargetEnvKeys = ["WEAPP_TW_TARGET", "WEAPP_TAILWINDCSS_TARGET"];
const uniWebPlatformEnvKeys = ["UNI_PLATFORM", "UNI_UTS_PLATFORM"];
const mpxWebPlatformEnvKeys = ["MPX_CLI_MODE", "MPX_CURRENT_TARGET_MODE"];
function getEnvValue(key) {
return typeof process === "undefined" ? void 0 : process.env[key];
}
function normalizeGeneratorTargetValue(value) {
return value === "weapp" || value === "web" ? value : void 0;
}
function isUniWebPlatform(value) {
const normalized = value?.trim().toLowerCase();
return normalized === "h5" || normalized?.startsWith("web") === true;
}
function isUniAppWebViewPlatform(value) {
const normalized = value?.trim().toLowerCase();
return normalized === "app" || normalized === "app-plus";
}
function isUniNativeAppPlatform(value) {
return (value?.trim().toLowerCase())?.startsWith("app-") === true;
}
function isMpxWebPlatform(value) {
return value?.trim().toLowerCase() === "web";
}
function inferGeneratorTargetFromExplicitEnv() {
for (const key of explicitGeneratorTargetEnvKeys) {
const target = normalizeGeneratorTargetValue(getEnvValue(key));
if (target !== void 0) return target;
}
}
function shouldUseWebGeneratorTargetFromEnv() {
return uniWebPlatformEnvKeys.some((key) => isUniWebPlatform(getEnvValue(key))) || isUniAppWebViewPlatform(getEnvValue("UNI_PLATFORM")) && !isUniNativeAppPlatform(getEnvValue("UNI_UTS_PLATFORM")) || mpxWebPlatformEnvKeys.some((key) => isMpxWebPlatform(getEnvValue(key))) || getEnvValue("TARO_ENV") === "h5";
}
function shouldUseUniAppWebRpxCompatibility(appType) {
return appType === "uni-app-vite" || appType === "uni-app-x" || shouldUseWebGeneratorTargetFromEnv();
}
function shouldUseUniAppViteWebViewGeneratorTarget(appType, platform = getEnvValue("UNI_PLATFORM")) {
return appType === "uni-app-vite" && isUniAppWebViewPlatform(platform);
}
function inferGeneratorTargetFromEnv() {
return inferGeneratorTargetFromExplicitEnv() ?? (shouldUseWebGeneratorTargetFromEnv() ? "web" : "weapp");
}
//#endregion
//#region src/tailwindcss/v4-engine/candidates.ts
const UNSUPPORTED_MINI_PROGRAM_TAILWIND_V4_CANDIDATE_RE = /(?:^|:)(?:group|peer|in|not-in)-[^\s:]*\/|(?:^|:)(?:in|not-in)-\[/;
function isUnsupportedMiniProgramTailwindV4Candidate(candidate) {
return UNSUPPORTED_MINI_PROGRAM_TAILWIND_V4_CANDIDATE_RE.test(candidate);
}
function filterUnsupportedMiniProgramTailwindV4Candidates(candidates) {
if (!candidates) return;
return new Set([...candidates].filter((candidate) => !isUnsupportedMiniProgramTailwindV4Candidate(candidate)));
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/rpx-candidates.ts
const RPX_LENGTH_UTILITY_PATTERN = String.raw`text|border(?:-[trblxyse])?|bg|outline|ring`;
const BARE_RPX_LENGTH_CANDIDATE_RE = new RegExp(String.raw`(^|:)(!?)(${RPX_LENGTH_UTILITY_PATTERN})-\[([-+]?(?:\d+|\d*\.\d+)rpx)\](.*)$`, "u");
const BARE_RPX_LENGTH_HINT_CANDIDATE_RE = new RegExp(String.raw`(?:^|:)!?(${RPX_LENGTH_UTILITY_PATTERN})-\[length:([-+]?(?:\d+|\d*\.\d+)rpx)\].*$`, "u");
const RPX_LENGTH_SELECTOR_RE = new RegExp(String.raw`(${RPX_LENGTH_UTILITY_PATTERN})-\\\[length\\:((?:\\[.+-]|[+\-.\d])+rpx)\\\]`, "g");
function normalizeRpxLengthCandidate(candidate) {
return candidate.replace(BARE_RPX_LENGTH_CANDIDATE_RE, (_match, prefix, important, utility, value, suffix) => {
return `${prefix}${important}${utility}-[length:${value}]${suffix}`;
});
}
function normalizeRpxLengthCandidates(candidates) {
const normalized = /* @__PURE__ */ new Set();
const restoreCandidates = /* @__PURE__ */ new Map();
for (const candidate of candidates) {
const normalizedCandidate = normalizeRpxLengthCandidate(candidate);
normalized.add(normalizedCandidate);
if (normalizedCandidate !== candidate) restoreCandidates.set(normalizedCandidate, candidate);
}
return {
candidates: normalized,
restoreCandidates
};
}
function restoreRpxLengthCandidates(candidates, restoreCandidates) {
if (restoreCandidates.size === 0) return new Set(candidates);
return new Set([...candidates].map((candidate) => restoreCandidates.get(candidate) ?? candidate));
}
function normalizeCssEscapedRpxSelectorValue(value) {
return value.replace(/\\([.+-])/g, "$1");
}
function restoreRpxLengthCssSelectors(css, restoreCandidates) {
if (restoreCandidates.size === 0 || !css.includes("\\[length\\:")) return css;
const restoredUtilities = new Set([...restoreCandidates.keys()].map((candidate) => {
const match = BARE_RPX_LENGTH_HINT_CANDIDATE_RE.exec(candidate);
return match ? `${match[1]}:${match[2]}` : void 0;
}).filter((value) => Boolean(value)));
return css.replace(RPX_LENGTH_SELECTOR_RE, (match, utility, value) => {
return restoredUtilities.has(`${utility}:${normalizeCssEscapedRpxSelectorValue(value)}`) ? `${utility}-\\[${value}\\]` : match;
});
}
const INCREMENTAL_GENERATE_ENTRY_CANDIDATES_MAX = 12e3;
const INCREMENTAL_GENERATE_ENTRY_CSS_BYTES_MAX = 2 * 1024 * 1024;
const incrementalGenerateCache = new LRUCache({ max: 8 });
const incrementalGenerateTaskCache = new LRUCache({ max: 32 });
function collectCandidates(candidates) {
return new Set(candidates ?? []);
}
function hasRemovedCandidates(previousCandidates, nextCandidates) {
for (const candidate of previousCandidates) if (!nextCandidates.has(candidate)) return true;
return false;
}
function createStableJson(value) {
if (value === void 0) return "undefined";
if (value === null || typeof value !== "object") return JSON.stringify(value);
if (Array.isArray(value)) return `[${value.map((item) => createStableJson(item)).join(",")}]`;
return `{${Object.keys(value).sort().map((key) => {
const record = value;
return `${JSON.stringify(key)}:${createStableJson(record[key])}`;
}).join(",")}}`;
}
function createDependencyFingerprint(files) {
return files.map((file) => {
try {
const stat = fs.statSync(file);
return `${file}:${stat.size}:${stat.mtimeMs}`;
} catch {
return `${file}:missing`;
}
}).join("|");
}
function createTailwindV4SourceCacheKey(source) {
return [
source.projectRoot,
source.base,
createStableJson(source.baseFallbacks),
source.css,
createDependencyFingerprint(source.dependencies)
].join("\0");
}
function createIncrementalGenerateCacheKey(source, target, styleOptions) {
return [
createTailwindV4SourceCacheKey(source),
target,
createStableJson(styleOptions)
].join("\0");
}
function createIncrementalGenerateTaskCacheKey(cacheKey, requestedCandidates, scanSources) {
return [
cacheKey,
scanSources === true ? "scan:1" : "scan:0",
[...requestedCandidates].sort().join("\n")
].join("\0");
}
function runIncrementalGenerateTask(cacheKey, requestedCandidates, scanSources, task) {
const taskKey = createIncrementalGenerateTaskCacheKey(cacheKey, requestedCandidates, scanSources);
const cachedTask = incrementalGenerateTaskCache.get(taskKey);
if (cachedTask) return cachedTask;
const promise = task();
incrementalGenerateTaskCache.set(taskKey, promise);
promise.finally(() => {
if (incrementalGenerateTaskCache.get(taskKey) === promise) incrementalGenerateTaskCache.delete(taskKey);
});
return promise;
}
function createIncrementalDesignSystemPromise(source, cacheKey) {
const promise = loadTailwindV4DesignSystem(source);
promise.catch(() => {
if (incrementalGenerateCache.get(cacheKey)?.designSystemPromise === promise) incrementalGenerateCache.delete(cacheKey);
});
return promise;
}
function resolveTargetCandidates(candidates, target) {
const collected = collectCandidates(candidates);
return target === "weapp" ? filterUnsupportedMiniProgramTailwindV4Candidates(collected) : collected;
}
function collectSeenCandidates(generated) {
return new Set(generated.classSet);
}
function createIncrementalStyleOptions(styleOptions) {
return {
...styleOptions,
isMainChunk: false
};
}
function resolveStyleOptions(source, options) {
return hasCssMacroTailwindV4Source(source.css) ? withCssMacroStyleOptions(options) : options;
}
function collectCustomPropertyValues(css) {
const values = /* @__PURE__ */ new Map();
try {
postcss.parse(css).walkDecls((decl) => {
if (decl.prop.startsWith("--")) values.set(decl.prop, decl.value.trim());
});
} catch {}
return values;
}
function mergeCustomPropertyValues(target, css) {
for (const [prop, value] of collectCustomPropertyValues(css)) target.set(prop, value);
}
function createStableTextSignature(input) {
let hash = 2166136261;
for (let i = 0; i < input.length; i++) {
hash ^= input.charCodeAt(i);
hash = Math.imul(hash, 16777619);
}
return (hash >>> 0).toString(36);
}
function summarizeIncrementalCacheKey(key) {
return {
keyHash: createStableTextSignature(key),
keyBytes: key.length
};
}
function shouldRebuildIncrementalEntry(cached, requestedCandidates, missingCandidates) {
return cached.seenCandidates.size + missingCandidates.length > 12e3 || cached.css.length > 2097152 || cached.rawCss.length > 2097152 || requestedCandidates.size > 12e3;
}
function shouldAdmitIncrementalEntry(requestedCandidates, generated) {
return requestedCandidates.size <= 12e3 && generated.css.length <= 2097152 && generated.rawCss.length <= 2097152;
}
function seedIncrementalGenerateCache(options) {
if (!shouldAdmitIncrementalEntry(options.requestedCandidates, options.generated)) return false;
const cacheKey = createIncrementalGenerateCacheKey(options.compatibleSource, options.target, options.styleOptions);
const customPropertyValues = collectCustomPropertyValues(options.compatibleSource.css);
mergeCustomPropertyValues(customPropertyValues, options.generated.css);
incrementalGenerateCache.set(cacheKey, {
seenCandidates: collectSeenCandidates(options.generated),
classSet: new Set(options.generated.classSet),
css: options.generated.css,
rawCss: options.generated.rawCss,
customPropertyValues,
designSystemPromise: createIncrementalDesignSystemPromise(options.compatibleSource, cacheKey),
dependencies: options.generated.dependencies,
sources: options.generated.sources,
root: options.generated.root,
target: options.generated.target
});
return true;
}
function shouldNormalizeRpxLengthCandidatesForTarget(target, styleOptions) {
if (target !== "web") return true;
return shouldUseUniAppWebRpxCompatibility(styleOptions?.appType);
}
function normalizeTargetRpxLengthCandidates(candidates, target, styleOptions) {
return shouldNormalizeRpxLengthCandidatesForTarget(target, styleOptions) ? normalizeRpxLengthCandidates(candidates) : {
candidates: new Set(candidates),
restoreCandidates: /* @__PURE__ */ new Map()
};
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/cache-stats.ts
function getTailwindV4IncrementalGenerateCacheStats() {
return {
max: 8,
entryCandidatesMax: INCREMENTAL_GENERATE_ENTRY_CANDIDATES_MAX,
entryCssBytesMax: INCREMENTAL_GENERATE_ENTRY_CSS_BYTES_MAX,
size: incrementalGenerateCache.size,
taskMax: 32,
taskSize: incrementalGenerateTaskCache.size,
entries: [...incrementalGenerateCache.entries()].map(([key, entry]) => ({
...summarizeIncrementalCacheKey(key),
candidates: entry.seenCandidates.size,
classSet: entry.classSet.size,
cssBytes: entry.css.length,
rawCssBytes: entry.rawCss.length
})),
keys: [...incrementalGenerateCache.keys()].map(summarizeIncrementalCacheKey),
taskKeys: [...incrementalGenerateTaskCache.keys()].map(summarizeIncrementalCacheKey)
};
}
//#endregion
//#region src/tailwindcss/v4-engine/css-macro-source.ts
function resolveCssMacroTailwindV4Source(source) {
const css = transformCssMacroTailwindV4Source(source.css);
return css === source.css ? source : {
...source,
css
};
}
//#endregion
//#region src/tailwindcss/v4-engine/miniprogram.ts
const defaultStyleHandler = createStyleHandler({
cssChildCombinatorReplaceValue: ["view", "text"],
cssRemoveHoverPseudoClass: true,
isMainChunk: true,
majorVersion: 4
});
const CSS_DECLARATION_URL_RE = /(:\s*)url\(([^\n\r"';[\]{}]*[[\]{}][^\n\r;]*)\)(?=\s*;)/g;
function normalizeTailwindV4GeneratedUrlValues(css) {
return css.replace(CSS_DECLARATION_URL_RE, (match, prefix, urlValue) => {
try {
return `${prefix}url("${urlValue.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}")`;
} catch {
return match;
}
});
}
async function transformTailwindV4CssToWeapp(css, options) {
const compatibleCss = normalizeTailwindV4GeneratedUrlValues(hasCssMacroStyleOptions(options) ? await transformCssMacroCss(css, options) : css);
const customPropertyValues = options?.customPropertyValues;
const protectedCss = protectDynamicColorMixAlpha(compatibleCss, { customPropertyValues });
const result = await defaultStyleHandler(protectedCss.css, {
cssChildCombinatorReplaceValue: ["view", "text"],
cssRemoveHoverPseudoClass: true,
isMainChunk: true,
majorVersion: 4,
...options
});
const pruneOptions = {
preserveContentInit: options?.uniAppX === true && options.uniAppXCssTarget === "uvue" ? false : void 0,
preservePreflight: true,
preserveConditionalComments: hasCssMacroStyleOptions(options)
};
return pruneMiniProgramGeneratedCss$1(protectedCss.restore(result.css), pruneOptions);
}
function transformTailwindV4WebRpxCss(css) {
if (!css.includes("rpx")) return css;
try {
const root = postcss.parse(css);
return normalizeTailwindcssWebRpxDeclarations(root, { majorVersion: 4 }) ? root.toString() : css;
} catch {
return css;
}
}
async function transformTailwindV4CssByTarget(css, target, options) {
if (target === "weapp") return transformTailwindV4CssToWeapp(css, options);
const resolvedWebCss = await (hasCssMacroStyleOptions(options) ? transformCssMacroCss(css, options) : css);
return shouldUseUniAppWebRpxCompatibility(options?.appType) ? transformTailwindV4WebRpxCss(resolvedWebCss) : resolvedWebCss;
}
//#endregion
//#region src/tailwindcss/v4-engine/tailwind-v4-default-colors.ts
const TAILWIND_V4_COLOR_STEPS = [
"50",
"100",
"200",
"300",
"400",
"500",
"600",
"700",
"800",
"900",
"950"
];
const TAILWIND_V4_COLOR_PALETTE = {
slate: [
"#f8fafc",
"#f1f5f9",
"#e2e8f0",
"#cad5e2",
"#90a1b9",
"#62748e",
"#45556c",
"#314158",
"#1d293d",
"#0f172b",
"#020618"
],
gray: [
"#f9fafb",
"#f3f4f6",
"#e5e7eb",
"#d1d5dc",
"#99a1af",
"#6a7282",
"#4a5565",
"#364153",
"#1e2939",
"#101828",
"#030712"
],
zinc: [
"#fafafa",
"#f4f4f5",
"#e4e4e7",
"#d4d4d8",
"#9f9fa9",
"#71717b",
"#52525c",
"#3f3f46",
"#27272a",
"#18181b",
"#09090b"
],
neutral: [
"#fafafa",
"#f5f5f5",
"#e5e5e5",
"#d4d4d4",
"#a1a1a1",
"#737373",
"#525252",
"#404040",
"#262626",
"#171717",
"#0a0a0a"
],
stone: [
"#fafaf9",
"#f5f5f4",
"#e7e5e4",
"#d6d3d1",
"#a6a09b",
"#79716b",
"#57534d",
"#44403b",
"#292524",
"#1c1917",
"#0c0a09"
],
mauve: [
"#fafafa",
"#f3f1f3",
"#e7e4e7",
"#d7d0d7",
"#a89ea9",
"#79697b",
"#594c5b",
"#463947",
"#2a212c",
"#1d161e",
"#0c090c"
],
olive: [
"#fbfbf9",
"#f4f4f0",
"#e8e8e3",
"#d8d8d0",
"#abab9c",
"#7c7c67",
"#5b5b4b",
"#474739",
"#2b2b22",
"#1d1d16",
"#0c0c09"
],
mist: [
"#f9fbfb",
"#f1f3f3",
"#e3e7e8",
"#d0d6d8",
"#9ca8ab",
"#67787c",
"#4b585b",
"#394447",
"#22292b",
"#161b1d",
"#090b0c"
],
taupe: [
"#fbfaf9",
"#f3f1f1",
"#e8e4e3",
"#d8d2d0",
"#aba09c",
"#7c6d67",
"#5b4f4b",
"#473c39",
"#2b2422",
"#1d1816",
"#0c0a09"
],
red: [
"#fef2f2",
"#ffe2e2",
"#ffc9c9",
"#ffa2a2",
"#ff6467",
"#fb2c36",
"#e7000b",
"#c10007",
"#9f0712",
"#82181a",
"#460809"
],
orange: [
"#fff7ed",
"#ffedd4",
"#ffd6a7",
"#ffb86a",
"#ff8904",
"#ff6900",
"#f54900",
"#ca3500",
"#9f2d00",
"#7e2a0c",
"#441306"
],
amber: [
"#fffbeb",
"#fef3c6",
"#fee685",
"#ffd230",
"#ffb900",
"#fe9a00",
"#e17100",
"#bb4d00",
"#973c00",
"#7b3306",
"#461901"
],
yellow: [
"#fefce8",
"#fef9c2",
"#fff085",
"#ffdf20",
"#fdc700",
"#f0b100",
"#d08700",
"#a65f00",
"#894b00",
"#733e0a",
"#432004"
],
lime: [
"#f7fee7",
"#ecfcca",
"#d8f999",
"#bbf451",
"#9ae600",
"#7ccf00",
"#5ea500",
"#497d00",
"#3c6300",
"#35530e",
"#192e03"
],
green: [
"#f0fdf4",
"#dcfce7",
"#b9f8cf",
"#7bf1a8",
"#05df72",
"#00c950",
"#00a63e",
"#008236",
"#016630",
"#0d542b",
"#032e15"
],
emerald: [
"#ecfdf5",
"#d0fae5",
"#a4f4cf",
"#5ee9b5",
"#00d492",
"#00bc7d",
"#009966",
"#007a55",
"#006045",
"#004f3b",
"#002c22"
],
teal: [
"#f0fdfa",
"#cbfbf1",
"#96f7e4",
"#46ecd5",
"#00d5be",
"#00bba7",
"#009689",
"#00786f",
"#005f5a",
"#0b4f4a",
"#022f2e"
],
cyan: [
"#ecfeff",
"#cefafe",
"#a2f4fd",
"#53eafd",
"#00d3f2",
"#00b8db",
"#0092b8",
"#007595",
"#005f78",
"#104e64",
"#053345"
],
sky: [
"#f0f9ff",
"#dff2fe",
"#b8e6fe",
"#74d4ff",
"#00bcff",
"#00a6f4",
"#0084d1",
"#0069a8",
"#00598a",
"#024a70",
"#052f4a"
],
blue: [
"#eff6ff",
"#dbeafe",
"#bedbff",
"#8ec5ff",
"#51a2ff",
"#2b7fff",
"#155dfc",
"#1447e6",
"#193cb8",
"#1c398e",
"#162456"
],
indigo: [
"#eef2ff",
"#e0e7ff",
"#c6d2ff",
"#a3b3ff",
"#7c86ff",
"#615fff",
"#4f39f6",
"#432dd7",
"#372aac",
"#312c85",
"#1e1a4d"
],
violet: [
"#f5f3ff",
"#ede9fe",
"#ddd6ff",
"#c4b4ff",
"#a684ff",
"#8e51ff",
"#7f22fe",
"#7008e7",
"#5d0ec0",
"#4d179a",
"#2f0d68"
],
purple: [
"#faf5ff",
"#f3e8ff",
"#e9d4ff",
"#dab2ff",
"#c27aff",
"#ad46ff",
"#9810fa",
"#8200db",
"#6e11b0",
"#59168b",
"#3c0366"
],
fuchsia: [
"#fdf4ff",
"#fae8ff",
"#f6cfff",
"#f4a8ff",
"#ed6aff",
"#e12afb",
"#c800de",
"#a800b7",
"#8a0194",
"#721378",
"#4b004f"
],
pink: [
"#fdf2f8",
"#fce7f3",
"#fccee8",
"#fda5d5",
"#fb64b6",
"#f6339a",
"#e60076",
"#c6005c",
"#a3004c",
"#861043",
"#510424"
],
rose: [
"#fff1f2",
"#ffe4e6",
"#ffccd3",
"#ffa1ad",
"#ff637e",
"#ff2056",
"#ec003f",
"#c70036",
"#a50036",
"#8b0836",
"#4d0218"
]
};
function createTailwindV4DefaultColorThemeCss() {
const declarations = [" --color-black: #000;", " --color-white: #fff;"];
for (const [color, values] of Object.entries(TAILWIND_V4_COLOR_PALETTE)) for (let index = 0; index < TAILWIND_V4_COLOR_STEPS.length; index++) declarations.push(` --color-${color}-${TAILWIND_V4_COLOR_STEPS[index]}: ${values[index]};`);
return [
"@theme {",
...declarations,
"}"
].join("\n");
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/css-compat.ts
const require$1 = createRequire(import.meta.url);
const tailwindThemeCssCache = /* @__PURE__ */ new Map();
function findLeadingImportInsertionIndex(css) {
const importPattern = /(?:^|\n)\s*@import\b[^;]*;/g;
let insertionIndex = 0;
let match = importPattern.exec(css);
while (match !== null) {
insertionIndex = match.index + match[0].length;
match = importPattern.exec(css);
}
return insertionIndex;
}
function readCachedCss(file) {
const cached = tailwindThemeCssCache.get(file);
if (cached !== void 0) return cached;
const css = readFileSync(file, "utf8");
tailwindThemeCssCache.set(file, css);
return css;
}
function resolveTailwindV4ThemeCssFromImport(css) {
const root = postcss.parse(css);
let resolved;
root.walkAtRules("import", (rule) => {
if (resolved) return;
const specifier = parseCssImportSpecifier$2(rule.params);
if (!specifier || !path.isAbsolute(specifier) || path.basename(specifier) !== "index.css") return;
const themeCss = path.join(path.dirname(specifier), "theme.css");
if (existsSync(themeCss)) resolved = themeCss;
});
return resolved;
}
function resolveTailwindV4ThemeCssFromBase(base) {
try {
return createRequire(path.join(base, "package.json")).resolve("tailwindcss/theme.css");
} catch {
try {
return require$1.resolve("tailwindcss/theme.css");
} catch {
return;
}
}
}
function resolveTailwindV4DefaultThemeCss(source) {
try {
const themeCss = resolveTailwindV4ThemeCssFromImport(source.css) ?? resolveTailwindV4ThemeCssFromBase(source.base);
return themeCss ? readCachedCss(themeCss) : createTailwindV4DefaultColorThemeCss();
} catch {
return createTailwindV4DefaultColorThemeCss();
}
}
function applyMiniProgramTailwindV4DefaultColorCss(css, source) {
const themeCss = resolveTailwindV4DefaultThemeCss(source);
const insertionIndex = findLeadingImportInsertionIndex(css);
if (insertionIndex === 0) return `${themeCss}\n${css}`;
return `${css.slice(0, insertionIndex)}\n${themeCss}\n${css.slice(insertionIndex)}`;
}
function parseCssImportSpecifier$2(params) {
const value = params.trim();
const quoted = /^(['"])(.*?)\1/.exec(value);
if (quoted) return quoted[2];
const url = /^url\(\s*(?:(['"])(.*?)\1|([^'")\s]+))\s*\)/.exec(value);
return url?.[2] ?? url?.[3];
}
function isTailwindCssPreflightImport(params) {
const specifier = parseCssImportSpecifier$2(params);
return specifier === "tailwindcss/preflight.css" || specifier === "tailwindcss/preflight";
}
function removeTailwindV4PreflightImports(css) {
if (!css.includes("preflight")) return css;
let root;
try {
root = postcss.parse(css);
} catch {
return css;
}
let changed = false;
root.walkAtRules("import", (rule) => {
if (isTailwindCssPreflightImport(rule.params)) {
rule.remove();
changed = true;
}
});
return changed ? root.toString() : css;
}
function hasThemeParent(rule) {
let parent = rule.parent;
while (parent) {
if (parent.type === "atrule" && parent.name === "theme") return true;
parent = parent.parent;
}
return false;
}
function isVendorPrefixedKeyframes(rule) {
return rule.name.startsWith("-") && rule.name.endsWith("keyframes");
}
function removeUnsupportedThemeVendorKeyframes(css) {
if (!css.includes("@theme") || !css.includes("@-")) return css;
let root;
try {
root = postcss.parse(css);
} catch {
return css;
}
let changed = false;
root.walkAtRules((rule) => {
if (isVendorPrefixedKeyframes(rule) && hasThemeParent(rule)) {
rule.remove();
changed = true;
}
});
return changed ? root.toString() : css;
}
function createCompatibleSource(source, target) {
const filteredSourceCss = target === "weapp" ? removeTailwindV4PreflightImports(source.css) : source.css;
const compatibleSourceCss = removeUnsupportedThemeVendorKeyframes(target === "weapp" ? applyMiniProgramTailwindV4DefaultColorCss(filteredSourceCss, source) : filteredSourceCss);
return compatibleSourceCss === source.css ? source : {
...source,
css: compatibleSourceCss
};
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/native-session.ts
var TailwindV4NativeSessionPool = class {
constructor(createSession = createTailwindGenerationSession) {
this.createSession = createSession;
_defineProperty(this, "sessions", /* @__PURE__ */ new Map());
_defineProperty(this, "disposed", false);
}
generate(target, sourceKey, source, request) {
const entry = this.getSession(target, sourceKey, source);
const generated = entry.pending.then(() => entry.session.generate(request));
entry.pending = generated.then(() => void 0, () => void 0);
return generated;
}
dispose() {
for (const entry of this.sessions.values()) this.disposeEntry(entry);
this.sessions.clear();
this.disposed = true;
}
get size() {
return this.sessions.size;
}
getSession(target, sourceKey, source) {
if (this.disposed) throw new Error("TailwindV4NativeSessionPool 已释放。");
const cached = this.sessions.get(target);
if (cached?.sourceKey === sourceKey) return cached;
if (cached) this.disposeEntry(cached);
const session = this.createSession(source);
const entry = {
pending: Promise.resolve(),
session,
sourceKey
};
this.sessions.set(target, entry);
return entry;
}
disposeEntry(entry) {
entry.pending.then(() => entry.session.dispose());
}
};
function createEngineSourceEntries(sources, sourceId) {
return sources.map((source, index) => ({
id: `${sourceId}:candidate-source:${index}`,
...source
}));
}
function serializeTailwindGenerationArtifact(artifact) {
return [...artifact.fragments].sort((left, right) => left.order - right.order).map((fragment) => fragment.root.toString()).join("\n");
}
//#endregion
//#region src/tailwindcss/source-scan.ts
const DEFAULT_SOURCE_SCAN_EXTENSIONS = [
"html",
"wxml",
"axml",
"jxml",
"ksml",
"ttml",
"qml",
"tyml",
"xhsml",
"swan",
"vue",
"mpx",
"js",
"jsx",
"ts",
"tsx"
];
const FULL_SOURCE_SCAN_EXTENSIONS = [
"js",
"jsx",
"mjs",
"cjs",
"ts",
"tsx",
"mts",
"cts",
"vue",
"uvue",
"nvue",
"svelte",
"mpx",
"html",
"wxml",
"axml",
"jxml",
"ksml",
"ttml",
"qml",
"tyml",
"xhsml",
"swan",
"css",
"wxss",
"acss",
"jxss",
"ttss",
"qss",
"tyss",
"scss",
"sass",
"less",
"styl",
"stylus"
];
function createSourceScanPattern(extensions = DEFAULT_SOURCE_SCAN_EXTENSIONS) {
return `**/*.{${extensions.join(",")}}`;
}
const FULL_SOURCE_SCAN_PATTERN = createSourceScanPattern(FULL_SOURCE_SCAN_EXTENSIONS);
const FULL_SOURCE_SCAN_EXTENSION_RE = new RegExp(`\\.(?:${FULL_SOURCE_SCAN_EXTENSIONS.map((extension) => extension.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})$`);
function toPosixPath(value) {
return value.split(path.sep).join("/");
}
function resolveSourceScanPath(value) {
const resolved = path.resolve(value);
try {
return realpathSync.native(resolved);
} catch {
return resolved;
}
}
function normalizeEntryPattern(entry) {
return path.isAbsolute(entry.pattern) ? toPosixPath(path.relative(resolveSourceScanPath(entry.base), entry.pattern)) : entry.pattern;
}
function isFileMatchedByTailwindSourceEntry(file, entry) {
const relative = toPosixPath(path.relative(resolveSourceScanPath(entry.base), file));
return relative && !relative.startsWith("../") && !path.isAbsolute(relative) && micromatch.isMatch(relative, normalizeEntryPattern(entry));
}
function isFileExcludedByTailwindSourceEntries(file, entries) {
if (!entries?.length) return false;
const resolvedFile = resolveSourceScanPath(file);
return entries.some((entry) => entry.negated && isFileMatchedByTailwindSourceEntry(resolvedFile, entry));
}
function isFileMatchedByTailwindSourceEntries(file, entries) {
if (!entries?.length) return true;
const positiveEntries = entries.filter((entry) => !entry.negated);
const negativeEntries = entries.filter((entry) => entry.negated);
const resolvedFile = resolveSourceScanPath(file);
if (positiveEntries.length === 0) return !negativeEntries.some((entry) => isFileMatchedByTailwindSourceEntry(resolvedFile, entry));
if (!positiveEntries.some((entry) => isFileMatchedByTailwindSourceEntry(resolvedFile, entry))) return false;
return !negativeEntries.some((entry) => isFileMatchedByTailwindSourceEntry(resolvedFile, entry));
}
function createTailwindSourceEntryMatcher(entries) {
if (!entries?.length) return;
return (file) => isFileMatchedByTailwindSourceEntries(file, entries);
}
function resolveTailwindV4CssSourceBase(source, fallbackBase) {
if (typeof source.base === "string" && source.base.length > 0) return source.base;
if (typeof source.file === "string" && source.file.length > 0) return path.dirname(source.file);
return fallbackBase;
}
function parseConfigParam(params) {
const value = params.trim();
return /^(['"])(.+)\1$/.exec(value)?.[2];
}
function isLegacyContentObject(value) {
return typeof value === "object" && value !== null && "files" in value;
}
function normalizeGlobPattern(pattern) {
return pattern.startsWith("./") ? pattern.slice(2) : pattern;
}
function hasGlobMagic(value) {
return /[*?[\]{}()!+@]/.test(value);
}
function splitStaticGlobPrefix(pattern) {
const segments = normalizeGlobPattern(pattern).split(/[\\/]+/);
const prefix = [];
const rest = [];
let reachedGlob = false;
for (const segment of segments) {
if (!reachedGlob && segment && !hasGlobMagic(segment)) {
prefix.push(segment);
continue;
}
reachedGlob = true;
rest.push(segment);
}
return {
prefix,
rest
};
}
function normalizeLegacyContentEntries(content, base, options = {}) {
if (typeof content === "string") {
const negated = content.startsWith("!");
return [{
base,
negated,
pattern: normalizeGlobPattern(negated ? content.slice(1) : content)
}];
}
if (Array.isArray(content)) return content.flatMap((item) => normalizeLegacyContentEntries(item, base, options));
if (isLegacyContentObject(content)) return normalizeLegacyContentEntries(content.files, content.relative && options.relativeBase ? options.relativeBase : base, options);
return [];
}
async function pathExistsAsDirectory(file) {
try {
return (await stat(file)).isDirectory();
} catch {
return false;
}
}
async function resolveTailwindSourceEntry(sourcePath, base, negated, defaultPattern = createSourceScanPattern()) {
const absoluteSource = path.isAbsolute(sourcePath) ? path.resolve(sourcePath) : path.resolve(base, sourcePath);
if (await pathExistsAsDirectory(absoluteSource)) return {
base: absoluteSource,
negated,
pattern: normalizeGlobPattern(defaultPattern)
};
if (path.isAbsolute(sourcePath) && hasGlobMagic(sourcePath)) {
const { prefix, rest } = splitStaticGlobPrefix(sourcePath);
const root = path.parse(sourcePath).root;
const normalizedPrefix = prefix[0] === "" ? prefix.slice(1) : prefix;
if (rest.length > 0) return {
base: path.resolve(root, ...normalizedPrefix),
negated,
pattern: normalizeGlobPattern(rest.join("/"))
};
}
if (path.isAbsolute(sourcePath)) return {
base: path.dirname(absoluteSource),
negated,
pattern: normalizeGlobPattern(path.basename(absoluteSource))
};
const { prefix, rest } = splitStaticGlobPrefix(sourcePath);
if (prefix.length > 0 && rest.length > 0) return {
base: path.resolve(base, ...prefix),
negated,
pattern: normalizeGlobPattern(rest.join("/"))
};
return {
base,
negated,
pattern: normalizeGlobPattern(sourcePath)
};
}
function parseSourceFileParam(params) {
const value = params.trim();
if (!value || value === "none" || value.startsWith("inline(")) return;
const negated = value.startsWith("not ");
const sourceValue = negated ? value.slice(4).trim() : value;
if (sourceValue.startsWith("inline(")) return;
const match = /^(['"])(.+)\1$/.exec(sourceValue);
return match?.[2] ? {
negated,
sourcePath: match[2]
} : void 0;
}
async function resolveCssSourceEntries(root, base, defaultPattern = createSourceScanPattern()) {
const entries = [];
const tasks = [];
root.walkAtRules("source", (rule) => {
const parsed = parseSourceFileParam(rule.params);
if (!parsed) return;
tasks.push(resolveTailwindSourceEntry(parsed.sourcePath, base, parsed.negated, defaultPattern));
});
entries.push(...await Promise.all(tasks));
return entries;
}
async function expandTailwindSourceEntries(entries, options = {}) {
if (entries.length === 0) return [];
const files = /* @__PURE__ */ new Set();
const entriesByBase = /* @__PURE__ */ new Map();
for (const entry of entries) {
const base = path.resolve(entry.base);
const group = entriesByBase.get(base) ?? [];
group.push({
...entry,
base
});
entriesByBase.set(base, group);
}
await Promise.all([...entriesByBase.entries()].map(async ([base, group]) => {
const ignoredSources = options.ignore?.map((pattern) => ({
base,
pattern: normalizeGlobPattern(pattern),
negated: true
}));
const matched = await resolveProjectSourceFiles({
cwd: base,
sources: group,
...ignoredSources === void 0 ? {} : { ignoredSources }
});
for (const file of matched) files.add(path.resolve(file));
}));
return [...files].filter((file) => !isFileExcludedByTailwindSourceEntries(file, entries));
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/scan-sources.ts
const TAILWIND_V4_DEFAULT_IGNORED_SOURCE_PATTERNS = [
"**/.git/**",
"**/.hg/**",
"**/.jj/**",
"**/.next/**",
"**/.parcel-cache/**",
"**/.pnpm-store/**",
"**/.svelte-kit/**",
"**/.svn/**",
"**/.turbo/**",
"**/.venv/**",
"**/.vercel/**",
"**/.yarn/**",
"**/__pycache__/**",
"**/node_modules/**",
"**/venv/**",
"**/*.less",
"**/*.lock",
"**/*.sass",
"**/*.scss",
"**/*.styl",
"**/*.log",
"**/tailwind.config.js",
"**/tailwind.config.cjs",
"**/tailwind.config.mjs",
"**/tailwind.config.ts",
"**/tailwind.config.cts",
"**/tailwind.config.mts",
"**/tailwind.config.*.js",
"**/tailwind.config.*.cjs",
"**/tailwind.config.*.mjs",
"**/tailwind.config.*.ts",
"**/tailwind.config.*.cts",
"**/tailwind.config.*.mts",
"**/package-lock.json",
"**/pnpm-lock.yaml",
"**/bun.lockb",
"**/.gitignore",
"**/.env",
"**/.env.*"
];
function parseImportSourceParam(params) {
const match = /\bsource\(\s*(none|(['"])(.*?)\2)\s*\)/.exec(params);
if (!match) return;
return {
none: match[1] === "none",
sourcePath: match[3]
};
}
function parseCssImportSpecifier$1(params) {
const value = params.trim();
const quoted = /^(['"])(.*?)\1/.exec(value);
if (quoted) return quoted[2];
const url = /^url\(\s*(?:(['"])(.*?)\1|([^'")\s]+))\s*\)/.exec(value);
return url?.[2] ?? url?.[3];
}
function isTailwindCssImport(params) {
const specifier = parseCssImportSpecifier$1(params);
return specifier === "tailwindcss" || specifier?.startsWith("tailwindcss/") || specifier?.replaceAll("\\", "/").endsWith("/tailwindcss/index.css");
}
function resolveSourceBase(base, sourcePath) {
return path.isAbsolute(sourcePath) ? sourcePath : path.resolve(base, sourcePath);
}
function createDefaultIgnoredScanSources(base) {
return TAILWIND_V4_DEFAULT_IGNORED_SOURCE_PATTERNS.map((pattern) => ({
base,
pattern,
negated: true
}));
}
function normalizeCssDefinedScanSources(base, entries) {
return entries.length > 0 && entries.every((entry) => entry.negated) ? [{
base,
pattern: "**/*",
negated: false
}, ...entries] : entries;
}
function resolveDefaultSourceBase(source) {
return source.projectRoot ?? source.cwd ?? source.base;
}
async function resolveCssDefinedScanSources(source) {
let importSourceBase;
let hasSourceNone = false;
let hasTailwindImport = false;
const from = source.dependencies[0];
let root;
try {
root = postcss.parse(source.css, { from });
} catch {
return;
}
root.walkAtRules((rule) => {
if (rule.name === "import") {
if (!isTailwindCssImport(rule.params)) return;
hasTailwindImport = true;
const sourceParam = parseImportSourceParam(rule.params);
if (sourceParam?.none) hasSourceNone = true;
if (sourceParam?.sourcePath) importSourceBase = resolveSourceBase(source.base, sourceParam.sourcePath);
}
});
const sourcePatterns = await resolveCssSourceEntries(root, source.base, "**/*");
if (!importSourceBase) {
if (sourcePatterns.length > 0) return [...normalizeCssDefinedScanSources(source.base, sourcePatterns), ...createDefaultIgnoredScanSources(source.base)];
if (hasSourceNone) return false;
if (hasTailwindImport) {
const defaultBase = resolveDefaultSourceBase(source);
return [await resolveTailwindSourceEntry(".", defaultBase, false, "**/*"), ...createDefaultIgnoredScanSources(defaultBase)];
}
return;
}
return [
await resolveTailwindSourceEntry(".", importSourceBase, false, "**/*"),
...sourcePatterns,
...createDefaultIgnoredScanSources(importSourceBase)
];
}
async function resolveScanSources(source, scanSources) {
if (scanSources !== true) return scanSources;
return await resolveCssDefinedScanSources(source) ?? false;
}
function resolveCompiledSourceRoot(source) {
let root = null;
try {
postcss.parse(source.css).walkAtRules("import", (rule) => {
if (!isTailwindCssImport(rule.params)) return;
const sourceParam = parseImportSourceParam(rule.params);
if (sourceParam?.none) {
root = "none";
return false;
}
if (sourceParam?.sourcePath) {
root = {
base: source.base,
pattern: sourceParam.sourcePath
};
return false;
}
});
} catch {}
return root;
}
//#endregion
//#region src/tailwindcss/v4-engine/generator/engine.ts
function isCssSyntaxError(error) {
return error instanceof Error && error.name === "CssSyntaxError";
}
function createTailwindV4Engine$1(source) {
const generationSessions = new TailwindV4NativeSessionPool();
const incrementalCacheKeys = /* @__PURE__ */ new Set();
const validationEngine = createTailwindV4Engine(source);
async function generateOnce(generateSource, options = {}) {
const { scanSources = true, styleOptions, target = "weapp", ...patchOptions } = options;
const resolvedStyleOptions = resolveStyleOptions(generateSource, styleOptions);
const compatibleSource = createCompatibleSource(resolveCssMacroTailwindV4Source(generateSource), target);
const resolvedScanSources = await resolveScanSources(generateSource, scanSources);
const filesystemCandidates = Array.isArray(resolvedScanSources) ? new Set(await extractRawCandidates(resolvedScanSources, { ...patchOptions.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: patchOptions.bareArbitraryValues } })) : void 0;
const normalizedCandidates = normalizeTargetRpxLengthCandidates(resolveTargetCandidates(/* @__PURE__ */ new Set([...collectCandidates(patchOptions.candidates), ...filesystemCandidates ?? []]), target), target, resolvedStyleOptions);
const sourceId = compatibleSource.dependencies[0] ?? compatibleSource.base;
const generationRequest = {
...patchOptions.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: patchOptions.bareArbitraryValues },
...patchOptions.sources === void 0 ? {} : { sourceEntries: createEngineSourceEntries(patchOptions.sources, sourceId) },
candidates: normalizedCandidates.candidates
};
let generatedCss;
let classSet;
let rawCandidates;
let dependencies;
try {
const artifact = await generationSessions.generate(target, createTailwindV4SourceCacheKey(compatibleSource), compatibleSource, generationRequest);
generatedCss = serializeTailwindGenerationArtifact(artifact);
classSet = artifact.classSet;
rawCandidates = artifact.rawCandidates;
dependencies = artifact.dependencies;
} catch (error) {
if (!isCssSyntaxError(error)) throw error;
const legacyResult = await createTailwindV4Engine(compatibleSource).generate({
...patchOptions.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: patchOptions.bareArbitraryValues },
...patchOptions.sources === void 0 ? {} : { sources: patchOptions.sources },
candidates: normalizedCandidates.candidates,
scanSources: false
});
generatedCss = legacyResult.css;
classSet = legacyResult.classSet;
rawCandidates = legacyResult.rawCandidates;
dependencies = legacyResult.dependencies;
}
const sources = Array.isArray(resolvedScanSources) ? resolvedScanSources : [];
const rawCss = restoreRpxLengthCssSelectors(generatedCss, normalizedCandidates.restoreCandidates);
const css = await transformTailwindV4CssByTarget(rawCss, target, resolvedStyleOptions);
return {
classSet: restoreRpxLengthCandidates(classSet, normalizedCandidates.restoreCandidates),
rawCandidates: restoreRpxLengthCandidates(rawCandidates, normalizedCandidates.restoreCandidates),
dependencies,
root: resolveCompiledSourceRoot(compatibleSource),
sources,
css,
rawCss,
target
};
}
async function generateWithIncrementalCache(options = {}) {
const target = options.target ?? "weapp";
const cssMacroSource = resolveCssMacroTailwindV4Source(source);
const compatibleSource = createCompatibleSource(cssMacroSource, target);
const requestedCandidates = resolveTargetCandidates(options.candidates, target);
const styleOptions = resolveStyleOptions(source, options.styleOptions);
if ((options.sources?.length ?? 0) > 0 || options.bareArbitraryValues !== void 0 || Array.isArray(options.scanSources)) return generateOnce(cssMacroSource, options);
const cacheKey = createIncrementalGenerateCacheKey(compatibleSource, target, styleOptions);
incrementalCacheKeys.add(cacheKey);
if (options.scanSources === true) return runIncrementalGenerateTask(cacheKey, requestedCandidates, options.scanSources, async () => {
const generated = await generateOnce(cssMacroSource, options);
if (!seedIncrementalGenerateCache({
compatibleSource,
generated,
requestedCandidates,
styleOptions,
target
})) incrementalGenerateCache.delete(cacheKey);
return generated;
});
const cached = incrementalGenerateCache.get(cacheKey);
if (cached) {
if (hasRemovedCandidates(cached.seenCandidates, requestedCandidates)) return runIncrementalGenerateTask(cacheKey, requestedCandidates, options.scanSources, async () => {
const generated = await generateOnce(cssMacroSource, options);
if (!seedIncrementalGenerateCache({
compatibleSource,
generated,
requestedCandidates,
styleOptions,
target
})) incrementalGenerateCache.delete(cacheKey);
return generated;
});
const missingCandidates = [...requestedCandidates].filter((candidate) => !cached.seenCandidates.has(candidate));
if (missingCandidates.length === 0) return {
css: cached.css,
rawCss: cached.rawCss,
incrementalCss: "",
incrementalRawCss: "",
classSet: new Set(cached.classSet),
rawCandidates: new Set(cached.seenCandidates),
dependencies: cached.dependencies,
sources: cached.sources,
root: cached.root,
target: cached.target
};
if (shouldRebuildIncrementalEntry(cached, requestedCandidates, missingCandidates)) return runIncrementalGenerateTask(cacheKey, requestedCandidates, options.scanSources, async () => {
const generated = await generateOnce(cssMacroSource, options);
if (!seedIncrementalGenerateCache({
compatibleSource,
generated,
requestedCandidates,
styleOptions,
target
})) incrementalGenerateCache.delete(cacheKey);
return generated;
});
return runIncrementalGenerateTask(cacheKey, requestedCandidates, options.scanSources, async () => {
const designSystem = await cached.designSystemPromise;
const normalizedMissing = normalizeTargetRpxLengthCandidates(missingCandidates, target, styleOptions);
const normalizedMissingCandidates = [...normalizedMissing.candidates];
const cssByCandidate = designSystem.candidatesToCss(normalizedMissingCandidates);
const rawCssParts = [];
const classSet = /* @__PURE__ */ new Set();
for (let index = 0; index < normalizedMissingCandidates.length; index += 1) {
const candidate = normalizedMissingCandidates[index];
const css = cssByCandidate[index];
if (candidate && typeof css === "string" && css.trim().length > 0) {
rawCssParts.push(restoreRpxLengthCssSelectors(css, normalizedMissing.restoreCandidates));
classSet.add(normalizedMissing.restoreCandidates.get(candidate) ?? candidate);
}
}
const rawCss = rawCssParts.join("\n");
const incrementalCss = rawCss.length > 0 ? await transformTailwindV4CssByTarget(rawCss, target, {
...createIncrementalStyleOptions(styleOptions),
customPropertyValues: cached.customPropertyValues
}) : "";
for (const candidate of missingCandidates) cached.seenCandidates.add(candidate);
for (const className of classSet) cached.classSet.add(className);
cached.css = [cached.css, incrementalCss].filter(Boolean).join("\n");
cached.rawCss = [cached.rawCss, rawCss].filter(Boolean).join("\n");
mergeCustomPropertyValues(cached.customPropertyValues, incrementalCss);
return {
css: cached.css,
rawCss: cached.rawCss,
incrementalCss,
incrementalRawCss: rawCss,
classSet: new Set(cached.classSet),
rawCandidates: new Set(cached.seenCandidates),
dependencies: cached.dependencies,
sources: cached.sources,
root: cached.root,
target: cached.target
};
});
}
return runIncrementalGenerateTask(cacheKey, requestedCandidates, options.scanSources, async () => {
const generated = await generateOnce(cssMacroSource, options);
seedIncrementalGenerateCache({
compatibleSource,
generated,
requestedCandidates,
styleOptions,
target
});
return generated;
});
}
async function generate(options = {}) {
return options.incrementalCache ? generateWithIncrementalCache(options) : generateOnce(source, options);
}
return {
source,
loadDesignSystem: validationEngine.loadDesignSystem,
validateCandidates: validationEngine.validateCandidates,
generate,
dispose() {
generationSessions.dispose();
for (const cacheKey of incrementalCacheKeys) incrementalGenerateCache.delete(cacheKey);
incrementalCacheKeys.clear();
}
};
}
//#endregion
//#region src/bundlers/shared/generator-css/config-directive.ts
function quoteCssString(value) {
return value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"");
}
function toCssPath(value) {
return value.replaceAll("\\", "/");
}
function prependConfigDirective(css, config) {
if (!config || /@config\s+/.test(css)) return css;
return `@config "${quoteCssString(toCssPath(config))}";\n${css}`;
}
function normalizeConfigDirective(css, config) {
if (!config || !/@config\s+/.test(css)) return css;
return css.replace(/@config\s+(["'])(.+?)\1\s*;?/, `@config "${quoteCssString(toCssPath(config))}";`);
}
//#endregion
//#region src/bundlers/shared/generator-css/markers.ts
const TAILWIND_V4_BANNER_RE = /\/\*!\s*tailwindcss v4\./;
const TAILWIND_ESCAPED_UTILITY_MARKER_RE = /\.[^,{]{0,512}(?:\\:|\\\[|\\#)/;
const TAILWIND_ROOT_THEME_MARKER_RE = /(?::root\s*,\s*:host|:host\s*,\s*page\s*,\s*\.tw-root\s*,\s*wx-root-portal-content)[^{]{0,256}\{[^}]{0,4096}(?:--spacing\b|--(?:color|text|font|default|radius)-)/;
const GENERATOR_PLACEHOLDER_MARKER_RE = /\/\*!\s*weapp-tailwindcss generator-placeholder\s*\*\//i;
const GENERATOR_PLACEHOLDER_MARKER_GLOBAL_RE = /\/\*!\s*weapp-tailwindcss generator-placeholder\s*\*\/\s*/gi;
const TAILWIND_BANNER_PREFIX_RE = /^\/\*!\s*tailwindcss v[^*]*\*\/\s*/i;
const TAILWIND_BANNER_RE = /\/\*!\s*tailwindcss v[^*]*\*\//i;
const TAILWIND_BANNER_GLOBAL_RE = /\/\*!\s*tailwindcss v[^*]*\*\/\s*/gi;
const VITE_MARKER_RE = /\/\*\$vite\$:[^*]*\*\//g;
function createCssAppend(base, extra) {
if (!base) return extra;
if (!extra) return base;
return `${base}\n${extra}`;
}
function splitTailwindV4GeneratedCssBySourceOrder(rawSource, rawTailwindCss) {
const trimmedRaw = rawSource.trim();
const trimmedTailwind = rawTailwindCss.trim();
if (trimmedRaw === trimmedTailwind) return {
before: "",
after: ""
};
if (trimmedTailwind.startsWith(trimmedRaw)) return {
before: "",
after: ""
};
const start = rawSource.indexOf(rawTailwindCss);
if (start === -1) return;
return {
before: rawSource.slice(0, start),
after: rawSource.slice(start + rawTailwindCss.length)
};
}
function splitGeneratorPlaceholderCssBySourceOrder(rawSource, rawTailwindCss) {
const match = GENERATOR_PLACEHOLDER_MARKER_RE.exec(rawSource);
if (!match || match.index === void 0) return;
let afterStart = match.index + match[0].length;
while (/\s/.test(rawSource[afterStart] ?? "")) afterStart++;
if (rawTailwindCss && rawSource.slice(afterStart).startsWith(rawTailwindCss)) {
afterStart += rawTailwindCss.length;
while (/\s/.test(rawSource[afterStart] ?? "")) afterStart++;
}
return {
before: rawSource.slice(0, match.index),
after: rawSource.slice(afterStart)
};
}
function splitTailwindGeneratedCssByBanner(rawSource, start) {
const match = start === void 0 ? TAILWIND_BANNER_RE.exec(rawSource) : { index: start };
if (!match || match.index === void 0) return;
return {
before: rawSource.slice(0, match.index),
after: [...rawSource.slice(match.index).matchAll(VITE_MARKER_RE)].map((item) => item[0]).join("\n")
};
}
function stripTailwindBanner(css) {
return css.replace(TAILWIND_BANNER_PREFIX_RE, "");
}
function stripTailwindBanners(css) {
return css.replace(TAILWIND_BANNER_GLOBAL_RE, "");
}
function stripGeneratorPlaceholderMarkers(css) {
return css.replace(GENERATOR_PLACEHOLDER_MARKER_GLOBAL_RE, "");
}
function hasTailwindGeneratedCss(rawSource) {
return TAILWIND_V4_BANNER_RE.test(rawSource);
}
function hasTailwindGeneratedCssMarkers(rawSource) {
if (rawSource.includes("--tw-") || rawSource.includes("tailwindcss v") || rawSource.includes(":not(#\\#)") || GENERATOR_PLACEHOLDER_MARKER_RE.test(rawSource)) return true;
if (!rawSource.includes("\\:") && !rawSource.includes("\\[") && !rawSource.includes("\\#") && !rawSource.includes("--color-") && !rawSource.includes("--spacing") && !rawSource.