DevKitHub

Programming

Markdown Preview — Live Markdown to HTML

Type or paste Markdown to see it rendered beside the source, then copy or download the HTML. GitHub’s extensions are on by default, and raw HTML is shown as text until you allow it.

29 lines
Previewsandboxed

4 headings · 99 words

HTML
Heading anchors (4)
  • acme-sync#acme-sync
  • Install#install
  • Commands#commands
  • Roadmap#roadmap

This tool runs entirely in your browser. Your input is never uploaded, stored or logged.

How it works

The renderer follows CommonMark 0.31.2 the way the specification itself lays out, in two passes, and with GitHub extensions off and raw HTML allowed, every one of the spec’s 652 examples produces its reference HTML exactly. The first pass reads the text line by line into blocks. Block quotes and list items are containers, and a line stays inside one only if it carries that container’s marker: a > for a quote, enough indentation for a list item. A line without the marker can still continue an open paragraph, which the spec calls laziness, and is why an unindented line under a list item joins its text. Link reference definitions are collected as paragraphs close, so a link can use a definition written further down. The second pass turns each block’s text into inlines, with the spec’s delimiter-run rules for emphasis: that is why snake_case_name stays literal while un*frigging*believable turns italic.

With GitHub extensions on, the parser adds what the GFM specification defines and cmark-gfm, the library GitHub runs, implements: tables with alignment colons and \| for a literal pipe, strikethrough with one or two tildes, task list items, bare www., http:// and https:// addresses and email addresses turned into links with trailing punctuation left out, and, when raw HTML is allowed, the tag filter that escapes <script>, <style>, <iframe> and six other tags. Each heading also gets GitHub’s anchor id: lowercase, punctuation removed, spaces turned into hyphens, and -1, -2 added to repeats, so a link written for GitHub such as #install points at the same heading here. Not supported, because GitHub adds them on top of GFM rather than GFM defining them: footnotes, alerts such as > [!NOTE], emoji shortcodes, math, Mermaid diagrams and @mentions.

CommonMark does not sanitise anything: raw HTML passes straight through, and javascript:alert(1) is a valid link destination. So by default raw HTML is shown as text, and javascript:, vbscript: and data: destinations are removed, apart from data: URLs for PNG, GIF, JPEG and WebP images; a warning counts each. Allowing raw HTML gives you exactly what CommonMark specifies. Either way the preview is drawn in an iframe with an empty sandbox attribute, so no script in it can run and it cannot read or reach this page. The HTML you copy is not sandboxed. If other people’s Markdown ends up on your site, sanitise the output there with an allowlist sanitiser rather than relying on the renderer.

Common problems

Every example below is run against this tool in our test suite, so what it says here is what the tool actually does.

#Heading shows as a line of text, not a heading.

Why:
An ATX heading needs a space, or the end of the line, after its #s. Without one the line is a paragraph, which is also what keeps a #hashtag or an issue number such as #42 at the start of a line from becoming a heading.
Fix:
Put a space after the #s: # Heading.

The table shows as plain text, pipes and all.

Why:
A GFM table needs a delimiter row directly under the header row, with the same number of cells. | a | b | over | --- | has two header cells and one delimiter cell, so it is not a table, and GitHub does not warn you either.
Fix:
Give the delimiter row one ---, :--, --: or :-: per column. Leading and trailing pipes are optional; the counts are not. Body rows may be shorter (they are padded) or longer (the extra cells are dropped, with a warning here).

snake_case_name stays as typed, but un*frigging*believable turns italic.

Why:
CommonMark lets an underscore open or close emphasis only at the edge of a word, so identifiers with underscores in them are not mangled. An asterisk has no such rule and works inside a word.
Fix:
Use * for emphasis inside a word. To keep a * or _ literal, escape it as \* or \_, or put code in backticks.

A line such as "1986. A great year" becomes a numbered list starting at 1986.

Why:
A number followed by a full stop or ) and a space starts an ordered list, and the list keeps that number as its start. Directly under a line of text it is safe, because only a list starting at 1 may interrupt a paragraph.
Fix:
Escape the full stop: 1986\. A great year.

A link with a space in its URL shows as [text](my file.md).

Why:
A link destination ends at the first space, so what follows no longer fits the (destination "title") form and the whole construct is left as text.
Fix:
Write the space as %20, or wrap the destination in angle brackets: [text](<my file.md>).

**bold** inside a <div> is not bold.

Why:
An HTML block runs until the next blank line, and everything in it is raw HTML, not parsed as Markdown. With <div> on one line and Markdown on the next, the Markdown is part of the HTML block.
Fix:
Leave a blank line after <div> and before </div>, and the Markdown between them is parsed as usual. Raw HTML also has to be allowed for the <div> to render at all.

Lines typed one under another run together into one line.

Why:
A single line break inside a paragraph is a soft break, which HTML displays as a space. It lets you wrap long lines in the source without changing the output.
Fix:
End the line with two spaces or a backslash for a line break (<br>), or leave a blank line to start a new paragraph.

Frequently asked questions

Is this the same as GitHub’s Markdown?
It implements the same specification, GFM, the way cmark-gfm does, so tables, task lists, strikethrough, autolinks and heading anchors come out as they do on GitHub. GitHub then adds features that are not part of GFM — footnotes, alerts such as > [!NOTE], emoji shortcodes, math, Mermaid diagrams, @mentions and issue links — which are not rendered here. GitHub also cleans raw HTML against an allowlist, where this tool either shows it as text or, if you allow it, passes all of it through.
What is the difference between CommonMark and GitHub Flavored Markdown?
CommonMark is the specification that settles what the original Markdown description left open: where a list ends, when emphasis closes, how HTML blocks behave. GFM is CommonMark plus five extensions: tables, task list items, strikethrough, extended autolinks and a filter for dangerous HTML tags. Turn off GitHub extensions to see strict CommonMark 0.31.2.
Why is my HTML shown as text?
Because raw HTML is off by default. CommonMark passes HTML through unchanged, which on a web page means running any script in it. Turn on Allow raw HTML to render it; the preview is a sandboxed frame, so a script there still cannot run.
How do I get the HTML?
Copy gives you the HTML fragment exactly as the HTML tab shows it, ready to paste into a template. Download saves it as a complete .html page with the same readable styles as the preview.
Is my Markdown uploaded anywhere?
No. It is rendered in your browser and never sent to a server. Images your Markdown links to are loaded from their own addresses, as they would be on any page.

Last updated