Please don’t write your documentation in Markdown. Please. I’m begging you.

Markdown is tolerable for short documentation, like a readme.md. Past that, it’s the wrong tool for the job.

Markdown is about formatting, not information

Markdown is just a way to write simpler, nice looking HTML. There is direct mapping between _foo_ and <em>foo</em> . This is why people use it: it’s easy to learn and it’s easy to write a kinda okay markdown parser in any programming language.¹

Markdown cannot carry data. There’s no way to imbue properties into text using markdown. Good documentation is all about the semantic markup. A “definition” is not just a different formatting or like. It means there’s actually a concept of a “definition” as a discrete concept in your documentation. You should be able to hide all the definitions if you want or show only the definitions. You should be able to mark several code samples as doing the same thing in different languages. You should be able to generate the documentation with and without “TODO” sections, so you can share separate versions internally and externally. You can’t do this if all you have to work with is formatting information.

Most documentation systems for Markdown accept this. They usually add their own extra bits of flavor to enable more sophisticated content markup. This leads to a thing we are not writing in Markdown but a Markdown dialect consistent rules.

Not extendable

In Markdown you have three kinds of formatting: bold, italics, and code . What if you want to have some things in the documentation be colored blue? You can’t! The best you can do is change the CSS for <em> , but then you lose italics.

The way you’re “supposed” to extend markdown is by adding in raw HTML. HTML is interpreted as HTML inside of a Markdown document. But the entire point of Markdown is to avoid having to write HTML in the first place! You can’t even “hybrid” it by wrapping existing Markdown with HTML, since anything inside HTML tags won’t be parsed as Markdown.

As before, people try to fix this with Markdown “extensions”. Most modern processors support tables. But these extensions are directly added to the Markdown engine, not as part of an “extensibility” feature of Markdown. If you want to have a new thing, you have to modify the code of the engine. Like, say, images with a caption. That’s not part of the Markdown spec!

Local processing only

Markdown is a strictly local kind of formatting. One of the reasons Markdown is so simple is so that you can parse it in a single pass. But this also means that you can’t talk about the documentation as a whole. Markdown provides no natural way to have a reference in one page and automatically link a cross-reference in another page. The best you can do is hardcode the url path in a Markdown link. You also can’t do things like “collect all of the definitions into a glossary page” or “have two callout boxes alias the same text”.

Once again, this is a known problem with Markdown documentation, and most static generators add a layer of preprocessing to deal with that. Hugo uses {% ref link %} to mean cross-references. In Github Wiki, you can write [[text|reference]] to refer to another page. But both of these tie the reference name to the header name, meaning that if you fix a typo in the header name you also break the link.

All of these extra levels of syntax are working against Markdown, not with it. The preprocessor syntax is not a first-class entity in the Markdown framework. You’re much better off using something that is designed for global content in the first place.

HTML Only

Markdown is good for generating HTML and terrible for making PDFs.²

(Side rant: please, please, PLEASE make your documentation viewable offline. If not a PDF, at least provide a download link for the docs.)

What to use instead

LaTeX.

Kidding. LaTeX is extremely powerful but also a nightmare to use and almost impossible to turn into online documentation.

A better answer is reStructuredText or RST. This is almost always used with the Sphinx documentation generator. It gets around the issues markdown has by having special syntax for semantic properties and extensions. Sphinx uses them to add cross-documentation references without having to add a second layer of preprocessing syntax.

# Document 1 .. _reference: Title ----- # Document 2 Please see :ref:`reference` for more.

You can add all sorts of other stuff, too, like show/hide sections or embed math. The downside to RST is that it’s more complex than Markdown, and then Sphinx as more complexity on top of that.³ But I think good documentation is worth the effort.

I’ve also heard of AsciiDoc, which seems perfectly fine too. There’s probably others that I don’t know about, but you really can’t go wrong with anything that gives you both custom properties and extensions. So something that’s not Markdown.

I wrote learntla and Practical TLA+ in Markdown. Don’t make my mistakes. Don’t write your documentation in Markdown.

¹ But not a correct one. The Commonmark Specification is over 20,000 words long.

² Pandoc helps here.