Skip to content

Implement it

What to build, in what order, to write a GistUI Format processor or renderer in another language, and how to prove it conforms.

Updated View as Markdown

The specification is written so that a second implementation is possible without reading the first. This is the order that works.

A processor (Core profile)

Line classifier and lexer

Split bytes into lines, handling LF, CRLF, CR and a byte-order mark. Classify each line (statement, table row, comment, fence, prose). Keep the lexer’s state between chunks so it only ever scans new bytes. Sections 4 and 5.

Statement parser

A recursive-descent or Pratt parser over the tokens of one statement. Apply the recovery rules as you go and record a diagnostic for each. Sections 6 to 8.

Catalog

Load the manifest (schemas/catalog.schema.json). Build the derived sets: flag names, enum values per component, aliases. Implement the closest-name rule. Section 9.

Binding arguments

Turn a parsed call into a node: resolve bare words, bind positional and named arguments, coerce values, collect children. Section 11. Then tables: section 12.

The tree and edits

Assign node ids, build the tree, apply replace, patch, append and delete. Sections 13 and 14.

End of stream

Close open brackets, drop unresolved references, break cycles, find the root, report unreachable statements. Order the diagnostics as section 22.2 requires. Section 15.

Limits

Apply every processor limit of section 21.1. Test with hostile input: deep nesting, huge tables, a shared-reference graph.

Run the suite

Every case, whole and one character at a time. See Conformance.

A good first milestone is the first twenty cases, which cover the common path. The reference processor is about 16 KB gzip of TypeScript, so this is a project of weeks, not months.

A runtime (Interactive and Tools)

  • An evaluator for the expression grammar that interprets, never compiles.
  • State with declared defaults and change notification.
  • Dependency tracking, so a state change re-evaluates only what read it.
  • The built-in functions of section 18.7, exactly.
  • A query manager: caching per argument set, refresh timers, cancellation, the call budget.
  • An action runner: steps in order, stop at the first failure, report through the action envelope.
  • Every runtime limit of section 21.2.

A renderer

  • Map each catalog component to a native one. Key on node ids, so an update touches only what changed.
  • Draw #pending nodes as placeholders and nothing for #unknown beyond their children.
  • Apply the URL policy before loading any image, video or background (section 23.4).
  • Render Markdown without raw HTML.
  • Meet the accessibility requirements of section 24.
  • Report every interaction with the action envelope of section 20.3.

Use the reference implementation as an oracle

When the specification seems ambiguous, compare with @gistui/core:

import { parse } from "@gistui/core";

const r = parse(source, catalog);
console.log(JSON.stringify({ tree: r.root, errors: r.errors, valid: r.valid }, null, 2));

If the two disagree and the specification does not settle it, that is a defect in the specification. Please report it: Appendix D lists the points already known.

Schemas

Schema For
tree.schema.json The abstract tree in JSON form
diagnostic.schema.json One diagnostic
catalog.schema.json A catalog manifest
action.schema.json The action envelope
capabilities.schema.json The capability object
expected.schema.json A conformance expectation file

They are in spec/schemas/. Their $ids are under https://gistui.com/schemas/1.0/; those are identifiers, and the files are not published there yet.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close