What Markdown to HTML conversion does
The converter reads Markdown syntax and emits HTML tags. A # Heading becomes , a - list becomes , and backticks become . The point is to let you write in plain text and publish structured HTML without hand-coding tags. Good converters also escape special characters in code blocks so your snippet shows as code instead of being interpreted as markup.
That escaping detail hides where conversions actually go wrong: headings, paragraphs, and links convert identically in every tool on earth; the failure zone is dialect features, indentation, and raw HTML.
There is no single "Markdown" standard
"Markdown" is a family of dialects, not a standard. The closest thing to a common core is the CommonMark spec — currently version 0.31, built from roughly 650 worked examples that pin down exactly how ambiguous input should parse, including decade-old arguments like whether underscores inside words count as emphasis (they do not).
GitHub-Flavored Markdown, usually abbreviated GFM, extends CommonMark with four well-known additions: pipe tables, strikethrough (~~like this~~), task lists (- [x] done), and autolinks for bare URLs. Those extensions are why GFM exists as its own formal specification — GitHub needed them and strict CommonMark deliberately left them out. Pandoc Markdown adds citations and footnotes; kramdown, Jekyll's default, has its own attribute syntax.
The practical consequence shows up the moment you switch tools. A task list item like - [ ] Ship the beta is a checkbox on GitHub and literal bracket text on a strict CommonMark converter; a pipe table is a table under GFM and three disconnected paragraphs elsewhere. When output looks wrong, the cause is almost never a bug — it is a dialect mismatch.
Block vs inline: why the blank line matters
Markdown divides every element into two classes. Block elements — headings, paragraphs, lists, code blocks — need surrounding blank lines. Inline elements — bold, links, code spans — live inside a line. This is why two paragraphs without a blank line between them merge into one in the output.
Three block-level traps cause most of the damage:
- Nested list indentation. To nest a bullet, indent it to align with the parent item's text — two spaces under a
-marker. But an ordered list marker like1.is three characters wide, so its children need three spaces. Four spaces is the classic accident, because in CommonMark four spaces of indentation means "code block" — a nested list over-indented by one space renders as literal code in the middle of your list. - Reference-style links. Instead of writing
[our pricing](https://example.com/pricing?ref=x&lang=y)inline, you write[our pricing][pricing]and collect[pricing]: https://example.com/pricing?ref=x&lang=yat the bottom of the document. The prose stays readable, and one definition can serve ten links. Documentation teams live on this syntax; most blog writers never learn it exists. - Loose vs tight lists. Blank lines between list items produce "loose" lists, where each
wraps its content intags; no blank lines produce "tight" lists. The rendered spacing differs, and some CSS themes style one and not the other.
Why "no upload" matters for drafts
Your drafts are unfinished thinking — internal notes, client copy, unpublished ideas. Pasting them into a converter that uploads the text means a copy lands on someone else's server, possibly indexed or logged. A browser-based converter transforms the text on the page and never sends it anywhere, so your half-formed work stays yours until you choose to publish it.
This is not a theoretical worry for anyone doing contract or product work. Unreleased feature names in a doc, a client's legal-review comments, an embargoed announcement — a paste into the wrong tool can leak all of them, silently. And plenty of "free converter" sites are lead-generation operations: the converter is the hook, the paste is the product.
When you need it
- Blog posts written in Markdown but published on an HTML CMS — WordPress classic editor, custom HTML blocks, and most headless CMS rich-text fields.
- Documentation where you author in plain text and ship HTML — support portals accept HTML blocks but rarely Markdown files.
- Email templates built from Markdown source — email platforms almost never accept Markdown natively, so a conversion step is mandatory.
- README and notes that need to render in a viewer that expects HTML.
- Any paste where hand-writing tags would be slow and error-prone.
The reverse case: if your platform accepts Markdown natively — Ghost, static site generators like Hugo and Jekyll — do not convert; every conversion is a chance for a dialect mismatch.
How to convert well
Paste valid Markdown and confirm the converter handles the features you use: headings, lists, links, images, tables, and fenced code. Check that code blocks are escaped so they display literally. Watch for raw HTML you included — some converters pass it through, others strip it. After conversion, glance at the output for unclosed tags before you drop it into a page.
Why two converters disagree on the same input
Extension support is the first cause, as covered above: tables and task lists simply do not exist in strict CommonMark. The second cause is whitespace handling:
- Indented code blocks vs fenced code blocks. CommonMark treats any line indented four or more spaces as a code block — legacy behavior from Markdown's original design. Fenced code, three backticks before and after, is unambiguous and survives copy-paste. Indent a nested list with four spaces per level and every level past the first is one alignment error away from becoming code. Prefer fences for anything important.
- Soft line breaks. In spec-compliant Markdown, a single newline inside a paragraph renders as a space; GitHub comments and some wikis render it as a hard break instead. Paste GitHub-formatted text into a strict converter and your carefully broken lines merge.
The security check: raw HTML and XSS
This is the check most people skip and should not. CommonMark explicitly allows raw HTML inline — that is a feature, not a bug. It means any , , or tag in your source can pass straight through a converter into the published page. Conversion and sanitization are two separate steps, and many plain converters only do the first.
The GFM spec itself defines a "disallowed raw HTML" extension that strips a short list of the most dangerous tags — script, iframe, style, textarea, and a few others — but only some renderers enable it. The widely used markdown-it library ships with raw HTML disabled by default and requires an explicit opt-in to allow it.
What this means in practice:
- Your own Markdown into your own CMS: platforms like WordPress sanitize HTML for non-admin users through their kses filter. Note the gap — administrator accounts bypass that filter, which is why a compromised admin login escalates into stored XSS across the whole site.
- Anyone else's Markdown: contributor submissions, AI output, forum snippets. Run it through a converter that strips HTML, or scan the output for