Markdown flavours and a crash-proof writing workflow

CommonMark, GitHub Flavored Markdown and the rest: which syntax works where, with real parser output, and a draft workflow a closed tab cannot destroy.

On this page

Markdown is plain text that turns into formatted text: **bold** becomes bold, a line starting with # becomes a heading. It is the default for README files, issue trackers, chat apps, note-taking tools and static site generators. The catch is that there is no single Markdown. This article explains the main flavours, shows how one parser treats the cases that differ between them (with real output from the parser behind our Markdown editor), and describes a writing workflow that does not lose work when a browser tab closes.

A short history of the flavours

John Gruber published Markdown in 2004, with help from Aaron Swartz, as a Perl script and a syntax description. The description left many cases open (what exactly ends a list? can emphasis start in the middle of a word?), and every implementation answered them differently. Three flavours matter today:

  • CommonMark (from 2014) is a precise specification with hundreds of examples, written to settle those open cases. Most modern parsers follow it.
  • GitHub Flavored Markdown (GFM) is CommonMark plus extensions: tables, task lists, strikethrough with ~~, and URLs that become links without angle brackets. Its specification is published by GitHub. Many tools that say "Markdown" mean roughly this.
  • Extended dialects such as Pandoc's Markdown and MultiMarkdown add footnotes, definition lists, citations and metadata blocks, and are common in academic and book publishing.

If you write for one platform, use its flavour. If a text has to work in several places, stick to the CommonMark core plus GFM tables and task lists, which almost everything now supports.

Cases that differ, with real output

These come from the parser our editor and our Markdown to HTML converter share, which follows CommonMark for the core and supports the common GFM extensions.

Single line breaks. In CommonMark a single newline inside a paragraph is a soft break: line one then line two on the next line renders as one paragraph, the newline kept as a space. Some chat apps and older GitHub comments turned every newline into a <br>. To force a line break portably, end the line with two spaces (or a backslash): line one␣␣ gives line one<br />line two.

Underscores inside words. snake_case_name stays as written in CommonMark, because an underscore between letters cannot open emphasis. An asterisk can: *a*b gives <em>a</em>b. Gruber's original script italicised parts of underscored names, which is why older documents look broken in new tools.

Tables and task lists are GFM. This:

| a | b |
|:--|--:|
| 1 | 2 |

gives a table with the first column left-aligned and the second right-aligned, and - [ ] todo / - [x] done gives two disabled checkboxes, the second ticked. A strict CommonMark parser without extensions shows both as plain text.

Raw HTML. CommonMark passes HTML through; GitHub filters some tags. Our parser is stricter: <b>hi</b> is shown as text, &lt;b&gt;hi&lt;/b&gt;, so pasted content can never run script. If you need HTML in your output, write it in the exported file afterwards.

Footnotes and reference links (text[^1], [ref][x]) are Pandoc and MultiMarkdown features, and GitHub added footnotes later. Our parser does not support them and shows them as typed, which is better than silently dropping them, but worth knowing before you write a long document that depends on them.

Loose and tight lists. A blank line between items (* a, blank, * b) makes a loose list, and each item's text is wrapped in its own <p>: more vertical space. Remove the blank lines for a compact list. This is the most common "why is my list so spaced out?" surprise.

A workflow that survives a crash

Most lost writing is lost in a browser tab: a mistaken close, a crash, a laptop that runs out of battery, a page that reloads after an update. A workflow that survives this has three layers.

  1. Autosave locally while you type. Our editor saves the text in the browser's local storage every time you pause for about half a second. Close the tab, reopen the editor, and the draft is restored with a message saying so. Nothing is sent to a server. Two limits to know: the draft lives in that browser on that device, and clearing site data erases it. Some private windows refuse storage entirely; the editor tells you when saving fails instead of failing silently.
  2. Download a real file at milestones. Ctrl or ⌘ S downloads the .md named after your first heading ("Meeting notes" becomes meeting-notes.md). A file in your documents folder is backed up with everything else and opens in any text editor in twenty years.
  3. Export the format the reader needs, last. A .html page for the web or an email, or a PDF through the print dialog (the editor prints only the rendered document, black on white, avoiding page breaks inside tables and code blocks). Keep the .md as the source; regenerate exports from it rather than editing them.

Common mistakes

  • Mixing flavours in one document. Footnotes written for Pandoc appear as raw [^1] on GitHub. Decide where the text will be read first.
  • Relying on single newlines for line breaks. They work in some apps and not in others. Use a blank line for a new paragraph and two trailing spaces for a break.
  • Indenting nested lists with too few spaces. A sub-item must be indented to line up with the text of its parent item (two spaces after - , three after 1. ), or it becomes a separate list.
  • Writing a long document only in a web form. Text areas on most sites keep nothing when the tab closes. Draft in an editor that saves, then paste.
  • Trusting autosave as a backup. Local storage is a safety net for crashes, not an archive. Download the file.

The editor's toolbar and shortcuts (B, I, K, E with Ctrl or ⌘) insert the syntax for you, and the live preview shows immediately which flavour rule you have run into.

Tools mentioned in this article

Back to the blog