What Markdown is and why it looks the way it does
Markdown is a way of writing formatted text using plain characters. It was created in 2004 by John Gruber, with Aaron Swartz contributing to the syntax, and its design goal was that a document should stay readable even before it is converted. A line that starts with # is a heading, text wrapped in double asterisks is bold, and a hyphen at the start of a line is a bullet. Because the source is just text, it works in any editor, diffs cleanly in version control, and survives being pasted into a chat window. That is why it is the default format for README files, developer documentation, static-site blogs, note-taking apps and wikis.
This page converts Markdown to HTML with a small converter written for it. You can switch the result pane between the rendered preview and the raw HTML, copy that HTML, and watch four counters (characters, lines, headings and links) plus a counter of URLs that were blocked as unsafe.
Exactly which syntax this converter handles
Every row in the table below was checked against the converter on this page. Paste any entry from the Input column into the editor to see the result.
| Syntax | Input | HTML | Notes |
|---|---|---|---|
| Headings | # H1 ... ###### H6 | h1-h6 | A space after # is required. Underlined style (=== / ---) also works |
| Bold / italic | **bold** *italic* | strong, em | __bold__ and _italic_ also work (underscores inside a word are ignored) |
| Strikethrough | ~~removed~~ | del | GFM extension |
| Lists | - item / 1. item | ul, ol | Indent two or more spaces to nest; an ordered list keeps its starting number |
| Task lists | - [x] done / - [ ] open | input[type=checkbox] | GFM extension; the boxes are disabled in the preview |
| Tables | | A | B | + |:--|--:| | table | GFM extension; colons in the delimiter row set alignment |
| Blockquote | > quoted text | blockquote | Lists and headings can be nested inside |
| Code | `code` / ```lang ... ``` | code, pre | ~~~ fences work too; contents are shown without conversion |
| Links / images | [text](url) /  | a, img | Only http, https, mailto, tel and relative paths are kept; an optional quoted title is read |
| Autolinks | https://example.com / <https://...> | a | http and https only |
| Rule / line break | --- / two trailing spaces | hr, br | A --- directly under a paragraph line becomes a heading underline instead |
Backslash escapes are also honored, so \* prints a literal asterisk. Nesting is limited to eight levels, and anything deeper is shown as escaped text instead of being converted. A table is only recognized when the header row and the delimiter row have the same number of columns.
Not supported: reference-style links ([text][1]), footnotes, definition lists, math, Mermaid diagrams, indented code blocks (use a fence instead), and raw HTML blocks. These are areas where renderers genuinely disagree, so a converter that guessed would give you a preview that fails to match your final platform.
CommonMark, GFM and the original Markdown
The original Markdown description left many corner cases open, and implementations produced different output for the same input. CommonMark is the specification written to remove that ambiguity; at the time of writing its latest version is 0.31.2, dated January 28, 2024. GitHub Flavored Markdown (GFM) is CommonMark plus a handful of extensions:
- Tables built from pipes and a delimiter row, which the original syntax never had.
- Task lists:
- [ ]and- [x]. - Strikethrough with
~~text~~. - Autolinks, so a bare address becomes a link.
- Tag filtering: certain raw HTML tags such as
script,iframeandstyleare neutralized.
This tool implements the tables, task lists, strikethrough and autolinks, but not tag filtering, because it never passes raw HTML through at all (see the safety section below).
Where the same Markdown renders differently
- Line breaks. In CommonMark a single newline inside a paragraph is just a space; you need two trailing spaces or a backslash for a hard break. Some comment and chat systems turn every newline into a break. The checkbox above the editor reproduces that second behavior.
- Raw HTML. Most renderers allow some HTML inside Markdown, but they disagree on which tags and attributes survive. This tool escapes all of it and shows it as text.
- Nested list indentation. Two spaces work in some renderers and four in others. For numbered lists, indent to the width of the marker (usually three spaces) to be safe.
- Heading spacing.
#Titlewithout a space is a heading in a few parsers and plain text in most. Always write# Title. - Table columns. A header row and delimiter row with different column counts is not a table.
Two worked examples, taken from the converter's real output
Example 1: a table with alignment. The input has a two-column header, a delimiter row using :-- (left) and --: (right), and two data rows. The converter wraps the table in a scrolling container and puts a text-align style on every header and data cell, giving two body rows of two cells each.
| Name | Score |
|:--|--:|
| Ann | 90 |
| Bob | 85 |<div class="md-table-wrap"><table>
<thead><tr><th style="text-align:left">Name</th><th style="text-align:right">Score</th></tr></thead>
<tbody>
<tr><td style="text-align:left">Ann</td><td style="text-align:right">90</td></tr>
<tr><td style="text-align:left">Bob</td><td style="text-align:right">85</td></tr>
</tbody></table></div>Example 2: a nested list. Indenting "Apple" and "Pear" by two spaces turns them into a child list inside the "Fruit" item. The result has two top-level items and two nested ones.
- Fruit
- Apple
- Pear
- Veg<ul>
<li>Fruit
<ul>
<li>Apple</li>
<li>Pear</li>
</ul></li>
<li>Veg</li>
</ul>Safety: why converted HTML should never be trusted blindly
Markdown allows HTML in the source, so turning user-supplied Markdown straight into page HTML is a classic route to cross-site scripting (XSS). Three attacks come up again and again:
- Script tags and event attributes, such as an image tag whose
onerrorattribute runs code. - Dangerous URL schemes, such as a link whose address starts with
javascript:. - Attribute breakout, where a quote character inside a URL closes the
hrefattribute and lets the attacker add new ones.
This converter handles each of them in code. It first replaces &, <, > and both quote characters with entities, so raw HTML in your input is displayed as text and never becomes an element. Link and image addresses are accepted only if they use http, https, mailto or tel, or are relative paths or anchors; anything else is replaced with #, and control characters inserted to disguise a scheme are stripped before the check. External links get rel="noopener noreferrer nofollow" and open in a new tab. The preview pane is filled with the generated HTML, so these steps are the only protection. There is no separate sanitizing library involved. In the security sample the javascript: link and the data: image are replaced with # and the "Blocked URLs" counter shows 2, while the script and image tags appear as visible text.
That is good enough for a preview tool that only ever shows your own text to you. It is not a recommendation for production code. A hand-written converter can miss unusual combinations, so if your site renders Markdown written by other people, use a maintained Markdown library together with a dedicated HTML sanitizer, and add a Content Security Policy as a second layer.
Common mistakes
- No blank line before a list. Some renderers will not start a list that touches the paragraph above. Leave one empty line.
- Mismatched code fences. Opening with three backticks and closing with two turns the rest of the document into code. If the code itself contains three backticks, fence it with four.
- Accidental emphasis. Asterisks and underscores in math or file names (
snake_case_name,2*3*4) can trigger italics. Escape them with a backslash. - Spaces or unbalanced parentheses in URLs. Encode a space as
%20. A balanced pair of parentheses inside an address is accepted, but an unbalanced one is not. - Empty image alt text.
leaves screen-reader users and broken-image situations with no information.
Limits, and when not to use this tool
This is a compact converter for the core syntax and a few GFM extensions. It does not pass the full CommonMark test suite, and complicated structures, such as code blocks inside nested lists, may render differently from GitHub or your static-site generator. An image with an external address makes your browser contact that host when the preview loads, which can reveal your IP address to it. Always do a last check in the real target, whether that is GitHub, your blog engine or your notes app, before publishing. As a general habit, do not paste passwords or personal data into any online tool; this one does not transmit your input, but it is a good rule regardless.
Putting the output to work
- Write on the left and watch the heading levels. Skipping from h1 straight to h3 hurts accessibility and document outlines.
- Open the HTML source tab to see what the converter produced, then use Copy HTML if you need the markup. Remember that whatever site receives it will apply its own sanitizing rules.
- For a README or wiki page, confirm in the target renderer that tables, task lists and line breaks match.
- Check length limits with the word counter, compare two drafts with the text diff checker, and normalize headings or titles with the text case converter.
- If your Markdown embeds JSON samples, tidy them first with the JSON formatter.
Frequently Asked Questions
Can I copy the generated HTML?
Yes. Open the "HTML source" tab to read it, or press "Copy HTML". When you paste it into another site, that site's own sanitizer decides which tags and attributes survive.
How do I make a table?
Write the header as | Col 1 | Col 2 |, then a delimiter row such as |--|--|, then the data rows. In the delimiter row, :-- aligns left, :-: centers and --: aligns right. Every row needs the same number of columns as the header.
Can I put HTML tags in my Markdown?
Not here. For safety this tool shows HTML tags as literal text instead of rendering them. Renderers such as GitHub keep an allowed subset and strip the rest, and the allowed subset differs between platforms, so test on the platform you are publishing to.
Why do my lines run together into one paragraph?
In CommonMark a single newline does not start a new line. End the line with two spaces, or leave a blank line to start a new paragraph. You can also tick "Keep line breaks as <br>" above the editor to see how a newline-sensitive system would display it.
Is my text sent to a server?
No. The conversion is done by a script running in your browser tab, and your input is not uploaded. The one exception is an image link: if your Markdown points to an external image, the preview loads it from that address.
Should I write in Markdown or HTML?
Markdown is quicker for text-centered documents such as READMEs, blog posts and notes. HTML is better when you need exact layout, colors or forms. Many platforms let you mix a little HTML into Markdown, but only where their renderer allows it.