importRefs
uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process
The links in a page's imports: each name brought in from the codebase to its definition, #codebase/a/b to the
namespace's page, and a package to its page (at the range the definition uses). Node's builtins aren't pages.
import type { Codebase } from "#codebase/tcmts/cli/codebase"; import type { HighlightRef } from "#codebase/tcmts/cli/pages"; import { isTypeOnlyImport, parse } from "#codebase/tcmts/core/ts"; import type { DefRecord } from "#codebase/tcmts/core/types"; import { isImportDeclaration as ts_isImportDeclaration, isNamedImports as ts_isNamedImports, isStringLiteral as ts_isStringLiteral, } from "typescript/ast"; export function importRefs(cb: Codebase, text: string, rec: DefRecord): HighlightRef[] { const out: HighlightRef[] = []; const ranges = new Map<string, string>(); for (const sp of rec.spans) { const m = sp.ext && /^npm:((?:@[^/@]+\/)?[^@/]+)@([^/#]+)/.exec(sp.ext.module); if (m) ranges.set(m[1]!, m[2]!); } const sf = parse("page.ts", text); for (const st of sf.statements) { if (!ts_isImportDeclaration(st) || !ts_isStringLiteral(st.moduleSpecifier)) continue; const spec = st.moduleSpecifier.text; const at = { start: st.moduleSpecifier.getStart(sf), end: st.moduleSpecifier.end }; if (spec === "#codebase" || spec.startsWith("#codebase/")) { const ns = spec.slice("#codebase".length).replace(/^\//, "").replaceAll("/", "."); out.push({ ...at, namespace: ns }); const b = st.importClause?.namedBindings; if (!b || !ts_isNamedImports(b)) continue; for (const el of b.elements) { const id = el.propertyName ?? el.name; const hs = cb.store.hashesAt(ns ? `${ns}.${id.text}` : id.text); // a name holding a type and a value: the one imported const typeOnly = isTypeOnlyImport(st.importClause) || el.isTypeOnly; const h = hs.find((x) => (cb.store.getDef(x)?.kind === "type") === typeOnly) ?? hs[0]; if (h) out.push({ start: id.getStart(sf), end: id.end, hash: h }); } continue; } const name = /^((?:@[^/]+\/)?[^/]+)/.exec(spec)?.[1]; const range = name && ranges.get(name); if (name && range) out.push({ ...at, package: { name, range } }); } return out; }
uses
- tcmts.cli.codebase.Codebase
- tcmts.cli.pages.HighlightRef
- tcmts.core.ts.isTypeOnlyImport
- tcmts.core.ts.parse
- tcmts.core.types.DefRecord