tailwind-canonical 0.2.2 → 0.4.0
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 +58 -4
- package/dist/cli/cli.d.ts +33 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +416 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/index.js +4 -315
- package/dist/cli/index.js.map +1 -1
- package/dist/core/analyzer.d.ts +2 -1
- package/dist/core/analyzer.d.ts.map +1 -1
- package/dist/core/analyzer.js +8 -14
- package/dist/core/analyzer.js.map +1 -1
- package/dist/core/class-strings.d.ts +6 -1
- package/dist/core/class-strings.d.ts.map +1 -1
- package/dist/core/class-strings.js +19 -8
- package/dist/core/class-strings.js.map +1 -1
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +20 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/consistency.d.ts +6 -1
- package/dist/core/consistency.d.ts.map +1 -1
- package/dist/core/consistency.js +38 -101
- package/dist/core/consistency.js.map +1 -1
- package/dist/core/deduplicator.d.ts +5 -1
- package/dist/core/deduplicator.d.ts.map +1 -1
- package/dist/core/deduplicator.js +26 -17
- package/dist/core/deduplicator.js.map +1 -1
- package/dist/core/fixer.d.ts +5 -1
- package/dist/core/fixer.d.ts.map +1 -1
- package/dist/core/fixer.js +8 -10
- package/dist/core/fixer.js.map +1 -1
- package/dist/core/lexicon.d.ts +16 -0
- package/dist/core/lexicon.d.ts.map +1 -0
- package/dist/core/lexicon.js +133 -0
- package/dist/core/lexicon.js.map +1 -0
- package/dist/core/merger.d.ts +5 -1
- package/dist/core/merger.d.ts.map +1 -1
- package/dist/core/merger.js +7 -8
- package/dist/core/merger.js.map +1 -1
- package/dist/core/rules.d.ts +3 -0
- package/dist/core/rules.d.ts.map +1 -1
- package/dist/core/rules.js +15 -1
- package/dist/core/rules.js.map +1 -1
- package/dist/core/scanner.d.ts +5 -2
- package/dist/core/scanner.d.ts.map +1 -1
- package/dist/core/scanner.js +12 -80
- package/dist/core/scanner.js.map +1 -1
- package/dist/core/sorter.d.ts +5 -1
- package/dist/core/sorter.d.ts.map +1 -1
- package/dist/core/sorter.js +7 -7
- package/dist/core/sorter.js.map +1 -1
- package/dist/core/suppressions.d.ts +8 -0
- package/dist/core/suppressions.d.ts.map +1 -0
- package/dist/core/suppressions.js +44 -0
- package/dist/core/suppressions.js.map +1 -0
- package/dist/core/typos.d.ts +14 -0
- package/dist/core/typos.d.ts.map +1 -0
- package/dist/core/typos.js +71 -0
- package/dist/core/typos.js.map +1 -0
- package/dist/eslint/plugin.d.ts +3 -74
- package/dist/eslint/plugin.d.ts.map +1 -1
- package/dist/eslint/plugin.js +30 -16
- package/dist/eslint/plugin.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -3
- package/dist/index.js.map +1 -1
- package/dist/io/analyzer.d.ts +4 -0
- package/dist/io/analyzer.d.ts.map +1 -0
- package/dist/io/analyzer.js +7 -0
- package/dist/io/analyzer.js.map +1 -0
- package/dist/io/config.d.ts +3 -0
- package/dist/io/config.d.ts.map +1 -0
- package/dist/io/config.js +12 -0
- package/dist/io/config.js.map +1 -0
- package/dist/io/consistency.d.ts +4 -0
- package/dist/io/consistency.d.ts.map +1 -0
- package/dist/io/consistency.js +21 -0
- package/dist/io/consistency.js.map +1 -0
- package/dist/io/deduplicator.d.ts +3 -0
- package/dist/io/deduplicator.d.ts.map +1 -0
- package/dist/io/deduplicator.js +10 -0
- package/dist/io/deduplicator.js.map +1 -0
- package/dist/io/fixer.d.ts +3 -0
- package/dist/io/fixer.d.ts.map +1 -0
- package/dist/io/fixer.js +10 -0
- package/dist/io/fixer.js.map +1 -0
- package/dist/io/merger.d.ts +3 -0
- package/dist/io/merger.d.ts.map +1 -0
- package/dist/io/merger.js +11 -0
- package/dist/io/merger.js.map +1 -0
- package/dist/io/scanner.d.ts +4 -0
- package/dist/io/scanner.d.ts.map +1 -0
- package/dist/io/scanner.js +78 -0
- package/dist/io/scanner.js.map +1 -0
- package/dist/io/sorter.d.ts +4 -0
- package/dist/io/sorter.d.ts.map +1 -0
- package/dist/io/sorter.js +10 -0
- package/dist/io/sorter.js.map +1 -0
- package/dist/io/typos.d.ts +4 -0
- package/dist/io/typos.d.ts.map +1 -0
- package/dist/io/typos.js +7 -0
- package/dist/io/typos.js.map +1 -0
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Lint and auto-fix Tailwind CSS classes: arbitrary values → canonical, deduplication, shorthand collapsing, and class sorting.
|
|
4
4
|
|
|
5
|
+
> Compatible with Tailwind CSS v3.3+ and v4 — zero `tailwindcss` dependency (conventions are built in). Custom theme tokens are supported via config.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -89,6 +91,34 @@ npx tailwind-canonical --fix --reporter json ./src
|
|
|
89
91
|
npx tailwind-canonical --reporter sarif ./src > results.sarif
|
|
90
92
|
```
|
|
91
93
|
|
|
94
|
+
## Typo detection (`--typos`)
|
|
95
|
+
|
|
96
|
+
Flags likely misspelled Tailwind color names (Levenshtein distance 1, low false-positive bias). Read-only.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx tailwind-canonical --typos ./src
|
|
100
|
+
# src/Card.tsx:3:17 text-gry-500 → text-gray-500 [typo]
|
|
101
|
+
# src/Nav.tsx:8:12 bg-slte-100 → bg-slate-100 [typo]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Only color-property classes (`text-`, `bg-`, `border-`, …) are checked. Valid colors, non-color utilities (`text-center`), custom colors (`bg-brand-500`), and arbitrary values are never flagged. Pairs with `--reporter json`; exits `1` on findings.
|
|
105
|
+
|
|
106
|
+
## Suppression comments
|
|
107
|
+
|
|
108
|
+
Skip specific lines or blocks from check and all transforms (`--fix`, `--dedup`, `--merge`, `--sort`):
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
{/* tailwind-canonical-disable-next-line */}
|
|
112
|
+
<div className="text-[13px]" /> {/* left untouched */}
|
|
113
|
+
|
|
114
|
+
{/* tailwind-canonical-disable */}
|
|
115
|
+
<div className="text-[13px] p-[7px]" /> {/* whole block untouched */}
|
|
116
|
+
<div className="m-[9px]" />
|
|
117
|
+
{/* tailwind-canonical-enable */}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The pragmas are matched as substrings, so any comment style works (`//`, `/* */`, `{/* */}`).
|
|
121
|
+
|
|
92
122
|
## Cross-file consistency (`--analyze`)
|
|
93
123
|
|
|
94
124
|
Detects semantic inconsistencies visible only at project scale — it never modifies files.
|
|
@@ -215,7 +245,10 @@ left-2 right-2 → inset-x-2
|
|
|
215
245
|
| `h-[64px]` | `h-16` | Spacing scale ÷4 |
|
|
216
246
|
| `w-[50%]` | `w-1/2` | Percentage fractions |
|
|
217
247
|
| `opacity-[0.5]` | `opacity-50` | Opacity scale |
|
|
218
|
-
| `text-[11px]` | `text-2xs` |
|
|
248
|
+
| `text-[11px]` | `text-2xs` | Built-in extra token |
|
|
249
|
+
| `text-[8px]`–`text-[10px]` | `text-3xs` | Built-in extra token |
|
|
250
|
+
|
|
251
|
+
`text-2xs` (11px) and `text-3xs` (8–10px) are part of the built-in text size map — they convert with no config. Override or extend the map via `customTextTokens`.
|
|
219
252
|
|
|
220
253
|
Non-divisible values (`h-[22px]`, `px-[7px]`) are left untouched.
|
|
221
254
|
|
|
@@ -228,7 +261,6 @@ export default {
|
|
|
228
261
|
customTextTokens: {
|
|
229
262
|
10: '3xs',
|
|
230
263
|
11: '2xs',
|
|
231
|
-
13: 'xxs',
|
|
232
264
|
},
|
|
233
265
|
customSpacingTokens: {
|
|
234
266
|
14: '3.5',
|
|
@@ -237,10 +269,12 @@ export default {
|
|
|
237
269
|
attributeNames: ['className', 'class', ':class', 'tw'],
|
|
238
270
|
// Support utility function wrappers
|
|
239
271
|
functionNames: ['cn', 'clsx', 'cva'],
|
|
272
|
+
// Never suggest replacements for classes matching these patterns
|
|
273
|
+
ignorePatterns: [/^font-/, /-\[var\(/],
|
|
240
274
|
}
|
|
241
275
|
```
|
|
242
276
|
|
|
243
|
-
`customTextTokens` merges with the built-in text size map. `customSpacingTokens` supplements the default ÷4 spacing logic.
|
|
277
|
+
`customTextTokens` merges with the built-in text size map. `customSpacingTokens` supplements the default ÷4 spacing logic. `ignorePatterns` makes `suggestCanonical` skip matching classes everywhere — CLI, analyzer, and the ESLint plugin.
|
|
244
278
|
|
|
245
279
|
`attributeNames` controls which HTML/JSX attributes are scanned (default: `['className']`). Use `['class']` for plain HTML/PHP/Jinja templates, `[':class']` for Vue, `['tw']` for styled-components.
|
|
246
280
|
|
|
@@ -264,6 +298,26 @@ export default [
|
|
|
264
298
|
]
|
|
265
299
|
```
|
|
266
300
|
|
|
301
|
+
### Rule options
|
|
302
|
+
|
|
303
|
+
`no-arbitrary-canonical` accepts the full tailwind-canonical `Config` object as
|
|
304
|
+
its rule options, so the same shared config can be reused for both the CLI and
|
|
305
|
+
ESLint without schema errors:
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
'tailwind-canonical/no-arbitrary-canonical': [
|
|
309
|
+
'warn',
|
|
310
|
+
{ customTextTokens: { 11: '2xs' }, ignorePatterns: [/^font-/] },
|
|
311
|
+
],
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
The rule **honors**: `customTextTokens`, `customSpacingTokens`, `ignorePatterns`
|
|
315
|
+
(all applied via `suggestCanonical`).
|
|
316
|
+
|
|
317
|
+
It **accepts but ignores**: `functionNames`, `attributeNames`, `sortOrder`.
|
|
318
|
+
These are CLI-only options, allowed in the schema purely so a single shared
|
|
319
|
+
config object can be passed without errors.
|
|
320
|
+
|
|
267
321
|
## Pre-commit hook (Husky / Lefthook)
|
|
268
322
|
|
|
269
323
|
```yaml
|
|
@@ -292,7 +346,7 @@ npx tailwind-canonical --fix --dedup --sort ./src ./app
|
|
|
292
346
|
pnpm knip
|
|
293
347
|
```
|
|
294
348
|
|
|
295
|
-
Detects unused exports, files, and dependencies. Config in `knip.json`.
|
|
349
|
+
Detects unused exports, files, and dependencies. Config in `knip.json`. Enforced in CI and in the `pre-push` git hook.
|
|
296
350
|
|
|
297
351
|
## Programmatic API
|
|
298
352
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type Sink = {
|
|
2
|
+
log: (s: string) => void;
|
|
3
|
+
error: (s: string) => void;
|
|
4
|
+
write: (s: string) => void;
|
|
5
|
+
};
|
|
6
|
+
export type RunResult = {
|
|
7
|
+
exitCode: number;
|
|
8
|
+
watching?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type Reporter = 'text' | 'json' | 'sarif';
|
|
11
|
+
type Flags = {
|
|
12
|
+
fix: boolean;
|
|
13
|
+
merge: boolean;
|
|
14
|
+
dedup: boolean;
|
|
15
|
+
sort: boolean;
|
|
16
|
+
watch: boolean;
|
|
17
|
+
analyze: boolean;
|
|
18
|
+
typos: boolean;
|
|
19
|
+
reporter: Reporter;
|
|
20
|
+
targets: string[];
|
|
21
|
+
error?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function parseArgs(argv: string[]): Flags;
|
|
24
|
+
/**
|
|
25
|
+
* Modes are mutually exclusive with a fixed precedence: analyze > typos >
|
|
26
|
+
* transform/check. `--watch` is only honored in transform/check mode. This
|
|
27
|
+
* computes warnings for every flag that the active mode will ignore. Pure and
|
|
28
|
+
* order-stable so it can be unit-tested via the injectable sink.
|
|
29
|
+
*/
|
|
30
|
+
export declare function flagWarnings(flags: Flags): string[];
|
|
31
|
+
export declare function run(argv: string[], cwd: string, sink?: Sink): Promise<RunResult>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,IAAI,GAAG;IACjB,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzB,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3B,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5B,CAAC;AAQF,MAAM,MAAM,SAAS,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAEjE,KAAK,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE1C,KAAK,KAAK,GAAG;IACX,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAsFF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CA0C/C;AASD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAwBnD;AAyLD,wBAAsB,GAAG,CACvB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAkB,GACvB,OAAO,CAAC,SAAS,CAAC,CAiMpB"}
|
package/dist/cli/cli.js
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import { watch as fsWatch } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { analyzeFile } from '../core/analyzer.js';
|
|
4
|
+
import { toClassStringOpts } from '../core/class-strings.js';
|
|
5
|
+
import { loadConfig } from '../core/config.js';
|
|
6
|
+
import { analyzeConsistencyFiles, toConsistencyOptions, } from '../core/consistency.js';
|
|
7
|
+
import { dedupeFile } from '../core/deduplicator.js';
|
|
8
|
+
import { fixFile } from '../core/fixer.js';
|
|
9
|
+
import { mergeFile } from '../core/merger.js';
|
|
10
|
+
import { resolveTargets } from '../core/scanner.js';
|
|
11
|
+
import { sortFile } from '../core/sorter.js';
|
|
12
|
+
import { analyzeTyposFile } from '../core/typos.js';
|
|
13
|
+
const SARIF_SCHEMA = 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json';
|
|
14
|
+
const USAGE = 'Usage: tailwind-canonical [--fix] [--merge] [--dedup] [--sort] [--analyze] [--typos] [--watch] [--reporter json|sarif] <dir|file> [dir|file...]';
|
|
15
|
+
const defaultSink = {
|
|
16
|
+
log: (s) => console.log(s),
|
|
17
|
+
error: (s) => console.error(s),
|
|
18
|
+
write: (s) => process.stdout.write(s),
|
|
19
|
+
};
|
|
20
|
+
function errMsg(e) {
|
|
21
|
+
return e instanceof Error ? e.message : String(e);
|
|
22
|
+
}
|
|
23
|
+
function pluralize(n, word) {
|
|
24
|
+
return `${n} ${word}${n !== 1 ? 's' : ''}`;
|
|
25
|
+
}
|
|
26
|
+
function timestamp() {
|
|
27
|
+
const d = new Date();
|
|
28
|
+
const pad = (n) => n.toString().padStart(2, '0');
|
|
29
|
+
return `[${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}]`;
|
|
30
|
+
}
|
|
31
|
+
const REPORTERS = ['text', 'json', 'sarif'];
|
|
32
|
+
function isReporter(value) {
|
|
33
|
+
return REPORTERS.includes(value);
|
|
34
|
+
}
|
|
35
|
+
export function parseArgs(argv) {
|
|
36
|
+
let reporter = 'text';
|
|
37
|
+
let reporterRaw;
|
|
38
|
+
const consumed = new Set();
|
|
39
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
40
|
+
const arg = argv[i];
|
|
41
|
+
if (arg === '--reporter') {
|
|
42
|
+
consumed.add(i);
|
|
43
|
+
reporterRaw = argv[i + 1];
|
|
44
|
+
if (i + 1 < argv.length)
|
|
45
|
+
consumed.add(i + 1);
|
|
46
|
+
}
|
|
47
|
+
else if (arg.startsWith('--reporter=')) {
|
|
48
|
+
consumed.add(i);
|
|
49
|
+
reporterRaw = arg.slice('--reporter='.length);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let error;
|
|
53
|
+
if (reporterRaw !== undefined) {
|
|
54
|
+
if (isReporter(reporterRaw)) {
|
|
55
|
+
reporter = reporterRaw;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
error = `Unknown reporter: ${reporterRaw} (expected ${REPORTERS.join('|')})`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const targets = argv.filter((a, i) => !(a.startsWith('--') || consumed.has(i)));
|
|
62
|
+
return {
|
|
63
|
+
fix: argv.includes('--fix'),
|
|
64
|
+
merge: argv.includes('--merge'),
|
|
65
|
+
dedup: argv.includes('--dedup'),
|
|
66
|
+
sort: argv.includes('--sort'),
|
|
67
|
+
watch: argv.includes('--watch'),
|
|
68
|
+
analyze: argv.includes('--analyze'),
|
|
69
|
+
typos: argv.includes('--typos'),
|
|
70
|
+
reporter,
|
|
71
|
+
targets,
|
|
72
|
+
error,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const TRANSFORM_FLAGS = [
|
|
76
|
+
{ key: 'fix', flag: '--fix' },
|
|
77
|
+
{ key: 'dedup', flag: '--dedup' },
|
|
78
|
+
{ key: 'merge', flag: '--merge' },
|
|
79
|
+
{ key: 'sort', flag: '--sort' },
|
|
80
|
+
];
|
|
81
|
+
/**
|
|
82
|
+
* Modes are mutually exclusive with a fixed precedence: analyze > typos >
|
|
83
|
+
* transform/check. `--watch` is only honored in transform/check mode. This
|
|
84
|
+
* computes warnings for every flag that the active mode will ignore. Pure and
|
|
85
|
+
* order-stable so it can be unit-tested via the injectable sink.
|
|
86
|
+
*/
|
|
87
|
+
export function flagWarnings(flags) {
|
|
88
|
+
const warnings = [];
|
|
89
|
+
if (flags.analyze) {
|
|
90
|
+
for (const { key, flag } of TRANSFORM_FLAGS) {
|
|
91
|
+
if (flags[key])
|
|
92
|
+
warnings.push(`${flag} ignored: --analyze takes priority`);
|
|
93
|
+
}
|
|
94
|
+
if (flags.typos)
|
|
95
|
+
warnings.push('--typos ignored: --analyze takes priority');
|
|
96
|
+
if (flags.watch)
|
|
97
|
+
warnings.push('--watch ignored: not supported with --analyze');
|
|
98
|
+
return warnings;
|
|
99
|
+
}
|
|
100
|
+
if (flags.typos) {
|
|
101
|
+
for (const { key, flag } of TRANSFORM_FLAGS) {
|
|
102
|
+
if (flags[key])
|
|
103
|
+
warnings.push(`${flag} ignored: --typos takes priority`);
|
|
104
|
+
}
|
|
105
|
+
if (flags.watch)
|
|
106
|
+
warnings.push('--watch ignored: not supported with --typos');
|
|
107
|
+
return warnings;
|
|
108
|
+
}
|
|
109
|
+
return warnings;
|
|
110
|
+
}
|
|
111
|
+
function runTypos(files, config, reporter, sink) {
|
|
112
|
+
let hadError = false;
|
|
113
|
+
const findings = [];
|
|
114
|
+
for (const file of files) {
|
|
115
|
+
try {
|
|
116
|
+
findings.push(...analyzeTyposFile(file, config));
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
hadError = true;
|
|
120
|
+
sink.error(`${file}: ${errMsg(err)}`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (reporter === 'json') {
|
|
124
|
+
const report = {
|
|
125
|
+
total: findings.length,
|
|
126
|
+
typos: findings,
|
|
127
|
+
};
|
|
128
|
+
sink.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
129
|
+
return { exitCode: findings.length > 0 || hadError ? 1 : 0 };
|
|
130
|
+
}
|
|
131
|
+
for (const f of findings) {
|
|
132
|
+
sink.log(` ${f.file}:${f.line}:${f.col} ${f.original} → ${f.suggestion} [typo]`);
|
|
133
|
+
}
|
|
134
|
+
if (findings.length === 0) {
|
|
135
|
+
sink.log('✓ No likely typos found');
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
sink.log(`\n✖ Found ${pluralize(findings.length, 'likely typo')}`);
|
|
139
|
+
}
|
|
140
|
+
return { exitCode: findings.length > 0 || hadError ? 1 : 0 };
|
|
141
|
+
}
|
|
142
|
+
async function processFile(file, flags, config) {
|
|
143
|
+
const opts = toClassStringOpts(config);
|
|
144
|
+
const counts = { fixed: 0, deduped: 0, merged: 0, sorted: 0 };
|
|
145
|
+
if (flags.fix)
|
|
146
|
+
counts.fixed = fixFile(file, config);
|
|
147
|
+
if (flags.dedup)
|
|
148
|
+
counts.deduped = dedupeFile(file, opts);
|
|
149
|
+
if (flags.merge)
|
|
150
|
+
counts.merged = await mergeFile(file, opts);
|
|
151
|
+
if (flags.sort)
|
|
152
|
+
counts.sorted = sortFile(file, opts, config.sortOrder);
|
|
153
|
+
return counts;
|
|
154
|
+
}
|
|
155
|
+
function totalOf(c) {
|
|
156
|
+
return c.fixed + c.deduped + c.merged + c.sorted;
|
|
157
|
+
}
|
|
158
|
+
function runAnalyze(files, config, reporter, sink) {
|
|
159
|
+
let hadError = false;
|
|
160
|
+
const options = toConsistencyOptions(config);
|
|
161
|
+
const report = analyzeConsistencyFiles(files, config, options, (file, err) => {
|
|
162
|
+
hadError = true;
|
|
163
|
+
sink.error(`${file}: ${errMsg(err)}`);
|
|
164
|
+
});
|
|
165
|
+
const issueCount = report.colorVariants.length +
|
|
166
|
+
report.scaleInconsistencies.length +
|
|
167
|
+
report.combinations.length;
|
|
168
|
+
if (reporter === 'json') {
|
|
169
|
+
sink.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
170
|
+
return { exitCode: issueCount > 0 || hadError ? 1 : 0 };
|
|
171
|
+
}
|
|
172
|
+
for (const group of report.colorVariants) {
|
|
173
|
+
const tokens = group.variants
|
|
174
|
+
.map((v) => `${group.property}-${v.token} (${v.count})`)
|
|
175
|
+
.join(', ');
|
|
176
|
+
sink.log(` Warning: ${group.variants.length} ${group.family} color variants used for ${group.property}: ${tokens}`);
|
|
177
|
+
}
|
|
178
|
+
for (const scale of report.scaleInconsistencies) {
|
|
179
|
+
const values = scale.values
|
|
180
|
+
.map((v) => `${scale.property}-${v.value} (${pluralize(v.files.length, 'file')})`)
|
|
181
|
+
.join(' vs ');
|
|
182
|
+
sink.log(` Warning: ${scale.property} inconsistency: ${values}`);
|
|
183
|
+
}
|
|
184
|
+
for (const combo of report.combinations) {
|
|
185
|
+
sink.log(` Pattern: "${combo.classes.join(' ')}" repeated in ${pluralize(combo.files.length, 'file')}`);
|
|
186
|
+
}
|
|
187
|
+
if (issueCount === 0) {
|
|
188
|
+
sink.log('✓ No cross-file inconsistencies found');
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
sink.log(`\n✖ Found ${pluralize(issueCount, 'consistency issue')} across ${pluralize(report.filesAnalyzed, 'file')}`);
|
|
192
|
+
}
|
|
193
|
+
return { exitCode: issueCount > 0 || hadError ? 1 : 0 };
|
|
194
|
+
}
|
|
195
|
+
function startWatch(files, flags, config, sink) {
|
|
196
|
+
const transforming = flags.fix || flags.dedup || flags.merge || flags.sort;
|
|
197
|
+
const fileSet = new Set(files);
|
|
198
|
+
const inFlight = new Set();
|
|
199
|
+
const timers = new Map();
|
|
200
|
+
const dirs = new Set(files.map((f) => dirname(f)));
|
|
201
|
+
sink.log(`Watching ${pluralize(files.length, 'file')}... (Ctrl+C to stop)`);
|
|
202
|
+
for (const dir of dirs) {
|
|
203
|
+
fsWatch(dir, { recursive: true }, (_, filename) => {
|
|
204
|
+
if (!filename)
|
|
205
|
+
return;
|
|
206
|
+
const full = resolve(dir, filename);
|
|
207
|
+
if (!fileSet.has(full) || inFlight.has(full))
|
|
208
|
+
return;
|
|
209
|
+
clearTimeout(timers.get(full));
|
|
210
|
+
timers.set(full, setTimeout(() => {
|
|
211
|
+
if (transforming) {
|
|
212
|
+
inFlight.add(full);
|
|
213
|
+
processFile(full, flags, config)
|
|
214
|
+
.then((counts) => {
|
|
215
|
+
const total = totalOf(counts);
|
|
216
|
+
if (total > 0) {
|
|
217
|
+
sink.log(`${timestamp()} ${full} — ${pluralize(total, 'change')} applied`);
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.catch((err) => {
|
|
221
|
+
sink.error(`${timestamp()} ${full} — error: ${err instanceof Error ? err.message : String(err)}`);
|
|
222
|
+
})
|
|
223
|
+
.finally(() => inFlight.delete(full));
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
const findings = analyzeFile(full, config);
|
|
227
|
+
if (findings.length > 0) {
|
|
228
|
+
sink.log(`${timestamp()} ${full} — ${pluralize(findings.length, 'finding')}`);
|
|
229
|
+
for (const f of findings) {
|
|
230
|
+
const tag = f.suggestion.isCustomToken ? ' [custom token]' : '';
|
|
231
|
+
sink.log(` ${f.line}:${f.col} ${f.suggestion.original} → ${f.suggestion.canonical}${tag}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}, 50));
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
process.on('SIGINT', () => {
|
|
239
|
+
sink.log('\nWatcher stopped.');
|
|
240
|
+
process.exit(0);
|
|
241
|
+
});
|
|
242
|
+
return { exitCode: 0, watching: true };
|
|
243
|
+
}
|
|
244
|
+
export async function run(argv, cwd, sink = defaultSink) {
|
|
245
|
+
const flags = parseArgs(argv);
|
|
246
|
+
if (flags.error) {
|
|
247
|
+
sink.error(flags.error);
|
|
248
|
+
return { exitCode: 1 };
|
|
249
|
+
}
|
|
250
|
+
if (flags.targets.length === 0) {
|
|
251
|
+
sink.error(USAGE);
|
|
252
|
+
return { exitCode: 1 };
|
|
253
|
+
}
|
|
254
|
+
if (flags.merge) {
|
|
255
|
+
try {
|
|
256
|
+
await import('tailwind-merge');
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
sink.error('--merge requires tailwind-merge: pnpm add -D tailwind-merge');
|
|
260
|
+
return { exitCode: 1 };
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
let config;
|
|
264
|
+
try {
|
|
265
|
+
config = await loadConfig(cwd);
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
sink.error(`tailwind-canonical: ${err instanceof Error ? err.message : String(err)}`);
|
|
269
|
+
return { exitCode: 1 };
|
|
270
|
+
}
|
|
271
|
+
for (const warning of flagWarnings(flags)) {
|
|
272
|
+
sink.error(`Warning: ${warning}`);
|
|
273
|
+
}
|
|
274
|
+
const files = await resolveTargets(flags.targets);
|
|
275
|
+
if (flags.analyze)
|
|
276
|
+
return runAnalyze(files, config, flags.reporter, sink);
|
|
277
|
+
if (flags.typos)
|
|
278
|
+
return runTypos(files, config, flags.reporter, sink);
|
|
279
|
+
const transforming = flags.fix || flags.dedup || flags.merge || flags.sort;
|
|
280
|
+
const totals = { fixed: 0, deduped: 0, merged: 0, sorted: 0 };
|
|
281
|
+
const allFindings = [];
|
|
282
|
+
const changedFiles = [];
|
|
283
|
+
let hadError = false;
|
|
284
|
+
if (!flags.watch) {
|
|
285
|
+
for (const file of files) {
|
|
286
|
+
try {
|
|
287
|
+
if (transforming) {
|
|
288
|
+
const counts = await processFile(file, flags, config);
|
|
289
|
+
totals.fixed += counts.fixed;
|
|
290
|
+
totals.deduped += counts.deduped;
|
|
291
|
+
totals.merged += counts.merged;
|
|
292
|
+
totals.sorted += counts.sorted;
|
|
293
|
+
if (totalOf(counts) > 0)
|
|
294
|
+
changedFiles.push(file);
|
|
295
|
+
if (flags.reporter === 'text') {
|
|
296
|
+
if (counts.fixed > 0)
|
|
297
|
+
sink.log(` fixed ${file} (${pluralize(counts.fixed, 'replacement')})`);
|
|
298
|
+
if (counts.deduped > 0)
|
|
299
|
+
sink.log(` deduped ${file} (${pluralize(counts.deduped, 'class string')})`);
|
|
300
|
+
if (counts.merged > 0)
|
|
301
|
+
sink.log(` merged ${file} (${pluralize(counts.merged, 'conflict')})`);
|
|
302
|
+
if (counts.sorted > 0)
|
|
303
|
+
sink.log(` sorted ${file} (${pluralize(counts.sorted, 'class string')})`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
const findings = analyzeFile(file, config);
|
|
308
|
+
allFindings.push(...findings);
|
|
309
|
+
if (flags.reporter === 'text') {
|
|
310
|
+
for (const f of findings) {
|
|
311
|
+
const tag = f.suggestion.isCustomToken ? ' [custom token]' : '';
|
|
312
|
+
sink.log(` ${f.file}:${f.line}:${f.col} ${f.suggestion.original} → ${f.suggestion.canonical}${tag}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch (err) {
|
|
318
|
+
hadError = true;
|
|
319
|
+
sink.error(`${file}: ${errMsg(err)}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (flags.watch)
|
|
324
|
+
return startWatch(files, flags, config, sink);
|
|
325
|
+
if (transforming) {
|
|
326
|
+
if (flags.reporter === 'json') {
|
|
327
|
+
const report = {
|
|
328
|
+
files: files.length,
|
|
329
|
+
changedFiles,
|
|
330
|
+
fixed: totals.fixed,
|
|
331
|
+
deduped: totals.deduped,
|
|
332
|
+
merged: totals.merged,
|
|
333
|
+
sorted: totals.sorted,
|
|
334
|
+
};
|
|
335
|
+
sink.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
336
|
+
return { exitCode: hadError ? 1 : 0 };
|
|
337
|
+
}
|
|
338
|
+
const parts = [];
|
|
339
|
+
if (flags.fix)
|
|
340
|
+
parts.push(pluralize(totals.fixed, 'replacement'));
|
|
341
|
+
if (flags.dedup)
|
|
342
|
+
parts.push(pluralize(totals.deduped, 'dedup'));
|
|
343
|
+
if (flags.merge)
|
|
344
|
+
parts.push(`${pluralize(totals.merged, 'conflict')} merged`);
|
|
345
|
+
if (flags.sort)
|
|
346
|
+
parts.push(`${totals.sorted} sorted`);
|
|
347
|
+
sink.log(`\n✓ Fixed ${parts.join(', ')} across ${pluralize(files.length, 'file')}`);
|
|
348
|
+
return { exitCode: hadError ? 1 : 0 };
|
|
349
|
+
}
|
|
350
|
+
const totalFindings = allFindings.length;
|
|
351
|
+
if (flags.reporter === 'json') {
|
|
352
|
+
const report = {
|
|
353
|
+
files: files.length,
|
|
354
|
+
total: totalFindings,
|
|
355
|
+
findings: allFindings.map((f) => ({
|
|
356
|
+
file: f.file,
|
|
357
|
+
line: f.line,
|
|
358
|
+
col: f.col,
|
|
359
|
+
original: f.suggestion.original,
|
|
360
|
+
canonical: f.suggestion.canonical,
|
|
361
|
+
isCustomToken: f.suggestion.isCustomToken,
|
|
362
|
+
})),
|
|
363
|
+
};
|
|
364
|
+
sink.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
365
|
+
return { exitCode: totalFindings > 0 || hadError ? 1 : 0 };
|
|
366
|
+
}
|
|
367
|
+
if (flags.reporter === 'sarif') {
|
|
368
|
+
const sarifOutput = {
|
|
369
|
+
$schema: SARIF_SCHEMA,
|
|
370
|
+
version: '2.1.0',
|
|
371
|
+
runs: [
|
|
372
|
+
{
|
|
373
|
+
tool: {
|
|
374
|
+
driver: {
|
|
375
|
+
name: 'tailwind-canonical',
|
|
376
|
+
informationUri: 'https://github.com/peak-lab/tailwind-canonical',
|
|
377
|
+
rules: [
|
|
378
|
+
{
|
|
379
|
+
id: 'no-arbitrary-canonical',
|
|
380
|
+
name: 'NoArbitraryCanonical',
|
|
381
|
+
shortDescription: {
|
|
382
|
+
text: 'Arbitrary value has a canonical Tailwind equivalent',
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
],
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
results: allFindings.map((f) => ({
|
|
389
|
+
ruleId: 'no-arbitrary-canonical',
|
|
390
|
+
message: {
|
|
391
|
+
text: `${f.suggestion.original} → ${f.suggestion.canonical}`,
|
|
392
|
+
},
|
|
393
|
+
locations: [
|
|
394
|
+
{
|
|
395
|
+
physicalLocation: {
|
|
396
|
+
artifactLocation: { uri: f.file },
|
|
397
|
+
region: { startLine: f.line, startColumn: f.col },
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
],
|
|
401
|
+
})),
|
|
402
|
+
},
|
|
403
|
+
],
|
|
404
|
+
};
|
|
405
|
+
sink.write(`${JSON.stringify(sarifOutput, null, 2)}\n`);
|
|
406
|
+
return { exitCode: totalFindings > 0 || hadError ? 1 : 0 };
|
|
407
|
+
}
|
|
408
|
+
if (totalFindings > 0) {
|
|
409
|
+
sink.log(`\n✖ Found ${totalFindings} non-canonical class${totalFindings !== 1 ? 'es' : ''}`);
|
|
410
|
+
sink.log(' Run with --fix to auto-replace\n');
|
|
411
|
+
return { exitCode: 1 };
|
|
412
|
+
}
|
|
413
|
+
sink.log('✓ No non-canonical classes found');
|
|
414
|
+
return { exitCode: hadError ? 1 : 0 };
|
|
415
|
+
}
|
|
416
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"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"}
|