DEV Community

Cover image for My HTML-to-Markdown converter taught me that Markdown flavor is a contract, not a style
InApp
InApp

Posted on Originally published at imapp.blogspot.com

My HTML-to-Markdown converter taught me that Markdown flavor is a contract, not a style

I built the HTML-to-Markdown API with options for heading style (atx vs setext), bullet marker, code fence style, and emphasis delimiters — thinking they were cosmetic. Then a user's RAG pipeline silently broke.

Their chunker split documents on ## headings (atx). My API defaulted to setext (=== underlines) because it looked cleaner in raw output. Every converted page came back with zero atx headings, so the chunker merged entire docs into one context window. No errors, no warnings — just retrieval quality that quietly tanked. It took them three days to notice chunks were 40k tokens.

The lesson: when an API emits Markdown, the delimiter choice is part of the interface. A downstream parser has opinions about * vs _, about ~~~ vs , about - vs *. If you don't expose those switches, you've made the decision for someone else's pipeline and they won't find out until something downstream misbehaves.

Now I treat the options as the product. Default to the most widely parsed flavor (atx, -, fenced code), and let callers match whatever their consumer expects. Same bytes of content, different contract.

Packaged here: https://x402.freeq.one/tools/html_to_markdown.html

Top comments (0)