tailwind-unwind 0.1.0 → 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config/validate.ts","../src/config/loadConfig.ts","../src/analyzer/suggestions.ts","../src/analyzer/dedupe.ts","../src/analyzer/combiner.ts","../src/analyzer/patternFinder.ts","../src/parser/classHelpers.ts","../src/parser/ast.ts","../src/parser/jsxParser.ts","../src/scanner/ignore.ts","../src/scanner/fileWalker.ts","../src/core/scanProject.ts","../src/reporters/consoleReporter.ts","../src/reporters/jsonReporter.ts","../src/commands/analyze.ts","../src/codemod/replaceClassNames.ts","../src/generator/classPrefix.ts","../src/generator/cssGenerator.ts","../src/core/buildComponents.ts","../src/commands/apply.ts","../src/commands/generate.ts"],"sourcesContent":["import type { CustomNamesConfig, TailwindUnwindConfigFile } from './types.js';\n\nconst CLASS_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_-]*$/;\nconst KNOWN_ROOT_KEYS = new Set([\n 'include',\n 'exclude',\n 'names',\n 'prefix',\n 'output',\n 'minOccurrences',\n 'minSize',\n 'maxSize',\n 'top',\n 'dedupeSubsets',\n 'dryRun',\n 'analyze',\n 'generate',\n 'apply',\n]);\n\nconst KNOWN_COMMAND_KEYS = new Set([\n 'minOccurrences',\n 'minSize',\n 'maxSize',\n 'top',\n 'prefix',\n 'output',\n 'dedupeSubsets',\n 'dryRun',\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction assertPositiveNumber(\n value: unknown,\n path: string,\n errors: string[],\n): void {\n if (value === undefined) {\n return;\n }\n\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 1) {\n errors.push(`${path} must be a positive number`);\n }\n}\n\nfunction assertBoolean(value: unknown, path: string, errors: string[]): void {\n if (value === undefined) {\n return;\n }\n\n if (typeof value !== 'boolean') {\n errors.push(`${path} must be a boolean`);\n }\n}\n\nfunction assertStringArray(\n value: unknown,\n path: string,\n errors: string[],\n): void {\n if (value === undefined) {\n return;\n }\n\n if (\n !Array.isArray(value) ||\n !value.every((item) => typeof item === 'string' && item.length > 0)\n ) {\n errors.push(`${path} must be an array of non-empty strings`);\n }\n}\n\nfunction validateCommandSection(\n value: unknown,\n section: string,\n errors: string[],\n): void {\n if (value === undefined) {\n return;\n }\n\n if (!isRecord(value)) {\n errors.push(`${section} must be an object`);\n return;\n }\n\n for (const key of Object.keys(value)) {\n if (!KNOWN_COMMAND_KEYS.has(key)) {\n errors.push(`Unknown key \"${key}\" in ${section}`);\n }\n }\n\n assertPositiveNumber(value.minOccurrences, `${section}.minOccurrences`, errors);\n assertPositiveNumber(value.minSize, `${section}.minSize`, errors);\n assertPositiveNumber(value.maxSize, `${section}.maxSize`, errors);\n assertPositiveNumber(value.top, `${section}.top`, errors);\n assertBoolean(value.dedupeSubsets, `${section}.dedupeSubsets`, errors);\n assertBoolean(value.dryRun, `${section}.dryRun`, errors);\n\n if (\n value.prefix !== undefined &&\n (typeof value.prefix !== 'string' || value.prefix.length === 0)\n ) {\n errors.push(`${section}.prefix must be a non-empty string`);\n }\n\n if (\n value.output !== undefined &&\n (typeof value.output !== 'string' || value.output.length === 0)\n ) {\n errors.push(`${section}.output must be a non-empty string`);\n }\n}\n\nfunction validateNames(value: unknown, errors: string[]): void {\n if (value === undefined) {\n return;\n }\n\n if (!isRecord(value)) {\n errors.push('names must be an object of \"utility string\": \"class-name\" pairs');\n return;\n }\n\n for (const [utilities, name] of Object.entries(value)) {\n if (typeof utilities !== 'string' || utilities.trim().length === 0) {\n errors.push('names keys must be non-empty utility strings');\n continue;\n }\n\n if (typeof name !== 'string' || !CLASS_NAME_PATTERN.test(name)) {\n errors.push(\n `names[\"${utilities}\"] must be a valid class name (letters, numbers, hyphens)`,\n );\n }\n }\n}\n\n/**\n * Validate a parsed config object and throw with all errors at once.\n */\nexport function validateConfigFile(raw: unknown, configPath: string): void {\n if (!isRecord(raw)) {\n throw new Error(`Invalid config in ${configPath}: root value must be an object`);\n }\n\n const source = isRecord(raw.default) ? raw.default : raw;\n const errors: string[] = [];\n\n for (const key of Object.keys(source)) {\n if (!KNOWN_ROOT_KEYS.has(key)) {\n errors.push(`Unknown config key \"${key}\"`);\n }\n }\n\n assertStringArray(source.include, 'include', errors);\n assertStringArray(source.exclude, 'exclude', errors);\n assertPositiveNumber(source.minOccurrences, 'minOccurrences', errors);\n assertPositiveNumber(source.minSize, 'minSize', errors);\n assertPositiveNumber(source.maxSize, 'maxSize', errors);\n assertPositiveNumber(source.top, 'top', errors);\n assertBoolean(source.dedupeSubsets, 'dedupeSubsets', errors);\n assertBoolean(source.dryRun, 'dryRun', errors);\n validateNames(source.names, errors);\n validateCommandSection(source.analyze, 'analyze', errors);\n validateCommandSection(source.generate, 'generate', errors);\n validateCommandSection(source.apply, 'apply', errors);\n\n if (\n source.prefix !== undefined &&\n (typeof source.prefix !== 'string' || source.prefix.length === 0)\n ) {\n errors.push('prefix must be a non-empty string');\n }\n\n if (\n source.output !== undefined &&\n (typeof source.output !== 'string' || source.output.length === 0)\n ) {\n errors.push('output must be a non-empty string');\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Invalid config in ${configPath}:\\n${errors.map((error) => ` - ${error}`).join('\\n')}`,\n );\n }\n}\n\nexport function normalizeNamesConfig(\n names: CustomNamesConfig | undefined,\n): Map<string, string> {\n const map = new Map<string, string>();\n\n if (!names) {\n return map;\n }\n\n for (const [utilities, baseName] of Object.entries(names)) {\n const tokens = utilities\n .trim()\n .split(/\\s+/)\n .filter((token) => token.length > 0);\n const key = [...tokens].sort().join(' ');\n map.set(key, baseName);\n }\n\n return map;\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type {\n CliCommand,\n CommandConfig,\n ResolvedCommandOptions,\n TailwindUnwindConfig,\n TailwindUnwindConfigFile,\n} from './types.js';\nimport { normalizeNamesConfig, validateConfigFile } from './validate.js';\n\nconst CONFIG_FILENAMES = [\n 'tailwind-unwind.config.js',\n 'tailwind-unwind.config.mjs',\n 'tailwind-unwind.config.cjs',\n 'tailwind-unwind.config.json',\n '.tailwind-unwindrc',\n '.tailwind-unwindrc.json',\n] as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction pickNumber(\n source: Record<string, unknown>,\n key: keyof CommandConfig,\n): number | undefined {\n const value = source[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction pickCommandConfig(source: Record<string, unknown>): CommandConfig {\n const config: CommandConfig = {};\n\n const minOccurrences = pickNumber(source, 'minOccurrences');\n if (minOccurrences !== undefined) config.minOccurrences = minOccurrences;\n\n const minSize = pickNumber(source, 'minSize');\n if (minSize !== undefined) config.minSize = minSize;\n\n const maxSize = pickNumber(source, 'maxSize');\n if (maxSize !== undefined) config.maxSize = maxSize;\n\n const top = pickNumber(source, 'top');\n if (top !== undefined) config.top = top;\n\n if (typeof source.prefix === 'string' && source.prefix.length > 0) {\n config.prefix = source.prefix;\n }\n\n if (typeof source.output === 'string' && source.output.length > 0) {\n config.output = source.output;\n }\n\n if (typeof source.dedupeSubsets === 'boolean') {\n config.dedupeSubsets = source.dedupeSubsets;\n }\n\n if (typeof source.dryRun === 'boolean') {\n config.dryRun = source.dryRun;\n }\n\n return config;\n}\n\nfunction pickNames(\n source: Record<string, unknown>,\n): TailwindUnwindConfig['names'] | undefined {\n if (!isRecord(source.names)) {\n return undefined;\n }\n\n const names: TailwindUnwindConfig['names'] = {};\n\n for (const [utilities, name] of Object.entries(source.names)) {\n if (typeof utilities === 'string' && typeof name === 'string') {\n names[utilities] = name;\n }\n }\n\n return Object.keys(names).length > 0 ? names : undefined;\n}\n\nfunction normalizeLoadedConfig(raw: unknown): TailwindUnwindConfigFile {\n if (!isRecord(raw)) {\n return {};\n }\n\n const source = isRecord(raw.default) ? raw.default : raw;\n const config: TailwindUnwindConfigFile = {\n ...pickCommandConfig(source),\n };\n\n const names = pickNames(source);\n if (names) {\n config.names = names;\n }\n\n if (Array.isArray(source.include)) {\n config.include = source.include.filter(\n (item): item is string => typeof item === 'string' && item.length > 0,\n );\n }\n\n if (Array.isArray(source.exclude)) {\n config.exclude = source.exclude.filter(\n (item): item is string => typeof item === 'string' && item.length > 0,\n );\n }\n\n if (isRecord(source.analyze)) {\n config.analyze = pickCommandConfig(source.analyze);\n }\n\n if (isRecord(source.generate)) {\n config.generate = pickCommandConfig(source.generate);\n }\n\n if (isRecord(source.apply)) {\n config.apply = pickCommandConfig(source.apply);\n }\n\n return config;\n}\n\nfunction mergeCommandConfig(\n command: CliCommand,\n fileConfig: TailwindUnwindConfigFile,\n): TailwindUnwindConfig {\n const { analyze, generate, apply, ...root } = fileConfig;\n const commandSection =\n command === 'analyze' ? analyze : command === 'generate' ? generate : apply;\n\n return {\n ...root,\n ...commandSection,\n };\n}\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function collectSearchRoots(\n cwd: string,\n targetPath?: string,\n): Promise<string[]> {\n const roots: string[] = [path.resolve(cwd)];\n\n if (!targetPath) {\n return roots;\n }\n\n let current = path.resolve(targetPath);\n\n try {\n const stat = await fs.stat(current);\n if (stat.isFile()) {\n current = path.dirname(current);\n }\n } catch {\n return roots;\n }\n\n while (true) {\n const resolved = path.resolve(current);\n if (!roots.includes(resolved)) {\n roots.push(resolved);\n }\n\n const parent = path.dirname(resolved);\n if (parent === resolved) {\n break;\n }\n current = parent;\n }\n\n return roots;\n}\n\nasync function resolveConfigFile(\n explicitPath: string | undefined,\n searchRoots: string[],\n): Promise<string | null> {\n if (explicitPath) {\n const resolved = path.resolve(explicitPath);\n if (!(await pathExists(resolved))) {\n throw new Error(`Config file not found: ${resolved}`);\n }\n return resolved;\n }\n\n for (const root of searchRoots) {\n for (const filename of CONFIG_FILENAMES) {\n const candidate = path.join(root, filename);\n if (await pathExists(candidate)) {\n return candidate;\n }\n }\n }\n\n return null;\n}\n\nasync function importConfigModule(configPath: string): Promise<unknown> {\n const moduleUrl = pathToFileURL(configPath).href;\n const imported = await import(moduleUrl);\n return imported;\n}\n\nasync function readJsonConfig(configPath: string): Promise<unknown> {\n const raw = await fs.readFile(configPath, 'utf-8');\n return JSON.parse(raw) as unknown;\n}\n\n/**\n * Load tailwind-unwind config for a command and merge CLI overrides on top.\n */\nexport async function loadCommandOptions(\n command: CliCommand,\n cliOptions: ResolvedCommandOptions,\n options: { cwd?: string; targetPath?: string } = {},\n): Promise<ResolvedCommandOptions> {\n const cwd = options.cwd ?? process.cwd();\n const searchRoots = await collectSearchRoots(cwd, options.targetPath);\n const configPath = await resolveConfigFile(cliOptions.configPath, searchRoots);\n\n if (!configPath) {\n return cliOptions;\n }\n\n const isJson =\n configPath.endsWith('.json') || configPath.endsWith('.tailwind-unwindrc');\n\n const loaded = isJson\n ? await readJsonConfig(configPath)\n : await importConfigModule(configPath);\n\n validateConfigFile(loaded, configPath);\n\n const fileConfig = mergeCommandConfig(command, normalizeLoadedConfig(loaded));\n const { configPath: _ignored, ...cliOverrides } = cliOptions;\n\n return {\n ...fileConfig,\n ...Object.fromEntries(\n Object.entries(cliOverrides).filter(([, value]) => value !== undefined),\n ),\n configPath,\n };\n}\n","const BREAKPOINT_PREFIX = /^(sm|md|lg|xl|2xl):/;\n\nfunction baseClass(cls: string): string {\n return cls.replace(BREAKPOINT_PREFIX, '');\n}\n\nfunction has(classes: string[], name: string): boolean {\n return classes.some((cls) => baseClass(cls) === name);\n}\n\nfunction hasPrefix(classes: string[], prefix: string): boolean {\n return classes.some((cls) => baseClass(cls).startsWith(prefix));\n}\n\nfunction hasAll(classes: string[], names: string[]): boolean {\n return names.every((name) => has(classes, name));\n}\n\nfunction hasAny(classes: string[], names: string[]): boolean {\n return names.some((name) => has(classes, name));\n}\n\nfunction hasAnyPrefix(classes: string[], prefixes: string[]): boolean {\n return prefixes.some((prefix) => hasPrefix(classes, prefix));\n}\n\nfunction hasPadding(classes: string[]): boolean {\n return hasAnyPrefix(classes, ['p-', 'px-', 'py-', 'pt-', 'pb-', 'pl-', 'pr-']);\n}\n\nfunction hasMargin(classes: string[]): boolean {\n return hasAnyPrefix(classes, ['m-', 'mx-', 'my-', 'mt-', 'mb-', 'ml-', 'mr-']);\n}\n\nfunction hasGap(classes: string[]): boolean {\n return hasPrefix(classes, 'gap-') || hasPrefix(classes, 'gap-x-') || hasPrefix(classes, 'gap-y-');\n}\n\nfunction hasShadow(classes: string[]): boolean {\n return hasPrefix(classes, 'shadow-');\n}\n\nfunction hasRing(classes: string[]): boolean {\n return hasPrefix(classes, 'ring-');\n}\n\nfunction isFullWidth(classes: string[]): boolean {\n return has(classes, 'w-full');\n}\n\nfunction gridColumnCount(classes: string[]): string | null {\n const colClass = classes.find((cls) => baseClass(cls).startsWith('grid-cols-'));\n if (!colClass) return null;\n return baseClass(colClass).replace('grid-cols-', '');\n}\n\nfunction iconSize(classes: string[]): boolean {\n return hasAny(classes, ['w-4', 'h-4', 'w-5', 'h-5', 'w-6', 'h-6', 'size-4', 'size-5', 'size-6']);\n}\n\ninterface NamingRule {\n name: string;\n match: (classes: string[]) => boolean;\n}\n\n/**\n * Ordered from most specific to general — first match wins.\n * Names describe UI intent, not utility lists.\n */\nconst SEMANTIC_RULES: NamingRule[] = [\n // ── Navigation & chrome ──────────────────────────────────────────\n {\n name: 'page-header',\n match: (c) =>\n hasAll(c, ['flex', 'items-center', 'justify-between']) &&\n (hasPadding(c) || hasPrefix(c, 'border-b')),\n },\n {\n name: 'toolbar',\n match: (c) => hasAll(c, ['flex', 'items-center', 'justify-between']),\n },\n {\n name: 'footer-bar',\n match: (c) =>\n has(c, 'flex') && hasPrefix(c, 'border-t') && hasPadding(c),\n },\n {\n name: 'action-bar',\n match: (c) =>\n hasAll(c, ['flex', 'items-center', 'justify-end']) && hasPadding(c),\n },\n {\n name: 'breadcrumb',\n match: (c) =>\n hasAll(c, ['flex', 'items-center']) &&\n hasGap(c) &&\n hasAny(c, ['text-sm', 'text-xs']),\n },\n {\n name: 'nav-item',\n match: (c) =>\n hasAll(c, ['flex', 'items-center']) && hasGap(c) && hasPadding(c),\n },\n {\n name: 'sidebar',\n match: (c) =>\n hasAll(c, ['flex', 'flex-col']) &&\n (has(c, 'h-full') || has(c, 'h-screen') || hasPrefix(c, 'w-')),\n },\n {\n name: 'tab-bar',\n match: (c) =>\n has(c, 'flex') && hasPrefix(c, 'border-b') && hasGap(c),\n },\n\n // ── Flex layout ──────────────────────────────────────────────────\n {\n name: 'centered-row',\n match: (c) => hasAll(c, ['flex', 'items-center', 'justify-center']),\n },\n {\n name: 'spread-row',\n match: (c) => has(c, 'flex') && has(c, 'justify-between'),\n },\n {\n name: 'aligned-row',\n match: (c) => hasAll(c, ['flex', 'items-center']),\n },\n {\n name: 'inline-actions',\n match: (c) => has(c, 'inline-flex') && has(c, 'items-center'),\n },\n {\n name: 'wrap-row',\n match: (c) => has(c, 'flex') && has(c, 'flex-wrap'),\n },\n {\n name: 'form-row',\n match: (c) => hasAll(c, ['flex', 'flex-col']) && hasGap(c),\n },\n {\n name: 'stack',\n match: (c) => hasAll(c, ['flex', 'flex-col']),\n },\n {\n name: 'row',\n match: (c) => has(c, 'flex'),\n },\n\n // ── Grid layout ──────────────────────────────────────────────────\n {\n name: 'photo-grid',\n match: (c) => has(c, 'grid') && hasPrefix(c, 'grid-cols-') && has(c, 'object-cover'),\n },\n {\n name: 'card-grid',\n match: (c) => has(c, 'grid') && hasGap(c) && hasPrefix(c, 'grid-cols-'),\n },\n {\n name: 'grid',\n match: (c) => has(c, 'grid'),\n },\n\n // ── Media & images ───────────────────────────────────────────────\n {\n name: 'media-cover',\n match: (c) => has(c, 'object-cover') && isFullWidth(c),\n },\n {\n name: 'media-contain',\n match: (c) => has(c, 'object-contain') && isFullWidth(c),\n },\n {\n name: 'aspect-video',\n match: (c) => has(c, 'aspect-video'),\n },\n {\n name: 'aspect-square',\n match: (c) => has(c, 'aspect-square'),\n },\n {\n name: 'avatar',\n match: (c) =>\n has(c, 'rounded-full') &&\n (hasPrefix(c, 'w-') || hasPrefix(c, 'h-') || hasPrefix(c, 'size-')) &&\n hasPrefix(c, 'object-'),\n },\n {\n name: 'thumbnail',\n match: (c) =>\n has(c, 'object-cover') &&\n hasAnyPrefix(c, ['w-16', 'w-12', 'w-20', 'h-16', 'h-12', 'h-20']),\n },\n {\n name: 'icon',\n match: (c) => iconSize(c) && !has(c, 'flex'),\n },\n {\n name: 'logo',\n match: (c) => hasAny(c, ['h-8', 'h-6', 'h-10']) && has(c, 'w-auto'),\n },\n {\n name: 'media-frame',\n match: (c) => isFullWidth(c) && has(c, 'h-auto'),\n },\n\n // ── Interactive (before surfaces — shares bg-/rounded-/px-) ─────\n {\n name: 'badge',\n match: (c) =>\n has(c, 'rounded-full') &&\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasAny(c, ['text-xs', 'text-sm']),\n },\n {\n name: 'chip',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) &&\n !has(c, 'rounded-full') &&\n hasPrefix(c, 'rounded-') &&\n hasAny(c, ['text-xs', 'text-sm']),\n },\n {\n name: 'tag',\n match: (c) =>\n hasAnyPrefix(c, ['px-2', 'px-3']) &&\n hasAnyPrefix(c, ['py-0', 'py-1']) &&\n hasPrefix(c, 'rounded-md'),\n },\n {\n name: 'icon-button',\n match: (c) =>\n hasAnyPrefix(c, ['p-1', 'p-1.5', 'p-2', 'p-3']) &&\n hasPrefix(c, 'rounded-') &&\n !hasAnyPrefix(c, ['px-4', 'px-5', 'px-6', 'px-8']),\n },\n {\n name: 'primary-button',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasPrefix(c, 'rounded-') &&\n hasAnyPrefix(c, ['bg-blue', 'bg-indigo', 'bg-primary', 'bg-violet']),\n },\n {\n name: 'danger-button',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasPrefix(c, 'rounded-') &&\n hasAnyPrefix(c, ['bg-red', 'bg-rose', 'bg-destructive']),\n },\n {\n name: 'ghost-button',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasPrefix(c, 'rounded-') &&\n hasAnyPrefix(c, ['hover:bg-', 'bg-transparent']),\n },\n {\n name: 'input',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasPrefix(c, 'border') &&\n hasPrefix(c, 'rounded-'),\n },\n {\n name: 'textarea',\n match: (c) =>\n hasPrefix(c, 'border') &&\n hasPrefix(c, 'rounded-') &&\n hasAny(c, ['resize-none', 'min-h-']),\n },\n {\n name: 'select',\n match: (c) =>\n hasPrefix(c, 'border') &&\n hasPrefix(c, 'rounded-') &&\n has(c, 'appearance-none'),\n },\n {\n name: 'checkbox-row',\n match: (c) =>\n hasAll(c, ['flex', 'items-center']) && hasGap(c) && hasAny(c, ['text-sm', 'text-base']),\n },\n {\n name: 'button',\n match: (c) =>\n hasAnyPrefix(c, ['px-', 'py-']) && hasPrefix(c, 'rounded-'),\n },\n\n // ── Surfaces & containers ────────────────────────────────────────\n {\n name: 'page-container',\n match: (c) => has(c, 'mx-auto') && hasPrefix(c, 'max-w-'),\n },\n {\n name: 'section',\n match: (c) => hasPadding(c) && hasMargin(c) && !has(c, 'flex') && !has(c, 'grid'),\n },\n {\n name: 'hero',\n match: (c) =>\n hasPadding(c) &&\n hasAny(c, ['text-center', 'justify-center']) &&\n hasAnyPrefix(c, ['text-3xl', 'text-4xl', 'text-5xl']),\n },\n {\n name: 'alert',\n match: (c) =>\n hasAnyPrefix(c, ['border-l-4', 'border-l-2']) &&\n hasPadding(c) &&\n hasPrefix(c, 'bg-'),\n },\n {\n name: 'callout',\n match: (c) =>\n hasPrefix(c, 'bg-') && hasPadding(c) && hasPrefix(c, 'border') && hasPrefix(c, 'rounded-'),\n },\n {\n name: 'panel',\n match: (c) =>\n hasPrefix(c, 'rounded-') && hasPadding(c) && hasPrefix(c, 'border'),\n },\n {\n name: 'card',\n match: (c) =>\n hasPrefix(c, 'rounded-') && hasPadding(c) && hasPrefix(c, 'bg-'),\n },\n {\n name: 'elevated-card',\n match: (c) =>\n hasShadow(c) && hasPrefix(c, 'rounded-') && hasPadding(c),\n },\n {\n name: 'surface',\n match: (c) => hasPrefix(c, 'bg-') && hasPadding(c),\n },\n\n // ── Overlays & positioning ───────────────────────────────────────\n {\n name: 'backdrop',\n match: (c) =>\n has(c, 'fixed') && has(c, 'inset-0') && hasAnyPrefix(c, ['bg-black', 'bg-white', 'bg-gray']),\n },\n {\n name: 'overlay',\n match: (c) => has(c, 'fixed') && has(c, 'inset-0'),\n },\n {\n name: 'modal-shell',\n match: (c) =>\n has(c, 'fixed') && hasAll(c, ['flex', 'items-center', 'justify-center']),\n },\n {\n name: 'drawer',\n match: (c) =>\n has(c, 'fixed') &&\n hasAny(c, ['inset-y-0', 'top-0', 'bottom-0']) &&\n hasPrefix(c, 'w-'),\n },\n {\n name: 'sticky-header',\n match: (c) =>\n has(c, 'sticky') && hasPrefix(c, 'top-') && hasPrefix(c, 'z-'),\n },\n {\n name: 'dropdown',\n match: (c) =>\n has(c, 'absolute') && hasPrefix(c, 'z-') && hasPrefix(c, 'rounded-') && hasShadow(c),\n },\n\n // ── Typography ───────────────────────────────────────────────────\n {\n name: 'prose',\n match: (c) => hasPrefix(c, 'prose'),\n },\n {\n name: 'heading',\n match: (c) =>\n hasAnyPrefix(c, ['text-xl', 'text-2xl', 'text-3xl', 'text-4xl', 'text-5xl']) &&\n hasPrefix(c, 'font-'),\n },\n {\n name: 'title',\n match: (c) =>\n hasAnyPrefix(c, ['text-lg', 'text-xl', 'text-2xl']) && hasPrefix(c, 'font-semibold'),\n },\n {\n name: 'subtitle',\n match: (c) =>\n hasAnyPrefix(c, ['text-base', 'text-lg']) && hasPrefix(c, 'text-gray'),\n },\n {\n name: 'label',\n match: (c) =>\n hasAny(c, ['text-xs', 'text-sm']) && hasAnyPrefix(c, ['font-medium', 'font-semibold']),\n },\n {\n name: 'caption',\n match: (c) =>\n hasAny(c, ['text-sm', 'text-xs']) &&\n hasPrefix(c, 'font-') &&\n !hasAnyPrefix(c, ['font-medium', 'font-semibold']),\n },\n {\n name: 'muted',\n match: (c) =>\n hasAnyPrefix(c, ['text-gray', 'text-slate', 'text-zinc', 'text-neutral']),\n },\n {\n name: 'error-text',\n match: (c) => hasAnyPrefix(c, ['text-red', 'text-rose', 'text-destructive']),\n },\n {\n name: 'link',\n match: (c) =>\n has(c, 'underline') ||\n hasAnyPrefix(c, ['text-blue', 'text-indigo', 'text-primary']),\n },\n {\n name: 'truncate',\n match: (c) => has(c, 'truncate') || has(c, 'line-clamp-1'),\n },\n\n // ── Lists & tables ───────────────────────────────────────────────\n {\n name: 'table-header',\n match: (c) =>\n hasAnyPrefix(c, ['text-xs', 'uppercase']) &&\n hasAnyPrefix(c, ['font-medium', 'font-semibold', 'tracking-']),\n },\n {\n name: 'table-row',\n match: (c) => hasPrefix(c, 'border-b') && hasAll(c, ['flex', 'items-center']),\n },\n {\n name: 'list-item',\n match: (c) =>\n hasAll(c, ['flex', 'items-center']) && hasGap(c) && hasPadding(c),\n },\n {\n name: 'menu-item',\n match: (c) =>\n hasAll(c, ['flex', 'items-center']) &&\n hasGap(c) &&\n hasAnyPrefix(c, ['px-', 'py-']) &&\n hasAnyPrefix(c, ['hover:bg-', 'rounded-']),\n },\n {\n name: 'divider',\n match: (c) =>\n hasPrefix(c, 'border-') && (isFullWidth(c) || hasMargin(c)),\n },\n\n // ── States & effects ─────────────────────────────────────────────\n {\n name: 'skeleton',\n match: (c) => has(c, 'animate-pulse') && hasPrefix(c, 'bg-'),\n },\n {\n name: 'loading',\n match: (c) => has(c, 'animate-spin') || has(c, 'animate-pulse'),\n },\n {\n name: 'disabled',\n match: (c) => has(c, 'opacity-50') || has(c, 'cursor-not-allowed'),\n },\n {\n name: 'focus-ring',\n match: (c) => hasRing(c) || hasAnyPrefix(c, ['focus:ring-', 'focus-visible:ring-']),\n },\n {\n name: 'hover-lift',\n match: (c) =>\n hasAnyPrefix(c, ['hover:shadow-', 'hover:-translate-y-']) && hasPrefix(c, 'transition'),\n },\n\n // ── Scroll & overflow ────────────────────────────────────────────\n {\n name: 'scroll-panel',\n match: (c) =>\n hasAny(c, ['overflow-y-auto', 'overflow-auto', 'overflow-x-auto', 'overflow-hidden']),\n },\n\n // ── Visual fallbacks ─────────────────────────────────────────────\n {\n name: 'shadow-box',\n match: (c) => hasShadow(c) && hasPrefix(c, 'rounded-'),\n },\n {\n name: 'bordered',\n match: (c) => hasPrefix(c, 'border') && hasPadding(c),\n },\n {\n name: 'rounded-box',\n match: (c) => hasPrefix(c, 'rounded-'),\n },\n {\n name: 'padded',\n match: (c) => hasPadding(c),\n },\n];\n\n/** Build a short compositional name from layout + traits. */\nfunction buildCompositionalName(classes: string[]): string {\n const parts: string[] = [];\n\n if (has(classes, 'flex')) {\n if (has(classes, 'flex-col')) parts.push('stack');\n else if (has(classes, 'flex-wrap')) parts.push('wrap');\n else if (has(classes, 'justify-between')) parts.push('between');\n else if (has(classes, 'justify-center')) parts.push('centered');\n else if (has(classes, 'items-center')) parts.push('aligned');\n else parts.push('row');\n } else if (has(classes, 'grid')) {\n const cols = gridColumnCount(classes);\n parts.push(cols ? `grid-${cols}` : 'grid');\n } else if (has(classes, 'inline-flex')) {\n parts.push('inline-row');\n } else if (has(classes, 'inline-block')) {\n parts.push('inline');\n } else if (has(classes, 'block')) {\n parts.push('block');\n }\n\n if (has(classes, 'fixed')) parts.push('fixed');\n else if (has(classes, 'absolute')) parts.push('absolute');\n else if (has(classes, 'sticky')) parts.push('sticky');\n else if (has(classes, 'relative')) parts.push('relative');\n\n if (has(classes, 'object-cover')) parts.push('cover');\n else if (has(classes, 'object-contain')) parts.push('contain');\n else if (has(classes, 'aspect-video')) parts.push('video');\n else if (has(classes, 'rounded-full')) parts.push('circle');\n else if (hasPrefix(classes, 'rounded-')) parts.push('rounded');\n\n if (hasShadow(classes)) parts.push('shadow');\n else if (hasRing(classes)) parts.push('ring');\n else if (hasPrefix(classes, 'border')) parts.push('bordered');\n\n if (hasPrefix(classes, 'bg-')) parts.push('surface');\n else if (hasPrefix(classes, 'text-')) parts.push('text');\n\n if (has(classes, 'truncate')) parts.push('truncate');\n if (has(classes, 'animate-pulse')) parts.push('pulse');\n if (has(classes, 'transition')) parts.push('transition');\n\n if (parts.length === 0 && hasPadding(classes)) parts.push('padded');\n if (parts.length === 0 && hasMargin(classes)) parts.push('spaced');\n\n const unique = [...new Set(parts)];\n return unique.slice(0, 2).join('-') || 'component';\n}\n\n/**\n * Suggest a short, human-readable component class name from a utility list.\n * Prefers semantic names (toolbar, media-cover) over utility concatenation.\n */\nexport function suggestClassName(classes: string[]): string {\n if (classes.length === 0) {\n return 'component';\n }\n\n for (const rule of SEMANTIC_RULES) {\n if (rule.match(classes)) {\n return rule.name;\n }\n }\n\n return buildCompositionalName(classes);\n}\n","import type { ClassCombination } from '../parser/types.js';\n\n/** True when every class in `smaller` is also present in `larger`. */\nexport function isStrictSubset(smaller: string[], larger: string[]): boolean {\n if (smaller.length >= larger.length) {\n return false;\n }\n\n const largerSet = new Set(larger);\n return smaller.every((cls) => largerSet.has(cls));\n}\n\n/**\n * Drop subset combinations when a strict superset is already in the list\n * (e.g. drop \"flex p-4\" when \"flex items-center p-4\" is present).\n */\nexport function dedupeSubsetCombinations(\n combinations: ClassCombination[],\n): ClassCombination[] {\n return combinations.filter((combo) => {\n return !combinations.some(\n (other) =>\n other.normalized !== combo.normalized &&\n isStrictSubset(combo.classes, other.classes),\n );\n });\n}\n","/**\n * Normalize a class list so order does not affect identity.\n * \"flex p-4\" and \"p-4 flex\" produce the same key.\n */\nexport function normalizeClasses(classes: string[]): string {\n return [...classes].sort().join(' ');\n}\n\n/** Split a className string into individual Tailwind tokens. */\nexport function splitClassString(classString: string): string[] {\n return classString\n .trim()\n .split(/\\s+/)\n .filter((token) => token.length > 0);\n}\n\n/**\n * Generate every combination of size `size` from `classes` (order preserved in output,\n * but callers should normalize before counting).\n */\nexport function generateCombinations(\n classes: string[],\n size: number,\n): string[][] {\n if (size < 1 || size > classes.length) {\n return [];\n }\n\n const results: string[][] = [];\n\n const backtrack = (start: number, current: string[]): void => {\n if (current.length === size) {\n results.push([...current]);\n return;\n }\n\n for (let i = start; i <= classes.length - (size - current.length); i += 1) {\n const item = classes[i];\n if (item !== undefined) {\n current.push(item);\n backtrack(i + 1, current);\n current.pop();\n }\n }\n };\n\n backtrack(0, []);\n return results;\n}\n","import type {\n ClassCombination,\n ClassNameOccurrence,\n CombinationLocation,\n} from '../parser/types.js';\nimport { suggestClassName } from './suggestions.js';\nimport { dedupeSubsetCombinations } from './dedupe.js';\nimport { generateCombinations, normalizeClasses } from './combiner.js';\n\nconst DEFAULT_MIN_COMBINATION_SIZE = 2;\nconst DEFAULT_MAX_COMBINATION_SIZE = 5;\nconst DEFAULT_MIN_OCCURRENCES = 5;\nconst DEFAULT_TOP_LIMIT = 10;\n\nexport interface PatternFinderOptions {\n minOccurrences?: number;\n minSize?: number;\n maxSize?: number;\n topLimit?: number;\n dedupeSubsets?: boolean;\n}\n\ninterface FrequencyEntry {\n classes: string[];\n count: number;\n locations: CombinationLocation[];\n}\n\nfunction locationKey(location: CombinationLocation): string {\n return `${location.filePath}:${location.line ?? 0}`;\n}\n\n/**\n * From every className occurrence, enumerate class subsets,\n * count normalized combinations, and return the most frequent ones.\n */\nexport function findFrequentPatterns(\n occurrences: ClassNameOccurrence[],\n options: PatternFinderOptions = {},\n): ClassCombination[] {\n const minOccurrences = options.minOccurrences ?? DEFAULT_MIN_OCCURRENCES;\n const minSize = options.minSize ?? DEFAULT_MIN_COMBINATION_SIZE;\n const maxSize = options.maxSize ?? DEFAULT_MAX_COMBINATION_SIZE;\n const topLimit = options.topLimit ?? DEFAULT_TOP_LIMIT;\n const dedupeSubsets = options.dedupeSubsets ?? true;\n\n const frequency = new Map<string, FrequencyEntry>();\n\n for (const occurrence of occurrences) {\n const uniqueInElement = [...new Set(occurrence.classes)];\n\n if (uniqueInElement.length < minSize) {\n continue;\n }\n\n const location: CombinationLocation = {\n filePath: occurrence.filePath,\n line: occurrence.line,\n };\n\n const cappedMaxSize = Math.min(maxSize, uniqueInElement.length);\n\n for (let size = minSize; size <= cappedMaxSize; size += 1) {\n const combos = generateCombinations(uniqueInElement, size);\n\n for (const combo of combos) {\n const normalized = normalizeClasses(combo);\n const existing = frequency.get(normalized);\n\n if (existing) {\n existing.count += 1;\n const key = locationKey(location);\n if (!existing.locations.some((loc) => locationKey(loc) === key)) {\n existing.locations.push(location);\n }\n } else {\n frequency.set(normalized, {\n classes: [...combo].sort(),\n count: 1,\n locations: [location],\n });\n }\n }\n }\n }\n\n let frequent = [...frequency.entries()]\n .filter(([, value]) => value.count > minOccurrences)\n .map(([normalized, value]) => ({\n normalized,\n classes: value.classes,\n occurrences: value.count,\n suggestion: `.${suggestClassName(value.classes)}`,\n locations: value.locations,\n }))\n .sort((a, b) => {\n if (b.occurrences !== a.occurrences) {\n return b.occurrences - a.occurrences;\n }\n return b.classes.length - a.classes.length;\n });\n\n if (dedupeSubsets) {\n frequent = dedupeSubsetCombinations(frequent);\n }\n\n return frequent.slice(0, topLimit);\n}\n\n/**\n * Find exact duplicate className sets (full class lists per element).\n * Better suited for CSS generation than combinatorial subset search.\n */\nexport function findRepeatedClassSets(\n occurrences: ClassNameOccurrence[],\n options: PatternFinderOptions = {},\n): ClassCombination[] {\n const minOccurrences = options.minOccurrences ?? 3;\n const minSize = options.minSize ?? 2;\n const maxSize = options.maxSize ?? DEFAULT_MAX_COMBINATION_SIZE;\n const topLimit = options.topLimit ?? DEFAULT_TOP_LIMIT;\n\n const frequency = new Map<string, FrequencyEntry>();\n\n for (const occurrence of occurrences) {\n const uniqueInElement = [...new Set(occurrence.classes)];\n\n if (uniqueInElement.length < minSize || uniqueInElement.length > maxSize) {\n continue;\n }\n\n const normalized = normalizeClasses(uniqueInElement);\n const location: CombinationLocation = {\n filePath: occurrence.filePath,\n line: occurrence.line,\n };\n\n const existing = frequency.get(normalized);\n\n if (existing) {\n existing.count += 1;\n const key = locationKey(location);\n if (!existing.locations.some((loc) => locationKey(loc) === key)) {\n existing.locations.push(location);\n }\n } else {\n frequency.set(normalized, {\n classes: [...uniqueInElement].sort(),\n count: 1,\n locations: [location],\n });\n }\n }\n\n return [...frequency.entries()]\n .filter(([, value]) => value.count >= minOccurrences)\n .map(([normalized, value]) => ({\n normalized,\n classes: value.classes,\n occurrences: value.count,\n suggestion: `.${suggestClassName(value.classes)}`,\n locations: value.locations,\n }))\n .sort((a, b) => {\n if (b.occurrences !== a.occurrences) {\n return b.occurrences - a.occurrences;\n }\n return b.classes.length - a.classes.length;\n })\n .slice(0, topLimit);\n}\n\n/**\n * Estimate how much repeated utility usage could be collapsed into components.\n * Uses the best full combination: each redundant instance could replace N utilities with 1.\n */\nexport function calculatePotentialReduction(\n occurrences: ClassNameOccurrence[],\n topCombinations: ClassCombination[],\n): number {\n const totalClassUsages = occurrences.reduce(\n (sum, occurrence) => sum + occurrence.classes.length,\n 0,\n );\n\n if (totalClassUsages === 0 || topCombinations.length === 0) {\n return 0;\n }\n\n const best = [...topCombinations].sort((a, b) => {\n if (b.classes.length !== a.classes.length) {\n return b.classes.length - a.classes.length;\n }\n return b.occurrences - a.occurrences;\n })[0];\n\n if (!best || best.occurrences <= 1 || best.classes.length < 2) {\n return 0;\n }\n\n const redundantInstances = best.occurrences - 1;\n const utilitiesSavedPerInstance = best.classes.length - 1;\n const savable = redundantInstances * utilitiesSavedPerInstance;\n\n return Math.min(100, Math.round((savable / totalClassUsages) * 100));\n}\n","import type {\n ArrayExpression,\n CallExpression,\n ConditionalExpression,\n Expression,\n LogicalExpression,\n TemplateLiteral,\n} from '@babel/types';\nimport { splitClassString } from '../analyzer/combiner.js';\n\n/** Utilities commonly used to merge Tailwind class strings. */\nexport const CLASS_MERGE_CALLEES = new Set([\n 'cn',\n 'clsx',\n 'classnames',\n 'classNames',\n 'twMerge',\n 'cx',\n]);\n\nexport interface ExtractedClasses {\n classes: string[];\n isDynamic: boolean;\n}\n\nfunction mergeExtractions(parts: ExtractedClasses[]): ExtractedClasses {\n const classes = [...new Set(parts.flatMap((part) => part.classes))];\n const isDynamic = parts.some((part) => part.isDynamic);\n\n return { classes, isDynamic };\n}\n\nfunction extractFromStringLiteral(value: string): ExtractedClasses {\n return {\n classes: splitClassString(value),\n isDynamic: false,\n };\n}\n\nfunction extractFromTemplateLiteral(node: TemplateLiteral): ExtractedClasses {\n const parts: string[] = [];\n\n for (const quasi of node.quasis) {\n if (quasi.value.cooked) {\n parts.push(quasi.value.cooked);\n }\n }\n\n const combined = parts.join(' ').trim();\n\n return {\n classes: combined ? splitClassString(combined) : [],\n isDynamic: node.expressions.length > 0,\n };\n}\n\nfunction isClassMergeCallee(expression: Expression): boolean {\n if (expression.type === 'Identifier') {\n return CLASS_MERGE_CALLEES.has(expression.name);\n }\n\n if (\n expression.type === 'MemberExpression' &&\n expression.property.type === 'Identifier'\n ) {\n return CLASS_MERGE_CALLEES.has(expression.property.name);\n }\n\n return false;\n}\n\nfunction extractFromCallArguments(\n args: CallExpression['arguments'],\n): ExtractedClasses {\n const parts: ExtractedClasses[] = [];\n\n for (const arg of args) {\n if (arg.type === 'SpreadElement' || arg.type === 'ArgumentPlaceholder') {\n parts.push({ classes: [], isDynamic: true });\n continue;\n }\n\n parts.push(extractClassesFromExpression(arg));\n }\n\n return mergeExtractions(parts);\n}\n\n/**\n * Recursively pull static Tailwind tokens from JSX className expressions.\n * Unknown/dynamic fragments set `isDynamic: true` but may still yield partial classes.\n */\nexport function extractClassesFromExpression(\n expression: Expression,\n): ExtractedClasses {\n switch (expression.type) {\n case 'StringLiteral':\n return extractFromStringLiteral(expression.value);\n\n case 'TemplateLiteral':\n return extractFromTemplateLiteral(expression);\n\n case 'CallExpression': {\n const { callee } = expression;\n if (callee.type !== 'V8IntrinsicIdentifier' && isClassMergeCallee(callee)) {\n return extractFromCallArguments(expression.arguments);\n }\n return { classes: [], isDynamic: true };\n }\n\n case 'ConditionalExpression': {\n const merged = mergeExtractions([\n extractClassesFromExpression(expression.consequent),\n extractClassesFromExpression(expression.alternate),\n ]);\n return { ...merged, isDynamic: true };\n }\n\n case 'LogicalExpression': {\n const merged = mergeExtractions([\n extractClassesFromExpression(expression.left),\n extractClassesFromExpression(expression.right),\n ]);\n return { ...merged, isDynamic: true };\n }\n\n case 'ArrayExpression':\n return extractFromArrayExpression(expression);\n\n case 'ObjectExpression':\n // clsx object form: { 'p-4': isActive } — keys are potential classes\n return extractFromObjectExpression(expression);\n\n default:\n return { classes: [], isDynamic: true };\n }\n}\n\nfunction extractFromArrayExpression(node: ArrayExpression): ExtractedClasses {\n const parts: ExtractedClasses[] = [];\n\n for (const element of node.elements) {\n if (element === null || element.type === 'SpreadElement') {\n parts.push({ classes: [], isDynamic: true });\n continue;\n }\n\n parts.push(extractClassesFromExpression(element));\n }\n\n return mergeExtractions(parts);\n}\n\nfunction extractFromObjectExpression(\n node: import('@babel/types').ObjectExpression,\n): ExtractedClasses {\n const classes: string[] = [];\n let isDynamic = false;\n\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') {\n isDynamic = true;\n continue;\n }\n\n if (prop.type !== 'ObjectProperty') {\n isDynamic = true;\n continue;\n }\n\n const key = prop.key;\n if (key.type === 'StringLiteral') {\n classes.push(...splitClassString(key.value));\n } else if (key.type === 'Identifier') {\n classes.push(...splitClassString(key.name));\n }\n\n if (prop.value.type !== 'BooleanLiteral' || prop.value.value !== true) {\n isDynamic = true;\n }\n }\n\n return {\n classes: [...new Set(classes)],\n isDynamic,\n };\n}\n","import { parse } from '@babel/parser';\nimport type { JSXAttribute, Node } from '@babel/types';\nimport type { ClassNameExtraction } from './types.js';\nimport { extractClassesFromExpression } from './classHelpers.js';\n\nexport const PARSER_PLUGINS = [\n 'jsx',\n 'typescript',\n 'decorators-legacy',\n 'classProperties',\n 'classPrivateProperties',\n 'classPrivateMethods',\n 'dynamicImport',\n 'importMeta',\n] as const;\n\nconst CLASS_ATTRIBUTES = new Set(['className', 'class']);\n\nfunction getAttributeName(attr: JSXAttribute): string | null {\n if (attr.name.type === 'JSXIdentifier') {\n return attr.name.name;\n }\n return null;\n}\n\nexport function isClassAttribute(attr: JSXAttribute): boolean {\n const name = getAttributeName(attr);\n return name !== null && CLASS_ATTRIBUTES.has(name);\n}\n\n/** Extract Tailwind classes from a className/class JSX attribute. */\nexport function extractFromJSXAttribute(\n attr: JSXAttribute,\n): ClassNameExtraction | null {\n if (!isClassAttribute(attr)) {\n return null;\n }\n\n const line = attr.loc?.start.line;\n const value = attr.value;\n\n if (value == null) {\n return { classes: [], isDynamic: true, line };\n }\n\n if (value.type === 'StringLiteral') {\n const result = extractClassesFromExpression(value);\n return { classes: result.classes, isDynamic: result.isDynamic, line };\n }\n\n if (value.type === 'JSXExpressionContainer') {\n const expr = value.expression;\n\n if (expr.type === 'JSXEmptyExpression') {\n return { classes: [], isDynamic: true, line };\n }\n\n const result = extractClassesFromExpression(expr);\n return { classes: result.classes, isDynamic: result.isDynamic, line };\n }\n\n return { classes: [], isDynamic: true, line };\n}\n\nexport function parseSourceToAst(source: string): Node {\n return parse(source, {\n sourceType: 'module',\n plugins: [...PARSER_PLUGINS],\n errorRecovery: true,\n allowReturnOutsideFunction: true,\n ranges: false,\n tokens: false,\n });\n}\n","import babelTraverse from '@babel/traverse';\nimport type { NodePath } from '@babel/traverse';\nimport type { JSXAttribute, JSXElement, Node } from '@babel/types';\nimport fs from 'node:fs/promises';\nimport type { ClassNameExtraction, ParseResult } from './types.js';\nimport {\n extractFromJSXAttribute,\n isClassAttribute,\n parseSourceToAst,\n} from './ast.js';\n\ntype TraverseFn = (\n ast: Node,\n visitors: { JSXElement?: (path: NodePath<JSXElement>) => void },\n) => void;\n\nfunction resolveTraverse(module: unknown): TraverseFn {\n if (typeof module === 'function') {\n return module as TraverseFn;\n }\n\n const withDefault = module as { default?: unknown };\n if (typeof withDefault.default === 'function') {\n return withDefault.default as TraverseFn;\n }\n\n throw new Error('Failed to load @babel/traverse');\n}\n\nconst traverse = resolveTraverse(babelTraverse);\n\nfunction isJSXElementWithClassAttribute(path: NodePath<JSXElement>): boolean {\n const opening = path.node.openingElement;\n return opening.attributes.some(\n (attr) => attr.type === 'JSXAttribute' && isClassAttribute(attr),\n );\n}\n\nfunction collectExtractionsFromAst(\n ast: Node,\n filePath: string,\n): { extractions: ClassNameExtraction[]; warnings: string[] } {\n const extractions: ClassNameExtraction[] = [];\n const warnings: string[] = [];\n\n traverse(ast, {\n JSXElement(path: NodePath<JSXElement>) {\n if (!isJSXElementWithClassAttribute(path)) {\n return;\n }\n\n const opening = path.node.openingElement;\n\n for (const attr of opening.attributes) {\n if (attr.type !== 'JSXAttribute') continue;\n\n const extraction = extractFromJSXAttribute(attr);\n if (!extraction) continue;\n\n if (extraction.isDynamic && extraction.classes.length === 0) {\n const lineInfo = extraction.line ? `:${extraction.line}` : '';\n warnings.push(\n `Dynamic className skipped in ${filePath}${lineInfo}`,\n );\n continue;\n }\n\n if (extraction.classes.length > 0) {\n extractions.push(extraction);\n }\n }\n },\n });\n\n return { extractions, warnings };\n}\n\n/**\n * Parse in-memory source (used by tests and parseFile).\n */\nexport function parseSource(\n source: string,\n filePath = 'unknown',\n): ParseResult {\n const extractions: ClassNameExtraction[] = [];\n const warnings: string[] = [];\n\n try {\n const ast = parseSourceToAst(source);\n const collected = collectExtractionsFromAst(ast, filePath);\n extractions.push(...collected.extractions);\n warnings.push(...collected.warnings);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n warnings.push(`Failed to parse ${filePath}: ${message}`);\n }\n\n return { filePath, extractions, warnings };\n}\n\n/**\n * Parse a single source file and collect all className/class values from JSX.\n */\nexport async function parseFile(filePath: string): Promise<ParseResult> {\n const source = await fs.readFile(filePath, 'utf-8');\n return parseSource(source, filePath);\n}\n","/** Directories excluded from recursive file scanning. */\nexport const IGNORED_DIRECTORIES = [\n 'node_modules',\n '.next',\n 'dist',\n 'build',\n '.git',\n] as const;\n\n/** fast-glob ignore patterns — match directories at any depth. */\nexport const IGNORE_PATTERNS: string[] = IGNORED_DIRECTORIES.map(\n (dir) => `**/${dir}/**`,\n);\n","import fg from 'fast-glob';\nimport path from 'node:path';\nimport { IGNORE_PATTERNS } from './ignore.js';\n\nconst SOURCE_EXTENSIONS = ['tsx', 'jsx', 'ts', 'js'] as const;\n\nexport interface WalkSourceFilesOptions {\n include?: string[];\n exclude?: string[];\n}\n\nfunction toAbsolutePattern(basePath: string, pattern: string): string {\n const normalized = pattern.replace(/\\\\/g, '/');\n if (path.isAbsolute(normalized)) {\n return normalized;\n }\n\n return path.join(basePath, normalized).replace(/\\\\/g, '/');\n}\n\nfunction buildIncludePatterns(\n basePath: string,\n include?: string[],\n): string[] {\n if (include && include.length > 0) {\n return include.map((pattern) => toAbsolutePattern(basePath, pattern));\n }\n\n return SOURCE_EXTENSIONS.map((ext) =>\n path.join(basePath, `**/*.${ext}`).replace(/\\\\/g, '/'),\n );\n}\n\nfunction buildIgnorePatterns(exclude?: string[]): string[] {\n const userExcludes = (exclude ?? []).map((pattern) => {\n const normalized = pattern.replace(/\\\\/g, '/');\n if (normalized.startsWith('**')) {\n return normalized;\n }\n return `**/${normalized}`;\n });\n\n return [...IGNORE_PATTERNS, ...userExcludes];\n}\n\n/**\n * Recursively collect source files under `targetPath`, skipping common build/cache dirs.\n */\nexport async function walkSourceFiles(\n targetPath: string,\n options: WalkSourceFilesOptions = {},\n): Promise<string[]> {\n const absolutePath = path.resolve(targetPath);\n const patterns = buildIncludePatterns(absolutePath, options.include);\n const ignore = buildIgnorePatterns(options.exclude);\n\n const files = await fg(patterns, {\n absolute: true,\n onlyFiles: true,\n unique: true,\n ignore,\n dot: false,\n });\n\n return files.sort();\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {\n calculatePotentialReduction,\n findFrequentPatterns,\n findRepeatedClassSets,\n type PatternFinderOptions,\n} from '../analyzer/patternFinder.js';\nimport { normalizeClasses } from '../analyzer/combiner.js';\nimport { parseFile } from '../parser/jsxParser.js';\nimport type {\n AnalysisReport,\n ClassNameOccurrence,\n} from '../parser/types.js';\nimport { walkSourceFiles } from '../scanner/fileWalker.js';\n\nasync function pathExists(targetPath: string): Promise<boolean> {\n try {\n await fs.access(targetPath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport interface ScanProjectOptions extends PatternFinderOptions {\n targetPath: string;\n include?: string[];\n exclude?: string[];\n /** Threshold used to mark combinations as extractable by generate/apply */\n extractableMinOccurrences?: number;\n}\n\nexport interface ScanProjectResult {\n resolvedPath: string;\n files: string[];\n occurrences: ClassNameOccurrence[];\n warnings: string[];\n report: AnalysisReport;\n}\n\n/**\n * Scan a directory, parse className usage, and build an analysis report.\n */\nexport async function scanProject(\n options: ScanProjectOptions,\n): Promise<ScanProjectResult> {\n const resolvedPath = path.resolve(options.targetPath);\n\n if (!(await pathExists(resolvedPath))) {\n throw new Error(`Path does not exist: ${resolvedPath}`);\n }\n\n const files = await walkSourceFiles(resolvedPath, {\n include: options.include,\n exclude: options.exclude,\n });\n\n if (files.length === 0) {\n throw new Error(\n `No source files (.tsx, .jsx, .ts, .js) found in: ${resolvedPath}`,\n );\n }\n\n const occurrences: ClassNameOccurrence[] = [];\n const warnings: string[] = [];\n\n for (const file of files) {\n const result = await parseFile(file);\n warnings.push(...result.warnings);\n\n for (const extraction of result.extractions) {\n if (extraction.classes.length > 0) {\n occurrences.push({\n classes: extraction.classes,\n filePath: file,\n line: extraction.line,\n });\n }\n }\n }\n\n const uniqueCombinationKeys = new Set(\n occurrences.map((occurrence) =>\n normalizeClasses([...new Set(occurrence.classes)]),\n ),\n );\n\n const frequentCombinations = findFrequentPatterns(occurrences, {\n minOccurrences: options.minOccurrences,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: options.topLimit,\n dedupeSubsets: options.dedupeSubsets,\n });\n\n const extractableSets = findRepeatedClassSets(occurrences, {\n minOccurrences: options.extractableMinOccurrences ?? 3,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: Number.POSITIVE_INFINITY,\n });\n const extractableKeys = new Set(\n extractableSets.map((combo) => combo.normalized),\n );\n\n const topCombinations = frequentCombinations.map((combo) => ({\n ...combo,\n extractable: extractableKeys.has(combo.normalized),\n }));\n\n const potentialReductionPercent = calculatePotentialReduction(\n occurrences,\n topCombinations,\n );\n\n const report: AnalysisReport = {\n targetPath: resolvedPath,\n stats: {\n filesScanned: files.length,\n componentsWithClassName: occurrences.length,\n uniqueCombinations: uniqueCombinationKeys.size,\n totalClassUsages: occurrences.reduce(\n (sum, occurrence) => sum + occurrence.classes.length,\n 0,\n ),\n topCombinations,\n potentialReductionPercent,\n },\n parseWarnings: warnings,\n };\n\n return {\n resolvedPath,\n files,\n occurrences,\n warnings,\n report,\n };\n}\n","import chalk from 'chalk';\nimport type { AnalysisReport } from '../parser/types.js';\nimport { normalizeClasses } from '../analyzer/combiner.js';\n\nfunction formatNumber(value: number): string {\n return value.toLocaleString('en-US');\n}\n\nfunction formatLocations(\n locations: AnalysisReport['stats']['topCombinations'][number]['locations'],\n): string {\n const preview = locations.slice(0, 3).map((loc) => {\n const line = loc.line ? `:${loc.line}` : '';\n return `${loc.filePath}${line}`;\n });\n\n const suffix =\n locations.length > 3 ? ` (+${locations.length - 3} more)` : '';\n\n return preview.join(', ') + suffix;\n}\n\ninterface ConsoleReportOptions {\n topLimit?: number;\n}\n\n/**\n * Render the analysis report to stdout with colors and the layout from the spec.\n */\nexport function printConsoleReport(\n report: AnalysisReport,\n options: ConsoleReportOptions = {},\n): void {\n const { stats } = report;\n const topLimit = options.topLimit ?? 10;\n\n console.log('');\n console.log(chalk.bold.cyan('📊 Tailwind Analysis Report'));\n console.log(chalk.cyan('━'.repeat(41)));\n console.log(`Files scanned: ${chalk.white(formatNumber(stats.filesScanned))}`);\n console.log(\n `Components with className: ${chalk.white(formatNumber(stats.componentsWithClassName))}`,\n );\n console.log(\n `Unique class combinations: ${chalk.white(formatNumber(stats.uniqueCombinations))}`,\n );\n console.log('');\n\n if (stats.topCombinations.length === 0) {\n console.log(\n chalk.yellow(\n 'No frequent class combinations found matching the current filters.',\n ),\n );\n } else {\n console.log(\n chalk.bold.green(`🏆 Top ${Math.min(topLimit, stats.topCombinations.length)} most frequent combinations:`),\n );\n console.log('');\n\n stats.topCombinations.forEach((combo, index) => {\n const displayClasses = normalizeClasses(combo.classes);\n console.log(\n chalk.white(`${index + 1}. `) +\n chalk.yellow(`\"${displayClasses}\"`),\n );\n console.log(\n chalk.gray(` Occurrences: `) + chalk.white(String(combo.occurrences)),\n );\n console.log(\n chalk.gray(` Suggestion: `) + chalk.green(combo.suggestion),\n );\n if (combo.extractable) {\n console.log(\n chalk.gray(` Extractable: `) +\n chalk.green('yes — use generate/apply'),\n );\n } else {\n console.log(\n chalk.gray(` Extractable: `) +\n chalk.yellow('subset only — analyze hint'),\n );\n }\n console.log(\n chalk.gray(` Found in: `) + chalk.dim(formatLocations(combo.locations)),\n );\n console.log('');\n });\n }\n\n console.log(\n chalk.magenta(\n `💡 Potential code reduction: ${stats.potentialReductionPercent}%`,\n ),\n );\n const extractableCount = stats.topCombinations.filter(\n (combo) => combo.extractable,\n ).length;\n if (extractableCount > 0) {\n console.log(\n chalk.magenta(\n `💡 ${extractableCount} pattern(s) ready for generate/apply`,\n ),\n );\n }\n console.log(\n chalk.magenta(\n '💡 Generate CSS: npx tailwind-unwind generate <path> --output styles.css',\n ),\n );\n console.log(\n chalk.magenta(\n '💡 Apply classes: npx tailwind-unwind apply <path> --output styles.css',\n ),\n );\n console.log('');\n}\n","import type { AnalysisReport } from '../parser/types.js';\n\n/** Serialize the analysis report as formatted JSON. */\nexport function printJsonReport(report: AnalysisReport): void {\n console.log(JSON.stringify(report, null, 2));\n}\n","import chalk from 'chalk';\nimport { scanProject } from '../core/scanProject.js';\nimport type { AnalysisReport, AnalyzeOptions } from '../parser/types.js';\nimport { printConsoleReport } from '../reporters/consoleReporter.js';\nimport { printJsonReport } from '../reporters/jsonReporter.js';\n\n/**\n * Run the full analyze pipeline: scan → parse → find patterns → report.\n */\nexport async function analyzeCommand(\n targetPath: string,\n options: AnalyzeOptions = {},\n): Promise<AnalysisReport> {\n let scanResult;\n\n try {\n scanResult = await scanProject({\n targetPath,\n minOccurrences: options.minOccurrences,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: options.top,\n dedupeSubsets: options.dedupeSubsets,\n include: options.include,\n exclude: options.exclude,\n extractableMinOccurrences: 3,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n\n if (options.format !== 'json') {\n for (const warning of scanResult.warnings) {\n console.warn(chalk.yellow(`⚠ ${warning}`));\n }\n }\n\n const report = scanResult.report;\n\n if (options.format === 'json') {\n printJsonReport(report);\n } else {\n printConsoleReport(report, { topLimit: options.top });\n }\n\n return report;\n}\n","import babelGenerate from '@babel/generator';\nimport babelTraverse from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { NodePath } from '@babel/traverse';\nimport type {\n CallExpression,\n Expression,\n JSXAttribute,\n JSXElement,\n Node,\n} from '@babel/types';\nimport { normalizeClasses } from '../analyzer/combiner.js';\nimport {\n CLASS_MERGE_CALLEES,\n extractClassesFromExpression,\n} from '../parser/classHelpers.js';\nimport {\n extractFromJSXAttribute,\n isClassAttribute,\n parseSourceToAst,\n} from '../parser/ast.js';\n\ntype TraverseFn = (\n ast: Node,\n visitors: { JSXElement?: (path: NodePath<JSXElement>) => void },\n) => void;\n\ntype GenerateFn = (\n ast: Node,\n options?: { retainLines?: boolean },\n source?: string,\n) => { code: string };\n\nfunction resolveTraverse(module: unknown): TraverseFn {\n if (typeof module === 'function') {\n return module as TraverseFn;\n }\n\n const withDefault = module as { default?: unknown };\n if (typeof withDefault.default === 'function') {\n return withDefault.default as TraverseFn;\n }\n\n throw new Error('Failed to load @babel/traverse');\n}\n\nfunction resolveGenerator(module: unknown): GenerateFn {\n if (typeof module === 'function') {\n return module as GenerateFn;\n }\n\n const withDefault = module as { default?: unknown };\n if (typeof withDefault.default === 'function') {\n return withDefault.default as GenerateFn;\n }\n\n throw new Error('Failed to load @babel/generator');\n}\n\nconst traverse = resolveTraverse(babelTraverse);\nconst generate = resolveGenerator(babelGenerate);\n\nexport interface ClassReplacement {\n filePath: string;\n line?: number;\n from: string;\n to: string;\n partial?: boolean;\n}\n\nexport interface SkippedReplacement {\n filePath: string;\n line?: number;\n reason: string;\n classes: string[];\n}\n\nexport interface ReplaceClassNamesResult {\n source: string;\n replacements: ClassReplacement[];\n skipped: SkippedReplacement[];\n changed: boolean;\n}\n\nfunction isClassMergeCallee(expression: Expression): boolean {\n if (expression.type === 'Identifier') {\n return CLASS_MERGE_CALLEES.has(expression.name);\n }\n\n if (\n expression.type === 'MemberExpression' &&\n expression.property.type === 'Identifier'\n ) {\n return CLASS_MERGE_CALLEES.has(expression.property.name);\n }\n\n return false;\n}\n\nfunction isClassMergeCall(expression: Expression): expression is CallExpression {\n return (\n expression.type === 'CallExpression' &&\n expression.callee.type !== 'V8IntrinsicIdentifier' &&\n isClassMergeCallee(expression.callee)\n );\n}\n\nfunction lookupReplacement(\n extraction: { classes: string[]; isDynamic: boolean },\n replacementMap: Map<string, string>,\n): string | null {\n if (extraction.isDynamic || extraction.classes.length === 0) {\n return null;\n }\n\n const key = normalizeClasses([...new Set(extraction.classes)]);\n return replacementMap.get(key) ?? null;\n}\n\nfunction setStringClassAttribute(attr: JSXAttribute, className: string): void {\n attr.value = t.stringLiteral(className);\n}\n\ninterface MergeCallReplacement {\n expression: Expression;\n from: string;\n to: string;\n partial: boolean;\n}\n\n/**\n * Replace static utility groups inside cn()/clsx() while preserving dynamic args.\n */\nfunction tryReplaceMergeCall(\n call: CallExpression,\n replacementMap: Map<string, string>,\n): MergeCallReplacement | null {\n const staticClasses: string[] = [];\n const dynamicArgs: CallExpression['arguments'] = [];\n\n for (const arg of call.arguments) {\n if (arg.type === 'SpreadElement' || arg.type === 'ArgumentPlaceholder') {\n dynamicArgs.push(arg);\n continue;\n }\n\n const extracted = extractClassesFromExpression(arg);\n if (extracted.isDynamic) {\n dynamicArgs.push(arg);\n continue;\n }\n\n staticClasses.push(...extracted.classes);\n }\n\n const combinedKey = normalizeClasses([...new Set(staticClasses)]);\n const combinedReplacement = replacementMap.get(combinedKey);\n\n if (combinedReplacement && staticClasses.length > 0) {\n if (dynamicArgs.length === 0) {\n return {\n expression: t.stringLiteral(combinedReplacement),\n from: combinedKey,\n to: combinedReplacement,\n partial: false,\n };\n }\n\n return {\n expression: t.callExpression(call.callee, [\n t.stringLiteral(combinedReplacement),\n ...dynamicArgs,\n ]),\n from: combinedKey,\n to: combinedReplacement,\n partial: true,\n };\n }\n\n let replaced = false;\n let replacedTo = '';\n let replacedFrom = '';\n const newArgs = [...call.arguments];\n\n for (let index = 0; index < call.arguments.length; index += 1) {\n const arg = call.arguments[index];\n if (\n arg === undefined ||\n arg.type === 'SpreadElement' ||\n arg.type === 'ArgumentPlaceholder'\n ) {\n continue;\n }\n\n const extracted = extractClassesFromExpression(arg);\n if (extracted.isDynamic || extracted.classes.length === 0) {\n continue;\n }\n\n const argKey = normalizeClasses(extracted.classes);\n const replacement = replacementMap.get(argKey);\n if (!replacement) {\n continue;\n }\n\n newArgs[index] = t.stringLiteral(replacement);\n if (!replaced) {\n replacedFrom = argKey;\n replacedTo = replacement;\n }\n replaced = true;\n }\n\n if (!replaced) {\n return null;\n }\n\n return {\n expression: t.callExpression(call.callee, newArgs),\n from: replacedFrom,\n to: replacedTo,\n partial: true,\n };\n}\n\nfunction tryReplaceClassAttribute(\n attr: JSXAttribute,\n replacementMap: Map<string, string>,\n): MergeCallReplacement | null {\n const value = attr.value;\n if (value?.type !== 'JSXExpressionContainer') {\n return null;\n }\n\n const expression = value.expression;\n if (expression.type === 'JSXEmptyExpression' || !isClassMergeCall(expression)) {\n return null;\n }\n\n return tryReplaceMergeCall(expression, replacementMap);\n}\n\n/**\n * Replace exact matching className/class values with generated component classes.\n * Supports partial replacement inside cn()/clsx() when dynamic args are present.\n */\nexport function replaceClassNamesInSource(\n source: string,\n replacementMap: Map<string, string>,\n filePath: string,\n): ReplaceClassNamesResult {\n const replacements: ClassReplacement[] = [];\n const skipped: SkippedReplacement[] = [];\n\n if (replacementMap.size === 0) {\n return { source, replacements, skipped, changed: false };\n }\n\n let ast: Node;\n\n try {\n ast = parseSourceToAst(source);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to parse ${filePath}: ${message}`);\n }\n\n traverse(ast, {\n JSXElement(path: NodePath<JSXElement>) {\n const opening = path.node.openingElement;\n\n for (const attr of opening.attributes) {\n if (attr.type !== 'JSXAttribute' || !isClassAttribute(attr)) {\n continue;\n }\n\n const extraction = extractFromJSXAttribute(attr);\n if (!extraction) continue;\n\n const mergeReplacement = tryReplaceClassAttribute(attr, replacementMap);\n if (mergeReplacement) {\n if (mergeReplacement.expression.type === 'StringLiteral') {\n setStringClassAttribute(attr, mergeReplacement.expression.value);\n } else {\n attr.value = t.jsxExpressionContainer(mergeReplacement.expression);\n }\n\n replacements.push({\n filePath,\n line: extraction.line,\n from: mergeReplacement.from,\n to: mergeReplacement.to,\n partial: mergeReplacement.partial,\n });\n continue;\n }\n\n const replacement = lookupReplacement(extraction, replacementMap);\n\n if (!replacement) {\n if (extraction.classes.length > 0) {\n const key = normalizeClasses([...new Set(extraction.classes)]);\n if (replacementMap.size > 0 && !replacementMap.has(key)) {\n if (extraction.isDynamic) {\n skipped.push({\n filePath,\n line: extraction.line,\n reason: 'dynamic className',\n classes: extraction.classes,\n });\n }\n }\n }\n continue;\n }\n\n const from = normalizeClasses([...new Set(extraction.classes)]);\n setStringClassAttribute(attr, replacement);\n\n replacements.push({\n filePath,\n line: extraction.line,\n from,\n to: replacement,\n });\n }\n },\n });\n\n if (replacements.length === 0) {\n return { source, replacements, skipped, changed: false };\n }\n\n const output = generate(ast, { retainLines: true }, source);\n return {\n source: output.code,\n replacements,\n skipped,\n changed: true,\n };\n}\n","/** Default namespace for generated component classes. */\nexport const DEFAULT_CLASS_PREFIX = 'twu-';\n\n/** Normalize prefix so generated classes are clearly namespaced. */\nexport function normalizeClassPrefix(prefix?: string): string {\n if (!prefix || prefix.trim().length === 0) {\n return DEFAULT_CLASS_PREFIX;\n }\n\n const trimmed = prefix.trim();\n return trimmed.endsWith('-') ? trimmed : `${trimmed}-`;\n}\n\n/** Attach a namespace prefix to a base component class name. */\nexport function withClassPrefix(baseName: string, prefix?: string): string {\n const normalizedPrefix = normalizeClassPrefix(prefix);\n\n if (baseName.startsWith(normalizedPrefix)) {\n return baseName;\n }\n\n return `${normalizedPrefix}${baseName}`;\n}\n","import { normalizeClasses } from '../analyzer/combiner.js';\nimport { suggestClassName } from '../analyzer/suggestions.js';\nimport { normalizeNamesConfig } from '../config/validate.js';\nimport type { CustomNamesConfig } from '../config/types.js';\nimport type { ClassCombination } from '../parser/types.js';\nimport { normalizeClassPrefix, withClassPrefix } from './classPrefix.js';\n\nexport interface GeneratedComponent {\n className: string;\n classes: string[];\n occurrences: number;\n}\n\nexport interface CssGeneratorOptions {\n sourcePath: string;\n combinations: ClassCombination[];\n prefix?: string;\n names?: CustomNamesConfig;\n}\n\nexport interface CssGeneratorResult {\n css: string;\n components: GeneratedComponent[];\n}\n\nexport interface AssignClassNamesOptions {\n prefix?: string;\n names?: CustomNamesConfig;\n}\n\nfunction resolveBaseClassName(\n classes: string[],\n customNames: Map<string, string>,\n): string {\n const key = normalizeClasses(classes);\n return customNames.get(key) ?? suggestClassName(classes);\n}\n\n/** Assign unique, prefixed component class names. */\nexport function assignComponentClassNames(\n combinations: ClassCombination[],\n options: AssignClassNamesOptions = {},\n): GeneratedComponent[] {\n const used = new Set<string>();\n const customNames = normalizeNamesConfig(options.names);\n\n return combinations.map((combo) => {\n const base = resolveBaseClassName(combo.classes, customNames);\n let className = withClassPrefix(base, options.prefix);\n let suffix = 2;\n\n while (used.has(className)) {\n className = withClassPrefix(`${base}-${suffix}`, options.prefix);\n suffix += 1;\n }\n\n used.add(className);\n\n return {\n className,\n classes: combo.classes,\n occurrences: combo.occurrences,\n };\n });\n}\n\n/**\n * Build a Tailwind CSS file with @layer components and @apply rules\n * for the most frequent class combinations.\n */\nexport function generateComponentCss(\n options: CssGeneratorOptions,\n): CssGeneratorResult {\n const components = assignComponentClassNames(options.combinations, {\n prefix: options.prefix,\n names: options.names,\n });\n const timestamp = new Date().toISOString();\n const classPrefix = normalizeClassPrefix(options.prefix);\n\n const header = [\n '/**',\n ' * Generated by tailwind-unwind',\n ` * Source: ${options.sourcePath}`,\n ` * Generated at: ${timestamp}`,\n ` * Class prefix: ${classPrefix}`,\n ' */',\n '',\n ].join('\\n');\n\n if (components.length === 0) {\n return {\n css: `${header}\\n/* No frequent class combinations found. Try lowering --min-occurrences. */\\n`,\n components: [],\n };\n }\n\n const rules = components\n .map((component) => {\n const applyClasses = component.classes.join(' ');\n return ` .${component.className} {\\n @apply ${applyClasses};\\n }`;\n })\n .join('\\n\\n');\n\n const css = `${header}\\n@layer components {\\n${rules}\\n}\\n`;\n\n return { css, components };\n}\n","import { findRepeatedClassSets } from '../analyzer/patternFinder.js';\nimport {\n assignComponentClassNames,\n generateComponentCss,\n type GeneratedComponent,\n} from '../generator/cssGenerator.js';\nimport type { ClassNameOccurrence } from '../parser/types.js';\nimport type { PatternFinderOptions } from '../analyzer/patternFinder.js';\n\nexport interface BuildComponentsOptions extends PatternFinderOptions {\n sourcePath: string;\n prefix?: string;\n names?: Record<string, string>;\n}\n\nexport interface BuildComponentsResult {\n components: GeneratedComponent[];\n css: string;\n replacementMap: Map<string, string>;\n}\n\n/** Build component classes, CSS, and a normalized-class → name lookup map. */\nexport function buildComponents(\n occurrences: ClassNameOccurrence[],\n options: BuildComponentsOptions,\n): BuildComponentsResult {\n const combinations = findRepeatedClassSets(occurrences, {\n minOccurrences: options.minOccurrences,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: options.topLimit,\n });\n\n const { css, components } = generateComponentCss({\n sourcePath: options.sourcePath,\n combinations,\n prefix: options.prefix,\n names: options.names,\n });\n\n const replacementMap = new Map<string, string>();\n\n for (const component of components) {\n const key = [...component.classes].sort().join(' ');\n replacementMap.set(key, component.className);\n }\n\n return { components, css, replacementMap };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport { replaceClassNamesInSource } from '../codemod/replaceClassNames.js';\nimport { buildComponents } from '../core/buildComponents.js';\nimport { scanProject } from '../core/scanProject.js';\nimport type { AnalyzeOptions } from '../parser/types.js';\n\nexport interface ApplyOptions extends AnalyzeOptions {\n output: string;\n dryRun?: boolean;\n}\n\nexport interface ApplyResult {\n filesModified: number;\n replacementsTotal: number;\n outputPath: string;\n componentsGenerated: number;\n}\n\n/**\n * Generate component CSS and replace matching className strings in source files.\n */\nexport async function applyCommand(\n targetPath: string,\n options: ApplyOptions,\n): Promise<ApplyResult> {\n let scanResult;\n\n try {\n scanResult = await scanProject({\n targetPath,\n include: options.include,\n exclude: options.exclude,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n\n for (const warning of scanResult.warnings) {\n console.warn(chalk.yellow(`⚠ ${warning}`));\n }\n\n const { components, css, replacementMap } = buildComponents(\n scanResult.occurrences,\n {\n sourcePath: scanResult.resolvedPath,\n minOccurrences: options.minOccurrences ?? 3,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: options.top,\n prefix: options.prefix,\n names: options.names,\n },\n );\n\n if (components.length === 0) {\n console.error(\n chalk.yellow(\n 'No repeated className sets found. Try lowering --min-occurrences.',\n ),\n );\n process.exit(1);\n }\n\n const outputPath = path.resolve(options.output);\n let filesModified = 0;\n let replacementsTotal = 0;\n const allReplacements: Array<{\n filePath: string;\n line?: number;\n from: string;\n to: string;\n partial?: boolean;\n }> = [];\n const allSkipped: Array<{\n filePath: string;\n line?: number;\n reason: string;\n classes: string[];\n }> = [];\n\n for (const file of scanResult.files) {\n const original = await fs.readFile(file, 'utf-8');\n const result = replaceClassNamesInSource(\n original,\n replacementMap,\n file,\n );\n\n replacementsTotal += result.replacements.length;\n allReplacements.push(...result.replacements);\n allSkipped.push(...result.skipped);\n\n if (result.changed) {\n filesModified += 1;\n if (!options.dryRun) {\n await fs.writeFile(file, result.source, 'utf-8');\n }\n }\n }\n\n if (!options.dryRun) {\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, css, 'utf-8');\n }\n\n console.log('');\n if (options.dryRun) {\n console.log(chalk.bold.yellow('🔍 Dry run — no files were modified'));\n } else {\n console.log(chalk.bold.green('✅ Classes applied successfully'));\n }\n\n console.log(chalk.gray(` CSS output: `) + chalk.white(outputPath));\n console.log(\n chalk.gray(` Component classes: `) + chalk.white(String(components.length)),\n );\n console.log(\n chalk.gray(` Files modified: `) + chalk.white(String(filesModified)),\n );\n console.log(\n chalk.gray(` Replacements: `) + chalk.white(String(replacementsTotal)),\n );\n\n if (allReplacements.length > 0) {\n console.log('');\n console.log(chalk.bold('Replacements:'));\n for (const item of allReplacements) {\n const line = item.line ? `:${item.line}` : '';\n const partialTag = item.partial ? chalk.dim(' (partial)') : '';\n console.log(\n chalk.gray(` ${item.filePath}${line}`) +\n chalk.white(` \"${item.from}\" `) +\n chalk.cyan('→') +\n chalk.green(` \"${item.to}\"`) +\n partialTag,\n );\n }\n }\n\n if (allSkipped.length > 0) {\n console.log('');\n console.log(\n chalk.bold.yellow(`Skipped (${allSkipped.length}):`),\n );\n for (const item of allSkipped) {\n const line = item.line ? `:${item.line}` : '';\n const classes = item.classes.join(' ');\n console.log(\n chalk.gray(` ${item.filePath}${line}`) +\n chalk.yellow(` [${item.reason}]`) +\n chalk.dim(` \"${classes}\"`),\n );\n }\n }\n\n console.log('');\n if (!options.dryRun) {\n console.log(\n chalk.cyan(\n `Import ${path.basename(outputPath)} in your global CSS if you haven't already.`,\n ),\n );\n console.log('');\n }\n\n return {\n filesModified,\n replacementsTotal,\n outputPath,\n componentsGenerated: components.length,\n };\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport chalk from 'chalk';\nimport { buildComponents } from '../core/buildComponents.js';\nimport { scanProject } from '../core/scanProject.js';\nimport type { AnalyzeOptions } from '../parser/types.js';\n\nexport interface GenerateOptions extends AnalyzeOptions {\n output: string;\n}\n\nexport interface GenerateResult {\n outputPath: string;\n componentsGenerated: number;\n report: Awaited<ReturnType<typeof scanProject>>['report'];\n}\n\n/**\n * Analyze a project and write @layer components CSS to the output file.\n */\nexport async function generateCommand(\n targetPath: string,\n options: GenerateOptions,\n): Promise<GenerateResult> {\n let scanResult;\n\n try {\n scanResult = await scanProject({\n targetPath,\n include: options.include,\n exclude: options.exclude,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(chalk.red(`Error: ${message}`));\n process.exit(1);\n }\n\n for (const warning of scanResult.warnings) {\n console.warn(chalk.yellow(`⚠ ${warning}`));\n }\n\n const { css, components } = buildComponents(scanResult.occurrences, {\n sourcePath: scanResult.resolvedPath,\n minOccurrences: options.minOccurrences ?? 3,\n minSize: options.minSize,\n maxSize: options.maxSize,\n topLimit: options.top,\n prefix: options.prefix,\n names: options.names,\n });\n\n const outputPath = path.resolve(options.output);\n await fs.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.writeFile(outputPath, css, 'utf-8');\n\n console.log('');\n console.log(chalk.bold.green('✅ CSS generated successfully'));\n console.log(chalk.gray(` Output: `) + chalk.white(outputPath));\n console.log(\n chalk.gray(` Components: `) + chalk.white(String(components.length)),\n );\n\n if (components.length > 0) {\n console.log('');\n console.log(chalk.bold('Generated classes:'));\n for (const component of components) {\n console.log(\n chalk.green(` .${component.className}`) +\n chalk.gray(` — ${component.occurrences} occurrences, `) +\n chalk.dim(component.classes.join(' ')),\n );\n }\n console.log('');\n console.log(\n chalk.cyan(\n 'Run apply to replace className strings: npx tailwind-unwind apply <path> --output styles.css',\n ),\n );\n } else {\n console.log(\n chalk.yellow(\n '\\nNo repeated className sets matched the filters. Try lowering --min-occurrences.',\n ),\n );\n }\n\n console.log('');\n\n return {\n outputPath,\n componentsGenerated: components.length,\n report: scanResult.report,\n };\n}\n"],"mappings":"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","names":["path","isRecord","generate","fs","path","fs","path","path","fs","path","pathExists","fs","path","chalk","chalk","babelTraverse","resolveTraverse","traverse","babelTraverse","isClassMergeCallee","path","fs","path","chalk","chalk","path","fs","fs","path","chalk","chalk","path","fs"]}
package/dist/cli/index.js CHANGED
@@ -2,23 +2,136 @@
2
2
  import {
3
3
  analyzeCommand,
4
4
  applyCommand,
5
- generateCommand
6
- } from "../chunk-N7HD4T2I.js";
5
+ generateCommand,
6
+ loadCommandOptions
7
+ } from "../chunk-FASYIEVZ.js";
7
8
 
8
9
  // src/cli/index.ts
9
10
  import { Command } from "commander";
11
+ import chalk from "chalk";
12
+
13
+ // src/cli/defaults.ts
14
+ var ANALYZE_DEFAULTS = {
15
+ minOccurrences: 5,
16
+ minSize: 2,
17
+ maxSize: 5,
18
+ top: 10
19
+ };
20
+ var GENERATE_DEFAULTS = {
21
+ minOccurrences: 3,
22
+ minSize: 2,
23
+ maxSize: 5,
24
+ top: 10,
25
+ prefix: "twu-"
26
+ };
27
+
28
+ // src/cli/parseOptions.ts
29
+ function splitPatterns(value) {
30
+ if (typeof value !== "string" || value.trim().length === 0) {
31
+ return void 0;
32
+ }
33
+ return value.split(",").map((part) => part.trim()).filter((part) => part.length > 0);
34
+ }
35
+ function optionalNumber(value) {
36
+ if (value === void 0 || value === null || value === "") {
37
+ return void 0;
38
+ }
39
+ const parsed = Number(value);
40
+ return Number.isFinite(parsed) ? parsed : void 0;
41
+ }
42
+ function cliNumber(value, fallback) {
43
+ const parsed = optionalNumber(value);
44
+ return parsed ?? fallback;
45
+ }
46
+ async function resolveCommandOptions(command, opts, targetPath) {
47
+ const resolved = await loadCommandOptions(
48
+ command,
49
+ {
50
+ configPath: opts.config,
51
+ minOccurrences: optionalNumber(opts.minOccurrences),
52
+ minSize: optionalNumber(opts.minSize),
53
+ maxSize: optionalNumber(opts.maxSize),
54
+ top: optionalNumber(opts.top),
55
+ prefix: opts.prefix,
56
+ dedupeSubsets: opts.dedupeSubsets,
57
+ include: splitPatterns(opts.include),
58
+ exclude: splitPatterns(opts.exclude),
59
+ output: opts.output,
60
+ dryRun: opts.dryRun
61
+ },
62
+ { targetPath }
63
+ );
64
+ return {
65
+ minOccurrences: resolved.minOccurrences,
66
+ minSize: resolved.minSize,
67
+ maxSize: resolved.maxSize,
68
+ top: resolved.top,
69
+ prefix: resolved.prefix,
70
+ dedupeSubsets: resolved.dedupeSubsets,
71
+ include: resolved.include,
72
+ exclude: resolved.exclude,
73
+ configPath: resolved.configPath,
74
+ output: resolved.output,
75
+ names: resolved.names,
76
+ format: opts.format === "json" ? "json" : "console",
77
+ dryRun: opts.dryRun ?? resolved.dryRun
78
+ };
79
+ }
80
+ function withNumericDefaults(resolved, opts, defaults) {
81
+ return {
82
+ ...resolved,
83
+ minOccurrences: resolved.minOccurrences ?? cliNumber(opts.minOccurrences, defaults.minOccurrences),
84
+ minSize: resolved.minSize ?? cliNumber(opts.minSize, defaults.minSize),
85
+ maxSize: resolved.maxSize ?? cliNumber(opts.maxSize, defaults.maxSize),
86
+ top: resolved.top ?? cliNumber(opts.top, defaults.top),
87
+ prefix: resolved.prefix ?? opts.prefix ?? defaults.prefix
88
+ };
89
+ }
90
+
91
+ // src/cli/version.ts
92
+ import { readFileSync } from "fs";
93
+ import path from "path";
94
+ import { fileURLToPath } from "url";
95
+ function readPackageVersion() {
96
+ const currentDir = path.dirname(fileURLToPath(import.meta.url));
97
+ const packageJsonPath = path.join(currentDir, "../../package.json");
98
+ const raw = readFileSync(packageJsonPath, "utf-8");
99
+ const pkg = JSON.parse(raw);
100
+ return pkg.version ?? "0.0.0";
101
+ }
102
+ var CLI_VERSION = readPackageVersion();
103
+
104
+ // src/cli/index.ts
10
105
  var program = new Command();
11
- program.name("tailwind-unwind").description("Analyze Tailwind CSS class usage in React/Next.js projects").version("0.1.0");
12
- program.command("analyze").description("Scan a directory and report frequent Tailwind class combinations").argument("<path>", "Directory to analyze").option("--min-occurrences <n>", "Minimum occurrences threshold", "5").option("--min-size <n>", "Minimum classes per combination", "2").option("--max-size <n>", "Maximum classes per combination", "5").option("--top <n>", "Number of top combinations to show", "10").option("--format <type>", "Output format: console or json", "console").option("--no-dedupe-subsets", "Include subset combinations in results").action(async (targetPath, opts) => {
106
+ function addSharedOptions(command) {
107
+ return command.option("--config <file>", "Path to tailwind-unwind config file").option(
108
+ "--include <patterns>",
109
+ 'Comma-separated glob include patterns (e.g. "src/**/*.tsx")'
110
+ ).option(
111
+ "--exclude <patterns>",
112
+ 'Comma-separated glob exclude patterns (e.g. "**/*.test.tsx")'
113
+ );
114
+ }
115
+ program.name("tailwind-unwind").description("Analyze Tailwind CSS class usage in React/Next.js projects").version(CLI_VERSION);
116
+ addSharedOptions(
117
+ program.command("analyze").description("Scan a directory and report frequent Tailwind class combinations").argument("<path>", "Directory to analyze").option("--min-occurrences <n>", "Minimum occurrences threshold").option("--min-size <n>", "Minimum classes per combination").option("--max-size <n>", "Maximum classes per combination").option("--top <n>", "Number of top combinations to show").option("--format <type>", "Output format: console or json", "console").option("--no-dedupe-subsets", "Include subset combinations in results")
118
+ ).action(async (targetPath, opts) => {
13
119
  try {
14
- const format = opts.format === "json" ? "json" : "console";
120
+ const resolved = withNumericDefaults(
121
+ await resolveCommandOptions("analyze", opts, targetPath),
122
+ opts,
123
+ ANALYZE_DEFAULTS
124
+ );
15
125
  await analyzeCommand(targetPath, {
16
- minOccurrences: Number(opts.minOccurrences),
17
- minSize: Number(opts.minSize),
18
- maxSize: Number(opts.maxSize),
19
- top: Number(opts.top),
20
- format,
21
- dedupeSubsets: opts.dedupeSubsets
126
+ minOccurrences: resolved.minOccurrences,
127
+ minSize: resolved.minSize,
128
+ maxSize: resolved.maxSize,
129
+ top: resolved.top,
130
+ format: resolved.format,
131
+ dedupeSubsets: process.argv.includes("--no-dedupe-subsets") ? false : resolved.dedupeSubsets ?? true,
132
+ include: resolved.include,
133
+ exclude: resolved.exclude,
134
+ configPath: resolved.configPath
22
135
  });
23
136
  } catch (error) {
24
137
  const message = error instanceof Error ? error.message : String(error);
@@ -26,15 +139,31 @@ program.command("analyze").description("Scan a directory and report frequent Tai
26
139
  process.exit(1);
27
140
  }
28
141
  });
29
- program.command("generate").description("Generate @layer components CSS from repeated className sets").argument("<path>", "Directory to analyze").requiredOption("--output <file>", "Output CSS file path").option("--min-occurrences <n>", "Minimum occurrences threshold", "3").option("--min-size <n>", "Minimum classes per combination", "2").option("--max-size <n>", "Maximum classes per combination", "5").option("--top <n>", "Number of combinations to generate", "10").option("--prefix <name>", "Namespace prefix for generated classes", "twu-").action(async (targetPath, opts) => {
142
+ addSharedOptions(
143
+ program.command("generate").description("Generate @layer components CSS from repeated className sets").argument("<path>", "Directory to analyze").requiredOption("--output <file>", "Output CSS file path").option("--min-occurrences <n>", "Minimum occurrences threshold").option("--min-size <n>", "Minimum classes per combination").option("--max-size <n>", "Maximum classes per combination").option("--top <n>", "Number of combinations to generate").option("--prefix <name>", "Namespace prefix for generated classes")
144
+ ).action(async (targetPath, opts) => {
30
145
  try {
146
+ const resolved = withNumericDefaults(
147
+ await resolveCommandOptions("generate", opts, targetPath),
148
+ opts,
149
+ GENERATE_DEFAULTS
150
+ );
151
+ const output = opts.output ?? resolved.output;
152
+ if (!output) {
153
+ console.error(chalk.red("Error: --output is required"));
154
+ process.exit(1);
155
+ }
31
156
  await generateCommand(targetPath, {
32
- output: opts.output,
33
- minOccurrences: Number(opts.minOccurrences),
34
- minSize: Number(opts.minSize),
35
- maxSize: Number(opts.maxSize),
36
- top: Number(opts.top),
37
- prefix: opts.prefix
157
+ output,
158
+ minOccurrences: resolved.minOccurrences,
159
+ minSize: resolved.minSize,
160
+ maxSize: resolved.maxSize,
161
+ top: resolved.top,
162
+ prefix: resolved.prefix,
163
+ include: resolved.include,
164
+ exclude: resolved.exclude,
165
+ configPath: resolved.configPath,
166
+ names: resolved.names
38
167
  });
39
168
  } catch (error) {
40
169
  const message = error instanceof Error ? error.message : String(error);
@@ -42,16 +171,32 @@ program.command("generate").description("Generate @layer components CSS from rep
42
171
  process.exit(1);
43
172
  }
44
173
  });
45
- program.command("apply").description("Replace repeated className strings with generated component classes").argument("<path>", "Directory to modify").requiredOption("--output <file>", "Output CSS file path").option("--min-occurrences <n>", "Minimum occurrences threshold", "3").option("--min-size <n>", "Minimum classes per combination", "2").option("--max-size <n>", "Maximum classes per combination", "5").option("--top <n>", "Number of component classes to use", "10").option("--dry-run", "Preview replacements without writing files").option("--prefix <name>", "Namespace prefix for generated classes", "twu-").action(async (targetPath, opts) => {
174
+ addSharedOptions(
175
+ program.command("apply").description("Replace repeated className strings with generated component classes").argument("<path>", "Directory to modify").requiredOption("--output <file>", "Output CSS file path").option("--min-occurrences <n>", "Minimum occurrences threshold").option("--min-size <n>", "Minimum classes per combination").option("--max-size <n>", "Maximum classes per combination").option("--top <n>", "Number of component classes to use").option("--dry-run", "Preview replacements without writing files").option("--prefix <name>", "Namespace prefix for generated classes")
176
+ ).action(async (targetPath, opts) => {
46
177
  try {
178
+ const resolved = withNumericDefaults(
179
+ await resolveCommandOptions("apply", opts, targetPath),
180
+ opts,
181
+ GENERATE_DEFAULTS
182
+ );
183
+ const output = opts.output ?? resolved.output;
184
+ if (!output) {
185
+ console.error(chalk.red("Error: --output is required"));
186
+ process.exit(1);
187
+ }
47
188
  await applyCommand(targetPath, {
48
- output: opts.output,
49
- minOccurrences: Number(opts.minOccurrences),
50
- minSize: Number(opts.minSize),
51
- maxSize: Number(opts.maxSize),
52
- top: Number(opts.top),
53
- prefix: opts.prefix,
54
- dryRun: Boolean(opts.dryRun)
189
+ output,
190
+ minOccurrences: resolved.minOccurrences,
191
+ minSize: resolved.minSize,
192
+ maxSize: resolved.maxSize,
193
+ top: resolved.top,
194
+ prefix: resolved.prefix,
195
+ include: resolved.include,
196
+ exclude: resolved.exclude,
197
+ configPath: resolved.configPath,
198
+ names: resolved.names,
199
+ dryRun: Boolean(resolved.dryRun)
55
200
  });
56
201
  } catch (error) {
57
202
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { analyzeCommand } from '../commands/analyze.js';\nimport { applyCommand } from '../commands/apply.js';\nimport { generateCommand } from '../commands/generate.js';\n\nconst program = new Command();\n\nprogram\n .name('tailwind-unwind')\n .description('Analyze Tailwind CSS class usage in React/Next.js projects')\n .version('0.1.0');\n\nprogram\n .command('analyze')\n .description('Scan a directory and report frequent Tailwind class combinations')\n .argument('<path>', 'Directory to analyze')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold', '5')\n .option('--min-size <n>', 'Minimum classes per combination', '2')\n .option('--max-size <n>', 'Maximum classes per combination', '5')\n .option('--top <n>', 'Number of top combinations to show', '10')\n .option('--format <type>', 'Output format: console or json', 'console')\n .option('--no-dedupe-subsets', 'Include subset combinations in results')\n .action(async (targetPath: string, opts) => {\n try {\n const format = opts.format === 'json' ? 'json' : 'console';\n\n await analyzeCommand(targetPath, {\n minOccurrences: Number(opts.minOccurrences),\n minSize: Number(opts.minSize),\n maxSize: Number(opts.maxSize),\n top: Number(opts.top),\n format,\n dedupeSubsets: opts.dedupeSubsets,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n });\n\nprogram\n .command('generate')\n .description('Generate @layer components CSS from repeated className sets')\n .argument('<path>', 'Directory to analyze')\n .requiredOption('--output <file>', 'Output CSS file path')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold', '3')\n .option('--min-size <n>', 'Minimum classes per combination', '2')\n .option('--max-size <n>', 'Maximum classes per combination', '5')\n .option('--top <n>', 'Number of combinations to generate', '10')\n .option('--prefix <name>', 'Namespace prefix for generated classes', 'twu-')\n .action(async (targetPath: string, opts) => {\n try {\n await generateCommand(targetPath, {\n output: opts.output,\n minOccurrences: Number(opts.minOccurrences),\n minSize: Number(opts.minSize),\n maxSize: Number(opts.maxSize),\n top: Number(opts.top),\n prefix: opts.prefix,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n });\n\nprogram\n .command('apply')\n .description('Replace repeated className strings with generated component classes')\n .argument('<path>', 'Directory to modify')\n .requiredOption('--output <file>', 'Output CSS file path')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold', '3')\n .option('--min-size <n>', 'Minimum classes per combination', '2')\n .option('--max-size <n>', 'Maximum classes per combination', '5')\n .option('--top <n>', 'Number of component classes to use', '10')\n .option('--dry-run', 'Preview replacements without writing files')\n .option('--prefix <name>', 'Namespace prefix for generated classes', 'twu-')\n .action(async (targetPath: string, opts) => {\n try {\n await applyCommand(targetPath, {\n output: opts.output,\n minOccurrences: Number(opts.minOccurrences),\n minSize: Number(opts.minSize),\n maxSize: Number(opts.maxSize),\n top: Number(opts.top),\n prefix: opts.prefix,\n dryRun: Boolean(opts.dryRun),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/index.ts","../../src/cli/defaults.ts","../../src/cli/parseOptions.ts","../../src/cli/version.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport chalk from 'chalk';\nimport { analyzeCommand } from '../commands/analyze.js';\nimport { applyCommand } from '../commands/apply.js';\nimport { generateCommand } from '../commands/generate.js';\nimport { ANALYZE_DEFAULTS, GENERATE_DEFAULTS } from './defaults.js';\nimport { resolveCommandOptions, withNumericDefaults } from './parseOptions.js';\nimport { CLI_VERSION } from './version.js';\n\nconst program = new Command();\n\nfunction addSharedOptions(command: Command): Command {\n return command\n .option('--config <file>', 'Path to tailwind-unwind config file')\n .option(\n '--include <patterns>',\n 'Comma-separated glob include patterns (e.g. \"src/**/*.tsx\")',\n )\n .option(\n '--exclude <patterns>',\n 'Comma-separated glob exclude patterns (e.g. \"**/*.test.tsx\")',\n );\n}\n\nprogram\n .name('tailwind-unwind')\n .description('Analyze Tailwind CSS class usage in React/Next.js projects')\n .version(CLI_VERSION);\n\naddSharedOptions(\n program\n .command('analyze')\n .description('Scan a directory and report frequent Tailwind class combinations')\n .argument('<path>', 'Directory to analyze')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold')\n .option('--min-size <n>', 'Minimum classes per combination')\n .option('--max-size <n>', 'Maximum classes per combination')\n .option('--top <n>', 'Number of top combinations to show')\n .option('--format <type>', 'Output format: console or json', 'console')\n .option('--no-dedupe-subsets', 'Include subset combinations in results'),\n).action(async (targetPath: string, opts) => {\n try {\n const resolved = withNumericDefaults(\n await resolveCommandOptions('analyze', opts, targetPath),\n opts,\n ANALYZE_DEFAULTS,\n );\n\n await analyzeCommand(targetPath, {\n minOccurrences: resolved.minOccurrences,\n minSize: resolved.minSize,\n maxSize: resolved.maxSize,\n top: resolved.top,\n format: resolved.format,\n dedupeSubsets: process.argv.includes('--no-dedupe-subsets')\n ? false\n : (resolved.dedupeSubsets ?? true),\n include: resolved.include,\n exclude: resolved.exclude,\n configPath: resolved.configPath,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n});\n\naddSharedOptions(\n program\n .command('generate')\n .description('Generate @layer components CSS from repeated className sets')\n .argument('<path>', 'Directory to analyze')\n .requiredOption('--output <file>', 'Output CSS file path')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold')\n .option('--min-size <n>', 'Minimum classes per combination')\n .option('--max-size <n>', 'Maximum classes per combination')\n .option('--top <n>', 'Number of combinations to generate')\n .option('--prefix <name>', 'Namespace prefix for generated classes'),\n).action(async (targetPath: string, opts) => {\n try {\n const resolved = withNumericDefaults(\n await resolveCommandOptions('generate', opts, targetPath),\n opts,\n GENERATE_DEFAULTS,\n );\n const output = opts.output ?? resolved.output;\n\n if (!output) {\n console.error(chalk.red('Error: --output is required'));\n process.exit(1);\n }\n\n await generateCommand(targetPath, {\n output,\n minOccurrences: resolved.minOccurrences,\n minSize: resolved.minSize,\n maxSize: resolved.maxSize,\n top: resolved.top,\n prefix: resolved.prefix,\n include: resolved.include,\n exclude: resolved.exclude,\n configPath: resolved.configPath,\n names: resolved.names,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n});\n\naddSharedOptions(\n program\n .command('apply')\n .description('Replace repeated className strings with generated component classes')\n .argument('<path>', 'Directory to modify')\n .requiredOption('--output <file>', 'Output CSS file path')\n .option('--min-occurrences <n>', 'Minimum occurrences threshold')\n .option('--min-size <n>', 'Minimum classes per combination')\n .option('--max-size <n>', 'Maximum classes per combination')\n .option('--top <n>', 'Number of component classes to use')\n .option('--dry-run', 'Preview replacements without writing files')\n .option('--prefix <name>', 'Namespace prefix for generated classes'),\n).action(async (targetPath: string, opts) => {\n try {\n const resolved = withNumericDefaults(\n await resolveCommandOptions('apply', opts, targetPath),\n opts,\n GENERATE_DEFAULTS,\n );\n const output = opts.output ?? resolved.output;\n\n if (!output) {\n console.error(chalk.red('Error: --output is required'));\n process.exit(1);\n }\n\n await applyCommand(targetPath, {\n output,\n minOccurrences: resolved.minOccurrences,\n minSize: resolved.minSize,\n maxSize: resolved.maxSize,\n top: resolved.top,\n prefix: resolved.prefix,\n include: resolved.include,\n exclude: resolved.exclude,\n configPath: resolved.configPath,\n names: resolved.names,\n dryRun: Boolean(resolved.dryRun),\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error('Unexpected error:', message);\n process.exit(1);\n }\n});\n\nprogram.parse();\n","export const ANALYZE_DEFAULTS = {\n minOccurrences: 5,\n minSize: 2,\n maxSize: 5,\n top: 10,\n} as const;\n\nexport const GENERATE_DEFAULTS = {\n minOccurrences: 3,\n minSize: 2,\n maxSize: 5,\n top: 10,\n prefix: 'twu-',\n} as const;\n","import { loadCommandOptions } from '../config/loadConfig.js';\nimport type { CliCommand } from '../config/types.js';\nimport type { AnalyzeOptions } from '../parser/types.js';\n\nfunction splitPatterns(value: unknown): string[] | undefined {\n if (typeof value !== 'string' || value.trim().length === 0) {\n return undefined;\n }\n\n return value\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part.length > 0);\n}\n\nfunction optionalNumber(value: unknown): number | undefined {\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nexport interface RawCliOptions {\n config?: string;\n minOccurrences?: string | number;\n minSize?: string | number;\n maxSize?: string | number;\n top?: string | number;\n prefix?: string;\n dedupeSubsets?: boolean;\n include?: string;\n exclude?: string;\n output?: string;\n format?: string;\n dryRun?: boolean;\n}\n\nfunction cliNumber(\n value: string | number | undefined,\n fallback: number,\n): number {\n const parsed = optionalNumber(value);\n return parsed ?? fallback;\n}\n\n/**\n * Merge config file values with CLI flags (CLI wins).\n */\nexport async function resolveCommandOptions(\n command: CliCommand,\n opts: RawCliOptions,\n targetPath?: string,\n): Promise<\n AnalyzeOptions & { output?: string; dryRun?: boolean; names?: Record<string, string> }\n> {\n const resolved = await loadCommandOptions(\n command,\n {\n configPath: opts.config,\n minOccurrences: optionalNumber(opts.minOccurrences),\n minSize: optionalNumber(opts.minSize),\n maxSize: optionalNumber(opts.maxSize),\n top: optionalNumber(opts.top),\n prefix: opts.prefix,\n dedupeSubsets: opts.dedupeSubsets,\n include: splitPatterns(opts.include),\n exclude: splitPatterns(opts.exclude),\n output: opts.output,\n dryRun: opts.dryRun,\n },\n { targetPath },\n );\n\n return {\n minOccurrences: resolved.minOccurrences,\n minSize: resolved.minSize,\n maxSize: resolved.maxSize,\n top: resolved.top,\n prefix: resolved.prefix,\n dedupeSubsets: resolved.dedupeSubsets,\n include: resolved.include,\n exclude: resolved.exclude,\n configPath: resolved.configPath,\n output: resolved.output,\n names: resolved.names,\n format: opts.format === 'json' ? 'json' : 'console',\n dryRun: opts.dryRun ?? resolved.dryRun,\n };\n}\n\nexport function withNumericDefaults(\n resolved: Awaited<ReturnType<typeof resolveCommandOptions>>,\n opts: RawCliOptions,\n defaults: {\n minOccurrences: number;\n minSize: number;\n maxSize: number;\n top: number;\n prefix?: string;\n },\n) {\n return {\n ...resolved,\n minOccurrences:\n resolved.minOccurrences ??\n cliNumber(opts.minOccurrences, defaults.minOccurrences),\n minSize: resolved.minSize ?? cliNumber(opts.minSize, defaults.minSize),\n maxSize: resolved.maxSize ?? cliNumber(opts.maxSize, defaults.maxSize),\n top: resolved.top ?? cliNumber(opts.top, defaults.top),\n prefix: resolved.prefix ?? opts.prefix ?? defaults.prefix,\n };\n}\n\n/** @deprecated Use resolveCommandOptions */\nexport const resolveAnalyzeOptions = (\n opts: RawCliOptions,\n targetPath?: string,\n) => resolveCommandOptions('analyze', opts, targetPath);\n","import { readFileSync } from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nfunction readPackageVersion(): string {\n const currentDir = path.dirname(fileURLToPath(import.meta.url));\n const packageJsonPath = path.join(currentDir, '../../package.json');\n const raw = readFileSync(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(raw) as { version?: string };\n return pkg.version ?? '0.0.0';\n}\n\nexport const CLI_VERSION = readPackageVersion();\n"],"mappings":"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","names":[]}