The Grand Markdown Feature Test
A single document that pokes at every corner of your renderer: typography, structure, tables, code, math, alerts, and a few sneaky edge cases. If something looks off, you've found a bug worth fixing.[1]
Typography
Plain text, bold, italic, bold and italic, strikethrough, inline code, and a regular link. Autolinks work too: https://example.com. You can also use highlighted text, H2O, E = mc2, and keyboard keys like Ctrl + K.
Escaped characters: *not italic*, `not code`, # not a heading, 1. not a list.
A hard line break follows this line.
And this line comes right after it.
Emoji shortcodes and literals: 🚀 ✨ 🎉
Typographic niceties: "curly quotes", 'single quotes', an em dash --- like this, an en dash for ranges (2020--2026), and an ellipsis...
Heading level three
Heading level four
Heading level five
Heading level six
Setext Heading One
Setext Heading Two
Lists
Unordered
- First item
Second item
Nested item
- Deeply nested item
- Another nested item
- Third item
Ordered
- Gather ingredients
Mix thoroughly
- Dry first
- Wet second
- Bake until golden
Task list
- Write the test document
- Include every feature
- Ship the blog
- Take a long nap
Mixed and loose
A numbered item with a paragraph.
A second paragraph inside the same item.
echo "code inside a list item"A numbered item with a bullet list:
- one
- two
Definition-style list
Term One : The first definition, if your renderer supports it.
Term Two : The second definition.
Blockquotes
A simple quote.
A longer quote with formatting,
code, and a link.It even spans multiple paragraphs.
And contains a nested quote.
And one more level down.
"The best way to find out if your renderer works is to throw everything at it."
--- Somebody, probably
Alerts
Useful information that users should know, even when skimming content.
Helpful advice for doing things better or more easily.
Key information users need to know to achieve their goal.
Urgent info that needs immediate user attention to avoid problems.
Advises about risks or negative outcomes of certain actions.
Alerts can hold richer content too, like a list:
- Item one
- Item
twoconst nested = "code inside an alert";
Tables
| Feature | Supported | Notes |
|---|---|---|
| Tables | Yes | You are looking at one |
| Alignment | Yes | Left, centre, and right |
Inline code | Yes | Works inside cells |
| Formatting | Yes | Italic, |
Alignment test:
| Left aligned | Centre aligned | Right aligned |
|---|---|---|
| apple | banana | cherry |
| 1 | 22 | 333 |
| a longer cell here | mid | x |
Wide table, to test horizontal overflow on small screens:
| Column A | Column B | Column C | Column D | Column E | Column F | Column G | Column H |
|---|---|---|---|---|---|---|---|
| Lorem ipsum dolor | Sit amet consectetur | Adipiscing elit sed | Do eiusmod tempor | Incididunt ut labore | Et dolore magna | Aliqua ut enim | Ad minim veniam |
Math
Math is written in Typst syntax. Inline math sits in the flow of a sentence, like or , and should align neatly with the surrounding text.
Euler's identity, the famous one:
The quadratic formula:
The Gaussian integral:
The Basel problem:
A matrix and a determinant:
A piecewise function:
The Laplace transform, with a series expansion:
Maxwell, in potential form:
A beastly limit, to stress the layout engine:
And some inline odds and ends: , , , , and .
Programming
TypeScript
export function render(
content: string,
block: boolean,
mode: "svg" | "html",
): string {
const math = block ? `$ ${content} $` : `$${content}$`;
const doc =
`#set page(width: auto, height: auto, margin: 0pt)\n` +
`#set text(size: 18pt)\n${math}`;
compiler ??= NodeCompiler.create();
const output =
mode == "svg"
? compiler.svg({ mainFileContent: doc })
: (compiler.tryHtml({ mainFileContent: doc }).result?.body() ?? "");
const tag = mode == "svg" ? "svg" : "math";
return (
output.match(new RegExp(`<${tag}\\b[^>]*>[\\s\\S]*?<\\/${tag}>`))?.[0] ?? ""
);
}Python
from dataclasses import dataclass
from functools import lru_cache
@dataclass(frozen=True)
class Point:
x: float
y: float
def distance_to(self, other: "Point") -> float:
return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5
@lru_cache(maxsize=None)
def fib(n: int) -> int:
return n if n < 2 else fib(n - 1) + fib(n - 2)
print([fib(i) for i in range(10)]) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]Rust
use std::collections::HashMap;
fn word_count(text: &str) -> HashMap<&str, usize> {
let mut counts = HashMap::new();
for word in text.split_whitespace() {
*counts.entry(word).or_insert(0) += 1;
}
counts
}
fn main() {
let counts = word_count("the quick brown fox jumps over the lazy dog the end");
println!("{:?}", counts.get("the")); // Some(3)
}Shell
#!/usr/bin/env bash
set -euo pipefail
for file in ./posts/*.md; do
echo "Building ${file}..."
typst compile "$file" || echo "failed: $file" >&2
doneJSON, YAML, and TOML
{
"name": "my-blog",
"version": "1.0.0",
"features": ["math", "alerts", "footnotes"],
"nested": { "enabled": true, "count": 42, "ratio": 0.75, "nothing": null }
}site:
title: My Blog
serif: false
tags:
- markdown
- typst[site]
title = "My Blog"
serif = false
tags = ["markdown", "typst"]Diff
- const old = "before";
+ const updated = "after";
const unchanged = true;Typst
#set text(font: "Inter", size: 11pt)
= A Typst heading
Some *strong* text and an equation: $ integral_0^1 x^2 dif x = 1/3 $HTML and CSS
<article class="post">
<h1>Hello, world</h1>
<p>Nothing fancy here.</p>
</article>.post {
max-width: 65ch;
margin-inline: auto;
font-family: system-ui, sans-serif;
}Plain block, no language
No syntax highlighting here.
Whitespace is preserved.Long line, to test horizontal scrolling
This is a very long line of code that should scroll horizontally rather than wrap or break the layout of the page, because that is what code blocks are supposed to do when they get wide.Media
An image with alt text:
A linked image:
Raw HTML
Click to expand this collapsible section
Hidden content, which can still contain Markdown, code, and lists:
- One
- Two
- Three
Footnotes and References
Footnotes appear at the bottom of the page, like this one.[2] You can reference the same note twice.[2] Long notes can hold more structure.[3]
Reference-style links keep prose tidy: here is one and here is another.
Heading links work too: jump back to the math section or the code section.
The Finale
If you made it this far, everything rendered. Here's one last combo of everything at once:
Mix bold, italic,code,strike, a link, and math like in one place, and make sure it all still looks good.
It has a second paragraph, indented by four spaces.
```ts
const footnoteCode = "even code blocks";
```