@tailwind-ts/eslint-plugin 0.1.0 → 0.2.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 +97 -0
- package/package.json +1 -21
package/README.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
ESLint plugin for detecting invalid Tailwind CSS v4 class names — typos, undefined utilities, and bad `@apply` usage — in JavaScript, TypeScript, CSS, and Vue projects.
|
|
4
4
|
|
|
5
|
+
## What's new in v0.2.0
|
|
6
|
+
|
|
7
|
+
- **`cva()` variant validation** — lints base classes and variant values inside `class-variance-authority` configs
|
|
8
|
+
- **CSS `@apply` linting** — new `no-invalid-apply` rule for `.css` files
|
|
9
|
+
- **Typo suggestions** — reports `Did you mean "flex"?` when a close match exists
|
|
10
|
+
- **Import-aware helpers** — validates `cn()` / `clsx()` when imported from `@/lib/utils`
|
|
11
|
+
- **Vue `:class` support** — lints class bindings in `.vue` files
|
|
12
|
+
- **`tv()` helper** — tailwind-variants added to defaults
|
|
13
|
+
- **Config presets** — `react`, `vue`, and `css` presets
|
|
14
|
+
- **Multi-entry CSS** — `cssConfigPath` accepts a string or array for monorepos
|
|
15
|
+
- **Batch validation** — faster lint runs via batched worker calls and shared cache
|
|
16
|
+
|
|
5
17
|
## Features
|
|
6
18
|
|
|
7
19
|
- **`cva()` variant validation** — lints base classes and variant values inside `class-variance-authority` configs
|
|
@@ -84,6 +96,19 @@ export default [
|
|
|
84
96
|
| `vue` | `*.{vue,js,ts}` | Enables `:class` parsing (requires `vue-eslint-parser`) |
|
|
85
97
|
| `css` | `**/*.css` | Enables `@apply` validation |
|
|
86
98
|
|
|
99
|
+
Combine presets for full-stack apps:
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
export default [
|
|
103
|
+
{
|
|
104
|
+
extends: [tailwindTs.configs.react, tailwindTs.configs.css],
|
|
105
|
+
settings: {
|
|
106
|
+
tailwindTs: { cssConfigPath: "./src/styles/tailwind.css" },
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
```
|
|
111
|
+
|
|
87
112
|
## Rules
|
|
88
113
|
|
|
89
114
|
| Rule | Description | Default |
|
|
@@ -91,6 +116,61 @@ export default [
|
|
|
91
116
|
| [`no-invalid-classname`](./docs/rules/no-invalid-classname.md) | Disallow invalid Tailwind classes in JSX, helpers, and Vue bindings | `error` |
|
|
92
117
|
| [`no-invalid-apply`](./docs/rules/no-invalid-apply.md) | Disallow invalid classes in CSS `@apply` directives | `error` |
|
|
93
118
|
|
|
119
|
+
Both rules share the same Tailwind design-system validator and support typo suggestions.
|
|
120
|
+
|
|
121
|
+
## Examples
|
|
122
|
+
|
|
123
|
+
### JSX typo with suggestion
|
|
124
|
+
|
|
125
|
+
```jsx
|
|
126
|
+
// error: Class "flexs" is not a valid Tailwind CSS class. Did you mean "flex"?
|
|
127
|
+
<div className="flexs items-center" />
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `cva()` variant values
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
import { cva } from "class-variance-authority";
|
|
134
|
+
|
|
135
|
+
const button = cva("rounded-lg", {
|
|
136
|
+
variants: {
|
|
137
|
+
size: {
|
|
138
|
+
sm: "p-2 text-lgg", // error on "text-lgg"
|
|
139
|
+
md: "p-4 text-base",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### CSS `@apply`
|
|
146
|
+
|
|
147
|
+
```css
|
|
148
|
+
.card {
|
|
149
|
+
@apply flexs items-center rounded-lg; /* error */
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Import-aware `cn()`
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import { cn } from "@/lib/utils";
|
|
157
|
+
|
|
158
|
+
<div className={cn("p-4", "text-lgg")} />
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Monorepo CSS entries
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
settings: {
|
|
165
|
+
tailwindTs: {
|
|
166
|
+
cssConfigPath: [
|
|
167
|
+
"./apps/web/src/styles/tailwind.css",
|
|
168
|
+
"./apps/admin/src/styles/tailwind.css",
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
```
|
|
173
|
+
|
|
94
174
|
## Settings
|
|
95
175
|
|
|
96
176
|
| Option | Type | Default | Description |
|
|
@@ -99,7 +179,10 @@ export default [
|
|
|
99
179
|
| `attributes` | `string[]` | `["class", "className"]` | JSX/Vue attributes to lint |
|
|
100
180
|
| `functions` | `string[]` | `["cn", "clsx", "cva", "tv", "twMerge", "twJoin"]` | Helper calls to lint |
|
|
101
181
|
| `whitelist` | `string[]` | `[]` | Regex patterns for allowed non-Tailwind classes |
|
|
182
|
+
| `ignoredKeys` | `string[]` | `["defaultVariants", "compoundVariants", "compoundSlots"]` | Object keys skipped in helper calls |
|
|
102
183
|
| `suggestSimilarClasses` | `boolean` | `true` | Include "Did you mean …?" hints for typos |
|
|
184
|
+
| `cacheMaxAge` | `number` | `600000` | Validation cache TTL in ms (10 min) |
|
|
185
|
+
| `cacheMaxSize` | `number` | `250000` | Max cached validation entries |
|
|
103
186
|
|
|
104
187
|
### Typesafe settings
|
|
105
188
|
|
|
@@ -109,6 +192,7 @@ settings: {
|
|
|
109
192
|
/** @type {import('@tailwind-ts/eslint-plugin').PluginSettings} */
|
|
110
193
|
({
|
|
111
194
|
cssConfigPath: "./src/styles/tailwind.css",
|
|
195
|
+
suggestSimilarClasses: true,
|
|
112
196
|
}),
|
|
113
197
|
},
|
|
114
198
|
```
|
|
@@ -116,8 +200,21 @@ settings: {
|
|
|
116
200
|
## Limitations
|
|
117
201
|
|
|
118
202
|
- Dynamic template interpolation (e.g. `` className={`p-${size}`} ``) is not validated
|
|
203
|
+
- Spread props (`className={props.className}`) are skipped unless the value is a static literal upstream
|
|
119
204
|
- Vue support requires `vue-eslint-parser` in your ESLint config
|
|
120
205
|
|
|
206
|
+
## Migration from v0.1.0
|
|
207
|
+
|
|
208
|
+
No breaking changes to rule names or settings. v0.2.0 adds optional presets and the `no-invalid-apply` rule via `configs.css`.
|
|
209
|
+
|
|
210
|
+
```js
|
|
211
|
+
// v0.1.0 — still works
|
|
212
|
+
extends: [tailwindTs.configs.recommended]
|
|
213
|
+
|
|
214
|
+
// v0.2.0 — add CSS @apply linting
|
|
215
|
+
extends: [tailwindTs.configs.recommended, tailwindTs.configs.css]
|
|
216
|
+
```
|
|
217
|
+
|
|
121
218
|
## License
|
|
122
219
|
|
|
123
220
|
MIT
|
package/package.json
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailwind-ts/eslint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "ESLint plugin for detecting invalid Tailwind CSS v4 class names with cva, @apply, and typo suggestions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"author": "",
|
|
8
7
|
"repository": {
|
|
9
8
|
"type": "git",
|
|
10
9
|
"url": "git+https://github.com/tailwind-ts/eslint-plugin.git"
|
|
@@ -47,12 +46,6 @@
|
|
|
47
46
|
"docs/",
|
|
48
47
|
"lib/"
|
|
49
48
|
],
|
|
50
|
-
"scripts": {
|
|
51
|
-
"build": "unbuild --config unbuild.config.ts && node scripts/copy-worker.mjs",
|
|
52
|
-
"test": "vitest run",
|
|
53
|
-
"lint": "eslint .",
|
|
54
|
-
"prepublishOnly": "npm run build && npm test"
|
|
55
|
-
},
|
|
56
49
|
"dependencies": {
|
|
57
50
|
"@typescript-eslint/utils": "^8.37.0",
|
|
58
51
|
"synckit": "^0.11.11"
|
|
@@ -69,18 +62,5 @@
|
|
|
69
62
|
"vue-eslint-parser": {
|
|
70
63
|
"optional": true
|
|
71
64
|
}
|
|
72
|
-
},
|
|
73
|
-
"devDependencies": {
|
|
74
|
-
"@eslint/js": "^9.31.0",
|
|
75
|
-
"@tailwindcss/node": "^4.3.2",
|
|
76
|
-
"@types/node": "^22.15.0",
|
|
77
|
-
"@typescript-eslint/parser": "^8.37.0",
|
|
78
|
-
"@typescript-eslint/rule-tester": "^8.37.0",
|
|
79
|
-
"eslint": "^9.31.0",
|
|
80
|
-
"tailwindcss": "^4.3.2",
|
|
81
|
-
"typescript": "^5.9.2",
|
|
82
|
-
"typescript-eslint": "^8.42.0",
|
|
83
|
-
"unbuild": "^3.3.1",
|
|
84
|
-
"vitest": "^3.2.4"
|
|
85
65
|
}
|
|
86
66
|
}
|