Convert Markdown to HTML and Back
Markdown and HTML describe the same documents at different levels of ceremony, and moving between them should be mechanical. It is — until tables, raw HTML, and ambiguous nesting appear. This guide covers both directions and the edge cases.
When to convert, and in which direction
Markdown to HTML is the publishing direction: source documents written for humans become rendered pages for browsers. Content management pipelines, static site generators, and README rendering all live here, and the conversion is well-defined — headings, emphasis, lists, links, code blocks map to their obvious HTML counterparts. HTML to Markdown is the archival direction: capturing web content into an editable, diffable, tool-friendly text form — research notes, scraped references, exported documentation. The reverse direction is harder because HTML expresses things Markdown cannot, and every converter makes lossy choices.
The decision rule follows from fidelity. If the destination is a browser and the source is prose, convert to HTML and let rendering do the rest. If the destination is a text editor, a diff, or another tool's input, convert to Markdown and accept that visual-only styling will not survive. And if the document is genuinely presentational — complex layouts, embedded components — the honest answer may be keeping it in HTML, because forcing it through Markdown round-trips erodes it a little each time. Conversion is a pipeline tool, not a storage strategy.
The core mapping, both ways
The clean correspondences are worth memorizing because they cover ninety percent of real documents. Hash headings map to heading tags, one through six. Double asterisks or underscores map to strong, singles to emphasis. Dash or asterisk bullets map to unordered lists; numbered lines to ordered lists. Bracketed text with parenthesized URLs maps to anchors, and image syntax adds the source attribute. Fenced code blocks map to pre and code elements; single backticks to inline code. Blockquotes, horizontal rules, and paragraphs follow equally directly.
The mapping acquires texture in reverse. A heading tag converts cleanly to hashes, but a heading styled with classes and IDs loses those attributes — Markdown has no attribute syntax in its core. A link with title text survives; a link with target, rel, or tracking attributes does not. Ordered lists preserve numbering in Markdown's syntax but lose start-at offsets. The working principle: structural meaning survives both directions; presentation rides along only where Markdown's syntax reaches. Knowing the boundary in advance is what separates predictable conversions from surprises discovered mid-migration.
Edge cases: tables, raw HTML, and nesting
Tables are the classic friction point. GitHub-flavored Markdown added pipe tables, but they express only simple grids — no row or column spans, no nested content beyond inline formatting, alignment via colon positions rather than attributes. HTML tables routinely exceed those limits, so HTML-to-Markdown conversion of anything beyond a simple grid either degrades gracefully — spans flattened, structure simplified — or breaks into raw text. Before converting, look at the table honestly: simple grid, it will survive; merged cells and nested lists inside cells, it will not.
Raw HTML inside Markdown is the second edge case: the CommonMark spec permits HTML passthrough, which means documents frequently contain both syntaxes interleaved. Markdown-to-HTML conversion passes raw HTML through untouched — convenient and occasionally dangerous, since untrusted Markdown with embedded script is a cross-site scripting vector if rendered without sanitization. HTML-to-Markdown converters face the inverse choice: preserve unrecognized HTML as raw blocks, keeping fidelity at the cost of Markdown purity, or drop it, keeping purity at the cost of content. Check which your converter does before trusting it with real documents.
Keeping both formats consistent
Documents maintained in both formats drift unless the pipeline enforces a source of truth. The sustainable pattern is single-source: Markdown as the edited artifact, HTML generated from it on every change, and the generated output never hand-edited. Hand-editing generated HTML is how the formats diverge — the next regeneration overwrites the edits, or worse, the edits persist and quietly contradict the source. Regeneration from source is the only synchronization mechanism that scales.
For round-trip workflows — Markdown to HTML and back, say during migrations — the discipline is diffing. Convert the source, convert the result back, and diff against the original. Differences reveal exactly what the round trip destroys: attribute losses, table degradation, whitespace normalization, link title drops. One deliberate diff review before a bulk migration beats discovering losses at document number four hundred. And where documents must remain in both forms indefinitely, regenerate on a schedule and treat divergence as a defect: the formats are two renderings of one document, and they should be provably so.
Sanitization: HTML from Markdown is still untrusted
The security posture of converted content surprises people: Markdown that passes through a renderer becomes HTML, and HTML is what browsers execute. Because CommonMark allows raw HTML inline, a Markdown document can carry script tags and event handlers straight through conversion into the page. Rendering user-submitted Markdown without sanitization is therefore the same exposure as rendering user-submitted HTML — the Markdown wrapper changes the source format, not the risk profile.
The defenses are standard but must be applied at the right layer. Sanitize the HTML output before it reaches the page, using an allowlist approach that keeps structural and inline formatting tags while stripping scripts, event handlers, and dangerous URL schemes — javascript: links survive naive conversion and deserve explicit blocking. Alternatively, configure the converter to escape raw HTML rather than pass it through, trading fidelity for safety on untrusted input. The rule of thumb: trusted content authored by your own pipeline can pass through; anything written by strangers gets sanitized, every time, no exceptions negotiated per feature.
A practical conversion workflow
The efficient sequence, Markdown to HTML: run the conversion, render the result, and review against the source with attention to the known loss points — tables, attributes, raw blocks, code fence languages. Fix problems at the source, not the output, because regeneration will overwrite output edits. For publishing pipelines, wire conversion into the build so the HTML never exists as a manually maintained artifact.
The reverse sequence — HTML to Markdown: choose a converter whose loss behavior you know, convert a representative sample first, and diff or review before bulk processing. Inspect tables, check that links kept their URLs, confirm images survived with sources, and decide the raw-HTML policy: preserve or strip. After conversion, read three documents in full — beginning, middle, and one you know well — because sampling catches failure classes that bulk metrics miss. The entire discipline takes minutes per document and converts what would be editorial archaeology into a mechanical pass. Conversion should be boring; these workflows are how it stays that way.
Frequently asked questions
Does Markdown to HTML conversion lose anything?
Core structure survives completely. Losses appear at the edges: HTML attributes, complex tables, and presentation-only styling have no Markdown equivalent.
Can I include raw HTML in Markdown?
Yes — CommonMark passes raw HTML through. That convenience is also a security risk with untrusted input, so sanitize rendered output.
Why do my tables break when converting to Markdown?
Pipe tables support only simple grids. Merged cells, spans, and nested content exceed the syntax and degrade during conversion.
Is converting HTML to Markdown reversible?
No — the reverse conversion is lossy for anything beyond simple structure. Keep the original HTML if fidelity matters.
Should I hand-edit the generated HTML?
No — edits get overwritten on regeneration. Fix the Markdown source and regenerate; single-source is the only consistent workflow.
Is rendered Markdown safe to display?
Only with sanitization for untrusted content. Raw HTML in Markdown can carry scripts through to the page.
What about links with titles or attributes?
Link titles survive in Markdown syntax; target, rel, and class attributes do not. Expect attribute loss in both directions.
How do I check a bulk conversion for losses?
Round-trip a sample and diff against the originals. One diff review before migration reveals every failure class at once.
Should my project be written in Markdown or HTML?
Markdown for prose-heavy content that benefits from clean diffs and portability; HTML or component systems for presentation-rich pages Markdown would constrain.
Is it okay to mix raw HTML into Markdown?
Sparingly, for components Markdown cannot express. When raw HTML becomes the majority, the project has outgrown Markdown as its authoring format.