Skip to main content
Narrator’s core doesn’t know about TypeScript. It knows about source languages, which are objects that can say whether they handle a file and can create a narrator for it. @usenarrator/lang-ts is one implementation. Python, Go or SQL files would each be another.

The contract

  • handles decides by path. createNarrator uses the first language that handles a file, and narrator.diff skips files no language handles.
  • ecosystems names the dependency registries this language imports from, such as ["npm"] for TypeScript or ["crates"] for Rust. The narrator uses it to pick which manifests apply. See Dependency detection.
  • create is called once per file, so the file narrator it returns can keep per-file state, such as which imports the file has. When the narrator was given a dependency index, ctx.dependencies(path) returns the package dependencies (name to version range) for a file in this language’s ecosystems.
  • narrate returns lines, the number of parse errors, and stats. Count a fallback each time you show raw code instead of English, so tools like bun stress can measure coverage.
  • problems is optional. Return syntax errors and failed rules from narrate as problems, and from the latest units call through problems(), so diffs can report them. You don’t need to catch your own crashes: the narrator turns an exception into a narrator problem for that file and carries on with the others.
  • units splits the file into matchable pieces for diffs. Use the declaration name as the key and keep it stable across edits. See Units and diffs.

Lines

Each Line describes one sentence:
d is the indent depth, start and end are source offsets (use -1 for lines that don’t map to code), and text may contain markup. Use head for a declaration’s heading line, because diffs use it to title the unit.

Phrases

The core CorePhrases type is shaped around JavaScript concepts. A new language can reuse the parts that fit, such as conditions, statements and most expressions, and define its own phrasebook type for the rest. Follow the pattern plugins use: a typed phrasebook with a required en entry, so the language can be translated the same way.

Registering it

Pass the language to createNarrator next to TypeScript. Order matters only when two languages claim the same file.
python() here is hypothetical. TypeScript and JavaScript are the only source languages today. If you want to build one, open an issue on GitHub first so the contract can grow with you.