feat(extraction+resolution): Astro support — frontmatter/template extraction + src/pages routes (#768) (#815)

.astro files were not indexed at all, leaving a typical Astro site mostly
invisible to search/impact/explore. New AstroExtractor (Svelte/Vue SFC
pattern): component node per file, TS frontmatter + <script> blocks
delegated to the TypeScript extractor, template {fn(...)} calls (incl. the
multiline `{posts.map((post) => (` opening line), PascalCase component-tag
references. New astroResolver: Astro global + astro:* virtual modules as
framework-provided, component resolution with the #764 ambiguity rule,
src/pages/ file-based routes ([param]→:param, [...rest]→*rest, _-prefixed
and *.config.* excluded). SFC languages now preload the TS/JS grammars
their extractors delegate to (a pure-SFC file set previously had none
loaded). Also fixes a pre-existing Svelte/Vue script-block off-by-one that
reported every script symbol one line low.

Validated per the playbook: stalux (the issue's repro) 54/54 .astro files
indexed, getIconNode found at its exact line, 14/14 routes, 93.0% fair
cross-file coverage; AstroPaper 27/27 components, 13/13 routes (underscore
dirs correctly excluded), explore connects page→Card→Datetime through the
jsx-render synthesizer; node/edge counts stable across re-syncs.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-06-11 18:50:11 -05:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 763ee9c825
commit 823ffd1c3d
15 changed files with 934 additions and 16 deletions
+5
View File
@@ -24,6 +24,7 @@ import { EXTRACTORS } from './languages';
import { LiquidExtractor } from './liquid-extractor';
import { RazorExtractor } from './razor-extractor';
import { SvelteExtractor } from './svelte-extractor';
import { AstroExtractor } from './astro-extractor';
import { DfmExtractor } from './dfm-extractor';
import { VueExtractor } from './vue-extractor';
import { MyBatisExtractor } from './mybatis-extractor';
@@ -4752,6 +4753,10 @@ export function extractFromSource(
// Use custom extractor for Vue
const extractor = new VueExtractor(filePath, source);
result = extractor.extract();
} else if (detectedLanguage === 'astro') {
// Use custom extractor for Astro (frontmatter + template delegation)
const extractor = new AstroExtractor(filePath, source);
result = extractor.extract();
} else if (detectedLanguage === 'liquid') {
// Use custom extractor for Liquid
const extractor = new LiquidExtractor(filePath, source);