Creating a Blog with Hugo and AsciiDoctor

OK. I did it. It took long.

Back in the days, I did some blogging already. Roller, Blogspot, Tumblr and what not. Some problems nagged me

  • reserving time to create content 🤔

  • awful writing experience

  • missing control

Then static site generators came up. For years I looked into them, be it Jekyll, JBake or Hugo. I did a lot of experiments, but when it came to customization, theming and a perfect writing experience I realized that things weren’t perfect out of the box, and I would have to invest way more time that I usually have at hand just to get started.

Nevertheless, I stumbled many times about things and procedures worth being blogged about. If I only had a blog again …​ a vicious circle.

Lately I read a nice article by Sergei Egorov about debugging with Testcontainers. But not only the content was great, I also liked the blog experience presented. Nice and clean, and developer oriented. Thankfully the right hints were provided - the blog was based on Hugo and the Hugo Coder Theme. I suddenly was intrigued to get my hands dirty again.

AsciiDoc(tor)

Getting to roll with Hugo is damn easy. Create a site from a template (Hugo Coder provides a nice one) and start serving and watching

$ hugo server

                   | EN
+------------------+----+
  Pages            | 36
  Paginator pages  |  0
  Non-page files   |  0
  Static files     | 13
  Processed images |  0
  Aliases          | 14
  Sitemaps         |  1
  Cleaned          |  0

Total in 615 ms
Watching for changes in /Users/rene/DevHome/Blog/rgielen-blog/{content,layouts,static,themes}
Watching for config changes in /Users/rene/DevHome/Blog/rgielen-blog/config.toml
Environment: "development"
Serving pages from memory
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

But as with most of the static site generators known to me, only Markdown is a first class citizen (Kudos to JBake for being an exception here). Hugo has basic AsciiDoc support. But when you write your first article you realize that built-in syntax highlighting support, admonitions and many other things don’t work out of the box.

OK, you ask, so why not go with Markdown? Don’t get me wrong, there is nothing wrong with Markdown - except that no one should probably use it when AsciiDoc(tor) is available. I’m doing AsciiDoc-only these days, and a blog shouldn’t be an exception to that.

Unfortunately, when searching the interwebz, there was not much to find about advanced blogging with Hugo+AsciiDoctor. How to create a blog with AsciiDoc is a nice article covering AsciiDoc and Hugo, but did not answer all my questions, e.g. for syntax highlighting. I also stumbled over Robin Moffatt’s post about moving from Ghost to Hugo, covering the syntax highlight topic. But this was rather discouraging, since it suggested to use Hugo shortcodes rather than the native AsciiDoc authoring experience, which Robin mentioned he was unable to get working.

But this time I did not want to put my blog creation task to hibernation again, it felt like being almost there. So I digged deeper. Quickly I learned that once you use a highlighter like Pygments or Rouge in AsciiDoc, there is a possibility to let it generate the needed CSS for you. Could it be so easy? Yes, in fact:

gem install rouge
rougify style molokai > static/css/molokai.css

Putting things to work was as easy as adding the CSS to my config.toml along with a custom.css for some further adjustments

[params]
    # Custom CSS
    custom_css = ["css/molokai.css","css/custom.css"]

As for admonitions, icon fonts and other goodies, it turned out that to add partial styles from the default AsciiDoctor Stylesheet works very well. Here is my starter configuration in custom.css

/* AsciiDoctor*/
table{border-collapse:collapse;border-spacing:0}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(100,100,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}

.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}

Given this, working with syntax highlighting became AsciiDoctor native experience. A test article like so

---
date: "2019-04-17"
title: "An Article"
description: "for Testing"
tags: ["hugo", "test", "asciidoc"]
---

:source-highlighter: rouge
:rouge-style: molokai
:icons: font

[NOTE]
====
There are things to note!
====

```java,linenums
public static void main( String args[] ) {
    System.out.println("Foobar!"); <1>
}
```
<1> Print something

would render like so:

There are things to note!

1
2
3
public static void main( String args[] ) {
    System.out.println("Foobar!"); (1)
}
1 Print something

I’m sure there is more customization to come once I go ahead, but for now I’m quite content. Could this be the start of a steady blogging experience from now on? Let’s see …​