Repository navigation
fix(frontend): Vue/Svelte indexing and five-repo smoke matrix - #155
PatrickSys wants to merge 1 commit into
Conversation
Add .vue/.svelte to scan and language detection, extract script blocks for generic analysis, detect Nuxt/SvelteKit from workspace deps, and ignore SvelteKit + routes and non-Next app/pages paths. Document five-repo smoke results in docs/benchmark.md with fixture tests.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8fd2c49b2c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const jstsContent = scriptBody ?? content; | ||
|
|
||
| if (jstsLanguage) { | ||
| const parsed = await this.parseJSTSFile(filePath, jstsContent, jstsLanguage); |
There was a problem hiding this comment.
Preserve source line offsets when parsing extracted scripts
When a Vue or Svelte script follows a template or other leading content, parsing the extracted, trimmed body makes all component and import locations relative to the script rather than the original file. Those components are then passed to createChunksFromCode alongside the full source, so its component-boundary slicing selects unrelated lines. For example, a function on source line 24 becomes a component on line 1, producing a chunk of template lines that omits the function entirely. Preserve the original line positions during extraction or translate the parsed locations before using them for chunking.
Useful? React with 👍 / 👎.
| kind: 'vue' | 'svelte' | ||
| ): { body: string; language: 'typescript' | 'javascript' } | null { | ||
| const tag = 'script'; | ||
| const match = content.match(new RegExp(`<${tag}([^>]*)>([\\s\\S]*?)<\\/${tag}>`, 'i')); |
There was a problem hiding this comment.
Extract both script blocks from single-file components
For components containing two script blocks, content.match extracts only the first and silently ignores the second. This affects Vue components combining a normal script with <script setup> and Svelte components combining module and instance scripts. If the first block contains module exports and the second imports child components, GenericAnalyzer.analyze never records those imports or the second block's declarations, leaving dependency metadata incomplete. Process all supported script blocks, preserving each block's source locations.
Useful? React with 👍 / 👎.
[Medium impact] The PR changes indexing and analyzer selection for frontend repositories. Fix source positions and support multiple script blocks before merging. Findings
SummaryAdds Vue/Svelte file discovery and script analysis, dependency-based framework claims, tighter Next.js detection, and five-repository smoke results.
Review checks were static; no runtime verification was performed. Diagram%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Vue or Svelte file] --> B[Extract first script and trim]
B --> C[Parse imports, exports, and declarations]
C --> D[Script-relative source positions]
D --> E[Slice original component file]
E --> F[Chunks can contain unrelated lines]
A --> G[Later script blocks are skipped]
Reviews (1) · Last reviewed commit: "fix(frontend): index Vue/Svelte sources ..." · Reviewed by Greptile |
| const jstsContent = scriptBody ?? content; | ||
|
|
||
| if (jstsLanguage) { | ||
| const parsed = await this.parseJSTSFile(filePath, jstsContent, jstsLanguage); |
There was a problem hiding this comment.
Parsing the trimmed script resets source line numbers, but createChunksFromCode still slices the full component file. In a Vue file with a long template before its script, a function near the start of the script gets a chunk containing template lines instead of the function. Import locations are shifted too.
Preserve the original line positions when extracting scripts, or map parsed positions back before using them.
| const match = content.match(new RegExp(`<${tag}([^>]*)>([\\s\\S]*?)<\\/${tag}>`, 'i')); | ||
| if (!match?.[2]) { | ||
| return null; |
There was a problem hiding this comment.
The single regex match reads only the first script block. Vue files can contain both <script> and <script setup>, and Svelte files can contain module and instance scripts. Imports, exports, and declarations in the second block are never parsed, so they are missing from the analysis.
Extract and analyze every script block, keeping each block's language and original positions.
| function matchesNextAppRouterConvention(filePath: string): boolean { | ||
| if (!isInAppRouter(filePath)) { | ||
| return false; | ||
| } | ||
| return getAppRouteFileKind(path.basename(filePath)) !== null; | ||
| } |
There was a problem hiding this comment.
Metadata routes lose Next.js labels
The narrower filename check excludes real Next.js files such as app/robots.ts and app/sitemap.ts when they have no next import. Neither name appears in APP_ROUTE_FILE_KINDS, so these files lose their Next.js label and disappear from searches filtered to nextjs.
Include Next.js metadata filenames in the convention check while keeping the SvelteKit exclusion.
| it('writes vue files into a temp project manifest via glob include patterns', async () => { | ||
| const root = path.join(process.cwd(), 'tests/fixtures/frontend-vue-mini'); | ||
| const analyzer = new GenericAnalyzer(); | ||
| const filePath = path.join(root, 'Button.vue'); | ||
| const content = await import('node:fs/promises').then((fs) => fs.readFile(filePath, 'utf-8')); | ||
| const result = await analyzer.analyze(filePath, content); | ||
| expect(result.language).toBe('vue'); | ||
| expect(result.chunks[0]?.metadata.analyzer).toBe('generic'); |
There was a problem hiding this comment.
These tests never run CodebaseIndexer. The glob test calls GenericAnalyzer directly, and the incremental test analyzes one file once without changing it. Both would still pass if the new include glob were removed or updates stopped reaching Vue files.
Add an indexing test that checks the manifest, then changes a component and checks the updated index. Cover Svelte too.
Summary
.vueand.sveltefiles (glob, language detection, generic analyzer script extraction).+route files and Nuxtapp/pages/*.vuepaths.docs/benchmark.md.tests/frontend-spa-indexing.test.ts,tests/fixtures/frontend-vue-mini/.Benchmark highlights (model-free reindex)
Edit preflight remains not ready on broad NL queries across all five (expected conservatism).
Test plan
pnpm exec vitest run(1311 passed)/tmp/fe-benchmark