Full CommonMark is a large spec — tables, nested lists, footnotes, definition lists, raw HTML blocks, and a long list of edge cases around when a blank line does or doesn't end a paragraph. A lightweight converter that doesn't pull in a real Markdown engine will cover the common 90%: headings, bold/italic, inline code, fenced code blocks, links, images, single-level lists, blockquotes, and horizontal rules. If your input uses anything outside that list, it either passes through as literal text or renders wrong — worth knowing before you assume the tool is broken.
What doesn't work here
- Tables — the
| col | col |pipe syntax isn't parsed at all; it comes through as a literal paragraph of pipe characters. - Nested lists — a sub-list indented under a list item stays flat; it doesn't become a nested
<ul>. - Raw HTML passthrough — dropping a literal
<div>into your Markdown gets HTML-escaped and shown as text, not rendered as an element.
Supporting all three properly means either writing a much larger parser or depending on a real CommonMark library. For a converter meant to handle a paste-and-convert README or a quick doc, the tradeoff favors staying small and dependency-free over full spec coverage.
Links and images are filtered, not just rendered
[click me](javascript:alert(1)) looks like a normal Markdown link, but the URL scheme matters: only http:, https:, mailto:, and relative/anchor links (/path, #section, ./file) are allowed through. A javascript: or data: URL gets replaced with # instead of being rendered as-is. That's not a Markdown-spec rule — it's because the converted HTML gets inserted directly into the page, and an unfiltered javascript: link in that position is a real place to pick up an XSS bug, not just a theoretical one.
An unterminated code fence eats the rest of the document
Open a fenced code block with ``` and forget the closing fence, and every line after it — headings, lists, everything — gets treated as code content, because the parser is still looking for the line that closes the block. If output after a certain point in a long document looks completely wrong, scroll back up and check for a fence that never got closed before assuming something else is broken.