Developer FIELD NOTES · 3 MIN READ
Markdown to HTML and Back: How Two-Way Conversion Works
Both conversion directions compared: escape-first rendering, the reverse pattern walk, and what survives a Markdown-HTML round trip.
Markdown is what you write; HTML is what the browser renders. Most converters handle that one direction and stop — but content has a habit of traveling the other way too: exported CMS pages, scraped documentation, HTML emails destined for a Markdown-based static site. A bidirectional converter makes the bridge two-way, and the two directions are surprisingly different engineering problems.
Markdown → HTML: escape first, format second
The forward pass runs through a fixed order of steps, and the first one is the safety-critical move: every <, >, and & in your input is escaped into entities before any formatting applies. Paste a snippet containing raw <b>bold</b> and it comes out as visible text — <b>bold</b> — not markup. Your Markdown is treated as text to format, never as HTML to inject. (The entity encodings doing that work are detailed in How HTML Entities Work.)
Only then do the formatting rules fire, in order: fenced code blocks, inline backticks, headings # through ######, bold and italic stars, images before links (so  doesn't get mangled into an anchor), dash and digit lists, blockquotes, and finally paragraph wrapping — blank lines split blocks, and single newlines inside a block become <br>. A small document:
# Title
Hello **world** and `code`.
comes out as:
<h1>Title</h1>
<p>Hello <strong>world</strong> and <code>code</code>.</p>
HTML → Markdown: a priority queue of patterns
The reverse direction is a different game: HTML is far larger than Markdown's vocabulary, so the converter processes a prioritized list of patterns and lets the rest fall through. Fenced <pre> blocks become triple-backtick fences (with entities decoded inside), headings become # rows, blockquotes gain a > per line, images map to  and anchors to [text](href), lists regain their dashes, and <strong>/<em> collapse back to asterisks. Ordered lists are renumbered from 1, so <ol start="5"> numbering does not carry over. Anything the pattern list doesn't recognize — <div> wrappers, attribute-bearing spans — ends with its tags stripped and its text kept:
<h2 class="x">T</h2><p title="y">Body</p>
→
## T
Body
What survives the round trip
Feed HTML through the converter and the Markdown back through again, and the supported subset is stable: headings, paragraphs, bold, italic (star form), links, images, code, blockquotes, horizontal rules, flat lists. The things that don't survive are just as important to know:
- Attributes vanish. Markdown syntax has no slots for
class,title, orid, so HTML→Markdown drops them by design. - Nested lists lose their indentation. A two-space-indented
- nestedline under a list item is not parsed as a sublist — it stays literal text after the list closes. Flatten nested lists before converting. - GFM tables aren't parsed. Pipe-table input renders as a paragraph with
<br>line breaks, and HTML tables come back as bare cell text. - Underscore italics stay literal. The forward pass converts
*star*to<em>but leaves_under_score_untouched — a deliberate ambiguity dodge, since underscores appear inside identifiers and URLs.
Why bidirectional beats two one-way tools
Round-tripping is the killer use case. Migrating a blog from an HTML CMS to a Markdown static-site generator, pulling reference docs into a wiki, or cleaning scraped pages all need the HTML→Markdown direction — and then the edited result usually needs converting forward again to check how it renders. Having both modes in one tool means you paste, flip, edit, and flip back without changing context or re-uploading. The concepts and flavors behind the syntax itself are covered in Markdown Explained.
Try it yourself
Convert in both directions with the Markdown to HTML Converter (Two-Way) — try the Title example above, then reverse it. For pure Markdown→HTML rendering, the Markdown to HTML tool stays in one mode; the Markdown Table Generator builds the pipe tables this converter intentionally leaves alone; and the HTML Entity Encoder & Decoder shows the escaped &-forms the forward pass relies on.