UNPKG

weapp-tailwindcss

Version:

把 tailwindcss 原子化样式思想,带给小程序开发者们! bring tailwindcss to miniprogram developers!

1,326 lines 239 kB
const require_rolldown_runtime = require("./rolldown-runtime-CVvi-lCc.cjs"); const require_generator = require("./generator-BE34PYSC.cjs"); require("./auto-DtU6f3X6.cjs"); const require_object = require("./object-C_Vr6_S5.cjs"); const require_options = require("./options-hVsoTfwL.cjs"); const require_wxml = require("./wxml-DSMNuUaP.cjs"); const require_style_options = require("./style-options-B_ppaVIg.cjs"); let node_fs = require("node:fs"); let node_path = require("node:path"); node_path = require_rolldown_runtime.__toESM(node_path, 1); let node_process = require("node:process"); node_process = require_rolldown_runtime.__toESM(node_process, 1); let _tailwindcss_mangle_engine = require("@tailwindcss-mangle/engine"); let _weapp_tailwindcss_postcss = require("@weapp-tailwindcss/postcss"); let lru_cache = require("lru-cache"); let node_fs_promises = require("node:fs/promises"); let _weapp_core_escape = require("@weapp-core/escape"); let _weapp_tailwindcss_shared_node = require("@weapp-tailwindcss/shared/node"); //#region src/bundlers/shared/source-candidates/scan-root.ts const TAILWIND_V4_IGNORED_CONTENT_DIRS = [ ".git", ".hg", ".jj", ".next", ".parcel-cache", ".pnpm-store", ".svelte-kit", ".svn", ".turbo", ".venv", ".vercel", ".yarn", "__pycache__", "node_modules", "venv" ]; const TAILWIND_V4_IGNORED_EXTENSIONS = [ "css", "less", "postcss", "pcss", "lock", "sass", "scss", "styl", "stylus", "log", "wxss", "acss", "jxss", "ttss", "qss", "tyss" ]; const TAILWIND_V4_IGNORED_FILES = [ "package-lock.json", "pnpm-lock.yaml", "bun.lockb", ".gitignore", ".env", ".env.*" ]; function resolveOutDirIgnorePattern(root, outDir) { if (!outDir) return; const relative = node_path.default.relative(root, node_path.default.resolve(root, outDir)); if (!relative || relative.startsWith("..") || node_path.default.isAbsolute(relative)) return; return `${require_generator.toPosixPath(relative)}/**`; } function normalizeScanEntries(root, entries, outDirIgnore) { const hasPositiveEntry = entries?.some((entry) => !entry.negated) === true; const scanEntries = entries?.length ? hasPositiveEntry ? entries : [{ base: root, pattern: "**/*", negated: false }, ...entries] : void 0; if (!outDirIgnore) return scanEntries; return [...scanEntries ?? [{ base: root, pattern: "**/*", negated: false }], { base: root, pattern: outDirIgnore, negated: true }]; } function shouldApplyDefaultIgnoredSources(entries) { return entries?.length === void 0 ? false : entries.length > 0 && entries.every((entry) => entry.negated); } function createDefaultIgnoredSources(root, outDirIgnore, entries, explicit) { return [...!explicit || shouldApplyDefaultIgnoredSources(entries) ? [ ...TAILWIND_V4_IGNORED_CONTENT_DIRS.map((pattern) => ({ base: root, pattern: `**/${pattern}/**`, negated: true })), ...TAILWIND_V4_IGNORED_EXTENSIONS.map((extension) => ({ base: root, pattern: `**/*.${extension}`, negated: true })), ...TAILWIND_V4_IGNORED_FILES.map((pattern) => ({ base: root, pattern: `**/${pattern}`, negated: true })) ] : [], ...outDirIgnore ? [{ base: root, pattern: outDirIgnore, negated: true }] : []]; } function resolveSourceCandidateScanFiles(options) { const resolvedRoot = node_path.default.resolve(options.root); if (options.explicit && options.entries?.length && options.entries.every((entry) => entry.negated)) return Promise.resolve([]); const outDirIgnore = resolveOutDirIgnorePattern(resolvedRoot, options.outDir); const scanEntries = normalizeScanEntries(resolvedRoot, options.entries, outDirIgnore); const ignoredSources = createDefaultIgnoredSources(resolvedRoot, outDirIgnore, options.entries, options.explicit); return (0, _tailwindcss_mangle_engine.resolveProjectSourceFiles)({ cwd: resolvedRoot, ...scanEntries === void 0 ? {} : { sources: scanEntries }, ...ignoredSources.length > 0 ? { ignoredSources } : {}, filter: options.filter }); } //#endregion //#region src/tailwindcss/candidates.ts const SCRIPT_SOURCE_CANDIDATE_EXTENSIONS = /* @__PURE__ */ new Set([ "js", "jsx", "mjs", "cjs", "ts", "tsx", "mts", "cts" ]); const TEMPLATE_SOURCE_CANDIDATE_EXTENSIONS = /* @__PURE__ */ new Set([ "html", "wxml", "axml", "jxml", "ksml", "ttml", "qml", "tyml", "xhsml", "swan", "vue", "uvue", "nvue", "mpx" ]); async function extractCandidatesFromSource(source, extension, options = {}) { const candidates = options.extractor ? new Set(await options.extractor(source, extension)) : new Set(await (0, _tailwindcss_mangle_engine.extractSourceCandidates)(source, extension, { ...options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: options.bareArbitraryValues } })); const scriptCandidates = await extractScriptStringCandidates(source, extension, options); for (const candidate of scriptCandidates) candidates.add(candidate); const templateAttributeCandidates = await extractTemplateAttributeCandidates(source, extension, options); for (const candidate of templateAttributeCandidates) candidates.add(candidate); return candidates; } function isDefaultTemplateAttribute(name) { if (name === "class" || name === "hover-class" || name === "virtualhostclass") return true; const lowerName = name.toLowerCase(); return lowerName === "class" || lowerName === "hover-class" || lowerName === "virtualhostclass"; } async function extractCandidateTokensFromTemplateAttributeValue(value, options) { return options.extractor ? await options.extractor(value, "html") : await (0, _tailwindcss_mangle_engine.extractSourceCandidates)(value, "html", { ...options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: options.bareArbitraryValues } }); } async function extractTemplateAttributeCandidates(source, extension, options) { if (!TEMPLATE_SOURCE_CANDIDATE_EXTENSIONS.has(extension)) return []; if (!options.customAttributesEntities?.length) return []; const candidates = /* @__PURE__ */ new Set(); const matchCustomAttribute = require_wxml.createAttributeMatcher(options.customAttributesEntities); const defaultTemplateHandlerEnabled = !options.disabledDefaultTemplateHandler; let tag = ""; const tasks = []; const parser = new require_wxml.Parser({ onopentagname(name) { tag = name; }, onattribute(name, value) { if (!value) return; const shouldHandleDefault = defaultTemplateHandlerEnabled && isDefaultTemplateAttribute(name); const shouldHandleCustom = matchCustomAttribute?.(tag, name) ?? false; if (!shouldHandleDefault && !shouldHandleCustom) return; tasks.push((async () => { for (const candidate of await extractCandidateTokensFromTemplateAttributeValue(value, options)) candidates.add(candidate); })()); }, onclosetag() { tag = ""; } }, { xmlMode: true }); parser.write(source); parser.end(); await Promise.all(tasks); return candidates; } async function extractScriptStringCandidates(source, extension, options) { if (!SCRIPT_SOURCE_CANDIDATE_EXTENSIONS.has(extension)) return []; const values = /* @__PURE__ */ new Set(); try { require_wxml.traverse(require_wxml.babelParse(source, { cache: true, cacheKey: `source-candidates:${extension}`, plugins: ["jsx", "typescript"], sourceType: "unambiguous" }), { noScope: true, StringLiteral(path) { values.add(path.node.value); }, TemplateElement(path) { values.add(path.node.value.raw); } }); } catch { return []; } const candidates = /* @__PURE__ */ new Set(); for (const value of values) { const extractedCandidates = options.extractor ? await options.extractor(value, "html") : await (0, _tailwindcss_mangle_engine.extractSourceCandidates)(value, "html", { ...options.bareArbitraryValues === void 0 ? {} : { bareArbitraryValues: options.bareArbitraryValues } }); for (const candidate of extractedCandidates) candidates.add(candidate); } return candidates; } //#endregion //#region src/bundlers/shared/source-candidates/types-and-cache.ts const CLEAN_URL_RE = /[?#].*$/; const sourceCandidateContentCache = new lru_cache.LRUCache({ max: 128 }); function cleanUrl(id) { return require_generator.resolveSourceScanPath(id.replace(CLEAN_URL_RE, "")); } function resolveSourceCandidateExtension(id) { const normalized = cleanUrl(id); return /\.([^.\\/]+)$/.exec(normalized)?.[1] ?? "html"; } function createSourceCandidateContentCacheKey(extension, source, bareArbitraryValues, customAttributesEntities, disabledDefaultTemplateHandler, extractor) { return [ extension, JSON.stringify(bareArbitraryValues ?? false), createCustomAttributesCacheSignature(customAttributesEntities), disabledDefaultTemplateHandler === true ? "default-template:off" : "default-template:on", extractor ? "custom" : "default", (0, _weapp_tailwindcss_shared_node.md5)(source) ].join("\0"); } function createCustomAttributesCacheSignature(customAttributesEntities) { return JSON.stringify((customAttributesEntities ?? []).map(([selector, props]) => [stringifyCustomAttributeToken(selector), Array.isArray(props) ? props.map(stringifyCustomAttributeToken) : stringifyCustomAttributeToken(props)])); } function stringifyCustomAttributeToken(token) { return typeof token === "string" ? `s:${token}` : `r:${token.source}/${token.flags}`; } async function extractCandidates(source, extension, options) { return extractCandidatesFromSource(source, extension, options); } function isSourceCandidateRequest(id) { return require_generator.FULL_SOURCE_SCAN_EXTENSION_RE.test(cleanUrl(id)); } function removeCandidateSet(candidateCount, candidates) { for (const candidate of candidates) { const count = candidateCount.get(candidate); if (count == null) continue; if (count <= 1) { candidateCount.delete(candidate); continue; } candidateCount.set(candidate, count - 1); } } function addCandidateSet(candidateCount, candidates) { for (const candidate of candidates) candidateCount.set(candidate, (candidateCount.get(candidate) ?? 0) + 1); } function diffCandidateSets(previous, next) { const addedCandidates = /* @__PURE__ */ new Set(); const removedCandidates = /* @__PURE__ */ new Set(); for (const candidate of next) if (!previous.has(candidate)) addedCandidates.add(candidate); for (const candidate of previous) if (!next.has(candidate)) removedCandidates.add(candidate); return { addedCandidates, removedCandidates }; } //#endregion //#region src/bundlers/shared/source-candidates/store.ts function createSourceCandidateStore(options = {}) { const candidatesById = /* @__PURE__ */ new Map(); const scanCandidatesById = /* @__PURE__ */ new Map(); const transformCandidatesById = /* @__PURE__ */ new Map(); const cssCandidatesById = /* @__PURE__ */ new Map(); const scanSourceById = /* @__PURE__ */ new Map(); const transformSourceById = /* @__PURE__ */ new Map(); const cssSourceById = /* @__PURE__ */ new Map(); const candidateCount = /* @__PURE__ */ new Map(); let inlineIncludedCandidates = /* @__PURE__ */ new Set(); let inlineExcludedCandidates = /* @__PURE__ */ new Set(); async function resolveCandidates(source, extension) { const contentCacheKey = createSourceCandidateContentCacheKey(extension, source, options.bareArbitraryValues, options.customAttributesEntities, options.disabledDefaultTemplateHandler, options.extractor); const cachedCandidates = sourceCandidateContentCache.get(contentCacheKey); if (cachedCandidates) return new Set(cachedCandidates); const nextCandidates = await extractCandidates(source, extension, options); sourceCandidateContentCache.set(contentCacheKey, [...nextCandidates]); return nextCandidates; } function isCandidateVisible(candidate) { if (inlineExcludedCandidates.has(candidate)) return false; return inlineIncludedCandidates.has(candidate) || candidateCount.has(candidate); } function collectVisibleCandidates(candidates) { const visible = /* @__PURE__ */ new Set(); for (const candidate of candidates) if (isCandidateVisible(candidate)) visible.add(candidate); return visible; } async function sync(id, source) { const normalizedId = cleanUrl(id); scanSourceById.set(normalizedId, source); replaceScanLayer(normalizedId, await resolveCandidates(source, resolveSourceCandidateExtension(normalizedId))); } async function syncCss(id, source) { const normalizedId = cleanUrl(id); cssSourceById.set(normalizedId, source); replaceCssLayer(normalizedId, await resolveCandidates(source, "css")); } async function merge(id, source) { const normalizedId = cleanUrl(id); transformSourceById.set(normalizedId, source); replaceTransformLayer(normalizedId, await resolveCandidates(source, resolveSourceCandidateExtension(normalizedId))); } async function syncFile(id) { const normalizedId = cleanUrl(id); try { await sync(normalizedId, await (0, node_fs_promises.readFile)(normalizedId, "utf8")); } catch (error) { if ((typeof error === "object" && error !== null && "code" in error ? error.code : void 0) === "ENOENT") { remove(normalizedId); return; } throw error; } } async function syncCurrentSource(id, source) { const normalizedId = cleanUrl(id); transformCandidatesById.delete(normalizedId); cssCandidatesById.delete(normalizedId); transformSourceById.delete(normalizedId); cssSourceById.delete(normalizedId); recompute(normalizedId); const previousFileCandidates = new Set(candidatesById.get(normalizedId) ?? []); const nextCandidates = await resolveCandidates(source, resolveSourceCandidateExtension(normalizedId)); const affectedCandidates = /* @__PURE__ */ new Set([...previousFileCandidates, ...nextCandidates]); const previousVisibleCandidates = collectVisibleCandidates(affectedCandidates); scanSourceById.set(normalizedId, source); replaceScanLayer(normalizedId, nextCandidates); return diffCandidateSets(previousVisibleCandidates, collectVisibleCandidates(affectedCandidates)); } async function syncCurrentFile(id) { const normalizedId = cleanUrl(id); try { return await syncCurrentSource(normalizedId, await (0, node_fs_promises.readFile)(normalizedId, "utf8")); } catch (error) { if ((typeof error === "object" && error !== null && "code" in error ? error.code : void 0) === "ENOENT") return remove(normalizedId); throw error; } } async function scanRoot({ entries, explicit, root, outDir }) { const files = await resolveSourceCandidateScanFiles({ entries, explicit, filter: isSourceCandidateRequest, outDir, root }); await Promise.all(files.map((file) => syncFile(require_generator.resolveSourceScanPath(file)))); } function replaceFinal(id, nextCandidates) { const normalizedId = cleanUrl(id); const previousCandidates = candidatesById.get(normalizedId); if (previousCandidates) { removeCandidateSet(candidateCount, previousCandidates); candidatesById.delete(normalizedId); } if (nextCandidates.size === 0) return; candidatesById.set(normalizedId, nextCandidates); addCandidateSet(candidateCount, nextCandidates); } function replaceScanLayer(id, nextCandidates) { const normalizedId = cleanUrl(id); if (nextCandidates.size === 0) scanCandidatesById.delete(normalizedId); else scanCandidatesById.set(normalizedId, nextCandidates); recompute(normalizedId); } function replaceTransformLayer(id, nextCandidates) { const normalizedId = cleanUrl(id); if (nextCandidates.size === 0) transformCandidatesById.delete(normalizedId); else transformCandidatesById.set(normalizedId, nextCandidates); recompute(normalizedId); } function replaceCssLayer(id, nextCandidates) { const normalizedId = cleanUrl(id); if (nextCandidates.size === 0) cssCandidatesById.delete(normalizedId); else cssCandidatesById.set(normalizedId, nextCandidates); recompute(normalizedId); } function recompute(id) { const normalizedId = cleanUrl(id); replaceFinal(normalizedId, /* @__PURE__ */ new Set([ ...scanCandidatesById.get(normalizedId) ?? [], ...transformCandidatesById.get(normalizedId) ?? [], ...cssCandidatesById.get(normalizedId) ?? [] ])); } function syncInline(inlineCandidates) { inlineIncludedCandidates = new Set(inlineCandidates?.included ?? []); inlineExcludedCandidates = new Set(inlineCandidates?.excluded ?? []); } function remove(id) { const normalizedId = cleanUrl(id); const affectedCandidates = new Set(candidatesById.get(normalizedId) ?? []); const previousVisibleCandidates = collectVisibleCandidates(affectedCandidates); scanCandidatesById.delete(normalizedId); transformCandidatesById.delete(normalizedId); cssCandidatesById.delete(normalizedId); scanSourceById.delete(normalizedId); transformSourceById.delete(normalizedId); cssSourceById.delete(normalizedId); const previousCandidates = candidatesById.get(normalizedId); if (!previousCandidates) return diffCandidateSets(previousVisibleCandidates, /* @__PURE__ */ new Set()); removeCandidateSet(candidateCount, previousCandidates); candidatesById.delete(normalizedId); return diffCandidateSets(previousVisibleCandidates, collectVisibleCandidates(affectedCandidates)); } function source(id) { const normalizedId = cleanUrl(id); return scanSourceById.get(normalizedId) ?? cssSourceById.get(normalizedId) ?? transformSourceById.get(normalizedId); } function sources() { return mergeSourcesByPriority().entries(); } function values() { const values = /* @__PURE__ */ new Set([...candidateCount.keys(), ...inlineIncludedCandidates]); for (const candidate of inlineExcludedCandidates) values.delete(candidate); return values; } function valuesForEntries(entries, options = {}) { if (entries === void 0) { if (!options.excludeEntries?.length) return values(); } if (entries?.length === 0) return new Set(inlineIncludedCandidates); const filtered = /* @__PURE__ */ new Set(); for (const [id, candidates] of candidatesById) { if (entries !== void 0 && !require_generator.isFileMatchedByTailwindSourceEntries(id, entries)) continue; if (options.excludeEntries?.length && require_generator.isFileMatchedByTailwindSourceEntries(id, options.excludeEntries)) continue; for (const candidate of candidates) filtered.add(candidate); } for (const candidate of inlineIncludedCandidates) filtered.add(candidate); for (const candidate of inlineExcludedCandidates) filtered.delete(candidate); return filtered; } function sourcesForEntries(entries, options = {}) { const sources = /* @__PURE__ */ new Map(); const addCandidateSource = (candidate, id) => { let candidateSources = sources.get(candidate); if (!candidateSources) { candidateSources = /* @__PURE__ */ new Set(); sources.set(candidate, candidateSources); } if (id) candidateSources.add(id); }; if (entries?.length === 0) { for (const candidate of inlineIncludedCandidates) addCandidateSource(candidate, void 0); for (const candidate of inlineExcludedCandidates) sources.delete(candidate); return sources; } for (const [id, candidates] of candidatesById) { if (entries !== void 0 && !require_generator.isFileMatchedByTailwindSourceEntries(id, entries)) continue; if (options.excludeEntries?.length && require_generator.isFileMatchedByTailwindSourceEntries(id, options.excludeEntries)) continue; for (const candidate of candidates) addCandidateSource(candidate, id); } for (const candidate of inlineIncludedCandidates) addCandidateSource(candidate, void 0); for (const candidate of inlineExcludedCandidates) sources.delete(candidate); return sources; } function clear() { candidatesById.clear(); scanCandidatesById.clear(); transformCandidatesById.clear(); cssCandidatesById.clear(); scanSourceById.clear(); transformSourceById.clear(); cssSourceById.clear(); candidateCount.clear(); inlineIncludedCandidates.clear(); inlineExcludedCandidates.clear(); } function clearScan() { for (const id of scanCandidatesById.keys()) { scanCandidatesById.delete(id); recompute(id); } inlineIncludedCandidates.clear(); inlineExcludedCandidates.clear(); } function resetScan() { inlineIncludedCandidates.clear(); inlineExcludedCandidates.clear(); } function snapshot() { return { candidatesById: [...candidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]), cssCandidatesById: [...cssCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]), cssSourceById: [...cssSourceById.entries()], scanCandidatesById: [...scanCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]), scanSourceById: [...scanSourceById.entries()], sourceById: [...mergeSourcesByPriority().entries()], transformCandidatesById: [...transformCandidatesById.entries()].map(([id, candidates]) => [id, [...candidates]]), transformSourceById: [...transformSourceById.entries()], inlineExcludedCandidates: [...inlineExcludedCandidates], inlineIncludedCandidates: [...inlineIncludedCandidates] }; } function restore(snapshot) { clear(); inlineExcludedCandidates = new Set(snapshot.inlineExcludedCandidates); inlineIncludedCandidates = new Set(snapshot.inlineIncludedCandidates); const scanEntries = snapshot.scanCandidatesById ?? snapshot.candidatesById; for (const [id, candidates] of scanEntries) { const candidateSet = new Set(candidates); if (candidateSet.size === 0) continue; scanCandidatesById.set(id, candidateSet); } for (const [id, candidates] of snapshot.transformCandidatesById ?? []) { const candidateSet = new Set(candidates); if (candidateSet.size === 0) continue; transformCandidatesById.set(id, candidateSet); } for (const [id, candidates] of snapshot.cssCandidatesById ?? []) { const candidateSet = new Set(candidates); if (candidateSet.size === 0) continue; cssCandidatesById.set(id, candidateSet); } for (const [id, source] of snapshot.scanSourceById ?? snapshot.sourceById ?? []) scanSourceById.set(id, source); for (const [id, source] of snapshot.transformSourceById ?? []) transformSourceById.set(id, source); for (const [id, source] of snapshot.cssSourceById ?? []) cssSourceById.set(id, source); const ids = /* @__PURE__ */ new Set([ ...scanCandidatesById.keys(), ...transformCandidatesById.keys(), ...cssCandidatesById.keys() ]); for (const id of ids) recompute(id); } return { syncSource: sync, sync, syncCss, merge, syncFile, syncCurrentSource, syncCurrentFile, scanRoot, syncInline, remove, source, sources, values, valuesForEntries, sourcesForEntries, snapshot, restore, clearScan, resetScan, clear }; function mergeSourcesByPriority() { const sources = /* @__PURE__ */ new Map(); for (const [id, source] of transformSourceById) sources.set(id, source); for (const [id, source] of cssSourceById) sources.set(id, source); for (const [id, source] of scanSourceById) sources.set(id, source); return sources; } } //#endregion //#region src/bundlers/shared/source-candidates/collector.ts function createSourceCandidateCollector(options = {}) { return createSourceCandidateStore(options); } //#endregion //#region src/compiler/artifact.ts function createCssFragment(options) { return { id: options.id, kind: options.kind, root: _weapp_tailwindcss_postcss.postcss.parse(options.css, { from: options.sourceId }), sourceId: options.sourceId, scope: options.scope, order: options.order ?? 0, stage: options.stage ?? "raw" }; } function cloneCssFragment(fragment) { return { ...fragment, root: fragment.root.clone(), scope: { ...fragment.scope } }; } function cloneGenerationArtifact(artifact) { return { fragments: artifact.fragments.map(cloneCssFragment), classSet: new Set(artifact.classSet), rawCandidates: new Set(artifact.rawCandidates), dependencies: [...artifact.dependencies], sourceEntries: [...artifact.sourceEntries], ...artifact.revision === void 0 ? {} : { revision: artifact.revision } }; } function createGenerationArtifact(fragments, options) { return cloneGenerationArtifact({ fragments, ...options }); } //#endregion //#region src/compiler/candidate-index.ts var CandidateIndex = class { constructor() { require_object._defineProperty(this, "candidatesBySource", /* @__PURE__ */ new Map()); } sync(sourceId, candidates) { const previous = this.candidatesBySource.get(sourceId) ?? /* @__PURE__ */ new Set(); const next = new Set(candidates); const addedCandidates = new Set([...next].filter((candidate) => !previous.has(candidate))); const removedCandidates = new Set([...previous].filter((candidate) => !next.has(candidate))); this.candidatesBySource.set(sourceId, next); return { sourceId, addedCandidates, removedCandidates }; } remove(sourceId) { const previous = this.candidatesBySource.get(sourceId) ?? /* @__PURE__ */ new Set(); this.candidatesBySource.delete(sourceId); return { sourceId, addedCandidates: /* @__PURE__ */ new Set(), removedCandidates: new Set(previous) }; } values() { const values = /* @__PURE__ */ new Set(); for (const candidates of this.candidatesBySource.values()) for (const candidate of candidates) values.add(candidate); return values; } get(sourceId) { return new Set(this.candidatesBySource.get(sourceId) ?? []); } entries() { return new Map([...this.candidatesBySource].map(([sourceId, candidates]) => [sourceId, new Set(candidates)])); } clear() { this.candidatesBySource.clear(); } }; //#endregion //#region src/compiler/compilation-scope-graph.ts function sourceNodeId(sourceId) { return `source:${sourceId}`; } function dependencyNodeId(dependencyId) { return `dependency:${dependencyId}`; } function createCompilationDependencyChanges(dependencyIds, type = "dependency-changed") { return [...new Set(dependencyIds)].map((id) => ({ id, type })); } function mergeCompilationDependencyChanges(...groups) { const changes = /* @__PURE__ */ new Map(); for (const group of groups) for (const change of group ?? []) { const previous = changes.get(change.id); changes.set(change.id, { id: change.id, type: previous?.type === "config-changed" ? previous.type : change.type }); } return [...changes.values()]; } function mergeCompilationScopeDependencies(...groups) { const dependencies = /* @__PURE__ */ new Map(); for (const group of groups) for (const dependency of group ?? []) { const previous = dependencies.get(dependency.id); if (previous && previous.kind !== dependency.kind) throw new Error(`同一个依赖不能对应不同类型:${dependency.id}`); dependencies.set(dependency.id, { ...dependency }); } return [...dependencies.values()]; } function dependencySignature(source) { return mergeCompilationScopeDependencies(source.dependencies).map((dependency) => `${dependency.kind}\0${dependency.id}`).sort().join("\0"); } function createCompilationScopeGraph(scope, outputId, sources) { const normalizedSources = [...sources].map((source) => ({ ...source, dependencies: mergeCompilationScopeDependencies(source.dependencies) })); const dependencies = mergeCompilationScopeDependencies(...normalizedSources.map((source) => source.dependencies)); const outputNodeId = `asset:${outputId}`; return { nodes: [ ...normalizedSources.map((source) => ({ id: sourceNodeId(source.id), kind: source.kind, scope: { ...scope }, ...source.content === void 0 ? {} : { content: source.content } })), ...dependencies.map((dependency) => ({ id: dependencyNodeId(dependency.id), kind: dependency.kind, scope: { ...scope } })), { id: outputNodeId, kind: "asset", scope: { ...scope } } ], edges: normalizedSources.flatMap((source) => [{ from: sourceNodeId(source.id), to: outputNodeId, kind: "emits-to" }, ...source.dependencies.map((dependency) => ({ from: sourceNodeId(source.id), to: dependencyNodeId(dependency.id), kind: "depends-on" }))]) }; } function createCompilationScopeSnapshot(scope, outputId, sources, options = {}) { const normalizedSources = [...sources]; return { ...createCompilationScopeGraph(scope, outputId, normalizedSources), candidatesBySource: normalizedSources.map((source) => [sourceNodeId(source.id), source.candidates]), ...options.changes === void 0 ? {} : { changes: options.changes }, ...options.preserveDeletedCss === void 0 ? {} : { preserveDeletedCss: options.preserveDeletedCss }, ...options.validatedClassSet === void 0 ? {} : { validatedClassSet: options.validatedClassSet } }; } //#endregion //#region src/compiler/compilation-dependency-state.ts var CompilationDependencyState = class { constructor() { require_object._defineProperty(this, "revisions", /* @__PURE__ */ new Map()); } getAffectedScopes(entries, changes) { return new Set(this.getAffectedScopeChanges(entries, changes).keys()); } getAffectedScopeChanges(entries, changes) { const changesByNodeId = new Map([...changes].map((change) => [dependencyNodeId(change.id), change])); const affectedScopeChanges = /* @__PURE__ */ new Map(); for (const entry of entries) { const scopeChanges = entry.latest?.graphNodes.map((node) => changesByNodeId.get(node.id)).filter((change) => change !== void 0); if (scopeChanges && scopeChanges.length > 0) affectedScopeChanges.set(entry.scope.id, scopeChanges.map((change) => ({ ...change }))); } return affectedScopeChanges; } record(entries, changes) { const affectedScopes = this.getAffectedScopes(entries, changes); this.recordScopes(affectedScopes); return affectedScopes; } recordScopes(scopeIds) { for (const scopeId of scopeIds) this.revisions.set(scopeId, (this.revisions.get(scopeId) ?? 0) + 1); } getRevision(scopeId) { return this.revisions.get(scopeId) ?? 0; } delete(scopeId) { this.revisions.delete(scopeId); } clear() { this.revisions.clear(); } }; //#endregion //#region src/compiler/compiler-owner-state.ts const compilerOwnerDisposals = /* @__PURE__ */ new WeakMap(); const compilerOwnerActivities = /* @__PURE__ */ new WeakMap(); function ensureCompilerOwnerActive(owner) { if (compilerOwnerDisposals.has(owner)) throw new Error("Compiler owner 正在释放,不能创建新的编译状态。"); } function acquireCompilerOwnerActivity(owner) { const currentDisposal = compilerOwnerDisposals.get(owner); if (currentDisposal) return currentDisposal.then(() => acquireCompilerOwnerActivity(owner)); let state = compilerOwnerActivities.get(owner); if (!state) { state = { active: 0, idleWaiters: /* @__PURE__ */ new Set() }; compilerOwnerActivities.set(owner, state); } state.active += 1; let released = false; return () => { if (released) return; released = true; state.active -= 1; if (state.active > 0) return; compilerOwnerActivities.delete(owner); for (const resolve of state.idleWaiters) resolve(); state.idleWaiters.clear(); }; } function waitForCompilerOwnerIdle(owner) { const state = compilerOwnerActivities.get(owner); if (!state || state.active === 0) return Promise.resolve(); return new Promise((resolve) => { state.idleWaiters.add(resolve); }); } function runCompilerOwnerActivity(owner, activity) { const acquired = acquireCompilerOwnerActivity(owner); if (typeof acquired !== "function") return acquired.then((release) => runCompilerOwnerActivityWithRelease(activity, release)); return runCompilerOwnerActivityWithRelease(activity, acquired); } function runCompilerOwnerActivityWithRelease(activity, release) { try { return Promise.resolve(activity()).finally(release); } catch (error) { release(); return Promise.reject(error); } } function runCompilerOwnerDisposal(owner, dispose) { const currentDisposal = compilerOwnerDisposals.get(owner); if (currentDisposal) return currentDisposal; const disposal = Promise.resolve().then(async () => { await waitForCompilerOwnerIdle(owner); await dispose(); }).finally(() => { if (compilerOwnerDisposals.get(owner) === disposal) compilerOwnerDisposals.delete(owner); }); compilerOwnerDisposals.set(owner, disposal); return disposal; } //#endregion //#region src/compiler/invalidation.ts function resolveInvalidatedScopes(graph, changes) { const invalidatedScopes = /* @__PURE__ */ new Set(); const visit = (sourceId, visited) => { if (visited.has(sourceId)) return; visited.add(sourceId); const node = graph.getNode(sourceId); if (node) invalidatedScopes.add(node.scope.id); for (const dependent of graph.getDependents(sourceId)) visit(dependent, visited); }; for (const change of changes) visit(change.sourceId, /* @__PURE__ */ new Set()); return invalidatedScopes; } //#endregion //#region src/compiler/source-graph.ts var SourceGraph = class { constructor() { require_object._defineProperty(this, "edges", /* @__PURE__ */ new Map()); require_object._defineProperty(this, "nodes", /* @__PURE__ */ new Map()); } replace(nodes, edges) { this.clear(); for (const node of nodes) this.nodes.set(node.id, { ...node, scope: { ...node.scope } }); for (const edge of edges) { if (!this.nodes.has(edge.from) || !this.nodes.has(edge.to)) throw new Error(`编译图边引用了不存在的节点:${edge.from} -> ${edge.to}`); this.edges.set(this.edgeKey(edge), { ...edge }); } } getNode(id) { const node = this.nodes.get(id); return node ? { ...node, scope: { ...node.scope } } : void 0; } getNodes() { return [...this.nodes.values()].map((node) => ({ ...node, scope: { ...node.scope } })); } getEdges() { return [...this.edges.values()].map((edge) => ({ ...edge })); } getDependents(id) { return this.getEdges().filter((edge) => edge.to === id).map((edge) => edge.from); } clear() { this.edges.clear(); this.nodes.clear(); } edgeKey(edge) { return `${edge.kind}\0${edge.from}\0${edge.to}`; } }; //#endregion //#region src/compiler/session.ts var DefaultCompilationSession = class { constructor() { require_object._defineProperty(this, "candidateIndex", new CandidateIndex()); require_object._defineProperty(this, "graph", new SourceGraph()); require_object._defineProperty(this, "retainedCandidates", /* @__PURE__ */ new Set()); require_object._defineProperty(this, "validatedClassSet", /* @__PURE__ */ new Set()); require_object._defineProperty(this, "invalidatedScopes", /* @__PURE__ */ new Set()); require_object._defineProperty(this, "revision", 0); } update(snapshot) { const changes = [...snapshot.changes ?? []]; const invalidatedScopes = resolveInvalidatedScopes(this.graph, changes); this.graph.replace(snapshot.nodes, snapshot.edges); for (const [sourceId, candidates] of snapshot.candidatesBySource ?? []) { const change = this.candidateIndex.sync(sourceId, candidates); if (change.addedCandidates.size > 0 || change.removedCandidates.size > 0) changes.push(change); } for (const change of changes) if ("type" in change && change.type === "source-removed") this.candidateIndex.remove(change.sourceId); const currentCandidates = this.candidateIndex.values(); if (snapshot.preserveDeletedCss) for (const candidate of currentCandidates) this.retainedCandidates.add(candidate); else { this.retainedCandidates.clear(); for (const candidate of currentCandidates) this.retainedCandidates.add(candidate); } if (snapshot.validatedClassSet !== void 0) this.validatedClassSet = new Set(snapshot.validatedClassSet); else if (!snapshot.preserveDeletedCss) this.validatedClassSet = new Set([...this.validatedClassSet].filter((candidate) => this.retainedCandidates.has(candidate))); this.revision += 1; for (const scopeId of resolveInvalidatedScopes(this.graph, changes)) invalidatedScopes.add(scopeId); this.invalidatedScopes = invalidatedScopes; return this.createResult(); } commitValidation(revision, validatedClassSet, graph) { if (revision !== this.revision) throw new Error(`不能向编译 revision ${this.revision} 提交 revision ${revision} 的 classSet。`); if (graph) this.graph.replace(graph.nodes, graph.edges); this.validatedClassSet = new Set(validatedClassSet); return this.createResult(); } createResult() { return { revision: this.revision, candidates: new Set(this.retainedCandidates), candidatesBySource: this.candidateIndex.entries(), validatedClassSet: new Set(this.validatedClassSet), invalidatedScopes: new Set(this.invalidatedScopes), graphEdges: this.graph.getEdges(), graphNodes: this.graph.getNodes() }; } dispose() { this.candidateIndex.clear(); this.graph.clear(); this.retainedCandidates.clear(); this.validatedClassSet.clear(); this.invalidatedScopes.clear(); this.revision = 0; } }; //#endregion //#region src/compiler/compilation-session-pool.ts const COMPILATION_SCOPE_CACHE_MAX = 128; function cloneScopeSource(source) { return { ...source, candidates: new Set(source.candidates), dependencies: source.dependencies?.map((dependency) => ({ ...dependency })) }; } var CompilationSessionPool = class { constructor() { require_object._defineProperty(this, "dependencyState", new CompilationDependencyState()); require_object._defineProperty(this, "entries", /* @__PURE__ */ new Map()); require_object._defineProperty(this, "disposed", false); } run(request, compile) { const entry = this.getEntry(request.scope); const execution = this.runEntry(entry, request, compile); entry.executions.add(execution); execution.then(() => entry.executions.delete(execution), () => entry.executions.delete(execution)); return execution; } invalidateScope(scopeId) { const entry = this.entries.get(scopeId); if (!entry) return; entry.active = false; this.disposeEntry(entry); this.entries.delete(scopeId); this.dependencyState.delete(scopeId); } dispose() { if (this.disposed) return Promise.resolve(); this.disposed = true; const entries = [...this.entries.values()]; for (const entry of entries) entry.active = false; this.entries.clear(); this.dependencyState.clear(); return Promise.all(entries.map((entry) => this.disposeEntry(entry))).then(() => void 0); } get size() { return this.entries.size; } getAffectedScopes(changes) { return this.dependencyState.getAffectedScopes(this.entries.values(), changes); } getAffectedScopeChanges(changes) { return this.dependencyState.getAffectedScopeChanges(this.entries.values(), changes); } recordDependencyChanges(changes) { return this.dependencyState.record(this.entries.values(), changes); } recordAffectedScopes(scopeIds) { this.dependencyState.recordScopes(scopeIds); } getScopeDependencyRevision(scopeId) { return this.dependencyState.getRevision(scopeId); } getEntry(scope) { if (this.disposed) throw new Error("CompilationSessionPool 已释放。"); const cached = this.entries.get(scope.id); if (cached) { if (cached.scope.kind !== scope.kind) throw new Error(`同一个 scope id 不能对应不同类型:${scope.id}`); this.entries.delete(scope.id); this.entries.set(scope.id, cached); return cached; } const entry = { active: true, executions: /* @__PURE__ */ new Set(), pending: Promise.resolve(), scope: { ...scope }, session: new DefaultCompilationSession(), generatedDependencies: /* @__PURE__ */ new Map(), sources: /* @__PURE__ */ new Map() }; this.entries.set(scope.id, entry); while (this.entries.size > COMPILATION_SCOPE_CACHE_MAX) { const oldestScopeId = this.entries.keys().next().value; if (oldestScopeId === void 0 || oldestScopeId === scope.id) break; this.invalidateScope(oldestScopeId); } return entry; } async disposeEntry(entry) { await Promise.allSettled([...entry.executions]); await entry.pending; entry.session.dispose(); } async runEntry(entry, request, compile) { const prepared = await this.enqueue(entry, () => this.prepareEntry(entry, request)); const value = await compile(prepared.compilation); const validatedClassSet = request.preserveDeletedCss ? /* @__PURE__ */ new Set([...prepared.compilation.validatedClassSet, ...value?.classSet ?? []]) : new Set(value?.classSet ?? []); const generatedDependencies = value?.dependenciesBySource === void 0 ? void 0 : this.normalizeGeneratedDependencies(value.dependenciesBySource, prepared.sources); let committed = false; let committedCompilation; await this.enqueue(entry, () => { if (!entry.active || entry.latest?.revision !== prepared.compilation.revision) return; if (generatedDependencies) entry.generatedDependencies = generatedDependencies; entry.latest = entry.session.commitValidation(prepared.compilation.revision, validatedClassSet, createCompilationScopeGraph(request.scope, request.outputId, this.createGraphSources(prepared.sources, entry.generatedDependencies))); committedCompilation = this.toScopeState(entry.latest, prepared.sources); committed = true; }); const compilation = committedCompilation ?? { ...prepared.compilation, validatedClassSet }; return committed ? { committed, compilation, value } : { committed, compilation }; } prepareEntry(entry, request) { const nextSources = new Map(request.sources.map((source) => [source.id, cloneScopeSource(source)])); const changes = [...request.changes ?? []].map((change) => ({ sourceId: dependencyNodeId(change.id), type: change.type })); for (const sourceId of entry.sources.keys()) if (!nextSources.has(sourceId)) changes.push({ sourceId: sourceNodeId(sourceId), type: "source-removed" }); for (const [sourceId, source] of nextSources) { const previous = entry.sources.get(sourceId); if (previous && (previous.content !== source.content || dependencySignature(previous) !== dependencySignature(source))) changes.push({ sourceId: sourceNodeId(sourceId), type: "dependency-changed" }); } entry.sources = nextSources; entry.generatedDependencies = new Map([...entry.generatedDependencies].filter(([sourceId]) => nextSources.has(sourceId))); entry.latest = entry.session.update(createCompilationScopeSnapshot(request.scope, request.outputId, this.createGraphSources(nextSources, entry.generatedDependencies), { changes, preserveDeletedCss: request.preserveDeletedCss })); return { compilation: this.toScopeState(entry.latest, nextSources), sources: nextSources }; } createGraphSources(sources, generatedDependencies) { return [...sources.values()].map((source) => ({ ...source, dependencies: mergeCompilationScopeDependencies(source.dependencies, generatedDependencies.get(source.id)) })); } normalizeGeneratedDependencies(dependenciesBySource, sources) { const normalized = /* @__PURE__ */ new Map(); for (const [sourceId, dependencies] of dependenciesBySource) { if (!sources.has(sourceId)) throw new Error(`生成结果引用了未知 source:${sourceId}`); normalized.set(sourceId, mergeCompilationScopeDependencies(normalized.get(sourceId), dependencies)); } return normalized; } enqueue(entry, task) { const execution = entry.pending.then(task); entry.pending = execution.then(() => void 0, () => void 0); return execution; } toScopeState(compilation, sources) { return { ...compilation, candidatesBySource: new Map([...sources.keys()].map((sourceId) => [sourceId, compilation.candidatesBySource.get(sourceNodeId(sourceId)) ?? /* @__PURE__ */ new Set()])) }; } }; const compilationSessionPools = /* @__PURE__ */ new WeakMap(); function getCompilationSessionPool(owner) { ensureCompilerOwnerActive(owner); let pool = compilationSessionPools.get(owner); if (!pool) { pool = new CompilationSessionPool(); compilationSessionPools.set(owner, pool); } return pool; } function disposeCompilationSessionPool(owner) { const pool = compilationSessionPools.get(owner); if (!pool) return Promise.resolve(); compilationSessionPools.delete(owner); return pool.dispose(); } //#endregion //#region src/compiler/tailwind-generation-session-pool.ts const SESSION_ENGINE_CACHE_MAX = 32; function createSourceKey(source) { return (0, _weapp_tailwindcss_shared_node.md5)([ source.projectRoot, source.base, source.baseFallbacks.join("\0"), source.css, source.dependencies.join("\0") ].join("\0")); } function disposeGenerator(generator) { generator?.dispose?.(); } var TailwindGenerationSessionPool = class { constructor() { require_object._defineProperty(this, "generators", /* @__PURE__ */ new Map()); require_object._defineProperty(this, "disposed", false); } async generate(source, options) { return this.getGenerator(source).generate(options); } async validateCandidates(source, candidates) { return this.getGenerator(source).validateCandidates(candidates); } invalidate(change) { if (change.type === "all" || change.type === "dependencies") { for (const generator of this.generators.values()) disposeGenerator(generator); this.generators.clear(); return; } const key = createSourceKey(change.source); disposeGenerator(this.generators.get(key)); this.generators.delete(key); } dispose() { for (const generator of this.generators.values()) disposeGenerator(generator); this.generators.clear(); this.disposed = true; } get size() { return this.generators.size; } getGenerator(source) { if (this.disposed) throw new Error("TailwindGenerationSessionPool 已释放。"); const key = createSourceKey(source); const cached = this.generators.get(key); if (cached) { this.generators.delete(key); this.generators.set(key, cached); return cached; } const generator = require_generator.createWeappTailwindcssGenerator(source); this.generators.set(key, generator); while (this.generators.size > SESSION_ENGINE_CACHE_MAX) { const oldest = this.generators.keys().next().value; if (oldest === void 0) break; disposeGenerator(this.generators.get(oldest)); this.generators.delete(oldest); } return generator; } }; const sessionPools = /* @__PURE__ */ new WeakMap(); function getTailwindGenerationSessionPool(owner) { ensureCompilerOwnerActive(owner); let pool = sessionPools.get(owner); if (!pool) { pool = new TailwindGenerationSessionPool(); sessionPools.set(owner, pool); } return pool; } function disposeTailwindGenerationSessionPool(owner) { const pool = sessionPools.get(owner); if (!pool) return; sessionPools.delete(owner); pool.dispose(); } //#endregion //#region src/compiler/compilation-change-coordinator.ts var CompilationChangeCoordinator = class { constructor(compilationPool, generationPool) { this.compilationPool = compilationPool; this.generationPool = generationPool; require_object._defineProperty(this, "pendingChangesByScope", /* @__PURE__ */ new Map()); require_object._defineProperty(this, "disposed", false); } record(changes) { this.ensureActive(); const normalizedChanges = mergeCompilationDependencyChanges(changes); if (normalizedChanges.length === 0) return /* @__PURE__ */ new Set(); const affectedScopeChanges = this.compilationPool.getAffectedScopeChanges(normalizedChanges); const affectedScopes = new Set(affectedScopeChanges.keys()); const newlyPendingScopes = /* @__PURE__ */ new Set(); const invalidatedPaths = /* @__PURE__ */ new Set(); for (const [scopeId, scopeChanges] of affectedScopeChanges) { let pendingChanges = this.pendingChangesByScope.get(scopeId); if (!pendingChanges) { pendingChanges = /* @__PURE__ */ new Map(); this.pendingChangesByScope.set(scopeId, pendingChanges); newlyPendingScopes.add(scopeId); } for (const change of scopeChanges) { const previous = pendingChanges.get(change.id); const mergedChange = mergeCompilationDependencyChanges(previous ? [previous] : void 0, [change])[0]; if (!previous || previous.type !== mergedChange.type) { pendingChanges.set(change.id, mergedChange); invalidatedPaths.add(change.id); } } } if (newlyPendingScopes.size > 0) this.compilationPool.recordAffectedScopes(newlyPendingScopes); if (invalidatedPaths.size > 0) this.generationPool.invalidate({ type: "dependencies", paths: invalidatedPaths }); return affectedScopes; } consume(scopeId) { this.ensureActive(); const pendingChanges = this.pendingChangesByScope.get(scopeId); if (!pendingChanges) return; this.pendingChangesByScope.delete(scopeId); return [...pendingChanges.values()].map((change) => ({ ...change })); } invalidateScope(scopeId) { this.ensureActive(); this.pendingChangesByScope.delete(scopeId); this.compilationPool.invalidateScope(scopeId); } getScopeDependencyRevision(scopeId) { this.ensureActive(); return this.compilationPool.getScopeDependencyRevision(scopeId); } dispose() { this.pendingChangesByScope.clear(); this.disposed = true; } ensureActive() { if (this.disposed) throw new Error("CompilationChangeCoordinator 已释放。"); } }; const compilationChangeCoordinators = /* @__PURE__ */ new WeakMap(); function getCompilationChangeCoordinator(owner) { ensureCompilerOwnerActive(owner); let coordinator = compilationChangeCoordinators.get(owner); if (!coordinator) { coordinator = new CompilationChangeCoordinator(getCompilationSessionPool(owner), getTailwindGenerationSessionPool(owner)); compilationChangeCoordinators.set(owner, coordinator); } return coordinator; } function recordCompilationDependencyChanges(owner, changes) { return getCompilationChangeCoordinator(owner).record(changes); } function consumeCompilationScopeChanges(owner, scopeId) { return getCompilationChangeCoordinator(owner).consume(scopeId); } function getCompilationScopeDependencyRevision(owner, scopeId) { return getCompilationChangeCoordinator(owner).getScopeDependencyRevision(scopeId); } function invalidateCompilationScope(owner, scopeId) { getCompilationChangeCoordinator(owner).invalidateScope(scopeId); } function disposeCompilationChangeCoordinator(owner) { const coordinator = compilationChangeCoordinators.get(owner); if (!coordinator) return; compilationChangeCoordinators.delete(owner); coordinator.dispose(); } //#endregion //#region src/compiler/composition.ts function orderCssFragments(fragments) { return [...fragments].sort((left, right) => left.order - right.order || left.id.localeCompare(right.id