Docs

How a document is rendered

What happens between your Markdown and the page a reader sees, why maths is set by KaTeX and what it cannot do, and why the preview matches the page.

What you save is Markdown source, and what a reader receives is a page of HTML with the formulae already typeset. Between the two is one renderer, the same everywhere your text appears. Knowing roughly what it does explains most of the dialect's rules, and most of the surprises in troubleshooting.

The source is what is kept

A work's text is stored as the Markdown you wrote, not as HTML. The visual editor writes Markdown too: what it shows formatted, it saves as source. That is what keeps a document portable. You can export it, convert it, edit it by hand or with the command-line client, and nothing is lost in a format only one program reads.

It also means a document is rendered again whenever the renderer improves. A fix to how a construct is drawn reaches every document that uses it, with no one re-saving anything.

From source to page

The renderer works in four stages.

  1. Repairs on the raw text. A few things have to be settled before the text is parsed, because a Markdown parser would otherwise destroy them: \(…\) and \[…\] are rewritten to dollar form, since CommonMark reads \( as an escaped bracket; the leading spaces of a verse line are kept; a block attribute line such as {align=center} is tied to the block below it; and nested ::: blocks are given the colon depths they need.
  2. Parsing. The text is read as CommonMark with GitHub's extensions, maths and directives, into a tree of paragraphs, headings, lists, directives and so on.
  3. Claiming. Each construct of the dialect claims its part of the tree: the statements claim :::theorem and its kin, the admonitions claim :::note, the figure claims :::figure. Anything left unclaimed after them is turned back into the characters you typed, which is why a misspelt directive shows on the page rather than vanishing. Headings are moved below the title's level here too.
  4. Writing the page. The tree becomes HTML. Formulae are typeset, code is highlighted, every heading gets an anchor, and the result passes through the sanitizer described below.

The page a reader receives already contains all of it. Formulae, labels, captions and code colours are in the HTML, so the text reads without scripts, in a feed reader, in print and to a screen reader. Scripts add only what needs a browser: switching tabs, the full-screen image viewer, and starting a video player.

Why maths is KaTeX

Formulae are set by KaTeX, which reads LaTeX maths and writes HTML. It was chosen for what it lets the page promise:

  • The formula is in the page. KaTeX typesets when the page is built, not in the reader's browser, so a formula appears with the text, with no flash of raw LaTeX and no script to wait for.
  • The same input gives the same output. A formula renders identically on every page, in the editor's preview and in search results.
  • It cannot do harm. KaTeX renders maths and nothing else. It cannot load a file, run a command or open a link, so a formula from a stranger is as safe as their prose.

What it cannot do

The last point has a price. KaTeX implements most of LaTeX's maths mode, but not all of it, and some of what it leaves out is deliberate:

  • No packages. There is no \usepackage. What KaTeX supports is the list on its supported functions page; a command from elsewhere, such as physics's \norm or \abs, is shown in red. Write it out: \lVert x \rVert, \lvert x \rvert.
  • No links in formulae. \href and \url are refused. A formula may produce maths and nothing else: no link, no class, no id that could point a reader somewhere or change the page around it. Put the link in the sentence around the formula.
  • Macros last one formula. A \newcommand or \def is forgotten at the end of the formula that defines it.
  • No drawings. Apart from a rectangular commutative square, which KaTeX's \begin{CD} draws, diagrams and plots are not maths mode. Draw them in a TikZ block, which is compiled by a real LaTeX when the work is saved.
  • Display needs its own lines. An environment that works only in display mode, such as align* or a \tag, fails when its $$ delimiters share a line with it, because then the formula is inline.

A formula KaTeX cannot read never breaks the page. It is shown in place, in red, with your source, so you can see what to fix.

Why the preview is the page

The editor's preview, the published page and this documentation site all render through the same renderer, with the same options. That is why the preview can be trusted: a document that looks right there is right for every reader.

Three places use a smaller set on purpose. Titles, abstracts and biographies take inline formatting only, because they appear in browser tabs, search results and citation exports where a block cannot go. Comments and direct messages take text, maths and code, but no media and no blocks; see Comments. The rules for each are written once and shared, so a construct new to documents is refused in those fields by default rather than appearing in a title by accident.

What the sanitizer does

A Markdown document may contain raw HTML, and HTML can carry scripts, styles and frames. So the last stage keeps only an allowed list of elements and attributes and removes everything else, silently:

  • no <script>, no <style>, and no on… event attributes;
  • no links or images with addresses other than https, http and, for links, mailto;
  • no frames except the two video players;
  • no free style attributes, so a document cannot restyle the page around it;
  • any id you write gets user-content- in front of it, so it can never take over a part of the page itself.

The same rules apply to HTML the renderer writes from your Markdown and to HTML you type, so there is no way around them. The reasons for each, and the list of HTML you can use, are on HTML and security.

What happens at save time

Two things are not done on every page view, because they are slow or depend on other people's data, and are prepared when the work is saved instead:

  • TikZ diagrams are compiled by LaTeX into images, one for a light page and one for a dark page, and the page shows the image. Until a diagram has been compiled, its place shows Diagram not rendered.
  • Mentions are matched to profiles, so @handle links to a person who exists, and keeps linking to them if they change their handle. A handle that matches nobody stays plain text. The editor's preview has nothing saved to match against, so there every well-formed handle is a link.