MD091 - Markdown inside an HTML block renders as literal text¶
Aliases: no-markdown-in-html
This rule is opt-in. Enable it with extend-enable = ["MD091"] in the [global]
section of your config.
What this rule does¶
Reports a link or an image written inside an HTML block, where CommonMark does not parse it. The line renders as the characters you typed, brackets and all.
Why this matters¶
A centered banner is the usual way to meet this. It looks like it should work, and every part of it is valid on its own:
<div align="center">
<img src="../logo.png" width="200">
<br>
[Documentation](https://example.com/docs) | [Changelog](CHANGELOG.md)
</div>
The two links there are published as [Documentation](https://example.com/docs) |
[Changelog](CHANGELOG.md). Nothing warns about it: the markdown is well formed,
the HTML is well formed, and the failure is that the two were combined.
The reason is CommonMark's HTML block. A line starting with <div> (or another
block-level tag) opens a block that runs until a blank line, and inside it every
line is passed through to the output untouched. So the block above extends from
<div align="center"> through </div>, and the links sit inside it.
This is easy to get wrong in the other direction too. Inline HTML does not do
this, so the same links after a <span> render normally, and an author who has
seen one case work is likely to assume the other does as well.
The remedy is a blank line, which ends the block and returns the rest to markdown:
<div align="center">
<img src="../logo.png" width="200">
[Documentation](https://example.com/docs) | [Changelog](CHANGELOG.md)
</div>
Note how little separates the two. The blank line is the whole difference between a working banner and a broken one, and neither version looks wrong on its own.
Examples¶
Incorrect¶
Correct¶
A blank line after the opening tag ends the HTML block, so the markdown below it is markdown again:
Inline HTML opens no block at all, so nothing in this line is affected:
Writing the link as HTML is equally correct, and is what the surrounding block already is:
Configuration¶
This rule has no options.
What this rule leaves alone¶
The test for a finding is whether the construct would have rendered differently outside the block. Several shapes fail that test and are silent.
Reference links whose label is not defined. [text][ref] is a link only when
ref has a definition somewhere in the document. Without one it is literal text
in both contexts, so the HTML block broke nothing:
This is what separates a real dead link from the bracket grammar that fills HTML
tables in reference documentation, where [ a | b ] and [a-z][0-9] are common
and none of it is a link. A reference link with a definition is reported, because
that one really would have resolved:
Anything inside a tag. <div title="see [docs](/docs)"> puts the construct in
an attribute value, which no markdown parser reads in any context.
<code> elements and backtick spans. An inline <code> element does not stop
markdown, so <code>[a](b)</code> outside a block genuinely does produce a link
inside the code element, and a backtick span outside a block genuinely does become
<code>. Both are nevertheless left alone, because an author who wraps a
construct in either is asking for it to be shown rather than followed, and inside
the block that is what they get. Reporting a broken link there would name the
wrong problem.
Raw-text elements. pre, script, style and textarea hold literal text by
design, so markdown-looking characters in them are content:
markdown="1" containers. kramdown, Python-Markdown and MkDocs parse those
bodies as markdown, so for those users the markdown really is markdown:
HTML comments. Nothing inside one reaches the page.
Only links and images are reported. Emphasis, headings, lists and other constructs are also inert inside an HTML block, but they degrade to text that still reads correctly, while a link degrades to a URL the reader cannot follow.
Automatic fixes¶
None. A blank line after the opening tag is usually what the author wanted, but
not always: it splits one HTML block into two, which changes what CSS selectors
and align attributes apply to, and in a <table> it produces invalid markup
that browsers relocate. Converting the link to an <a> tag instead is a
different document. Which of those is right depends on what the block is for, so
the choice stays with the author.
Related rules¶
- MD033 - No inline HTML, for projects that would rather not have the HTML at all
- MD034 - No bare URLs, another rule about links that do not render the way they were written
- MD042 - No empty links, for links that render but go nowhere