tailwindcss-patch
Version:
patch tailwindcss for exposing context and extract classes
561 lines (542 loc) • 20 kB
text/typescript
import { SourceEntry } from '@tailwindcss/oxide';
import postcss, { Node, Rule } from 'postcss';
import { Config } from 'tailwindcss';
import { PackageResolvingOptions, PackageInfo } from 'local-pkg';
import { TailwindLocatorOptions, TailwindNextOptions, getConfig } from '@tailwindcss-mangle/config';
export { defineConfig } from '@tailwindcss-mangle/config';
import { Command, CAC } from 'cac';
import * as consola from 'consola';
type CacheStrategy = 'merge' | 'overwrite';
type CacheDriver = 'file' | 'memory' | 'noop';
/**
* Configures how the Tailwind class cache is stored and where it lives on disk.
*/
interface CacheUserOptions {
/** Whether caching is enabled. */
enabled?: boolean;
/** Working directory used when resolving cache paths. */
cwd?: string;
/** Directory where cache files are written. */
dir?: string;
/**
* Cache filename. Defaults to `class-cache.json` inside the derived cache folder
* when omitted.
*/
file?: string;
/** Strategy used when merging new class lists with an existing cache. */
strategy?: CacheStrategy;
/** Backend used to persist the cache (`file`, `memory`, or `noop`). Defaults to `file`. */
driver?: CacheDriver;
}
/**
* Controls how extracted class lists are written to disk.
*/
interface OutputUserOptions {
/** Whether to produce an output file. */
enabled?: boolean;
/** Optional absolute or relative path to the output file. */
file?: string;
/** Output format, defaults to JSON when omitted. */
format?: 'json' | 'lines';
/** Pretty-print spacing (truthy value enables indentation). */
pretty?: number | boolean;
/** Whether to strip the universal selector (`*`) from the final list. */
removeUniversalSelector?: boolean;
}
/**
* Options controlling how Tailwind contexts are exposed during runtime patching.
*/
interface ExposeContextUserOptions {
/** Name of the property used to reference an exposed context. */
refProperty?: string;
}
/**
* Extends the built-in length-unit patch with custom defaults.
*/
interface ExtendLengthUnitsUserOptions extends Partial<ILengthUnitsPatchOptions> {
/** Enables or disables the length-unit patch. */
enabled?: boolean;
}
/**
* Feature switches that toggle optional Tailwind patch capabilities.
*/
interface FeatureUserOptions {
/** Whether to expose runtime Tailwind contexts (or configure how they are exposed). */
exposeContext?: boolean | ExposeContextUserOptions;
/** Extends the length-unit patch or disables it entirely. */
extendLengthUnits?: false | ExtendLengthUnitsUserOptions;
}
/**
* Shared configuration used for Tailwind v2/v3 patching flows.
*/
interface TailwindConfigUserOptions {
/** Path to a Tailwind config file when auto-detection is insufficient. */
config?: string;
/** Custom working directory used when resolving config-relative paths. */
cwd?: string;
/** Optional PostCSS plugin name to use instead of the default. */
postcssPlugin?: string;
}
/**
* Additional configuration specific to Tailwind CSS v4 extraction.
*/
interface TailwindV4UserOptions {
/** Base directory used when resolving v4 content sources and configs. */
base?: string;
/** Raw CSS passed directly to the v4 design system. */
css?: string;
/** Set of CSS entry files that should be scanned for `@config` directives. */
cssEntries?: string[];
/** Overrides the content sources scanned by the oxide scanner. */
sources?: SourceEntry[];
}
/**
* High-level Tailwind patch configuration shared across versions.
*/
interface TailwindUserOptions extends TailwindConfigUserOptions {
/**
* Optional hint for picking the patch strategy.
* When omitted we infer from the installed Tailwind CSS package version.
*/
version?: 2 | 3 | 4;
/** Tailwind package name if the project uses a fork. */
packageName?: string;
/** Package resolution options forwarded to `local-pkg`. */
resolve?: PackageResolvingOptions;
/** Overrides applied when patching Tailwind CSS v2. */
v2?: TailwindConfigUserOptions;
/** Overrides applied when patching Tailwind CSS v3. */
v3?: TailwindConfigUserOptions;
/** Options specific to Tailwind CSS v4 patching. */
v4?: TailwindV4UserOptions;
}
/**
* Root configuration consumed by the Tailwind CSS patch runner.
*/
interface TailwindcssPatchOptions {
/**
* Base directory used when resolving Tailwind resources.
* Defaults to `process.cwd()`.
*/
cwd?: string;
/** Whether to overwrite generated artifacts (e.g., caches, outputs). */
overwrite?: boolean;
/** Tailwind-specific configuration grouped by major version. */
tailwind?: TailwindUserOptions;
/** Feature toggles for optional helpers. */
features?: FeatureUserOptions;
/** Optional function that filters final class names. */
filter?: (className: string) => boolean;
/** Cache configuration or boolean to enable/disable quickly. */
cache?: boolean | CacheUserOptions;
/** Output configuration or boolean to inherits defaults. */
output?: OutputUserOptions;
}
/**
* Stable shape for output configuration after normalization.
*/
interface NormalizedOutputOptions {
enabled: boolean;
file?: string;
format: 'json' | 'lines';
pretty: number | false;
removeUniversalSelector: boolean;
}
/**
* Stable cache configuration used internally after defaults are applied.
*/
interface NormalizedCacheOptions {
enabled: boolean;
cwd: string;
dir: string;
file: string;
path: string;
strategy: CacheStrategy;
driver: CacheDriver;
}
/** Tracks whether runtime contexts should be exposed and via which property. */
interface NormalizedExposeContextOptions {
enabled: boolean;
refProperty: string;
}
/** Normalized representation of the extend-length-units feature flag. */
interface NormalizedExtendLengthUnitsOptions extends ILengthUnitsPatchOptions {
enabled: boolean;
}
/** Normalized Tailwind v4 configuration consumed by runtime helpers. */
interface NormalizedTailwindV4Options {
base: string;
configuredBase?: string;
css?: string;
cssEntries: string[];
sources: SourceEntry[];
hasUserDefinedSources: boolean;
}
/**
* Tailwind configuration ready for consumption by the runtime after normalization.
*/
interface NormalizedTailwindConfigOptions extends TailwindConfigUserOptions {
packageName: string;
versionHint?: 2 | 3 | 4;
resolve?: PackageResolvingOptions;
v2?: TailwindConfigUserOptions;
v3?: TailwindConfigUserOptions;
v4?: NormalizedTailwindV4Options;
}
/** Grouped normalized feature flags. */
interface NormalizedFeatureOptions {
exposeContext: NormalizedExposeContextOptions;
extendLengthUnits: NormalizedExtendLengthUnitsOptions | null;
}
/** Final normalized shape consumed throughout the patch runtime. */
interface NormalizedTailwindcssPatchOptions {
projectRoot: string;
overwrite: boolean;
tailwind: NormalizedTailwindConfigOptions;
features: NormalizedFeatureOptions;
output: NormalizedOutputOptions;
cache: NormalizedCacheOptions;
filter: (className: string) => boolean;
}
type TailwindcssClassCacheEntry = Rule | {
layer: string;
options: Record<string, any>;
sort: Record<string, any>;
};
type TailwindcssClassCache = Map<string, TailwindcssClassCacheEntry[]>;
interface TailwindcssRuntimeContext {
applyClassCache: Map<any, any>;
candidateRuleCache: Map<string, Set<[
{
arbitrary: any;
index: any;
layer: string;
options: any[];
parallelIndex: any;
parentLayer: string;
variants: any;
},
Node
]>>;
candidateRuleMap: Map<string | string, [object, Node][]>;
changedContent: any[];
classCache: TailwindcssClassCache;
disposables: any[];
getClassList: (...args: any[]) => any;
getClassOrder: (...args: any[]) => any;
getVariants: (...args: any[]) => any;
markInvalidUtilityCandidate: (...args: any[]) => any;
markInvalidUtilityNode: (...args: any[]) => any;
notClassCache: Set<string>;
offsets: {
layerPositions: object;
offsets: object;
reservedVariantBits: any;
variantOffsets: Map<string, any>;
};
postCssNodeCache: Map<object, [Node]>;
ruleCache: Set<[object, Node]>;
stylesheetCache: Record<string, Set<any>>;
tailwindConfig: Config;
userConfigPath: string | null;
variantMap: Map<string, [[object, (...args: any[]) => unknown]]>;
variantOptions: Map<string, object>;
}
interface ExtractResult {
classList: string[];
classSet: Set<string>;
filename?: string;
}
interface TailwindTokenLocation {
rawCandidate: string;
file: string;
relativeFile: string;
extension: string;
start: number;
end: number;
length: number;
line: number;
column: number;
lineText: string;
}
type TailwindTokenFileKey = 'relative' | 'absolute';
interface TailwindTokenReport {
entries: TailwindTokenLocation[];
filesScanned: number;
sources: SourceEntry[];
skippedFiles: {
file: string;
reason: string;
}[];
}
type TailwindTokenByFileMap = Record<string, TailwindTokenLocation[]>;
interface TailwindPatchRuntime {
options: NormalizedTailwindcssPatchOptions;
majorVersion: 2 | 3 | 4;
}
interface ILengthUnitsPatchOptions {
units: string[];
lengthUnitsFilePath?: string;
variableName?: string;
overwrite?: boolean;
destPath?: string;
}
type PatchCheckStatus = 'applied' | 'not-applied' | 'skipped' | 'unsupported';
type PatchName = 'exposeContext' | 'extendLengthUnits';
interface PatchStatusEntry {
name: PatchName;
status: PatchCheckStatus;
reason?: string;
files: string[];
}
interface PatchStatusReport {
package: {
name?: string;
version?: string;
root: string;
};
majorVersion: 2 | 3 | 4;
entries: PatchStatusEntry[];
}
interface ExposeContextPatchParams {
rootDir: string;
refProperty: string;
overwrite: boolean;
majorVersion: 2 | 3;
}
interface ExposeContextPatchResult {
applied: boolean;
files: Record<string, string>;
}
declare function applyExposeContextPatch(params: ExposeContextPatchParams): ExposeContextPatchResult;
declare function applyExtendLengthUnitsPatchV3(rootDir: string, options: NormalizedExtendLengthUnitsOptions): {
changed: boolean;
code: undefined;
} | {
changed: boolean;
code: string;
};
interface V4FilePatch {
file: string;
code: string;
hasPatched: boolean;
}
interface V4Candidate extends V4FilePatch {
match: RegExpExecArray;
}
declare function applyExtendLengthUnitsPatchV4(rootDir: string, options: NormalizedExtendLengthUnitsOptions): {
changed: boolean;
files: V4Candidate[];
};
interface PatchRunnerResult {
exposeContext?: ReturnType<typeof applyExposeContextPatch>;
extendLengthUnits?: ReturnType<typeof applyExtendLengthUnitsPatchV3> | ReturnType<typeof applyExtendLengthUnitsPatchV4>;
}
interface LegacyCacheOptions {
dir?: string;
cwd?: string;
file?: string;
strategy?: 'merge' | 'overwrite';
enabled?: boolean;
}
interface LegacyOutputOptions {
filename?: string;
loose?: boolean;
removeUniversalSelector?: boolean;
}
interface LegacyTailwindcssOptions {
version?: 2 | 3 | 4;
v2?: TailwindLocatorOptions;
v3?: TailwindLocatorOptions;
v4?: TailwindNextOptions;
config?: string;
cwd?: string;
}
interface LegacyPatchOptions {
packageName?: string;
output?: LegacyOutputOptions;
tailwindcss?: LegacyTailwindcssOptions;
overwrite?: boolean;
applyPatches?: {
exportContext?: boolean;
extendLengthUnits?: boolean | ILengthUnitsPatchOptions;
};
filter?: (className: string) => boolean;
cwd?: string;
resolve?: PackageResolvingOptions;
}
interface LegacyTailwindcssPatcherOptions {
cache?: LegacyCacheOptions | boolean;
patch?: LegacyPatchOptions;
}
interface ExtractValidCandidatesOption {
sources?: SourceEntry[];
base?: string;
baseFallbacks?: string[];
css?: string;
cwd?: string;
}
declare function extractRawCandidatesWithPositions(content: string, extension?: string): Promise<{
rawCandidate: string;
start: number;
end: number;
}[]>;
declare function extractRawCandidates(sources?: SourceEntry[]): Promise<string[]>;
declare function extractValidCandidates(options?: ExtractValidCandidatesOption): Promise<string[]>;
interface ExtractProjectCandidatesOptions {
cwd?: string;
sources?: SourceEntry[];
}
declare function extractProjectCandidatesWithPositions(options?: ExtractProjectCandidatesOptions): Promise<TailwindTokenReport>;
declare function groupTokensByFile(report: TailwindTokenReport, options?: {
key?: TailwindTokenFileKey;
stripAbsolutePaths?: boolean;
}): TailwindTokenByFileMap;
type TailwindMajorVersion = 2 | 3 | 4;
type TailwindcssPatcherInitOptions = TailwindcssPatchOptions | LegacyTailwindcssPatcherOptions;
declare class TailwindcssPatcher {
readonly options: NormalizedTailwindcssPatchOptions;
readonly packageInfo: PackageInfo;
readonly majorVersion: TailwindMajorVersion;
private readonly cacheStore;
constructor(options?: TailwindcssPatcherInitOptions);
patch(): Promise<PatchRunnerResult>;
getPatchStatus(): Promise<PatchStatusReport>;
getContexts(): TailwindcssRuntimeContext[];
private runTailwindBuildIfNeeded;
private collectClassSet;
private mergeWithCache;
private mergeWithCacheSync;
getClassSet(): Promise<Set<string>>;
getClassSetSync(): Set<string> | undefined;
extract(options?: {
write?: boolean;
}): Promise<ExtractResult>;
extractValidCandidates: typeof extractValidCandidates;
collectContentTokens(options?: {
cwd?: string;
sources?: SourceEntry[];
}): Promise<TailwindTokenReport>;
collectContentTokensByFile(options?: {
cwd?: string;
sources?: SourceEntry[];
key?: TailwindTokenFileKey;
stripAbsolutePaths?: boolean;
}): Promise<TailwindTokenByFileMap>;
}
declare class CacheStore {
private readonly options;
private readonly driver;
private memoryCache;
constructor(options: NormalizedCacheOptions);
private ensureDir;
private ensureDirSync;
private createTempPath;
private replaceCacheFile;
private replaceCacheFileSync;
private cleanupTempFile;
private cleanupTempFileSync;
write(data: Set<string>): Promise<string | undefined>;
writeSync(data: Set<string>): string | undefined;
read(): Promise<Set<string>>;
readSync(): Set<string>;
}
declare const logger: consola.ConsolaInstance;
type TailwindcssPatchCommand = 'install' | 'extract' | 'tokens' | 'init' | 'status';
declare const tailwindcssPatchCommands: TailwindcssPatchCommand[];
type TokenOutputFormat = 'json' | 'lines' | 'grouped-json';
type TokenGroupKey = 'relative' | 'absolute';
type CacOptionConfig = Parameters<Command['option']>[2];
interface TailwindcssPatchCommandOptionDefinition {
flags: string;
description?: string;
config?: CacOptionConfig;
}
interface TailwindcssPatchCommandOptions {
name?: string;
aliases?: string[];
description?: string;
optionDefs?: TailwindcssPatchCommandOptionDefinition[];
appendDefaultOptions?: boolean;
}
interface BaseCommandArgs {
cwd: string;
}
interface InstallCommandArgs extends BaseCommandArgs {
}
interface ExtractCommandArgs extends BaseCommandArgs {
output?: string;
format?: 'json' | 'lines';
css?: string;
write?: boolean;
}
interface TokensCommandArgs extends BaseCommandArgs {
output?: string;
format?: TokenOutputFormat;
groupKey?: TokenGroupKey;
write?: boolean;
}
interface InitCommandArgs extends BaseCommandArgs {
}
interface StatusCommandArgs extends BaseCommandArgs {
json?: boolean;
}
interface TailwindcssPatchCommandArgMap {
install: InstallCommandArgs;
extract: ExtractCommandArgs;
tokens: TokensCommandArgs;
init: InitCommandArgs;
status: StatusCommandArgs;
}
interface TailwindcssPatchCommandResultMap {
install: void;
extract: ExtractResult;
tokens: TailwindTokenReport;
init: void;
status: PatchStatusReport;
}
interface TailwindcssPatchCommandContext<TCommand extends TailwindcssPatchCommand> {
cli: CAC;
command: Command;
commandName: TCommand;
args: TailwindcssPatchCommandArgMap[TCommand];
cwd: string;
logger: typeof logger;
loadConfig: () => ReturnType<typeof getConfig>;
loadPatchOptions: (overrides?: TailwindcssPatchOptions) => Promise<TailwindcssPatchOptions>;
createPatcher: (overrides?: TailwindcssPatchOptions) => Promise<TailwindcssPatcher>;
}
type TailwindcssPatchCommandHandler<TCommand extends TailwindcssPatchCommand> = (context: TailwindcssPatchCommandContext<TCommand>, next: () => Promise<TailwindcssPatchCommandResultMap[TCommand]>) => Promise<TailwindcssPatchCommandResultMap[TCommand]> | TailwindcssPatchCommandResultMap[TCommand];
type TailwindcssPatchCommandHandlerMap = Partial<{
[K in TailwindcssPatchCommand]: TailwindcssPatchCommandHandler<K>;
}>;
interface TailwindcssPatchCliMountOptions {
commandPrefix?: string;
commands?: TailwindcssPatchCommand[];
commandOptions?: Partial<Record<TailwindcssPatchCommand, TailwindcssPatchCommandOptions>>;
commandHandlers?: TailwindcssPatchCommandHandlerMap;
}
interface TailwindcssPatchCliOptions {
name?: string;
mountOptions?: TailwindcssPatchCliMountOptions;
}
declare function mountTailwindcssPatchCommands(cli: CAC, options?: TailwindcssPatchCliMountOptions): CAC;
declare function createTailwindcssPatchCli(options?: TailwindcssPatchCliOptions): CAC;
declare function normalizeOptions(options?: TailwindcssPatchOptions): NormalizedTailwindcssPatchOptions;
interface PatchStatusContext {
packageInfo: PackageInfo;
options: NormalizedTailwindcssPatchOptions;
majorVersion: 2 | 3 | 4;
}
declare function getPatchStatusReport(context: PatchStatusContext): PatchStatusReport;
declare function collectClassesFromContexts(contexts: TailwindcssRuntimeContext[], filter: (className: string) => boolean): Set<string>;
declare function collectClassesFromTailwindV4(options: NormalizedTailwindcssPatchOptions): Promise<Set<string>>;
declare function loadRuntimeContexts(packageInfo: PackageInfo, majorVersion: 2 | 3 | 4, refProperty: string): TailwindcssRuntimeContext[];
interface TailwindBuildOptions {
cwd: string;
config?: string;
majorVersion: 2 | 3 | 4;
postcssPlugin?: string;
}
declare function runTailwindBuild(options: TailwindBuildOptions): Promise<postcss.Result<postcss.Root>>;
export { CacheStore, type CacheStrategy, type ExtractResult, type ILengthUnitsPatchOptions, type NormalizedTailwindcssPatchOptions, type PatchCheckStatus, type PatchName, type PatchStatusEntry, type PatchStatusReport, type TailwindPatchRuntime, type TailwindTokenByFileMap, type TailwindTokenFileKey, type TailwindTokenLocation, type TailwindTokenReport, type TailwindcssClassCache, type TailwindcssPatchCliMountOptions, type TailwindcssPatchCliOptions, type TailwindcssPatchCommand, type TailwindcssPatchCommandContext, type TailwindcssPatchCommandHandler, type TailwindcssPatchCommandHandlerMap, type TailwindcssPatchCommandOptionDefinition, type TailwindcssPatchCommandOptions, type TailwindcssPatchOptions, TailwindcssPatcher, type TailwindcssRuntimeContext, collectClassesFromContexts, collectClassesFromTailwindV4, createTailwindcssPatchCli, extractProjectCandidatesWithPositions, extractRawCandidates, extractRawCandidatesWithPositions, extractValidCandidates, getPatchStatusReport, groupTokensByFile, loadRuntimeContexts, logger, mountTailwindcssPatchCommands, normalizeOptions, runTailwindBuild, tailwindcssPatchCommands };