tailwind-typescript-plugin 1.4.0-beta.13 → 1.4.0-beta.16

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.
Files changed (71) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +212 -143
  3. package/lib/core/interfaces.d.ts +17 -12
  4. package/lib/core/interfaces.d.ts.map +1 -1
  5. package/lib/core/types.d.ts +81 -0
  6. package/lib/core/types.d.ts.map +1 -1
  7. package/lib/extractors/JsxAttributeExtractor.d.ts +2 -1
  8. package/lib/extractors/JsxAttributeExtractor.d.ts.map +1 -1
  9. package/lib/extractors/JsxAttributeExtractor.js +13 -7
  10. package/lib/extractors/JsxAttributeExtractor.js.map +1 -1
  11. package/lib/extractors/SvelteAttributeExtractor.d.ts +17 -0
  12. package/lib/extractors/SvelteAttributeExtractor.d.ts.map +1 -0
  13. package/lib/extractors/SvelteAttributeExtractor.js +27 -0
  14. package/lib/extractors/SvelteAttributeExtractor.js.map +1 -0
  15. package/lib/extractors/VueAttributeExtractor.d.ts +18 -0
  16. package/lib/extractors/VueAttributeExtractor.d.ts.map +1 -0
  17. package/lib/extractors/VueAttributeExtractor.js +28 -0
  18. package/lib/extractors/VueAttributeExtractor.js.map +1 -0
  19. package/lib/infrastructure/TailwindValidator.css-vars.spec.js +1 -11
  20. package/lib/infrastructure/TailwindValidator.css-vars.spec.js.map +1 -1
  21. package/lib/infrastructure/TailwindValidator.d.ts +1 -3
  22. package/lib/infrastructure/TailwindValidator.d.ts.map +1 -1
  23. package/lib/infrastructure/TailwindValidator.js +6 -26
  24. package/lib/infrastructure/TailwindValidator.js.map +1 -1
  25. package/lib/infrastructure/TailwindValidator.spec.js +7 -17
  26. package/lib/infrastructure/TailwindValidator.spec.js.map +1 -1
  27. package/lib/plugin/TailwindTypescriptPlugin.d.ts +0 -1
  28. package/lib/plugin/TailwindTypescriptPlugin.d.ts.map +1 -1
  29. package/lib/plugin/TailwindTypescriptPlugin.js +29 -66
  30. package/lib/plugin/TailwindTypescriptPlugin.js.map +1 -1
  31. package/lib/services/ClassNameExtractionService.d.ts +19 -3
  32. package/lib/services/ClassNameExtractionService.d.ts.map +1 -1
  33. package/lib/services/ClassNameExtractionService.js +74 -13
  34. package/lib/services/ClassNameExtractionService.js.map +1 -1
  35. package/lib/services/ClassNameExtractionService.spec.d.ts +2 -0
  36. package/lib/services/ClassNameExtractionService.spec.d.ts.map +1 -0
  37. package/lib/services/ClassNameExtractionService.spec.js +160 -0
  38. package/lib/services/ClassNameExtractionService.spec.js.map +1 -0
  39. package/lib/services/CodeActionService.spec.js +1 -2
  40. package/lib/services/CodeActionService.spec.js.map +1 -1
  41. package/lib/services/CompletionService.d.ts +1 -3
  42. package/lib/services/CompletionService.d.ts.map +1 -1
  43. package/lib/services/CompletionService.js +1 -12
  44. package/lib/services/CompletionService.js.map +1 -1
  45. package/lib/services/CompletionService.spec.js +11 -12
  46. package/lib/services/CompletionService.spec.js.map +1 -1
  47. package/lib/services/ConflictClassDetection.spec.js +5 -5
  48. package/lib/services/ConflictClassDetection.spec.js.map +1 -1
  49. package/lib/services/DiagnosticService.d.ts +8 -8
  50. package/lib/services/DiagnosticService.d.ts.map +1 -1
  51. package/lib/services/DiagnosticService.js +29 -13
  52. package/lib/services/DiagnosticService.js.map +1 -1
  53. package/lib/services/DuplicateClassDetection.spec.js +20 -21
  54. package/lib/services/DuplicateClassDetection.spec.js.map +1 -1
  55. package/lib/services/PluginConfigService.d.ts +38 -15
  56. package/lib/services/PluginConfigService.d.ts.map +1 -1
  57. package/lib/services/PluginConfigService.js +182 -82
  58. package/lib/services/PluginConfigService.js.map +1 -1
  59. package/lib/services/ValidationService.d.ts +5 -4
  60. package/lib/services/ValidationService.d.ts.map +1 -1
  61. package/lib/services/ValidationService.js +39 -42
  62. package/lib/services/ValidationService.js.map +1 -1
  63. package/lib/utils/FrameworkDetector.d.ts +24 -0
  64. package/lib/utils/FrameworkDetector.d.ts.map +1 -0
  65. package/lib/utils/FrameworkDetector.js +52 -0
  66. package/lib/utils/FrameworkDetector.js.map +1 -0
  67. package/lib/utils/FrameworkDetector.spec.d.ts +2 -0
  68. package/lib/utils/FrameworkDetector.spec.d.ts.map +1 -0
  69. package/lib/utils/FrameworkDetector.spec.js +75 -0
  70. package/lib/utils/FrameworkDetector.spec.js.map +1 -0
  71. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ## [1.4.0-beta.16](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.15...v1.4.0-beta.16) (2025-12-03)
2
+
3
+ ### ✨ Features
4
+
5
+ * add support for 'class' attribute in JSX elements ([258fe3e](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/258fe3e0006ebf8a9a5cdbdfe8c09ef39a2d9d4d))
6
+
7
+ ## [1.4.0-beta.15](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.14...v1.4.0-beta.15) (2025-12-02)
8
+
9
+ ### ♻️ Code Refactoring
10
+
11
+ * add multi-framework architecture with lazy initialization ([a403e18](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/a403e1869d92f8b926dc40a9e6eedc0bec55e06c))
12
+
13
+ ## [1.4.0-beta.14](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.13...v1.4.0-beta.14) (2025-12-02)
14
+
15
+ ### ⚠ BREAKING CHANGES
16
+
17
+ * Old config format no longer supported
18
+
19
+ ### ♻️ Code Refactoring
20
+
21
+ * restructure plugin configuration ([00c8816](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/commit/00c881612449e4c424c129f4994c57117d94d3c4))
22
+
1
23
  ## [1.4.0-beta.13](https://github.com/IvanRodriCalleja/tailwind-typescript-plugin/compare/v1.4.0-beta.12...v1.4.0-beta.13) (2025-11-30)
2
24
 
3
25
  ### ✨ Features
package/README.md CHANGED
@@ -59,6 +59,21 @@ pnpm add tailwind-typescript-plugin
59
59
 
60
60
  Add the plugin to the `compilerOptions.plugins` array in your `tsconfig.json`:
61
61
 
62
+ ```json
63
+ {
64
+ "compilerOptions": {
65
+ "plugins": [
66
+ {
67
+ "name": "tailwind-typescript-plugin",
68
+ "globalCss": "./src/global.css"
69
+ }
70
+ ]
71
+ }
72
+ }
73
+ ```
74
+
75
+ **Full configuration example with all options:**
76
+
62
77
  ```json
63
78
  {
64
79
  "compilerOptions": {
@@ -66,11 +81,41 @@ Add the plugin to the `compilerOptions.plugins` array in your `tsconfig.json`:
66
81
  {
67
82
  "name": "tailwind-typescript-plugin",
68
83
  "globalCss": "./src/global.css",
69
- "utilityFunctions": ["clsx", "cn", "classnames"],
70
- "allowedClasses": ["custom-button", "app-header", "project-card"],
71
- "variants": {
72
- "tailwindVariants": true,
73
- "classVarianceAuthority": true
84
+ "libraries": {
85
+ "utilities": {
86
+ "cn": "@/lib/utils",
87
+ "merge": "tailwind-merge",
88
+ "myFn": "*"
89
+ },
90
+ "variants": {
91
+ "tailwindVariants": true,
92
+ "classVarianceAuthority": true
93
+ }
94
+ },
95
+ "validation": {
96
+ "enabled": true,
97
+ "severity": "error",
98
+ "allowedClasses": ["custom-*", "app-*"]
99
+ },
100
+ "lint": {
101
+ "enabled": true,
102
+ "conflictingClasses": {
103
+ "enabled": true,
104
+ "severity": "warning"
105
+ },
106
+ "repeatedClasses": {
107
+ "enabled": true,
108
+ "severity": "warning"
109
+ }
110
+ },
111
+ "editor": {
112
+ "enabled": true,
113
+ "autocomplete": {
114
+ "enabled": true
115
+ },
116
+ "hover": {
117
+ "enabled": true
118
+ }
74
119
  }
75
120
  }
76
121
  ]
@@ -80,159 +125,183 @@ Add the plugin to the `compilerOptions.plugins` array in your `tsconfig.json`:
80
125
 
81
126
  **Configuration options:**
82
127
 
83
- - `globalCss` (required): Path to your global CSS file that imports Tailwind CSS. This can be relative to your project root.
84
-
85
- - `allowedClasses` (optional): Array of custom class names or wildcard patterns that should be treated as valid alongside Tailwind classes. Useful for project-specific or third-party utility classes that aren't part of Tailwind.
86
- - **Default**: `[]` (no custom classes allowed)
87
- - **Supports wildcard patterns**:
88
- | Pattern | Description | Example | Matches |
89
- |---------|-------------|---------|---------|
90
- | `prefix-*` | Matches classes starting with prefix | `custom-*` | `custom-button`, `custom-card` |
91
- | `*-suffix` | Matches classes ending with suffix | `*-icon` | `arrow-icon`, `close-icon` |
92
- | `*-contains-*` | Matches classes containing the string | `*-component-*` | `app-component-header` |
93
- | `exact` | Exact match (no wildcards) | `my-class` | Only `my-class` |
94
- - **Example**:
95
- ```json
96
- {
97
- "allowedClasses": [
98
- "custom-*",
99
- "*-icon",
100
- "*-component-*",
101
- "exact-class"
102
- ]
103
- }
104
- ```
105
- - Classes matching any pattern will be considered valid and won't trigger validation errors
106
- - Works with all extraction patterns (literals, expressions, functions, arrays, etc.)
107
- - Combines with Tailwind classes - both are validated independently
108
-
109
- - `variants` (optional): Configure which variant library extractors to enable. This is useful for performance optimization when you only use one library.
110
- - **Default behavior (no config)**: Both `tailwind-variants` and `class-variance-authority` are enabled
111
- - **Selective enabling**: If you specify ANY variant config, only those explicitly set to `true` are enabled
112
- - **Example configurations**:
113
- ```json
114
- // Enable only tailwind-variants
115
- {
116
- "variants": {
117
- "tailwindVariants": true
118
- }
119
- }
128
+ #### `globalCss` (required)
129
+ Path to your global CSS file that imports Tailwind CSS. This can be relative to your project root.
120
130
 
121
- // Enable only class-variance-authority
122
- {
123
- "variants": {
124
- "classVarianceAuthority": true
125
- }
126
- }
131
+ ---
127
132
 
128
- // Enable both explicitly
129
- {
130
- "variants": {
131
- "tailwindVariants": true,
132
- "classVarianceAuthority": true
133
- }
134
- }
133
+ #### `libraries` (optional)
134
+ Configure utility functions and variant libraries.
135
135
 
136
- // No config = both enabled by default
137
- {
138
- // variants not specified - both libraries validated
139
- }
140
- ```
141
- - **Performance impact**: Disabling unused extractors skips TypeChecker operations and symbol resolution for that library, providing faster validation
136
+ ##### `libraries.utilities`
137
+ Configure which utility functions to scan for class names. Keys are function names, values control import matching:
142
138
 
143
- - `utilityFunctions` (optional): Array of utility functions to validate. These will be **merged with the defaults**, so you don't lose the common ones. Supports two formats:
139
+ | Value | Description |
140
+ |-------|-------------|
141
+ | `"*"` | Match any import source |
142
+ | `"off"` | Disable this utility function |
143
+ | `"package-name"` | Only match if imported from this package |
144
144
 
145
- **Simple string format** (matches by function name only):
146
- ```json
147
- {
148
- "utilityFunctions": ["myCustomFn", "buildClasses"]
145
+ **Defaults** (automatically included):
146
+ ```json
147
+ {
148
+ "cn": "*",
149
+ "clsx": "clsx",
150
+ "classnames": "classnames",
151
+ "classNames": "classnames",
152
+ "cx": "classnames",
153
+ "twMerge": "tailwind-merge"
154
+ }
155
+ ```
156
+
157
+ **Example - Add custom utility and disable a default**:
158
+ ```json
159
+ {
160
+ "libraries": {
161
+ "utilities": {
162
+ "myMerge": "@/lib/utils",
163
+ "clsx": "off"
164
+ }
149
165
  }
150
- ```
151
-
152
- **Object format with import verification** (matches by name AND verifies import source):
153
- ```json
154
- {
155
- "utilityFunctions": [
156
- { "name": "merge", "from": "@/lib/utils" },
157
- { "name": "cx", "from": "my-styling-package" }
158
- ]
166
+ }
167
+ ```
168
+
169
+ **Supported import patterns**:
170
+ ```typescript
171
+ // Named import
172
+ import { merge } from '@/lib/utils';
173
+ className={merge('flex', 'items-center')} // Validated
174
+
175
+ // Default import
176
+ import merge from '@/lib/utils';
177
+ className={merge('flex', 'items-center')} // ✅ Validated
178
+
179
+ // Namespace import
180
+ import * as utils from '@/lib/utils';
181
+ className={utils.merge('flex', 'items-center')} // ✅ Validated
182
+
183
+ // Aliased import
184
+ import { something as merge } from '@/lib/utils';
185
+ className={merge('flex', 'items-center')} // ✅ Validated
186
+ ```
187
+
188
+ ##### `libraries.variants`
189
+ Configure which variant library extractors to enable.
190
+
191
+ | Option | Default | Description |
192
+ |--------|---------|-------------|
193
+ | `tailwindVariants` | `true` | Enable `tv()` function support |
194
+ | `classVarianceAuthority` | `true` | Enable `cva()` function support |
195
+
196
+ **Example - Enable only tailwind-variants**:
197
+ ```json
198
+ {
199
+ "libraries": {
200
+ "variants": {
201
+ "tailwindVariants": true,
202
+ "classVarianceAuthority": false
203
+ }
159
204
  }
160
- ```
161
-
162
- **Mixed format** (combine both):
163
- ```json
164
- {
165
- "utilityFunctions": [
166
- "anyFunctionNamedThis",
167
- { "name": "merge", "from": "@/lib/utils" }
168
- ]
205
+ }
206
+ ```
207
+
208
+ ---
209
+
210
+ #### `validation` (optional)
211
+ Configure invalid class detection.
212
+
213
+ | Option | Default | Description |
214
+ |--------|---------|-------------|
215
+ | `enabled` | `true` | Enable/disable invalid class validation |
216
+ | `severity` | `"error"` | `"error"` \| `"warning"` \| `"suggestion"` \| `"off"` |
217
+ | `allowedClasses` | `[]` | Custom class patterns to allow |
218
+
219
+ ##### `validation.allowedClasses`
220
+ Array of custom class names or wildcard patterns that should be treated as valid.
221
+
222
+ | Pattern | Description | Example | Matches |
223
+ |---------|-------------|---------|---------|
224
+ | `prefix-*` | Matches classes starting with prefix | `custom-*` | `custom-button`, `custom-card` |
225
+ | `*-suffix` | Matches classes ending with suffix | `*-icon` | `arrow-icon`, `close-icon` |
226
+ | `*-contains-*` | Matches classes containing the string | `*-component-*` | `app-component-header` |
227
+ | `exact` | Exact match (no wildcards) | `my-class` | Only `my-class` |
228
+
229
+ **Example**:
230
+ ```json
231
+ {
232
+ "validation": {
233
+ "allowedClasses": ["custom-*", "*-icon", "exact-class"]
169
234
  }
170
- ```
235
+ }
236
+ ```
237
+
238
+ ---
171
239
 
172
- - **Defaults (always included)**: `clsx` (from 'clsx'), `cn` (name-only), `classnames`/`classNames`/`cx` (from 'classnames'), `twMerge` (from 'tailwind-merge'). Note: `cva` and `tv` are variant functions handled by dedicated extractors.
173
- - **Import verification**: When using the object format with `from`, the plugin verifies the function is actually imported from that package before validating. This prevents false positives when a function with the same name exists but isn't a className utility.
174
- - **Subpath matching**: `{ "name": "fn", "from": "my-pkg" }` also matches `import { fn } from 'my-pkg/utils'`
240
+ #### `lint` (optional)
241
+ Configure lint rules for code quality issues.
175
242
 
176
- **Example configurations**:
177
- ```json
178
- // Simple: just add function names
179
- {
180
- "utilityFunctions": ["myCustomFn", "buildClasses"]
243
+ | Option | Default | Description |
244
+ |--------|---------|-------------|
245
+ | `enabled` | `true` | Master switch for all lint rules |
246
+ | `conflictingClasses` | `{ enabled: true, severity: "warning" }` | Detect conflicting utilities |
247
+ | `repeatedClasses` | `{ enabled: true, severity: "warning" }` | Detect duplicate classes |
248
+
249
+ **Example - Disable conflicting class detection**:
250
+ ```json
251
+ {
252
+ "lint": {
253
+ "conflictingClasses": {
254
+ "enabled": false
255
+ }
181
256
  }
257
+ }
258
+ ```
182
259
 
183
- // Precise: verify import sources
184
- {
185
- "utilityFunctions": [
186
- { "name": "cn", "from": "@/lib/utils" },
187
- { "name": "merge", "from": "tailwind-merge" }
188
- ]
260
+ **Example - Make duplicate classes an error**:
261
+ ```json
262
+ {
263
+ "lint": {
264
+ "repeatedClasses": {
265
+ "severity": "error"
266
+ }
189
267
  }
268
+ }
269
+ ```
190
270
 
191
- // Mixed: some with import verification, some without
192
- {
193
- "utilityFunctions": [
194
- "anyFn",
195
- { "name": "preciseFn", "from": "@/utils" }
196
- ]
271
+ ---
272
+
273
+ #### `editor` (optional)
274
+ Configure editor features like autocomplete and hover.
275
+
276
+ | Option | Default | Description |
277
+ |--------|---------|-------------|
278
+ | `enabled` | `true` | Master switch for all editor features |
279
+ | `autocomplete.enabled` | `true` | Enable Tailwind class autocomplete |
280
+ | `hover.enabled` | `true` | Enable hover information showing CSS |
281
+
282
+ **Example - Disable autocomplete**:
283
+ ```json
284
+ {
285
+ "editor": {
286
+ "autocomplete": {
287
+ "enabled": false
288
+ }
197
289
  }
198
- ```
199
-
200
- **Supported import patterns**:
201
- ```typescript
202
- // Named import
203
- import { merge } from '@/lib/utils';
204
- className={merge('flex', 'items-center')} // ✅ Validated
205
-
206
- // Default import
207
- import merge from '@/lib/utils';
208
- className={merge('flex', 'items-center')} // ✅ Validated
209
-
210
- // Aliased import
211
- import { something as merge } from '@/lib/utils';
212
- className={merge('flex', 'items-center')} // ✅ Validated
213
-
214
- // Wrong import source (not validated when using object format)
215
- import { merge } from 'different-package';
216
- className={merge('flex', 'invalid-class')} // ⏭️ Skipped (wrong import)
217
- ```
218
-
219
- **Supported call patterns**:
220
- ```typescript
221
- // Simple calls (validated by default):
222
- className={clsx('flex', 'items-center')}
223
- className={cn('flex', 'items-center')}
224
-
225
- // Member expressions (nested property access):
226
- className={utils.cn('flex', 'items-center')}
227
- className={lib.clsx('flex', 'items-center')}
228
-
229
- // Custom functions (add via config):
230
- className={myCustomFn('flex', 'items-center')}
231
- className={buildClasses('flex', 'items-center')}
232
-
233
- // Dynamic calls (ignored, won't throw errors):
234
- className={functions['cn']('flex', 'items-center')}
235
- ```
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ### Backwards Compatibility
296
+
297
+ The following deprecated options are still supported but will be removed in a future version:
298
+
299
+ | Deprecated | New Location |
300
+ |------------|--------------|
301
+ | `utilityFunctions` | `libraries.utilities` |
302
+ | `variants` | `libraries.variants` |
303
+ | `allowedClasses` | `validation.allowedClasses` |
304
+ | `enableLogging` | Removed (no replacement) |
236
305
 
237
306
  ### 2. Ensure your CSS file imports Tailwind
238
307
 
@@ -1,5 +1,5 @@
1
1
  import * as ts from 'typescript/lib/tsserverlibrary';
2
- import { ClassNameInfo, ExtractionContext, UtilityFunction } from './types';
2
+ import { ClassNameInfo, EditorConfig, ExtractionContext, LibrariesConfig, LintConfig, ValidationConfig } from './types';
3
3
  /**
4
4
  * Base interface for class name extractors
5
5
  * Follows the Strategy pattern for extensibility
@@ -22,22 +22,27 @@ export interface IClassNameValidator {
22
22
  isInitialized(): boolean;
23
23
  setAllowedClasses(allowedClasses: string[]): void;
24
24
  }
25
- /**
26
- * Interface for variant library configuration
27
- */
28
- export interface IVariantsConfig {
29
- tailwindVariants?: boolean;
30
- classVarianceAuthority?: boolean;
31
- }
32
25
  /**
33
26
  * Interface for configuration management
34
27
  */
35
28
  export interface IPluginConfig {
36
29
  globalCss?: string;
37
- utilityFunctions?: UtilityFunction[];
38
- variants?: IVariantsConfig;
39
- allowedClasses?: string[];
40
- enableLogging?: boolean;
30
+ /**
31
+ * Library configurations (utilities and variants)
32
+ */
33
+ libraries?: LibrariesConfig;
34
+ /**
35
+ * Validation configuration (invalid class detection)
36
+ */
37
+ validation?: ValidationConfig;
38
+ /**
39
+ * Lint configuration (conflicting and repeated classes)
40
+ */
41
+ lint?: LintConfig;
42
+ /**
43
+ * Editor features configuration (autocomplete and hover)
44
+ */
45
+ editor?: EditorConfig;
41
46
  }
42
47
  /**
43
48
  * Interface for diagnostic creation
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAE9D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC;CACrF"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EACN,aAAa,EACb,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAE9D;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAAC;CACpE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,aAAa,IAAI,OAAO,CAAC;IACzB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B;;OAEG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAE9B;;OAEG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,gBAAgB,CAAC,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC;CACrF"}
@@ -1,4 +1,5 @@
1
1
  import * as ts from 'typescript/lib/tsserverlibrary';
2
+ import { Framework } from '../utils/FrameworkDetector';
2
3
  /**
3
4
  * Represents a utility function configuration with optional import source
4
5
  * When 'from' is specified, the import will be verified before matching
@@ -6,6 +7,8 @@ import * as ts from 'typescript/lib/tsserverlibrary';
6
7
  * Examples:
7
8
  * - { name: 'clsx', from: 'clsx' } - matches `import { clsx } from 'clsx'` or `import clsx from 'clsx'`
8
9
  * - { name: 'cn', from: '@/lib/utils' } - matches `import { cn } from '@/lib/utils'`
10
+ *
11
+ * @deprecated Use the new libraries.utilities config format instead
9
12
  */
10
13
  export interface UtilityFunctionConfig {
11
14
  name: string;
@@ -15,8 +18,81 @@ export interface UtilityFunctionConfig {
15
18
  * A utility function can be either:
16
19
  * - A simple string (matches by function name only, backwards compatible)
17
20
  * - A UtilityFunctionConfig object (matches by name AND verifies import source)
21
+ *
22
+ * @deprecated Use the new libraries.utilities config format instead
18
23
  */
19
24
  export type UtilityFunction = string | UtilityFunctionConfig;
25
+ /**
26
+ * Severity level for diagnostics
27
+ */
28
+ export type DiagnosticSeverity = 'error' | 'warning' | 'suggestion' | 'off';
29
+ /**
30
+ * Configuration for utilities (utility functions like cn, clsx, etc.)
31
+ * Key is the function name, value is:
32
+ * - string: import path (e.g., "clsx", "@/lib/utils")
33
+ * - "*": match any import source
34
+ * - "off": disable this utility function
35
+ */
36
+ export type UtilitiesConfig = {
37
+ [functionName: string]: string;
38
+ };
39
+ /**
40
+ * Configuration for variant libraries
41
+ */
42
+ export interface VariantsConfig {
43
+ tailwindVariants?: boolean;
44
+ classVarianceAuthority?: boolean;
45
+ }
46
+ /**
47
+ * Configuration for libraries (utilities and variants)
48
+ */
49
+ export interface LibrariesConfig {
50
+ utilities?: UtilitiesConfig;
51
+ variants?: VariantsConfig;
52
+ }
53
+ /**
54
+ * Configuration for validation (invalid class detection)
55
+ */
56
+ export interface ValidationConfig {
57
+ enabled?: boolean;
58
+ severity?: DiagnosticSeverity;
59
+ allowedClasses?: string[];
60
+ }
61
+ /**
62
+ * Configuration for a single lint rule
63
+ */
64
+ export interface LintRuleConfig {
65
+ enabled?: boolean;
66
+ severity?: DiagnosticSeverity;
67
+ }
68
+ /**
69
+ * Configuration for lint rules
70
+ */
71
+ export interface LintConfig {
72
+ enabled?: boolean;
73
+ conflictingClasses?: LintRuleConfig;
74
+ repeatedClasses?: LintRuleConfig;
75
+ }
76
+ /**
77
+ * Configuration for autocomplete
78
+ */
79
+ export interface AutocompleteConfig {
80
+ enabled?: boolean;
81
+ }
82
+ /**
83
+ * Configuration for hover information
84
+ */
85
+ export interface HoverConfig {
86
+ enabled?: boolean;
87
+ }
88
+ /**
89
+ * Configuration for editor features
90
+ */
91
+ export interface EditorConfig {
92
+ enabled?: boolean;
93
+ autocomplete?: AutocompleteConfig;
94
+ hover?: HoverConfig;
95
+ }
20
96
  /**
21
97
  * Represents information about a class name found in source code
22
98
  */
@@ -65,6 +141,11 @@ export interface ExtractionContext {
65
141
  readonly sourceFile: ts.SourceFile;
66
142
  readonly utilityFunctions: UtilityFunction[];
67
143
  readonly typeChecker?: ts.TypeChecker;
144
+ /**
145
+ * The detected framework for the current file
146
+ * Used to determine which extractor to use
147
+ */
148
+ readonly framework?: Framework;
68
149
  }
69
150
  /**
70
151
  * Result of extraction operation
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC;CACtC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC5B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAE7D;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,GAAG,YAAY,GAAG,KAAK,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC7B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kBAAkB,CAAC,EAAE,cAAc,CAAC;IACpC,eAAe,CAAC,EAAE,cAAc,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,KAAK,CAAC,EAAE,WAAW,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,aAAa,CAAC,EAAE;QACf,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;KAClB,CAAC;IACF;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;CAC5B"}
@@ -2,7 +2,8 @@ import * as ts from 'typescript/lib/tsserverlibrary';
2
2
  import { ClassNameInfo, ExtractionContext } from '../core/types';
3
3
  import { BaseExtractor } from './BaseExtractor';
4
4
  /**
5
- * OPTIMIZED: Extracts class names from JSX className attributes
5
+ * OPTIMIZED: Extracts class names from JSX className and class attributes
6
+ * Supports both React (className) and Solid (class) syntaxes
6
7
  *
7
8
  * Performance improvements:
8
9
  * 1. Fast path for string literals (most common, ~70% of cases)
@@ -1 +1 @@
1
- {"version":3,"file":"JsxAttributeExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhD;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,aAAa;IACvD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,iBAAiB,CAA8B;;IASvD,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAO7D,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;CA2HnE"}
1
+ {"version":3,"file":"JsxAttributeExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIhD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,aAAa;IACvD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,iBAAiB,CAA8B;;IASvD,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAO7D,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;CAiInE"}
@@ -5,7 +5,8 @@ const BaseExtractor_1 = require("./BaseExtractor");
5
5
  const ExpressionExtractor_1 = require("./ExpressionExtractor");
6
6
  const TemplateExpressionExtractor_1 = require("./TemplateExpressionExtractor");
7
7
  /**
8
- * OPTIMIZED: Extracts class names from JSX className attributes
8
+ * OPTIMIZED: Extracts class names from JSX className and class attributes
9
+ * Supports both React (className) and Solid (class) syntaxes
9
10
  *
10
11
  * Performance improvements:
11
12
  * 1. Fast path for string literals (most common, ~70% of cases)
@@ -38,8 +39,13 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
38
39
  }
39
40
  // Process attributes
40
41
  for (const attr of attributes) {
41
- // OPTIMIZATION: Check both conditions at once
42
- if (!context.typescript.isJsxAttribute(attr) || attr.name.getText() !== 'className') {
42
+ // OPTIMIZATION: Check type first
43
+ if (!context.typescript.isJsxAttribute(attr)) {
44
+ continue;
45
+ }
46
+ // Support both className (React) and class (Solid, standard JSX)
47
+ const attrName = attr.name.getText();
48
+ if (attrName !== 'className' && attrName !== 'class') {
43
49
  continue;
44
50
  }
45
51
  const initializer = attr.initializer;
@@ -77,7 +83,7 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
77
83
  }
78
84
  continue; // Skip to next attribute
79
85
  }
80
- // JSX expression: className={'foo bar'} or className={clsx(...)}
86
+ // JSX expression: className={'foo bar'} or class={clsx(...)}
81
87
  if (context.typescript.isJsxExpression(initializer)) {
82
88
  const expression = initializer.expression;
83
89
  if (!expression) {
@@ -106,16 +112,16 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
106
112
  context.typescript.isTypeAssertionExpression(expression)) {
107
113
  classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
108
114
  }
109
- // Handle identifier references: className={dynamicClass}
115
+ // Handle identifier references: className={dynamicClass} or class={dynamicClass}
110
116
  // This resolves the variable to its declared value for validation
111
117
  else if (context.typescript.isIdentifier(expression)) {
112
118
  classNames.push(...addAttributeId(this.expressionExtractor.extractFromIdentifier(expression, context)));
113
119
  }
114
- // Handle array literal expressions: className={['flex', 'items-center']}
120
+ // Handle array literal expressions: className={['flex', 'items-center']} or class={['flex', 'items-center']}
115
121
  else if (context.typescript.isArrayLiteralExpression(expression)) {
116
122
  classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
117
123
  }
118
- // Handle object literal expressions: className={{ flex: true }}
124
+ // Handle object literal expressions: className={{ flex: true }} or class={{ flex: true }}
119
125
  else if (context.typescript.isObjectLiteralExpression(expression)) {
120
126
  classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
121
127
  }