tailwind-unwind 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Node, CallExpression, Expression, JSXAttribute } from '@babel/types';
2
2
 
3
- type CliCommand = 'analyze' | 'generate' | 'apply';
3
+ type CliCommand = 'analyze' | 'generate' | 'apply' | 'init';
4
4
  interface CommandConfig {
5
5
  minOccurrences?: number;
6
6
  minSize?: number;
@@ -31,6 +31,8 @@ interface TailwindUnwindConfig extends CommandConfig {
31
31
  }
32
32
  interface ResolvedCommandOptions extends TailwindUnwindConfig {
33
33
  configPath?: string;
34
+ changed?: boolean | string;
35
+ force?: boolean;
34
36
  }
35
37
 
36
38
  /**
@@ -82,6 +84,12 @@ interface AnalysisStats {
82
84
  totalClassUsages: number;
83
85
  topCombinations: ClassCombination[];
84
86
  potentialReductionPercent: number;
87
+ /** Exact duplicates eligible for generate/apply (not limited by --top) */
88
+ extractablePatternCount: number;
89
+ /** analyze min-occurrences used for the frequent-pattern list */
90
+ analyzeMinOccurrences: number;
91
+ /** threshold used to mark patterns as extractable */
92
+ extractableMinOccurrences: number;
85
93
  }
86
94
  interface AnalysisReport {
87
95
  targetPath: string;
@@ -90,6 +98,8 @@ interface AnalysisReport {
90
98
  }
91
99
  interface AnalyzeOptions {
92
100
  minOccurrences?: number;
101
+ /** Threshold for marking patterns as extractable (defaults to generate min-occurrences) */
102
+ extractableMinOccurrences?: number;
93
103
  minSize?: number;
94
104
  maxSize?: number;
95
105
  top?: number;
@@ -105,13 +115,73 @@ interface AnalyzeOptions {
105
115
  prettier?: boolean;
106
116
  fromReport?: string;
107
117
  extractableOnly?: boolean;
118
+ changed?: boolean | string;
119
+ force?: boolean;
120
+ }
121
+
122
+ interface InitOptions extends AnalyzeOptions {
123
+ output?: string;
124
+ force?: boolean;
108
125
  }
126
+ interface InitResult {
127
+ configPath: string;
128
+ extractablePatterns: number;
129
+ }
130
+ /**
131
+ * Scan a project and write a starter tailwind-unwind.config.json.
132
+ */
133
+ declare function initCommand(targetPath: string, options?: InitOptions): Promise<InitResult>;
109
134
 
110
135
  /**
111
136
  * Run the full analyze pipeline: scan → parse → find patterns → report.
112
137
  */
113
138
  declare function analyzeCommand(targetPath: string, options?: AnalyzeOptions): Promise<AnalysisReport>;
114
139
 
140
+ interface PatternFinderOptions {
141
+ minOccurrences?: number;
142
+ minSize?: number;
143
+ maxSize?: number;
144
+ topLimit?: number;
145
+ dedupeSubsets?: boolean;
146
+ }
147
+ /**
148
+ * From every className occurrence, enumerate class subsets,
149
+ * count normalized combinations, and return the most frequent ones.
150
+ */
151
+ declare function findFrequentPatterns(occurrences: ClassNameOccurrence[], options?: PatternFinderOptions): ClassCombination[];
152
+ /**
153
+ * Find exact duplicate className sets (full class lists per element).
154
+ * Better suited for CSS generation than combinatorial subset search.
155
+ */
156
+ declare function findRepeatedClassSets(occurrences: ClassNameOccurrence[], options?: PatternFinderOptions): ClassCombination[];
157
+ /**
158
+ * Estimate how much repeated utility usage could be collapsed into components.
159
+ * Uses the best full combination: each redundant instance could replace N utilities with 1.
160
+ */
161
+ declare function calculatePotentialReduction(occurrences: ClassNameOccurrence[], topCombinations: ClassCombination[]): number;
162
+
163
+ interface ScanProjectOptions extends PatternFinderOptions {
164
+ targetPath: string;
165
+ include?: string[];
166
+ exclude?: string[];
167
+ /** Threshold used to mark combinations as extractable by generate/apply */
168
+ extractableMinOccurrences?: number;
169
+ /** Scan only git-changed files; string value is the git ref to diff against */
170
+ changed?: boolean | string;
171
+ }
172
+ interface ScanProjectResult {
173
+ resolvedPath: string;
174
+ files: string[];
175
+ occurrences: ClassNameOccurrence[];
176
+ warnings: string[];
177
+ report: AnalysisReport;
178
+ extractableCombinations: ClassCombination[];
179
+ }
180
+ /**
181
+ * Scan a directory, parse className usage, and build an analysis report.
182
+ */
183
+ declare function scanProject(options: ScanProjectOptions): Promise<ScanProjectResult>;
184
+
115
185
  interface GeneratedComponent {
116
186
  className: string;
117
187
  classes: string[];
@@ -139,29 +209,6 @@ declare function assignComponentClassNames(combinations: ClassCombination[], opt
139
209
  */
140
210
  declare function generateComponentCss(options: CssGeneratorOptions): CssGeneratorResult;
141
211
 
142
- interface PatternFinderOptions {
143
- minOccurrences?: number;
144
- minSize?: number;
145
- maxSize?: number;
146
- topLimit?: number;
147
- dedupeSubsets?: boolean;
148
- }
149
- /**
150
- * From every className occurrence, enumerate class subsets,
151
- * count normalized combinations, and return the most frequent ones.
152
- */
153
- declare function findFrequentPatterns(occurrences: ClassNameOccurrence[], options?: PatternFinderOptions): ClassCombination[];
154
- /**
155
- * Find exact duplicate className sets (full class lists per element).
156
- * Better suited for CSS generation than combinatorial subset search.
157
- */
158
- declare function findRepeatedClassSets(occurrences: ClassNameOccurrence[], options?: PatternFinderOptions): ClassCombination[];
159
- /**
160
- * Estimate how much repeated utility usage could be collapsed into components.
161
- * Uses the best full combination: each redundant instance could replace N utilities with 1.
162
- */
163
- declare function calculatePotentialReduction(occurrences: ClassNameOccurrence[], topCombinations: ClassCombination[]): number;
164
-
165
212
  interface BuildComponentsOptions extends PatternFinderOptions {
166
213
  sourcePath: string;
167
214
  prefix?: string;
@@ -202,6 +249,19 @@ interface ReplaceClassNamesResult {
202
249
  */
203
250
  declare function replaceClassNamesInSource(source: string, replacementMap: Map<string, string>, filePath: string): ReplaceClassNamesResult;
204
251
 
252
+ interface SavingsReport {
253
+ replacementCount: number;
254
+ utilityTokensBefore: number;
255
+ utilityTokensAfter: number;
256
+ tokensSaved: number;
257
+ percentReduction: number;
258
+ }
259
+ /**
260
+ * Estimate utility-token savings from applied replacements.
261
+ * Each replacement collapses N utilities into 1 component class.
262
+ */
263
+ declare function calculateSavings(replacements: ClassReplacement[]): SavingsReport;
264
+
205
265
  interface GenerateJsonReport {
206
266
  command: 'generate';
207
267
  outputPath: string;
@@ -219,6 +279,7 @@ interface ApplyJsonReport {
219
279
  components: GeneratedComponent[];
220
280
  replacements: ClassReplacement[];
221
281
  skipped: SkippedReplacement[];
282
+ savings: SavingsReport;
222
283
  }
223
284
  declare function printGenerateJsonReport(report: GenerateJsonReport): void;
224
285
  declare function printApplyJsonReport(report: ApplyJsonReport): void;
@@ -226,6 +287,9 @@ declare function printApplyJsonReport(report: ApplyJsonReport): void;
226
287
  interface ApplyOptions extends AnalyzeOptions {
227
288
  output: string;
228
289
  dryRun?: boolean;
290
+ verboseSkipped?: boolean;
291
+ /** Suppress console/json output (for internal callers like check) */
292
+ quiet?: boolean;
229
293
  }
230
294
  interface ApplyResult {
231
295
  filesModified: number;
@@ -236,30 +300,39 @@ interface ApplyResult {
236
300
  replacements: ApplyJsonReport['replacements'];
237
301
  skipped: ApplyJsonReport['skipped'];
238
302
  prettierFormatted: string[];
303
+ savings: SavingsReport;
239
304
  }
240
305
  /**
241
306
  * Generate component CSS and replace matching className strings in source files.
242
307
  */
243
308
  declare function applyCommand(targetPath: string, options: ApplyOptions): Promise<ApplyResult>;
244
309
 
245
- interface ScanProjectOptions extends PatternFinderOptions {
246
- targetPath: string;
247
- include?: string[];
248
- exclude?: string[];
249
- /** Threshold used to mark combinations as extractable by generate/apply */
250
- extractableMinOccurrences?: number;
310
+ interface CheckOptions extends AnalyzeOptions {
311
+ output: string;
312
+ /** Exit with code 1 when extractablePatternCount exceeds this value */
313
+ failOnExtractable?: number;
314
+ verboseSkipped?: boolean;
251
315
  }
252
- interface ScanProjectResult {
253
- resolvedPath: string;
254
- files: string[];
255
- occurrences: ClassNameOccurrence[];
256
- warnings: string[];
257
- report: AnalysisReport;
316
+ interface CheckResult {
317
+ passed: boolean;
318
+ extractablePatternCount: number;
319
+ report: Awaited<ReturnType<typeof scanProject>>['report'];
320
+ preview: ApplyResult | null;
258
321
  }
259
322
  /**
260
- * Scan a directory, parse className usage, and build an analysis report.
323
+ * Scan for extractable duplicates and preview what apply would change (dry-run).
261
324
  */
262
- declare function scanProject(options: ScanProjectOptions): Promise<ScanProjectResult>;
325
+ declare function checkCommand(targetPath: string, options: CheckOptions): Promise<CheckResult>;
326
+
327
+ /**
328
+ * List source files changed relative to a git ref (default: working tree vs HEAD).
329
+ */
330
+ declare function getChangedSourceFiles(rootPath: string, ref?: string): Promise<string[]>;
331
+ declare function isGitRepository(rootPath: string): Promise<boolean>;
332
+ /**
333
+ * Changed source files under `scopePath`, resolved to absolute paths.
334
+ */
335
+ declare function getChangedFilesInScope(scopePath: string, ref?: string): Promise<string[]>;
263
336
 
264
337
  interface GenerateOptions extends AnalyzeOptions {
265
338
  output: string;
@@ -392,9 +465,45 @@ declare function printConsoleReport(report: AnalysisReport, options?: ConsoleRep
392
465
  /** Serialize the analysis report as formatted JSON. */
393
466
  declare function printJsonReport(report: AnalysisReport): void;
394
467
 
468
+ interface CheckJsonReport {
469
+ command: 'check';
470
+ passed: boolean;
471
+ outputPath: string;
472
+ extractablePatternCount: number;
473
+ analyzeMinOccurrences: number;
474
+ extractableMinOccurrences: number;
475
+ report: AnalysisReport;
476
+ preview: {
477
+ componentsGenerated: number;
478
+ filesModified: number;
479
+ replacementsTotal: number;
480
+ skippedTotal: number;
481
+ savings: ApplyResult['savings'];
482
+ } | null;
483
+ }
484
+ declare function printCheckJsonReport(report: CheckJsonReport): void;
485
+ interface CheckConsoleOptions {
486
+ outputPath: string;
487
+ topLimit?: number;
488
+ preview?: ApplyResult | null;
489
+ verboseSkipped?: boolean;
490
+ passed: boolean;
491
+ }
492
+ declare function printCheckConsoleReport(analysisReport: AnalysisReport, options: CheckConsoleOptions): void;
493
+
494
+ interface SkippedSummary {
495
+ reason: string;
496
+ count: number;
497
+ items: SkippedReplacement[];
498
+ }
499
+ declare function groupSkippedByReason(skipped: SkippedReplacement[]): SkippedSummary[];
500
+ declare function printSkippedReport(skipped: SkippedReplacement[], options?: {
501
+ verbose?: boolean;
502
+ }): void;
503
+
395
504
  /** Directories excluded from recursive file scanning. */
396
505
  declare const IGNORED_DIRECTORIES: readonly ["node_modules", ".next", "dist", "build", ".git"];
397
506
  /** fast-glob ignore patterns — match directories at any depth. */
398
507
  declare const IGNORE_PATTERNS: string[];
399
508
 
400
- export { type AnalysisReport, type AnalysisStats, type AnalyzeOptions, type ApplyOptions, type ApplyResult, CLASS_MERGE_CALLEES, type ClassCombination, type ClassNameExtraction, type ClassNameOccurrence, type ClassReplacement, type CliCommand, type CombinationLocation, type CommandConfig, type CssGeneratorOptions, type CssGeneratorResult, type CustomNamesConfig, DEFAULT_CLASS_PREFIX, type GenerateOptions, type GenerateResult, type GeneratedComponent, IGNORED_DIRECTORIES, IGNORE_PATTERNS, type ParseResult, type ReplaceClassNamesResult, type SkippedReplacement, type TailwindUnwindConfig, type TailwindUnwindConfigFile, VARIANT_CALLEES, analyzeCommand, applyCommand, assignComponentClassNames, buildComponents, buildComponentsFromCombinations, calculatePotentialReduction, collectVariantRegistry, dedupeSubsetCombinations, extractClassesFromExpression, extractClassesFromVariantCall, extractFromJSXAttribute, findFrequentPatterns, findRepeatedClassSets, formatModifiedFiles, formatSource, generateCombinations, generateCommand, generateComponentCss, isClassAttribute, isStrictSubset, isVariantCallee, loadCommandOptions, loadExtractableCombinations, normalizeClassPrefix, normalizeClasses, normalizeNamesConfig, parseFile, parseSource, parseSourceToAst, printApplyJsonReport, printConsoleReport, printGenerateJsonReport, printJsonReport, replaceClassNamesInSource, scanProject, splitClassString, suggestClassName, validateConfigFile, walkSourceFiles, withClassPrefix };
509
+ export { type AnalysisReport, type AnalysisStats, type AnalyzeOptions, type ApplyOptions, type ApplyResult, CLASS_MERGE_CALLEES, type ClassCombination, type ClassNameExtraction, type ClassNameOccurrence, type ClassReplacement, type CliCommand, type CombinationLocation, type CommandConfig, type CssGeneratorOptions, type CssGeneratorResult, type CustomNamesConfig, DEFAULT_CLASS_PREFIX, type GenerateOptions, type GenerateResult, type GeneratedComponent, IGNORED_DIRECTORIES, IGNORE_PATTERNS, type ParseResult, type ReplaceClassNamesResult, type SkippedReplacement, type TailwindUnwindConfig, type TailwindUnwindConfigFile, VARIANT_CALLEES, analyzeCommand, applyCommand, assignComponentClassNames, buildComponents, buildComponentsFromCombinations, calculatePotentialReduction, calculateSavings, checkCommand, collectVariantRegistry, dedupeSubsetCombinations, extractClassesFromExpression, extractClassesFromVariantCall, extractFromJSXAttribute, findFrequentPatterns, findRepeatedClassSets, formatModifiedFiles, formatSource, generateCombinations, generateCommand, generateComponentCss, getChangedFilesInScope, getChangedSourceFiles, groupSkippedByReason, initCommand, isClassAttribute, isGitRepository, isStrictSubset, isVariantCallee, loadCommandOptions, loadExtractableCombinations, normalizeClassPrefix, normalizeClasses, normalizeNamesConfig, parseFile, parseSource, parseSourceToAst, printApplyJsonReport, printCheckConsoleReport, printCheckJsonReport, printConsoleReport, printGenerateJsonReport, printJsonReport, printSkippedReport, replaceClassNamesInSource, scanProject, splitClassString, suggestClassName, validateConfigFile, walkSourceFiles, withClassPrefix };
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@ import {
10
10
  buildComponents,
11
11
  buildComponentsFromCombinations,
12
12
  calculatePotentialReduction,
13
+ calculateSavings,
14
+ checkCommand,
13
15
  collectVariantRegistry,
14
16
  dedupeSubsetCombinations,
15
17
  extractClassesFromExpression,
@@ -22,7 +24,12 @@ import {
22
24
  generateCombinations,
23
25
  generateCommand,
24
26
  generateComponentCss,
27
+ getChangedFilesInScope,
28
+ getChangedSourceFiles,
29
+ groupSkippedByReason,
30
+ initCommand,
25
31
  isClassAttribute,
32
+ isGitRepository,
26
33
  isStrictSubset,
27
34
  isVariantCallee,
28
35
  loadCommandOptions,
@@ -34,9 +41,12 @@ import {
34
41
  parseSource,
35
42
  parseSourceToAst,
36
43
  printApplyJsonReport,
44
+ printCheckConsoleReport,
45
+ printCheckJsonReport,
37
46
  printConsoleReport,
38
47
  printGenerateJsonReport,
39
48
  printJsonReport,
49
+ printSkippedReport,
40
50
  replaceClassNamesInSource,
41
51
  scanProject,
42
52
  splitClassString,
@@ -44,7 +54,7 @@ import {
44
54
  validateConfigFile,
45
55
  walkSourceFiles,
46
56
  withClassPrefix
47
- } from "./chunk-4GXMK3NB.js";
57
+ } from "./chunk-RMTZCCPS.js";
48
58
  export {
49
59
  CLASS_MERGE_CALLEES,
50
60
  DEFAULT_CLASS_PREFIX,
@@ -57,6 +67,8 @@ export {
57
67
  buildComponents,
58
68
  buildComponentsFromCombinations,
59
69
  calculatePotentialReduction,
70
+ calculateSavings,
71
+ checkCommand,
60
72
  collectVariantRegistry,
61
73
  dedupeSubsetCombinations,
62
74
  extractClassesFromExpression,
@@ -69,7 +81,12 @@ export {
69
81
  generateCombinations,
70
82
  generateCommand,
71
83
  generateComponentCss,
84
+ getChangedFilesInScope,
85
+ getChangedSourceFiles,
86
+ groupSkippedByReason,
87
+ initCommand,
72
88
  isClassAttribute,
89
+ isGitRepository,
73
90
  isStrictSubset,
74
91
  isVariantCallee,
75
92
  loadCommandOptions,
@@ -81,9 +98,12 @@ export {
81
98
  parseSource,
82
99
  parseSourceToAst,
83
100
  printApplyJsonReport,
101
+ printCheckConsoleReport,
102
+ printCheckJsonReport,
84
103
  printConsoleReport,
85
104
  printGenerateJsonReport,
86
105
  printJsonReport,
106
+ printSkippedReport,
87
107
  replaceClassNamesInSource,
88
108
  scanProject,
89
109
  splitClassString,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-unwind",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Analyze Tailwind CSS class usage patterns in React/Next.js projects",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,7 +60,8 @@
60
60
  "chalk": "^5.4.1",
61
61
  "cli-table3": "^0.6.5",
62
62
  "commander": "^13.1.0",
63
- "fast-glob": "^3.3.3"
63
+ "fast-glob": "^3.3.3",
64
+ "jiti": "^2.4.2"
64
65
  },
65
66
  "devDependencies": {
66
67
  "@types/babel__generator": "^7.6.8",