tailwind-typescript-plugin 0.0.2-beta.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/CHANGELOG.md +42 -0
- package/LICENSE +21 -0
- package/README.md +538 -0
- package/lib/core/interfaces.d.ts +45 -0
- package/lib/core/interfaces.d.ts.map +1 -0
- package/lib/core/interfaces.js +3 -0
- package/lib/core/interfaces.js.map +1 -0
- package/lib/core/types.d.ts +27 -0
- package/lib/core/types.d.ts.map +1 -0
- package/lib/core/types.js +3 -0
- package/lib/core/types.js.map +1 -0
- package/lib/extractors/BaseExtractor.d.ts +20 -0
- package/lib/extractors/BaseExtractor.d.ts.map +1 -0
- package/lib/extractors/BaseExtractor.js +83 -0
- package/lib/extractors/BaseExtractor.js.map +1 -0
- package/lib/extractors/CvaExtractor.d.ts +88 -0
- package/lib/extractors/CvaExtractor.d.ts.map +1 -0
- package/lib/extractors/CvaExtractor.js +425 -0
- package/lib/extractors/CvaExtractor.js.map +1 -0
- package/lib/extractors/ExpressionExtractor.d.ts +16 -0
- package/lib/extractors/ExpressionExtractor.d.ts.map +1 -0
- package/lib/extractors/ExpressionExtractor.js +132 -0
- package/lib/extractors/ExpressionExtractor.js.map +1 -0
- package/lib/extractors/JsxAttributeExtractor.d.ts +20 -0
- package/lib/extractors/JsxAttributeExtractor.d.ts.map +1 -0
- package/lib/extractors/JsxAttributeExtractor.js +107 -0
- package/lib/extractors/JsxAttributeExtractor.js.map +1 -0
- package/lib/extractors/JsxAttributeExtractor.original.d.ts +15 -0
- package/lib/extractors/JsxAttributeExtractor.original.d.ts.map +1 -0
- package/lib/extractors/JsxAttributeExtractor.original.js +84 -0
- package/lib/extractors/JsxAttributeExtractor.original.js.map +1 -0
- package/lib/extractors/StringLiteralExtractor.d.ts +12 -0
- package/lib/extractors/StringLiteralExtractor.d.ts.map +1 -0
- package/lib/extractors/StringLiteralExtractor.js +21 -0
- package/lib/extractors/StringLiteralExtractor.js.map +1 -0
- package/lib/extractors/TailwindVariantsExtractor.d.ts +87 -0
- package/lib/extractors/TailwindVariantsExtractor.d.ts.map +1 -0
- package/lib/extractors/TailwindVariantsExtractor.js +447 -0
- package/lib/extractors/TailwindVariantsExtractor.js.map +1 -0
- package/lib/extractors/TemplateExpressionExtractor.d.ts +14 -0
- package/lib/extractors/TemplateExpressionExtractor.d.ts.map +1 -0
- package/lib/extractors/TemplateExpressionExtractor.js +66 -0
- package/lib/extractors/TemplateExpressionExtractor.js.map +1 -0
- package/lib/index.d.ts +65 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +4 -0
- package/lib/index.js.map +1 -0
- package/lib/infrastructure/TailwindValidator.d.ts +42 -0
- package/lib/infrastructure/TailwindValidator.d.ts.map +1 -0
- package/lib/infrastructure/TailwindValidator.js +152 -0
- package/lib/infrastructure/TailwindValidator.js.map +1 -0
- package/lib/infrastructure/TailwindValidator.spec.d.ts +2 -0
- package/lib/infrastructure/TailwindValidator.spec.d.ts.map +1 -0
- package/lib/infrastructure/TailwindValidator.spec.js +219 -0
- package/lib/infrastructure/TailwindValidator.spec.js.map +1 -0
- package/lib/plugin/TailwindTypescriptPlugin.d.ts +52 -0
- package/lib/plugin/TailwindTypescriptPlugin.d.ts.map +1 -0
- package/lib/plugin/TailwindTypescriptPlugin.js +142 -0
- package/lib/plugin/TailwindTypescriptPlugin.js.map +1 -0
- package/lib/services/ClassNameExtractionService.d.ts +37 -0
- package/lib/services/ClassNameExtractionService.d.ts.map +1 -0
- package/lib/services/ClassNameExtractionService.js +98 -0
- package/lib/services/ClassNameExtractionService.js.map +1 -0
- package/lib/services/ClassNameExtractionService.original.d.ts +20 -0
- package/lib/services/ClassNameExtractionService.original.d.ts.map +1 -0
- package/lib/services/ClassNameExtractionService.original.js +48 -0
- package/lib/services/ClassNameExtractionService.original.js.map +1 -0
- package/lib/services/DiagnosticService.d.ts +14 -0
- package/lib/services/DiagnosticService.d.ts.map +1 -0
- package/lib/services/DiagnosticService.js +61 -0
- package/lib/services/DiagnosticService.js.map +1 -0
- package/lib/services/PerformanceCache.d.ts +15 -0
- package/lib/services/PerformanceCache.d.ts.map +1 -0
- package/lib/services/PerformanceCache.js +44 -0
- package/lib/services/PerformanceCache.js.map +1 -0
- package/lib/services/PluginConfigService.d.ts +22 -0
- package/lib/services/PluginConfigService.d.ts.map +1 -0
- package/lib/services/PluginConfigService.js +86 -0
- package/lib/services/PluginConfigService.js.map +1 -0
- package/lib/services/ValidationService.d.ts +25 -0
- package/lib/services/ValidationService.d.ts.map +1 -0
- package/lib/services/ValidationService.js +50 -0
- package/lib/services/ValidationService.js.map +1 -0
- package/lib/utils/Logger.d.ts +10 -0
- package/lib/utils/Logger.d.ts.map +1 -0
- package/lib/utils/Logger.js +13 -0
- package/lib/utils/Logger.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TailwindVariantsExtractor = void 0;
|
|
4
|
+
const BaseExtractor_1 = require("./BaseExtractor");
|
|
5
|
+
/**
|
|
6
|
+
* Extracts class names from tailwind-variants tv() function calls
|
|
7
|
+
*
|
|
8
|
+
* Supports:
|
|
9
|
+
* - base: string with classes or array of strings
|
|
10
|
+
* - variants: nested object with string values containing classes
|
|
11
|
+
* - compoundVariants: array of objects with class/className properties
|
|
12
|
+
* - slots: object where values contain classes
|
|
13
|
+
* - Import aliasing: import { tv as myTv } from 'tailwind-variants'
|
|
14
|
+
* - class property overrides: button({ color: 'primary', class: 'bg-pink-500' })
|
|
15
|
+
*
|
|
16
|
+
* PERFORMANCE OPTIMIZATIONS:
|
|
17
|
+
* - ✅ Import detection cached per file (one-time AST scan)
|
|
18
|
+
* - ✅ Early exits for non-tv calls (fast path)
|
|
19
|
+
* - ✅ Direct property access (no unnecessary traversal)
|
|
20
|
+
* - ✅ Inline hot paths (string literal extraction)
|
|
21
|
+
* - ✅ Short-circuit evaluation (skip work when possible)
|
|
22
|
+
* - ✅ TypeChecker-based origin tracking (cached per symbol)
|
|
23
|
+
*/
|
|
24
|
+
class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.tvImportCache = new Map();
|
|
28
|
+
this.tvVariableCache = new Map();
|
|
29
|
+
}
|
|
30
|
+
canHandle(node, context) {
|
|
31
|
+
return context.typescript.isCallExpression(node);
|
|
32
|
+
}
|
|
33
|
+
extract(node, context) {
|
|
34
|
+
// OPTIMIZATION: Type guard first (fastest check)
|
|
35
|
+
if (!context.typescript.isCallExpression(node)) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
const callExpression = node;
|
|
39
|
+
// OPTIMIZATION: Check if this is a tv() definition call
|
|
40
|
+
if (this.isTvCall(callExpression, context)) {
|
|
41
|
+
// OPTIMIZATION: Early exit for empty arguments
|
|
42
|
+
if (callExpression.arguments.length === 0) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
const configArg = callExpression.arguments[0];
|
|
46
|
+
// OPTIMIZATION: Early exit if not an object literal
|
|
47
|
+
if (!context.typescript.isObjectLiteralExpression(configArg)) {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
// Extract class names from the tv() configuration object
|
|
51
|
+
return this.extractFromTvConfig(configArg, context);
|
|
52
|
+
}
|
|
53
|
+
// Check if this is a call to a function created by tv() (e.g., button({ class: '...' }))
|
|
54
|
+
// IMPORTANT: Only validate if NOT a utility function
|
|
55
|
+
if (this.isTvCreatedFunctionCall(callExpression, context)) {
|
|
56
|
+
return this.extractFromTvFunctionCall(callExpression, context);
|
|
57
|
+
}
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if this call expression is a tv() call from tailwind-variants
|
|
62
|
+
* Supports import aliasing: import { tv as myTv } from 'tailwind-variants'
|
|
63
|
+
*/
|
|
64
|
+
isTvCall(callExpression, context) {
|
|
65
|
+
const expr = callExpression.expression;
|
|
66
|
+
const tvNames = this.getTvImportNames(context);
|
|
67
|
+
// No tv imports found
|
|
68
|
+
if (tvNames.size === 0) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
// Handle simple calls: tv(...) or myTv(...)
|
|
72
|
+
if (context.typescript.isIdentifier(expr)) {
|
|
73
|
+
return tvNames.has(expr.text);
|
|
74
|
+
}
|
|
75
|
+
// Handle member expressions: variants.tv(...), utils.myTv(...)
|
|
76
|
+
if (context.typescript.isPropertyAccessExpression(expr)) {
|
|
77
|
+
return tvNames.has(expr.name.text);
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get all local names for tv imports from tailwind-variants
|
|
83
|
+
* Supports aliasing: import { tv as myTv } -> returns Set(['myTv'])
|
|
84
|
+
* Caches result per file for performance
|
|
85
|
+
*/
|
|
86
|
+
getTvImportNames(context) {
|
|
87
|
+
const fileName = context.sourceFile.fileName;
|
|
88
|
+
// Check cache first
|
|
89
|
+
if (this.tvImportCache.has(fileName)) {
|
|
90
|
+
return this.tvImportCache.get(fileName);
|
|
91
|
+
}
|
|
92
|
+
// Search for import statement
|
|
93
|
+
const tvNames = new Set();
|
|
94
|
+
for (const statement of context.sourceFile.statements) {
|
|
95
|
+
if (!context.typescript.isImportDeclaration(statement)) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
99
|
+
if (!context.typescript.isStringLiteral(moduleSpecifier) ||
|
|
100
|
+
moduleSpecifier.text !== 'tailwind-variants') {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
const importClause = statement.importClause;
|
|
104
|
+
if (!importClause) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// Check named imports: import { tv } or import { tv as myTv }
|
|
108
|
+
const namedBindings = importClause.namedBindings;
|
|
109
|
+
if (namedBindings && context.typescript.isNamedImports(namedBindings)) {
|
|
110
|
+
for (const element of namedBindings.elements) {
|
|
111
|
+
// Check if the original export name is 'tv'
|
|
112
|
+
// For: import { tv } -> propertyName is undefined, name is 'tv'
|
|
113
|
+
// For: import { tv as myTv } -> propertyName is 'tv', name is 'myTv'
|
|
114
|
+
const originalName = element.propertyName?.text || element.name.text;
|
|
115
|
+
if (originalName === 'tv') {
|
|
116
|
+
// Add the local name (what it's called in this file)
|
|
117
|
+
tvNames.add(element.name.text);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Cache the result
|
|
123
|
+
this.tvImportCache.set(fileName, tvNames);
|
|
124
|
+
return tvNames;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Extract class names from tv() configuration object
|
|
128
|
+
*/
|
|
129
|
+
extractFromTvConfig(config, context) {
|
|
130
|
+
const classNames = [];
|
|
131
|
+
for (const property of config.properties) {
|
|
132
|
+
if (!context.typescript.isPropertyAssignment(property)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const propertyName = this.getPropertyName(property, context);
|
|
136
|
+
if (!propertyName) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
// Handle different tv() properties
|
|
140
|
+
switch (propertyName) {
|
|
141
|
+
case 'base':
|
|
142
|
+
// base: 'flex items-center' or base: ['flex', 'items-center']
|
|
143
|
+
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
144
|
+
break;
|
|
145
|
+
case 'variants':
|
|
146
|
+
// variants: { size: { sm: 'text-sm', lg: 'text-lg' } }
|
|
147
|
+
classNames.push(...this.extractFromVariants(property.initializer, context));
|
|
148
|
+
break;
|
|
149
|
+
case 'compoundVariants':
|
|
150
|
+
// compoundVariants: [{ size: 'sm', color: 'primary', class: 'font-bold' }]
|
|
151
|
+
classNames.push(...this.extractFromCompoundVariants(property.initializer, context));
|
|
152
|
+
break;
|
|
153
|
+
case 'slots':
|
|
154
|
+
// slots: { base: 'flex', item: 'p-2' }
|
|
155
|
+
classNames.push(...this.extractFromSlots(property.initializer, context));
|
|
156
|
+
break;
|
|
157
|
+
case 'defaultVariants':
|
|
158
|
+
// defaultVariants doesn't contain classes, skip
|
|
159
|
+
break;
|
|
160
|
+
default:
|
|
161
|
+
// Other properties might contain classes, try to extract
|
|
162
|
+
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return classNames;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Extract class names from the variants object
|
|
170
|
+
* Structure: { variantName: { optionName: 'classes' } }
|
|
171
|
+
*/
|
|
172
|
+
extractFromVariants(node, context) {
|
|
173
|
+
if (!context.typescript.isObjectLiteralExpression(node)) {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
const classNames = [];
|
|
177
|
+
// Iterate through each variant (e.g., size, color)
|
|
178
|
+
for (const variantProp of node.properties) {
|
|
179
|
+
if (!context.typescript.isPropertyAssignment(variantProp)) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Each variant value should be an object with options
|
|
183
|
+
if (context.typescript.isObjectLiteralExpression(variantProp.initializer)) {
|
|
184
|
+
// Iterate through each option (e.g., sm, lg, primary, secondary)
|
|
185
|
+
for (const optionProp of variantProp.initializer.properties) {
|
|
186
|
+
if (!context.typescript.isPropertyAssignment(optionProp)) {
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
// Extract classes from the option value
|
|
190
|
+
classNames.push(...this.extractFromValue(optionProp.initializer, context));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return classNames;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Extract class names from compoundVariants array
|
|
198
|
+
* Structure: [{ condition: value, class: 'classes' or className: 'classes' }]
|
|
199
|
+
*/
|
|
200
|
+
extractFromCompoundVariants(node, context) {
|
|
201
|
+
if (!context.typescript.isArrayLiteralExpression(node)) {
|
|
202
|
+
return [];
|
|
203
|
+
}
|
|
204
|
+
const classNames = [];
|
|
205
|
+
// Iterate through each compound variant object
|
|
206
|
+
for (const element of node.elements) {
|
|
207
|
+
if (!context.typescript.isObjectLiteralExpression(element)) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
// Look for 'class' or 'className' property
|
|
211
|
+
for (const prop of element.properties) {
|
|
212
|
+
if (!context.typescript.isPropertyAssignment(prop)) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
const propName = this.getPropertyName(prop, context);
|
|
216
|
+
if (propName === 'class' || propName === 'className') {
|
|
217
|
+
classNames.push(...this.extractFromValue(prop.initializer, context));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return classNames;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Extract class names from slots object
|
|
225
|
+
* Structure: { slotName: 'classes' } or { slotName: { base: 'classes', variants: {...} } }
|
|
226
|
+
*/
|
|
227
|
+
extractFromSlots(node, context) {
|
|
228
|
+
if (!context.typescript.isObjectLiteralExpression(node)) {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
const classNames = [];
|
|
232
|
+
for (const slotProp of node.properties) {
|
|
233
|
+
if (!context.typescript.isPropertyAssignment(slotProp)) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const slotValue = slotProp.initializer;
|
|
237
|
+
// If slot value is a string, extract classes
|
|
238
|
+
if (context.typescript.isStringLiteral(slotValue)) {
|
|
239
|
+
classNames.push(...this.extractFromStringLiteral(slotValue, context));
|
|
240
|
+
}
|
|
241
|
+
// If slot value is an object with base/variants, recurse
|
|
242
|
+
else if (context.typescript.isObjectLiteralExpression(slotValue)) {
|
|
243
|
+
classNames.push(...this.extractFromTvConfig(slotValue, context));
|
|
244
|
+
}
|
|
245
|
+
// Handle arrays and other expressions
|
|
246
|
+
else {
|
|
247
|
+
classNames.push(...this.extractFromValue(slotValue, context));
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return classNames;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Extract class names from any expression value
|
|
254
|
+
*/
|
|
255
|
+
extractFromValue(node, context) {
|
|
256
|
+
// String literal: 'flex items-center'
|
|
257
|
+
if (context.typescript.isStringLiteral(node)) {
|
|
258
|
+
return this.extractFromStringLiteral(node, context);
|
|
259
|
+
}
|
|
260
|
+
// No-substitution template literal: `flex items-center`
|
|
261
|
+
if (context.typescript.isNoSubstitutionTemplateLiteral(node)) {
|
|
262
|
+
return this.extractFromStringLiteral(node, context);
|
|
263
|
+
}
|
|
264
|
+
// Array: ['flex', 'items-center']
|
|
265
|
+
if (context.typescript.isArrayLiteralExpression(node)) {
|
|
266
|
+
const classNames = [];
|
|
267
|
+
for (const element of node.elements) {
|
|
268
|
+
if (context.typescript.isStringLiteral(element)) {
|
|
269
|
+
classNames.push(...this.extractFromStringLiteral(element, context));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return classNames;
|
|
273
|
+
}
|
|
274
|
+
// Template expression with variables: `flex ${something}`
|
|
275
|
+
// For now, we extract only the static parts
|
|
276
|
+
if (context.typescript.isTemplateExpression(node)) {
|
|
277
|
+
const classNames = [];
|
|
278
|
+
const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
279
|
+
// Extract from head
|
|
280
|
+
if (node.head.text) {
|
|
281
|
+
const headText = node.head.text;
|
|
282
|
+
const headStart = node.head.getStart() + 1; // +1 to skip backtick
|
|
283
|
+
let offset = 0;
|
|
284
|
+
headText.split(' ').forEach(className => {
|
|
285
|
+
if (className) {
|
|
286
|
+
classNames.push({
|
|
287
|
+
className,
|
|
288
|
+
absoluteStart: headStart + offset,
|
|
289
|
+
length: className.length,
|
|
290
|
+
line: lineNumber,
|
|
291
|
+
file: context.sourceFile.fileName
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
offset += className.length + 1;
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
// Extract from template spans
|
|
298
|
+
for (const span of node.templateSpans) {
|
|
299
|
+
if (span.literal.text) {
|
|
300
|
+
const spanText = span.literal.text;
|
|
301
|
+
const spanStart = span.literal.getStart() + 1; // +1 to skip template literal quote
|
|
302
|
+
let offset = 0;
|
|
303
|
+
spanText.split(' ').forEach(className => {
|
|
304
|
+
if (className) {
|
|
305
|
+
classNames.push({
|
|
306
|
+
className,
|
|
307
|
+
absoluteStart: spanStart + offset,
|
|
308
|
+
length: className.length,
|
|
309
|
+
line: lineNumber,
|
|
310
|
+
file: context.sourceFile.fileName
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
offset += className.length + 1;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return classNames;
|
|
318
|
+
}
|
|
319
|
+
return [];
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Get property name from a property assignment
|
|
323
|
+
*/
|
|
324
|
+
getPropertyName(property, context) {
|
|
325
|
+
const name = property.name;
|
|
326
|
+
if (context.typescript.isIdentifier(name)) {
|
|
327
|
+
return name.text;
|
|
328
|
+
}
|
|
329
|
+
if (context.typescript.isStringLiteral(name)) {
|
|
330
|
+
return name.text;
|
|
331
|
+
}
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Check if this call expression is calling a function created by tv()
|
|
336
|
+
* Uses TypeChecker for accurate origin tracking
|
|
337
|
+
* IMPORTANT: Returns false for utility functions
|
|
338
|
+
*/
|
|
339
|
+
isTvCreatedFunctionCall(callExpression, context) {
|
|
340
|
+
// OPTIMIZATION: Early exit if no type checker available
|
|
341
|
+
if (!context.typeChecker) {
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
const expr = callExpression.expression;
|
|
345
|
+
// OPTIMIZATION: Only handle simple identifiers and property access
|
|
346
|
+
// This covers: button(...), variants.button(...), etc.
|
|
347
|
+
if (!context.typescript.isIdentifier(expr) &&
|
|
348
|
+
!context.typescript.isPropertyAccessExpression(expr)) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
// OPTIMIZATION: Check if this is a utility function (exclude from validation)
|
|
352
|
+
const functionName = context.typescript.isIdentifier(expr)
|
|
353
|
+
? expr.text
|
|
354
|
+
: context.typescript.isPropertyAccessExpression(expr)
|
|
355
|
+
? expr.name.text
|
|
356
|
+
: null;
|
|
357
|
+
if (functionName && context.utilityFunctions.includes(functionName)) {
|
|
358
|
+
// Debug: log when skipping utility function
|
|
359
|
+
// console.log(`[TV] Skipping utility function: ${functionName}`);
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
// Debug: log function being checked
|
|
363
|
+
// console.log(`[TV] Checking if ${functionName} is tv-created, utility functions:`, context.utilityFunctions);
|
|
364
|
+
// Get the symbol for the called function
|
|
365
|
+
const symbol = context.typeChecker.getSymbolAtLocation(expr);
|
|
366
|
+
if (!symbol) {
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
// OPTIMIZATION: Check cache first
|
|
370
|
+
if (this.tvVariableCache.has(symbol)) {
|
|
371
|
+
return this.tvVariableCache.get(symbol);
|
|
372
|
+
}
|
|
373
|
+
// Check if this symbol's declaration is assigned from a tv() call
|
|
374
|
+
const isTvCreated = this.isSymbolFromTvCall(symbol, context);
|
|
375
|
+
this.tvVariableCache.set(symbol, isTvCreated);
|
|
376
|
+
return isTvCreated;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Check if a symbol's declaration is from a tv() call
|
|
380
|
+
* Handles: const button = tv(...), export const button = tv(...), etc.
|
|
381
|
+
*/
|
|
382
|
+
isSymbolFromTvCall(symbol, context) {
|
|
383
|
+
const declarations = symbol.getDeclarations();
|
|
384
|
+
if (!declarations || declarations.length === 0) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
// Check each declaration to see if it's assigned from tv()
|
|
388
|
+
for (const declaration of declarations) {
|
|
389
|
+
// Handle: const button = tv(...)
|
|
390
|
+
if (context.typescript.isVariableDeclaration(declaration)) {
|
|
391
|
+
const initializer = declaration.initializer;
|
|
392
|
+
if (initializer && context.typescript.isCallExpression(initializer)) {
|
|
393
|
+
if (this.isTvCall(initializer, context)) {
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// Handle: export default tv(...) or similar patterns
|
|
399
|
+
else if (context.typescript.isExportAssignment(declaration)) {
|
|
400
|
+
const expr = declaration.expression;
|
|
401
|
+
if (context.typescript.isCallExpression(expr)) {
|
|
402
|
+
if (this.isTvCall(expr, context)) {
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Extract class names from a tv() function call
|
|
412
|
+
* Example: button({ color: 'primary', class: 'bg-pink-500' })
|
|
413
|
+
*/
|
|
414
|
+
extractFromTvFunctionCall(callExpression, context) {
|
|
415
|
+
// OPTIMIZATION: Early exit for empty arguments
|
|
416
|
+
if (callExpression.arguments.length === 0) {
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
const arg = callExpression.arguments[0];
|
|
420
|
+
// The argument should be an object literal with properties like { color: 'primary', class: '...' }
|
|
421
|
+
if (!context.typescript.isObjectLiteralExpression(arg)) {
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
const classNames = [];
|
|
425
|
+
// Look for 'class' or 'className' properties
|
|
426
|
+
for (const property of arg.properties) {
|
|
427
|
+
if (!context.typescript.isPropertyAssignment(property)) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
const propName = this.getPropertyName(property, context);
|
|
431
|
+
if (propName === 'class' || propName === 'className') {
|
|
432
|
+
// Extract classes from the value
|
|
433
|
+
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return classNames;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Clear the import cache (useful for testing or when files change)
|
|
440
|
+
*/
|
|
441
|
+
clearCache() {
|
|
442
|
+
this.tvImportCache.clear();
|
|
443
|
+
this.tvVariableCache.clear();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
exports.TailwindVariantsExtractor = TailwindVariantsExtractor;
|
|
447
|
+
//# sourceMappingURL=TailwindVariantsExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TailwindVariantsExtractor.js","sourceRoot":"","sources":["../../src/extractors/TailwindVariantsExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { ClassNameInfo, ExtractionContext } from '../core/types';
|
|
3
|
+
import { BaseExtractor } from './BaseExtractor';
|
|
4
|
+
/**
|
|
5
|
+
* Extracts class names from template expressions
|
|
6
|
+
* Example: `flex ${condition ? 'hidden' : 'block'}`
|
|
7
|
+
*/
|
|
8
|
+
export declare class TemplateExpressionExtractor extends BaseExtractor {
|
|
9
|
+
private expressionExtractor;
|
|
10
|
+
constructor();
|
|
11
|
+
canHandle(node: ts.Node, context: ExtractionContext): boolean;
|
|
12
|
+
extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=TemplateExpressionExtractor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateExpressionExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/TemplateExpressionExtractor.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;AAGhD;;;GAGG;AACH,qBAAa,2BAA4B,SAAQ,aAAa;IAC7D,OAAO,CAAC,mBAAmB,CAAsB;;IAOjD,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;CAwDnE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateExpressionExtractor = void 0;
|
|
4
|
+
const BaseExtractor_1 = require("./BaseExtractor");
|
|
5
|
+
const ExpressionExtractor_1 = require("./ExpressionExtractor");
|
|
6
|
+
/**
|
|
7
|
+
* Extracts class names from template expressions
|
|
8
|
+
* Example: `flex ${condition ? 'hidden' : 'block'}`
|
|
9
|
+
*/
|
|
10
|
+
class TemplateExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
11
|
+
constructor() {
|
|
12
|
+
super();
|
|
13
|
+
this.expressionExtractor = new ExpressionExtractor_1.ExpressionExtractor();
|
|
14
|
+
}
|
|
15
|
+
canHandle(node, context) {
|
|
16
|
+
return (context.typescript.isTemplateExpression(node) ||
|
|
17
|
+
context.typescript.isNoSubstitutionTemplateLiteral(node));
|
|
18
|
+
}
|
|
19
|
+
extract(node, context) {
|
|
20
|
+
const classNames = [];
|
|
21
|
+
// Handle no-substitution template literal: `flex items-center`
|
|
22
|
+
if (context.typescript.isNoSubstitutionTemplateLiteral(node)) {
|
|
23
|
+
return this.extractFromStringLiteral(node, context);
|
|
24
|
+
}
|
|
25
|
+
// Handle template expression with substitutions
|
|
26
|
+
if (context.typescript.isTemplateExpression(node)) {
|
|
27
|
+
const parts = [];
|
|
28
|
+
// Add the head (the part before the first ${})
|
|
29
|
+
parts.push({
|
|
30
|
+
text: node.head.text,
|
|
31
|
+
start: node.head.getStart() + 1
|
|
32
|
+
});
|
|
33
|
+
// Add each template span's literal part
|
|
34
|
+
node.templateSpans.forEach(span => {
|
|
35
|
+
// Extract from the interpolated expression
|
|
36
|
+
const expressionClasses = this.expressionExtractor.extractFromExpression(span.expression, context);
|
|
37
|
+
classNames.push(...expressionClasses);
|
|
38
|
+
// Add the literal part after the interpolation
|
|
39
|
+
parts.push({
|
|
40
|
+
text: span.literal.text,
|
|
41
|
+
start: span.literal.getStart() + 1
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
// Process each static part for class names
|
|
45
|
+
parts.forEach(part => {
|
|
46
|
+
let offset = 0;
|
|
47
|
+
const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(part.start).line + 1;
|
|
48
|
+
part.text.split(' ').forEach(className => {
|
|
49
|
+
if (className) {
|
|
50
|
+
classNames.push({
|
|
51
|
+
className: className,
|
|
52
|
+
absoluteStart: part.start + offset,
|
|
53
|
+
length: className.length,
|
|
54
|
+
line: lineNumber,
|
|
55
|
+
file: context.sourceFile.fileName
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
offset += className.length + 1;
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return classNames;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.TemplateExpressionExtractor = TemplateExpressionExtractor;
|
|
66
|
+
//# sourceMappingURL=TemplateExpressionExtractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TemplateExpressionExtractor.js","sourceRoot":"","sources":["../../src/extractors/TemplateExpressionExtractor.ts"],"names":[],"mappings":";;;AAGA,mDAAgD;AAChD,+DAA4D;AAE5D;;;GAGG;AACH,MAAa,2BAA4B,SAAQ,6BAAa;IAG7D;QACC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,mBAAmB,GAAG,IAAI,yCAAmB,EAAE,CAAC;IACtD,CAAC;IAED,SAAS,CAAC,IAAa,EAAE,OAA0B;QAClD,OAAO,CACN,OAAO,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAC7C,OAAO,CAAC,UAAU,CAAC,+BAA+B,CAAC,IAAI,CAAC,CACxD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAa,EAAE,OAA0B;QAChD,MAAM,UAAU,GAAoB,EAAE,CAAC;QAEvC,+DAA+D;QAC/D,IAAI,OAAO,CAAC,UAAU,CAAC,+BAA+B,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9D,OAAO,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrD,CAAC;QAED,gDAAgD;QAChD,IAAI,OAAO,CAAC,UAAU,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,KAAK,GAA2C,EAAE,CAAC;YAEzD,+CAA+C;YAC/C,KAAK,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI;gBACpB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC;aAC/B,CAAC,CAAC;YAEH,wCAAwC;YACxC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBACjC,2CAA2C;gBAC3C,MAAM,iBAAiB,GAAG,IAAI,CAAC,mBAAmB,CAAC,qBAAqB,CACvE,IAAI,CAAC,UAAU,EACf,OAAO,CACP,CAAC;gBACF,UAAU,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC;gBAEtC,+CAA+C;gBAC/C,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;oBACvB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;iBAClC,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,2CAA2C;YAC3C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBACpB,IAAI,MAAM,GAAG,CAAC,CAAC;gBACf,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;gBAEzF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;oBACxC,IAAI,SAAS,EAAE,CAAC;wBACf,UAAU,CAAC,IAAI,CAAC;4BACf,SAAS,EAAE,SAAS;4BACpB,aAAa,EAAE,IAAI,CAAC,KAAK,GAAG,MAAM;4BAClC,MAAM,EAAE,SAAS,CAAC,MAAM;4BACxB,IAAI,EAAE,UAAU;4BAChB,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ;yBACjC,CAAC,CAAC;oBACJ,CAAC;oBACD,MAAM,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC;IACnB,CAAC;CACD;AAvED,kEAuEC"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as ts from 'typescript/lib/tsserverlibrary';
|
|
2
|
+
import { TailwindTypescriptPlugin } from './plugin/TailwindTypescriptPlugin';
|
|
3
|
+
/**
|
|
4
|
+
* Main entry point for the TypeScript Language Service Plugin
|
|
5
|
+
*
|
|
6
|
+
* REFACTORED ARCHITECTURE:
|
|
7
|
+
*
|
|
8
|
+
* This plugin now follows Clean Architecture and SOLID principles:
|
|
9
|
+
*
|
|
10
|
+
* 1. Core Layer (src/core/):
|
|
11
|
+
* - types.ts: Domain types (ClassNameInfo, ExtractionContext, etc.)
|
|
12
|
+
* - interfaces.ts: Contracts (IClassNameExtractor, IClassNameValidator, etc.)
|
|
13
|
+
*
|
|
14
|
+
* 2. Extractors Layer (src/extractors/):
|
|
15
|
+
* - BaseExtractor: Abstract base with common functionality
|
|
16
|
+
* - StringLiteralExtractor: Handles string literals
|
|
17
|
+
* - TemplateExpressionExtractor: Handles template strings
|
|
18
|
+
* - ExpressionExtractor: Handles all expression types (ternary, binary, etc.)
|
|
19
|
+
* - JsxAttributeExtractor: Main orchestrator for JSX className attributes
|
|
20
|
+
*
|
|
21
|
+
* 3. Services Layer (src/services/):
|
|
22
|
+
* - ClassNameExtractionService: Orchestrates AST traversal and extraction
|
|
23
|
+
* - DiagnosticService: Creates TypeScript diagnostics
|
|
24
|
+
* - ValidationService: Validates classes and creates diagnostics
|
|
25
|
+
* - PluginConfigService: Manages plugin configuration
|
|
26
|
+
* - PerformanceCache: LRU cache for performance optimization
|
|
27
|
+
*
|
|
28
|
+
* 4. Plugin Layer (src/plugin/):
|
|
29
|
+
* - TailwindTypescriptPlugin: Thin adapter to TypeScript API
|
|
30
|
+
*
|
|
31
|
+
* 5. Infrastructure Layer:
|
|
32
|
+
* - TailwindValidator: Validates against Tailwind CSS design system
|
|
33
|
+
* - Logger: Logging abstraction
|
|
34
|
+
*
|
|
35
|
+
* SOLID PRINCIPLES APPLIED:
|
|
36
|
+
*
|
|
37
|
+
* - Single Responsibility: Each class has one clear purpose
|
|
38
|
+
* - Open/Closed: Easy to add new extractors without modifying existing code
|
|
39
|
+
* - Liskov Substitution: All extractors implement the same interface
|
|
40
|
+
* - Interface Segregation: Small, focused interfaces
|
|
41
|
+
* - Dependency Inversion: Depends on abstractions (IClassNameValidator, etc.)
|
|
42
|
+
*
|
|
43
|
+
* EXTENSIBILITY:
|
|
44
|
+
*
|
|
45
|
+
* To add a new extraction pattern:
|
|
46
|
+
* 1. Create a new extractor class extending BaseExtractor
|
|
47
|
+
* 2. Implement canHandle() and extract() methods
|
|
48
|
+
* 3. Add it to ClassNameExtractionService.extractors array
|
|
49
|
+
*
|
|
50
|
+
* To use the TypeScript type checker:
|
|
51
|
+
* The type checker is obtained fresh for each file validation from the current program.
|
|
52
|
+
* It's available in the ExtractionContext passed to extractors for type-based features.
|
|
53
|
+
*
|
|
54
|
+
* PERFORMANCE OPTIMIZATIONS:
|
|
55
|
+
*
|
|
56
|
+
* - LRU cache for validation results (2000 entries)
|
|
57
|
+
* - Lazy initialization of design system
|
|
58
|
+
* - Fresh type checker per-file (always accurate, no staleness)
|
|
59
|
+
* - Fast path for static class validation
|
|
60
|
+
*/
|
|
61
|
+
declare const _default: (mod: {
|
|
62
|
+
typescript: typeof ts;
|
|
63
|
+
}) => TailwindTypescriptPlugin;
|
|
64
|
+
export = _default;
|
|
65
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAErD,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;yBACO,KAAK;IAAE,UAAU,EAAE,OAAO,EAAE,CAAA;CAAE;AAAxC,kBAA0F"}
|
package/lib/index.js
ADDED
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,gFAA6E;AA4D7E,iBAAS,CAAC,GAA8B,EAAE,EAAE,CAAC,IAAI,mDAAwB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC"}
|