Markdown, Asciidoc, or reStructuredText – a tale of docs-as-code
dewanahmed.com
dewanahmed.com
1. We get a _lot_ of casual contributors to MDN: about 180-200 unique contributors/month, most of whom we never see again. Almost all of them can contribute much more easily with Markdown than with anything else. Many of these people are unlikely to put even an half an hour into learning a new syntax.
2. Markdown has great tooling support. For example, if we want to run Prettier over our embedded code samples, it's really easy if we are in Markdown. If we are in Markdown we will get nice formatting just about everywhere, including GitHub of course and most people's editors.
One thing that made the choice easier for us is that MDN's a very mature doc site, so we had a very good idea of which Markdown limitations were likely to be a problem for us.
If you're interested, we blogged about this project: https://openwebdocs.org/content/posts/markdown-conversion/.
I'll take the opportunity to do a shameless plug for the amazing "Markedly Structured Text", or MyST, a markdown flavor that is both easy to write like markdown, and expressive like rst.
Basically, if you know markdown, you can write decent MyST already. In fact, any markdown is valid MyST and .md is a valid file extension for MyST.
Once you want more, the syntax offers richer construct, but still easy enough to use.
Check it out: https://myst-parser.readthedocs.io/en/latest/syntax/syntax.h...
I wanted to love asciidoc because the format rocks, but it never took off and the tooling is still lacking. MyST piggy back on markdown ecosystem, this is less of a problem.
Also, the devs behind it also have a very good track record at creating a good FOSS ecosystem.
but I think https://myst-parser.readthedocs.io/en/latest/syntax/syntax.h... is misguided; AFAIK <!-- commentary --> is legal in markdown and far less likely to surprise someone, both with an abnormal comment character as well as the forced block break
But so far I never needed to.
> And are there implementations in other languages?
That's the probably the biggest limition for myst: for now it's very new and is only implemented in Python.
I supposed it's a good opportunity to learn rust by creating a parser :)
After a few years, I gave up and switched from rST and Sphinx to Markdown and MkDocs [2]. We addressed the limitations of Markdown with PyMdown Extensions [3]. Still haven't looked back; for our specific use case of writing (computer science) teaching materials, Markdown is a better choice than rST.
[1] https://gaseri.org/en/blog/2017-07-29-why-we-use-restructure...
[2] https://gaseri.org/en/blog/2021-08-16-markdown-vs-restructur...
What I like is how easy it is to host MkDocs on GitHub Pages via built-in support, but you can even make it behave like Jekyll with GitHub Actions. Shameless self-plug of another blog post: https://gaseri.org/en/blog/2022-11-01-publishing-material-fo...
Rather than actually solve the problem of filtering WYSIWYG input/output, providing a solution for creating easy to create and maintain semantic HTML, Mozilla shunted it aside and now use a stack of custom tooling and libraries and yet another Markdown-alike variant text format with their own scripting embeds and then patted themselves on the backs for all the effort they "saved".
Mozilla is supposed to be the standard bearer for web standards. It's sad to see that bunch of myopic techies decided to go with a trendy solution that just trashed a core principle of the organization (#6) for one of its most important products. It set an example others are now following, and as a result, MDN put the web back probably two decades.
They acted as if they tried to make it simple and easy for the community to keep MDN up and up to date. Outrageous!
The thing is that HTML (and SGML) was invented, but Markdown was discovered as a set of best practices through decades of text-only mailing lists. This is something that many people found natural enough.
It's bending perhaps history of mankind in my book a little too much, saying the author of Markdown has discovered that and not lets say, someone else the "one or other" millennia earlier.
And writing on the computer is commonly the least ergonomic form of writing at all.
Other block-level elements would auto-close either at a new line or when a new block tag starts, headers would automatically create <sections> that end when a new header appears, and inline elements would end at the next space, newline or generic end tag like </>, so they could be nested.
A lot of this is done already in the browser. A valid HTML doc just needs a doctype, title and a body tag and the spec specifies all the rest will be filled in automatically. The spaghetti logic employed to add in missing closing tags to keep pages looking decent is mind boggling. Seems like there could be a few additional spec rules and then plain-text HTML would be just as easy to create as any other markup.
Also #6 of their manifesto is about interoperability. Markdown is a great choice for this if you are consistent in your approach. No lock in, human and readible.
PDFs I've written in Markdown and typeset using ConTeXt:
* https://pdfhost.io/v/4FeAGGasj_SepiSolar_Highlevel_Software_...
* https://pdfhost.io/v/mhw8jCJzw_autnoma
* https://dave.autonoma.ca/blog/2020/04/28/typesetting-markdow...
* https://impacts.to/downloads/lowres/impacts.pdf
I think Markdown can be used in serious documentation projects. I am biased, given that I've been working on my free and open source, cross-platform Markdown editor for several years:
https://github.com/DaveJarvis/keenwrite/blob/master/docs/scr...
I've been generating PDF documentation with Obsidian. The challange is when a document will have multi, non-technical, owners. Invariably the "solution" is to open the PDF in Word.
Thank you! My sci-fi story, autónoma, is the reason I started to work on KeenWrite, and can be fully generated from within the app. The others could be edited in KeenWrite, but there'd probably need to be some work done to get the HTML/CSS preview panel to display the various annotated sections correctly. Speech bubbles (::: bubbletx and ::: bubblerx), for example, currently work in KeenWrite, but the spectrographic lines in the Impacts Project would need to have special CSS written to render correctly in the preview.
> The challange is when a document will have multi, non-technical, owners. Invariably the "solution" is to open the PDF in Word.
Teaching people to separate content from presentation takes a lot of effort. That's also a process problem. You could ask people to provide feedback by adding notes into the PDF, rather than editing it directly.
At some point it'd be nice to see real-time collaboration added to KeenWrite, which would go a little ways to helping solve multiple users editing a single document:
Thanks.
[0] https://orgmode.org/manual/Working-with-Source-Code.html [1] https://docs.racket-lang.org/scribble/how-to-doc.html#%28par...
The picture-of-a-tweet nails it, but the author misses the point. It's not "we have Python devs" it's "reST has the best syntax for extensibility": if you need to start doing some sort of macro or pre-processing, reST's syntax is cut out for that. M↓ is not; you'll need to do it out of band. Or, to put it differently, reST's directives offer extension hooks.
> You’ll need to set up an identity and access management (IAM) service in front of your static website. Unless IAM is your jam, it’s better to avail of a managed service to tackle it.
We throw ours behind Github, I think using https://github.com/oauth2-proxy/oauth2-proxy ; then Github is our IAM.
Honestly, while I think reST has a more cleanly thought out syntax that will allow you to grow the complex use cases docs will inevitably hit … the tooling just isn't as good, IMO. Markdown parsers are prolific … reST … not so much, particularly outside of Python. (And IMO, docutils in Python is not very easy to use if you want fine control over parsing & output. It's there, but just hard to take advantage of.) M↓'s syntax is also somewhat limiting: there's just not a lot it can do. (Admonitions, in particular, are useful in tech docs and missing.) There's always HTML, … but that's just not the same.
(I've no experience w/ AsciiDoc.)
reST actually has a strong enough spec document that you could reimplement it some other language that isn't Python and assume a base level compatibility (very contrary to Markdown's case and many flavors), and the reason there aren't more reST engines/libraries in other languages is as much the network effects of the existing ecosystem around Python-based extensions (and Sphinx) more than anything technical or missing in the specs.
Markdoc just hits the sweet spot of being super easy to get started with but elegantly extensible that makes it scale. I think the OP here simplifies a bit though of what Markdoc is. While it is pretty simple to integrate into a next.js site for a SSG doc site, it is more of a library that can be integrated into almost any site or rendering framework.
In some ways, this is the biggest "challenge" of Markdoc right now. It isn't focused on a polished out-of-the-box experience like Docusaurus or MKDocs, but is instead more of a DIY tool.
That said though, what is there is really great. With the ability to create custom tags easily and then the ability to analyze and transform an AST in a simple, but easy to understand way, I think markdoc is actually a great option for more than just building a doc site, but as a more general purpose tool for authoring any text-heavy content.
With Markdoc, I have built: * a higher level utility for creating a "library" of content with consistent ids for stable and validated links * a validation library to ensure that doc structures follows best practices like having metadata tags in the frontmatter, properly nests headers and doesn't skip H3s, etc * an integration for authoring and reusing doc content in spectacle[0] presentations * have a clear direction of how to "scale" docs-as-code as we were struggling to do that with a simple, flat file of markdown files
I have started to toy with the idea of a more general purpose CMS built around markdoc... but in general, a really great tool and kudos to stripe team for building it :)
Asciidoc:
* Almost as simple as Markdown.
* Less convoluted than reStructuredText.
* Excellent support for complex tables, captions, callouts, etc.
* We prefer Asciidocs table structure to Markdown's since it is easier to create and maintain.
* Excellent documentation.
Antora:
* Comes with a default template, which makes building prototypes easier.
* Ability to pull from multiple git repositories.
* Native Asciidoc support.
* Fast compile times.
* Good documentation.
Based on our research, I even migrated my personal 11ty sites from Markdown to Asciidoc and have been quite happy with it.
Asciidoc seems to have a solid backend. But it seems to have a problem with nesting. Nesting things should be tablestakes in a markup language.
I don’t know much about RestructuredText (no, I won’t play these silly free-caps games) but it doesn’t look that nice to me for whatever reason. It looks the closest to regular markup to me except they have replaced things like brackets with backticks.
And finally I am glad that I never have to use some Wiki lightweight markup variant with silly syntax like using X numbers of apostrophes for emphasis or whatever.
The upside of rST is that it's just more complete, it has more document elements available. Markdown is often written without thought to having a readable plain text document, but rST is often very readable in plain text too.
This is my beef with Markdown. Automatically numbered lists always break for me--every time. And Markdown doesn't support decimal numbered lists (1, 2, 2.1, 2.2).
I can ignore spacing, because every markdown has bad spacing (space before and after a formatted block or header or list), but I loath the inflexibility of numbered lists.
That said, for my projects I use Markdown, because its so simple--necessary and (mostly) sufficient.
Its the first I'm hearing of Antora though, so I'll be sure to check that out.
Maybe there's a great static site generator written in GO with strong Asciidoc support??
Antora is new to me as well, will review.
So people keep trying to add the semantic bits onto markdown, a process which I would argue destroys the genius of markdown in the first place.
Markdown is intended to be a nice looking text document. with strict limits on the format so that it can be transformed into a nice looking typeset document. If your base text document does not look great, you are doing markdown wrong. You would be better off with an actual markup language. This is also why I think markdown editors are wrong. again the whole point of markdown is to have a great looking text document, a text editor is perfect for this, any other specialized editor will produce a bad looking document.
I was kinda shocked that asciidoc came up as the recommended documentation solution; we use it and were looking to possibly make a move because of some of the warts (includes are great, but then make updating doc more complex, no one line ifdef check, feels a bit aged).
Anyone have any other suggestions we should look at?
Anything AsciiDoc can do, Markdoc can be extended to do, from variables through includes.
React or HTML output. AST transforms or functions. Upcoming editor support etc.
The community isn’t there yet but I predict it will show up.
As I wrote last week in a post that got flamed to pure carbon here on HN, the amount of man hours lost avoiding HTML is beyond comprehension. All of these languages are seriously flawed half-baked solutions to a problem that's already been solved.
1. https://en.m.wikipedia.org/wiki/Lightweight_markup_language
I tend to think so aswell but there is a big exception: code highlighting. Having a no-js solution to code highlighting implies having a build step to handle just that (unless you actually do it yourself while writing the docs, which would be insane). I haven't spent a lot of time researching it, but I have yet to find a tool as simple to use as e.g. Pygments or Chroma (with Sphinx and Hugo, respectively). What would you recommend?
In both cases you need to add some sort of markup to identify the code, right? In HTML it looks like:
<code class="js-syntax"> let a = "foo"; </code>
And Markdown looks like: ```js let a = "foo"; ```
But in HTML, you have a bunch of options built into the file itself: A WYSIWYG editor could add the syntax highlighting before saving, a build step could add in the appropriate styles before publishing, or a JS script could be added to the page and the browser could deal with it. A Markdown file only has one option: Here's your blob of code in plain text, go find some library to convert it.HTML is just a text document that happens to have had 30 years of work put into its spec and millions of man-hours put into optimizing its Object Model and parsing engine. It can be as simple as bog-standard Markdown output, or contain all the meta data needed without relying on custom tags and other hacks.
The docs are written as strings in a special tests directory, with special markup to mark code that is not included in the output, and special code for generating (at test-time) and creating inline iframes for results where applicable.
Code examples in docs that aren't executed will very often be wrong. That's just a fact of life. So we execute them all.
Is that how rust documentation works?
These are API docs, but mdBook[2], which generates documentation that looks like this[3], has a test command which checks the code blocks the same way.
[0]: https://doc.rust-lang.org/stable/src/alloc/string.rs.html#76
[1]: https://doc.rust-lang.org/stable/std/string/struct.String.ht...
> GFM is, by far, the most popular flavor of Markdown.
It is very sad because gfm is essentially "done" evolving. There's no desire from people I've spoken with to improve the implementation or add new features. For example: Multiline tables.
> Many tech companies love the rich ecosystem of Remark to transform Markdown with plugins. Still, extendability is the subject where Markdown scores the lowest.
The state of the world here is quite painful. I'd also like to say a prayer for anyone else out there writing custom extensions to cmark-gfm in c.
> reStructuredText offers a number of useful directives out-of-the-box. For example, admonitions (“safety messages” or “hazard statements”) can appear in rST like this...
We've been able to implement this as an extension in cmark-gfm and hoedown. It is quite painful but it is doable.
Markdown is just as extendable if you have control of all of the parsers and rendering code for your organization. This is no small feat.
Say that I generate a table using asciidoc's built-in syntax, the output will always generate HTML elements with the CSS classes already defined:
<table class="tableblock frame-all grid-all stretch">
<colgroup>
<col style="width: 50%;">
<col style="width: 50%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Column heading 1</th>
<th class="tableblock halign-left valign-top">Column heading 2</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Column 1, row 1</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Column 2, row 1</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">Column 1, row 2</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Column 2, row 2</p></td>
</tr>
</tbody>
</table>
For me, this output is needlessly verbose for a setup that uses nothing but default flags. Worse, it doesn't provide much of a leeway to change the classes or even let me use some other ways to style the elements.I prefer markdown's (and markdoc's) approach to styling, in that it doesn't really try to define any. My take on this is that stylings of the output should be be coupled with the toolings, as opposed to being bolted into the language standards.
edit: formatting
Yes, it's extensible. But I don't want to write a role just to add bold to a reference!
On the flip side, the stuff in the pile mostly wasn't authored by technical writers. The people who used tabs and blank lines for formatting and boldface+font size changes for section heads would be probably just create the same kind of semantic messes, but with the added bonus of having a BOM marker at the head of the document and CRLF line endings.
Good news though, the jupyter devs created myst (https://myst-parser.readthedocs.io/en/latest/syntax/syntax.h...), a superset of markdown that has almost all the features of rst, and can embed rst when it falls short.
And there is a plugin to use it with sphinx. It can even reside in a project that started with rst files, both format can coexist.
With this and sphinx-autoreload, writing doc is so much better.
Markdown nested lists could also be used as an alternative to JSON and YAML - they would appear as bullets in a rendered markdown file. I didn't know about this until I started experimenting but inline code blocks can contain backquotes just like fenced code blocks can contain triple backquotes, by wrapping them in a greater number of backquotes.
Hmm, if a Markdown file can have code interspersed, then can't a code file have Markdown interspersed, and the two interpretations of the file could in some sense be symmetric - and equally valid ?
Obv such "interspersions" exist in certain implementations, but I don't think such symmetries do, nor is there anything like a "standard" for it.
Literate programming using Markdown - who'da thunk it ?
Someone pls correct me if I'm OTL.
observablehq puts Markdown in JavaScript code.
I think it works better with Markdown even if it wasn't supported in multiple places, but since it does, I think having Markdown be the container format is a clear winner.
There is also MDX but I prefer stuff that displays in the rendered view as well as in the source. Of course the renderers can change, but that's slow.
As for inverting them without losing the data, that seems possible and would be interesting to see.
"The original version of Markdown by John Gruber doesn’t specify the syntax unambiguously. For example, it doesn’t have table formatting."
Table formatting is an example of a missing feature in a deliberately minimalist specification. Or possibly a feature that is handled elsewhere in the markdown "stack" (by html). So if the syntax is indeed not specified unambiguously (facts not in evidence?) then this isn't a good way of demonstrating that.
Big
===
Small
-----
I actually prefer those when editing in a text editor - like a nicely formatted plain text email.The code span (the ticks) became code in HTML, a lot of times it should be samp, kbd, var.
Also definition list. People often use h5.
You can use html for both in markdown thought.
I write in HTML the way some people write in Markdown using the abbreviated (but valid) syntax.
<!DOCTYPE html>
<title>The Great Novel of All Time</title>
<h1>Chapter One</h1>
<p>It was a dark and stormy night.
<p>Suddenly a shot rang out!
<p>A door slammed. The maid screamed.
If you avoid closing things that don't need to be closed, and use whitespace (and a syntax-highlighting editor) it's easy to write and easy to eye-parse.
No includes though.
Here. Let me tell you a story.
Some years ago, Leadership in <COMPANY REDACTED> decided to stop paying for the S1000D[1] software. This would make the publications group effectively homeless. The objective of this tactic was to force a move to the PDM system's tech writing system, which had previously been rejected by more or less everyone.
I put out a plan[2] to keep the S1000D architecture (filenames, books, links, etc) but use lightweight markup and open standards from the programming industry, to do the actual writing. Which lightweight markup language? I needed the following:
* Transclusion, need to bring in files (data modules) from a centralized publication module
* Partial Transclusion, need to be able to bring in part of another file, what would be called CIRs in S1000D
* Conditional content, usable inline, so that a step or a figure could be toggled on and off depending on a condition set in the Publication Module. This emulates Applicability in S1000D.
* Complex print output
* Nice-to-haves: an AST that maps to a legacy format aka DocBook/DITA/S1000D/MIL-STD-38784/etc; publishing pipelines capable of weird crap like complex front matter, TOC, indices, header/footer/margin running content; a singular standard that had some life in it
I took pretty much every lightweight markup variant out for a spin with a test migration and publish, on my own time, nights and weekends. I found that there was a Markdown variant that could almost do everything I wanted, but it had a dependency on a document processor. ReST functionality similarly depended on notebooks and Sphinx. LaTeX HTML pipelines were a bit janky and hard to set up on Windows. Neither really tied to a legacy XML format, which limited round-tripping with something as insane as S1000D. And the print options for both ReST and MD were not where I needed them, particularly for tables, but also for running content. Asciidoc came the closest to checking off all the boxes for me.
Anyway, it happened, it worked, I did it. But it hit business process problems. Stuff that would have hit any new instance of a pubs too. Like "we don't actually know which plane parts can work with each other" or "SMEs will never ever ever do a review in a text editor . . or electronically . . or in anything but a dead tree" or "a few writers don't know what the scroll wheel on the mouse does"[3] or . . eh, take your pick. I ate my own gun, though, and left. They're still using it - and probably still cursing my name - to this day. But that had been one of my big goals[4]: S1000D architecture on lightweight markup.
So. Lightweight markup. I haven't continued to shop around, and I probably should. For one, I'm of the growing opinion that inline conditional content is a mistake as a general design, and that the conditionals should probably live in the processing layer. That's a big chunk of the requirement covered by Asciidoc's `include` directive. For another, I won't deny that the Markdown ecosystem is about 100x the Asciidoc ecosystem, due to the much greater dev count with the JS ecosystem vs the Ruby ecosystem. Some of the toys in Markdownland are worth the move all by themselves. And round tripping S1000D? You can't even round trip S1000D with itself.
Then again, there's so many damn MD variants. .
[1] XML vocabulary for documentation of mil/aero systems. Think DITA but a million times more complicated. And a new Issue every two years, without any commonality in the scope.
[2] This was a mistake, as I made lasting enemies of the PDM boosters, who counted some executives among them. I would have been better off keeping my mouth shut and letting the whole thing sink into the ocean.
[3] And had no interest in finding out, either. "You're trying to turn us into programmers, with this git and text stuff!". No, no I am not, and if you ever want to work outside this sector you'll want to learn what git is.
[4] Should probably mention that annual per seat license costs for the big S100D solutions were pushing past 30k, with reviewer licenses lagging not far behind that. Not including the setup costs, or the consultants that will have to fly down for every tweak and button. I could not, for the life of me, figure out how anyone manages to pay for that in avionics, where the margins are razor thin. Turns out they don't, they just deeply discount their products so the OEM can "show them how it's done". Effectively they're paying their suppliers with dollars that can only be spent with the OEM.