Configuring the AsciiDoctor Maven Plugin

AsciiDoc is a great way to write technical documentation. It is text based, can be committed and versionned in your VSC with your project, has a rich syntax, has a huge ecosystem, integrates with several tools (such as PlantUML that I love) and, if there is still something missing, you can use extensions or create your own. And if you use the asciidoctor-maven-plugin to automatically generate all your documentation, you end up customizing it.

In this post I explain a few configurations that I use in the asciidoctor-maven-plugin.

Including remote code in your documentation

If like me you code and write documentation about your code with AsciiDoctor, you might use the source code block with syntax highlighting. So, you copy/paste your code into an Asciidoc [ source ] block and you can even give it a code highlighter (here, coderay), a language (Java), a title and so on. Then, you realize that you don’t want to copy/paste code, you just want to point at the code itself. So, if the Java file Book.java is sitting on your drive, you use the include:: directive and pass it the relative or absolute path. If you don’t want to include all the file, you can add just a portion of it, by using tags (eg. here the tag is called snipped).

== Using include with a local file

[ source ]
----
include::/Users/agoncal/Code/src/main/java/Book.java[tag=snippets]
----

This is much better than copy/paste as you can change your code, and it will get updated in your documentation once you re-generate it. Then, you realize that you don’t want to point at a file on your disk, but on a remote file on GitHub. Asciidoctor allows you to put a URI in the include directive:

== Using include with a remote file

[ source ]
----
include::https://raw.githubusercontent.com/agoncal/agoncal-book-javaee7/master/src/main/java/org/agoncal/Book.java[tag=snippets]
----

This will not work because you need to allow Asciidoctor to access remote URIs by passing the <allow-uri-read/> attribute. For security reasons you can’t just add this attribute to the document itself (with a : :allow-uri-read:), but instead, pass it on the pom.xml:

[sourcecode language=”xml” title=”pom.xml” highlight=”6″]
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<configuration>
<attributes>
<allow-uri-read/>
</attributes>
</configuration>
[/sourcecode]

Including Diagrams

If, like me, you use PlantUML, you either have the choice to create your diagrams in separate .puml files and include them in your document, or embed them straight into your .adoc file. Asciidoctor has a nice integration with PlantUML. You can add a diagram straight into the document:

== PlantUML Diagram

[plantuml,auth-protocol]
....
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response

Alice -> Bob: Another authentication Request
Alice <-- Bob: another authentication Response
....

For that to work, you need to setup the asciidoctor-diagram dependencies:

[sourcecode language=”xml” title=”pom.xml” highlight=”7,13,16″]
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj-diagram</artifactId>
<version>${asciidoctorj.diagram.version}</version>
</dependency>
</dependencies>
<configuration>
<attributes>
<data-uri/>
</attributes>
<requires>
<require>asciidoctor-diagram</require>
</requires>
</configuration>
[/sourcecode]

Notice the data-uri attribute. You can either set it on the pom.xml or straight into the document itself with :data-uri:. This allows you to embed the image straight into the HTML itself using the <img src="data:image/png;base64> syntax.

Using Extensions

If you think that Asciidoctor is only great, it’s because you don’t know extensions! With extensions, the sky is the limit to Asciidoctor. There are a few official and third party extensions, you can either build your own using an API, and play with the nice Asciidoctor Extensions Lab. The catalog of this lab extension is quite large and you can easily use the ones you want.

Let’s say I want to use emojicons in my document and also refer to Gists, I have two extensions that I can use: the Emoji Inline Extension and the Gist Block Macro.

== Emoji Inline Extension (emoji-inline-macro.rb)

I trully emoji:heart[lg] my little green emoji:turtle[1x]!

== Gist Block Extension (gist-block-macro.rb)

.A Gist from Dan Allen
gist::mojavelinux/5546622[]

But before using these extensions, you need to copy the Ruby files (here, under ${project.basedir}/src/main/asciidoc-extensions) and configure them in the pom.xml as follow (notice the allow-uri-read attribute to allow reading from external URIs for Gist in this example):

[sourcecode language=”xml” title=”pom.xml” highlight=”6,9,10″]
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<configuration>
<attributes>
<allow-uri-read/>
</attributes>
<requires>
<require>${project.basedir}/src/main/asciidoc-extensions/emoji-inline-macro.rb</require>
<require>${project.basedir}/src/main/asciidoc-extensions/gist-block-macro.rb</require>
</requires>
</configuration>
[/sourcecode]

Installing Gems

When you use extensions, sometimes, you hit an error because a Gem is not installed. For example, if you need a Lorem Ipsum in your document, there is an extension for generating it: lorem-block-macro. But if you use it as explained above, you will get an exception because this extension needs the Midlleman Gem. You can install this Gem in different ways… or leave your good old Maven to do it.

The Middleman Gem is published in the rubygems.org repository. And the RubyGem repository is proxied by TorqueBox at http://rubygems-proxy.torquebox.org. So it’s just a matter of adding this repository in your pom.xml and getting MiddleMan through Maven coordinates and the <type>gem</type>:

[sourcecode language=”xml” title=”pom.xml” highlight=”4,6,13″]
<dependencies>
<dependency>
<groupId>rubygems</groupId>
<artifactId>middleman</artifactId>
<version>4.2.1</version>
<type>gem</type>
</dependency>
</dependencies>
<repositories>
<repository>
<id>rubygems-proxy</id>
<name>Rubygems Proxy</name>
<url>http://rubygems-proxy.torquebox.org/releases</url&gt;
<layout>default</layout>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>
</repositories>
[/sourcecode]

We got the Gem into our Maven repository, but now we need to install it. For that we use the Maven Gem plugin and set it up on the Maven initialize phase. A simple mvn initialize will install all the needed Gems for Middleman in your target/rubygems directory:

[sourcecode language=”xml” title=”pom.xml” highlight=”4,6,13″]
<plugin>
<groupId>de.saumya.mojo</groupId>
<artifactId>gem-maven-plugin</artifactId>
<version>${version.gem.maven.plugin}</version>
<configuration>
<skip>true</skip>
<jrubyVersion>${version.jruby}</jrubyVersion>
</configuration>
<executions>
<execution>
<goals>
<goal>initialize</goal>
</goals>
</execution>
</executions>
</plugin>
[/sourcecode]

Then, it’s just a matter of using the Lorempsum extension straight into your document:

== Lorem Extension (lorem-block-macro.rb)

lorem::sentences[5]

Conclusion

Because I am mostly Maven centric, I like to automatically generate documentation from Maven, so I use extensively the asciidoctor-maven-plugin. But I have to say, sometimes I get lost in the documentation to find what I need. The Asciidoctor examples don’t always give the Maven configuration, so you have to spend some time trying around (check the asciidoctor-maven-examples).

Look at the entire code of my samples above and if you have any other tips or suggestions on how to configure the asciidoctor-maven-plugin, don’t hesitate to leave a comment, create an issue or push a PR.

References

One thought on “Configuring the AsciiDoctor Maven Plugin

  1. Thanks for sharing your ideas. It’s interesting espcially the part where you embed plant uml diagrams.
    Can you provide a working example on how to include .puml files directly within an .adoc file? You mentioned to use the “” syntax. But I don’t get it to work

Leave a Reply