Fontlex Markdown
The box below is a plain text box holding Markdown. The font renders it: the text engine
that lays out the letters runs GitHub Flavored Markdown's rules, line by line, hides the markup and styles the
text. The characters you type stay exactly as typed. No script on this page does any of it. It comes in two editions: monospaced, and proportional with code in a monospaced font, so the box looks like the rendered page.
Turn off "Render Markdown" to see the characters. Each line is read on its own: the font sees
one line at a time, as the browser lays it out.
What it renders
- Emphasis and strong emphasis, by CommonMark's full rules (left- and right-flanking runs, the rule of
three,
_ inside words, nesting), with Unicode punctuation and whitespace in any script.
- Code spans, with a background: any number of backticks, a space of padding kept visible.
- Inline links and images, shown as styled text, with destinations and titles hidden; links can't contain
links, images can.
- Autolinks (URLs and email addresses), raw HTML (dimmed), entity and numeric character references (shown
as their characters), and backslash escapes.
- GitHub's extensions: strikethrough with
~ or ~~, bare URLs
(www., http://, https://, ftp://, with the trailing
punctuation GitHub leaves out) and bare email addresses.
- Each line's block markup: headings, block quotes (a bar), list items (a bullet; numbers stay), task
boxes, thematic breaks (a rule), and lines that are code, code fences, HTML or link reference definitions,
which inline syntax leaves alone.
How exact it is
| Text | Lines | Monospace | Proportional |
| CommonMark's one-line spec examples | 447 | 100.0% | 100.0% |
| GitHub's one-line extension examples | 23 | 100.0% | 100.0% |
| Random lines of Markdown syntax | 19,526 | 100.0% | 100.0% |
| Random lines behind block markup | 4,902 | 100.0% | 100.0% |
Each character's glyph (hidden, or its style) is compared with what GitHub makes of the line
read as a document, as computed by ports of the reference implementations: commonmark.js 0.31.2, and
cmark-gfm 0.29.0.gfm.13 (github.com's parser) for the extensions. Lines past one of the font's bounds (below)
are left out of the count; many of them still come out right.
How a font can parse Markdown
OpenType lets a font substitute glyphs by context, one lookup after another, each a pass over the line
from left to right or from right to left. The font's 150 or so passes carry what they learn in glyph variants.
The trick that makes Markdown possible is that most passes only see the characters they care about: a pass
matching * and _ skips every letter in between, so a pair of markers is next to each
other however much text separates them.
- Right to left: what lies ahead of each character. Whether a code span's closing backticks
follow, whether a link destination
(…) follows a ], whether a valid tag or
autolink starts at a <, and what the line's block markup needs to know.
- Left to right, after that: the line's block markup, read from its start; a scan that settles code
spans, link destinations and raw HTML; then brackets and emphasis are matched in rounds, where each round
pairs every opener with the closer right after it and matched pairs drop out, so the next round sees the
next level of nesting; then each glyph is drawn in its style.
So CommonMark's inline syntax takes one change of direction. It can't take none: whether a run of backticks
opens a code span depends on what follows, and whether it is inside one depends on what precedes. GitHub's
extensions add a few right-to-left passes later on: where a bare URL's trailing punctuation starts, and
email addresses, which GitHub only looks for once emphasis is settled. Markdown's nesting is unbounded,
which no finite set of passes can follow, so the font has bounds: emphasis runs of up to 6 characters, nested 6 deep; 3 brackets open at once; backtick runs of up to 8; parentheses 3 deep in a destination.
Limits
- One line at a time: a line is read as if it were the whole document, so nothing that spans lines (a
paragraph continued into a list, a fenced code block's content, reference links).
- Browsers break a line into pieces before the font sees it, and the font can't see across them: Safari at
soft wraps (so this box doesn't wrap), Chrome where the script changes and at tabs, so
*мир*
after Latin text, a Latin URL after Cyrillic link text, or emphasis with a tab inside, stays as typed there
(Safari renders all three).
- In Safari a space inside a hidden link destination (before a title) still takes a space's width.
- Needs a browser or app that applies OpenType features and color fonts: current Chrome, Firefox and Safari.
Base fonts: JetBrains Mono, and Noto Sans with code in JetBrains Mono, each with its bold and italic (SIL Open Font License).