Hugo and AsciiDoc?

A few weeks ago, Jianmin started a blog. His first post covered his blogging setup with Hugo, the same generator I use. Instead of writing his posts in Markdown, though, he writes them in AsciiDoc. I did a little ducking and the claims for AsciiDoc sound pretty good. The Manning Free Content Center has a comparison of Hugo-supported markup languages; its author uses AsciiDoc and notes that since 2014 there have been dicussions of native AsciiDoc support in Hugo. Right now, AsciiDoc is supported using an external command, either asciidoc or asciidoctor. That said, I thought I should at least test it and ensure that my hugo-base theme supports AsciiDoc pages effectively.

It was more involved than I thought.

AsciiDoc, Asciidoctor, and Arch Linux

asciidoc is in the Arch repositories, so I installed it. However, hugo hard-codes the options it passes to external generators, and the options it uses for asciidoc don’t work on my system.

ERROR 2020/04/06 11:51:26 stick/ asciidoc: ERROR: <stdin>: line 1: unsafe: ifeval invalid
ERROR 2020/04/06 11:51:26 stick/ asciidoc: FAILED: <stdin>: line 1: ifeval invalid safe document
ERROR 2020/04/06 11:51:26 /usr/bin/asciidoc rendering stick/ exit status 1

Not so good. Fortunately asciidoctor is also available, and it works fine. I didn’t try very hard to make asciidoc work (more on why in a moment), so it might be possible to set it up correctly; I don’t know.

AsciiDoc HTML is awful

Here’s a sample (which I have cleaned up quite a bit already) that shows the horror of asciidoc's (and asciidoctor's) generated HTML.

<div class="paragraph"><p>...</p></div>
<div class="paragraph"><p>...</p></div>
<div class="paragraph"><p>...</p></div>
<div class="listingblock"><div class="content">
    <pre class="...">
        <code class="..." data-lang="...">...</code>

Let’s not.

Thankfully, there is a way around it. Hat tip to ratfactor for their write-up of asciidoctor-html5s, a backend for asciidoctor which generates (relatively) semantic HTML5. Because asciidoctor-html5s wasn’t available on Arch, I followed the Ruby Gem package guidelines and added it to the AUR (ruby-asciidoctor-html5s).

Once it’s installed, we run into the same problem we had with hugo and asciidoc earlier: hard-coded options. ratfactor’s post includes a way around this, as does jianmin’s Dockerfile. The basic gist is to override the actual asciidoctor command with a script, so that we can control which of hugo's arguments actually get passed to the generator. I already use similar functionality for other commands via an overrides folder in my dotfiles. The folder is added at the beginning of my $PATH so that executable there overrides other executables of the same name later in the $PATH. Here’s my script for asciidoctor:


/usr/bin/asciidoctor -r asciidoctor-html5s -b html5s \
    --attribute tabsize=4 \
    --attribute source-highlighter=rouge \
    --attribute rouge-css=style \
    --attribute rouge-style=base16.monokai \

No bashisms, so I use a POSIX shebang. command -v asciidoctor finds the actual asciidoctor command, which here is /usr/bin/asciidoctor. To that, we add the call to the html5s backend, along with some options for formatting and highlighting, and then add the options passed by hugo ("$@").

Syntax Highlighting

Speaking of syntax highlighting, all but one of the articles I looked at used Rouge for source highlighting. The odd one out uses a client-side JavaScript option. No thanks. Hugo uses Chroma, a replacement for Pygments. I suppose I could use Chroma to do it, but I would need to write a lot of pipe. Maybe later. Rouge is compatible with Pygments, it’s the default syntax highlighting solution for Jekyll, and it’s already integrated with asciidoctor. So be it.

Rouge is available in the Arch repositories, thankfully (ruby-rouge). Once installed, it seems the default way to use it is to add attributes to the AsciiDoc header. I could not get that to work; no matter what I tried, either hugo incorrectly stripped the header, or asciidoctor did not recognize the attribute. In the end, the solution was to add the attributes to the asciidoctor override script (shown above); this keeps the document files cleaner anyway.

Once I had it working, the next hurdle was theming. If you are looking online, this is not the whole list of themes. Thank you to mcpride for his post pointing out that you can list all highlighting themes with rougify (rougify help style).

Vim Workflow

There is limited support in Vim; syntax highlighting works out of the box but nothing fancy. If your file extension is .ad, be sure to set filetype=asciidoc since Vim auto-detects xdefaults instead. You can do this in filetype.vim as below:

if exists('did_load_filetypes')
augroup filetypedetect
    autocmd! BufNewFile,BufRead *.ad setlocal filetype=asciidoc
augroup END