tailwind-canonical 0.3.0 → 0.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 +85 -9
- package/dist/cli/cli.d.ts +9 -1
- package/dist/cli/cli.d.ts.map +1 -1
- package/dist/cli/cli.js +409 -78
- package/dist/cli/cli.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 +5 -15
- package/dist/core/analyzer.js.map +1 -1
- package/dist/core/class-strings.d.ts +5 -1
- package/dist/core/class-strings.d.ts.map +1 -1
- package/dist/core/class-strings.js +74 -55
- package/dist/core/class-strings.js.map +1 -1
- package/dist/core/config.d.ts +3 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +91 -33
- package/dist/core/config.js.map +1 -1
- package/dist/core/consistency.d.ts +18 -1
- package/dist/core/consistency.d.ts.map +1 -1
- package/dist/core/consistency.js +76 -110
- 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 +22 -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 +6 -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 +139 -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 +3 -8
- package/dist/core/merger.js.map +1 -1
- package/dist/core/rules.d.ts +17 -0
- package/dist/core/rules.d.ts.map +1 -1
- package/dist/core/rules.js +18 -9
- 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 +9 -10
- package/dist/core/sorter.js.map +1 -1
- package/dist/core/suppressions.d.ts +4 -0
- package/dist/core/suppressions.d.ts.map +1 -1
- package/dist/core/suppressions.js +10 -4
- package/dist/core/suppressions.js.map +1 -1
- 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 -95
- package/dist/eslint/plugin.d.ts.map +1 -1
- package/dist/eslint/plugin.js +68 -31
- package/dist/eslint/plugin.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -4
- 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 +13 -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 +17 -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 +84 -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 +22 -13
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,18 @@ 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
|
+
|
|
92
106
|
## Suppression comments
|
|
93
107
|
|
|
94
108
|
Skip specific lines or blocks from check and all transforms (`--fix`, `--dedup`, `--merge`, `--sort`):
|
|
@@ -111,9 +125,19 @@ Detects semantic inconsistencies visible only at project scale — it never modi
|
|
|
111
125
|
|
|
112
126
|
```bash
|
|
113
127
|
npx tailwind-canonical --analyze ./src
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
128
|
+
# tailwind-canonical analyze
|
|
129
|
+
# Files analyzed: 42
|
|
130
|
+
# Issue groups: 3 (1 color, 2 scales, 0 patterns)
|
|
131
|
+
#
|
|
132
|
+
# Color variants
|
|
133
|
+
# - text/red: text-red-500 x4, text-rose-500 x1
|
|
134
|
+
#
|
|
135
|
+
# Scale inconsistency groups
|
|
136
|
+
# - px: 2 values, 10 uses, 10 files
|
|
137
|
+
# Top: px-4 (8 uses, 8 files), px-3 (2 uses, 2 files)
|
|
138
|
+
#
|
|
139
|
+
# Rare scale values
|
|
140
|
+
# - px-11: 3 uses in 1 file (608 px uses total); e.g. src/Dialog.tsx
|
|
117
141
|
```
|
|
118
142
|
|
|
119
143
|
Three detectors:
|
|
@@ -122,6 +146,7 @@ Three detectors:
|
|
|
122
146
|
|---|---|
|
|
123
147
|
| Color variants | Multiple shades/colors of the same hue family used for one property (`text`, `bg`, `border`, …) |
|
|
124
148
|
| Scale inconsistency | Competing values for the same spacing / `gap` / `z` property across files |
|
|
149
|
+
| Rare scale values | Low-frequency scale values inside otherwise common properties (`ml-13`, `gap-24`, `px-11`, …) |
|
|
125
150
|
| Repeated patterns | Identical class combinations recurring across 3+ files |
|
|
126
151
|
|
|
127
152
|
Pairs with `--reporter json` for machine-readable output. Exits `1` when any inconsistency is found.
|
|
@@ -146,6 +171,10 @@ npx tailwind-canonical --analyze --reporter json ./src
|
|
|
146
171
|
{ "value": "3", "count": 2, "files": ["src/IconButton.tsx"] }
|
|
147
172
|
] }
|
|
148
173
|
],
|
|
174
|
+
"rareScaleValues": [
|
|
175
|
+
{ "property": "px", "value": "11", "className": "px-11",
|
|
176
|
+
"count": 3, "files": ["src/Dialog.tsx"], "propertyCount": 608 }
|
|
177
|
+
],
|
|
149
178
|
"combinations": []
|
|
150
179
|
}
|
|
151
180
|
```
|
|
@@ -168,8 +197,8 @@ Variants (`hover:`, `sm:`, `focus:`) are sorted after base classes, with respons
|
|
|
168
197
|
|
|
169
198
|
Override the category order via config. Categories you omit (and unknown classes) sort to the end, preserving their original relative order. Variants are always sorted after base classes regardless of order.
|
|
170
199
|
|
|
171
|
-
```
|
|
172
|
-
// tailwind-canonical.config.
|
|
200
|
+
```ts
|
|
201
|
+
// tailwind-canonical.config.ts
|
|
173
202
|
export default {
|
|
174
203
|
sortOrder: [
|
|
175
204
|
'display',
|
|
@@ -231,15 +260,18 @@ left-2 right-2 → inset-x-2
|
|
|
231
260
|
| `h-[64px]` | `h-16` | Spacing scale ÷4 |
|
|
232
261
|
| `w-[50%]` | `w-1/2` | Percentage fractions |
|
|
233
262
|
| `opacity-[0.5]` | `opacity-50` | Opacity scale |
|
|
234
|
-
| `text-[11px]` | `text-2xs` |
|
|
263
|
+
| `text-[11px]` | `text-2xs` | Built-in extra token |
|
|
264
|
+
| `text-[8px]`–`text-[10px]` | `text-3xs` | Built-in extra token |
|
|
265
|
+
|
|
266
|
+
`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`.
|
|
235
267
|
|
|
236
268
|
Non-divisible values (`h-[22px]`, `px-[7px]`) are left untouched.
|
|
237
269
|
|
|
238
270
|
## Config
|
|
239
271
|
|
|
240
|
-
Create `tailwind-canonical.config.
|
|
272
|
+
Create `tailwind-canonical.config.ts` at the root:
|
|
241
273
|
|
|
242
|
-
```
|
|
274
|
+
```ts
|
|
243
275
|
export default {
|
|
244
276
|
customTextTokens: {
|
|
245
277
|
10: '3xs',
|
|
@@ -252,6 +284,16 @@ export default {
|
|
|
252
284
|
attributeNames: ['className', 'class', ':class', 'tw'],
|
|
253
285
|
// Support utility function wrappers
|
|
254
286
|
functionNames: ['cn', 'clsx', 'cva'],
|
|
287
|
+
// Tune --analyze reporting
|
|
288
|
+
analyze: {
|
|
289
|
+
maxScaleGroups: 8,
|
|
290
|
+
maxScaleValues: 5,
|
|
291
|
+
maxRareValues: 12,
|
|
292
|
+
maxPatterns: 10,
|
|
293
|
+
minRareScalePropertyOccurrences: 10,
|
|
294
|
+
rareScaleMaxFiles: 2,
|
|
295
|
+
rareScaleMaxCount: 3,
|
|
296
|
+
},
|
|
255
297
|
// Never suggest replacements for classes matching these patterns
|
|
256
298
|
ignorePatterns: [/^font-/, /-\[var\(/],
|
|
257
299
|
}
|
|
@@ -263,6 +305,20 @@ export default {
|
|
|
263
305
|
|
|
264
306
|
`functionNames` enables scanning inside utility function calls like `cn(...)` and `clsx(...)`.
|
|
265
307
|
|
|
308
|
+
`analyze` controls project-scale consistency reporting. `maxScaleGroups`,
|
|
309
|
+
`maxScaleValues`, `maxRareValues`, and `maxPatterns` keep terminal output
|
|
310
|
+
compact. `minRareScalePropertyOccurrences`, `rareScaleMaxFiles`, and
|
|
311
|
+
`rareScaleMaxCount` control which low-frequency values are surfaced as rare
|
|
312
|
+
scale values. Defaults are conservative: only properties with 10+ total
|
|
313
|
+
occurrences are considered, and a value is rare when it appears in at most 2
|
|
314
|
+
files and at most 3 times.
|
|
315
|
+
|
|
316
|
+
The older top-level rare-value keys are still accepted for compatibility, but
|
|
317
|
+
new configs should prefer `analyze`.
|
|
318
|
+
|
|
319
|
+
`tailwind-canonical.config.js` is still loaded as a fallback when no TypeScript
|
|
320
|
+
config exists.
|
|
321
|
+
|
|
266
322
|
## ESLint plugin
|
|
267
323
|
|
|
268
324
|
```js
|
|
@@ -281,6 +337,26 @@ export default [
|
|
|
281
337
|
]
|
|
282
338
|
```
|
|
283
339
|
|
|
340
|
+
### Rule options
|
|
341
|
+
|
|
342
|
+
`no-arbitrary-canonical` accepts the full tailwind-canonical `Config` object as
|
|
343
|
+
its rule options, so the same shared config can be reused for both the CLI and
|
|
344
|
+
ESLint without schema errors:
|
|
345
|
+
|
|
346
|
+
```js
|
|
347
|
+
'tailwind-canonical/no-arbitrary-canonical': [
|
|
348
|
+
'warn',
|
|
349
|
+
{ customTextTokens: { 11: '2xs' }, ignorePatterns: [/^font-/] },
|
|
350
|
+
],
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The rule **honors**: `customTextTokens`, `customSpacingTokens`, `ignorePatterns`
|
|
354
|
+
(all applied via `suggestCanonical`).
|
|
355
|
+
|
|
356
|
+
It **accepts but ignores**: `functionNames`, `attributeNames`, `sortOrder`.
|
|
357
|
+
These are CLI-only options, allowed in the schema purely so a single shared
|
|
358
|
+
config object can be passed without errors.
|
|
359
|
+
|
|
284
360
|
## Pre-commit hook (Husky / Lefthook)
|
|
285
361
|
|
|
286
362
|
```yaml
|
|
@@ -309,7 +385,7 @@ npx tailwind-canonical --fix --dedup --sort ./src ./app
|
|
|
309
385
|
pnpm knip
|
|
310
386
|
```
|
|
311
387
|
|
|
312
|
-
Detects unused exports, files, and dependencies. Config in `knip.json`.
|
|
388
|
+
Detects unused exports, files, and dependencies. Config in `knip.json`. Enforced in CI and in the `pre-push` git hook.
|
|
313
389
|
|
|
314
390
|
## Programmatic API
|
|
315
391
|
|
package/dist/cli/cli.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export type Sink = {
|
|
|
3
3
|
error: (s: string) => void;
|
|
4
4
|
write: (s: string) => void;
|
|
5
5
|
};
|
|
6
|
-
export declare const defaultSink: Sink;
|
|
7
6
|
export type RunResult = {
|
|
8
7
|
exitCode: number;
|
|
9
8
|
watching?: boolean;
|
|
@@ -16,10 +15,19 @@ type Flags = {
|
|
|
16
15
|
sort: boolean;
|
|
17
16
|
watch: boolean;
|
|
18
17
|
analyze: boolean;
|
|
18
|
+
typos: boolean;
|
|
19
19
|
reporter: Reporter;
|
|
20
20
|
targets: string[];
|
|
21
|
+
error?: string;
|
|
21
22
|
};
|
|
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[];
|
|
23
31
|
export declare function run(argv: string[], cwd: string, sink?: Sink): Promise<RunResult>;
|
|
24
32
|
export {};
|
|
25
33
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli/cli.ts"],"names":[],"mappings":"AAwBA,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;AA2IF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,CAqD/C;AASD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAwBnD;AAgbD,wBAAsB,GAAG,CACvB,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,IAAkB,GACvB,OAAO,CAAC,SAAS,CAAC,CAqLpB"}
|