tailwindcss-patch 8.3.0 → 8.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -6
- package/dist/{chunk-SN7IO2IS.mjs → chunk-C3YPPFE6.mjs} +355 -168
- package/dist/{chunk-7ZWFVW77.js → chunk-FKEOVCUS.js} +354 -167
- package/dist/cli.js +2 -2
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +64 -6
- package/dist/index.d.ts +64 -6
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,40 @@ cli.help()
|
|
|
59
59
|
cli.parse()
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
#### Custom command hooks
|
|
63
|
+
|
|
64
|
+
Hosts can override per-command lifecycles by supplying `commandHandlers`. Each handler receives a context object (with the resolved `cwd`, parsed `args`, memoized `loadConfig`/`createPatcher` helpers, and the shared `logger`) plus a `next()` callback that runs the built-in action.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
mountTailwindcssPatchCommands(cli, {
|
|
68
|
+
commandHandlers: {
|
|
69
|
+
install: async (ctx) => {
|
|
70
|
+
const patcher = await ctx.createPatcher()
|
|
71
|
+
await clearTailwindcssPatcherCache(ctx.cwd)
|
|
72
|
+
await patcher.patch()
|
|
73
|
+
await saveCliPatchTargetRecord({ cwd: ctx.cwd })
|
|
74
|
+
},
|
|
75
|
+
extract: async (ctx, next) => {
|
|
76
|
+
const result = await next() // run the default extract implementation
|
|
77
|
+
ctx.logger.success(`[host] wrote ${result.classList.length} classes`)
|
|
78
|
+
return result
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
commandOptions: {
|
|
82
|
+
extract: {
|
|
83
|
+
description: 'Localised extract command',
|
|
84
|
+
appendDefaultOptions: false,
|
|
85
|
+
optionDefs: [
|
|
86
|
+
{ flags: '--entry <file>', description: 'Tailwind CSS entry file' },
|
|
87
|
+
{ flags: '--preview', description: 'Print a preview instead of writing' },
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Skip `next()` to fully replace a command (e.g. custom `init` or cache clearing before `install`). Calling `next()` returns the default result—`ExtractResult`, `TailwindTokenReport`, etc.—so hosts can log metadata or feed it into their own telemetry without re-implementing the commands.
|
|
95
|
+
|
|
62
96
|
### Extract options
|
|
63
97
|
|
|
64
98
|
| Flag | Description |
|
|
@@ -73,13 +107,13 @@ The CLI loads `tailwindcss-patch.config.ts` via `@tailwindcss-mangle/config`. Le
|
|
|
73
107
|
|
|
74
108
|
### Token report options
|
|
75
109
|
|
|
76
|
-
| Flag
|
|
77
|
-
|
|
|
78
|
-
| `--cwd <dir>`
|
|
79
|
-
| `--output <file>`
|
|
110
|
+
| Flag | Description |
|
|
111
|
+
| -------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
112
|
+
| `--cwd <dir>` | Use a different working directory when loading configuration. |
|
|
113
|
+
| `--output <file>` | Override the token report target file (defaults to `.tw-patch/tw-token-report.json`). |
|
|
80
114
|
| `--format <json\|lines\|grouped-json>` | Choose between a JSON payload (default), newline summaries, or JSON grouped by file path. |
|
|
81
|
-
| `--group-key <relative\|absolute>`
|
|
82
|
-
| `--no-write`
|
|
115
|
+
| `--group-key <relative\|absolute>` | Control grouped-json keys (defaults to relative paths). |
|
|
116
|
+
| `--no-write` | Skip writing to disk and only print a preview. |
|
|
83
117
|
|
|
84
118
|
## Programmatic API
|
|
85
119
|
|
|
@@ -5,6 +5,9 @@ var logger_default = logger;
|
|
|
5
5
|
|
|
6
6
|
// src/cache/store.ts
|
|
7
7
|
import fs from "fs-extra";
|
|
8
|
+
function isErrnoException(error) {
|
|
9
|
+
return error instanceof Error && typeof error.code === "string";
|
|
10
|
+
}
|
|
8
11
|
var CacheStore = class {
|
|
9
12
|
constructor(options) {
|
|
10
13
|
this.options = options;
|
|
@@ -55,6 +58,9 @@ var CacheStore = class {
|
|
|
55
58
|
return new Set(data.filter((item) => typeof item === "string"));
|
|
56
59
|
}
|
|
57
60
|
} catch (error) {
|
|
61
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
62
|
+
return /* @__PURE__ */ new Set();
|
|
63
|
+
}
|
|
58
64
|
logger_default.warn("Unable to read Tailwind class cache, removing invalid file.", error);
|
|
59
65
|
try {
|
|
60
66
|
await fs.remove(this.options.path);
|
|
@@ -78,6 +84,9 @@ var CacheStore = class {
|
|
|
78
84
|
return new Set(data.filter((item) => typeof item === "string"));
|
|
79
85
|
}
|
|
80
86
|
} catch (error) {
|
|
87
|
+
if (isErrnoException(error) && error.code === "ENOENT") {
|
|
88
|
+
return /* @__PURE__ */ new Set();
|
|
89
|
+
}
|
|
81
90
|
logger_default.warn("Unable to read Tailwind class cache, removing invalid file.", error);
|
|
82
91
|
try {
|
|
83
92
|
fs.removeSync(this.options.path);
|
|
@@ -387,7 +396,7 @@ function normalizeTailwindV4Options(v4, fallbackBase) {
|
|
|
387
396
|
const hasUserDefinedSources = Boolean(userSources?.length);
|
|
388
397
|
const sources = hasUserDefinedSources ? userSources : [
|
|
389
398
|
{
|
|
390
|
-
base,
|
|
399
|
+
base: fallbackBase,
|
|
391
400
|
pattern: "**/*",
|
|
392
401
|
negated: false
|
|
393
402
|
}
|
|
@@ -516,13 +525,6 @@ async function collectClassesFromTailwindV4(options) {
|
|
|
516
525
|
if (!v4Options.sources?.length) {
|
|
517
526
|
return void 0;
|
|
518
527
|
}
|
|
519
|
-
if (!v4Options.hasUserDefinedSources && !resolvedConfiguredBase) {
|
|
520
|
-
return v4Options.sources.map((source) => ({
|
|
521
|
-
base,
|
|
522
|
-
pattern: source.pattern,
|
|
523
|
-
negated: source.negated
|
|
524
|
-
}));
|
|
525
|
-
}
|
|
526
528
|
return v4Options.sources.map((source) => ({
|
|
527
529
|
base: source.base ?? base,
|
|
528
530
|
pattern: source.pattern,
|
|
@@ -1656,156 +1658,143 @@ var acceptChars = [..."abcdefghijklmnopqrstuvwxyz"];
|
|
|
1656
1658
|
import cac from "cac";
|
|
1657
1659
|
import fs8 from "fs-extra";
|
|
1658
1660
|
import path9 from "pathe";
|
|
1659
|
-
var tailwindcssPatchCommands = [
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
];
|
|
1665
|
-
function createTailwindcssPatchCli(options = {}) {
|
|
1666
|
-
const cli = cac(options.name ?? "tw-patch");
|
|
1667
|
-
mountTailwindcssPatchCommands(cli, options.mountOptions);
|
|
1668
|
-
return cli;
|
|
1661
|
+
var tailwindcssPatchCommands = ["install", "extract", "tokens", "init"];
|
|
1662
|
+
var TOKEN_FORMATS = ["json", "lines", "grouped-json"];
|
|
1663
|
+
var DEFAULT_TOKEN_REPORT = ".tw-patch/tw-token-report.json";
|
|
1664
|
+
function formatTokenLine(entry) {
|
|
1665
|
+
return `${entry.relativeFile}:${entry.line}:${entry.column} ${entry.rawCandidate} (${entry.start}-${entry.end})`;
|
|
1669
1666
|
}
|
|
1670
|
-
function
|
|
1671
|
-
const
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
},
|
|
1685
|
-
extract() {
|
|
1686
|
-
const { name, aliases } = resolveCommandNames("extract", options, prefix);
|
|
1687
|
-
const command = cli.command(name, "Collect generated class names into a cache file").option("--cwd <dir>", "Working directory", { default: process5.cwd() }).option("--output <file>", "Override output file path").option("--format <format>", "Output format (json|lines)").option("--css <file>", "Tailwind CSS entry CSS when using v4").option("--no-write", "Skip writing to disk").action(async (args) => {
|
|
1688
|
-
const overrides = {};
|
|
1689
|
-
if (args.output || args.format) {
|
|
1690
|
-
overrides.output = {
|
|
1691
|
-
file: args.output,
|
|
1692
|
-
format: args.format
|
|
1693
|
-
};
|
|
1694
|
-
}
|
|
1695
|
-
if (args.css) {
|
|
1696
|
-
overrides.tailwind = {
|
|
1697
|
-
v4: {
|
|
1698
|
-
cssEntries: [args.css]
|
|
1699
|
-
}
|
|
1700
|
-
};
|
|
1701
|
-
}
|
|
1702
|
-
const patchOptions = await loadPatchOptions(args.cwd, overrides);
|
|
1703
|
-
const patcher = new TailwindcssPatcher(patchOptions);
|
|
1704
|
-
const result = await patcher.extract({ write: args.write });
|
|
1705
|
-
if (result.filename) {
|
|
1706
|
-
logger_default.success(`Collected ${result.classList.length} classes \u2192 ${result.filename}`);
|
|
1707
|
-
} else {
|
|
1708
|
-
logger_default.success(`Collected ${result.classList.length} classes.`);
|
|
1709
|
-
}
|
|
1710
|
-
});
|
|
1711
|
-
aliases.forEach((alias) => command.alias(alias));
|
|
1712
|
-
},
|
|
1713
|
-
tokens() {
|
|
1714
|
-
const { name, aliases } = resolveCommandNames("tokens", options, prefix);
|
|
1715
|
-
const command = cli.command(name, "Extract Tailwind tokens with file/position metadata").option("--cwd <dir>", "Working directory", { default: process5.cwd() }).option("--output <file>", "Override output file path", { default: ".tw-patch/tw-token-report.json" }).option("--format <format>", "Output format (json|lines|grouped-json)", { default: "json" }).option("--group-key <key>", "Grouping key for grouped-json output (relative|absolute)", { default: "relative" }).option("--no-write", "Skip writing to disk").action(async (args) => {
|
|
1716
|
-
const patchOptions = await loadPatchOptions(args.cwd);
|
|
1717
|
-
const patcher = new TailwindcssPatcher(patchOptions);
|
|
1718
|
-
const report = await patcher.collectContentTokens();
|
|
1719
|
-
const shouldWrite = args.write ?? true;
|
|
1720
|
-
let format = args.format ?? "json";
|
|
1721
|
-
if (!TOKEN_FORMATS.includes(format)) {
|
|
1722
|
-
format = "json";
|
|
1723
|
-
}
|
|
1724
|
-
const targetFile = args.output ?? ".tw-patch/tw-token-report.json";
|
|
1725
|
-
const groupKey = args.groupKey === "absolute" ? "absolute" : "relative";
|
|
1726
|
-
const buildGrouped = () => groupTokensByFile(report, {
|
|
1727
|
-
key: groupKey,
|
|
1728
|
-
stripAbsolutePaths: groupKey !== "absolute"
|
|
1729
|
-
});
|
|
1730
|
-
const grouped = format === "grouped-json" ? buildGrouped() : null;
|
|
1731
|
-
const resolveGrouped = () => grouped ?? buildGrouped();
|
|
1732
|
-
if (shouldWrite) {
|
|
1733
|
-
const target = path9.resolve(targetFile);
|
|
1734
|
-
await fs8.ensureDir(path9.dirname(target));
|
|
1735
|
-
if (format === "json") {
|
|
1736
|
-
await fs8.writeJSON(target, report, { spaces: 2 });
|
|
1737
|
-
} else if (format === "grouped-json") {
|
|
1738
|
-
await fs8.writeJSON(target, resolveGrouped(), { spaces: 2 });
|
|
1739
|
-
} else {
|
|
1740
|
-
const lines = report.entries.map(formatTokenLine);
|
|
1741
|
-
await fs8.writeFile(target, `${lines.join("\n")}
|
|
1742
|
-
`, "utf8");
|
|
1743
|
-
}
|
|
1744
|
-
logger_default.success(
|
|
1745
|
-
`Collected ${report.entries.length} tokens (${format}) \u2192 ${target.replace(process5.cwd(), ".")}`
|
|
1746
|
-
);
|
|
1747
|
-
} else {
|
|
1748
|
-
logger_default.success(`Collected ${report.entries.length} tokens from ${report.filesScanned} files.`);
|
|
1749
|
-
if (format === "lines") {
|
|
1750
|
-
const preview = report.entries.slice(0, 5).map(formatTokenLine).join("\n");
|
|
1751
|
-
if (preview) {
|
|
1752
|
-
logger_default.log("");
|
|
1753
|
-
logger_default.info(preview);
|
|
1754
|
-
if (report.entries.length > 5) {
|
|
1755
|
-
logger_default.info(`\u2026and ${report.entries.length - 5} more.`);
|
|
1756
|
-
}
|
|
1757
|
-
}
|
|
1758
|
-
} else if (format === "grouped-json") {
|
|
1759
|
-
const map = resolveGrouped();
|
|
1760
|
-
const { preview, moreFiles } = formatGroupedPreview(map);
|
|
1761
|
-
if (preview) {
|
|
1762
|
-
logger_default.log("");
|
|
1763
|
-
logger_default.info(preview);
|
|
1764
|
-
if (moreFiles > 0) {
|
|
1765
|
-
logger_default.info(`\u2026and ${moreFiles} more files.`);
|
|
1766
|
-
}
|
|
1767
|
-
}
|
|
1768
|
-
} else {
|
|
1769
|
-
const previewEntries = report.entries.slice(0, 3);
|
|
1770
|
-
if (previewEntries.length) {
|
|
1771
|
-
logger_default.log("");
|
|
1772
|
-
logger_default.info(JSON.stringify(previewEntries, null, 2));
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
if (report.skippedFiles.length) {
|
|
1777
|
-
logger_default.warn("Skipped files:");
|
|
1778
|
-
for (const skipped of report.skippedFiles) {
|
|
1779
|
-
logger_default.warn(` \u2022 ${skipped.file} (${skipped.reason})`);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
});
|
|
1783
|
-
aliases.forEach((alias) => command.alias(alias));
|
|
1784
|
-
},
|
|
1785
|
-
init() {
|
|
1786
|
-
const { name, aliases } = resolveCommandNames("init", options, prefix);
|
|
1787
|
-
const command = cli.command(name, "Generate a tailwindcss-patch config file").option("--cwd <dir>", "Working directory", { default: process5.cwd() }).action(async (args) => {
|
|
1788
|
-
await initConfig(args.cwd);
|
|
1789
|
-
logger_default.success(`\u2728 ${CONFIG_NAME}.config.ts initialized!`);
|
|
1790
|
-
});
|
|
1791
|
-
aliases.forEach((alias) => command.alias(alias));
|
|
1792
|
-
}
|
|
1667
|
+
function formatGroupedPreview(map, limit = 3) {
|
|
1668
|
+
const files = Object.keys(map);
|
|
1669
|
+
if (!files.length) {
|
|
1670
|
+
return { preview: "", moreFiles: 0 };
|
|
1671
|
+
}
|
|
1672
|
+
const lines = files.slice(0, limit).map((file) => {
|
|
1673
|
+
const tokens = map[file];
|
|
1674
|
+
const sample = tokens.slice(0, 3).map((token) => token.rawCandidate).join(", ");
|
|
1675
|
+
const suffix = tokens.length > 3 ? ", \u2026" : "";
|
|
1676
|
+
return `${file}: ${tokens.length} tokens (${sample}${suffix})`;
|
|
1677
|
+
});
|
|
1678
|
+
return {
|
|
1679
|
+
preview: lines.join("\n"),
|
|
1680
|
+
moreFiles: Math.max(0, files.length - limit)
|
|
1793
1681
|
};
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
}
|
|
1682
|
+
}
|
|
1683
|
+
function resolveCwd(rawCwd) {
|
|
1684
|
+
if (!rawCwd) {
|
|
1685
|
+
return process5.cwd();
|
|
1799
1686
|
}
|
|
1800
|
-
return
|
|
1687
|
+
return path9.resolve(rawCwd);
|
|
1688
|
+
}
|
|
1689
|
+
function createDefaultRunner(factory) {
|
|
1690
|
+
let promise;
|
|
1691
|
+
return () => {
|
|
1692
|
+
if (!promise) {
|
|
1693
|
+
promise = factory();
|
|
1694
|
+
}
|
|
1695
|
+
return promise;
|
|
1696
|
+
};
|
|
1801
1697
|
}
|
|
1802
|
-
async function
|
|
1698
|
+
async function loadPatchOptionsForCwd(cwd, overrides) {
|
|
1803
1699
|
const { config } = await getConfig(cwd);
|
|
1804
1700
|
const legacyConfig = config;
|
|
1805
1701
|
const base = config?.registry ? fromUnifiedConfig(config.registry) : legacyConfig?.patch ? fromLegacyOptions({ patch: legacyConfig.patch }) : {};
|
|
1806
1702
|
const merged = defu(overrides ?? {}, base);
|
|
1807
1703
|
return merged;
|
|
1808
1704
|
}
|
|
1705
|
+
function createCommandContext(cli, command, commandName, args, cwd) {
|
|
1706
|
+
let cachedOptions;
|
|
1707
|
+
let cachedPatcher;
|
|
1708
|
+
let cachedConfig;
|
|
1709
|
+
const loadPatchOptionsForContext = (overrides) => {
|
|
1710
|
+
if (overrides) {
|
|
1711
|
+
return loadPatchOptionsForCwd(cwd, overrides);
|
|
1712
|
+
}
|
|
1713
|
+
if (!cachedOptions) {
|
|
1714
|
+
cachedOptions = loadPatchOptionsForCwd(cwd);
|
|
1715
|
+
}
|
|
1716
|
+
return cachedOptions;
|
|
1717
|
+
};
|
|
1718
|
+
const createPatcherForContext = async (overrides) => {
|
|
1719
|
+
if (overrides) {
|
|
1720
|
+
const patchOptions = await loadPatchOptionsForCwd(cwd, overrides);
|
|
1721
|
+
return new TailwindcssPatcher(patchOptions);
|
|
1722
|
+
}
|
|
1723
|
+
if (!cachedPatcher) {
|
|
1724
|
+
cachedPatcher = loadPatchOptionsForContext().then((options) => new TailwindcssPatcher(options));
|
|
1725
|
+
}
|
|
1726
|
+
return cachedPatcher;
|
|
1727
|
+
};
|
|
1728
|
+
return {
|
|
1729
|
+
cli,
|
|
1730
|
+
command,
|
|
1731
|
+
commandName,
|
|
1732
|
+
args,
|
|
1733
|
+
cwd,
|
|
1734
|
+
logger: logger_default,
|
|
1735
|
+
loadConfig: () => {
|
|
1736
|
+
if (!cachedConfig) {
|
|
1737
|
+
cachedConfig = getConfig(cwd);
|
|
1738
|
+
}
|
|
1739
|
+
return cachedConfig;
|
|
1740
|
+
},
|
|
1741
|
+
loadPatchOptions: loadPatchOptionsForContext,
|
|
1742
|
+
createPatcher: createPatcherForContext
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
function createCwdOptionDefinition(description = "Working directory") {
|
|
1746
|
+
return {
|
|
1747
|
+
flags: "--cwd <dir>",
|
|
1748
|
+
description,
|
|
1749
|
+
config: { default: process5.cwd() }
|
|
1750
|
+
};
|
|
1751
|
+
}
|
|
1752
|
+
function buildDefaultCommandDefinitions() {
|
|
1753
|
+
return {
|
|
1754
|
+
install: {
|
|
1755
|
+
description: "Apply Tailwind CSS runtime patches",
|
|
1756
|
+
optionDefs: [createCwdOptionDefinition()]
|
|
1757
|
+
},
|
|
1758
|
+
extract: {
|
|
1759
|
+
description: "Collect generated class names into a cache file",
|
|
1760
|
+
optionDefs: [
|
|
1761
|
+
createCwdOptionDefinition(),
|
|
1762
|
+
{ flags: "--output <file>", description: "Override output file path" },
|
|
1763
|
+
{ flags: "--format <format>", description: "Output format (json|lines)" },
|
|
1764
|
+
{ flags: "--css <file>", description: "Tailwind CSS entry CSS when using v4" },
|
|
1765
|
+
{ flags: "--no-write", description: "Skip writing to disk" }
|
|
1766
|
+
]
|
|
1767
|
+
},
|
|
1768
|
+
tokens: {
|
|
1769
|
+
description: "Extract Tailwind tokens with file/position metadata",
|
|
1770
|
+
optionDefs: [
|
|
1771
|
+
createCwdOptionDefinition(),
|
|
1772
|
+
{ flags: "--output <file>", description: "Override output file path", config: { default: DEFAULT_TOKEN_REPORT } },
|
|
1773
|
+
{
|
|
1774
|
+
flags: "--format <format>",
|
|
1775
|
+
description: "Output format (json|lines|grouped-json)",
|
|
1776
|
+
config: { default: "json" }
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
flags: "--group-key <key>",
|
|
1780
|
+
description: "Grouping key for grouped-json output (relative|absolute)",
|
|
1781
|
+
config: { default: "relative" }
|
|
1782
|
+
},
|
|
1783
|
+
{ flags: "--no-write", description: "Skip writing to disk" }
|
|
1784
|
+
]
|
|
1785
|
+
},
|
|
1786
|
+
init: {
|
|
1787
|
+
description: "Generate a tailwindcss-patch config file",
|
|
1788
|
+
optionDefs: [createCwdOptionDefinition()]
|
|
1789
|
+
}
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
function addPrefixIfMissing(value, prefix) {
|
|
1793
|
+
if (!prefix || value.startsWith(prefix)) {
|
|
1794
|
+
return value;
|
|
1795
|
+
}
|
|
1796
|
+
return `${prefix}${value}`;
|
|
1797
|
+
}
|
|
1809
1798
|
function resolveCommandNames(command, mountOptions, prefix) {
|
|
1810
1799
|
const override = mountOptions.commandOptions?.[command];
|
|
1811
1800
|
const baseName = override?.name ?? command;
|
|
@@ -1813,30 +1802,228 @@ function resolveCommandNames(command, mountOptions, prefix) {
|
|
|
1813
1802
|
const aliases = (override?.aliases ?? []).map((alias) => addPrefixIfMissing(alias, prefix));
|
|
1814
1803
|
return { name, aliases };
|
|
1815
1804
|
}
|
|
1816
|
-
function
|
|
1817
|
-
if (!
|
|
1818
|
-
return
|
|
1805
|
+
function resolveOptionDefinitions(defaults, override) {
|
|
1806
|
+
if (!override) {
|
|
1807
|
+
return defaults;
|
|
1819
1808
|
}
|
|
1820
|
-
|
|
1809
|
+
const appendDefaults = override.appendDefaultOptions ?? true;
|
|
1810
|
+
const customDefs = override.optionDefs ?? [];
|
|
1811
|
+
if (!appendDefaults) {
|
|
1812
|
+
return customDefs;
|
|
1813
|
+
}
|
|
1814
|
+
if (customDefs.length === 0) {
|
|
1815
|
+
return defaults;
|
|
1816
|
+
}
|
|
1817
|
+
return [...defaults, ...customDefs];
|
|
1821
1818
|
}
|
|
1822
|
-
function
|
|
1823
|
-
|
|
1819
|
+
function applyCommandOptions(command, optionDefs) {
|
|
1820
|
+
for (const option of optionDefs) {
|
|
1821
|
+
command.option(option.flags, option.description ?? "", option.config);
|
|
1822
|
+
}
|
|
1824
1823
|
}
|
|
1825
|
-
function
|
|
1826
|
-
const
|
|
1827
|
-
|
|
1828
|
-
|
|
1824
|
+
function runWithCommandHandler(cli, command, commandName, args, handler, defaultHandler) {
|
|
1825
|
+
const cwd = resolveCwd(args.cwd);
|
|
1826
|
+
const context = createCommandContext(cli, command, commandName, args, cwd);
|
|
1827
|
+
const runDefault = createDefaultRunner(() => defaultHandler(context));
|
|
1828
|
+
if (!handler) {
|
|
1829
|
+
return runDefault();
|
|
1830
|
+
}
|
|
1831
|
+
return handler(context, runDefault);
|
|
1832
|
+
}
|
|
1833
|
+
function resolveCommandMetadata(command, mountOptions, prefix, defaults) {
|
|
1834
|
+
const names = resolveCommandNames(command, mountOptions, prefix);
|
|
1835
|
+
const definition = defaults[command];
|
|
1836
|
+
const override = mountOptions.commandOptions?.[command];
|
|
1837
|
+
const description = override?.description ?? definition.description;
|
|
1838
|
+
const optionDefs = resolveOptionDefinitions(definition.optionDefs, override);
|
|
1839
|
+
return { ...names, description, optionDefs };
|
|
1840
|
+
}
|
|
1841
|
+
async function installCommandDefaultHandler(ctx) {
|
|
1842
|
+
const patcher = await ctx.createPatcher();
|
|
1843
|
+
await patcher.patch();
|
|
1844
|
+
logger_default.success("Tailwind CSS runtime patched successfully.");
|
|
1845
|
+
}
|
|
1846
|
+
async function extractCommandDefaultHandler(ctx) {
|
|
1847
|
+
const { args } = ctx;
|
|
1848
|
+
const overrides = {};
|
|
1849
|
+
let hasOverrides = false;
|
|
1850
|
+
if (args.output || args.format) {
|
|
1851
|
+
overrides.output = {
|
|
1852
|
+
file: args.output,
|
|
1853
|
+
format: args.format
|
|
1854
|
+
};
|
|
1855
|
+
hasOverrides = true;
|
|
1829
1856
|
}
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1857
|
+
if (args.css) {
|
|
1858
|
+
overrides.tailwind = {
|
|
1859
|
+
v4: {
|
|
1860
|
+
cssEntries: [args.css]
|
|
1861
|
+
}
|
|
1862
|
+
};
|
|
1863
|
+
hasOverrides = true;
|
|
1864
|
+
}
|
|
1865
|
+
const patcher = await ctx.createPatcher(hasOverrides ? overrides : void 0);
|
|
1866
|
+
const result = await patcher.extract({ write: args.write });
|
|
1867
|
+
if (result.filename) {
|
|
1868
|
+
logger_default.success(`Collected ${result.classList.length} classes \u2192 ${result.filename}`);
|
|
1869
|
+
} else {
|
|
1870
|
+
logger_default.success(`Collected ${result.classList.length} classes.`);
|
|
1871
|
+
}
|
|
1872
|
+
return result;
|
|
1873
|
+
}
|
|
1874
|
+
async function tokensCommandDefaultHandler(ctx) {
|
|
1875
|
+
const { args } = ctx;
|
|
1876
|
+
const patcher = await ctx.createPatcher();
|
|
1877
|
+
const report = await patcher.collectContentTokens();
|
|
1878
|
+
const shouldWrite = args.write ?? true;
|
|
1879
|
+
let format = args.format ?? "json";
|
|
1880
|
+
if (!TOKEN_FORMATS.includes(format)) {
|
|
1881
|
+
format = "json";
|
|
1882
|
+
}
|
|
1883
|
+
const targetFile = args.output ?? DEFAULT_TOKEN_REPORT;
|
|
1884
|
+
const groupKey = args.groupKey === "absolute" ? "absolute" : "relative";
|
|
1885
|
+
const buildGrouped = () => groupTokensByFile(report, {
|
|
1886
|
+
key: groupKey,
|
|
1887
|
+
stripAbsolutePaths: groupKey !== "absolute"
|
|
1835
1888
|
});
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1889
|
+
const grouped = format === "grouped-json" ? buildGrouped() : null;
|
|
1890
|
+
const resolveGrouped = () => grouped ?? buildGrouped();
|
|
1891
|
+
if (shouldWrite) {
|
|
1892
|
+
const target = path9.resolve(targetFile);
|
|
1893
|
+
await fs8.ensureDir(path9.dirname(target));
|
|
1894
|
+
if (format === "json") {
|
|
1895
|
+
await fs8.writeJSON(target, report, { spaces: 2 });
|
|
1896
|
+
} else if (format === "grouped-json") {
|
|
1897
|
+
await fs8.writeJSON(target, resolveGrouped(), { spaces: 2 });
|
|
1898
|
+
} else {
|
|
1899
|
+
const lines = report.entries.map(formatTokenLine);
|
|
1900
|
+
await fs8.writeFile(target, `${lines.join("\n")}
|
|
1901
|
+
`, "utf8");
|
|
1902
|
+
}
|
|
1903
|
+
logger_default.success(`Collected ${report.entries.length} tokens (${format}) \u2192 ${target.replace(process5.cwd(), ".")}`);
|
|
1904
|
+
} else {
|
|
1905
|
+
logger_default.success(`Collected ${report.entries.length} tokens from ${report.filesScanned} files.`);
|
|
1906
|
+
if (format === "lines") {
|
|
1907
|
+
const preview = report.entries.slice(0, 5).map(formatTokenLine).join("\n");
|
|
1908
|
+
if (preview) {
|
|
1909
|
+
logger_default.log("");
|
|
1910
|
+
logger_default.info(preview);
|
|
1911
|
+
if (report.entries.length > 5) {
|
|
1912
|
+
logger_default.info(`\u2026and ${report.entries.length - 5} more.`);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
} else if (format === "grouped-json") {
|
|
1916
|
+
const map = resolveGrouped();
|
|
1917
|
+
const { preview, moreFiles } = formatGroupedPreview(map);
|
|
1918
|
+
if (preview) {
|
|
1919
|
+
logger_default.log("");
|
|
1920
|
+
logger_default.info(preview);
|
|
1921
|
+
if (moreFiles > 0) {
|
|
1922
|
+
logger_default.info(`\u2026and ${moreFiles} more files.`);
|
|
1923
|
+
}
|
|
1924
|
+
}
|
|
1925
|
+
} else {
|
|
1926
|
+
const previewEntries = report.entries.slice(0, 3);
|
|
1927
|
+
if (previewEntries.length) {
|
|
1928
|
+
logger_default.log("");
|
|
1929
|
+
logger_default.info(JSON.stringify(previewEntries, null, 2));
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
if (report.skippedFiles.length) {
|
|
1934
|
+
logger_default.warn("Skipped files:");
|
|
1935
|
+
for (const skipped of report.skippedFiles) {
|
|
1936
|
+
logger_default.warn(` \u2022 ${skipped.file} (${skipped.reason})`);
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
return report;
|
|
1940
|
+
}
|
|
1941
|
+
async function initCommandDefaultHandler(ctx) {
|
|
1942
|
+
await initConfig(ctx.cwd);
|
|
1943
|
+
logger_default.success(`\u2728 ${CONFIG_NAME}.config.ts initialized!`);
|
|
1944
|
+
}
|
|
1945
|
+
function mountTailwindcssPatchCommands(cli, options = {}) {
|
|
1946
|
+
const prefix = options.commandPrefix ?? "";
|
|
1947
|
+
const selectedCommands = options.commands ?? tailwindcssPatchCommands;
|
|
1948
|
+
const defaultDefinitions = buildDefaultCommandDefinitions();
|
|
1949
|
+
const registrars = {
|
|
1950
|
+
install: () => {
|
|
1951
|
+
const metadata = resolveCommandMetadata("install", options, prefix, defaultDefinitions);
|
|
1952
|
+
const command = cli.command(metadata.name, metadata.description);
|
|
1953
|
+
applyCommandOptions(command, metadata.optionDefs);
|
|
1954
|
+
command.action(async (args) => {
|
|
1955
|
+
return runWithCommandHandler(
|
|
1956
|
+
cli,
|
|
1957
|
+
command,
|
|
1958
|
+
"install",
|
|
1959
|
+
args,
|
|
1960
|
+
options.commandHandlers?.install,
|
|
1961
|
+
installCommandDefaultHandler
|
|
1962
|
+
);
|
|
1963
|
+
});
|
|
1964
|
+
metadata.aliases.forEach((alias) => command.alias(alias));
|
|
1965
|
+
},
|
|
1966
|
+
extract: () => {
|
|
1967
|
+
const metadata = resolveCommandMetadata("extract", options, prefix, defaultDefinitions);
|
|
1968
|
+
const command = cli.command(metadata.name, metadata.description);
|
|
1969
|
+
applyCommandOptions(command, metadata.optionDefs);
|
|
1970
|
+
command.action(async (args) => {
|
|
1971
|
+
return runWithCommandHandler(
|
|
1972
|
+
cli,
|
|
1973
|
+
command,
|
|
1974
|
+
"extract",
|
|
1975
|
+
args,
|
|
1976
|
+
options.commandHandlers?.extract,
|
|
1977
|
+
extractCommandDefaultHandler
|
|
1978
|
+
);
|
|
1979
|
+
});
|
|
1980
|
+
metadata.aliases.forEach((alias) => command.alias(alias));
|
|
1981
|
+
},
|
|
1982
|
+
tokens: () => {
|
|
1983
|
+
const metadata = resolveCommandMetadata("tokens", options, prefix, defaultDefinitions);
|
|
1984
|
+
const command = cli.command(metadata.name, metadata.description);
|
|
1985
|
+
applyCommandOptions(command, metadata.optionDefs);
|
|
1986
|
+
command.action(async (args) => {
|
|
1987
|
+
return runWithCommandHandler(
|
|
1988
|
+
cli,
|
|
1989
|
+
command,
|
|
1990
|
+
"tokens",
|
|
1991
|
+
args,
|
|
1992
|
+
options.commandHandlers?.tokens,
|
|
1993
|
+
tokensCommandDefaultHandler
|
|
1994
|
+
);
|
|
1995
|
+
});
|
|
1996
|
+
metadata.aliases.forEach((alias) => command.alias(alias));
|
|
1997
|
+
},
|
|
1998
|
+
init: () => {
|
|
1999
|
+
const metadata = resolveCommandMetadata("init", options, prefix, defaultDefinitions);
|
|
2000
|
+
const command = cli.command(metadata.name, metadata.description);
|
|
2001
|
+
applyCommandOptions(command, metadata.optionDefs);
|
|
2002
|
+
command.action(async (args) => {
|
|
2003
|
+
return runWithCommandHandler(
|
|
2004
|
+
cli,
|
|
2005
|
+
command,
|
|
2006
|
+
"init",
|
|
2007
|
+
args,
|
|
2008
|
+
options.commandHandlers?.init,
|
|
2009
|
+
initCommandDefaultHandler
|
|
2010
|
+
);
|
|
2011
|
+
});
|
|
2012
|
+
metadata.aliases.forEach((alias) => command.alias(alias));
|
|
2013
|
+
}
|
|
1839
2014
|
};
|
|
2015
|
+
for (const name of selectedCommands) {
|
|
2016
|
+
const register = registrars[name];
|
|
2017
|
+
if (register) {
|
|
2018
|
+
register();
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
return cli;
|
|
2022
|
+
}
|
|
2023
|
+
function createTailwindcssPatchCli(options = {}) {
|
|
2024
|
+
const cli = cac(options.name ?? "tw-patch");
|
|
2025
|
+
mountTailwindcssPatchCommands(cli, options.mountOptions);
|
|
2026
|
+
return cli;
|
|
1840
2027
|
}
|
|
1841
2028
|
|
|
1842
2029
|
export {
|
|
@@ -1854,6 +2041,6 @@ export {
|
|
|
1854
2041
|
runTailwindBuild,
|
|
1855
2042
|
TailwindcssPatcher,
|
|
1856
2043
|
tailwindcssPatchCommands,
|
|
1857
|
-
|
|
1858
|
-
|
|
2044
|
+
mountTailwindcssPatchCommands,
|
|
2045
|
+
createTailwindcssPatchCli
|
|
1859
2046
|
};
|