I recently found Markdown not sufficient for authoring my site contents: its expressive power is quite limited and it is fairly often to get into character escaping issues when writing complex articles, and started to search for alternatives. After comparing a few markup processors, I decided to use AsciiDoc.

First Attempt

Since I am currently using Jekyll for site compilation, I tried to integrate AsciiDoc and Jekyll, and after a quick search on Google, it seems that there exists a Jekyll plugin for exactly this task on GitHub, asciidoctor/jekyll-asciidoc, from the same folks who maintain AsciiDoctor, a Ruby version of AsciiDoc processor; and imagined that the integration process would be easy. But unfortunately, it turns out being not.

Simply enabling AsciiDoc as another markup processor in Jekyll is as easy as installing the jekyll-asciidoc Gem and enabling it in in the Jekyll _config.yml. After applying those, files with .asciidoc extension are processed with AsciiDoctor before handed to the template engine, and simple pages would be rendered fine.

But soon I found that there are several problems.

  • Firstly, I’m using GitLab CI for site compilation and deployment, and for compilation, the Docker image jekyll/jekyll is used. This means the jekyll-asciidoc Gem won’t be available there.

  • Secondly, the HTML AsciiDoctor output for AsciiDoc is structured in a specific way that doesn’t play well with my site CSS, so anything beyond plain paragraphs would look weird if not ugly.

  • Thirdly, the awesome and somehow unique feature, admonitions doesn’t work out of the box. After some trials and failures, it seems that special CSS are required for this feature.

To over come those problems, I was forced to spend a significant amount of time to configure my site generation mechanism, but the outcome is worthy enough for the time.

The steps I took in the first attempt were:

  1. install the Gem jekyll-asciidoc with sudo gem install jekyll-asciidoc

  2. enable it in the _config.yml by adding the following snippet:

    gems:
      - jekyll-asciidoc

Migration to Bundler

Bundler is a Gem dependency management tool for the Ruby platform. In my case, it is used exactly for what it is intended. Migration to Bundler itself is again quite simple, just involving authoring a Gemfile and change compilation command in .gitlab-ci.yml from jekyll build to bundle exec jekyll build. Cares just need to be taken with generating and tracking Gemfile.lock and make sure the CI build script runs bundle install before the compilation command.

But again, there were some problems. In my first try, the site doesn’t build in the CI environment. After some investigation, it turns out that the jekyll/jekyll Docker image doesn’t have enough packages installed in order to build the ffi Gem, so I had to switch to the official Ruby Docker image.

After switching the Docker image, everything worked fine. But I noticed that the Gems are downloaded and installed every time, which is quite inefficient. And it turns out that caching /usr/local/bundle of the building container would help. After caching this directory, build time reduced dramatically, from 30-ish seconds to 7 or 8 seconds, which was a huge save on time, not even taking account of the reduction of network bandwidth usage.

The steps I took were:

  1. create a Gemfile with the following contents

    source 'https://rubygems.org'
    
    gem 'jekyll', '~> 3.1.6'
    gem 'asciidoctor', '~> 1.5.0'
    gem 'jekyll-asciidoc', '~> 2.0.0'
  2. run bundle install and track both the Gemfile and the Gemfile.lock in git

  3. modify the .gitlab-ci-yml file and

    1. change image: jekyll/jekyll:3.1.6 to image: ruby:2.3.1

    2. modify the compilation script from

      - jekyll --version | grep 3.1.6
      - jekyll build

      to

      - bundle install
      - bundle exec jekyll build
  4. add /usr/local/bundle to the runners.docker.volumes array in the GitLab Runner configuration, i.e. ~/.gitlab-runner/config.toml for caching the Gems installed by Bundler across builds

Enabling Code Highlighting

Merely installing jekyll-asciidoc won’t automatically enable syntax highlighting of source code blocks. I referred the asciidoctor/jekyll-asciidoc-quickstart project for setting up coderay as the source code syntax highlighter for AsciiDoctor and added a CSS stylesheet for the highlighter result based on https://gist.github.com/andrewpthorp/5134070.

The steps I took were:

  1. add the following line to Gemfile:

    gem 'coderay', '~> 1.1.0'
  2. add the following lines to _config.yml

    asciidoctor:
      attributes:
        - source-highlighter=coderay
  3. add my code highlight stylesheet /css/coderay.css, which is customized basing on https://gist.github.com/andrewpthorp/5134070

  4. add the following snippet to /_includes/head.html so the /css/coderay.css is referred in all documents processed with AsciiDoctor (the detection is based on file extension of source files, which is assumed to be .asciidoc)

    {% capture page_ext %}{{ page.path | split: "." | last }}{% endcapture %}
    {% if page_ext == "asciidoc" %}
        <link rel="stylesheet" href="{{ '/css/coderay.css' | prepend: site.baseurl }}" media="screen" type="text/css">
    {% endif %}

The Rest of the Story

TBD