From a69f7cdce043e0d4e4cfdf0650856a5b7f1cf9d8 Mon Sep 17 00:00:00 2001 From: chris Date: Thu, 29 Jan 2026 15:58:56 +0100 Subject: [PATCH] Add Astro language support Parse .astro files by extracting frontmatter (TypeScript between --- markers) for imports, and treat components as default exports. Co-Authored-By: Claude Opus 4.5 --- README.md | 1 + main.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 70 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 16d261f..24910f3 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Lightweight AST-based codebase indexer for AI coding assistants. Generates a `re ## Supported Languages - JavaScript / TypeScript (.js, .jsx, .ts, .tsx) +- Astro (.astro) — parses frontmatter imports, treats component as default export - Go (.go) - Python (.py) - Clojure / ClojureScript (.cljs, .clj, .cljc) — detected but not yet parsed (no tree-sitter grammar available) diff --git a/main.go b/main.go index 1f37a99..c912795 100644 --- a/main.go +++ b/main.go @@ -54,15 +54,16 @@ var ( } extToLang = map[string]string{ - ".js": "javascript", - ".jsx": "javascript", - ".ts": "typescript", - ".tsx": "typescript", - ".cljs": "clojurescript", - ".clj": "clojure", - ".cljc": "clojure", - ".go": "go", - ".py": "python", + ".js": "javascript", + ".jsx": "javascript", + ".ts": "typescript", + ".tsx": "typescript", + ".astro": "astro", + ".cljs": "clojurescript", + ".clj": "clojure", + ".cljc": "clojure", + ".go": "go", + ".py": "python", } ) @@ -182,6 +183,8 @@ func parseFile(parser *sitter.Parser, content []byte, lang string) parseResult { treeSitterLang = javascript.GetLanguage() case "typescript": treeSitterLang = typescript.GetLanguage() + case "astro": + return parseAstro(parser, content) case "clojure", "clojurescript": return parseResult{} case "go": @@ -372,6 +375,63 @@ func parseJSTS(root *sitter.Node, content []byte) parseResult { return result } +// parseAstro handles .astro files by extracting the frontmatter (TypeScript) +// and parsing it for imports. Astro components are always exported by their file. +func parseAstro(parser *sitter.Parser, content []byte) parseResult { + var result parseResult + + // Extract frontmatter between --- markers + frontmatter := extractAstroFrontmatter(content) + if len(frontmatter) > 0 { + // Parse frontmatter as TypeScript + parser.SetLanguage(typescript.GetLanguage()) + tree, err := parser.ParseCtx(context.Background(), nil, frontmatter) + if err == nil { + defer tree.Close() + fmResult := parseJSTS(tree.RootNode(), frontmatter) + result.Imports = fmResult.Imports + // Include defines from frontmatter (exported functions, etc.) + result.Defines = fmResult.Defines + } + } + + // Astro components are always exported as the default export + result.Exports = append(result.Exports, "default") + result.Defines = append(result.Defines, Symbol{ + Name: "default", + Type: "component", + Line: 1, + }) + + return result +} + +// extractAstroFrontmatter extracts content between --- markers at the start of an Astro file +func extractAstroFrontmatter(content []byte) []byte { + str := string(content) + + // Find the first --- + firstIdx := strings.Index(str, "---") + if firstIdx == -1 { + return nil + } + + // Check that --- is at the start (allowing leading whitespace/newlines) + prefix := strings.TrimSpace(str[:firstIdx]) + if prefix != "" { + return nil + } + + // Find the closing --- + rest := str[firstIdx+3:] + secondIdx := strings.Index(rest, "---") + if secondIdx == -1 { + return nil + } + + return []byte(rest[:secondIdx]) +} + func extractExportClause(node *sitter.Node, content []byte, result *parseResult) { for i := 0; i < int(node.ChildCount()); i++ { child := node.Child(i) -- 2.51.2