Tackling Hugo Integration of Asciidoctor
Integrate Asciidoctor as everyone should expect
While Hugo comes with Asciidoctor support, they are in reality several issues to account for at this time:
While basic rendering of asciidoc files works, we soon encounter problems ; the very first
-
Source listings are not syntax-highlighted.
-
Include directives don’t work
-
There’s no icons with admonition blocks
-
Source listing callouts are way off
So reading a few blogs posts to tackle these issues, and learn :
The first useful hack
First we need to be able to override how hugo invoke asciidoctor .
Hugo expects an executable name asciidoctor , we can trick it to run a
shell script instead, by creating in the repository a file named
./bin/asciidoctor . Then run hugo with the following environment :
env PATH=$PWD/bin:$PATH hugo serve .
|
Hugo uses : --no-header-footer --safe --trace -
args, as seen in
getAsciidocContent
.
|
Set safe mode level to safe. Enables include directives, but prevents access to ancestor paths of source file. Provided for compatibility with the asciidoc command. If not set, the safe mode level defaults to unsafe when Asciidoctor is invoked using this script. |
|
Output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. This option is useful for producing documents that can be inserted into an external template. |
|
If FILE is - then the AsciiDoc source is read from standard input. |
So using the trick learned in the above blog posts, and with quite a bit of trial and error I got up the following script:
#!/bin/sh
ad="/usr/local/bin/asciidoctor"
$ad --trace --verbose \
--base-dir ./content \ # (1)
--no-header-footer \ # (2)
--attribute nofooter \
--attribute docinfo=shared \
--attribute icons=font \ # (3)
--attribute source-highlighter=highlightjs \ # (4)
--attribute sectlinks \ # (5)
--attribute sectanchors \
--attribute figure-caption! \
--attribute toc-title! \
- # (6)
1 | The dot . is where hugo has been started, usually it’s the Hugo
site root, and content is where website content is located by default,
so the content folder is the base directory of asciidoc, this is important
for include: directives where the path will be relative to the ./content
folder. This option is useful because asciidoctor is invoked to use
stdin/stdout via - |
2 | The most important settings, tell asciidoctor to not
generate the header and footer as those are part of the Hugo theme,
in addition, this command also tells to not generate content footer
and trick asciidoctor to believe header and footer are part of
docinfo
by using the value shared . This helps in case of some external
script that are being injected like FontAwesome, Highlight.JS,
or MathJax for example. |
3 | Use Font Awesome, however Asciidoctor uses Font Awesome 4 which can be tricky to integrate in a theme that rely on Font Awesome 5. |
4 | This tells Asciidoctor to render pre code elements with
highlight.js information for them. This require that the theme correctly
set-up Highlight.JS. |
5 | sectlinks , sectanchors , figure-caption , or toc-title are attributes
to tweak the rendering, usually they are part of the document, but since I prefer to
have this setting global they are here in the command line. |
6 | Read the source from stdin |
Then run hugo
by overriding the PATH
environment variable.
./bin/asciidoctor
scriptexec env PATH=$PWD/bin:$PATH hugo # the hugo options
By the way if you forgot the --no-header-footer
option the whole HTML document
produced by asciidoctor is inserted by Hugo (as expected in fact) in the generated page.
Inline CSS and scripts import emitted by Asciidoctor are then competing with
the one of the Hugo theme.
See the <div class="post">
<div class="post">
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.10">
<title>Integrate Asciidoctor as everyone should expect</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
//... asciidoctor inline css
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<body class="article">
<div id="header">
</div>
<div id="content">
... the article content
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/github.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js"></script>
<script>hljs.initHighlighting()</script>
<script type="text/x-mathjax-config;executed=true">
MathJax.Hub.Config({
messageStyle: "none",
tex2jax: {
inlineMath: [["\\(", "\\)"]],
displayMath: [["\\[", "\\]"]],
ignoreClass: "nostem|nolatexmath"
},
asciimath2jax: {
delimiters: [["\\$", "\\$"]],
ignoreClass: "nostem|noasciimath"
},
TeX: { equationNumbers: { autoNumber: "none" } }
})
MathJax.Hub.Register.StartupHook("AsciiMath Jax Ready", function () {
MathJax.InputJax.AsciiMath.postfilterHooks.Add(function (data, node) {
if ((node = data.script.parentNode) && (node = node.parentNode) && node.classList.contains('stemblock')) {
data.math.root.display = "block"
}
return data
})
})
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_HTMLorMML"></script>
</body>
</html>
</div>
Porting the asciidoctor CSS
So now that we have the content HTML structure, the rendering of the article is still way off.
-
source listings are not syntax-highlighted.
-
Font Awesome icons are missing, incompatibility between FA4 and FA5
-
CSS is off or way off for almost all elements of Asciidoctor’s particular features,
The process was tedious, just copying the default asciidoctor css isn’t quite the right thing as stylesheet from the theme and the stylesheet from asciidoctor interfere, (corrupting other elements of the theme like the sidebar).
For example the theme alternate the background color table’s rows, and asciidoctor rely on lot on tables to layout some features, be it callout, admonition blocks, some lists, etc. in order to fix that the CSS has t be patched with rules like these:
tbody tr:nth-child(2n+1) td, tbody tr:nth-child(2n+1) th {
background-color: inherit;
}
Actually this work took significantly more time that I was prepared for, fortunately the Asciidoctor default CSS helped, and the way the theme of my choosing was using Sass (many other thems use it as it’s part of Hugo).
I ported and tweaked necessary Asciidoctor CSS rules to my scss
files using
an online CSS to SASS/SCSS converter. I’m
not a web developer so the result is probably incorrect, inefficient in some part
but it works for the feature I’m using.
Like thme layout overrides, hugo let’s you override scss files in the respective
directories like ./assets/scss
.
@import "hyde-hyde/variables";
// poole
@import "poole/base";
@import "poole/layout";
@import "poole/posts";
// hyde-hyde
@import 'hyde-hyde/mixins';
@import 'hyde-hyde/base';
@import 'hyde-hyde/sidebar';
@import 'hyde-hyde/list';
@import 'hyde-hyde/post';
@import 'hyde-hyde/code';
@import 'hyde-hyde/gist';
@import 'hyde-hyde/navigation';
@import 'hyde-hyde/taxonomies';
@import 'hyde-hyde/project';
@import 'hyde-hyde/responsive';
@import 'hyde-hyde/misc';
@import 'hyde-hyde/theme';
@import 'hyde-hyde/asciidoctor'; (1)
1 | Imports asciidoctor last. |
.post { (1)
// asciidoctor style
}
1 | Make asciidoctor rule applied within the first .post class
this is necessary otherwise asciidoctor rules may interfere with
theme elements that are name the same, such as .sidebar , or .title |
The current state of this file covers most features of Asciidoctor but a few leftover like colors.
Resolving Font Awesome 4/5 issues
One of the neat thing about Asciidoctor is their use of Font Awesome is
various parts like admonition icons. This is activated whith this attribute
definition :fonts: icons
.
But, Asciidoctor 2.0.10 uses Font Awesome 4.7, which is incompatible with my theme as it is using FOnt Awesome 5. This took me quite a while to figure out a solution, and it’s not perfect either.
To be more specific let’s dive into the admonition block TIP:
, Asciidoctor
will generate HTML with the icon-tip
class.
<td class="icon">
<i class="fa icon-tip" title="Tip"></i>
</td>
Asciidoctor uses the pseudo-element ::before
in order to display
the right icon. So only using unicode character code, and the right font family
should do it.
td.icon {
[class^="fa icon-"] {
font-size: 2rem;
font-family: 'Font Awesome 5 Free'; (1)
cursor: default;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
text-rendering: auto;
-webkit-font-smoothing: antialiased;
}
.icon-tip::before {
content: "\f0eb"; (2)
font-weight: 400; (3)
text-shadow: 1px 1px 2px rgba(155, 155, 0, 0.8);
}
}
1 | Use the FA5 font family that has the icons |
2 | Equivalent to <i class="far fa-lightbulb"></i> , but use the right
font-weight to access the free icons in the Regular set |
3 | 400 allows access to the Regular set, however only icons present in
the font family are present, in the Free family only a few Regular icons are
available. |
However, this didn’t work quite well. As I dicovered that the SVG framework
that is used when the JS scripts are loaded at the end of the page don’t quite
like the fa icon-tip
class. The script always replace this element
by the missing icon (a dotted circle with an exclamation mark alterning with a
question mark). I tried may variations, adding script in the head
, at the end,
playing with defer
, etc.
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js" integrity="sha256-KzZiKy0DWYsnwMF+X1DvQngQ2/FxF7MF3Ff72XcpuPs=" crossorigin="anonymous"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/v4-shims.min.js" integrity="sha256-prFmieX9aRVhOV/ldXGklUUhS7NRBQUijQU4HcdnO8Q=" crossorigin="anonymous"></script>
It took me a while but I ultimately decided to remove the usage of the SVG framework and as such loading these scripts as I never got them to work. Leaving only the FA5 CSS imports.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" integrity="sha256-h20CPZ0QyXlBuAw7A+KluUYx/3pK+c7lYEpqLTlxjYQ=" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/v4-shims.min.css" integrity="sha256-wN7QJaqAwQ03kgUhyN4EU2phRdDkLrQYbFe0EvpQ60U=" crossorigin="anonymous" />
And now tada, even with the asciidoctor macro :
But be sure to use FA4 icons, otherwise the icon won’t be found :
Yet it is still possible to use asciidoctor’s
passthrough macro with the HTML
right class from FA5 <i class="fab fa-java fa-3x"></i>
or the pass:[<i class="fab fa-java fa-2x"></i>]
inline macro
At some point it might be interesting to look for macro extensions, also see extension lab for more.
-
asciidoctor/asciidoctor-reveal.js#304 indicated FA5 is not something supported at the moment
Trying the semantic HTML5 backend
Also, one of the blog post is suggesting to switch to semantic HTML5, because the structure of the HTML5 asciidoctor’s backend is not modern enough, e.g.
<div class="paragraph">
<p>I’ve crafted my own simple shortcode for Amazon <code>{{< amzn "B07XW76VHZ" >}}</code> :</p>
</div>
Using the semantic HTML5 backend as suggested in this blog post
require to gem install asciidoctor-html5s
. And pass this option in the
script --backend html5s
.
In practice the Semantic HTML5 converter from https://github.com/jirutka/asciidoctor-html5s outputs semantic HTML, but doesn’t support all features of asciidoctor like icons for admonition blocks, also it uses the asciidoctor default CSS which is not suited for this semantic HTML5 tree: elements differ, CSS class names differ as well.
So while this slightly improves the HTML structure, this made CSS port too challenging for me, broken syntax highlighting, titles are not styled as expected, etc., so I didn’t use it in the end. At least this decision didn’t increase the complexity of the setup.
Using diagrams
2020-09-20: Hugo 0.74.0 and asciidoctor-diagram 2.0.3 finally allowed me to get rid of the setup below, which is nice in particular for diagrams. I’ll blog about the change at some point. |
Asciidoctor has a useful extension asciidoctor-diagram
that allows the generation of
diagrams from simple text listing, this may not be necessary for everyone, but it was
a mandatory thing for me.
It’s necessary to install the extension gem install asciidoctor-diagram
and to adapt the ./bin/asciidoctor
script to
$ad --trace --verbose \
--base-dir ./content \
+ --require asciidoctor-diagram \
--no-header-footer \
--attribute nofooter \
--attribute docinfo=shared \
This wasn’t enough as asciidoctor-diagram
outputs the generated SVG
in the wrong directory to be served by Hugo. I got a tip by reading this
blog entry, which
consists in modifying the URI of the diagrams in the rendered HTML, and moving
the generated files.
--attribute sectanchors \
--attribute figure-caption! \
--attribute toc-title! \
- -
+ - | sed -E -e "s/img src=\"([^/]+)\"/img src=\"\/diagram\/\1\"/"
+
+ mkdir -p static/diagram
+
+ if ls *.svg >/dev/null 2>&1; then
+ mv -f *.svg static/diagram
+ fi
+
+ if ls *.png >/dev/null 2>&1; then
+ mv -f *.png static/diagram
+ fi
In practice, I wasn’t satisfied by this setup for several reasons:
-
The
sed
targets allimg
elements. -
The files are moved in
static/diagram
, this is the most annoying point, because-
This move operation is not performed atomically with the content rendering, thus when served locally it triggers another refresh, which also triggers the rendering of the original document and then regenerate the diagram images which are again moved to
static/diagram
, triggering another refresh cycle. -
The generated files are moved in the
static
folder but are not supposed to be put in git, this can create unnecessary noise.
-
To be faire the orignal blog post runs hugo serve
with these options
--disableFastRender --disableLiveReload --renderToDisk
.
I couldn’t get a satisfying solution, so I decided to inline the generated SVG,
by declaring the opts="inline"
in the descriptor.
[plantuml,"sequence-diagram-example",format="svg",opts="inline"]
.Sequence diagram
----
// plantuml
----
This doesn’t require to pipe the output to sed
and mv
SVGs afterwards,
but the asciidoctor-diagram
outputs the images in the basedir.
While I’ve tried to set imagesoutdir
or out_dir
attributes in ./bin/asciidoctor
as documented (her):
Diagrams will be put in the mentioned folder like resources/_gen
yet somehow there still
stored on basedir
as well.
Also, I have tried to make SVG inlining as default for diagrams using this change that appeared in Asciidoctor 2, but it didn’t quite work as expected, as explained in asciidoctor/asciidoctor-diagram#247 comment.
Also, in the future it may be interesting to look at using charts macro, like suggested by this blog post.
Tweaking .gitignore
For me this ws due to asciidoctor-diagram
that generates files
here in a .asciidoctor
directory which is located in the configured base directory.
Let’s ignore it.
+ ### Asciidoctor
+ **/.asciidoctor
Adapting Github Actions
As seen in the previous entry, the site is rendered by a Github Action job, this job needs to be updated to run asciidoctor the way I want it. Fortunately I read few blog entries on the topic.
I mostly got inspired by Gunnar Morling in this matter, and looked on his github repository to see on it was done. And went the same way.
Make a docker image with hugo
and asciidoctor
His workflow is now based on running a docker image that has asciidoctor and hugo.
Since I wanted a full featured asciidoctor experience I needed something more that was in his image.
Trying to use docker-asciidoctor
I tried to use asciidoctor/docker-asciidoctor as a base image since it offers the whole experience. And it easy to just download and install a single executable.
However, I experienced issues to execute hugo
, I suspect this is due to alpine
base
but I wasn’t able to pin point the issue:
bash-5.0# hugo version
bash: /usr/local/bin/hugo: No such file or directory
bash-5.0# ldd /usr/local/bin/hugo
/lib64/ld-linux-x86-64.so.2 (0x7fcf85eb4000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7fcf85eb4000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fcf85d1b000)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7fcf85eb4000)
libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fcf85eb4000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fcf85d07000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fcf85eb4000)
...
bash-5.0# ldd /usr/local/hugo/hugo
/lib64/ld-linux-x86-64.so.2 (0x7f339a631000)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f339a631000)
Error loading shared library libstdc++.so.6: No such file or directory (needed by /usr/local/hugo/hugo)
libdl.so.2 => /lib64/ld-linux-x86-64.so.2 (0x7f339a631000)
libm.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f339a631000)
Error loading shared library libgcc_s.so.1: No such file or directory (needed by /usr/local/hugo/hugo)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f339a631000)
Create my own image
I ended up forking gunnarmorling/hugo-builder
to adapt it to my needs, installing a more recent version of hugo, asciidoctor-diagrams,
make hugo use of the asciidoctor
script hack.
I found this blog instructions easy to follow in order to publish my own image on docker hub. |
THe only issue I’ve encountered is that I forgot that a JDK is necessary to run
asciidoctor-diagram
.
ERROR 2020/04/20 22:00:39 posts/2020-04-20-tackling-hugo-integration-of-asciidoctor/index.adoc: asciidoctor: ERROR: <stdin>: line 284: Failed to generate image: Could not find Java executable
At this time here’s what my bric3/hugo-builder `Dockerfile looks like:
FROM registry.fedoraproject.org/fedora-minimal
EXPOSE 1313
WORKDIR /src
VOLUME /src
RUN microdnf -y install curl ruby tar java-11-openjdk && microdnf clean all
ARG HUGO_VERSION=0.69.0
ARG ASCIIDOCTOR_VERSION=2.0.10
ARG ASCIIDOCTOR_DIAGRAM_VERSION=2.0.2
RUN gem install --no-document \
"asciidoctor:${ASCIIDOCTOR_VERSION}" \
"asciidoctor-diagram:${ASCIIDOCTOR_DIAGRAM_VERSION}"
# Downloading latest manually as packages are a bit dated
RUN mkdir -p /usr/local/hugo \
&& curl -LO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz \
&& tar xzvf hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz -C /usr/local/hugo/ \
&& ln -s /usr/local/hugo/hugo /usr/local/bin/hugo \
&& rm hugo_extended_${HUGO_VERSION}_Linux-64bit.tar.gz
ENV PATH="/src/bin:${PATH}"
Modifying the GA workflow
Then using this docker image I change the Github Action workflow to this.
# ...
jobs:
build-deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:
submodules: true
fetch-depth: 0
- name: Build
run: docker run --rm --volume $PWD:/src bric3/hugo-builder hugo
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
publish_branch: master
publish_dir: ./public
cname: blog.arkey.fr
A note about speed
Using asciidoctor the rendering speed certainly took a hit, let’s compare some numbers. (It’s not reasonable benchmark though, but the magnitude of the hit certainly gives an indication).
❯ docker run --rm --volume $PWD:/src --publish "0.0.0.0:1313:1313" bric3/hugo-builder hugo serve --bind=0.0.0.0 --baseUrl=blog.local --buildDrafts
Building sites …
| EN-US
-------------------+--------
Pages | 378
Paginator pages | 1
Non-page files | 18
Static files | 75
Processed images | 0
Aliases | 2
Sitemaps | 1
Cleaned | 0
Built in 27921 ms (1)
Watching for changes in /src/{archetypes,assets,content,data,layouts,static,themes}
Watching for config changes in /src/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 //blog.local:1313/ (bind address 0.0.0.0)
Press Ctrl+C to stop
^C% ❯ docker run --rm --volume $PWD:/src --publish "0.0.0.0:1313:1313" bric3/hugo-builder hugo serve --bind=0.0.0.0 --baseUrl=blog.local --buildDrafts
❯ env PATH=$PWD/bin:$PATH hugo serve --baseUrl=blog.local --bind=0.0.0.0 --buildDrafts
| EN-US
-------------------+--------
Pages | 378
Paginator pages | 1
Non-page files | 18
Static files | 75
Processed images | 0
Aliases | 2
Sitemaps | 1
Cleaned | 0
Built in 4767 ms (2)
Watching for changes in /Users/bric3/private/bric3.github.io/{archetypes,assets,content,data,layouts,static,themes}
Watching for config changes in /Users/bric3/private/bric3.github.io/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 //blog.local:1313/ (bind address 0.0.0.0)
Press Ctrl+C to stop
^C%
❯ env PATH=$PWD/bin:$PATH hugo serve --baseUrl=blog.local --bind=0.0.0.0
| EN-US
-------------------+--------
Pages | 307
Paginator pages | 1
Non-page files | 0
Static files | 75
Processed images | 0
Aliases | 2
Sitemaps | 1
Cleaned | 0
Built in 145 ms (3)
Watching for changes in /Users/bric3/private/bric3.github.io/{archetypes,assets,content,data,layouts,static,themes}
Watching for config changes in /Users/bric3/private/bric3.github.io/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 //blog.local:1313/ (bind address 0.0.0.0)
Press Ctrl+C to stop
^C%
1 | ~28s to build the whole website in Docker with two asciidoctor articles and around ten diagrams. |
2 | ~4.8s seconds to build the whole website with two asciidoctor articles and around ten diagrams. |
3 | 145ms to build the whole website, but the two asciidoctor articles (those were drafts) |
The docker hugo serve
takes quite a long time, even when the site is rebuilt watching
the changes, so docker based may have to be used with care. Fortunately the local hugo serve
is much more fast to respond to change.
I’m using Docker Desktop for macOs Hardware : * 2,7 GHz Quad-Core Intel Core i7 * 16 GB 2133 MHz LPDDR3 |
Trying with Asciidoctorj
In order to see if speed improved, I tried to use asciidoctorj
instead,
it comes packed with asciidoctor-diagram by default, that’s useful.
#!/bin/sh
- ad="/usr/local/bin/asciidoctor"
+ ad="/usr/local/bin/asciidoctorj" (1)
basedir=./content
diagram_target=/assets/diagram
$ad --trace --verbose \
--base-dir ${basedir} \
--require asciidoctor-diagram \ (2)
--attribute icons=font \
--attribute docinfo=shared \
--no-header-footer \
--attribute nofooter \
--attribute sectlinks \
--attribute sectanchors \
--attribute figure-caption! \
--attribute source-highlighter=highlightjs \
--attribute toc-title! \
- - \
+ - 2> /dev/null (3)
1 | Use asciidoctorj , that bath is usually the one from Homebrew,
maybe Linuxbrew and others |
2 | Asciidoctorj 2.x is packed with asciidoctorj-diagram , and it’s not necessary
to install the gem, but it’s necessary to add the --require option. |
3 | I’m not yet sure why but any message appearing there are treated as errors by Hugo, which terminates the process, so this simply tell to ignore them. |
But in the end the speed is not quite that either, but this may be because I only have two Asciidoc articles at this time, so the JVM bootstrap doesn’t quite worth it. I’ll revisit this later if needed. Especially for the diagram part.
Wrap up
I went to Hugo because it supports Asciidoctor, however I didn’t expect so much work to benefit from a near complete Asciidoctor experience. And the current work isn’t even over.
I wasn’t looking for such asciidoctor or asciidoc tag when bootstrapping the site, but looking now I wish there was theme with asciidoctor support right out of the box, yet no theme have the asciidoctor tag at this time.
I really must thank all the people that blogged about this before, they really helped to make this happen.
Over the time I need to tackle some remaining topic
-
[ ] Some color codes are missing, see #_text[this section] of the smoke test
-
[ ] Table of content
-
[ ] Extract colors in Sass variables
-
[ ] Investigate custom macros, also see the extension lab
-
[ ] Investigate
-a data-uri
or-a diagram-svg-type=inline
-
[ ] Charts macro
-
[ ] MathJax (stem)
The last two point could certainly be made optional by adding a toggle in the front matter that can activate something in the theme.
What really helped me was the help of a smoke test content to check what feature works or not, I adapted this gist from Dan Allen who is the project lead of asciidoctor:
Smoke test example
Not everything is rendered in a example block, like titles
= Asciidoctor Demo
Dan Allen <[email protected]>
-
emoji :plus: :spade:
-
html +
This is a demonstration of asciidoctor-ruby. And this is the preamble of this document.
If you want the output to look familiar, copy (or link) the AsciiDoc stylesheet, asciidoc.css, to the output directory. |
Items marked with TODO are either not yet supported or a work in progress. |
== First Steps with AsciiDoc
-
single quotes around a phrase place 'emphasis'
-
astericks around a phrase make the text bold
-
double astericks around one or more letters in a word make those letters bold
-
double underscore around a substring in a word emphasize that substring
-
use carrots around characters to make them superscript
-
use tildes around characters to make them subscript
-
to pass through HTML directly, surround the text with triple plus
-
characters can be escaped using a \
-
for instance, you can escape a quote inside emphasized text like 'Here's Johnny!'
-
-
you can safely use reserved XML characters like <, > and &, which are escaped when rendering
-
force a space between inline elements using the {sp} attribute
-
hold text together with an intrinsic non-breaking space attribute, {nbsp}
-
handle words with unicode characters like in the name Gregory Romé
-
claim your copyright ©, registered trademark ® or trademark ™
You can write text with inline links, optionally using an explicit link prefix. In either case, the link can have a query string.
If you want to break a line
just end it in a + sign
and continue typing on the next line.
=== Lists Upon Lists
-
this list
-
should join
-
to have
-
four items
-
These items
-
will be auto-numbered
-
and can be nested
-
-
A numbered list can nest
-
unordered
-
list
-
items
-
I swear I left it in 'Guy's' car. Let's go look for it.
This should be a standalone paragraph, not grabbed by the definition list.
-
first level written on two lines
-
first level
with this literal text
-
second level
-
third level
-
fourth level
-
-
-
-
back to
first level
Let’s make a horizontal rule…
then take a break.
== We’re back!
Want to see a ?
Do you feel safer with the tiger in a box?
Optional Title
This is an example
single-paragraph note.
|
Optional Title
This is an example
single-paragraph note.
|
Tip. |
Important. |
Warning. |
Caution. |
*Listing* Block Use: code or file listings
Example Block
Use: examples :)
Default caption "Example:" can be changed using
[caption="Custom: "]
before example block.
Optional Title
NOTE Block Use: multi-paragraph notes. |
*Literal* Block Use: workaround when literal paragraph (indented) like 1. First. 2. Second. incorrectly processed as list.
Quote Block
Use: cite somebody
cite source
== Text
normal, italic, bold, mono.
``double quoted'', `single quoted'.
normal, super, sub.
Command: ls -al
mono *bold*
passthru bold
Path: '/some/filez.txt', '.b'
red text on yellow large all bold
aqua aqua-background black black-background blue blue-background fuchsia fuchsia-background gray gray-background green green-background lime lime-background maroon maroon-background olive olive-background purple purple-background red red-background silver silver-background teal teal-background white white-background yellow yellow-background
Chars: nibmr
Escaped: _italic_, _italic_, t__e__st, t__e__st, bold, <b>normal</b> ¶ `not single quoted' \`\`not double quoted''
== Images
First home , second home .
== Lists
-
bullet
-
bullet
-
bullet
-
bullet
-
-
bullet
-
bullet
-
bullet
-
bullet
-
bullet
-
bullet
-
bullet
-
bullet
-
bullet
-
-
bullet
-
-
bullet
-
-
bullet
-
-
bullet
-
bullet
-
bullet
-
-
number
-
number
-
letter
-
letter
-
-
number
-
loweralpha
-
loweralpha
-
lowerroman
-
lowerroman
-
upperalpha
-
upperalpha
-
upperroman
-
upperroman
-
-
upperalpha
-
-
lowerroman
-
-
loweralpha
-
-
number
-
letter
-
letter
-
letter2
-
letter2
-
number
-
number
-
number2
-
number2
-
number2
-
number2
-
-
number
-
-
letter2
-
-
letter
- Term 1
-
Definition 1
- Term 2
-
Definition 2
- Term 2.1
-
Definition 2.1
- Term 2.2
-
Definition 2.2
- Term 3
-
Definition 3
- Term 4
-
Definition 4
- Term 4.1
-
Definition 4.1
- Term 4.2
-
Definition 4.2
- Term 4.2.1
-
Definition 4.2.1
- Term 4.2.2
-
Definition 4.2.2
- Term 4.3
-
Definition 4.3
- Term 5
-
Definition 5
- Term 1
-
Definition 1
- Term 1.1
-
Definition 1.1
Term 1 |
Definition 1 |
Term 2 |
Definition 2 |
Term 2.1 |
Definition 2.1 |
Term 2.2 |
Definition 2.2
|
Term 4.1 |
Definition 4.1 |
Term 4.2 |
Definition 4.2 |
Term 4.2.1 |
Definition 4.2.1 |
Term 4.2.2 |
Definition 4.2.2
|
-
Question 1
Answer 1
-
Question 2
Answer 2
-
bullet
-
another bullet
-
number
-
again number
-
letter
-
again letter
-
letter
-
-
-
number
-
-
-
bullet
-
-
bullet
-
number
-
number
Independent paragraph break list.
-
number
-
number
-
List block define list boundary too
-
number
-
number
-
number
-
number
-
bullet continuation
-
number continuation
-
bullet
literal continuation
-
letter
Non-literal continuation.
any block can be included in list
Last continuation.
-
-
-
-
bullet
-
bullet
-
bullet
-
bullet
-
-
-
bullet
-
-
bullet
-
number
-
letter
-
number
-
letter
-
-
-
letter
-
-
number
-
Col 1 | Col 2 | Col 3 |
---|---|---|
1 |
Item 1 |
a |
2 |
Item 2 |
b |
3 |
Item 3 |
c |
6 |
Three items |
d |
1 |
2 |
3 |
4 |
a |
b |
c |
d |
A |
B |
C |
D |
ID | FName | LName | Address | Phone |
---|---|---|---|---|
1 |
Vasya |
Pupkin |
London |
|
2 |
X |
Y |
A,B |
|
Date | Duration | Avg HR | Notes |
---|---|---|---|
22-Aug-08 |
10:24 |
157 |
Worked out MSHR (max sustainable heart rate) by going hard for this interval. |
22-Aug-08 |
152 |
Back-to-back with previous interval. |
|
24-Aug-08 |
none |
doc = Asciidoctor::Document.new("*This* is it!", :header_footer => false)
puts doc.render
Here’s what it outputs (using the built-in templates):
<div class="paragraph"> <p><strong>This</strong> is it!</p> </div>
=== ``Quotes''
AsciiDoc is 'so' powerful!
This verse comes to mind.
La la la
Here’s another quote:
When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.
The Adventures of Sherlock Holmes
Want to get literal? Just prefix a line with a space (just one will do).
I'll join that party, too.
We forgot to mention in Numbered lists that you can change the numbering style.
-
first item (yeah!)
-
second item, looking
so mono
-
third item, mono it is!
That was literal
=== Passthrough block
Passthrough means pure HTML
Ghost from this codepen== Wrap-up
AsciiDoc is quite cool, you should try it! |
Here’s a reference to the definition of another term, in case you forgot it.
One more thing. Happy documenting! |
When all else fails, head over to http://google.com.
PlantUML smoke test example
Not everything is rendered in a example block, like titles
attribute diagram-svg-type
: inline
== Sequence diagram
== Activity diagrams (the new one)
== Timing diagram
== Gantt diagram
== Wireframe
== Ditaa
== Sprites diagram
EDIT 2021-01-22: The asciidoctor-diagram:2.1.0 saw some changes and now ships with few dependencies for some diagram component. PlantUML in particular saw a braking change in the way it handles GraphViz dot diagrams, it doesn’t support anymore jdot and instead require to use smetana.
-
asciidoctor-diagram:2.1.0
-
asciidoctor-diagram-ditaamini:0.13.1
-
asciidoctor-diagram-plantuml:1.2021.0
- !pragma graphviz_dot jdot
+ !pragma graphviz_dot smetana
Following diagrams today require GraphViz’s dot
binary, a possible
alternative would be to use an abandoned port (3 years without update)
of dot
in Java, however not everything is supported, like arrows.
!pragma graphviz_dot jdot
== Component diagram
== State diagram
== Object diagram
== Class diagram
== Use-case diagram
== Deployment diagram
== Available archimate sprites
== Archimate sprites
Macros
Ctrl+Shift+N
OK
ruby, asciidoctor
ruby, asciidoctor
\$sqrt(4) = 2\$
\$H_2O\$
\$[[a,b],[c,d]]((n),(k))\$
\(C = \alpha + \beta Y^{\gamma} + \epsilon\)
[1]
Block switch
<dependency>
<groupId>com.example</groupId>
<artifactId>some-library</artifactId>
<version>1.2.3</version>
</dependency>
implementation 'com.example:some-library:1.2.3'
implementation("com.example:some-library:1.2.3")
maven_jar(
name = "jackson-annotations",
artifact = "com.example:some-library:1.2.3",
sha1 = "c626020ae55d19c690d25cb51c1532ba76e5890f",
)
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.0</version>
<type>bundle</type>
</dependency>
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.11.0'
implementation("com.fasterxml.jackson.core:jackson-annotations:2.11.0")
maven_jar(
name = "jackson-annotations",
artifact = "com.fasterxml.jackson.core:jackson-annotations:2.11.0",
sha1 = "c626020ae55d19c690d25cb51c1532ba76e5890f",
)
aaa
bbb
{
"a" : "b",
"c" : [
{ "d" : "e" },
{ "d" : "f" },
{ "d" : "g" },
{ "d" : "h" }
]
}
A |
B |
1 |
2 |
Hugo shortcodes
Hugo 0.24 Released: Big archetype update + @Netlify _redirects etc. file supporthttps://t.co/X94FmYDEZJ #gohugo #golang @spf13 @bepsays
— GoHugo.io (@GoHugoIO) June 21, 2017