Markdown to HTML

Markdown is a shorthand for HTML. Every construct maps to specific elements, and knowing the mapping explains most of markdown's odder rules — why blank lines matter, why alt text is not a caption, why indentation nests.

The right-hand column below is the converted HTML, rendered. Copy any snippet into a paste to get the same result.

Headings become h1 to h6

One hash per level. The count of hashes is the heading level, so four hashes give you an h4.

You write
# Becomes h1
## Becomes h2
### Becomes h3
You get

Becomes h1

Becomes h2

Becomes h3

Most converters also generate an id on each heading so you can link to it — that is what powers a table of contents.

Blank lines become paragraphs

Text separated by a blank line becomes separate p elements. A single newline inside a paragraph is collapsed to a space.

You write
First paragraph, which
continues on this line.

Second paragraph.
You get

First paragraph, which continues on this line.

Second paragraph.

This is the rule that surprises people moving from a word processor: your line breaks are suggestions, blank lines are structure.

Emphasis becomes em and strong

Not i and b. The distinction is semantic: em and strong carry meaning for screen readers, italic and bold are only visual.

You write
*emphasis* becomes em

**strong importance** becomes strong

~~struck~~ becomes del
You get

emphasis becomes em

strong importance becomes strong

struck becomes del

Lists become ul, ol and li

Bullets produce an unordered list, numbers an ordered one. Indentation nests one list inside another li.

You write
- becomes ul > li
- second item
  - nested becomes ul > li > ul > li

1. becomes ol > li
2. second item
You get
  • becomes ul > li
  • second item
    • nested becomes ul > li > ul > li
  1. becomes ol > li
  2. second item

Code becomes code and pre

Inline code is a bare code element. A fenced block is a pre wrapping a code element, which is what preserves whitespace.

You write
Inline `code` becomes a code element.

```javascript
// A fence becomes pre > code
const html = render(markdown)
```
You get

Inline code becomes a code element.

javascript
// A fence becomes pre > codeconst html = render(markdown)

The language after the fence usually becomes a class like `language-javascript`, which is the hook syntax highlighters use.

Tables become table, thead and tbody

The header row becomes thead with th cells, body rows become tbody with td cells. Alignment colons become inline styles or align attributes.

You write
| Markdown | HTML |
|:---------|-----:|
| header row | thead > th |
| body row | tbody > td |
You get
MarkdownHTML
header rowthead > th
body rowtbody > td

Blockquotes become blockquote

Angle brackets wrap content in a blockquote. Nesting them nests the elements, and markdown inside still converts.

You write
> Becomes a blockquote
>
> > Nested becomes a blockquote inside a blockquote
You get

Becomes a blockquote

Nested becomes a blockquote inside a blockquote

Raw HTML passes through

Markdown is a superset of HTML — anything the syntax cannot express, you write directly, and the converter leaves it alone.

You write
<details>
<summary>Passed through untouched</summary>

Markdown inside still converts, given a blank line.

</details>
You get
Passed through untouched

Markdown inside still converts, given a blank line.

Pass-through is why converting untrusted markdown to HTML is a security decision. Anything user-supplied needs sanitising, or a script tag rides straight through.

Convert and share

Paste markdown and get a rendered page at a shareable link. Add /raw to any paste URL to get the original markdown source back.