fix(ds): generate-component-registry usa AST parser (Onda 2 PR 2.3)#103
Conversation
…Onda 2 PR 2.3) Resolve issue do CodeRabbit no PR #97 (Onda 1.2): regex `/[a-zA-Z0-9]+(?=:)/g` capturava prefixos do Tailwind dentro das strings de classes (`hover:`, `focus:`, `dark:`) como se fossem nomes de variants. ## O bug ```ts variants: { variant: { default: 'h-10', ghost: 'h-9 hover:bg-accent focus:ring-2', // ^^^^^ ^^^^^ // Capturados como subkeys 'hover' e 'focus' — errado! } } ``` Output buggado em registry.json: ```json { "variant": ["default", "ghost", "hover", "focus", "hover"] } ``` Output correto: ```json { "variant": ["default", "ghost"] } ``` ## Stats: antes vs depois | Métrica | Antes | Depois | |---|---|---| | Ocorrências de "hover" no registry.json | **45** | **0** | | Ocorrências de "focus" no registry.json | 0 | 0 | | Componentes com variants | 13 | 13 (sem mudança real) | ## Solução: TypeScript Compiler API Substituí o regex por AST parser usando `ts.createSourceFile()` (built-in, já nas deps via TS 5.8.3 — sem deps novas). A função `extractVariants()` agora: 1. Cria um AST do source TSX 2. Visita cada `ObjectLiteralExpression` 3. Procura por nó com **AMBAS** as propriedades `variants` e `defaultVariants` (padrão CVA — Class Variance Authority — descarta objetos não-CVA) 4. Para cada variant, extrai apenas as `PropertyAssignment` no nível correto da árvore — strings/className NÃO são parseadas ## Componentes que tinham keys fantasma (todos corrigidos) - icon-button: tinha 9 "hover" + 6 keys reais → agora só 6 keys reais - card: tinha 8 "hover" + variants reais → corrigido - (e outros 11 componentes) ## Stress-test - ✅ `bun run build` (1m): registry regenerado durante prebuild, sem erros - ✅ `bun run scripts/generate-component-registry.ts`: 13 with variants, 56 skipped - ✅ TypeScript: sem erros novos - ✅ Diff de registry.json: pesquisa de "hover" caiu de 45 → 0 ## Refs - /workspace/notes/coderabbit-feedback-pr97.md (issue do PR #97) - TypeScript AST: https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/generate-component-registry.ts (1)
127-133: ⚡ Quick winOrdene os arquivos antes do loop para saída determinística do
registry.json.Sem ordenação, a ordem pode variar por filesystem/ambiente e gerar diff ruidoso entre execuções.
💡 Diff sugerido
-const files = readdirSync(UI_DIR); +const files = readdirSync(UI_DIR).sort((a, b) => a.localeCompare(b));🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/generate-component-registry.ts` around lines 127 - 133, Ordene a lista retornada por readdirSync antes do loop para tornar a saída de registry.json determinística: após const files = readdirSync(UI_DIR) (usado pelo loop for (const file of files)), chame files.sort() ou reatribua const files = readdirSync(UI_DIR).sort(); isso garante ordem estável entre execuções e evita diffs ruidosos; mantenha o resto da lógica que atualiza processed e skipped inalterada.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@scripts/generate-component-registry.ts`:
- Around line 127-133: Ordene a lista retornada por readdirSync antes do loop
para tornar a saída de registry.json determinística: após const files =
readdirSync(UI_DIR) (usado pelo loop for (const file of files)), chame
files.sort() ou reatribua const files = readdirSync(UI_DIR).sort(); isso garante
ordem estável entre execuções e evita diffs ruidosos; mantenha o resto da lógica
que atualiza processed e skipped inalterada.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 30a530b8-7bfc-4946-8ba6-e7472bc0f36e
📒 Files selected for processing (2)
scripts/generate-component-registry.tssrc/components/ui/registry.json
There was a problem hiding this comment.
Pull request overview
Atualiza o gerador de src/components/ui/registry.json para usar o AST do TypeScript (Compiler API) em vez de regex, eliminando falsos positivos onde prefixos do Tailwind (hover:, focus:, etc.) eram indevidamente coletados como “variants”.
Changes:
- Substitui o parser por regex no
generate-component-registry.tspor um walker de AST viats.createSourceFile()para coletar apenasPropertyAssignmentno nível correto. - Restringe a detecção de “blocos CVA” para objetos que contenham
variantsedefaultVariants. - Regenera
src/components/ui/registry.json, removendo entradas espúrias (ex.:hover,visible,before,after,duration) e capturando corretamente chaves string-literal (ex.:"2xl","icon-sm").
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| scripts/generate-component-registry.ts | Troca regex por AST (TypeScript Compiler API) para extrair variants com precisão e evitar falsos positivos de Tailwind. |
| src/components/ui/registry.json | Arquivo gerado atualizado, removendo variants inválidos e refletindo corretamente as opções reais dos componentes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| filename, | ||
| content, | ||
| ts.ScriptTarget.Latest, | ||
| /* setParentNodes */ true, |
| const files = readdirSync(UI_DIR); | ||
| let processed = 0; | ||
| let skipped = 0; | ||
|
|
||
| for (const file of files) { | ||
| if (file.endsWith('.tsx')) { | ||
| const content = readFileSync(join(UI_DIR, file), 'utf-8'); | ||
| const variants = extractVariants(content); | ||
| const path = join(UI_DIR, file); |
| function extractVariants(content: string, filename: string): Record<string, string[]> | null { | ||
| const sourceFile = ts.createSourceFile( | ||
| filename, | ||
| content, | ||
| ts.ScriptTarget.Latest, | ||
| /* setParentNodes */ true, | ||
| ts.ScriptKind.TSX | ||
| ); |
CodeRabbit no PR #103: sem sort, ordem do readdirSync varia por filesystem/ambiente, gerando diff ruidoso entre execuções. ```diff - const files = readdirSync(UI_DIR); + const files = readdirSync(UI_DIR).sort((a, b) => a.localeCompare(b)); ``` Bonus: o registry.json agora fica ordenado alfabeticamente (avatar primeiro, zoom-in último), facilitando navegação visual e diff.
| filename, | ||
| content, | ||
| ts.ScriptTarget.Latest, | ||
| /* setParentNodes */ true, |
Resumo
Resolve issue do CodeRabbit no PR #97: regex
/[a-zA-Z0-9]+(?=:)/gcapturava prefixos Tailwind (hover:,focus:,dark:) como se fossem nomes de variants.Bug
Antes:
{ variant: ['default', 'ghost', 'hover', 'focus', 'hover'] }Depois:
{ variant: ['default', 'ghost'] }✓Stats
Solução: TypeScript Compiler API
ts.createSourceFile()(built-in via TS 5.8.3) parseia o AST e identifica apenasPropertyAssignmentno nível correto da árvore. O conteúdo das strings (className) é ignorado.Lógica adicional: só consideramos um bloco como variants se ele tem AMBAS
variantsEdefaultVariants(padrão CVA — Class Variance Authority). Isso filtra objetos parecidos mas não-CVA (ex: configurações de filtros que tenham uma chave "variants").Stress-test
bun run build(1m) — registry regenerado no prebuildbun run scripts/generate-component-registry.ts→ 13 components with variants, 56 skippedtypescriptque já estava (5.8.3)Métricas Onda 2
Summary by CodeRabbit
Notas de Versão
Melhorias
muted,interactive,underline,glowPurple,neon,2xl,icon-sm,icon-lg), com conjuntos de tokens mais enxutos e consistentes.Chores