weapp-tailwindcss
Version:
把 tailwindcss 原子化样式思想,带给小程序开发者们! bring tailwindcss to miniprogram developers!
1,129 lines (1,120 loc) • 35.1 kB
JavaScript
import {
defuOverrideArray
} from "./chunk-RR5HCKVQ.mjs";
// src/logger/index.ts
import { logger } from "@weapp-tailwindcss/logger";
// src/context/workspace.ts
import { existsSync, readdirSync, readFileSync } from "fs";
import path from "path";
var IGNORED_WORKSPACE_DIRS = /* @__PURE__ */ new Set([
"node_modules",
".git",
".hg",
".svn",
".turbo",
".output",
".next",
"dist",
"build"
]);
function findWorkspaceRoot(startDir) {
if (!startDir) {
return void 0;
}
let current = path.resolve(startDir);
while (true) {
const workspaceFile = path.join(current, "pnpm-workspace.yaml");
if (existsSync(workspaceFile)) {
return current;
}
const parent = path.dirname(current);
if (parent === current) {
return void 0;
}
current = parent;
}
}
function findNearestPackageRoot(startDir) {
if (!startDir) {
return void 0;
}
let current = path.resolve(startDir);
while (true) {
const pkgPath = path.join(current, "package.json");
if (existsSync(pkgPath)) {
return current;
}
const parent = path.dirname(current);
if (parent === current) {
return void 0;
}
current = parent;
}
}
function findWorkspacePackageDir(rootDir, packageName) {
const visited = /* @__PURE__ */ new Set();
const queue = [path.resolve(rootDir)];
while (queue.length > 0) {
const current = queue.shift();
const normalized = path.normalize(current);
if (visited.has(normalized)) {
continue;
}
visited.add(normalized);
try {
const pkgPath = path.join(normalized, "package.json");
if (existsSync(pkgPath)) {
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
if (pkg?.name === packageName) {
return normalized;
}
}
} catch {
}
let entries;
try {
entries = readdirSync(normalized, { withFileTypes: true });
} catch {
continue;
}
for (const entry of entries) {
if (!entry.isDirectory() || IGNORED_WORKSPACE_DIRS.has(entry.name) || entry.isSymbolicLink?.()) {
continue;
}
queue.push(path.join(normalized, entry.name));
}
}
return void 0;
}
// src/tailwindcss/v4/config.ts
import { logger as logger2 } from "@weapp-tailwindcss/logger";
var DEFAULT_CSS_CALC_CUSTOM_PROPERTIES = [];
function includesToken(list, token) {
return list.some((candidate) => {
if (typeof token === "string") {
if (typeof candidate === "string") {
return candidate === token;
}
candidate.lastIndex = 0;
return candidate.test(token);
}
if (typeof candidate === "string") {
token.lastIndex = 0;
return token.test(candidate);
}
return candidate.source === token.source && candidate.flags === token.flags;
});
}
function ensureDefaultsIncluded(value) {
if (value === true) {
return {
includeCustomProperties: [...DEFAULT_CSS_CALC_CUSTOM_PROPERTIES]
};
}
if (Array.isArray(value)) {
if (!DEFAULT_CSS_CALC_CUSTOM_PROPERTIES.length) {
return value;
}
const missing = DEFAULT_CSS_CALC_CUSTOM_PROPERTIES.filter((token) => !includesToken(value, token));
return missing.length > 0 ? [...value, ...missing] : value;
}
if (value && typeof value === "object") {
const include = value.includeCustomProperties;
if (!Array.isArray(include)) {
return {
...value,
includeCustomProperties: [...DEFAULT_CSS_CALC_CUSTOM_PROPERTIES]
};
}
if (!DEFAULT_CSS_CALC_CUSTOM_PROPERTIES.length) {
return value;
}
const missing = DEFAULT_CSS_CALC_CUSTOM_PROPERTIES.filter((token) => !includesToken(include, token));
return missing.length > 0 ? {
...value,
includeCustomProperties: [...include, ...missing]
} : value;
}
return value;
}
function normalizeCssEntriesConfig(entries) {
if (!entries) {
return void 0;
}
if (typeof entries === "string") {
const trimmed = entries.trim();
return trimmed ? [trimmed] : void 0;
}
if (!Array.isArray(entries)) {
return void 0;
}
const normalized = entries.map((entry) => typeof entry === "string" ? entry.trim() : "").filter((entry) => entry.length > 0);
return normalized.length > 0 ? normalized : void 0;
}
function hasConfiguredCssEntries(ctx) {
if (normalizeCssEntriesConfig(ctx.cssEntries)) {
return true;
}
if (normalizeCssEntriesConfig(ctx.tailwindcss?.v4?.cssEntries)) {
return true;
}
const patcherOptions = ctx.tailwindcssPatcherOptions;
if (patcherOptions) {
if (normalizeCssEntriesConfig(patcherOptions.tailwind?.v4?.cssEntries)) {
return true;
}
if (normalizeCssEntriesConfig(patcherOptions.patch?.tailwindcss?.v4?.cssEntries)) {
return true;
}
}
return false;
}
var hasWarnedMissingCssEntries = false;
function warnMissingCssEntries(ctx, patcher) {
if (hasWarnedMissingCssEntries) {
return;
}
if (patcher?.majorVersion !== 4) {
return;
}
if (hasConfiguredCssEntries(ctx)) {
return;
}
hasWarnedMissingCssEntries = true;
logger2.warn(
'[tailwindcss@4] \u672A\u68C0\u6D4B\u5230 cssEntries \u914D\u7F6E\u3002\u8BF7\u4F20\u5165\u5305\u542B tailwindcss \u5F15\u7528\u7684 CSS \u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u4F8B\u5982 cssEntries: ["/absolute/path/to/src/app.css"]\uFF0C\u5426\u5219 tailwindcss \u751F\u6210\u7684\u7C7B\u540D\u4E0D\u4F1A\u53C2\u4E0E\u8F6C\u8BD1\u3002'
);
}
function applyV4CssCalcDefaults(cssCalc, patcher) {
const cssCalcOptions = cssCalc ?? patcher?.majorVersion === 4;
if (patcher?.majorVersion === 4 && cssCalcOptions) {
return ensureDefaultsIncluded(cssCalcOptions);
}
return cssCalcOptions;
}
// src/tailwindcss/v4/patcher.ts
import path3 from "path";
import { logger as logger4 } from "@weapp-tailwindcss/logger";
// src/tailwindcss/patcher.ts
import { existsSync as existsSync2 } from "fs";
import { createRequire } from "module";
import path2 from "path";
import process from "process";
import { fileURLToPath } from "url";
import { logger as logger3 } from "@weapp-tailwindcss/logger";
import { defuOverrideArray as defuOverrideArray2 } from "@weapp-tailwindcss/shared";
import { TailwindcssPatcher } from "tailwindcss-patch";
var GENERIC_RELATIVE_SPECIFIERS = [".", ".."];
var DEFAULT_TAILWIND_CONFIG_SPECIFIERS = [
"stubs/config.full.js",
"defaultConfig.js"
];
function isPathSpecifier(specifier) {
if (!specifier) {
return false;
}
if (specifier.startsWith("file://")) {
return true;
}
if (path2.isAbsolute(specifier)) {
return true;
}
return GENERIC_RELATIVE_SPECIFIERS.some((prefix) => specifier.startsWith(`${prefix}/`) || specifier.startsWith(`${prefix}\\`));
}
function resolveModuleFromPaths(specifier, paths) {
if (!specifier || isPathSpecifier(specifier) || paths.length === 0) {
return void 0;
}
try {
const req = createRequire(import.meta.url);
return req.resolve(specifier, { paths });
} catch {
return void 0;
}
}
function resolveTailwindConfigFallback(packageName, paths) {
if (!packageName) {
return void 0;
}
for (const suffix of DEFAULT_TAILWIND_CONFIG_SPECIFIERS) {
const candidate = `${packageName}/${suffix}`;
const resolved = resolveModuleFromPaths(candidate, paths);
if (resolved) {
return resolved;
}
}
return void 0;
}
function createFallbackTailwindcssPatcher() {
const packageInfo = {
name: "tailwindcss",
version: void 0,
rootPath: "",
packageJsonPath: "",
packageJson: {}
};
return {
packageInfo,
async patch() {
return {
exposeContext: void 0,
extendLengthUnits: void 0
};
},
async getClassSet() {
return /* @__PURE__ */ new Set();
},
async extract(_options) {
const classSet = /* @__PURE__ */ new Set();
return {
classList: [],
classSet
};
},
async collectContentTokens() {
return {
entries: [],
filesScanned: 0,
sources: [],
skippedFiles: []
};
}
};
}
var hasLoggedMissingTailwind = false;
function appendNodeModules(paths, dir) {
if (!dir) {
return;
}
const nodeModulesDir = path2.join(dir, "node_modules");
if (existsSync2(nodeModulesDir)) {
paths.add(nodeModulesDir);
}
}
var TAILWIND_CONFIG_FILES = [
"tailwind.config.js",
"tailwind.config.cjs",
"tailwind.config.mjs",
"tailwind.config.ts",
"tailwind.config.cts",
"tailwind.config.mts"
];
function findTailwindConfig(searchRoots) {
for (const root of searchRoots) {
for (const file of TAILWIND_CONFIG_FILES) {
const candidate = path2.resolve(root, file);
if (existsSync2(candidate)) {
return candidate;
}
}
}
return void 0;
}
function createDefaultResolvePaths(basedir) {
const paths = /* @__PURE__ */ new Set();
let fallbackCandidates = [];
if (basedir) {
const resolvedBase = path2.resolve(basedir);
appendNodeModules(paths, resolvedBase);
fallbackCandidates.push(resolvedBase);
const packageRoot = findNearestPackageRoot(resolvedBase);
if (packageRoot) {
appendNodeModules(paths, packageRoot);
fallbackCandidates.push(packageRoot);
}
}
const cwd = process.cwd();
appendNodeModules(paths, cwd);
try {
const modulePath = fileURLToPath(import.meta.url);
const candidate = existsSync2(modulePath) && !path2.extname(modulePath) ? modulePath : path2.dirname(modulePath);
paths.add(candidate);
} catch {
paths.add(import.meta.url);
}
if (paths.size === 0) {
fallbackCandidates = fallbackCandidates.filter(Boolean);
if (fallbackCandidates.length === 0) {
fallbackCandidates.push(cwd);
}
for (const candidate of fallbackCandidates) {
paths.add(candidate);
}
}
return [...paths];
}
function normalizeExtendLengthUnits(value) {
if (value === false) {
return false;
}
if (value === true) {
return { enabled: true };
}
if (value && typeof value === "object") {
return {
enabled: true,
...value
};
}
return void 0;
}
function normalizeTailwindcssPatcherOptions(options) {
if (!options) {
return void 0;
}
if ("patch" in options) {
const { cache, patch } = options;
const normalized = {};
if (cache !== void 0) {
normalized.cache = cache;
}
if (patch?.overwrite !== void 0) {
normalized.overwrite = patch.overwrite;
}
if (patch?.filter) {
normalized.filter = patch.filter;
}
const extendLengthUnits = normalizeExtendLengthUnits(patch?.applyPatches?.extendLengthUnits);
const exposeContext = patch?.applyPatches?.exportContext;
if (extendLengthUnits !== void 0 || exposeContext !== void 0) {
normalized.features = {
exposeContext,
extendLengthUnits
};
}
const cwd = patch?.cwd ?? patch?.basedir;
if (cwd) {
normalized.cwd = cwd;
}
const tailwindOptions = patch?.tailwindcss ? { ...patch.tailwindcss } : void 0;
const legacyResolve = patch?.resolve;
let nextTailwindOptions = tailwindOptions;
if (nextTailwindOptions?.version === 2 && !nextTailwindOptions.packageName) {
nextTailwindOptions = {
...nextTailwindOptions,
packageName: "@tailwindcss/postcss7-compat",
postcssPlugin: nextTailwindOptions.postcssPlugin
};
if (!nextTailwindOptions.postcssPlugin) {
nextTailwindOptions.postcssPlugin = "@tailwindcss/postcss7-compat";
}
}
if (nextTailwindOptions || legacyResolve) {
const resolveOptions = nextTailwindOptions?.resolve;
const mergedResolve = legacyResolve || resolveOptions ? {
...resolveOptions ?? {},
...legacyResolve ?? {}
} : void 0;
normalized.tailwind = {
...nextTailwindOptions ?? {},
...mergedResolve ? { resolve: mergedResolve } : {}
};
}
return normalized;
}
return options;
}
function createTailwindcssPatcher(options) {
const { basedir, cacheDir, supportCustomLengthUnitsPatch, tailwindcss, tailwindcssPatcherOptions } = options || {};
const cache = {
driver: "memory"
};
const normalizedBasedir = basedir ? path2.resolve(basedir) : void 0;
const cacheRoot = findNearestPackageRoot(normalizedBasedir) ?? normalizedBasedir ?? process.cwd();
if (cacheDir) {
if (path2.isAbsolute(cacheDir)) {
cache.dir = cacheDir;
} else if (normalizedBasedir) {
cache.dir = path2.resolve(normalizedBasedir, cacheDir);
} else {
cache.dir = path2.resolve(process.cwd(), cacheDir);
}
} else {
cache.dir = path2.join(cacheRoot, "node_modules", ".cache", "tailwindcss-patch");
}
if (normalizedBasedir) {
cache.cwd = normalizedBasedir;
}
const resolvePaths = createDefaultResolvePaths(cache.cwd ?? normalizedBasedir ?? process.cwd());
const normalizedUserOptions = normalizeTailwindcssPatcherOptions(tailwindcssPatcherOptions);
const extendLengthUnits = normalizeExtendLengthUnits(supportCustomLengthUnitsPatch ?? true);
const baseTailwindOptions = defuOverrideArray2(
tailwindcss ?? {},
{
cwd: normalizedBasedir,
resolve: {
paths: resolvePaths
}
}
);
if (baseTailwindOptions.version === 2) {
if (!baseTailwindOptions.packageName) {
baseTailwindOptions.packageName = "@tailwindcss/postcss7-compat";
}
if (!baseTailwindOptions.postcssPlugin) {
baseTailwindOptions.postcssPlugin = "@tailwindcss/postcss7-compat";
}
} else if (!baseTailwindOptions.packageName) {
baseTailwindOptions.packageName = "tailwindcss";
}
if (!baseTailwindOptions.postcssPlugin) {
baseTailwindOptions.postcssPlugin = baseTailwindOptions.version === 4 ? "@tailwindcss/postcss" : "tailwindcss";
}
if (typeof baseTailwindOptions.postcssPlugin === "string") {
const resolvedPlugin = resolveModuleFromPaths(baseTailwindOptions.postcssPlugin, resolvePaths);
if (resolvedPlugin) {
baseTailwindOptions.postcssPlugin = resolvedPlugin;
}
}
const baseOptions = {
cwd: normalizedBasedir,
cache,
tailwind: baseTailwindOptions,
features: {
exposeContext: true,
extendLengthUnits
}
};
const resolvedOptions = defuOverrideArray2(
normalizedUserOptions ?? {},
baseOptions
);
if (resolvedOptions.tailwind) {
const existingResolve = resolvedOptions.tailwind.resolve ?? {};
const customPaths = Array.isArray(existingResolve.paths) && existingResolve.paths.length > 0;
const sourcePaths = customPaths ? existingResolve.paths : resolvePaths;
resolvedOptions.tailwind.resolve = {
...existingResolve,
paths: Array.from(new Set(sourcePaths))
};
logger3.debug("Tailwind resolve config %O", {
packageName: resolvedOptions.tailwind.packageName,
version: resolvedOptions.tailwind.version,
resolve: resolvedOptions.tailwind.resolve,
cwd: resolvedOptions.tailwind.cwd
});
if (typeof resolvedOptions.tailwind.postcssPlugin === "string") {
const resolvedPlugin = resolveModuleFromPaths(
resolvedOptions.tailwind.postcssPlugin,
resolvedOptions.tailwind.resolve?.paths ?? resolvePaths
);
if (resolvedPlugin) {
resolvedOptions.tailwind.postcssPlugin = resolvedPlugin;
}
}
const searchRoots = /* @__PURE__ */ new Set();
if (resolvedOptions.tailwind.cwd) {
searchRoots.add(resolvedOptions.tailwind.cwd);
}
for (const resolvePath of resolvedOptions.tailwind.resolve?.paths ?? []) {
const parentDir = path2.dirname(resolvePath);
searchRoots.add(parentDir);
}
const configPath = findTailwindConfig(searchRoots);
if (!resolvedOptions.tailwind.config) {
if (configPath) {
resolvedOptions.tailwind.config = configPath;
} else {
const fallbackConfig = resolveTailwindConfigFallback(
resolvedOptions.tailwind.packageName,
resolvedOptions.tailwind.resolve.paths ?? resolvePaths
);
if (fallbackConfig) {
resolvedOptions.tailwind.config = fallbackConfig;
}
}
}
if (!resolvedOptions.tailwind.cwd && configPath) {
resolvedOptions.tailwind.cwd = path2.dirname(configPath);
}
}
try {
return new TailwindcssPatcher(resolvedOptions);
} catch (error) {
const searchPaths = resolvedOptions.tailwind?.resolve?.paths;
if (error instanceof Error && /tailwindcss not found/i.test(error.message)) {
if (!hasLoggedMissingTailwind) {
logger3.warn("Tailwind CSS \u672A\u5B89\u88C5\uFF0C\u5DF2\u8DF3\u8FC7 Tailwind \u76F8\u5173\u8865\u4E01\u3002\u82E5\u9700\u4F7F\u7528 Tailwind \u80FD\u529B\uFF0C\u8BF7\u5B89\u88C5 tailwindcss\u3002");
hasLoggedMissingTailwind = true;
}
return createFallbackTailwindcssPatcher();
}
if (error instanceof Error && /unable to locate tailwind css package/i.test(error.message)) {
logger3.error('\u65E0\u6CD5\u5B9A\u4F4D Tailwind CSS \u5305 "%s"\uFF0C\u5DF2\u5C1D\u8BD5\u8DEF\u5F84: %O', resolvedOptions.tailwind?.packageName, searchPaths);
}
throw error;
}
}
// src/tailwindcss/v4/patcher.ts
function isLegacyTailwindcssPatcherOptions(options) {
return typeof options === "object" && options !== null && "patch" in options;
}
function isModernTailwindcssPatchOptions(options) {
return typeof options === "object" && options !== null && !("patch" in options);
}
function guessBasedirFromEntries(entries) {
if (!entries) {
return void 0;
}
for (const entry of entries) {
if (typeof entry !== "string") {
continue;
}
const trimmed = entry.trim();
if (!trimmed || !path3.isAbsolute(trimmed)) {
continue;
}
const entryDir = path3.dirname(trimmed);
const resolved = findNearestPackageRoot(entryDir) ?? entryDir;
if (resolved) {
return resolved;
}
}
return void 0;
}
function normalizeCssEntries(entries, anchor) {
if (!entries || entries.length === 0) {
return void 0;
}
const normalized = /* @__PURE__ */ new Set();
for (const entry of entries) {
if (typeof entry !== "string") {
continue;
}
const trimmed = entry.trim();
if (trimmed.length === 0) {
continue;
}
const resolved = path3.isAbsolute(trimmed) ? path3.normalize(trimmed) : path3.normalize(path3.resolve(anchor, trimmed));
normalized.add(resolved);
}
return normalized.size > 0 ? [...normalized] : void 0;
}
function isSubPath(parent, child) {
if (!parent || !child) {
return false;
}
const relative = path3.relative(parent, child);
return relative === "" || !relative.startsWith("..") && !path3.isAbsolute(relative);
}
function resolveCssEntryBase(entryDir, options) {
const normalizedDir = path3.normalize(entryDir);
const { preferredBaseDir, workspaceRoot } = options;
if (preferredBaseDir && isSubPath(preferredBaseDir, normalizedDir)) {
return preferredBaseDir;
}
if (workspaceRoot && isSubPath(workspaceRoot, normalizedDir)) {
return workspaceRoot;
}
const packageRoot = findNearestPackageRoot(normalizedDir);
if (packageRoot) {
return path3.normalize(packageRoot);
}
return normalizedDir;
}
function groupCssEntriesByBase(entries, options = {}) {
const normalizedOptions = {
preferredBaseDir: options.preferredBaseDir ? path3.normalize(options.preferredBaseDir) : void 0,
workspaceRoot: options.workspaceRoot ? path3.normalize(options.workspaceRoot) : void 0
};
const groups = /* @__PURE__ */ new Map();
for (const entry of entries) {
const entryDir = path3.dirname(entry);
const baseDir = resolveCssEntryBase(entryDir, normalizedOptions);
const bucket = groups.get(baseDir);
if (bucket) {
bucket.push(entry);
} else {
groups.set(baseDir, [entry]);
}
}
return groups;
}
function overrideTailwindcssPatcherOptionsForBase(options, baseDir, cssEntries) {
if (!options) {
return options;
}
if (isLegacyTailwindcssPatcherOptions(options)) {
const patchOptions = options.patch;
if (!patchOptions) {
return options;
}
const nextPatch = {
...patchOptions,
basedir: baseDir,
cwd: patchOptions.cwd ?? baseDir
};
if (patchOptions.tailwindcss) {
nextPatch.tailwindcss = {
...patchOptions.tailwindcss,
v4: {
...patchOptions.tailwindcss.v4 ?? {},
base: baseDir,
cssEntries
}
};
}
return {
...options,
patch: nextPatch
};
}
if (!isModernTailwindcssPatchOptions(options)) {
return options;
}
if (!options.tailwind) {
return options;
}
return {
...options,
tailwind: {
...options.tailwind,
v4: {
...options.tailwind.v4 ?? {},
base: baseDir,
cssEntries
}
}
};
}
function createPatcherForBase(baseDir, cssEntries, options) {
const {
tailwindcss,
tailwindcssPatcherOptions,
supportCustomLengthUnitsPatch
} = options;
const defaultTailwindcssConfig = {
cwd: baseDir,
v2: {
cwd: baseDir
},
v3: {
cwd: baseDir
},
v4: {
base: baseDir,
cssEntries
}
};
if (cssEntries?.length && (tailwindcss == null || tailwindcss.version == null)) {
defaultTailwindcssConfig.version = 4;
}
const mergedTailwindOptions = defuOverrideArray(
tailwindcss ?? {},
defaultTailwindcssConfig
);
if (!mergedTailwindOptions.v4) {
mergedTailwindOptions.v4 = {
base: baseDir,
cssEntries: cssEntries ?? []
};
} else {
mergedTailwindOptions.v4.base = baseDir;
if (cssEntries?.length) {
mergedTailwindOptions.v4.cssEntries = cssEntries;
} else if (!mergedTailwindOptions.v4.cssEntries) {
mergedTailwindOptions.v4.cssEntries = [];
}
}
const patchedOptions = overrideTailwindcssPatcherOptionsForBase(
tailwindcssPatcherOptions,
baseDir,
cssEntries ?? []
);
const configuredPackageName = tailwindcss?.packageName || tailwindcssPatcherOptions?.tailwind?.packageName || tailwindcssPatcherOptions?.patch?.tailwindcss?.packageName;
const configuredVersion = tailwindcss?.version || tailwindcssPatcherOptions?.tailwind?.version || tailwindcssPatcherOptions?.patch?.tailwindcss?.version || mergedTailwindOptions.version;
const isTailwindcss4Package = (packageName) => Boolean(
packageName && (packageName === "tailwindcss4" || packageName === "@tailwindcss/postcss" || packageName.includes("tailwindcss4"))
);
const isV4 = configuredVersion === 4 || mergedTailwindOptions.version === 4 || isTailwindcss4Package(configuredPackageName ?? mergedTailwindOptions.packageName);
const tailwindPackageConfigured = Boolean(configuredPackageName);
const shouldPatchV4PostcssPackage = isV4 && !tailwindPackageConfigured;
const packageCandidates = /* @__PURE__ */ new Set();
if (shouldPatchV4PostcssPackage) {
packageCandidates.add("@tailwindcss/postcss");
}
packageCandidates.add(
mergedTailwindOptions.packageName ?? configuredPackageName ?? "tailwindcss"
);
const patchers = Array.from(packageCandidates).map((packageName) => {
const tailwindOptionsForPackage = {
...mergedTailwindOptions,
packageName
};
return createTailwindcssPatcher({
basedir: baseDir,
supportCustomLengthUnitsPatch: supportCustomLengthUnitsPatch ?? true,
tailwindcss: tailwindOptionsForPackage,
tailwindcssPatcherOptions: patchedOptions
});
});
return patchers.length === 1 ? patchers[0] : createMultiTailwindcssPatcher(patchers);
}
function createMultiTailwindcssPatcher(patchers) {
if (patchers.length <= 1) {
return patchers[0];
}
const [first] = patchers;
const multiPatcher = {
packageInfo: first?.packageInfo,
majorVersion: first?.majorVersion,
options: first?.options,
async patch() {
let exposeContext;
let extendLengthUnits;
for (const patcher of patchers) {
const result = await patcher.patch();
if (result?.exposeContext && exposeContext == null) {
exposeContext = result.exposeContext;
}
if (result?.extendLengthUnits && extendLengthUnits == null) {
extendLengthUnits = result.extendLengthUnits;
}
}
return {
exposeContext,
extendLengthUnits
};
},
async getClassSet() {
const aggregated = /* @__PURE__ */ new Set();
for (const patcher of patchers) {
const current = await patcher.getClassSet();
for (const className of current) {
aggregated.add(className);
}
}
return aggregated;
},
async extract(options) {
const aggregatedSet = /* @__PURE__ */ new Set();
const aggregatedList = [];
let filename;
for (const patcher of patchers) {
const result = await patcher.extract(options);
if (!result) {
continue;
}
if (filename === void 0 && result.filename) {
filename = result.filename;
}
if (result.classList) {
for (const className of result.classList) {
if (!aggregatedSet.has(className)) {
aggregatedList.push(className);
}
aggregatedSet.add(className);
}
}
if (result.classSet) {
for (const className of result.classSet) {
aggregatedSet.add(className);
}
}
}
return {
classList: aggregatedList,
classSet: aggregatedSet,
filename
};
}
};
if (patchers.every((patcher) => typeof patcher.getClassSetSync === "function")) {
multiPatcher.getClassSetSync = () => {
const aggregated = /* @__PURE__ */ new Set();
for (const patcher of patchers) {
const current = patcher.getClassSetSync?.();
if (!current) {
continue;
}
for (const className of current) {
aggregated.add(className);
}
}
return aggregated;
};
}
return multiPatcher;
}
function tryCreateMultiTailwindcssPatcher(groups, options) {
if (groups.size <= 1) {
return void 0;
}
logger4.debug("detected multiple Tailwind CSS entry bases: %O", [...groups.keys()]);
const patchers = [];
for (const [baseDir, entries] of groups) {
patchers.push(createPatcherForBase(baseDir, entries, options));
}
return createMultiTailwindcssPatcher(patchers);
}
// src/context/tailwindcss.ts
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
import { createRequire as createRequire2 } from "module";
import path4 from "path";
import process2 from "process";
import { fileURLToPath as fileURLToPath2 } from "url";
import { logger as logger5 } from "@weapp-tailwindcss/logger";
var ENV_BASEDIR_KEYS = [
"WEAPP_TAILWINDCSS_BASEDIR",
"WEAPP_TAILWINDCSS_BASE_DIR",
"TAILWINDCSS_BASEDIR",
"TAILWINDCSS_BASE_DIR",
"UNI_INPUT_DIR",
"UNI_INPUT_ROOT",
"UNI_CLI_ROOT",
"UNI_APP_INPUT_DIR",
"INIT_CWD",
"PWD"
];
var GENERIC_ENV_BASEDIR_KEYS = /* @__PURE__ */ new Set(["INIT_CWD", "PWD"]);
function pickEnvBasedir() {
for (const key of ENV_BASEDIR_KEYS) {
const value = process2.env[key];
if (value && path4.isAbsolute(value)) {
return { key, value };
}
}
return void 0;
}
function pickPackageEnvBasedir() {
const packageJsonPath = process2.env.npm_package_json;
if (packageJsonPath) {
const packageDir = path4.dirname(packageJsonPath);
if (packageDir && path4.isAbsolute(packageDir)) {
return packageDir;
}
}
const localPrefix = process2.env.npm_config_local_prefix;
if (localPrefix && path4.isAbsolute(localPrefix)) {
return localPrefix;
}
return void 0;
}
function detectCallerBasedir() {
const stack = new Error("resolveTailwindcssBasedir stack probe").stack;
if (!stack) {
return void 0;
}
if (process2.env.WEAPP_TW_DEBUG_STACK === "1") {
logger5.debug("caller stack: %s", stack);
}
const lines = stack.split("\n");
for (const line of lines) {
const match = line.match(/\(([^)]+)\)/u) ?? line.match(/at\s+(\S.*)$/u);
const location = match?.[1];
if (!location) {
continue;
}
let filePath = location;
if (filePath.startsWith("file://")) {
try {
filePath = fileURLToPath2(filePath);
} catch {
continue;
}
}
const [candidate] = filePath.split(":");
const resolvedPath = path4.isAbsolute(filePath) ? filePath : candidate;
if (!path4.isAbsolute(resolvedPath)) {
continue;
}
if (resolvedPath.includes("node_modules") && resolvedPath.includes("weapp-tailwindcss")) {
continue;
}
try {
return path4.dirname(resolvedPath);
} catch {
continue;
}
}
return void 0;
}
function resolveTailwindcssBasedir(basedir, fallback) {
const envBasedirResult = pickEnvBasedir();
const envBasedir = envBasedirResult?.value;
const envBasedirKey = envBasedirResult?.key;
const envBasedirIsGeneric = envBasedirKey ? GENERIC_ENV_BASEDIR_KEYS.has(envBasedirKey) : false;
const packageEnvBasedir = pickPackageEnvBasedir();
const shouldDetectCaller = !envBasedir || envBasedirIsGeneric;
const callerBasedir = shouldDetectCaller ? detectCallerBasedir() : void 0;
const cwd = process2.cwd();
const anchor = envBasedir ?? packageEnvBasedir ?? fallback ?? callerBasedir ?? cwd;
const resolveRelative = (value) => path4.isAbsolute(value) ? path4.normalize(value) : path4.normalize(path4.resolve(anchor, value));
if (process2.env.WEAPP_TW_DEBUG_STACK === "1") {
logger5.debug("resolveTailwindcssBasedir anchor %O", {
basedir,
envBasedir,
envBasedirKey,
envBasedirIsGeneric,
packageEnvBasedir,
fallback,
callerBasedir,
npm_package_json: process2.env.npm_package_json,
cwd,
anchor
});
}
if (basedir && basedir.trim().length > 0) {
return resolveRelative(basedir);
}
if (envBasedir && !envBasedirIsGeneric) {
return path4.normalize(envBasedir);
}
if (fallback && fallback.trim().length > 0) {
return resolveRelative(fallback);
}
if (packageEnvBasedir) {
return path4.normalize(packageEnvBasedir);
}
if (callerBasedir) {
const normalizedCaller = path4.normalize(callerBasedir);
const librarySegment = `${path4.sep}weapp-tailwindcss${path4.sep}`;
if (!normalizedCaller.includes(librarySegment)) {
return normalizedCaller;
}
}
const packageName = process2.env.PNPM_PACKAGE_NAME;
if (packageName) {
try {
const anchorRequire = createRequire2(path4.join(anchor, "__resolve_tailwindcss_basedir__.cjs"));
const packageJsonPath = anchorRequire.resolve(`${packageName}/package.json`);
if (process2.env.WEAPP_TW_DEBUG_STACK === "1") {
logger5.debug("package basedir resolved from PNPM_PACKAGE_NAME: %s", packageJsonPath);
}
return path4.normalize(path4.dirname(packageJsonPath));
} catch {
if (process2.env.WEAPP_TW_DEBUG_STACK === "1") {
logger5.debug("failed to resolve package json for %s", packageName);
}
const workspaceRoot = findWorkspaceRoot(anchor);
if (workspaceRoot) {
const packageDir = findWorkspacePackageDir(workspaceRoot, packageName);
if (packageDir) {
return packageDir;
}
}
}
}
if (envBasedir) {
return path4.normalize(envBasedir);
}
return path4.normalize(cwd);
}
function isRaxWorkspace(appType, baseDir) {
if (appType === "rax") {
return true;
}
try {
const pkgPath = path4.join(baseDir, "package.json");
if (!existsSync3(pkgPath)) {
return false;
}
const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
const deps = {
...pkg.dependencies ?? {},
...pkg.devDependencies ?? {}
};
if (deps["rax-app"] || deps.rax) {
return true;
}
} catch {
return false;
}
return false;
}
function collectRaxStyleEntries(baseDir) {
const STYLE_CANDIDATES = [
"src/global.css",
"src/global.scss",
"src/global.less",
"src/global.sass",
"src/global.styl",
"src/global.stylus"
];
const discovered = [];
for (const relative of STYLE_CANDIDATES) {
const candidate = path4.resolve(baseDir, relative);
if (existsSync3(candidate)) {
discovered.push(path4.normalize(candidate));
}
}
return discovered;
}
function detectImplicitCssEntries(appType, baseDir) {
const baseCandidates = /* @__PURE__ */ new Set();
baseCandidates.add(path4.normalize(baseDir));
const envCandidates = [process2.cwd(), process2.env.INIT_CWD, process2.env.PWD];
for (const candidate of envCandidates) {
if (candidate) {
baseCandidates.add(path4.normalize(candidate));
}
}
for (const candidateBase of baseCandidates) {
if (!isRaxWorkspace(appType, candidateBase)) {
continue;
}
const entries = collectRaxStyleEntries(candidateBase);
if (entries.length) {
return entries;
}
}
return void 0;
}
function createTailwindcssPatcherFromContext(ctx) {
const {
tailwindcssBasedir,
supportCustomLengthUnitsPatch,
tailwindcss,
tailwindcssPatcherOptions,
cssEntries: rawCssEntries,
appType
} = ctx;
const absoluteCssEntryBasedir = guessBasedirFromEntries(rawCssEntries);
const resolvedTailwindcssBasedir = resolveTailwindcssBasedir(tailwindcssBasedir, absoluteCssEntryBasedir);
ctx.tailwindcssBasedir = resolvedTailwindcssBasedir;
logger5.debug("tailwindcss basedir resolved: %s", resolvedTailwindcssBasedir);
let normalizedCssEntries = normalizeCssEntries(rawCssEntries, resolvedTailwindcssBasedir);
if (!normalizedCssEntries) {
normalizedCssEntries = detectImplicitCssEntries(ctx.appType, resolvedTailwindcssBasedir);
}
if (normalizedCssEntries) {
ctx.cssEntries = normalizedCssEntries;
}
const patcherOptions = {
tailwindcss,
tailwindcssPatcherOptions,
supportCustomLengthUnitsPatch,
appType
};
const workspaceRoot = findWorkspaceRoot(resolvedTailwindcssBasedir) ?? (absoluteCssEntryBasedir ? findWorkspaceRoot(absoluteCssEntryBasedir) : void 0);
const groupedCssEntries = normalizedCssEntries ? groupCssEntriesByBase(normalizedCssEntries, {
preferredBaseDir: resolvedTailwindcssBasedir,
workspaceRoot
}) : void 0;
const multiPatcher = groupedCssEntries ? tryCreateMultiTailwindcssPatcher(groupedCssEntries, patcherOptions) : void 0;
if (multiPatcher) {
return multiPatcher;
}
if (groupedCssEntries?.size === 1) {
const firstGroup = groupedCssEntries.entries().next().value;
if (firstGroup) {
const [baseDir, entries] = firstGroup;
return createPatcherForBase(baseDir, entries, patcherOptions);
}
}
const effectiveCssEntries = normalizedCssEntries ?? rawCssEntries;
return createPatcherForBase(
resolvedTailwindcssBasedir,
effectiveCssEntries,
patcherOptions
);
}
export {
findWorkspaceRoot,
findNearestPackageRoot,
warnMissingCssEntries,
applyV4CssCalcDefaults,
resolveTailwindcssBasedir,
createTailwindcssPatcherFromContext,
logger
};