tailwindcss-patch
Version:
patch tailwindcss for exposing context and extract classes
960 lines (939 loc) • 33.6 kB
JavaScript
// ../../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
};