Writing with an AsciiDoc toolchain

I was about to start off with I’m not a technical writer by trade, but I realized that what I should be saying is “In addition to many other skills, I have done quite a bit of technical writing”. I have several published books and articles in my past, one book even still “in print”. I’ve written documentation for parts of many open source projects, countless internal corporate documents and created my own wiki structures, some of which weren’t even complete disasters. I’m still coming back to it again and again.

As it pertains to this post, I have written with ReStructuredText (and Sphinx to render), Hugo, Markdown and Jekyll. I had a strong preference for ReStructuredText for seriously-long-form writing (doc sites, books, etc) because it pretty sanely represented inter-document linkages, which always felt a like a terrible add-on hack and shim on Jekyll (w/ Markdown). Hugo, which Kubernetes docs uses was better – but the CLI tooling on the Mac was damned awkward. I do favor Hugo over Jekyll, especially for it’s internationalization support.

my writin’ toolchain creds…

When I did my last book project (Kubernetes for Developers), I ended up working with Packt Publishing. They have their own wonky internal toolchain setup, more or less a hacked-up version of WordPress from what I could tell. While I was working up the content, I seriously explored self-publishing. One of the ideas that I considered was looking more seriously at writing with AsciiDoc.

I’ve since taken a more serious stab at it, wanting to do some writing on Apple’s Combine framework. I decided I wanted to embrace the constraints of writing to a book format for this effort, and set up the content and toolchain to render HTML, PDF, and ePub concurrently. The core of the solution I landed on revolves around a lovely project called AsciiDoctor.

A caveat for folks reading this: If you’re wanting to do some online writing, and only want to render it to HTML, then while you can likely make this AsciiDoctor-based toolchain work, it’s honestly not the best tool for the job. You will probably be a lot happier with Jekyll or Hugo. AsciiDoctor & AsciiDoc are missing a lot of the “add on” flexibility and additional rendering pieces that are easily found in other HTML-specific rendering solutions (Jekyll, Hugo, and Sphinx).

The biggest constraint in my toolchain is the rendering to ePub. AsciiDoctor has a nice extension (asciidoctor-epub3), but it comes with some fairly strict structural constraints. If you want to adopt this toolchain for yourself, start with reading it’s composition rules.

The toolchain I use leverages prebuilt asciidoctor containers with Docker (so I don’t have to mess with ruby environments and maintaining that all together). The container (asciidoctor/docker-asciidoctor) is updated from the asciidoctor, and pretty easily usable. I did experiment with adding some extensions into my own docker image, but the baseline from the project is perfectly effective.

The key to using this setup is figuring out the correct invocation for the docker container so that the content runs on a local directory and generates the relevant output.

A sample of how I do this:

#
 HTML
docker run --rm -v $(pwd):/documents/ --name asciidoc-to-html asciidoctor/docker-asciidoctor asciidoctor -v -t -D /documents/output -r ./docs/lib/google-analytics-docinfoprocessor.rb docs/using-combine-book.adoc
# copy the images directory over for the rendered HTML

cp -r docs/images output/images
#
# PDF

docker run --rm -v $(pwd):/documents/ --name asciidoc-to-pdf asciidoctor/docker-asciidoctor asciidoctor-pdf -v -t -D /documents/output docs/using-combine-book.adoc

# ePUB

docker run --rm -v $(pwd):/documents/ --name asciidoc-to-epub3 asciidoctor/docker-asciidoctor asciidoctor-epub3 -v -t -D /documents/output docs/using-combine-book.adoc

I also wrote a simple bash script to make a one-line “re-render it all”, and tweaked it up so that it could also open the resulting file. If you’re so inclined, feel free to grab, copy, and use it yourself: re.bash

The example above, and my associated re.bash script, are set up to build content from a “docs” directory, with a specific “core” to the asciidoctor-based publication. In my case, I’ve called that file using-combine-book.adoc. My example embeds a Google Analytics code for the rendered HTML (omitting it for PDF and ePub of course), enables syntax-highlighting for source code blocks, and has the structure specifically enabled for ePub generation.

I’m hosting the content using Github Pages. At the time of this writing, they don’t support generating anything other than Jekyll with Markdown content through their built in system. You can, however, set up a TravisCI job to render the content (using the same docker containers) and then publish that by having the TravisCI job push the content to a specific gh-pages branch on the github repository.

Feel free to also snag and re-use the TravisCI configuration (.travis.yml). You’ll need to add 3 environment variables to your Travis job to make this work:

  • GH_USER_NAME
  • GH_USER_EMAIL
  • GH_TOKEN

The last of these is a “personal access token”, which is what allows the travis job to push content to your repository as you. Do make sure you tweak the repository name and location to match your own if you copy this. It’s worth mentioning that I extended the basic example I found at http://mgreau.com/posts/2016/03/28/asciidoc-to-gh-pages-with-travis-ci-docker-asciidoctor.html, and the .travis.yml file I linked will only push updates when they’re merged with the master branch on the repository.

The end result is effective and I’m happy with the toolchain

It doesn’t come without it’s own constraints, primarily imposed by my desire to create an ePub format at the end of this process. I’ve also been happy with the effectiveness of AsciiDoc, although frankly I’m still just learning the basics. If you’re curious about the markup language itself, I’ve found the AsciiDoc Syntax Quick Reference and Asciidoctor User Manual to be invaluable references. I keep a tab open to each of those pages for reference while I’m writing.

If you’re so inclined to view the current work-in-progress, you can see the rendered HTML content at https://heckj.github.io/swiftui-notes/, which is derived from the asciidoc content within https://github.com/heckj/swiftui-notes/tree/master/docs. I also go ahead and publish the PDF and ePub in the same fashion, available at https://heckj.github.io/swiftui-notes/using-combine-book.pdf and https://heckj.github.io/swiftui-notes/using-combine-book.epub respectfully.