Lightweight AST-based codebase indexer for AI coding assistants. Generates a relationships.json that Claude Code / Cursor / etc. can reference instead of exploring the entire codebase. paragraph.com/@metaend
ai llm eco ast golang
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <noreply@anthropic.com>

chris a69f7cdc 123cfb55

+70 -9
+1
README.md
··· 5 5 ## Supported Languages 6 6 7 7 - JavaScript / TypeScript (.js, .jsx, .ts, .tsx) 8 + - Astro (.astro) — parses frontmatter imports, treats component as default export 8 9 - Go (.go) 9 10 - Python (.py) 10 11 - Clojure / ClojureScript (.cljs, .clj, .cljc) — detected but not yet parsed (no tree-sitter grammar available)
+69 -9
main.go
··· 54 54 } 55 55 56 56 extToLang = map[string]string{ 57 - ".js": "javascript", 58 - ".jsx": "javascript", 59 - ".ts": "typescript", 60 - ".tsx": "typescript", 61 - ".cljs": "clojurescript", 62 - ".clj": "clojure", 63 - ".cljc": "clojure", 64 - ".go": "go", 65 - ".py": "python", 57 + ".js": "javascript", 58 + ".jsx": "javascript", 59 + ".ts": "typescript", 60 + ".tsx": "typescript", 61 + ".astro": "astro", 62 + ".cljs": "clojurescript", 63 + ".clj": "clojure", 64 + ".cljc": "clojure", 65 + ".go": "go", 66 + ".py": "python", 66 67 } 67 68 ) 68 69 ··· 182 183 treeSitterLang = javascript.GetLanguage() 183 184 case "typescript": 184 185 treeSitterLang = typescript.GetLanguage() 186 + case "astro": 187 + return parseAstro(parser, content) 185 188 case "clojure", "clojurescript": 186 189 return parseResult{} 187 190 case "go": ··· 370 373 371 374 walk(root) 372 375 return result 376 + } 377 + 378 + // parseAstro handles .astro files by extracting the frontmatter (TypeScript) 379 + // and parsing it for imports. Astro components are always exported by their file. 380 + func parseAstro(parser *sitter.Parser, content []byte) parseResult { 381 + var result parseResult 382 + 383 + // Extract frontmatter between --- markers 384 + frontmatter := extractAstroFrontmatter(content) 385 + if len(frontmatter) > 0 { 386 + // Parse frontmatter as TypeScript 387 + parser.SetLanguage(typescript.GetLanguage()) 388 + tree, err := parser.ParseCtx(context.Background(), nil, frontmatter) 389 + if err == nil { 390 + defer tree.Close() 391 + fmResult := parseJSTS(tree.RootNode(), frontmatter) 392 + result.Imports = fmResult.Imports 393 + // Include defines from frontmatter (exported functions, etc.) 394 + result.Defines = fmResult.Defines 395 + } 396 + } 397 + 398 + // Astro components are always exported as the default export 399 + result.Exports = append(result.Exports, "default") 400 + result.Defines = append(result.Defines, Symbol{ 401 + Name: "default", 402 + Type: "component", 403 + Line: 1, 404 + }) 405 + 406 + return result 407 + } 408 + 409 + // extractAstroFrontmatter extracts content between --- markers at the start of an Astro file 410 + func extractAstroFrontmatter(content []byte) []byte { 411 + str := string(content) 412 + 413 + // Find the first --- 414 + firstIdx := strings.Index(str, "---") 415 + if firstIdx == -1 { 416 + return nil 417 + } 418 + 419 + // Check that --- is at the start (allowing leading whitespace/newlines) 420 + prefix := strings.TrimSpace(str[:firstIdx]) 421 + if prefix != "" { 422 + return nil 423 + } 424 + 425 + // Find the closing --- 426 + rest := str[firstIdx+3:] 427 + secondIdx := strings.Index(rest, "---") 428 + if secondIdx == -1 { 429 + return nil 430 + } 431 + 432 + return []byte(rest[:secondIdx]) 373 433 } 374 434 375 435 func extractExportClause(node *sitter.Node, content []byte, result *parseResult) {