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.
Files changed (88) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/LICENSE +21 -0
  3. package/README.md +538 -0
  4. package/lib/core/interfaces.d.ts +45 -0
  5. package/lib/core/interfaces.d.ts.map +1 -0
  6. package/lib/core/interfaces.js +3 -0
  7. package/lib/core/interfaces.js.map +1 -0
  8. package/lib/core/types.d.ts +27 -0
  9. package/lib/core/types.d.ts.map +1 -0
  10. package/lib/core/types.js +3 -0
  11. package/lib/core/types.js.map +1 -0
  12. package/lib/extractors/BaseExtractor.d.ts +20 -0
  13. package/lib/extractors/BaseExtractor.d.ts.map +1 -0
  14. package/lib/extractors/BaseExtractor.js +83 -0
  15. package/lib/extractors/BaseExtractor.js.map +1 -0
  16. package/lib/extractors/CvaExtractor.d.ts +88 -0
  17. package/lib/extractors/CvaExtractor.d.ts.map +1 -0
  18. package/lib/extractors/CvaExtractor.js +425 -0
  19. package/lib/extractors/CvaExtractor.js.map +1 -0
  20. package/lib/extractors/ExpressionExtractor.d.ts +16 -0
  21. package/lib/extractors/ExpressionExtractor.d.ts.map +1 -0
  22. package/lib/extractors/ExpressionExtractor.js +132 -0
  23. package/lib/extractors/ExpressionExtractor.js.map +1 -0
  24. package/lib/extractors/JsxAttributeExtractor.d.ts +20 -0
  25. package/lib/extractors/JsxAttributeExtractor.d.ts.map +1 -0
  26. package/lib/extractors/JsxAttributeExtractor.js +107 -0
  27. package/lib/extractors/JsxAttributeExtractor.js.map +1 -0
  28. package/lib/extractors/JsxAttributeExtractor.original.d.ts +15 -0
  29. package/lib/extractors/JsxAttributeExtractor.original.d.ts.map +1 -0
  30. package/lib/extractors/JsxAttributeExtractor.original.js +84 -0
  31. package/lib/extractors/JsxAttributeExtractor.original.js.map +1 -0
  32. package/lib/extractors/StringLiteralExtractor.d.ts +12 -0
  33. package/lib/extractors/StringLiteralExtractor.d.ts.map +1 -0
  34. package/lib/extractors/StringLiteralExtractor.js +21 -0
  35. package/lib/extractors/StringLiteralExtractor.js.map +1 -0
  36. package/lib/extractors/TailwindVariantsExtractor.d.ts +87 -0
  37. package/lib/extractors/TailwindVariantsExtractor.d.ts.map +1 -0
  38. package/lib/extractors/TailwindVariantsExtractor.js +447 -0
  39. package/lib/extractors/TailwindVariantsExtractor.js.map +1 -0
  40. package/lib/extractors/TemplateExpressionExtractor.d.ts +14 -0
  41. package/lib/extractors/TemplateExpressionExtractor.d.ts.map +1 -0
  42. package/lib/extractors/TemplateExpressionExtractor.js +66 -0
  43. package/lib/extractors/TemplateExpressionExtractor.js.map +1 -0
  44. package/lib/index.d.ts +65 -0
  45. package/lib/index.d.ts.map +1 -0
  46. package/lib/index.js +4 -0
  47. package/lib/index.js.map +1 -0
  48. package/lib/infrastructure/TailwindValidator.d.ts +42 -0
  49. package/lib/infrastructure/TailwindValidator.d.ts.map +1 -0
  50. package/lib/infrastructure/TailwindValidator.js +152 -0
  51. package/lib/infrastructure/TailwindValidator.js.map +1 -0
  52. package/lib/infrastructure/TailwindValidator.spec.d.ts +2 -0
  53. package/lib/infrastructure/TailwindValidator.spec.d.ts.map +1 -0
  54. package/lib/infrastructure/TailwindValidator.spec.js +219 -0
  55. package/lib/infrastructure/TailwindValidator.spec.js.map +1 -0
  56. package/lib/plugin/TailwindTypescriptPlugin.d.ts +52 -0
  57. package/lib/plugin/TailwindTypescriptPlugin.d.ts.map +1 -0
  58. package/lib/plugin/TailwindTypescriptPlugin.js +142 -0
  59. package/lib/plugin/TailwindTypescriptPlugin.js.map +1 -0
  60. package/lib/services/ClassNameExtractionService.d.ts +37 -0
  61. package/lib/services/ClassNameExtractionService.d.ts.map +1 -0
  62. package/lib/services/ClassNameExtractionService.js +98 -0
  63. package/lib/services/ClassNameExtractionService.js.map +1 -0
  64. package/lib/services/ClassNameExtractionService.original.d.ts +20 -0
  65. package/lib/services/ClassNameExtractionService.original.d.ts.map +1 -0
  66. package/lib/services/ClassNameExtractionService.original.js +48 -0
  67. package/lib/services/ClassNameExtractionService.original.js.map +1 -0
  68. package/lib/services/DiagnosticService.d.ts +14 -0
  69. package/lib/services/DiagnosticService.d.ts.map +1 -0
  70. package/lib/services/DiagnosticService.js +61 -0
  71. package/lib/services/DiagnosticService.js.map +1 -0
  72. package/lib/services/PerformanceCache.d.ts +15 -0
  73. package/lib/services/PerformanceCache.d.ts.map +1 -0
  74. package/lib/services/PerformanceCache.js +44 -0
  75. package/lib/services/PerformanceCache.js.map +1 -0
  76. package/lib/services/PluginConfigService.d.ts +22 -0
  77. package/lib/services/PluginConfigService.d.ts.map +1 -0
  78. package/lib/services/PluginConfigService.js +86 -0
  79. package/lib/services/PluginConfigService.js.map +1 -0
  80. package/lib/services/ValidationService.d.ts +25 -0
  81. package/lib/services/ValidationService.d.ts.map +1 -0
  82. package/lib/services/ValidationService.js +50 -0
  83. package/lib/services/ValidationService.js.map +1 -0
  84. package/lib/utils/Logger.d.ts +10 -0
  85. package/lib/utils/Logger.d.ts.map +1 -0
  86. package/lib/utils/Logger.js +13 -0
  87. package/lib/utils/Logger.js.map +1 -0
  88. package/package.json +84 -0
@@ -0,0 +1,16 @@
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 various expression types
6
+ * This is a utility extractor used by other extractors to handle nested expressions
7
+ */
8
+ export declare class ExpressionExtractor extends BaseExtractor {
9
+ canHandle(node: ts.Node, context: ExtractionContext): boolean;
10
+ extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
11
+ /**
12
+ * Recursively extract class names from any expression type
13
+ */
14
+ extractFromExpression(expression: ts.Expression, context: ExtractionContext): ClassNameInfo[];
15
+ }
16
+ //# sourceMappingURL=ExpressionExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpressionExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/ExpressionExtractor.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;AAEhD;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;IACrD,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAQ7D,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;IAOnE;;OAEG;IACH,qBAAqB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,iBAAiB,GAAG,aAAa,EAAE;CAmH7F"}
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ExpressionExtractor = void 0;
4
+ const BaseExtractor_1 = require("./BaseExtractor");
5
+ /**
6
+ * Extracts class names from various expression types
7
+ * This is a utility extractor used by other extractors to handle nested expressions
8
+ */
9
+ class ExpressionExtractor extends BaseExtractor_1.BaseExtractor {
10
+ canHandle(node, context) {
11
+ return (context.typescript.isExpression(node) ||
12
+ context.typescript.isStringLiteral(node) ||
13
+ context.typescript.isNoSubstitutionTemplateLiteral(node));
14
+ }
15
+ extract(node, context) {
16
+ if (!context.typescript.isExpression(node)) {
17
+ return [];
18
+ }
19
+ return this.extractFromExpression(node, context);
20
+ }
21
+ /**
22
+ * Recursively extract class names from any expression type
23
+ */
24
+ extractFromExpression(expression, context) {
25
+ const classNames = [];
26
+ const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(expression.getStart()).line + 1;
27
+ // Handle string literals
28
+ if (context.typescript.isStringLiteral(expression)) {
29
+ return this.extractFromStringLiteral(expression, context);
30
+ }
31
+ // Handle conditional expressions: condition ? 'class1' : 'class2'
32
+ if (context.typescript.isConditionalExpression(expression)) {
33
+ classNames.push(...this.extractFromExpression(expression.whenTrue, context));
34
+ classNames.push(...this.extractFromExpression(expression.whenFalse, context));
35
+ }
36
+ // Handle binary expressions: condition && 'class-name'
37
+ else if (context.typescript.isBinaryExpression(expression)) {
38
+ if (expression.operatorToken.kind === context.typescript.SyntaxKind.AmpersandAmpersandToken ||
39
+ expression.operatorToken.kind === context.typescript.SyntaxKind.BarBarToken) {
40
+ classNames.push(...this.extractFromExpression(expression.right, context));
41
+ }
42
+ }
43
+ // Handle call expressions: clsx('class1', 'class2')
44
+ else if (context.typescript.isCallExpression(expression)) {
45
+ if (this.shouldValidateFunctionCall(expression, context.utilityFunctions)) {
46
+ expression.arguments.forEach(arg => {
47
+ classNames.push(...this.extractFromExpression(arg, context));
48
+ });
49
+ }
50
+ }
51
+ // Handle parenthesized expressions: ('class-name')
52
+ else if (context.typescript.isParenthesizedExpression(expression)) {
53
+ classNames.push(...this.extractFromExpression(expression.expression, context));
54
+ }
55
+ // Handle array literal expressions: ['class1', 'class2']
56
+ else if (context.typescript.isArrayLiteralExpression(expression)) {
57
+ expression.elements.forEach(element => {
58
+ classNames.push(...this.extractFromExpression(element, context));
59
+ });
60
+ }
61
+ // Handle object literal expressions: { 'class-name': true, 'another': condition }
62
+ else if (context.typescript.isObjectLiteralExpression(expression)) {
63
+ expression.properties.forEach(property => {
64
+ // Handle regular property assignments: { 'flex': true }
65
+ if (context.typescript.isPropertyAssignment(property)) {
66
+ const name = property.name;
67
+ // Handle string literal keys: { 'flex': true }
68
+ if (context.typescript.isStringLiteral(name)) {
69
+ const fullText = name.text;
70
+ const stringContentStart = name.getStart() + 1;
71
+ let offset = 0;
72
+ fullText.split(' ').forEach(className => {
73
+ if (className) {
74
+ classNames.push({
75
+ className: className,
76
+ absoluteStart: stringContentStart + offset,
77
+ length: className.length,
78
+ line: lineNumber,
79
+ file: context.sourceFile.fileName
80
+ });
81
+ }
82
+ offset += className.length + 1;
83
+ });
84
+ }
85
+ // Handle identifier keys: { flex: true }
86
+ else if (context.typescript.isIdentifier(name)) {
87
+ classNames.push({
88
+ className: name.text,
89
+ absoluteStart: name.getStart(),
90
+ length: name.text.length,
91
+ line: lineNumber,
92
+ file: context.sourceFile.fileName
93
+ });
94
+ }
95
+ // Handle computed property keys: { ['flex']: true }
96
+ else if (context.typescript.isComputedPropertyName(name)) {
97
+ classNames.push(...this.extractFromExpression(name.expression, context));
98
+ }
99
+ // Process the value - it might contain arrays, nested objects, etc.
100
+ classNames.push(...this.extractFromExpression(property.initializer, context));
101
+ }
102
+ // Handle shorthand property assignments: { flex }
103
+ else if (context.typescript.isShorthandPropertyAssignment(property)) {
104
+ const name = property.name;
105
+ if (context.typescript.isIdentifier(name)) {
106
+ classNames.push({
107
+ className: name.text,
108
+ absoluteStart: name.getStart(),
109
+ length: name.text.length,
110
+ line: lineNumber,
111
+ file: context.sourceFile.fileName
112
+ });
113
+ }
114
+ }
115
+ });
116
+ }
117
+ // Handle template expressions
118
+ else if (context.typescript.isTemplateExpression(expression)) {
119
+ // Import and use TemplateExpressionExtractor to avoid circular dependency
120
+ const { TemplateExpressionExtractor } = require('./TemplateExpressionExtractor');
121
+ const templateExtractor = new TemplateExpressionExtractor();
122
+ classNames.push(...templateExtractor.extract(expression, context));
123
+ }
124
+ // Handle no-substitution template literal
125
+ else if (context.typescript.isNoSubstitutionTemplateLiteral(expression)) {
126
+ return this.extractFromStringLiteral(expression, context);
127
+ }
128
+ return classNames;
129
+ }
130
+ }
131
+ exports.ExpressionExtractor = ExpressionExtractor;
132
+ //# sourceMappingURL=ExpressionExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpressionExtractor.js","sourceRoot":"","sources":["../../src/extractors/ExpressionExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import * as ts from 'typescript/lib/tsserverlibrary';
2
+ import { ClassNameInfo, ExtractionContext } from '../core/types';
3
+ import { BaseExtractor } from './BaseExtractor';
4
+ /**
5
+ * OPTIMIZED: Extracts class names from JSX className attributes
6
+ *
7
+ * Performance improvements:
8
+ * 1. Fast path for string literals (most common, ~70% of cases)
9
+ * 2. Inline hot paths to reduce function call overhead
10
+ * 3. Early returns to avoid unnecessary processing
11
+ * 4. Reuse extractor instances
12
+ */
13
+ export declare class JsxAttributeExtractor extends BaseExtractor {
14
+ private expressionExtractor;
15
+ private templateExtractor;
16
+ constructor();
17
+ canHandle(node: ts.Node, context: ExtractionContext): boolean;
18
+ extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
19
+ }
20
+ //# sourceMappingURL=JsxAttributeExtractor.d.ts.map
@@ -0,0 +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;CA+FnE"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsxAttributeExtractor = void 0;
4
+ const BaseExtractor_1 = require("./BaseExtractor");
5
+ const ExpressionExtractor_1 = require("./ExpressionExtractor");
6
+ const TemplateExpressionExtractor_1 = require("./TemplateExpressionExtractor");
7
+ /**
8
+ * OPTIMIZED: Extracts class names from JSX className attributes
9
+ *
10
+ * Performance improvements:
11
+ * 1. Fast path for string literals (most common, ~70% of cases)
12
+ * 2. Inline hot paths to reduce function call overhead
13
+ * 3. Early returns to avoid unnecessary processing
14
+ * 4. Reuse extractor instances
15
+ */
16
+ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
17
+ constructor() {
18
+ super();
19
+ // Create once, reuse (avoid recreation overhead)
20
+ this.expressionExtractor = new ExpressionExtractor_1.ExpressionExtractor();
21
+ this.templateExtractor = new TemplateExpressionExtractor_1.TemplateExpressionExtractor();
22
+ }
23
+ canHandle(node, context) {
24
+ return (context.typescript.isJsxOpeningElement(node) ||
25
+ context.typescript.isJsxSelfClosingElement(node));
26
+ }
27
+ extract(node, context) {
28
+ const classNames = [];
29
+ // Type guard (already checked in service, but keep for safety)
30
+ if (!context.typescript.isJsxOpeningElement(node) &&
31
+ !context.typescript.isJsxSelfClosingElement(node)) {
32
+ return classNames;
33
+ }
34
+ const attributes = node.attributes.properties;
35
+ // OPTIMIZATION: Early exit if no attributes
36
+ if (attributes.length === 0) {
37
+ return classNames;
38
+ }
39
+ // Process attributes
40
+ for (const attr of attributes) {
41
+ // OPTIMIZATION: Check both conditions at once
42
+ if (!context.typescript.isJsxAttribute(attr) || attr.name.getText() !== 'className') {
43
+ continue;
44
+ }
45
+ const initializer = attr.initializer;
46
+ if (!initializer) {
47
+ continue;
48
+ }
49
+ // FAST PATH: String literal (most common case ~70%)
50
+ // Inline this hot path to avoid function call overhead
51
+ if (context.typescript.isStringLiteral(initializer)) {
52
+ const fullText = initializer.text;
53
+ // OPTIMIZATION: Early exit for empty strings
54
+ if (fullText.length === 0) {
55
+ continue;
56
+ }
57
+ const stringContentStart = initializer.getStart() + 1;
58
+ const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(attr.getStart()).line + 1;
59
+ let offset = 0;
60
+ // OPTIMIZATION: Split and filter in one pass
61
+ const classes = fullText.split(' ');
62
+ for (let i = 0; i < classes.length; i++) {
63
+ const className = classes[i];
64
+ if (className) {
65
+ classNames.push({
66
+ className,
67
+ absoluteStart: stringContentStart + offset,
68
+ length: className.length,
69
+ line: lineNumber,
70
+ file: context.sourceFile.fileName
71
+ });
72
+ }
73
+ offset += className.length + 1;
74
+ }
75
+ continue; // Skip to next attribute
76
+ }
77
+ // JSX expression: className={'foo bar'} or className={clsx(...)}
78
+ if (context.typescript.isJsxExpression(initializer)) {
79
+ const expression = initializer.expression;
80
+ if (!expression) {
81
+ continue;
82
+ }
83
+ // OPTIMIZATION: Check type before delegating to extractor
84
+ if (context.typescript.isStringLiteral(expression)) {
85
+ classNames.push(...this.expressionExtractor.extract(expression, context));
86
+ }
87
+ else if (context.typescript.isTemplateExpression(expression) ||
88
+ context.typescript.isNoSubstitutionTemplateLiteral(expression)) {
89
+ classNames.push(...this.templateExtractor.extract(expression, context));
90
+ }
91
+ else if (context.typescript.isCallExpression(expression)) {
92
+ if (this.shouldValidateFunctionCall(expression, context.utilityFunctions)) {
93
+ classNames.push(...this.expressionExtractor.extract(expression, context));
94
+ }
95
+ }
96
+ else if (context.typescript.isBinaryExpression(expression) ||
97
+ context.typescript.isConditionalExpression(expression) ||
98
+ context.typescript.isParenthesizedExpression(expression)) {
99
+ classNames.push(...this.expressionExtractor.extract(expression, context));
100
+ }
101
+ }
102
+ }
103
+ return classNames;
104
+ }
105
+ }
106
+ exports.JsxAttributeExtractor = JsxAttributeExtractor;
107
+ //# sourceMappingURL=JsxAttributeExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsxAttributeExtractor.js","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
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 JSX className attributes
6
+ * This is the main orchestrator for JSX elements
7
+ */
8
+ export declare class JsxAttributeExtractor extends BaseExtractor {
9
+ private expressionExtractor;
10
+ private templateExtractor;
11
+ constructor();
12
+ canHandle(node: ts.Node, context: ExtractionContext): boolean;
13
+ extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
14
+ }
15
+ //# sourceMappingURL=JsxAttributeExtractor.original.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsxAttributeExtractor.original.d.ts","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.original.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;;;GAGG;AACH,qBAAa,qBAAsB,SAAQ,aAAa;IACvD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,iBAAiB,CAA8B;;IAQvD,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;CA0EnE"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsxAttributeExtractor = void 0;
4
+ const BaseExtractor_1 = require("./BaseExtractor");
5
+ const ExpressionExtractor_1 = require("./ExpressionExtractor");
6
+ const TemplateExpressionExtractor_1 = require("./TemplateExpressionExtractor");
7
+ /**
8
+ * Extracts class names from JSX className attributes
9
+ * This is the main orchestrator for JSX elements
10
+ */
11
+ class JsxAttributeExtractor extends BaseExtractor_1.BaseExtractor {
12
+ constructor() {
13
+ super();
14
+ this.expressionExtractor = new ExpressionExtractor_1.ExpressionExtractor();
15
+ this.templateExtractor = new TemplateExpressionExtractor_1.TemplateExpressionExtractor();
16
+ }
17
+ canHandle(node, context) {
18
+ return (context.typescript.isJsxOpeningElement(node) ||
19
+ context.typescript.isJsxSelfClosingElement(node));
20
+ }
21
+ extract(node, context) {
22
+ const classNames = [];
23
+ if (!context.typescript.isJsxOpeningElement(node) &&
24
+ !context.typescript.isJsxSelfClosingElement(node)) {
25
+ return classNames;
26
+ }
27
+ const attributes = node.attributes.properties;
28
+ for (const attr of attributes) {
29
+ if (context.typescript.isJsxAttribute(attr) && attr.name.getText() === 'className') {
30
+ const initializer = attr.initializer;
31
+ if (!initializer) {
32
+ continue;
33
+ }
34
+ // Handle string literal: className="foo bar"
35
+ if (context.typescript.isStringLiteral(initializer)) {
36
+ const fullText = initializer.text;
37
+ const stringContentStart = initializer.getStart() + 1;
38
+ const lineNumber = context.sourceFile.getLineAndCharacterOfPosition(attr.getStart()).line + 1;
39
+ let offset = 0;
40
+ fullText.split(' ').forEach(className => {
41
+ if (className) {
42
+ classNames.push({
43
+ className: className,
44
+ absoluteStart: stringContentStart + offset,
45
+ length: className.length,
46
+ line: lineNumber,
47
+ file: context.sourceFile.fileName
48
+ });
49
+ }
50
+ offset += className.length + 1;
51
+ });
52
+ }
53
+ // Handle JSX expression: className={'foo bar'} or className={clsx(...)}
54
+ else if (context.typescript.isJsxExpression(initializer)) {
55
+ const expression = initializer.expression;
56
+ if (!expression) {
57
+ continue;
58
+ }
59
+ // Delegate to appropriate extractor based on expression type
60
+ if (context.typescript.isStringLiteral(expression)) {
61
+ classNames.push(...this.expressionExtractor.extract(expression, context));
62
+ }
63
+ else if (context.typescript.isTemplateExpression(expression) ||
64
+ context.typescript.isNoSubstitutionTemplateLiteral(expression)) {
65
+ classNames.push(...this.templateExtractor.extract(expression, context));
66
+ }
67
+ else if (context.typescript.isCallExpression(expression)) {
68
+ if (this.shouldValidateFunctionCall(expression, context.utilityFunctions)) {
69
+ classNames.push(...this.expressionExtractor.extract(expression, context));
70
+ }
71
+ }
72
+ else if (context.typescript.isBinaryExpression(expression) ||
73
+ context.typescript.isConditionalExpression(expression) ||
74
+ context.typescript.isParenthesizedExpression(expression)) {
75
+ classNames.push(...this.expressionExtractor.extract(expression, context));
76
+ }
77
+ }
78
+ }
79
+ }
80
+ return classNames;
81
+ }
82
+ }
83
+ exports.JsxAttributeExtractor = JsxAttributeExtractor;
84
+ //# sourceMappingURL=JsxAttributeExtractor.original.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JsxAttributeExtractor.original.js","sourceRoot":"","sources":["../../src/extractors/JsxAttributeExtractor.original.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
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 string literals
6
+ * Example: 'flex items-center'
7
+ */
8
+ export declare class StringLiteralExtractor extends BaseExtractor {
9
+ canHandle(node: ts.Node, context: ExtractionContext): boolean;
10
+ extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
11
+ }
12
+ //# sourceMappingURL=StringLiteralExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StringLiteralExtractor.d.ts","sourceRoot":"","sources":["../../src/extractors/StringLiteralExtractor.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;AAEhD;;;GAGG;AACH,qBAAa,sBAAuB,SAAQ,aAAa;IACxD,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;CAOnE"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StringLiteralExtractor = void 0;
4
+ const BaseExtractor_1 = require("./BaseExtractor");
5
+ /**
6
+ * Extracts class names from string literals
7
+ * Example: 'flex items-center'
8
+ */
9
+ class StringLiteralExtractor extends BaseExtractor_1.BaseExtractor {
10
+ canHandle(node, context) {
11
+ return context.typescript.isStringLiteral(node);
12
+ }
13
+ extract(node, context) {
14
+ if (!context.typescript.isStringLiteral(node)) {
15
+ return [];
16
+ }
17
+ return this.extractFromStringLiteral(node, context);
18
+ }
19
+ }
20
+ exports.StringLiteralExtractor = StringLiteralExtractor;
21
+ //# sourceMappingURL=StringLiteralExtractor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StringLiteralExtractor.js","sourceRoot":"","sources":["../../src/extractors/StringLiteralExtractor.ts"],"names":[],"mappings":";;;AAGA,mDAAgD;AAEhD;;;GAGG;AACH,MAAa,sBAAuB,SAAQ,6BAAa;IACxD,SAAS,CAAC,IAAa,EAAE,OAA0B;QAClD,OAAO,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,IAAa,EAAE,OAA0B;QAChD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,CAAC;QACX,CAAC;QAED,OAAO,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;CACD;AAZD,wDAYC"}
@@ -0,0 +1,87 @@
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 tailwind-variants tv() function calls
6
+ *
7
+ * Supports:
8
+ * - base: string with classes or array of strings
9
+ * - variants: nested object with string values containing classes
10
+ * - compoundVariants: array of objects with class/className properties
11
+ * - slots: object where values contain classes
12
+ * - Import aliasing: import { tv as myTv } from 'tailwind-variants'
13
+ * - class property overrides: button({ color: 'primary', class: 'bg-pink-500' })
14
+ *
15
+ * PERFORMANCE OPTIMIZATIONS:
16
+ * - ✅ Import detection cached per file (one-time AST scan)
17
+ * - ✅ Early exits for non-tv calls (fast path)
18
+ * - ✅ Direct property access (no unnecessary traversal)
19
+ * - ✅ Inline hot paths (string literal extraction)
20
+ * - ✅ Short-circuit evaluation (skip work when possible)
21
+ * - ✅ TypeChecker-based origin tracking (cached per symbol)
22
+ */
23
+ export declare class TailwindVariantsExtractor extends BaseExtractor {
24
+ private tvImportCache;
25
+ private tvVariableCache;
26
+ canHandle(node: ts.Node, context: ExtractionContext): boolean;
27
+ extract(node: ts.Node, context: ExtractionContext): ClassNameInfo[];
28
+ /**
29
+ * Check if this call expression is a tv() call from tailwind-variants
30
+ * Supports import aliasing: import { tv as myTv } from 'tailwind-variants'
31
+ */
32
+ private isTvCall;
33
+ /**
34
+ * Get all local names for tv imports from tailwind-variants
35
+ * Supports aliasing: import { tv as myTv } -> returns Set(['myTv'])
36
+ * Caches result per file for performance
37
+ */
38
+ private getTvImportNames;
39
+ /**
40
+ * Extract class names from tv() configuration object
41
+ */
42
+ private extractFromTvConfig;
43
+ /**
44
+ * Extract class names from the variants object
45
+ * Structure: { variantName: { optionName: 'classes' } }
46
+ */
47
+ private extractFromVariants;
48
+ /**
49
+ * Extract class names from compoundVariants array
50
+ * Structure: [{ condition: value, class: 'classes' or className: 'classes' }]
51
+ */
52
+ private extractFromCompoundVariants;
53
+ /**
54
+ * Extract class names from slots object
55
+ * Structure: { slotName: 'classes' } or { slotName: { base: 'classes', variants: {...} } }
56
+ */
57
+ private extractFromSlots;
58
+ /**
59
+ * Extract class names from any expression value
60
+ */
61
+ private extractFromValue;
62
+ /**
63
+ * Get property name from a property assignment
64
+ */
65
+ private getPropertyName;
66
+ /**
67
+ * Check if this call expression is calling a function created by tv()
68
+ * Uses TypeChecker for accurate origin tracking
69
+ * IMPORTANT: Returns false for utility functions
70
+ */
71
+ private isTvCreatedFunctionCall;
72
+ /**
73
+ * Check if a symbol's declaration is from a tv() call
74
+ * Handles: const button = tv(...), export const button = tv(...), etc.
75
+ */
76
+ private isSymbolFromTvCall;
77
+ /**
78
+ * Extract class names from a tv() function call
79
+ * Example: button({ color: 'primary', class: 'bg-pink-500' })
80
+ */
81
+ private extractFromTvFunctionCall;
82
+ /**
83
+ * Clear the import cache (useful for testing or when files change)
84
+ */
85
+ clearCache(): void;
86
+ }
87
+ //# sourceMappingURL=TailwindVariantsExtractor.d.ts.map
@@ -0,0 +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;AAEhD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,yBAA0B,SAAQ,aAAa;IAC3D,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,eAAe,CAAiC;IAExD,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;IAmCnE;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAsBhB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAmDxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoD3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA8B3B;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAgCnC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA2ExB;;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;IAkCjC;;OAEG;IACH,UAAU,IAAI,IAAI;CAIlB"}