Gotchas

Overview

Not everything is plain sailing with either AsciiDoc or Antora. On the plus side the combination is powerful enough to tackle large scale documentation projects. However, they aren’t the easiest set of tools to learn and can seem complicated for smaller scale problems.

Antora also extends AsciiDoc by introducing the family directory concept. This is a key Antora idea that is particularly important for large multi-repo projects. However, perhaps more thought should have been given to making it backward compatible with plain standard AsciiDoc — at least for simpler projects.

AsciiDoc is Wordy

Writing basic AsciiDoc is really no different from writing Markdown but of course that isn’t really a testament to its usability.

You are only going to write AsciiDoc to access the extra features it unlocks. The essential cost benefit comparison is then whether those “extras” come at a low enough cost to justify the effort of learning a new syntax.

Certain features AsciiDoc provides out of the box are without doubt really useful for writing technical documentation and very easy to use! In particular, callouts and admonitions are enormously useful, much used, and take very little effort to learn.

Other features of AsciiDoc are occasionally useful but you will probably find yourself needing to go to the manual to refresh your memory on how to invoke them. This is because AsciiDoc syntax can be a bit wordy and frankly some aspects simply aren’t explained all that well in the core documentation so it is hard to develop an intuition how to do things.

One specific example is math mode in AsciiDoc. Technical documentation will often need to embed mathematical equations both inline and display style. The good news is that you can readily get AsciiDoc to support \(\TeX\) style equations but unfortunately in a somewhat wordy manner.

Using \(\TeX\) you write $A \cdot x$ to get the inline equation \(A \cdot x = b\).

In AsciiDoc (certainly if you want to use Antora) you instead need to write the longer stem:[A \cdot x = b]. It is even more wordy and space consuming to write the display version:

[stem]
++++
A \cdot x = b
++++

This does display correctly as

\[A \cdot x = b\]

but the raw source you are editing is much more visually cluttered than the equivalent \(\TeX\) code:

$$
A \cdot x = b
$$

One other thing that is less of a criticism but something to bear in mind is that at the end of the day, AsciiDoc is just a markup language for documents. As such it lies in complexity and capability between its simpler cousin Markdown and something like \(\LaTeX\) which is heavily used in many scientific disciplines.

You can write some very simple macros in AsciiDoc but those are mostly for doing substitutions. So you can assign an short attribute to say a long messy URL and then refer to that URL by using the attribute. This is definitely useful but a long way short of the type of things you can do (granted often painfully) in \(\TeX\).

And of course while AsciiDoc allows you to link documents together in a cohesive manner, it is not by itself by any means a website generator. You use the language to write the content for a website but bear in mind that you will need to go elsewhere to actually get a reasonable looking website.

Antora Extends AsciiDoc

A key improvement of AsciiDoc over Markdown is that it allows you to include one file (or even just a tagged portion of a file) in another one.

The target file in an AsciiDoc include directive is usually specified by simply giving its location relative to where you doing the actual include::. For example to include a source code file main.cpp that lives a couple of levels up in the source/ directory you might write:

include::../../source/main.cpp[]

AsciiDoc does support some variations on this theme but they are all equally straightforward.

The same sort of simple target resolution holds for inter-document cross references (an AsciiDoc xref) and for locating image files (the AsciiDoc image directive).

The downside is that this can be fragile especially if you want to reference files that exist in different repositories. AsciiDoc will let you do that but only by hard coding the URL of the target repo and the location of target file from there. If anything changes you end up with a lot of URLs to fix in your AsciiDoc files.

Antora is specifically targeted at large documentation projects where the components are spread across many repositories so this is a key problem it aims to fix.

It does so by applying a core notion. In Antora that all resources that go into the website (pages, images, snippets/partials, downloadable attachments etc.) are given a unique identifier—​an Antora ID.

During the build process Antora gathers all of the website resources into a virtual filesystem and assigns one of those ID’s to each item. Antora more or less insists that you use those ID’s when you want to include a resource either through the include, xref, or image directives.

In the greatest generality you do that by using all of the target resource’s Antora coordinates. These coordinates are exhaustive but also human friendly and include a version tag, a component name, a component module, an Antora family, and finally the name of the resource itself. These Antora coordinates are independent of the physical layout of the resource files and so eliminate the need for those somewhat hacky ../.. references in your documentation files.

That’s great and even better is the fact that most of the time you don’t need to specify almost any of those Antora coordinate elements. A directive like:

image::SomeImageFile.png[]

tells Antora to find SomeImageFile.png in the appropriate family directory which is always called images/ and always is a sibling to pages/ (in fact all the recognized family directories are siblings of pages/).

The Problem with Families!

AsciiDoc itself knows nothing about these Antora family directories. Neither do any of the Asciidoctor based renderers. The family directory concept is an Antora extension to standard AsciiDoc.

Antora’s core development team is undoubtedly capable and very productive, but it is also very small. Antora might die tomorrow or some alternative “better” website generator might come along that uses AsciiDoc as the content format. Locking oneself to AsciiDoc as a markup format seems fine, locking oneself to a very specific Antora content layout and relying on the family directory structure doesn’t seem so great.

Even on a short term basis, you will hit a problem when you try to preview individual AsciiDoc files in your browser/editor. The JavaScript AsciiDoc renderer in that plug-in knows nothing about the Antora family directories. That simple image:: directive above will fail because the renderer will look in the current directory for the SomeImageFile.png file instead of where it actually sits in the ../images/ directory.

Of course, you could always insist on using Antora before previewing a document. However, that entails building out the whole website when you just want a quick peek at one page!

Antora makes complicated things possible but isn’t great at making simple things simple. If you want your content files to also work outside the context of Antora you need to work at it a bit!

For what it’s worth, the Antora team is working on a tool that will take markup that uses those Antora coordinates and emit standard AsciiDoc markup where the references are appropriately resolved. That may help a little but still locks the writer into using the family directories which is an Antora extension.

Workarounds

For a simple site like ours with one component there is a pretty easy work-around.

The standard for AsciiDoc renderers is to always look in the :imagesdir: for target image files if that attribute happens to be set. On the other hand, Antora completely ignores the :imagesdir: attribute and only ever looks in the images$ “family” directory.

We can keep all systems happy by using the Antora family directory for images and then setting imagesdir at the start of the document to the actual relative location of that directory—​something along the lines of:

:imagesdir: ../images

Then when you quickly preview the file in your editor or browser the target of the image:: directive will be satisfactorily resolved.

More generally, you can check whether the site-gen-antora attribute is set to add or remove things depending on whether you are using Antora or some other AsciiDoc processor. For example, it is often handy to have a line like ifndef::site-gen-antora[:toc: left] at the start of a document. If you are previewing the file outside of Antora then you get a useful clickable table of contents on the left for quick navigation in larger documents. That table of contents is usually redundant in Antora as in the full website some other more sophisticated navigation is in play.

Getting Help

AsciiDoc is documented on the AsciiDoc documentation website, and Antora on the Antora documentation site.

AsciiDoc has been around a while so you can find other sources of tips by Googling. Though it’s not been added to in a while, I found the Awesome Asciidoctor site to be useful (the site’s content is also available as a book).

Antora is newer so there isn’t that much readable material available beyond the official documentation site.

There is an active forum you can follow on Zulip. However, the Antora Zulip site doesn’t appear to be indexed by the standard search engines which is annoying! If you type an Antora related search term into Google you will not see any results from the forum (though you may pick something up from an earlier one that existed prior to the migration to Zulip). A new user is expected to find Zulip through the Antora docs and then use the internal search tool there. This adds another point of friction when you are learning the system.