Step 1 of 5 · Reading · ~3 min
Read
Production Concerns
Extensions: Tables & Strikethrough
CommonMark is deliberately small. It standardises the constructs everyone already agreed on and stops there — no tables, no strikethrough, no task lists. Everything beyond that is an extension, and knowing which layer a feature lives in is the difference between portable Markdown and Markdown that only renders on one site.
Three layers, not one
| Layer | What it defines | Examples |
|---|---|---|
| CommonMark core | the base grammar | headings, lists, code, links |
| GFM (a formal spec) | five additions on top of core | tables, strikethrough, task lists, extended autolinks, disallowed raw HTML |
| Renderer features | one product's behaviour | footnotes, callouts, mermaid fences, LaTeX math |
A parser that claims "GFM support" owes you exactly those five things. Anything in the third row is a promise made by a website, not by a specification — which is why the same document looks different on a wiki, in a chat client, and in a static site generator.
Strikethrough
~~deleted~~ becomes <del>deleted</del>. The GFM spec accepts a matching pair
of one or two tildes, so ~deleted~ also works on GitHub; two is the
portable form because plenty of CommonMark-only parsers implement neither.
Tables
| Name | Age |
|:------|----:|
| Alice | 30 |
The header row is ordinary text until the delimiter row under it proves
otherwise. That row is the disambiguator: without it, | a | b | is just a
paragraph that happens to contain pipes. Colons in the delimiter cells set the
alignment — leading colon left, trailing colon right, both center, neither
default.
The trap that costs an afternoon
Inline transforms rewrite the string you are still scanning. Each pass can walk straight back into the HTML the previous pass produced:
Look at what the first line did: the emphasis pass matched an asterisk that was
left over from the strong pass and one that came after a closing tag, so it
wrapped </strong> inside an <em>. The tags are now interleaved and the HTML
is invalid. Stashing each finished fragment behind a placeholder makes later
passes structurally unable to see it.
Your exercise
Apply inline code, strong, em and strikethrough, in that order.
The mistake the grader catches is exactly the one above. A hidden test feeds
~~outer **inner *deepest*** end~~ and expects
<del>outer <strong>inner *deepest</strong>* end</del> — with a literal
asterisk surviving in the middle. Substituting in place produces interleaved
<em> and </strong> tags and fails.
The second trap is running strikethrough before inline code: a test contains
`~~code~~` next to real strikethrough on the same line, and the tildes
inside the backticks must stay literal. Stash the code span first and the rest
of the passes cannot reach it.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…