5.9 KiB
API
Scriptorium is a library with one package and five exported functions. The
signatures below are the whole public surface; everything else lives under
internal/ and reaches no caller. go doc sourcedock.dev/petrbalvin/scriptorium
is the authority on the signatures, and this file explains what each function
does, when it fails, and where the edges of the rendered surfaces are.
Library
Render(source []byte) []byte
Renders Markdown to HTML. The grammar is CommonMark 0.31.2 in full, with the GitHub Flavored Markdown extensions on top: tables, strikethrough, task lists and extended autolinks, plus footnotes and definition lists. Rendering never fails and never returns an error: any input parses, and a construct the grammar does not know stays in the output as literal text.
The extended autolinks supersede three CommonMark examples: a bare
www./http(s):///ftp:// address or a bare email address becomes a link
where CommonMark without the extension would leave it as text. That is the
specification's own trade, and GitHub's reference implementation makes it
too.
html := scriptorium.Render([]byte("# Title\n\nText with [a link](/uri).\n"))
The Markdown engine embeds no mathematics and no diagrams: a $…$ run stays
what the CommonMark grammar says it is. A consumer that wants mathematics
inside its documents calls RenderMath on the math spans it recognises and
splices the results into the HTML itself.
RenderMath(source []byte) []byte
Renders TeX mathematics to a complete MathML Core <math> element in the
inline form. Returns one line of markup with the namespace declared, ready to
embed in HTML. Never fails: see the degradation contract below.
RenderMathDisplay(source []byte) []byte
The display form: the same engine, with display="block" on the element and
the movable limits of big operators set above and below instead of beside.
RenderDiagram(source []byte) ([]byte, error)
Renders Mermaid source to a self-contained SVG document. The first line names the diagram type; only two families are carried:
flowchartand its historicalgraphalias, with any direction (TB/TD,BT,LR,RL), every node shape, every edge kind, subgraphs with their own direction, and theclassDef,class,styleandlinkStylestatements;sequenceDiagram, with participants and actors, all arrow kinds, notes, activations in both spellings, thealt,opt,loop,par,criticalandbreakblocks, colouredrectregions,autonumberand dividers.
Returns an error when the type is outside the two families, when a direction
is unknown, or when a statement does not parse; every error names the diagram
type or the source line, so the author can find the sentence at fault. The
click statement is refused on purpose: the SVG is static and carries no
interactivity.
SupportedDiagram(kind string) bool
Reports whether RenderDiagram carries the named Mermaid type. It answers
the question the error path would answer, before the call.
What every function guarantees
- Determinism. The same input produces byte-identical output on every call, in every process, on every machine. No layout decision reads a map iteration order; the tests assert byte equality across repeated renders.
- No sanitisation. The input is trusted, and the output is written to HTML, MathML or SVG verbatim. Whether the output may reach a given audience is the consumer's policy: a consumer of untrusted input keeps its own sanitiser and applies it to the rendered result.
- Concurrency safety. The engines hold no state between calls and share nothing, so every function is safe for concurrent use.
- No dependencies. The standard library alone; there is no
go.sumbecause there is nothing to sum.
The mathematics surface
The mathematics engine renders the standard TeX command surface that maps
into MathML Core, measured against the coverage list of KaTeX as the external
standard: the Greek letters including the variants, the relation and operator
tables including the negations and the colon relations, the arrows including
the extensible \x family, the big operators, the delimiters, the amsmath
environments, accents, the font and spacing commands, colours, and bounded
macros (\newcommand, \renewcommand, \providecommand, \def,
\DeclareMathOperator) with expansion limits.
Multi-character relations have no single Unicode character, so they render as
the linear two-character operators KaTeX's own MathML branch produces
(\coloneqq as ≔, \coloneq as :−, \Coloneqq as ∷=).
Degradation, not failure
A construct outside the mappable surface degrades in place: the offending
command stays in the output as its verbatim source inside an <merror>
element, and the rest of the expression still renders. The author sees what
was not understood, in the document, at the place it happened.
The commands that degrade are the ones no MathML Core construct can carry:
positioning (\raisebox, \vcenter, \smash, the \llap/\rlap/
\mathclap family, \kern, \mkern, \hskip), boxes and overlays
(\boxed, \colorbox, \fcolorbox, \sideset), text annotations of the
page rather than the formula (\tag, \label, \notag, \verb,
\char, \mathstrut), and the environments outside the table family
(\begin{CD}, \begin{tikzpicture} and every other unknown name).
A macro whose expansion would not terminate is cut by the expansion limits
and degrades at the call site.
A degraded render is still a valid render: the output remains well-formed MathML Core, and the tests assert well-formedness for every degraded corpus case.
Notes
The exported surface is documented in godoc form in the source, and go doc ./... is
the authority on signatures and types. This file explains what the surface is for and
how the parts fit together. It does not repeat the signatures, because a copy of a
signature is a future lie.