UNPKG

tailwindcss-patch

Version:

patch tailwindcss for exposing context and extract classes

960 lines (939 loc) 33.6 kB
// ../../node_modules/.pnpm/defu@6.1.4/node_modules/defu/dist/defu.mjs function isPlainObject(value) { if (value === null || typeof value !== "object") { return false; } const prototype = Object.getPrototypeOf(value); if (prototype !== null && prototype !== Object.prototype && Object.getPrototypeOf(prototype) !== null) { return false; } if (Symbol.iterator in value) { return false; } if (Symbol.toStringTag in value) { return Object.prototype.toString.call(value) === "[object Module]"; } return true; } function _defu(baseObject, defaults, namespace = ".", merger) { if (!isPlainObject(defaults)) { return _defu(baseObject, {}, namespace, merger); } const object = Object.assign({}, defaults); for (const key in baseObject) { if (key === "__proto__" || key === "constructor") { continue; } const value = baseObject[key]; if (value === null || value === void 0) { continue; } if (merger && merger(object, key, value, namespace)) { continue; } if (Array.isArray(value) && Array.isArray(object[key])) { object[key] = [...value, ...object[key]]; } else if (isPlainObject(value) && isPlainObject(object[key])) { object[key] = _defu( value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger ); } else { object[key] = value; } } return object; } function createDefu(merger) { return (...arguments_) => ( // eslint-disable-next-line unicorn/no-array-reduce arguments_.reduce((p, c) => _defu(p, c, "", merger), {}) ); } var defu = createDefu(); var defuFn = createDefu((object, key, currentValue) => { if (object[key] !== void 0 && typeof currentValue === "function") { object[key] = currentValue(object[key]); return true; } }); var defuArrayFn = createDefu((object, key, currentValue) => { if (Array.isArray(object[key]) && typeof currentValue === "function") { object[key] = currentValue(object[key]); return true; } }); // ../shared/src/utils.ts var defuOverrideArray = createDefu((obj, key, value) => { if (Array.isArray(obj[key]) && Array.isArray(value)) { obj[key] = value; return true; } }); var preserveClassNames = [ // https://tailwindcss.com/docs/transition-timing-function start // https://github.com/sonofmagic/tailwindcss-mangle/issues/21 "ease-out", "ease-linear", "ease-in", "ease-in-out" // https://tailwindcss.com/docs/transition-timing-function end ]; var preserveClassNamesMap = preserveClassNames.reduce((acc, cur) => { acc[cur] = true; return acc; }, {}); var acceptChars = [..."abcdefghijklmnopqrstuvwxyz"]; // src/logger.ts import { createConsola } from "consola"; var logger = createConsola(); var logger_default = logger; // src/core/cache.ts import process from "node:process"; import fs from "fs-extra"; import path from "pathe"; // src/constants.ts var pkgName = "tailwindcss-patch"; // src/core/cache.ts function getCacheOptions(options) { let cache; switch (typeof options) { case "undefined": { cache = { enable: false }; break; } case "boolean": { cache = { enable: options }; break; } case "object": { cache = { ...options, enable: true }; break; } } return cache; } var CacheManager = class { options; constructor(options = {}) { this.options = this.getOptions(options); } getOptions(options = {}) { const cwd = options.cwd ?? process.cwd(); const dir = options.dir ?? path.resolve(cwd, "node_modules/.cache", pkgName); const file = options.file ?? "index.json"; const filename = path.resolve(dir, file); return { cwd, dir, file, filename, strategy: "merge" }; } async write(data) { try { const { filename } = this.options; await fs.outputJSON(filename, [...data]); return filename; } catch (error) { logger_default.error(error); } } async read() { const { filename } = this.options; const isExisted = await fs.exists(filename); try { if (isExisted) { const data = await fs.readJSON(filename); return new Set(data ?? []); } } catch { try { isExisted && await fs.remove(filename); } catch (error) { logger_default.error(error); } } return /* @__PURE__ */ new Set(); } }; // src/defaults.ts import process2 from "node:process"; function getDefaultPatchOptions() { return { packageName: "tailwindcss", applyPatches: { exportContext: true, extendLengthUnits: false }, overwrite: true, filter: () => true }; } function getPatchOptions(options) { return defu( options, { output: { removeUniversalSelector: true }, basedir: process2.cwd() }, getDefaultPatchOptions() ); } // src/core/patches/exportContext/index.ts import fs2 from "fs-extra"; import path2 from "pathe"; // src/core/patches/exportContext/postcss-v2.ts import * as t from "@babel/types"; // src/babel/index.ts import _babelGenerate from "@babel/generator"; import _babelTraverse from "@babel/traverse"; import { parse, parseExpression } from "@babel/parser"; function _interopDefaultCompat(e) { return e && typeof e === "object" && "default" in e ? e.default : e; } var generate = _interopDefaultCompat(_babelGenerate); var traverse = _interopDefaultCompat(_babelTraverse); // src/core/patches/exportContext/postcss-v2.ts function inspectProcessTailwindFeaturesReturnContext(content) { const ast = parse(content, { sourceType: "unambiguous" }); let hasPatched = false; traverse(ast, { FunctionDeclaration(p) { const n = p.node; if (n.id?.name === "processTailwindFeatures" && n.body.body.length === 1 && t.isReturnStatement(n.body.body[0])) { const rts = n.body.body[0]; if (t.isFunctionExpression(rts.argument)) { const body = rts.argument.body.body; const lastStatement = body[body.length - 1]; hasPatched = t.isReturnStatement(lastStatement) && t.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"; if (!hasPatched) { const rts2 = t.returnStatement(t.identifier("context")); body.push(rts2); } } } } }); return { code: hasPatched ? content : generate(ast).code, hasPatched }; } function inspectPostcssPlugin(content) { const ast = parse(content); const exportKey = "contextRef"; const variableName = "contextRef"; const valueKey = "value"; let hasPatched = false; traverse(ast, { Program(p) { const n = p.node; const idx = n.body.findIndex((x) => { return t.isFunctionDeclaration(x) && x.id?.name === "_default"; }); if (idx > -1) { const prevStatement = n.body[idx - 1]; const lastStatement = n.body[idx - 2]; const hasPatchedCondition0 = prevStatement && t.isVariableDeclaration(prevStatement) && prevStatement.declarations.length === 1 && t.isIdentifier(prevStatement.declarations[0].id) && prevStatement.declarations[0].id.name === variableName; const hasPatchedCondition1 = t.isExpressionStatement(lastStatement) && t.isAssignmentExpression(lastStatement.expression) && t.isIdentifier(lastStatement.expression.right) && lastStatement.expression.right.name === variableName; hasPatched = hasPatchedCondition0 || hasPatchedCondition1; if (!hasPatched) { const statement = t.variableDeclaration("var", [ t.variableDeclarator(t.identifier(variableName), t.objectExpression([t.objectProperty(t.identifier(valueKey), t.arrayExpression())])) ]); n.body.splice( idx, 0, statement, // exports.contextRef = contextRef; t.expressionStatement( t.assignmentExpression( "=", t.memberExpression(t.identifier("exports"), t.identifier(exportKey)), t.identifier(variableName) ) ) ); } } }, FunctionDeclaration(p) { if (hasPatched) { return; } const n = p.node; if (n.id?.name === "_default" && n.body.body.length === 1 && t.isReturnStatement(n.body.body[0])) { const returnStatement3 = n.body.body[0]; if (t.isCallExpression(returnStatement3.argument) && t.isMemberExpression(returnStatement3.argument.callee) && t.isArrayExpression(returnStatement3.argument.callee.object)) { const targetFn = returnStatement3.argument.callee.object.elements[1]; if (t.isFunctionExpression(targetFn)) { const targetBlockStatement = targetFn.body; if (t.isExpressionStatement(targetBlockStatement.body[0]) && t.isAssignmentExpression(targetBlockStatement.body[0].expression) && t.isNumericLiteral(targetBlockStatement.body[0].expression.right)) { hasPatched = true; return; } const lastStatement = targetBlockStatement.body[targetBlockStatement.body.length - 1]; if (t.isExpressionStatement(lastStatement)) { const newExpressionStatement = t.expressionStatement( t.callExpression( t.memberExpression( t.memberExpression(t.identifier(variableName), t.identifier("value")), t.identifier("push") ), [lastStatement.expression] ) ); targetBlockStatement.body[targetBlockStatement.body.length - 1] = newExpressionStatement; } const ifIdx = targetBlockStatement.body.findIndex((x) => t.isIfStatement(x)); if (ifIdx > -1) { const ifRoot = targetBlockStatement.body[ifIdx]; if (t.isBlockStatement(ifRoot.consequent) && ifRoot.consequent.body[1] && t.isForOfStatement(ifRoot.consequent.body[1])) { const forOf = ifRoot.consequent.body[1]; if (t.isBlockStatement(forOf.body) && forOf.body.body.length === 1 && t.isIfStatement(forOf.body.body[0])) { const if2 = forOf.body.body[0]; if (t.isBlockStatement(if2.consequent) && if2.consequent.body.length === 1 && t.isExpressionStatement(if2.consequent.body[0])) { const target = if2.consequent.body[0]; const newExpressionStatement = t.expressionStatement( t.callExpression(t.memberExpression(t.memberExpression(t.identifier(variableName), t.identifier("value")), t.identifier("push")), [target.expression]) ); if2.consequent.body[0] = newExpressionStatement; } } } } targetBlockStatement.body.unshift( // contentRef.value = [] // t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(variableName), t.identifier(valueKey)), t.arrayExpression())) // contentRef.value.length = 0 t.expressionStatement( t.assignmentExpression( "=", t.memberExpression(t.memberExpression(t.identifier(variableName), t.identifier(valueKey)), t.identifier("length")), t.numericLiteral(0) ) ) ); } } } } }); return { code: hasPatched ? content : generate(ast).code, hasPatched }; } // src/core/patches/exportContext/postcss-v3.ts import * as t2 from "@babel/types"; function inspectProcessTailwindFeaturesReturnContext2(content) { const ast = parse(content); let hasPatched = false; traverse(ast, { FunctionDeclaration(p) { const n = p.node; if (n.id?.name === "processTailwindFeatures" && n.body.body.length === 1 && t2.isReturnStatement(n.body.body[0])) { const rts = n.body.body[0]; if (t2.isFunctionExpression(rts.argument)) { const body = rts.argument.body.body; const lastStatement = body[body.length - 1]; hasPatched = t2.isReturnStatement(lastStatement) && t2.isIdentifier(lastStatement.argument) && lastStatement.argument.name === "context"; if (!hasPatched) { const rts2 = t2.returnStatement(t2.identifier("context")); body.push(rts2); } } } } }); return { code: hasPatched ? content : generate(ast).code, hasPatched }; } function inspectPostcssPlugin2(content) { const ast = parse(content); const exportKey = "contextRef"; const variableName = "contextRef"; const valueKey = "value"; let hasPatched = false; traverse(ast, { Program(p) { const n = p.node; const idx = n.body.findIndex((x) => { return t2.isExpressionStatement(x) && t2.isAssignmentExpression(x.expression) && t2.isMemberExpression(x.expression.left) && t2.isFunctionExpression(x.expression.right) && x.expression.right.id?.name === "tailwindcss"; }); if (idx > -1) { const prevStatement = n.body[idx - 1]; const lastStatement = n.body[n.body.length - 1]; const hasPatchedCondition0 = prevStatement && t2.isVariableDeclaration(prevStatement) && prevStatement.declarations.length === 1 && t2.isIdentifier(prevStatement.declarations[0].id) && prevStatement.declarations[0].id.name === variableName; const hasPatchedCondition1 = t2.isExpressionStatement(lastStatement) && t2.isAssignmentExpression(lastStatement.expression) && t2.isIdentifier(lastStatement.expression.right) && lastStatement.expression.right.name === variableName; hasPatched = hasPatchedCondition0 || hasPatchedCondition1; if (!hasPatched) { const statement = t2.variableDeclaration("const", [ t2.variableDeclarator(t2.identifier(variableName), t2.objectExpression([t2.objectProperty(t2.identifier(valueKey), t2.arrayExpression())])) ]); n.body.splice(idx, 0, statement); n.body.push( t2.expressionStatement( t2.assignmentExpression( "=", t2.memberExpression(t2.memberExpression(t2.identifier("module"), t2.identifier("exports")), t2.identifier(exportKey)), t2.identifier(variableName) ) ) ); } } }, FunctionExpression(p) { if (hasPatched) { return; } const n = p.node; if (n.id?.name === "tailwindcss" && n.body.body.length === 1 && t2.isReturnStatement(n.body.body[0])) { const returnStatement3 = n.body.body[0]; if (t2.isObjectExpression(returnStatement3.argument) && returnStatement3.argument.properties.length === 2) { const properties = returnStatement3.argument.properties; if (t2.isObjectProperty(properties[0]) && t2.isObjectProperty(properties[1])) { const keyMatched = t2.isIdentifier(properties[0].key) && properties[0].key.name === "postcssPlugin"; const pluginsMatched = t2.isIdentifier(properties[1].key) && properties[1].key.name === "plugins"; if (pluginsMatched && keyMatched && t2.isCallExpression(properties[1].value) && t2.isMemberExpression(properties[1].value.callee) && t2.isArrayExpression(properties[1].value.callee.object)) { const pluginsCode = properties[1].value.callee.object.elements; if (pluginsCode[1] && t2.isFunctionExpression(pluginsCode[1])) { const targetBlockStatement = pluginsCode[1].body; const lastStatement = targetBlockStatement.body[targetBlockStatement.body.length - 1]; if (t2.isExpressionStatement(lastStatement)) { const newExpressionStatement = t2.expressionStatement( t2.callExpression( t2.memberExpression( t2.memberExpression(t2.identifier(variableName), t2.identifier("value")), t2.identifier("push") ), [lastStatement.expression] ) ); targetBlockStatement.body[targetBlockStatement.body.length - 1] = newExpressionStatement; } const ifIdx = targetBlockStatement.body.findIndex((x) => t2.isIfStatement(x)); if (ifIdx > -1) { const ifRoot = targetBlockStatement.body[ifIdx]; if (t2.isBlockStatement(ifRoot.consequent) && ifRoot.consequent.body[1] && t2.isForOfStatement(ifRoot.consequent.body[1])) { const forOf = ifRoot.consequent.body[1]; if (t2.isBlockStatement(forOf.body) && forOf.body.body.length === 1 && t2.isIfStatement(forOf.body.body[0])) { const if2 = forOf.body.body[0]; if (t2.isBlockStatement(if2.consequent) && if2.consequent.body.length === 1 && t2.isExpressionStatement(if2.consequent.body[0])) { const target = if2.consequent.body[0]; const newExpressionStatement = t2.expressionStatement( t2.callExpression(t2.memberExpression(t2.memberExpression(t2.identifier(variableName), t2.identifier("value")), t2.identifier("push")), [target.expression]) ); if2.consequent.body[0] = newExpressionStatement; } } } } targetBlockStatement.body.unshift( // contentRef.value = [] // t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(variableName), t.identifier(valueKey)), t.arrayExpression())) // contentRef.value.length = 0 t2.expressionStatement( t2.assignmentExpression( "=", t2.memberExpression(t2.memberExpression(t2.identifier(variableName), t2.identifier(valueKey)), t2.identifier("length")), t2.numericLiteral(0) ) ) ); } } } } } } // BlockStatement(p) { // const n = p.node // if (start && p.parent.type === 'FunctionExpression' && !p.parent.id) { // n.body.unshift(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.identifier(variableName), t.identifier(valueKey)), t.arrayExpression()))) // } // } }); return { code: hasPatched ? content : generate(ast).code, hasPatched }; } // src/core/patches/exportContext/index.ts function monkeyPatchForExposingContextV3(twDir, opt) { const k0 = "lib/processTailwindFeatures.js"; const processTailwindFeaturesFilePath = path2.resolve(twDir, k0); const processTailwindFeaturesContent = fs2.readFileSync(processTailwindFeaturesFilePath, "utf8"); const result = {}; if (processTailwindFeaturesContent) { const { code, hasPatched } = inspectProcessTailwindFeaturesReturnContext2(processTailwindFeaturesContent); if (!hasPatched && opt.overwrite) { fs2.writeFileSync(processTailwindFeaturesFilePath, code, { encoding: "utf8" }); logger_default.success("patch tailwindcss processTailwindFeatures for return context successfully!"); } result[k0] = code; } let injectFilepath; let k1; const try0 = "lib/plugin.js"; const try1 = "lib/index.js"; const pluginFilePath = path2.resolve(twDir, try0); const indexFilePath = path2.resolve(twDir, try1); if (fs2.existsSync(pluginFilePath)) { k1 = try0; injectFilepath = pluginFilePath; } else if (fs2.existsSync(indexFilePath)) { k1 = try1; injectFilepath = indexFilePath; } if (injectFilepath && k1) { const pluginContent = fs2.readFileSync(injectFilepath, "utf8"); if (pluginContent) { const { code, hasPatched } = inspectPostcssPlugin2(pluginContent); if (!hasPatched && opt.overwrite) { fs2.writeFileSync(injectFilepath, code, { encoding: "utf8" }); logger_default.success("patch tailwindcss for expose runtime context successfully!"); } result[k1] = code; } return result; } } function monkeyPatchForExposingContextV2(twDir, opt) { const k0 = "lib/jit/processTailwindFeatures.js"; const processTailwindFeaturesFilePath = path2.resolve(twDir, k0); const processTailwindFeaturesContent = fs2.readFileSync(processTailwindFeaturesFilePath, "utf8"); const result = {}; if (processTailwindFeaturesContent) { const { code, hasPatched } = inspectProcessTailwindFeaturesReturnContext(processTailwindFeaturesContent); if (!hasPatched && opt.overwrite) { fs2.writeFileSync(processTailwindFeaturesFilePath, code, { encoding: "utf8" }); logger_default.success("patch tailwindcss processTailwindFeatures for return content successfully!"); } result[k0] = code; } const k1 = "lib/jit/index.js"; const indexFilePath = path2.resolve(twDir, k1); const pluginContent = fs2.readFileSync(indexFilePath, "utf8"); if (pluginContent) { const { code, hasPatched } = inspectPostcssPlugin(pluginContent); if (!hasPatched && opt.overwrite) { fs2.writeFileSync(indexFilePath, code, { encoding: "utf8" }); logger_default.success("patch tailwindcss for expose runtime content successfully!"); } result[k1] = code; } return result; } // src/core/patches/supportCustomUnits/index.ts import * as t3 from "@babel/types"; import fs3 from "fs-extra"; import path3 from "pathe"; function findAstNode(content, options) { const { variableName, units } = options; const ast = parse(content); let arrayRef; let changed = false; traverse(ast, { Identifier(path7) { if (path7.node.name === variableName && t3.isVariableDeclarator(path7.parent) && t3.isArrayExpression(path7.parent.init)) { arrayRef = path7.parent.init; const set = new Set(path7.parent.init.elements.map((x) => x.value)); for (let i = 0; i < units.length; i++) { const unit = units[i]; if (!set.has(unit)) { path7.parent.init.elements = path7.parent.init.elements.map((x) => { if (t3.isStringLiteral(x)) { return { type: x?.type, value: x?.value }; } return x; }); path7.parent.init.elements.push({ type: "StringLiteral", value: unit }); changed = true; } } } } }); return { arrayRef, changed }; } function monkeyPatchForSupportingCustomUnit(rootDir, options) { const opts = defuOverrideArray(options, { units: ["rpx"], lengthUnitsFilePath: "lib/util/dataTypes.js", variableName: "lengthUnits", overwrite: true }); const { lengthUnitsFilePath, overwrite, destPath } = opts; const dataTypesFilePath = path3.resolve(rootDir, lengthUnitsFilePath); const dataTypesFileContent = fs3.readFileSync(dataTypesFilePath, { encoding: "utf8" }); const { arrayRef, changed } = findAstNode(dataTypesFileContent, opts); if (arrayRef && changed) { const { code } = generate(arrayRef, { jsescOption: { quotes: "single" } }); if (arrayRef.start && arrayRef.end) { const prev = dataTypesFileContent.slice(0, arrayRef.start); const next = dataTypesFileContent.slice(arrayRef.end); const newCode = prev + code + next; if (overwrite) { fs3.writeFileSync(destPath ?? dataTypesFilePath, newCode, { encoding: "utf8" }); logger_default.success("patch tailwindcss for custom length unit successfully!"); } } return { [opts.lengthUnitsFilePath]: code }; } } // src/core/runtime.ts import { createRequire } from "node:module"; import path4 from "pathe"; import { gte } from "semver"; var require2 = createRequire(import.meta.url); function internalPatch(pkgJsonPath, options) { if (pkgJsonPath) { const pkgJson = require2(pkgJsonPath); const twDir = path4.dirname(pkgJsonPath); options.version = pkgJson.version; if (gte(pkgJson.version, "3.0.0")) { let result = {}; if (options.applyPatches?.exportContext) { result = monkeyPatchForExposingContextV3(twDir, options); } if (options.applyPatches?.extendLengthUnits) { try { Object.assign(result ?? {}, monkeyPatchForSupportingCustomUnit(twDir, defu(options.applyPatches.extendLengthUnits === true ? void 0 : options.applyPatches.extendLengthUnits, { overwrite: options.overwrite }))); } catch { } } return result; } else if (gte(pkgJson.version, "2.0.0")) { if (options.applyPatches?.exportContext) { return monkeyPatchForExposingContextV2(twDir, options); } } } } // src/core/patcher.ts import { createRequire as createRequire3 } from "node:module"; import process5 from "node:process"; import fs4 from "fs-extra"; import { getPackageInfoSync } from "local-pkg"; import path6 from "pathe"; // src/utils.ts function isObject(val) { return val !== null && typeof val === "object" && Array.isArray(val) === false; } // src/core/candidates.ts import process3 from "node:process"; function importNode() { return import("@tailwindcss/node"); } function importOxide() { return import("@tailwindcss/oxide"); } async function extractRawCandidates(sources) { const { Scanner } = await importOxide(); const scanner = new Scanner({ sources }); const candidates = scanner.scan(); return candidates; } async function extractValidCandidates(options) { const cwd = process3.cwd(); const { sources, base, css } = defuOverrideArray( // @ts-ignore options, { css: '@import "tailwindcss";', base: cwd, sources: [ { base: cwd, pattern: "**/*" } ] } ); const { __unstable__loadDesignSystem } = await importNode(); const designSystem = await __unstable__loadDesignSystem(css, { base }); const candidates = await extractRawCandidates(sources); const validCandidates = candidates.filter( (rawCandidate) => designSystem.parseCandidate(rawCandidate).length > 0 ); return validCandidates; } // src/core/postcss.ts import { createRequire as createRequire2 } from "node:module"; import process4 from "node:process"; import path5 from "pathe"; import postcss from "postcss"; import { loadConfig } from "tailwindcss-config"; var require3 = createRequire2(import.meta.url); async function processTailwindcss(options) { const { config: userConfig, cwd, majorVersion, postcssPlugin } = defu(options, { cwd: process4.cwd(), majorVersion: 3 }); let config = userConfig; if (!(typeof config === "string" && path5.isAbsolute(config))) { const result = await loadConfig({ cwd }); if (!result) { throw new Error(`No TailwindCSS Config found in: ${cwd}`); } config = result.filepath; } const targetPostcssPlugin = postcssPlugin ?? (majorVersion === 4 ? "@tailwindcss/postcss" : "tailwindcss"); if (majorVersion === 4) { return await postcss([ require3(targetPostcssPlugin)({ config }) ]).process("@import 'tailwindcss';", { from: void 0 }); } return await postcss([ require3(targetPostcssPlugin)({ config }) ]).process("@tailwind base;@tailwind components;@tailwind utilities;", { from: void 0 }); } // src/core/patcher.ts var require4 = createRequire3(import.meta.url); var TailwindcssPatcher = class { rawOptions; cacheOptions; patchOptions; patch; cacheManager; packageInfo; majorVersion; filter; constructor(options = {}) { this.rawOptions = options; this.cacheOptions = getCacheOptions(options.cache); this.patchOptions = getPatchOptions(options.patch); this.cacheManager = new CacheManager(this.cacheOptions); this.filter = function filter(className) { if (this.patchOptions.output?.removeUniversalSelector && className === "*") { return false; } return Boolean(this.patchOptions.filter?.(className)); }; const packageInfo = getPackageInfoSync( this.patchOptions.packageName ?? "tailwindcss", this.patchOptions.resolve ); if (!packageInfo) { throw new Error("tailwindcss not found"); } if (packageInfo.version) { this.majorVersion = Number.parseInt(packageInfo.version[0]); } if (this.patchOptions.tailwindcss?.version) { this.majorVersion = this.patchOptions.tailwindcss.version; } this.packageInfo = packageInfo; this.patch = () => { if (this.majorVersion === 3 || this.majorVersion === 2) { try { return internalPatch(this.packageInfo?.packageJsonPath, this.patchOptions); } catch (error) { logger_default.error(`patch tailwindcss failed: ${error.message}`); } } }; } setCache(set) { if (this.cacheOptions.enable) { return this.cacheManager.write(set); } } getCache() { return this.cacheManager.read(); } getContexts() { if (this.packageInfo) { const distPath = path6.join(this.packageInfo.rootPath, "lib"); let injectFilePath; if (this.majorVersion === 2) { injectFilePath = path6.join(distPath, "jit/index.js"); } else if (this.majorVersion === 3) { injectFilePath = path6.join(distPath, "plugin.js"); if (!fs4.existsSync(injectFilePath)) { injectFilePath = path6.join(distPath, "index.js"); } } if (injectFilePath) { const mo = require4(injectFilePath); if (mo.contextRef) { return mo.contextRef.value; } } } return []; } getClassCaches() { const contexts = this.getContexts(); return contexts.filter((x) => isObject(x)).map((x) => x.classCache); } async getClassCacheSet() { const classSet = /* @__PURE__ */ new Set(); const { tailwindcss } = this.patchOptions; if (this.majorVersion === 4) { const { v4 } = tailwindcss ?? {}; if (Array.isArray(v4?.cssEntries)) { const results = (await Promise.all( v4.cssEntries.map(async (x) => { if (await fs4.exists(x)) { const css = await fs4.readFile(x, "utf8"); return css; } return false; }) )).filter((x) => x); for (const css of results) { const candidates = await extractValidCandidates({ base: v4?.base, css, sources: v4?.sources?.map((x) => { return { base: x.base ?? v4?.base ?? process5.cwd(), pattern: x.pattern }; }) }); for (const candidate of candidates) { this.filter?.(candidate) && classSet.add(candidate); } } } else { const candidates = await extractValidCandidates({ base: v4?.base, css: v4?.css, sources: v4?.sources?.map((x) => { return { base: x.base ?? v4?.base ?? process5.cwd(), pattern: x.pattern }; }) }); for (const candidate of candidates) { this.filter?.(candidate) && classSet.add(candidate); } } } else { const classCaches = this.getClassCaches(); for (const classCacheMap of classCaches) { const keys = classCacheMap.keys(); for (const key of keys) { const v = key.toString(); this.filter?.(v) && classSet.add(v); } } } return classSet; } /** * @description 在多个 tailwindcss 上下文时,这个方法将被执行多次,所以策略上应该使用 append */ async getClassSet() { const cacheStrategy = this.cacheOptions.strategy ?? "merge"; const set = await this.getClassCacheSet(); if (cacheStrategy === "overwrite") { set.size > 0 && this.setCache(set); } else if (cacheStrategy === "merge") { const cacheSet = await this.getCache(); if (cacheSet) { for (const x of cacheSet) { set.add(x); } } this.setCache(set); } return set; } async extract() { const { output, tailwindcss } = this.patchOptions; if (output && tailwindcss) { const { filename, loose } = output; if (this.majorVersion === 3 || this.majorVersion === 2) { await processTailwindcss({ ...tailwindcss, majorVersion: this.majorVersion }); } const set = await this.getClassSet(); if (filename) { const classList = [...set]; await fs4.outputJSON(filename, classList, { spaces: loose ? 2 : void 0 }); return { filename, classList }; } } } extractValidCandidates = extractValidCandidates; }; export { defuOverrideArray, logger_default, getCacheOptions, CacheManager, getPatchOptions, monkeyPatchForExposingContextV3, monkeyPatchForExposingContextV2, monkeyPatchForSupportingCustomUnit, internalPatch, TailwindcssPatcher };