tailwind-typescript-plugin 1.3.1-beta.4 → 1.4.0-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 +15 -0
- package/README.md +171 -0
- package/lib/core/types.d.ts +14 -0
- package/lib/core/types.d.ts.map +1 -1
- package/lib/extractors/CvaExtractor.d.ts.map +1 -1
- package/lib/extractors/CvaExtractor.js +44 -26
- package/lib/extractors/CvaExtractor.js.map +1 -1
- package/lib/extractors/ExpressionExtractor.d.ts +2 -1
- package/lib/extractors/ExpressionExtractor.d.ts.map +1 -1
- package/lib/extractors/ExpressionExtractor.js +46 -25
- package/lib/extractors/ExpressionExtractor.js.map +1 -1
- package/lib/extractors/JsxAttributeExtractor.d.ts.map +1 -1
- package/lib/extractors/JsxAttributeExtractor.js +13 -8
- package/lib/extractors/JsxAttributeExtractor.js.map +1 -1
- package/lib/extractors/TailwindVariantsExtractor.d.ts.map +1 -1
- package/lib/extractors/TailwindVariantsExtractor.js +50 -31
- package/lib/extractors/TailwindVariantsExtractor.js.map +1 -1
- package/lib/extractors/VariableReferenceExtractor.d.ts +1 -0
- package/lib/extractors/VariableReferenceExtractor.d.ts.map +1 -1
- package/lib/extractors/VariableReferenceExtractor.js +19 -14
- package/lib/extractors/VariableReferenceExtractor.js.map +1 -1
- package/lib/plugin/TailwindTypescriptPlugin.d.ts.map +1 -1
- package/lib/plugin/TailwindTypescriptPlugin.js +55 -18
- package/lib/plugin/TailwindTypescriptPlugin.js.map +1 -1
- package/lib/services/CodeActionService.d.ts +5 -0
- package/lib/services/CodeActionService.d.ts.map +1 -1
- package/lib/services/CodeActionService.js +37 -5
- package/lib/services/CodeActionService.js.map +1 -1
- package/lib/services/CodeActionService.spec.js +44 -0
- package/lib/services/CodeActionService.spec.js.map +1 -1
- package/lib/services/DiagnosticService.d.ts +26 -1
- package/lib/services/DiagnosticService.d.ts.map +1 -1
- package/lib/services/DiagnosticService.js +57 -2
- package/lib/services/DiagnosticService.js.map +1 -1
- package/lib/services/DuplicateClassDetection.spec.d.ts +2 -0
- package/lib/services/DuplicateClassDetection.spec.d.ts.map +1 -0
- package/lib/services/DuplicateClassDetection.spec.js +435 -0
- package/lib/services/DuplicateClassDetection.spec.js.map +1 -0
- package/lib/services/ValidationService.d.ts +4 -0
- package/lib/services/ValidationService.d.ts.map +1 -1
- package/lib/services/ValidationService.js +103 -6
- package/lib/services/ValidationService.js.map +1 -1
- package/package.json +1 -1
|
@@ -25,31 +25,43 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Recursively extract class names from any expression type
|
|
28
|
+
* @param conditionalBranchId - Identifies which conditional branch this expression is in
|
|
28
29
|
*/
|
|
29
|
-
extractFromExpression(expression, context) {
|
|
30
|
+
extractFromExpression(expression, context, conditionalBranchId) {
|
|
30
31
|
const classNames = [];
|
|
31
32
|
const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(expression.getStart()).line + 1;
|
|
33
|
+
// Helper to add conditionalBranchId to extracted classes
|
|
34
|
+
const addBranchId = (classes) => conditionalBranchId ? classes.map(c => ({ ...c, conditionalBranchId })) : classes;
|
|
32
35
|
// Handle string literals
|
|
33
36
|
if (context.typescript.isStringLiteral(expression)) {
|
|
34
|
-
return this.extractFromStringLiteral(expression, context);
|
|
37
|
+
return addBranchId(this.extractFromStringLiteral(expression, context));
|
|
35
38
|
}
|
|
36
39
|
// Handle conditional expressions: condition ? 'class1' : 'class2'
|
|
37
40
|
if (context.typescript.isConditionalExpression(expression)) {
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
// Use the ternary's position as a unique identifier
|
|
42
|
+
const ternaryId = expression.getStart();
|
|
43
|
+
classNames.push(...this.extractFromExpression(expression.whenTrue, context, `ternary:true:${ternaryId}`));
|
|
44
|
+
classNames.push(...this.extractFromExpression(expression.whenFalse, context, `ternary:false:${ternaryId}`));
|
|
40
45
|
}
|
|
41
46
|
// Handle binary expressions: condition && 'class-name'
|
|
42
47
|
else if (context.typescript.isBinaryExpression(expression)) {
|
|
43
48
|
if (expression.operatorToken.kind === context.typescript.SyntaxKind.AmpersandAmpersandToken ||
|
|
44
49
|
expression.operatorToken.kind === context.typescript.SyntaxKind.BarBarToken) {
|
|
45
|
-
classNames.push(...this.extractFromExpression(expression.right, context));
|
|
50
|
+
classNames.push(...this.extractFromExpression(expression.right, context, conditionalBranchId));
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
|
-
// Handle call expressions: clsx('class1', 'class2')
|
|
53
|
+
// Handle call expressions: clsx('class1', 'class2', myVar)
|
|
49
54
|
else if (context.typescript.isCallExpression(expression)) {
|
|
50
55
|
if (this.shouldValidateFunctionCall(expression, context.utilityFunctions)) {
|
|
51
56
|
expression.arguments.forEach(arg => {
|
|
52
|
-
|
|
57
|
+
// Handle identifier arguments (variable references in function calls)
|
|
58
|
+
if (context.typescript.isIdentifier(arg)) {
|
|
59
|
+
const extracted = this.variableExtractor.extractFromIdentifier(arg, context);
|
|
60
|
+
classNames.push(...addBranchId(extracted));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
classNames.push(...this.extractFromExpression(arg, context, conditionalBranchId));
|
|
64
|
+
}
|
|
53
65
|
});
|
|
54
66
|
}
|
|
55
67
|
}
|
|
@@ -58,40 +70,44 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
58
70
|
const inner = expression.expression;
|
|
59
71
|
// If inner is an identifier, resolve it as a variable reference
|
|
60
72
|
if (context.typescript.isIdentifier(inner)) {
|
|
61
|
-
|
|
73
|
+
const extracted = this.variableExtractor.extractFromIdentifier(inner, context);
|
|
74
|
+
classNames.push(...addBranchId(extracted));
|
|
62
75
|
}
|
|
63
76
|
else {
|
|
64
|
-
classNames.push(...this.extractFromExpression(inner, context));
|
|
77
|
+
classNames.push(...this.extractFromExpression(inner, context, conditionalBranchId));
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
// Handle type assertions: ('class-name' as string) or (myVar as string)
|
|
68
81
|
else if (context.typescript.isAsExpression(expression)) {
|
|
69
82
|
const inner = expression.expression;
|
|
70
83
|
if (context.typescript.isIdentifier(inner)) {
|
|
71
|
-
|
|
84
|
+
const extracted = this.variableExtractor.extractFromIdentifier(inner, context);
|
|
85
|
+
classNames.push(...addBranchId(extracted));
|
|
72
86
|
}
|
|
73
87
|
else {
|
|
74
|
-
classNames.push(...this.extractFromExpression(inner, context));
|
|
88
|
+
classNames.push(...this.extractFromExpression(inner, context, conditionalBranchId));
|
|
75
89
|
}
|
|
76
90
|
}
|
|
77
91
|
// Handle non-null assertions: expr! or myVar!
|
|
78
92
|
else if (context.typescript.isNonNullExpression(expression)) {
|
|
79
93
|
const inner = expression.expression;
|
|
80
94
|
if (context.typescript.isIdentifier(inner)) {
|
|
81
|
-
|
|
95
|
+
const extracted = this.variableExtractor.extractFromIdentifier(inner, context);
|
|
96
|
+
classNames.push(...addBranchId(extracted));
|
|
82
97
|
}
|
|
83
98
|
else {
|
|
84
|
-
classNames.push(...this.extractFromExpression(inner, context));
|
|
99
|
+
classNames.push(...this.extractFromExpression(inner, context, conditionalBranchId));
|
|
85
100
|
}
|
|
86
101
|
}
|
|
87
102
|
// Handle type assertions with angle brackets: <string>'class-name' (rare in JSX)
|
|
88
103
|
else if (context.typescript.isTypeAssertionExpression(expression)) {
|
|
89
104
|
const inner = expression.expression;
|
|
90
105
|
if (context.typescript.isIdentifier(inner)) {
|
|
91
|
-
|
|
106
|
+
const extracted = this.variableExtractor.extractFromIdentifier(inner, context);
|
|
107
|
+
classNames.push(...addBranchId(extracted));
|
|
92
108
|
}
|
|
93
109
|
else {
|
|
94
|
-
classNames.push(...this.extractFromExpression(inner, context));
|
|
110
|
+
classNames.push(...this.extractFromExpression(inner, context, conditionalBranchId));
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
113
|
// Handle array literal expressions: ['class1', 'class2', myVar]
|
|
@@ -99,10 +115,11 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
99
115
|
expression.elements.forEach(element => {
|
|
100
116
|
// Handle identifier elements (variable references in arrays)
|
|
101
117
|
if (context.typescript.isIdentifier(element)) {
|
|
102
|
-
|
|
118
|
+
const extracted = this.variableExtractor.extractFromIdentifier(element, context);
|
|
119
|
+
classNames.push(...addBranchId(extracted));
|
|
103
120
|
}
|
|
104
121
|
else {
|
|
105
|
-
classNames.push(...this.extractFromExpression(element, context));
|
|
122
|
+
classNames.push(...this.extractFromExpression(element, context, conditionalBranchId));
|
|
106
123
|
}
|
|
107
124
|
});
|
|
108
125
|
}
|
|
@@ -124,7 +141,8 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
124
141
|
absoluteStart: stringContentStart + offset,
|
|
125
142
|
length: className.length,
|
|
126
143
|
line: lineNumber,
|
|
127
|
-
file: context.sourceFile.fileName
|
|
144
|
+
file: context.sourceFile.fileName,
|
|
145
|
+
conditionalBranchId
|
|
128
146
|
});
|
|
129
147
|
}
|
|
130
148
|
offset += className.length + 1;
|
|
@@ -137,7 +155,8 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
137
155
|
absoluteStart: name.getStart(),
|
|
138
156
|
length: name.text.length,
|
|
139
157
|
line: lineNumber,
|
|
140
|
-
file: context.sourceFile.fileName
|
|
158
|
+
file: context.sourceFile.fileName,
|
|
159
|
+
conditionalBranchId
|
|
141
160
|
});
|
|
142
161
|
}
|
|
143
162
|
// Handle computed property keys: { ['flex']: true } or { [myVar]: true }
|
|
@@ -145,14 +164,15 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
145
164
|
const computedExpr = name.expression;
|
|
146
165
|
// Handle identifier in computed property (variable reference)
|
|
147
166
|
if (context.typescript.isIdentifier(computedExpr)) {
|
|
148
|
-
|
|
167
|
+
const extracted = this.variableExtractor.extractFromIdentifier(computedExpr, context);
|
|
168
|
+
classNames.push(...addBranchId(extracted));
|
|
149
169
|
}
|
|
150
170
|
else {
|
|
151
|
-
classNames.push(...this.extractFromExpression(computedExpr, context));
|
|
171
|
+
classNames.push(...this.extractFromExpression(computedExpr, context, conditionalBranchId));
|
|
152
172
|
}
|
|
153
173
|
}
|
|
154
174
|
// Process the value - it might contain arrays, nested objects, etc.
|
|
155
|
-
classNames.push(...this.extractFromExpression(property.initializer, context));
|
|
175
|
+
classNames.push(...this.extractFromExpression(property.initializer, context, conditionalBranchId));
|
|
156
176
|
}
|
|
157
177
|
// Handle shorthand property assignments: { flex }
|
|
158
178
|
else if (context.typescript.isShorthandPropertyAssignment(property)) {
|
|
@@ -163,7 +183,8 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
163
183
|
absoluteStart: name.getStart(),
|
|
164
184
|
length: name.text.length,
|
|
165
185
|
line: lineNumber,
|
|
166
|
-
file: context.sourceFile.fileName
|
|
186
|
+
file: context.sourceFile.fileName,
|
|
187
|
+
conditionalBranchId
|
|
167
188
|
});
|
|
168
189
|
}
|
|
169
190
|
}
|
|
@@ -174,11 +195,11 @@ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
174
195
|
// Import and use TemplateExpressionExtractor to avoid circular dependency
|
|
175
196
|
const { TemplateExpressionExtractor } = require('./TemplateExpressionExtractor');
|
|
176
197
|
const templateExtractor = new TemplateExpressionExtractor();
|
|
177
|
-
classNames.push(...templateExtractor.extract(expression, context));
|
|
198
|
+
classNames.push(...addBranchId(templateExtractor.extract(expression, context)));
|
|
178
199
|
}
|
|
179
200
|
// Handle no-substitution template literal
|
|
180
201
|
else if (context.typescript.isNoSubstitutionTemplateLiteral(expression)) {
|
|
181
|
-
return this.extractFromStringLiteral(expression, context);
|
|
202
|
+
return addBranchId(this.extractFromStringLiteral(expression, context));
|
|
182
203
|
}
|
|
183
204
|
// Note: Identifier handling is done in JsxAttributeExtractor for top-level variable references
|
|
184
205
|
// We don't resolve identifiers here to avoid validating dynamic variables inside template interpolations
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressionExtractor.js","sourceRoot":"","sources":["../../src/extractors/ExpressionExtractor.ts"],"names":[],"mappings":";;;AAGA,mDAAgD;AAChD,6EAA0E;AAE1E;;;GAGG;AACH,MAAa,mBAAoB,SAAQ,6BAAa;IAGrD;QACC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,iBAAiB,GAAG,IAAI,uDAA0B,EAAE,CAAC;IAC3D,CAAC;IAED,SAAS,CAAC,IAAa,EAAE,OAA0B;QAClD,OAAO,CACN,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC;YACrC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC;YACxC,OAAO,CAAC,UAAU,CAAC,+BAA+B,CAAC,IAAI,CAAC,CACxD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAa,EAAE,OAA0B;QAChD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,IAAqB,CAAC,EAAE,CAAC;YAC7D,OAAO,EAAE,CAAC;QACX,CAAC;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC,IAAqB,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"ExpressionExtractor.js","sourceRoot":"","sources":["../../src/extractors/ExpressionExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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"}
|
|
@@ -46,6 +46,8 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
46
46
|
if (!initializer) {
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
|
+
// Generate unique attributeId for duplicate detection
|
|
50
|
+
const attributeId = `${attr.getStart()}-${attr.getEnd()}`;
|
|
49
51
|
// FAST PATH: String literal (most common case ~70%)
|
|
50
52
|
// Inline this hot path to avoid function call overhead
|
|
51
53
|
if (context.typescript.isStringLiteral(initializer)) {
|
|
@@ -67,7 +69,8 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
67
69
|
length: part.length,
|
|
68
70
|
line: context.sourceFile.getLineAndCharacterOfPosition(stringContentStart + offset).line +
|
|
69
71
|
1,
|
|
70
|
-
file: context.sourceFile.fileName
|
|
72
|
+
file: context.sourceFile.fileName,
|
|
73
|
+
attributeId
|
|
71
74
|
});
|
|
72
75
|
}
|
|
73
76
|
offset += part.length;
|
|
@@ -80,17 +83,19 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
80
83
|
if (!expression) {
|
|
81
84
|
continue;
|
|
82
85
|
}
|
|
86
|
+
// Helper to add attributeId to extracted classes
|
|
87
|
+
const addAttributeId = (classes) => classes.map(c => ({ ...c, attributeId }));
|
|
83
88
|
// OPTIMIZATION: Check type before delegating to extractor
|
|
84
89
|
if (context.typescript.isStringLiteral(expression)) {
|
|
85
|
-
classNames.push(...this.expressionExtractor.extract(expression, context));
|
|
90
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
|
|
86
91
|
}
|
|
87
92
|
else if (context.typescript.isTemplateExpression(expression) ||
|
|
88
93
|
context.typescript.isNoSubstitutionTemplateLiteral(expression)) {
|
|
89
|
-
classNames.push(...this.templateExtractor.extract(expression, context));
|
|
94
|
+
classNames.push(...addAttributeId(this.templateExtractor.extract(expression, context)));
|
|
90
95
|
}
|
|
91
96
|
else if (context.typescript.isCallExpression(expression)) {
|
|
92
97
|
if (this.shouldValidateFunctionCall(expression, context.utilityFunctions)) {
|
|
93
|
-
classNames.push(...this.expressionExtractor.extract(expression, context));
|
|
98
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
else if (context.typescript.isBinaryExpression(expression) ||
|
|
@@ -99,20 +104,20 @@ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
99
104
|
context.typescript.isAsExpression(expression) ||
|
|
100
105
|
context.typescript.isNonNullExpression(expression) ||
|
|
101
106
|
context.typescript.isTypeAssertionExpression(expression)) {
|
|
102
|
-
classNames.push(...this.expressionExtractor.extract(expression, context));
|
|
107
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
|
|
103
108
|
}
|
|
104
109
|
// Handle identifier references: className={dynamicClass}
|
|
105
110
|
// This resolves the variable to its declared value for validation
|
|
106
111
|
else if (context.typescript.isIdentifier(expression)) {
|
|
107
|
-
classNames.push(...this.expressionExtractor.extractFromIdentifier(expression, context));
|
|
112
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extractFromIdentifier(expression, context)));
|
|
108
113
|
}
|
|
109
114
|
// Handle array literal expressions: className={['flex', 'items-center']}
|
|
110
115
|
else if (context.typescript.isArrayLiteralExpression(expression)) {
|
|
111
|
-
classNames.push(...this.expressionExtractor.extract(expression, context));
|
|
116
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
|
|
112
117
|
}
|
|
113
118
|
// Handle object literal expressions: className={{ flex: true }}
|
|
114
119
|
else if (context.typescript.isObjectLiteralExpression(expression)) {
|
|
115
|
-
classNames.push(...this.expressionExtractor.extract(expression, context));
|
|
120
|
+
classNames.push(...addAttributeId(this.expressionExtractor.extract(expression, context)));
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JsxAttributeExtractor.js","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.ts"],"names":[],"mappings":";;;AAGA,mDAAgD;AAChD,+DAA4D;AAC5D,+EAA4E;AAE5E;;;;;;;;GAQG;AACH,MAAa,qBAAsB,SAAQ,6BAAa;IAIvD;QACC,KAAK,EAAE,CAAC;QACR,iDAAiD;QACjD,IAAI,CAAC,mBAAmB,GAAG,IAAI,yCAAmB,EAAE,CAAC;QACrD,IAAI,CAAC,iBAAiB,GAAG,IAAI,yDAA2B,EAAE,CAAC;IAC5D,CAAC;IAED,SAAS,CAAC,IAAa,EAAE,OAA0B;QAClD,OAAO,CACN,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC;YAC5C,OAAO,CAAC,UAAU,CAAC,uBAAuB,CAAC,IAAI,CAAC,CAChD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,IAAa,EAAE,OAA0B;QAChD,MAAM,UAAU,GAAoB,EAAE,CAAC;QAEvC,+DAA+D;QAC/D,IACC,CAAC,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,IAAI,CAAC;YAC7C,CAAC,OAAO,CAAC,UAAU,CAAC,uBAAuB,CAAC,IAAI,CAAC,EAChD,CAAC;YACF,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAE9C,4CAA4C;QAC5C,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC;QACnB,CAAC;QAED,qBAAqB;QACrB,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC/B,8CAA8C;YAC9C,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,WAAW,EAAE,CAAC;gBACrF,SAAS;YACV,CAAC;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;YACrC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClB,SAAS;YACV,CAAC;YAED,oDAAoD;YACpD,uDAAuD;YACvD,IAAI,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC;gBACrD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC;gBAElC,6CAA6C;gBAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC3B,SAAS;gBACV,CAAC;gBAED,MAAM,kBAAkB,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;gBACtD,IAAI,MAAM,GAAG,CAAC,CAAC;gBAEf,yEAAyE;gBACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBAC1B,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;wBACjC,sCAAsC;wBACtC,UAAU,CAAC,IAAI,CAAC;4BACf,SAAS,EAAE,IAAI;4BACf,aAAa,EAAE,kBAAkB,GAAG,MAAM;4BAC1C,MAAM,EAAE,IAAI,CAAC,MAAM;4BACnB,IAAI,EACH,OAAO,CAAC,UAAU,CAAC,6BAA6B,CAAC,kBAAkB,GAAG,MAAM,CAAC,CAAC,IAAI;gCAClF,CAAC;4BACF,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ;
|
|
1
|
+
{"version":3,"file":"JsxAttributeExtractor.js","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TailwindVariantsExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/TailwindVariantsExtractor.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;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,yBAA0B,SAAQ,aAAa;IAC3D,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,iBAAiB,CAA6B;;IAQtD,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAI7D,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;
|
|
1
|
+
{"version":3,"file":"TailwindVariantsExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/TailwindVariantsExtractor.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;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,yBAA0B,SAAQ,aAAa;IAC3D,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,eAAe,CAAiC;IACxD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,iBAAiB,CAA6B;;IAQtD,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAI7D,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;IAsCnE;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAsBhB;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAoDxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuD3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAiCnC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAoCxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+IxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAsD/B;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA+B1B;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAoCjC;;OAEG;IACH,UAAU,IAAI,IAAI;CAIlB"}
|
|
@@ -52,8 +52,10 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
52
52
|
if (!context.typescript.isObjectLiteralExpression(configArg)) {
|
|
53
53
|
return [];
|
|
54
54
|
}
|
|
55
|
+
// Generate unique attributeId for duplicate detection within this tv() call
|
|
56
|
+
const attributeId = `tv:${callExpression.getStart()}-${callExpression.getEnd()}`;
|
|
55
57
|
// Extract class names from the tv() configuration object
|
|
56
|
-
return this.extractFromTvConfig(configArg, context);
|
|
58
|
+
return this.extractFromTvConfig(configArg, context, attributeId);
|
|
57
59
|
}
|
|
58
60
|
// Check if this is a call to a function created by tv() (e.g., button({ class: '...' }))
|
|
59
61
|
// IMPORTANT: Only validate if NOT a utility function
|
|
@@ -135,7 +137,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
135
137
|
/**
|
|
136
138
|
* Extract class names from tv() configuration object
|
|
137
139
|
*/
|
|
138
|
-
extractFromTvConfig(config, context) {
|
|
140
|
+
extractFromTvConfig(config, context, attributeId) {
|
|
139
141
|
const classNames = [];
|
|
140
142
|
for (const property of config.properties) {
|
|
141
143
|
if (!context.typescript.isPropertyAssignment(property)) {
|
|
@@ -149,26 +151,26 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
149
151
|
switch (propertyName) {
|
|
150
152
|
case 'base':
|
|
151
153
|
// base: 'flex items-center' or base: ['flex', 'items-center']
|
|
152
|
-
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
154
|
+
classNames.push(...this.extractFromValue(property.initializer, context, attributeId));
|
|
153
155
|
break;
|
|
154
156
|
case 'variants':
|
|
155
157
|
// variants: { size: { sm: 'text-sm', lg: 'text-lg' } }
|
|
156
|
-
classNames.push(...this.extractFromVariants(property.initializer, context));
|
|
158
|
+
classNames.push(...this.extractFromVariants(property.initializer, context, attributeId));
|
|
157
159
|
break;
|
|
158
160
|
case 'compoundVariants':
|
|
159
161
|
// compoundVariants: [{ size: 'sm', color: 'primary', class: 'font-bold' }]
|
|
160
|
-
classNames.push(...this.extractFromCompoundVariants(property.initializer, context));
|
|
162
|
+
classNames.push(...this.extractFromCompoundVariants(property.initializer, context, attributeId));
|
|
161
163
|
break;
|
|
162
164
|
case 'slots':
|
|
163
165
|
// slots: { base: 'flex', item: 'p-2' }
|
|
164
|
-
classNames.push(...this.extractFromSlots(property.initializer, context));
|
|
166
|
+
classNames.push(...this.extractFromSlots(property.initializer, context, attributeId));
|
|
165
167
|
break;
|
|
166
168
|
case 'defaultVariants':
|
|
167
169
|
// defaultVariants doesn't contain classes, skip
|
|
168
170
|
break;
|
|
169
171
|
default:
|
|
170
172
|
// Other properties might contain classes, try to extract
|
|
171
|
-
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
173
|
+
classNames.push(...this.extractFromValue(property.initializer, context, attributeId));
|
|
172
174
|
break;
|
|
173
175
|
}
|
|
174
176
|
}
|
|
@@ -178,7 +180,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
178
180
|
* Extract class names from the variants object
|
|
179
181
|
* Structure: { variantName: { optionName: 'classes' } }
|
|
180
182
|
*/
|
|
181
|
-
extractFromVariants(node, context) {
|
|
183
|
+
extractFromVariants(node, context, attributeId) {
|
|
182
184
|
if (!context.typescript.isObjectLiteralExpression(node)) {
|
|
183
185
|
return [];
|
|
184
186
|
}
|
|
@@ -196,7 +198,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
196
198
|
continue;
|
|
197
199
|
}
|
|
198
200
|
// Extract classes from the option value
|
|
199
|
-
classNames.push(...this.extractFromValue(optionProp.initializer, context));
|
|
201
|
+
classNames.push(...this.extractFromValue(optionProp.initializer, context, attributeId));
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
204
|
}
|
|
@@ -206,7 +208,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
206
208
|
* Extract class names from compoundVariants array
|
|
207
209
|
* Structure: [{ condition: value, class: 'classes' or className: 'classes' }]
|
|
208
210
|
*/
|
|
209
|
-
extractFromCompoundVariants(node, context) {
|
|
211
|
+
extractFromCompoundVariants(node, context, attributeId) {
|
|
210
212
|
if (!context.typescript.isArrayLiteralExpression(node)) {
|
|
211
213
|
return [];
|
|
212
214
|
}
|
|
@@ -223,7 +225,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
223
225
|
}
|
|
224
226
|
const propName = this.getPropertyName(prop, context);
|
|
225
227
|
if (propName === 'class' || propName === 'className') {
|
|
226
|
-
classNames.push(...this.extractFromValue(prop.initializer, context));
|
|
228
|
+
classNames.push(...this.extractFromValue(prop.initializer, context, attributeId));
|
|
227
229
|
}
|
|
228
230
|
}
|
|
229
231
|
}
|
|
@@ -233,7 +235,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
233
235
|
* Extract class names from slots object
|
|
234
236
|
* Structure: { slotName: 'classes' } or { slotName: { base: 'classes', variants: {...} } }
|
|
235
237
|
*/
|
|
236
|
-
extractFromSlots(node, context) {
|
|
238
|
+
extractFromSlots(node, context, attributeId) {
|
|
237
239
|
if (!context.typescript.isObjectLiteralExpression(node)) {
|
|
238
240
|
return [];
|
|
239
241
|
}
|
|
@@ -245,15 +247,16 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
245
247
|
const slotValue = slotProp.initializer;
|
|
246
248
|
// If slot value is a string, extract classes
|
|
247
249
|
if (context.typescript.isStringLiteral(slotValue)) {
|
|
248
|
-
|
|
250
|
+
const extracted = this.extractFromStringLiteral(slotValue, context);
|
|
251
|
+
classNames.push(...(attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted));
|
|
249
252
|
}
|
|
250
253
|
// If slot value is an object with base/variants, recurse
|
|
251
254
|
else if (context.typescript.isObjectLiteralExpression(slotValue)) {
|
|
252
|
-
classNames.push(...this.extractFromTvConfig(slotValue, context));
|
|
255
|
+
classNames.push(...this.extractFromTvConfig(slotValue, context, attributeId));
|
|
253
256
|
}
|
|
254
257
|
// Handle arrays and other expressions
|
|
255
258
|
else {
|
|
256
|
-
classNames.push(...this.extractFromValue(slotValue, context));
|
|
259
|
+
classNames.push(...this.extractFromValue(slotValue, context, attributeId));
|
|
257
260
|
}
|
|
258
261
|
}
|
|
259
262
|
return classNames;
|
|
@@ -261,33 +264,39 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
261
264
|
/**
|
|
262
265
|
* Extract class names from any expression value
|
|
263
266
|
*/
|
|
264
|
-
extractFromValue(node, context) {
|
|
267
|
+
extractFromValue(node, context, attributeId) {
|
|
265
268
|
// String literal: 'flex items-center'
|
|
266
269
|
if (context.typescript.isStringLiteral(node)) {
|
|
267
|
-
|
|
270
|
+
const extracted = this.extractFromStringLiteral(node, context);
|
|
271
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
268
272
|
}
|
|
269
273
|
// No-substitution template literal: `flex items-center`
|
|
270
274
|
if (context.typescript.isNoSubstitutionTemplateLiteral(node)) {
|
|
271
|
-
|
|
275
|
+
const extracted = this.extractFromStringLiteral(node, context);
|
|
276
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
272
277
|
}
|
|
273
278
|
// Identifier (variable reference): base: myBaseClasses
|
|
274
279
|
if (context.typescript.isIdentifier(node)) {
|
|
275
|
-
|
|
280
|
+
const extracted = this.variableExtractor.extractFromIdentifier(node, context);
|
|
281
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
276
282
|
}
|
|
277
283
|
// Array: ['flex', 'items-center', myVar]
|
|
278
284
|
if (context.typescript.isArrayLiteralExpression(node)) {
|
|
279
285
|
const classNames = [];
|
|
280
286
|
for (const element of node.elements) {
|
|
281
287
|
if (context.typescript.isStringLiteral(element)) {
|
|
282
|
-
|
|
288
|
+
const extracted = this.extractFromStringLiteral(element, context);
|
|
289
|
+
classNames.push(...(attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted));
|
|
283
290
|
}
|
|
284
291
|
else if (context.typescript.isIdentifier(element)) {
|
|
285
292
|
// Handle variable references in arrays
|
|
286
|
-
|
|
293
|
+
const extracted = this.variableExtractor.extractFromIdentifier(element, context);
|
|
294
|
+
classNames.push(...(attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted));
|
|
287
295
|
}
|
|
288
296
|
else if (context.typescript.isExpression(element)) {
|
|
289
297
|
// Handle complex expressions in arrays (ternary, binary, etc.)
|
|
290
|
-
|
|
298
|
+
const extracted = this.expressionExtractor.extractFromExpression(element, context);
|
|
299
|
+
classNames.push(...(attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted));
|
|
291
300
|
}
|
|
292
301
|
}
|
|
293
302
|
return classNames;
|
|
@@ -309,7 +318,8 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
309
318
|
absoluteStart: headStart + offset,
|
|
310
319
|
length: className.length,
|
|
311
320
|
line: lineNumber,
|
|
312
|
-
file: context.sourceFile.fileName
|
|
321
|
+
file: context.sourceFile.fileName,
|
|
322
|
+
attributeId
|
|
313
323
|
});
|
|
314
324
|
}
|
|
315
325
|
offset += className.length + 1;
|
|
@@ -328,7 +338,8 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
328
338
|
absoluteStart: spanStart + offset,
|
|
329
339
|
length: className.length,
|
|
330
340
|
line: lineNumber,
|
|
331
|
-
file: context.sourceFile.fileName
|
|
341
|
+
file: context.sourceFile.fileName,
|
|
342
|
+
attributeId
|
|
332
343
|
});
|
|
333
344
|
}
|
|
334
345
|
offset += className.length + 1;
|
|
@@ -339,27 +350,33 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
339
350
|
}
|
|
340
351
|
// Handle ternary expressions: condition ? 'class1' : 'class2'
|
|
341
352
|
if (context.typescript.isConditionalExpression(node)) {
|
|
342
|
-
|
|
353
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
354
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
343
355
|
}
|
|
344
356
|
// Handle binary expressions: condition && 'class-name'
|
|
345
357
|
if (context.typescript.isBinaryExpression(node)) {
|
|
346
|
-
|
|
358
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
359
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
347
360
|
}
|
|
348
361
|
// Handle parenthesized expressions: ('class-name')
|
|
349
362
|
if (context.typescript.isParenthesizedExpression(node)) {
|
|
350
|
-
|
|
363
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
364
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
351
365
|
}
|
|
352
366
|
// Handle type assertions: ('class-name' as string)
|
|
353
367
|
if (context.typescript.isAsExpression(node)) {
|
|
354
|
-
|
|
368
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
369
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
355
370
|
}
|
|
356
371
|
// Handle non-null assertions: expr!
|
|
357
372
|
if (context.typescript.isNonNullExpression(node)) {
|
|
358
|
-
|
|
373
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
374
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
359
375
|
}
|
|
360
376
|
// Handle type assertions with angle brackets: <string>'class-name'
|
|
361
377
|
if (context.typescript.isTypeAssertionExpression(node)) {
|
|
362
|
-
|
|
378
|
+
const extracted = this.expressionExtractor.extractFromExpression(node, context);
|
|
379
|
+
return attributeId ? extracted.map(c => ({ ...c, attributeId })) : extracted;
|
|
363
380
|
}
|
|
364
381
|
return [];
|
|
365
382
|
}
|
|
@@ -466,6 +483,8 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
466
483
|
if (!context.typescript.isObjectLiteralExpression(arg)) {
|
|
467
484
|
return [];
|
|
468
485
|
}
|
|
486
|
+
// Generate unique attributeId for duplicate detection within this tv function call
|
|
487
|
+
const attributeId = `tv-call:${callExpression.getStart()}-${callExpression.getEnd()}`;
|
|
469
488
|
const classNames = [];
|
|
470
489
|
// Look for 'class' or 'className' properties
|
|
471
490
|
for (const property of arg.properties) {
|
|
@@ -475,7 +494,7 @@ class TailwindVariantsExtractor extends BaseExtractor_1.BaseExtractor {
|
|
|
475
494
|
const propName = this.getPropertyName(property, context);
|
|
476
495
|
if (propName === 'class' || propName === 'className') {
|
|
477
496
|
// Extract classes from the value
|
|
478
|
-
classNames.push(...this.extractFromValue(property.initializer, context));
|
|
497
|
+
classNames.push(...this.extractFromValue(property.initializer, context, attributeId));
|
|
479
498
|
}
|
|
480
499
|
}
|
|
481
500
|
return classNames;
|