AsciidoctorJ 1.6.0 released, at last!

by Robert Panzer, Dan Allen and Sarah White -

After several years of brewing (or perhaps barrel aging?), we have finally released AsciidoctorJ 1.6.0! The artifacts are available from Bintray and Maven Central.

What is AsciidoctorJ?

AsciidoctorJ is the official library for running Asciidoctor on the JVM. With AsciidoctorJ, you can convert AsciiDoc content, analyze the structure of a parsed AsciiDoc document, and write Asciidoctor extensions in Java and other JVM languages.

Before you upgrade, there are important things you need to know, which this post covers. While AsciidoctorJ is still built on the strong foundation of the Asciidoctor RubyGem, it has matured into a project in its own right. This release brings stability and key enhancements to new and existing users alike. Grab a glass so we can pour you all the details.

A major stepping-stone to SemVer

Despite its version number, this release should be considered a major release. As such, it’s not binary compatible with the 1.5.x releases.

AsciidoctorJ 1.6.0 is a final, transitional release in preparation for the switch to Semantic Versioning (SemVer). We’re breaking the rules one last time, but for good reason. Given how long the 1.6.0 branch has been barrel aging, we wanted to allow it to be tapped to gather feedback and tease out unexpected surprises before making the jump to 2.0.0 and SemVer. If all goes well, we expect the 2.0.0 release to follow shortly after this one. At that point, we’ll begin versioning AsciidoctorJ according to the SemVer rules.

To learn more about SemVer and how it affects the Asciidoctor projects in general, see Making the Switch to Semantic Versioning.

Switching to SemVer also means that AsciidoctorJ will now be versioned independently of Asciidoctor. AsciidoctorJ has evolved into much more than just the Asciidoctor RubyGem repackaged for the JVM. It has a complete API, including Java-based extensions and tight integration with the Java ecosystem (e.g., JUL, Ruby object bridging, etc). Its own independent version line will allow it to evolve more quickly and help everyone better understand what to expect in each release. Most important, it will address the very situation that backed up the 1.6.0 release for several years.

New features

Major API and packaging changes

Since the start of AsciidoctorJ, we’ve learned so much about JRuby and how it bridges Ruby and Java objects. Using that knowledge, we’ve completely redesigned the low-level integration to address shortcomings in the original design.

That redesign required us to make breaking changes to the API, which were absolutely necessary for AsciidoctorJ to continue to move forward. But it also provided us with the opportunity to fix numerous bugs that could not be fixed in the 1.5.x line without disrupting compatibility. You’ll be happy to know that the redesign eliminates glitches that may have bitten you when writing extensions or navigating the document model using the 1.5.x releases.

As part of this change, we split the API and implementation classes into separate packages and JARs to properly isolate them. We also reconciled the competing document models by mapping all the node types in Asciidoctor and removing the ContentPart and StructuredDocument APIs. Refer to the API docs (api, impl) to see what types are available and how they are organized.

Reworked extension API

Thanks to the redesign, the JRuby-based implementation is much better hidden behind the API. In particular, there are no more references in the API to the RubyObject class from JRuby.

The interfaces for the Abstract Syntax Tree (AST) were completely renamed to better represent their purpose. For example, the AbstractNode interface was renamed to ContentNode, AbstractBlock was renamed to StructuralNode, and Inline was renamed to PhraseNode. Even more of the AST has been mapped in Java, including list and definition lists, as well as helpers for creating a table structure in an extension processor.

Overall, the APIs for extensions and the AST should feel like a pure Java library (e.g., getAttr() is now getAttribute()). You can even define extension processors using annotation-based configuration (e.g., @Name).

Check out the integrator’s guide to learn all about it and find lots of examples.

Added converter API

A new converter API has been introduced, making it possible to implement a converter for a custom output format entirely in Java. This API allows you to extend Asciidoctor from Java, similar to what you could already do using the extension APIs. You can learn how to use this new API by following the converter documentation.

In fact, there’s already one converter that’s using this API from Groovy to convert AsciiDoc to Leanpub-flavored Markdown.

Access to Asciidoctor’s logs

Asciidoctor logs error and warning messages to the Ruby logger whenever it encounters a problem in the document. When integrating Asciidoctor into your own software, it’s important to capture these log messages in order to handle them appropriately. Previously, these messages were out of reach of AsciidoctorJ. That’s no longer the case. The new Log Handling API picks up messages logged in Asciidoctor and routes them to your own log handler.

Better documentation

AsciidoctorJ 1.6.0 offers extended and tested documentation for writing extension and converters. This documentation is guaranteed to be correct because it’s tested with every commit ;) And the process is underway to incorporate the documentation into the new Antora-based documentation site for Asciidoctor.

Refer to the release notes for a more detailed account of what changed in this release. Keep in mind that, since the development of 1.6.0 ran in parallel with 1.5.x for so long, many changes from 1.6.0 may already be familiar to you as they were backported into the 1.5.x release line.

Migration notes

If you only use the Asciidoctor, Asciidoctor.Factory, and *Builder classes (e.g., Asciidoctor#convertFile), you likely don’t have to change your code. In fact, the Asciidoctor Maven Plugin and the Asciidoctor Gradle Plugin already work with this release, primarily because they only rely on the public load/convert APIs.

The necessary changes to the AST and extension APIs did introduce breaking changes that require modifying your existing extensions. Migrating an extension is a matter of conforming to the new API. This mostly involves switching to the new names for AST interfaces and aligning with the updated method signatures. Aside from the name and signature changes, the API should still be recognizable and thus compatible with your existing logic.

Here are several examples of extensions written for both AsciidoctorJ 1.5.8 and 1.6.0 to give you an idea of the types of changes to look out for:

If you have difficulty migrating your extension or document introspection code, please file an issues in the issue tracker so we can find a path forward.

Java compatibility

Asciidoctor 1.6.0 requires at least Java 8. It also runs on, and is tested against, Java 11.

Starting in AsciidoctorJ 1.6.0, the project will align its Java compatibility with the official Oracle Java SE support roadmap. While AsciidoctorJ doesn’t require Oracle Java SE, that roadmap serves as a useful signpost for which versions of Java are considered current.

Asciidoctor 1.6.0 does not yet support running on the module path, a key feature of the Java Platform Module System introduced in Java 9. We’d like to get there in an upcoming version. That will depend, however, on the progress AsciidoctorJ’s dependencies make towards this goal, most notably JRuby. Despite this limitation, you can still run Asciidoctor 1.6.0 on Java 11.


We’d like to take this opportunity to name several key individuals who came together to make this release what it is today.

  • Jérémie Bresson for initiating the split between the API and implementation packages and modernizing the API signatures.

  • Abel Romero for his help with the design of the JUL logging integration and for testing it in the Maven plugin first.

  • Frank Becker for overhauling and streamlining the Gradle build.

  • Guillaume Grossetie for loads of cleanups and improvements across the API and implementation and for stress testing the redesign by launching AsciidoctorG.

  • Charles Nutter, Thomas Enebo, and the JRuby team for creating and maintaining JRuby, on which AsciidoctorJ is based.

  • And finally, our “elder”, Alex Soto for starting the AsciidoctorJ project and showing us a vision of what’s possible.

Of course, there are many more people to thank. As we’ve said many times, this project would not be possible without the incredible work and collaboration by the many volunteers who work on it. So, thank you!

Outlook for 2.0.0

The breaking changes aren’t over just yet. Heading towards 2.0.0, we want to further split the API of AsciidoctorJ and its implementation. Our big goal is to support alternative implementations underneath, such as Asciidoctor.js, using the same public API.

To help us get to 2.0.0, we ask that you test 1.6.0 and let us know if you run into any problems or changes that prevent you from migrating to it. Now’s the chance to get it right before the 2.0.0 release. Please file any issues you find in the issue tracker.

Thank you for coming on this journey with us as we work to bring the very best of AsciiDoc to the JVM.

Asciidoclet 1.5.0 released!

by John Ericksen and Ben Evans -

Following on from the releases of Asciidoctor 1.5.0 and AsciidoctorJ 1.5.0, version 1.5.0 of Asciidoclet has been released with several significant new features, including a new look & feel!

What is Asciidoclet?

Asciidoclet allows Java developers to write Javadoc comments in the portable and rich AsciiDoc syntax instead of HTML.

In short, why write messy Javadoc like this?

 * This class has the following features:
 * <ul>
 *   <li>Support for <strong>foo</strong></li>
 *   <li>Support for bar</li>
 * </ul>
public class Thing implements Something { ... }

…​when you can write tidy Javadoc like this!

 * This class has the following features:
 * - Support for *foo*
 * - Support for bar
public class Thing implements Something { ... }

Much better! Now comments in the source code are much easier to read and write and can be reused outside of Javadoc. Best of all, the HTML generated from Javadoc still looks great (perhaps even better).

Of course, this example just scratches the surface of what’s possible. Tables, lists, code examples with syntax highlighting, links, includes and all of Asciidoctor’s capabilities are available via the lightweight AsciiDoc syntax.

Now, developers can focus on content rather than formatting, and still achieve a beautiful end result.

Artifact information

Artifact information (jCenter @ Bintray)
Group Id Artifact Id Version Download




pom jar javadoc (jar) sources (jar)

Artifact information (Maven Central)
Group Id Artifact Id Version Download




pom jar javadoc (jar) sources (jar)


In Maven, just add the Asciidoclet doclet name and artifact to the maven-javadoc-plugin declaration:


See the Asciidoclet guide for examples that apply to other build systems and all the available doclet options.

Release highlights

Built on Asciidoctor 1.5.0

Asciidoclet inherits all of the improvements from Asciidoctor 1.5.0 and AsciidoctorJ 1.5.0.

Asciidoctor 1.5.0 introduced some syntax changes. Please refer to the migration guide for details about how to migrate your content.

Improved stylesheets

Asciidoclet includes a default stylesheet with styles from Asciidoctor 1.5.0. This means that AsciiDoc content in the Javadoc is rendered with a similar look and feel to Asciidoctor in other environments.

Javadoc output
Figure 1. Example Javadoc using the Java 8-derived stylesheet

Javadoc’s HTML output varies between releases of the Java platform, so Asciidoclet selects an appropriate stylesheet based on the Java version it is running under:

  • For Java 7 & 8, a stylesheet based on the default Java 8 Javadoc stylesheet is used.

  • For Java 5 & 6, the stylesheet is based on the Java 6 Javadoc stylesheet.

If you want to use your own stylesheet, you can still do this by using Javadoc’s -stylesheetfile option.

AsciiDoc overview files

Javadoc’s -overview option lets you specify an HTML file that will be used as the overview or index page in the generated documentation. This is especially useful for larger projects, where the overview can provide users with a useful introduction and help them to navigate the API.

Asciidoclet now supports overview files written in AsciiDoc as well, with full support for AsciiDoc features such as includes and document attributes. Overview files named *.adoc, *.ad, *.asciidoc or *.txt are processed by Asciidoclet. Other files are assumed to be HTML, and will be processed by Javadoc’s standard doclet.

Document attributes

Asciidoclet now fully supports Asciidoctor’s document attributes. These are one of Asciidoctor’s most powerful features. Document attributes are parameters that can be passed to Asciidoctor to affect how the final output is generated.

Attributes are specified using one or more -a (or --attribute) options when running Asciidoclet. The --attributes-file option reads attributes from an AsciiDoc file. The attributes are passed to Asciidoctor when it renders Javadoc comments.

Here are some examples of how document attributes might be useful in your Javadoc.

Variable substitution

Attribute references in Javadoc comments or overview files are replaced with attribute values:

 * {product-name} will change your life!
 * @version {version}

When the doclet is run with -a product-name=Foo -a version=1.0, Asciidoctor replaces all {product-name} and {version} attribute references with the given values in the generated HTML output. This makes it very simple to inject values into the Javadoc, without changing the source.

Conditional inclusion

AsciiDoc’s conditional directives can selectively include content based on the presence or absence of attributes. This is useful when the same AsciiDoc source is used in different environments.

For example, if you wanted to reuse the same AsciiDoc content in your Javadoc overview page and your web site, but with some differences, you can use attributes to tell Asciidoctor when certain content should be included:

= Documentation for the Foo project

// content that should only appear in Javadoc

// content that should only appear on the web site

Asciidoclet automatically sets the javadoc attribute when it runs, so Javadoc-only content can easily be selected. You can of course define your own attributes as well.

Java and Ruby extension support

Asciidoctor can be extended using Java or Ruby libraries, and Asciidoclet inherits this capability as well.

  • Java extensions are loaded automatically when they are made available in the classpath, using AsciidoctorJ’s Extension SPI.

  • Ruby libraries (Gems) are loaded using the -r (or --require) option.

When using the --require option, we recommend specifying the --gem-path option as well to explicitly set the location of installed gems. Doing so ensures that your build remains portable and reproducible. You can use the gem-maven-plugin to install gems directly into your build directory.

Many extensions are available, but one that is probably most useful for Javadoc authors is Asciidoctor Diagram. Let’s see how it can be used with Asciidoclet.

Embedding diagrams in Javadoc

Asciidoctor Diagram is a popular Asciidoctor extension that lets you embed plain text diagram descriptions in your AsciiDoc source, which get rendered to images when Asciidoctor runs. This can be extremely valuable in Javadoc for describing the architecture or behavior implemeted by the software.

Here’s an example of a Javadoc comment containing a PlantUML sequence diagram:

 * This class implements the following protocol:
 * [plantuml]
 * ....
 * Alice -> Bob: Authentication Request
 * Bob --> Alice: Authentication Response
 * Alice -> Bob: Another authentication Request
 * Alice <-- Bob: another authentication Response
 * ....
public class AuthServer { ... }

Here’s how the diagram above appears in the Javadoc output:

Example output using Asciidoctor Diagram
Figure 2. Example output using Asciidoctor Diagram

Not bad! Developers can easily view and update diagrams in plain text, and users reading the Javadoc will see nicely rendered images.

Many other types of diagrams are supported, including Graphviz, blockdiag and ditaa. See the documentation for Asciidoctor Diagram for more examples.

To enable Asciidoctor Diagram support in Asciidoclet:

  1. Install the Asciidoctor Diagram gem, asciidoctor-diagram:

    $ gem install asciidoctor-diagram
  2. Run Asciidoclet with the following doclet options:

    --require asciidoctor-diagram
    --gem-path ${env.GEM_PATH} (1)
    --attribute data-uri (2)
    1 The --gem-path ${env.GEM_PATH} option tells Asciidoctor’s JRuby runtime where to find gems when using --require (effectively setting the $GEM_PATH environment variable internally).
    2 The data-uri attribute is required so that the image data is embedded inside the generated HTML files.[1]
  3. Admire the beautiful diagrams adorning your Javadoc!


We hope this new version makes your Javadocs even better. We appreciate everyone who has contributed to Asciidoclet. If you have ideas about how to improve on it, ideas and pull requests are always welcome via the repository on GitHub.

1. Without the data-uri attribute, Asciidoctor Diagram writes image files to a location that doesn’t line up with the generated HTML. This problem is being addressed in Asciidoctor Diagram at the time of writing. Refer to issue #39 for details.

Asciidoctor.js 1.5.0 released to Bower and npm!

by Guillaume Grossetie and Anthonny Quérouil -

The release train is on the move! Version 1.5.0 of Asciidoctor.js has been released and is now available in Bower and npm. This release is an important step toward making Asciidoctor.js widely available to the JavaScript ecosystem.

Bower and npm
Asciidoctor in JavaScript.
It was a dream.
Then it was a prototype.
Now, it’s the real deal.
What is Asciidoctor.js?

Asciidoctor.js is the official library for using Asciidoctor in JavaScript. It shares the same source code as Asciidoctor and is transcompiled to JavaScript using Opal. With Asciidoctor.js, you can convert AsciiDoc content or analyze the structure of a parsed AsciiDoc document from JavaScript.

When upgrading to Asciidoctor 1.5.0, please refer to the migration guide for details about how to migrate your content.

Release highlights

Asciidoctor.js is Asciidoctor

As mentioned in the release notes for Asciidoctor 1.5.0, we worked hard to align Asciidoctor.js (JavaScript) and Asciidoctor core (Ruby). That means you can expect Asciidoctor.js to parse and convert documents just like the original. Even includes work!

Getting certain features to work, like includes, requires special consideration because JavaScript is a different environment than Ruby and there are even key variations between JavaScript environments!

For example, reading an include file in Ruby is just a matter of using the normal Ruby IO API. In a browser environment, we have to use XMLHttpRequest (i.e., Ajax) as the IO API instead. If Asciidoctor.js is running on Node.js, we have to use the Node IO API, fs.readSync(), to make it work.

Rest assured we’re continuing to work on smoothing any differences to bring all the great features of Asciidoctor core to JavaScript.

Read on to learn how to get your hands on Asciidoctor.js!

Using Asciidoctor.js is easier than ever before

If you are a frontend or backend JavaScript developer, you’re only one command away from getting the latest version of Asciidoctor.js

Bower package

Installing Asciidoctor.js with Bower
$ bower install asciidoctor.js --save
The optional --save flag automatically adds the package to your project’s dependencies.

Once the package installed, you can add the following script tag to your HTML page:

<script src="bower_components/asciidoctor.js/dist/asciidoctor-all.min.js"></script>

The asciidoctor-all.min.js is a minified version and includes Asciidoctor core, extensions API and Opal.

Here is a simple example that converts AsciiDoc to HTML5 using the doctype: 'inline' option and showtitle attribute:

var asciidoc = "[*Asciidoctor*] " +
    "running on[_Opal_] " +
    "brings AsciiDoc to the browser!";
var options = Opal.hash2(['doctype', 'attributes'], {doctype: 'inline', attributes: ['showtitle']});
var html = Opal.Asciidoctor.$convert(asciidoc, options);

See the Front-end development guide to learn more about the Bower package.

npm package

Installing Asciidoctor.js with npm
$ npm install asciidoctor.js --save
The optional --save flag automatically adds the package to your project’s dependencies.

Once the package is installed, the first thing to do is to load the asciidoctor.js module using require, then you’re ready to start using the API:

var asciidoctor = require('asciidoctor.js')(); (1)
var opal = asciidoctor.Opal; (2)

var processor = null;
var useExtensions = true;

if (useExtensions) {
  processor = asciidoctor.Asciidoctor(true); (3)
else {
  processor = asciidoctor.Asciidoctor(); (4)

var content = "[*Asciidoctor*] " +
    "running on[_Opal_] " +
    "brings AsciiDoc to Node.js!";
var options = opal.hash2(
    ['doctype', 'attributes'],
    {doctype: 'inline', attributes: ['showtitle']});
var html = processor.$convert(content, options); (5)
console.log(html); (6)
1 Load the Asciidoctor.js library
2 Retrieve and alias the top-level Opal namespace
3 Instantiate Asciidoctor with extensions enabled
4 Instantiate Asciidoctor without extensions
5 Convert AsciiDoc content to HTML5 using Asciidoctor.js
6 Print the HTML5 output to the console

Save the file as sample.js and run it using the node command:

$ node sample.js

You should see the following output in your terminal:

<a href=""><strong>Asciidoctor</strong></a> running on <a href=""><em>Opal</em></a> brings AsciiDoc to Node.js!</p>
To be successful with Asciidoctor.js, it’s important to understand how to work with Ruby objects in the JavaScript environment. We recommend that you browse the Opal documentation to learn how method names are mapped and what data types it expects.

See the Back-end development guide to learn more about the npm package.

Asciidoctor.js is heating up on Node

Node.js is where the hottest JavaScript is happening and npm is the package manager that manages and distributes that hotness. We wanted Asciidoctor.js to be a part of this ecosystem. We also needed it there to start building tools. That’s why we took the first step of packaging Asciidoctor.js as an npm package…​in fact, several! Asciidoctor now has a new playground!

Here are the npm packages that are published:


the main npm package for Asciidoctor.js


an npm package for processing AsciiDoc source files in your Grunt project

Here’s how the community is playing with these packages already:

asciidoc-preview (Atom Editor)

A plugin for Atom that shows you a preview of your document while you type!

asciidoc-preview (Brackets Editor)

An extension for Brackets that shows you a preview of your document while you type!


a static website generator for Grunt by @tedbergeron

Of course there are still challenges, but we’ll solve them. Head over to the Asciidoctor.js project to get involved.

Let us play this new game!

Asciidoctor.js on the JVM

You read that right. The browser ain’t the only JavaScript game in town. (And we’re not talking about JavaScript engines that have escaped from the browser, like Node.js.) We’re talking about the most polyglot of polyglot runtimes, the JVM.

Alex Soto is working at getting Asciidoctor.js integrated into AsciidoctorJ so you can use it on the JVM using Nashorn, dynjs and other JavaScript engines that run on it. The AsciidocFX project is already using Asciidoctor.js on Nashorn, so it’s more than just an idea!

There are still several challenges to tackle to ensure Asciidoctor.js runs smoothly on the JVM, such as getting includes working. Head over to the AsciidoctorJ project to get involved and help make it happen!


The alignment of Asciidoctor.js with Asciidoctor core was a major effort. It required input from a lot of people and they really pulled together to meet this challenge.

We want to especially thank the Opal developers, notably Adam Beynon, meh and Elia Schito, for making Asciidoctor.js happen. They were very responsive to our effort, making changes and fixes to Opal and generally providing input that allowed us to continuously move forward.

We also want to thank Anthonny Quérouil for crafting a Grunt build to compile, aggregate and compress Asciidoctor.js and for helping to get the artifacts published to Bower and npm.

Thanks to everyone who tested Asciidoctor.js, either directly or by using the tools. Your participation has helped Asciidoctor.js become the real deal!

If you have questions or feedback, we encourage you to participate in the discussion list. Talk to you there!

Asciidoctor Maven plugin 1.5.0 released!

by Dan Allen -

Storm in Desert

The West may still be suffering from a dry spell, but we’re excited to shower Maven users with the release of version 1.5.0 of the Asciidoctor Maven plugin to Maven Central and jCenter!

This version brings all the improvements from Asciidoctor 1.5.0 and AsciidoctorJ 1.5.0, plus enhancements to the site plugin. Like other versions before it, this plugin is based on the same version of the Asciidoctor and AsciidoctorJ projects (now using semantic versioning) — 1.5.0.

Artifact information

Artifact information (jCenter @ Bintray)
Group Id Artifact Id Version Download




pom jar javadoc (jar) sources (jar)

Artifact information (Maven Central)
Group Id Artifact Id Version Download




pom jar javadoc (jar) sources (jar)

Installing or upgrading

Installing or upgrading to 1.5.0 is simple. Just update the version in your pom.xml. All necessary dependencies will be pulled in via Maven’s dependency management.


Refer to the example project to copy-paste your way to greatness!

When upgrading to Asciidoctor 1.5.0, please refer to the migration guide for details about how to migrate your content.

Please refer to the manual for the Asciidoctor Maven plugin for information about configuration options and other capabilities of the plugin.

Release highlights

Published the jCenter

The Asciidoctor Maven plugin is now published to Bintray’s jCenter! The means you can find the plugin more easily and its published to the future destination of binaries on the web. You can elect to get notified by Bintray when new versions are available.

Copy non-AsciiDoc files to output directory (#67)

The Asciidoctor Maven plugin now copies non-AsciiDoc files to the output directory so you can put resources, such as images or stylesheets, in the AsciiDoc source folder. This change aligns the behavior of the Asciidoctor Maven plugin with the behavior of Gradle plugin.

Add configuration for setting the gem path and loading additional gems (#109)

You can now specify the location to one or more gem installation directories (i.e., GEM_PATH) using the gemPath configuration option. The main purpose of this setting is to load additional Ruby libraries not packaged in AsciidoctorJ, such as asciidoctor-diagram. You can load additional libraries (absolute path, relative path or gem name) using the require configuration option.

Here’s an example of how to use that configuration within the plugin stanza in your pom.xml:

You’ll need to use the gem-maven-plugin if you want to download and install gems automatically as part of your build. Refer to the example project to copy-paste your way to greatness!
Configure AsciidoctorJ in isolation (#111)

Prior to 1.5.0, the Maven plugin would allow JRuby to see gems installed external to the project if you had the GEM_HOME or GEM_PATH environment defined (typical if you’re using RVM). This could result in non-reproducible builds.

We’ve gone part of the way of solving this problem by clearing the GEM_PATH environment variable unless it’s specified in the plugin configuration. However, the GEM_HOME environment variable won’t be cleared properly until AsciidoctorJ 1.5.1. In the interim, we issue a warning in the build if GEM_HOME is set to a path outside the build so that you know to reset the value manually (e.g., by running rvm use system).

Properly handle false and empty attribute values (#93)

There was a regression in 0.1.4 that treated both false and empty attribute values as true. Maven needs hand holding to properly convert these values. You can now use an empty string value and it will mean enable the attribute or a false value and it will mean disable the attribute. For example:


This configuration is the equivalent of the following commandline arguments to Asciidoctor:

-a toc -a linkcss!
Generate XHTML in the Maven site plugin (#61)

One of the most important improvements in Asciidoctor 1.5.0 was the addition of the XHTML backend. Simply put, this backend emits XHTML5 (XML-compliant HTML5) instead of the shorthand HTML5 that is the norm. The main reason this backend was added was to fix the behavior of the site module in the Asciidoctor Maven plugin. The XML parser that the Maven site plugin uses will thank you!

EPUB3 output

AsciidoctorJ provides integration with the Asciidoctor EPUB3 converter out of the box. That means you can use it in the Maven plugin without having to declare any additional dependencies. Just set the backend to epub3 and you’re ready to go!

The EPUB3 converter is currently alpha. Expect some glitches while the dust settles!

For more information about issues fixed in this release, please see the 1.5.0 milestone in the issue tracker.


Thank you to all the contributors for helping out with this release, and for everyone involved in making Asciidoctor an awesome documentation toolchain and community! We particularly want to that the developers of the Asciidoctor Gradle plugin for giving us lots of ideas for how to make the Maven plugin great!

Enjoy building great documentation!

Asciidoctor Gradle plugin 1.5.0 released!

by Andres Almiray -

It took us longer than what we hoped but Asciidoctor Gradle plugin version 1.5.0 is finally here! The Asciidoctor Gradle plugin is based on AsciidoctorJ and, for the first time, aligns with its version numbering scheme.

Here’s the basic setup to get you started:

The plugin tracks the AsciidoctorJ version starting with this release, hence the jump from 0.7.3 to 1.5.0. There are many goodies inside Asciidoctor 1.5.0 as explained in the release notes, but perhaps the most interesting one for Gradle users is the capability to write custom extensions (or tag handlers if you will) using Groovy. You can include extensions just by placing their containing JAR in the classpath, or you can write them directly in your Gradle build, by placing the code inside buildSrc. There’s a trivial example of the latest option at

Other features found in this release are:

  • ability to load Ruby-based extensions using the requires property on AsciidoctorTask.

  • ability to set the gem installation path using the gemPath property on AsciidoctorTask.

Developers are advised to upgrade as soon as possible. Be mindful of the compatibility issues raised at the plugins’ readme. Do not forget to review the changes brought by Asciidoctor 1.5.0 found at the migration guide.

Figure 1. Basel Hackergarten @ Canoo July 24th

The development team would like to thank participants of various Hackergarten sessions, both in Switzerland and abroad. Several issues and features have been contributed during those sessions. We couldn’t have done it without your help. Also, thank you to all the contributors for helping out.

Go forth and make great (and Groovy) documentation once again!

Upgrading to 1.5.0 (recommended) is simple. Just update the version in your Gradle build file. All necessary dependencies should be pulled in via Gradle.

When upgrading to Asciidoctor 1.5.0, please refer to the migration guide for details about how to migrate your content.

For more information about issues fixed in this release, please see the 1.5.0 milestone in the issue tracker!

AsciidoctorJ 1.5.0 released!

by Alex Soto -

We’re thrilled to bring the latest Asciidoctor milestone, Asciidoctor 1.5.0, to the JVM as AsciidoctorJ 1.5.0!

What is AsciidoctorJ?

AsciidoctorJ is the official library for using Asciidoctor on the JVM. With AsciidoctorJ, you can convert AsciiDoc content or analyze the structure of a parsed AsciiDoc document from Java and other JVM languages.

Resolved Issues

The following issues have been resolved in version 1.5.0:

  • Added methods to register extensions to AsciidoctorJ which can be written in Ruby or Java. Resolves #90 and #157.

  • Creates an SPI so Java extensions can be registered automatically by simply adding the jar inside classpath. Resolves #97

  • Extension API is updated with modifications done in Asciidoctor 1.5.0. Resolves #113, #114, #148, #162 and #166.

  • Provides a method to unregister any extension previously registered. Resolves #122

  • Added -r and -I flags to CLI classes to require additional Ruby scripts and append to the load path, respectively. Resolves #171.

  • Added -V and --version flags to CLI classes. Resolves #87 and #117.

  • Adds integration with the Asciidoctor EPUB3 project. You can set epub3 as a backend. Resolves #168 and #179

  • Updates AbstractBlock class with findBy method. Resolves #164

  • Updates Document class to be aligned with Asciidoctor::Document so getting a title can return a Title class with title, subtitle instead of as String with full title. Resolves #167

  • Promotes attributes sectnumlevels, hardbreaks, appendix-caption, stem, hide-uri-schema, nofooter, source-language and compat-mode. Resolves #91, #92, #94, #105, #121, #129, #144 and #163.

  • You can get the Ruby instance used in AsciidoctorJ from JRubyRuntimeContext class. Resolves #93

  • Fixes a bug with Ruby instance and Attributes class which prevented the Gradle plugin from working properly. Resolves #96

  • Skips files and directories that begin with an underscore (_) in AsciiDocDirectoryWalker. Resolves #124

  • Adds slf4j as logging system. Resolves #126

  • Fixes a bug with base_dir and Ruby environment. Resolves #135

  • Document objects like Section, Block, Node, Document, …​ are moved to the org.asciidoctor.dom package.

  • Updates Java version to Java 7. Resolves #176

For more information about issues fixed in this release, please see the 1.5.0 milestone in the issue tracker!


The artifactId changed from asciidoctor-java-integration to asciidoctorj starting in 1.5.0. You should now use the following dependency stanza in your project’s pom.xml file:


When upgrading to Asciidoctor 1.5.0, please refer to the migration guide for details about how to migrate your content. We also encourage you to browse the release notes for Asciidoctor 1.5.0.

Asciidoctor 1.5.0 introduced many changes internally and to the public API. For example, the extension API has been modified in non-trivial ways, so you’ll like need to update your extensions to the new API when upgrading to this release of AsciidoctorJ.

Visit the updated AsciidoctorJ manual to learn how to install and use AsciidoctorJ.

This release makes way for new releases of the Gradle plugin, Maven plugin and Asciidoclet, all of which are based on AsciidoctorJ. Look for those announcements to follow!

Asciidoctor 1.5.0 “Bleeding Heart” released!

by Dan Allen and Sarah White -

The long-awaited release of Asciidoctor 1.5.0 “Bleeding Heart” has arrived at last! This release includes a stockpile of 150 fixes, improvements and enhancements as well as several refinements to the AsciiDoc syntax. We’re confident you’re going to love writing with Asciidoctor more than ever before.

Asciidoctor 1.5.0 is the sequel to 0.1.4. We shifted the numbers to adopt a semantic versioning scheme and communicate that this release is well beyond stable.

Please take note!

Before you upgrade to Asciidoctor 1.5.0, it’s important to know we’ve introduced some changes to the AsciiDoc syntax that aren’t backward compatible. Don’t panic, though! We also introduced a compatibility mode.

Refer to the migration guide for information about the affected syntax and how to migrate (or prepare to migrate) your content. By making these syntax changes, we’re working to make AsciiDoc more consistent and easier to learn.

Milestones & momentum

We closed 150 issues during the Asciidoctor 1.5.0 development cycle. At the time of the last release, we announced that Asciidoctor had reached 50,000 downloads from This time around, we didn’t just double the download count, we quadrupled it! Asciidoctor has now been downloaded more than 225,000 times at the time of this release!

It’s not the download count of which we’re most proud. It’s the community of awesome people . There are now over 50 contributors in the Asciidoctor ecosystem, and this release alone has received participation from nearly every person in this group! If you haven’t had a chance to participate in Asciidoctor, there’s never been a better time to join in.

Here’s a summary of the milestones we’ve crossed:

  • 150 issues closed in 1.5.0

  • 50 total contributors

  • 225,000 total downloads

  • 1,800 total commits

  • 1,500 tests

  • 1000 total issues (including pull requests)

  • 800 issues closed in total (including pull requests)

  • 400 mailing list topics

  • 2 years of development (initial commit Jun 1, 2012)

This wouldn’t be an Asciidoctor release announcement without discussing the speed of the processor. The 1.5.0 release brings another 10% improvement in speed over the previous version. To give you a picture of how fast it is now, the Spring Framework Reference Guide, weighing in at 50,000+ lines, renders to HTML in 1.15 seconds on an Asus ZenBook UX301LA using Ruby 2.1.

Asciidoctor is now in use by even more open source projects, including Groovy, Griffon, GroovyFX, Infinispan, Weld, Hibernate OGM, Spring Data and It’s also used to produce NFJS, the Magazine. Best of all, Sarah has been hard at work filling in Asciidoctor’s own user manual and helping teams understand how to write better documentation.

In case you didn’t notice, the Asciidoctor project is on . On that note, let’s get to what’s in this new release!

Release highlights

Get technical with MathJax

If you need to get technical in your writing, Asciidoctor integrates with MathJax to allow you to write TeX / LaTeX or AsciiMath expressions directly in your document.

A typeset LaTeX math equation
\[x = {-b \pm \sqrt{b^2-4ac} \over 2a}\]

With a simple declaration of the stem attribute, you can now write inline and block formulas in plain text too!

Diagrams, diagrams, diagrams

You can add even more visual elements to your document with diagrams conjured from plain text. Asciidoctor Diagram emerged from a request to port the PlantUML extension for AsciiDoc Python to Asciidoctor. Pepijn Van Eeckhoudt (@pepijnve) took the reins and created a comprehensive diagram extension that not only adds integration with PlantUML, but three additional diagramming tools, as well as a framework for adding more in the future.

Asciidoctor Diagram 1.5.0 now supports the following diagramming tools:

Asciidoctor Diagram process diagram

See the Asciidoctor Diagram guide to learn how to create diagrams from ASCII art in your AsciiDoc documents.

Curious how to load extensions like Asciidoctor Diagram from the commandline interface? Read on.

Load extensions from the CLI

Asciidoctor introduced an extensions API in 0.1.4 that enables you to extend the AsciiDoc syntax and tap into the lifecycle of the processor. However, it was only possible to load these extensions when invoking Asciidoctor via the API or by creating a custom launch script.

The asciidoctor command now supports the -r and -I flags (ported from the ruby command) to require additional paths or modify the load path, respectively.

Here’s an example of how to use the -r flag to enable the Asciidoctor Diagram extension:

$ asciidoctor -r asciidoctor-diagram sample.adoc

The -r flag also accepts absolute or relative paths and can be used multiple times.

$ asciidoctor -r ./my-extension-a.rb -r ./my-extension-b.rb sample.adoc

The scripts referenced by the -r flag are loaded in the order they are listed before any other processing occurs.

Now you get the full power of the asciidoctor command plus extensions!

Embracing DocBook 5

The DocBook 5 specification was finalized in 2008. It’s time we embrace it.

DocBook 5 is now the default output when you use the docbook backend. If you still need to produce DocBook 4.5, use the docbook45 backend.

Making XML parsers happy

HTML5 reintroduced flexible HTML syntax that’s only loosely based on SGML…​and most certainly not XML. This decision makes HTML5 more approachable. However, it makes XML parsers .

To accommodate tools that use XML parsers to read the generated HTML, Asciidoctor can now output the XHTML variant of HTML5, known as XHTML5.

To output XHTML5 instead of HTML5, set the backend to xhtml or, to be more explicit, xhtml5. The “x” at the beginning of the name cleverly tells Asciidoctor to close short tags, assign values to boolean attributes and add the xmlns attribute to the root element.

Trust us, your XML parser will thank you.


Asciidoctor can now convert directly from AsciiDoc to PDF and EPUB3, using Asciidoctor PDF and Asciidoctor EPUB3, respectively. These converters are hosted in their own repositories and are distributed as separate gems.

EPUB3 generated by Asciidoctor EPUB3

The converters are currently alpha, but still very functional.

Asciidoctor.js is Asciidoctor

Guillaume Grossetie (@mogztter) led the effort during the 1.5.0 development cycle to align the Asciidoctor.js code base with Asciidoctor core. After a lot of fiddling and Opal patches, Asciidoctor.js now builds directly against master and the Asciidoctor 1.5.0 release. That means that for the first time, Asciidoctor.js is Asciidoctor.

Anthonny Quérouil (@anthonny) followed up by developing a Grunt build script to bundle Asciidoctor.js and publish it to npm (the Node.js package manager) and Bower (the web package manager).

Guillaume is the creator of the AsciiDoc preview for Chrome and Anthonny the creator of the AsciiDoc preview for Atom. The AsciiDoc preview for Atom complements the AsciiDoc language definition kicked off by Anton Moiseev (@antonmoiseev). Thomas Kern (@nerk) was quick to follow up with an AsciiDoc plugin for Brackets based on the aforementioned work. We also invited the veteran project of Asciidoctor.js, DocGist, into the Asciidoctor organization. DocGist was created by Anders Nawroth (@nawroth). Guillaume, Anthonny, Anders, Thomas, Anton and others have been collaborating on tooling based on Asciidoctor.js. They’re helping Asciidoctor boldly go where no AsciiDoc implementation has gone before.

The alignment of Asciidoctor.js with Asciidoctor core was a major effort. I want to sincerely thank Guillaume, Anthonny and the Opal team (Adam Beynon, meh and Elia Schito) for making this happen.

AsciiDoc syntax shuffle

The single quote (') and the backtick (`) are two markup characters in the AsciiDoc syntax that often give people trouble. They like to get in each other’s way. We decided to shuffle some of the AsciiDoc syntax to address this problem and, in general, make it more consistent and easy to learn. Not only do these changes reduce slip ups by the parser, they also strengthen the meaning of the plus character and bring more alignment with Markdown by making the backtick the primary character for monospace formatting.

Migrating with compat-mode

Before introducing what’s changed, we want to emphasize that you can forgo the italic, monospace and passthrough syntax changes by setting the compat-mode attribute, shown here defined in the document header:


or by using a two-line document title:

Document Title

Compat mode is used to enable legacy syntax when the new syntax deviates from it. See the migration guide for more information about migrating your AsciiDoc documents and the transitional syntax that’s available.

“+” means passthrough

The + character in the original AsciiDoc syntax is not used consistently. Single plus (+) and double plus (++) are used to format text as monospace, whereas triple plus (+++) and quadruple plus (++++) are used to escape text from processing.

We made AsciiDoc more intuitive and easier to teach by always using + as a passthrough formatting mark. Instead of using the single plus and double plus for monospaced formatting, we’ve made them constrained and unconstrained literals (i.e., “render it as it looks”), respectively. For example:

+_bar_+ becomes _bar_
foo++_bar_++ becomes foo_bar_

We haven’t yet mentioned how to format text as monospace. For that, we’ll put the backtick back into play.

Markdown-style monospace

Authors who are familiar with Markdown are accustomed to using the backtick (`) to format text as monospace. We’ve embraced this convention in Asciidoctor.

Using backtick characters around text now means the text should be formatted as monospace only. The backtick characters do not add passthrough semantics, as they did before. In most cases, the passthrough semantics aren’t necessary, so using the backticks for monospaced formatting is sufficient.

`literal` becomes literal (in monospace)
`{backend}` becomes html5 (in monospace)
a``||``b becomes a||b (where || is monospace)

If you want to prevent substitutions in the monospaced text, just remember, “plus for passthrough”:

`+{backend}+` becomes {backend} (in monospace)

By not mixing monospace formatting with passthrough (literal) semantics, we are deviating slightly from the behavior of backticks in Markdown. However, that’s because AsciiDoc has additional features, such as attribute references, that we want to be able to leverage when formatting text as monospace.

There will be a period of time during which you’ll have to process your document with both Asciidoctor 0.1.4 and 1.5.0 (mostly while we wait on GitHub to upgrade). We’ve added special logic in the processor to handle a hybrid syntax to use in the interim. Please refer to the migration guide for details.

Smarter “smart” quotes

Legacy AsciiDoc also uses the backtick character for making curved quotes. Because the syntax was so similar to that of monospaced literal text, it often matched in unexpected ways. We’ve made the smart quotes syntax…​smarter.

In Asciidoctor 1.5.0, the backtick acts as a modifier on a quote to indicate it should be curved. You now place the backtick inside the quote character, adjacent to the quoted phrase, to make it “smart”.

Dig through a copy of '`The Times`' and you're bound to see a lot of "`smart`" quotes.

This change brings the backtick closer in proximity to the quote and thus makes parsing more deterministic. See the user manual for more curved quote and apostrophe examples.

Quote means quote

Single quotes around a phrase are now left alone unless you’re running Asciidoctor in compat mode.

AsciiDoc traditionally supported single quotes as an alternate syntax for marking a phrase as italic. However, single quotes around a phrase already have a very well-defined meaning in Western languages. Making them something they aren’t just isn’t a good idea. We never recommended them for this purpose anyway. Furthermore, they conflict with the new curved quote syntax, so they had to go.

Refer to the migration guide to help ensure a smooth transition to the new syntax.

Level your offsets

The leveloffset attribute is used to shift the level of sections when combining documents. It works great for a single include level, but as Groovy developers Cédric and Guillaume discovered, it quickly breaks down when you get into multiple levels of nesting.

The problem is that the level offset value is assumed to be absolute. Asciidoctor now supports relative level offset values using a leading + or - operator.

:leveloffset: +1
:leveloffset: -1

Alternatively, you can specify the leveloffset attribute directly on the include directive so you don’t have to worry about restoring the old value.


Filtered tag directives

The Groovy developers use the include and tag directives a lot. They discovered that tag directives within a broader tagged range get carried over into the document. Asciidoctor now drops these lines so you can nest fine-grained ranges within broader ranges.

The tag directives are also searched using a more strict match to avoid false matches.

Substitution modifiers

When you needed to customize the substitutions on a block, you used to have to list out all the substitutions you wanted to enable. It’s now possible to add or remove substitutions to the default substitution set using the + and - modifiers (e.g., [subs=+quotes]). That should save a lot of unnecessary typing!

Secure assets

Serving assets over SSL is a best practice to avoid man-in-the-middle attacks and preying eyes in general.

All remote assets referenced out of the box in Asciidoctor, such as Font Awesome, are now served over SSL from and

Hide the URI scheme

Asciidoctor auto-detects and auto-links URLs. Writers often don’t take advantage of this feature because the link shows the URI scheme prefix (e.g., http://). So, they end up long-handing it for the sole purpose of hiding the prefix.[]

Now, Asciidoctor can produce the exact same result if you set the hide-uri-scheme attribute on the document.

Rendered URL when hide-url-scheme is set

Human-friendly cross references

If you’re linking to an anchor point somewhere else in your document, you can refer to it by title instead of by ID.

Refer to <<Section A>>.

== Section A

You’ll likely want to switch to using IDs as the document matures, but this should certainly help with flow in early drafts!

Print your docs

Leif Gruenwoldt (@leif81) pointed out that the print styles were too aggressive, causing the printed document to lose its integrity. We worked together to tweak the stylesheet until the output looked nearly as good as the PDF generated by the DocBook toolchain. The styles even separate chapters into different pages when using the book doctype. In addition to these styles, we also added the missing table border styles for all the grid and frame permutations on both web and print.

Who needs DocBook when you’ve got HTML5 and CSS3?

Print preview of HTML generated by Asciidoctor

Open Source fonts

The culture of Asciidoctor is deeply rooted in Open Source, so we want to be Open Source all the way down.

In the past, the default stylesheet relied on Microsoft Core Fonts (Arial and Georgia) installed on the user’s system. We’ve replaced these proprietary fonts with Open Source fonts, which we load from Google Fonts.

Here are the fonts we’ve selected:

  • Noto Serif - prose and block titles

  • Open Sans Light - section headings

  • Droid Sans Mono - monospaced text and preformatted blocks

We particularly like Noto Serif because it’s an extremely readable font and it supports all the world’s languages.

We made additional refinements to the default stylesheet that give it a professional, modern appearance. Here’s a preview of the new default theme:

Screenshot of default Asciidoctor theme

Font Awesome 4.1

Speaking of fonts, Asciidoctor integrates with Font Awesome 4.1, thanks to the work done by Guillaume Grossetie (@mogztter)! You now have over 400 icons available to accessorize your document!

Many icons were renamed in Font Awesome 4. If you have existing documents that use the icon macro, you may want to add the Font Awesome 3 compatibility CSS that Guillaume created to ease the transition.

“Everything is AWESOME!!!”


The best part of Asciidoctor is, and will always be, its thriving community. We’d like to thank the following people for participating in this release.

We’d like to give special shout outs to the following people:

  • to Guillaume Grossetie, Ken Dreyer, Leif Gruenwoldt, @megathaum, Ken Finnigan, Brian Carlson, Aslak Knutsen, David Gamba, Wim Champagne, Charles Moulliard, Jean-Louis Jouannic, Roman Priesol and James FitzGibbon for making their first source contributions to Asciidoctor core.

  • to Guillaume Grossetie for spearheading the effort to align Asciidoctor core and Asciidoctor.js.

  • to Anthonny Quérouil for setting up a Grunt build for Asciidoctor.js and getting it published to npm and Bower.

  • to members of the Opal team (Adam Beynon, meh and Elia Schito) for helping us achieve compatibility with Opal and making necessary upstream changes.

  • to Ken Dreyer for overhauling the RPM package for Fedora and upgrading the Asciidoctor test suite to Minitest 5.

  • to Peter Neubauer for making the very first Asciidoctor t-shirt, which I wore for the release!

I (Dan) would also like to thank Sarah White for her monstrous effort providing input into the software design, editing the user manual, updating the website, testing (read as: breaking) and establishing a documentation workflow for the project. Asciidoctor would not be what it is today without her dedication.

Additional thanks to everyone who is using the project, advocating for better documentation and those who have participated in the growing ecosystem of sub-projects. The mission of Asciidoctor is to help you write, publish and communicate your content successfully, and enjoy doing it! With your feedback and participation, we can achieve that goal together! We encourage you to ask questions and discuss any aspects of the project on the mailing list, Twitter or IRC.

If you discover errors or omissions in the source code, documentation, or website content, please don’t hesitate to submit an issue or open a pull request with a fix. We’re always eager to learn about your experiences and how we can help improve them. Together, we’re making documentation fun, easy, and rewarding!

What’s next?

This release is just the beginning of the release train. Look for releases of AsciidoctorJ, Asciidoctor.js, the build plugins (Gradle and Maven), the Linux packages and more!

The next release of Asciidoctor will be the 1.5.1 point release. From now on, we plan to iterate much faster and only do announcements for major and minor versions.

See the CHANGELOG for a complete list of changes.

Asciidoctor 0.1.4 released!

by Dan Allen and Sarah White -

We’re thrilled (and a bit relieved) to announce the release of Asciidoctor 0.1.4!

What is Asciidoctor?

Asciidoctor is a fast, open source text processor and publishing toolchain for transforming AsciiDoc markup into HTML 5, DocBook 5.0, DocBook 4.5 and custom output formats. Asciidoctor is written in Ruby, packaged as a RubyGem and published to The Asciidoctor processor is also accessible to any JVM language or build system via the Java integration library.

Follow the instructions on the Installing or Updating Asciidoctor page to get started.

A release marked by milestones

Asciidoctor 0.1.4 was originally planned to be a small release. Instead, it turned out to be a summer-long project, spanning from Memorial Day to Labor Day, which concluded in the biggest release to date. Ninety issues — that’s right, 90 — were closed along the way, resulting in 325 commits.

The extended development cycle was due in part to a major pickup in the amount of feedback from users. We also didn’t want to let another release slip by without including an extension mechanism, which we’re happy to say is available in this release as a technology preview.

This also turned out to be a development cycle full of milestones. At the time of the last release, we announced that Asciidoctor had reached 20,000 downloads in total. Asciidoctor 0.1.3 alone topped that number at 27,000 and the number of downloads in total broke the 50,000 mark! But that’s just the start.

Here are some of the additional milestones we surpassed:

  • > 1,000 commits (1,158 in total)

  • > 1,000 tests (1245 in total)

  • > 500 closed issues (523 in total)

  • > 100 mailing list topics (117 in total)

  • > 1 year of development (initial commit Jun 1, 2012)

Once again, the valuable feedback we’ve received from Asciidoctor’s awesome community has helped push Asciidoctor’s compliance with the AsciiDoc syntax beyond the Python implementation. Asciidoctor has also achieved another 15% increase in speed over the previous release. Just to give you an idea of how fast the processor is, the 16,000-line Enterprise Web Development: From Desktop to Mobile book, published by O’Reilly, renders to HTML in 0.85 seconds on an Ultrabook.

Asciidoctor is now in use by major open source projects, most notably Groovy, Spring XD, Spring Security, OpenShift Origin, Neo4j, CRaSH, RichFaces and Granite DS, among others. We’ve also kicked off our own documentation effort in Asciidoctor, admist all the development. Sarah started a documentation strategy (i.e., information architecture) for the project and composed an initial draft of the Asciidoctor user manual. For the first time, we also have a proper Changelog associated with each tag on GitHub and aggregated in the CHANGELOG.adoc file at the repository root.

As you can see, things are really on around here.

On that note, let’s get to what’s in this new release! (Jump to TL;DR to get the abbreviated version.)


Awesome icons everywhere!

Asciidoctor 0.1.4 introduces an inline macro for inserting an icon at an arbitrary place in paragraph content.

Here’s an example that inserts a tags icon in front of a list of tag names:

icon:tags[] ruby, asciidoctor

Here’s how this example renders:

ruby, asciidoctor

You can even give the icon color by assigning it a role:

icon:tags[role=blue] ruby, asciidoctor

which appears as:

ruby, asciidoctor

The icon macro recognizes a few attributes that can be used to modify the size, orientation and function of the icon. Here’s a large, blue Twitter logo that’s had too much to drink, but still manages to link to the Twitter homepage:

created from:

icon:twitter[4x, flip=vertical, link=]

At the moment, the name of the icon is resolved from the Font Awesome icon set. You can see the possible icon name options on the icons page. Support for other icon sets is being discussed in issue #539.

If you aren’t using the font-based icons, Asciidoctor looks for the images on disk in the iconsdir directory.

Resolves issue #529.

Additional improvements
  • Asciidoctor now uses Font Awesome 3.2.1 (loaded from (#451)

Inter-document references

In AsciiDoc, the xref inline macro is used to create a cross-reference (i.e., link) from one section to another. Asciidoctor 0.1.4 extends this functionality by allowing a link to be made to a section in another AsciiDoc document. This eliminates the need to use direct links between documents (e.g., HTML links) that couple the document to a single backend. The cross-reference also captures the intent to establish a reference between related documents.

Here’s how an xref is normally defined in AsciiDoc:

Refer to <<section-b>> for more information.

This xref creates a link to a section with the id section-b.

Let’s assume the xref is defined in the document document-a.adoc. If the target section is in a separate document, document-b.adoc, the author may be tempted to write:

Refer to link:document-b.html#section-b[Section B] for more information.

However, this link is coupled to HTML output. What’s worse, if document-b.adoc is included in the same master as document-a.adoc, then the link will refer to a document that doesn’t even exist!

These problems can be alleviated by using an inter-document xref:

Refer to <<document-b.adoc#section-b,Section B>> for more information.

See you when you get back from <<document-b#section-b,Section B>>!

The id of the target is now placed behind a hash symbol (#). Preceding the hash is the name of the reference document (the file extension is optional). We also assigned a label to the reference since Asciidoctor cannot (yet) resolve the section title in a separate document.

When Asciidoctor generates the link for this xref, it first checks to see if document-b.adoc is included in the same master as document-a.doc. If not, it will generate a link to document-b.html, intelligently substituting the original file extension with the file extension of the output file.

<a href="document-b.html#section-b">Section B</a>

If document-b.adoc is included in the same master as document-a.doc, then the document will be dropped in the link target and look like the output of a normal xref:

<a href="#section-b">Section B</a>

Now you can create inter-document references without the headache.

Resolves issue #417.

No more dropped lines!

By default, the original AsciiDoc processor drops the entire line if it contains a reference to a missing attribute (e.g., {bogus}). This "feature" was added to the Python implementation for use in creating custom backends, which are written using the AsciiDoc syntax.

This behavior is not needed in Asciidoctor since its templates are composed in a dedicated template language (e.g., ERB, Haml, Slim, etc). But the main issue with this behavior is that it’s frustrating to the author, editor or reader. To them, it’s not immediately apparent when a line goes missing. Discovering its absence often requires a full (and tedious) read-through of the document or section.

Asciidoctor 0.1.4 introduces two attributes to alleviate this inconvenience: attribute-missing and attribute-undefined.


The attribute attribute-missing controls how missing references are handled. By default, missing references are left intact so it’s clear to the author when one hasn’t been satisfied since, likely, the intent is for it to be replaced.

This attribute has three possible values:


leave the reference in place (default setting)


drop the reference, but not the line


drop the line on which the reference occurs (compliant behavior)

Consider the following line of AsciiDoc:

Hello, {name}!

Here’s how the line is handled in each case, assuming the name attribute is not defined:


Hello, {name}!


Hello, !



The attribute attribute-undefined controls how expressions that undefine an attribute are handled (e.g., {set:name!}). By default, the line is dropped since the expression is a statement, not content. It’s reasonable to stick with the compliant behavior in this case since such an expression is not intended to produce content.

We recommend putting any statement that undefines an attribute on a line by itself.

Resolves issue #523.

YouTube and Vimeo videos

The video::[] macro now supports videos from external video hosting services like YouTube and Vimeo. To use this feature, put the video ID in the macro target and the name of the hosting service in the first positional attribute. Asciidoctor will put the two together and generate the correct embed code to insert the video in the HTML output.

Here’s an example that embeds a YouTube video:

video::rPQoq7ThGAU[youtube, 640, 360]

and one that embeds a Vimeo video:

video::67480300[vimeo, 400, 300]

You can control the video settings using additional attributes and options on the macro. For instance, you can offset the start time of playback using the start attribute and enable autoplay using the autoplay option.

video::rPQoq7ThGAU[youtube, 640, 360, start=60, options=autoplay]

Resolves issue #587.

DocBook 5.0 backend

In addition to DocBook 4.5, Asciidoctor 0.1.4 can produce DocBook 5.0 output, which is handled by the docbook5 backend.

The output from the docbook5 backend only differs marginally from the docbook45, just enough to make it compliant with the DocBook 5.0 specification. A summary of the differences are as follows:

  • XSD declarations are used on the document root instead of a DTD

  • <info> elements for document info instead of <articleinfo> and <bookinfo>

  • elements that hold the author’s name are wrapped in a <personname> element

  • the id for an element is defined using an xml:id attribute

  • <link> is used for links instead of <ulink>

  • the URL for a link is defined using the xlink:href attribute

Refer to What’s new in DocBook v5.0? for more details about how DocBook 5.0 differs from DocBook 4.5.

To use the DocBook 5.0 backend, set the backend to docbook5, as shown in this example:

$ asciidoctor -b docbook5 sample.adoc

Here’s a sample DocBook 5.0 document generated by this backend:

<?xml version="1.0" encoding="UTF-8"?>
<article xmlns=""
    xmlns:xlink="" version="5.0" xml:lang="en">
    <title>Hello, AsciiDoc!</title>
    An introduction to <link xlink:href="">AsciiDoc</link>.
  <section xml:id="_first_section">
    <title>First Section</title>
        <simpara>item 1</simpara>
        <simpara>item 2</simpara>

Resolves issue #411.

Additional improvements
  • The xmlns attribute is now added to the root DocBook element by default. Set the attribute noxmlns to disable this feature.

Debian and Ubuntu package

Joining the Fedora package, Asciidoctor is now packaged for Debian and Ubuntu thanks to Per Andersson! 'nuff said!

You can install Asciidoctor on Debian or Ubuntu using:

$ sudo apt-get install asciidoctor
Currently, packages are only available for Asciidoctor 0.1.3. Updated packages for Asciidoctor 0.1.4 should become available within a few weeks following this release.

Resolves issue #216.

Classy code listings

We know code is important to you. It’s important to us too. That’s why we made some sweet refinements to code listings in this release.

Callouts don’t get caught in copy

Previously, when a reader selected and copied source code containing callouts from an HTML page generated by Asciidoctor, the callout numbers would get caught up in the copy. Those extra characters can cause compile or runtime errors at the spot where the reader pastes the code. Readers shouldn’t be surprised in this way or have to understand why extra characters end up in the clipboard. Copy and paste should just work.

In this release, we used some CSS ninja moves to prevent the callouts from getting caught up in the copy. No matter how hard the reader tries, those callouts just won’t get selected. (The same is true for line numbers as well).

On the other side of the coin, you don’t want the callout annotations to mess up your code either. We can’t play fancy CSS games in raw source code, but we can leverage line comments! You can now tuck your callouts neatly behind line comments. Asciidoctor will recognize the line comment characters in front of a callout number—​optionally offset by a space—​and remove them when rendering the document.

Here are the line comments that are supported:

line of code  // <1>
line of code   # <2>
line of code  ;; <3>
<1> A callout behind a line comment for JavaScript, Java, and C-style languages.
<2> A callout behind a line comment for Ruby, Python, Perl, etc.
<3> A callout behind a line comment for Clojure and Lisp-style languages.

Here’s how the commented callouts look when rendered:

line of code  (1)
line of code  (2)
line of code  (3)
1 A callout behind a line comment for JavaScript, Java, and C-style languages.
2 A callout behind a line comment for Ruby, Python, Perl, etc.
3 A callout behind a line comment for Clojure and Lisp-style languages.

Notice the line comment characters are gone! Now select the lines. As you can see, the callouts are left behind.

We want callouts to be an aid, not a pain.

Asciidoctor requires that callouts be placed at the end of the line.

Resolves issue #478.

Speaking of pain, what about callouts in XML? Read on to find out.

XML-friendly callouts

XML doesn’t have line comments, so our “tuck the callout behind a line comment” trick doesn’t work here. We played around with the syntax and came up with something we think works and looks pretty clean. We just stretched out the angled brackets around the callout number and turned it into an XML comment:


Here’s how the XML-friendly callout appears in a listing:

  <title>Section Title</title>  <!--1-->
<1> The section title is required.

Here’s how the callout looks when rendered:

  <title>Section Title</title>  (1)
1 The section title is required.

Again, notice the comment is gone and the callout number cannot be selected.

This syntax also works for callouts in HTML listings.

Resolves issue #582.

A macro definition for XML-friendly callouts is included in the AsciiDoc compatibility file so they can be recognized by the asciidoc command as well.

Thanks to these enhancements, both the reader and developer can copy and paste source code containing callouts without having to worry about error-causing hitchhikers. But, our tricks with callouts aren’t over quite yet.

Highlight-free callouts

We had reports that callouts weren’t getting replaced in some cases when using the CodeRay source highlighter (e.g., source-highlighter=coderay).

It turns out, the problem is that the very presence of callouts in the code, whether behind line comments or not, causes them to get caught in the highlighting and mangled. The trick here is to pull the callouts out of the source code before highlighting, then restore them afterward. That way, the source highlighter never sees them, and we can be sure that they end up where they’re supposed to be, unmangled.

There’s nothing you need to change to take advantage of this improvement. This feature works when using CodeRay or Pygments (i.e., the "server-side" source highlighters).

Resolves issue #534.

Wait, did you say Pygments?

That’s right. Asciidoctor can use Pygments to highlight source code!

Syntax highlighting with Pygments

The most popular source code highlighter in the AsciiDoc world—​perhaps the whole world—​is Pygments. Until now, Asciidoctor only integrated with CodeRay for "server-side" source highlighting, mostly because it’s also written in Ruby.

Thanks to the awesome folks at GitHub, Pygments has a nice Ruby wrapper library named pygments.rb that makes integrating with it a cinch.

In order to use Pygments with Asciidoctor, you need to install Pygments (and Python, if you don’t have it yet). Run something like:

$ "`\which apt-get || \which yum || \which brew`" install python-pygments

You then need to install the pygments.rb RubyGem.

$ gem install pygments.rb

To activate Pygments in Asciidoctor, assign the value pygments to the source-highlighter attribute in your document’s header.

:source-highlighter: pygments

Voila! Your code now has “pygments”.

Resolves issue #538.

Additional improvements
  • The default CodeRay theme has been updated so it matches better with the default Asciidoctor styles.

  • Syntax highlighting is no longer disabled if the subs attribute is used on a source listing (as long as specialcharacters is in the subs list).

To wrap or to scroll, that is the question

Previously, the Asciidoctor stylesheet was configured to prevent line wrapping (e.g., white-space: pre-wrap; word-wrap: normal) in listing and literal blocks. This behavior isn’t always desirable because it causes the browser window to scroll if the content overflows the width of the page. For many, this horizontal scrolling is considered a greater readability problem than line wrapping.

Since there are two camps on how to handle overflow text, neither choice would please both audiences. For that reason, we’ve made this behavior configurable in Asciidoctor 0.1.4.

The default Asciidoctor stylesheet now wraps long lines in listing and literal blocks by applying the CSS white-space: pre-wrap and word-wrap: break-word. The lines are wrapped at word boundaries, similar to how most text editors wrap lines.

There are two ways to prevent lines from wrapping so that horizontal scrolling is used instead:

  • set the nowrap option on the block

  • unset the prewrap document attribute

You can use the nowrap option on literal or listing blocks to prevent lines from being wrapped in the HTML:

public class ApplicationConfigurationProvider extends HttpConfigurationProvider
   public Configuration getConfiguration(ServletContext context)
      return ConfigurationBuilder.begin()
               .perform(Log.message(Level.INFO, "Client requested path: {path}"))

When the nowrap option is used, the nowrap class is added to the <pre> element. This style class changes the CSS to white-space: pre and word-wrap: normal.

To apply the nowrap option globally, unset the prewrap attribute on the document.


When the prewrap attribute is unset, the nowrap class is added to any <pre> element, even when the nowrap option is absent on the block.

Now, you can use the line wrapping strategy that works best for you and your readers.

Resolves issue #303.

Mark your lists

Lists are everywhere. Let’s put them to work.

Getting Things Done using checklists

List items can now be marked as complete using checklists. If you use Asciidoctor to track the completion of tasks, get ready to start checking off those tasks!

Checklists (i.e., task lists) are unordered lists that have items marked as checked ([*] or [x]) or unchecked ([ ]). Here’s an example:

- [*] checked
- [x] also checked
- [ ] not checked
-     normal list item

When checklists are rendered to HTML, the checkbox markup is transformed into an HTML checkbox with the appropriate checked state. For more details, check out the checklist section in the user manual.

If you enable font-based icons (i.e., -a icons=font), the checkbox markup is rendered using a font-based icon! Here’s how that looks:

  • checked

  • also checked

  • not checked

  • normal list item


Resolves issue #200.

More bullets and numerations styles for lists

Asciidoctor 0.1.4 offers additional bullet and numbering styles for lists. The list marker (bullet or numeration style) is set using the list’s block style.

Asciidoctor now recognizes all the unordered list bullets available in HTML and DocBook.

The unordered list marker can be set using any of the following block styles:

  • square

  • circle

  • disc

  • none or no-bullet (indented, but no bullets)

  • unstyled (no indentation or bullets) (HTML only)

  • inline (as paragraph, no bullets) (HTML only)

These styles are supported by the default Asciidoctor stylesheet.

When present, the style name is assigned to the unordered list element as follows:


the style name is assigned to the class attribute on the <ul> element.

For DocBook

the style name is assigned to the mark attribute on the <itemizedlist> element.

Here’s how you create an unordered list marked with square bullets:

* one
* two
* three

For ordered lists, Asciidoctor now supports the lowergreek and decimal-leading-zero numeration styles in addition to the existing options.

These two new styles are only supported in the HTML backend (DocBook doesn’t recognize these options).

Here are a few examples showing various numeration styles as defined by the block style shown in the header row:

[arabic]* [decimal] [loweralpha] [lowergreek]
  1. one

  2. two

  3. three

  1. one

  2. two

  3. three

  1. one

  2. two

  3. three

  1. one

  2. two

  3. three

* Default numeration if block style is not specified

Custom numeration styles can be implemented using a custom role. Define a new class selector (e.g., .custom) in your stylesheet that sets the list-style-type property to the value of your choice. Then, assign the name of that class as a role (e.g., [.custom]) on any list to which you want that numeration applied.

For more information about bullets and numerations, consult the user manual.

Resolves issues #364, #472 and #620.

Additional improvements
  • When the role shorthand (e.g., [.custom]) is used on an ordered list, the default numeration style is no longer dropped.

More time savers

Implicit header row for tables

After adding shorthand notation in Asciidoctor 0.1.3 for specifying the table format (e.g., ,===, ;===), it seemed tedious to still have to use a block attribute line to enable the header row (e.g, [options="header"]).

It’s now possible to enable the header row implicitly just by following a few conventions. Here are the conventions introduced in Asciidoctor 0.1.4 to determine if the first row should be a header row:

  1. The first line of content inside the table block delimiters is not empty.

  2. The second line of content inside the table block delimiters is empty.

  3. The options attribute has not been specified in the block attributes.

If all of these rules hold, the first row of the table is treated as a header row. Building on existing conventions, if the cols attribute has not been specified, the number of columns in the table is set to the number of columns in the first row (i.e., the header row).

Here’s an example of a table that has an implicit header row:

|A |B |C (1)


|A-2| B-2| C-2

1 Satisfies the convention for a header row.

Here’s how it looks when rendered:











You can arrange the cells in the remaining rows however you want. Note, however, that we’re considering using a similar convention for enabling the footer in the future. Thus, if you rely on this convention to enable the header row, it’s advised that you not put all the cells in the last row on the same line unless you intend on making it the footer row.

Resolves issue #387.

Shorthand notation for block options

In traditional AsciiDoc syntax, block options are specified using the options attribute in the block’s attribute list. Asciidoctor 0.1.4 allows options to be specified using a block shorthand notation, in which the option name is prefixed with a percent sign (%).

Consider the following table block with three options:

Block options using traditional AsciiDoc syntax
|Cell A |Cell B

Here’s how the options are written using the shorthand notation (%):

Block options using Asciidoctor shorthand notation
|Cell A |Cell B

Let’s consider the options when combined with other shorthand notations.

Traditional AsciiDoc syntax
[horizontal, role="properties", options="step"]
property 1:: does stuff
property 2:: does different stuff
Asciidoctor shorthand notation
property 1:: does stuff
property 2:: does different stuff

Resolves issue #481.

Shorthand notation on formatted (i.e., quoted) text

The shorthand notation introduced on blocks in Asciidoctor 0.1.3 can now be used on inline formatted (i.e., quoted) text as well.

Here’s an example of an inline anchor and formatted text that has two roles:

Traditional AsciiDoc syntax
[[free_the_world]][big goal]_free the world_
Asciidoctor shorthand notation
[#free_the_world.big.goal]_free the world_
Since quoted text doesn’t have an id, the id attribute is converted to an anchor that precedes the text.

In the HTML backend, this syntax becomes:

<a id="free_the_world"><em class="big goal">free the world</em>

In the DocBook backend, it becomes:

<anchor id="free_the_world" xreflabel="free the world"/><emphasis><phrase
role="big goal">free the world</phrase></emphasis>

Resolves issue #517.

Additional improvements
  • The attribute list preceding formatted text can be escaped using a backslash (e.g., \[role]*bold*). In this case, the text will still be formatted, but the attribute list will be unescaped and output verbatim. (#421)

Role-playing for text enclosed in backticks

To align with other formatted (i.e., quoted) text in AsciiDoc, roles can now be assigned to text enclosed in backticks.


[rolename]`escaped monospace text`

the following HTML is produced:

<code class="rolename">escaped monospace text</code>

Using the new shorthand notation in Asciidoctor 0.1.4, an id (i.e., anchor) can also be specified:

[#idname.rolename]`escaped monospace text`

which produces:

<a id="idname"></a><code class="rolename">escaped monospace text</code>

Keep in mind that text enclosed in backticks is not subject to other inline substitutions, but rather passed through as is.

Resolves issue #419.

Process multiple source files from the CLI

The Asciidoctor CLI (i.e., the asciidoctor command) is no longer single-minded! You can pass multiple source files (or a file name pattern) to the Asciidoctor CLI and it will process all the files in turn.

Let’s assume there are two AsciiDoc files in your directory, a.adoc and b.adoc. When you enter the following command in your terminal:

$ asciidoctor a.adoc b.adoc

Asciidoctor will process both files, transforming a.adoc to a.html and b.adoc to b.html.

To save you some typing, you can use the glob operator (*) to match both files using a single argument:

$ asciidoctor *.adoc

The shell will expand the previous command to the one you typed earlier:

$ asciidoctor a.adoc b.adoc

You can also render all the AsciiDoc files in immediate subfolders using the double glob operator (**) in place of the directory name:

$ asciidoctor **/*.adoc

To match all files in the current directory and immediate subfolders, use both glob patterns:

$ asciidoctor *.adoc **/*.adoc

If the file name argument is quoted, the shell will not expand it:

$ asciidoctor '*.adoc'

This time, the text *.adoc gets passed directly to Asciidoctor instead of being expanded to a.adoc and b.adoc. In this case, Asciidoctor handles the glob matching internally in the same way the shell does (when the file name is not in quotes)--with one exception. Asciidoctor can match files in the current directory and subfolders at any depth using a single glob pattern:

$ asciidoctor '**/*.adoc'

Now that’s saving you some typing!

Resolves issue #227.

Additional improvements
  • The asciidoctor command writes to the specified output file if the input is stdin. (#500)

For example, the following command writes to output.html instead of to the console:

$ echo "content" | asciidoctor -o output.html -

Formatting galore

Put images in their place

Images are a great way to enhance the text, whether it’s to illustrate an idea, show rather than tell, or just help the reader connect with the text.

Out of the box, images and text behave like oil and water. Images don’t like to share space with text. They are kind of "pushy" about it. That’s why we tuned the controls in the image macros so you can get the images and the text to flow together.

There are two approaches you can take when positioning your images:

  1. Named attributes

  2. Roles

Positioning attributes

Asciidoctor already supports the align attribute on block images to align the image within the block (e.g., left, right or center). In this release, we added the float named attribute to both the block and inline image macros. This attribute pulls the image to one side of the page or the other and wraps block or inline content around it, respectively.

Here’s an example of a floating block image. The paragraphs or other blocks that follow the image will float up into the available space next to the image. The image will also be positioned horizontally in the center of the image block.

A block image pulled to the right and centered within the block

Here’s an example of a floating inline image. The image will float into the upper-right corner of the paragraph text.

An inline image pulled to the right of the paragraph text
You can find Linux everywhere these days!

When you use the named attributes, CSS gets added inline (e.g., style="float: left"). That’s bad practice because it can make the page harder to style when you want to customize the theme. It’s far better to use CSS classes for these sorts of things, which map to roles in AsciiDoc terminology.

Positioning roles

Here are the examples from above, now configured to use roles that map to CSS classes in the default Asciidoctor stylesheet:

Image macros using positioning roles

You can find Linux everywhere these days!

The following table lists all the roles available out of the box for positioning images.

Roles for positioning images
Float Align







Block Image

Inline Image

Merely setting the float direction on an image is not sufficient for proper positioning. That’s because, by default, no space is left between the image and the text. To alleviate this problem, we’ve added sensible margins to images that use either the positioning named attributes or roles.

If you want to customize the image styles, perhaps to customize the margins, you can provide your own additions to the stylesheet (either by using your own stylesheet that builds on the default stylesheet or by adding the styles to a docinfo file).

Framing images

It’s common to frame the image in a border to further offset it from the text. You can style any block or inline image to appear as a thumbnail using the thumb role (or th for short), also in the default stylesheet.

The thumb role doesn’t alter the dimensions of the image. For that, you need to assign the image a height and width.

Here’s a very common example for adding an image to a blog post. The image floats to the right and is framed to make it stand out more from the text.

image:logo.png[role="related thumb right"] Here's text that will wrap around the image to the left.

Notice we added the related role to the image. This role isn’t technically required, but it gives the image semantic meaning.

Controlling the float

When you start floating images, you may discover that too much content is floating around the image. What you need is a way to clear the float. That is provided using another role, float-group.

Let’s assume that we’ve floated two images so that they are positioned next to each other and we want the next paragraph to appear below them.

.Image A

.Image B
image::b.png[B,240,180,title="Image B"]

Text below images.

When this example is rendered and viewed a browser, the paragraph text appears to the right of the images. To fix this behavior, you just need to "group" the images together in a block with self-contained floats. Here’s how it’s done:

.Image A

.Image B

Text below images.

This time, the text will appear below the images where we want it.

Resolves issue #460.

Image URLs are rendered, not mangled

AsciiDoc couldn’t decide if it wanted to support remote images (i.e., images with a URL target) or not. While you’ve always been able to use a URL for block images, both AsciiDoc and Asciidoctor were ignoring inline images with a URL target.

Even the block images would fall apart in AsciiDoc if you defined the imagesdir attribute to set the location of your local images. AsciiDoc was mangling the image URL in this case by blindly prefixing the URL with this path. Doh!

Things were messy. They aren’t anymore. You can now reference images served from any URL (e.g., your blog, an image hosting service, your docs server, etc.) and never have to worry about downloading the images and putting them somewhere locally. Asciidoctor gets it right. We’ve also updated the AsciiDoc compatibility file so that AsciiDoc gets it right too.

Here are a few examples of images that have a URL target:

Block image with a URL target
imagesdir: ./images

Inline image with a URL target
imagesdir: ./images

You can find image:[Linux,25,35] everywhere these days.
The value of imagesdir is ignored when the image target is a URI.

If you want to avoid typing the URL prefix for every image, and all the images are located on the same server, you can use the imagesdir attribute to set the base URL:

Using a URL as the base URL for images


This time, the imagesdir is used since the image target is not a URL (the imagesdir just happens to be one).

Resolves issue #470.

Additional improvements
  • Footnotes containing URLs are now parsed correctly and formatted properly when output to HTML. (#506)

A well-behaved table of contents (TOC)

The TOC in the html5 backend is now rendered as an unordered list instead of an ordered list. This change was made since the automatic numbering of an ordered list isn’t consistent with the numbering strategy in AsciiDoc and therefore is semantically incorrect. This also eliminates the "double numbering of sections" problem that was occurring when the default stylesheet was absent. Additionally, the type="none" list attribute work-around can be dropped.

Resolves issue #461.

Asciidoctor now correctly numbers sections in cases when numbering is disabled for a portion of the document. Previously, Asciidoctor would increment the section number counter in regions of the document where section numbering was disabled. This resulted in section numbers being skipped. Asciidoctor now freezes the counter where numbering is suppressed to prevent gaps in the numbering.

Asciidoctor was also preventing section numbering from being turned off if the document started with section numbering on. Now, if the -a numbered option is passed to Asciidoctor, it will still honor :numbered!: directives in the flow of the document.

In short, section numbering now works the way it should.

Resolves issue #341.

Additional improvements
  • toc and numbered attributes are enabled by default in the DocBook backend. (#540)

  • The TOC can be positioned to the right by assigning the value right to the toc-position, toc or toc2 attribute. (#467, #618)

  • The preamble toc has been updated with a panel-like styling in the default Asciidoctor stylesheet (as seen on (#507)

Markdown-style horizontal rules

Asciidoctor continues to expand support for (reasonable) Markdown syntax by recognizing Markdown horizontal rules. The motivation here is to ease migration (both of the content and the mind).

To avoid conflicts with the syntax of AsciiDoc block delimiters, only 3 repeating characters (- or *) are recognized. As with Markdown, whitespace between the characters is optional.

Recognized Markdown horizontal rule syntax

- - -


* * *

A macro definition for the Markdown horizontal rules is included in the AsciiDoc compatibility file so they can be recognized by the asciidoc command as well.

Resolves issue #455.

Content, more or less

Include content from a URI

The include directive can now include content directly from a URI.

Here’s an example that demonstrates how to include AsciiDoc content:



Here’s another example showing how to include specific lines of a source file:



Since this is a potentially dangerous feature, it’s disabled if the safe mode is SECURE or greater. Assuming the safe mode is less than SECURE, you must also set the allow-uri-read attribute to permit Asciidoctor to read content from a URI.

Reading content from a URI is obviously much slower than reading it from a local file. Asciidoctor provides a way for the content read from a URI to be cached, which is highly recommended.

To enable the built-in cache, you must:

  • install the open-uri-cached gem

  • set the cache-uri attribute

When these two conditions are satisfied, Asciidoctor will cache content read from a URI according the to HTTP caching recommendations.

Resolves issue #445.

Additional improvements
  • The include directive now resolves files relative to the current document instead of the root document. This applies to include directives used inside a file which itself has been included. (#572)

AsciiDoc allows you to include custom content in the header of the output document (HTML or DocBook) by supplying docinfo files. In Asciidoctor 0.1.4, docinfo files can be used to add custom content to the footer as well.

Footer docinfo files are differentiated from header docinfo files by adding -footer to the file name. In the HTML output, the footer content is inserted inside the footer div (i.e., <div id="footer">). In the DocBook output, the footer content is inserted immediately before the ending </article> or </book> element.


If you want to add content to the footer of a specific document, put the content in the file <docname>-footer.html (for HTML output) or <docname>-footer.xml (for DocBook output), where <docname> is the name of the document without the AsciiDoc extension. Then, set the attribute docinfo in the AsciiDoc source document to enable the feature.


If you want to add content to the footer of all documents in the same directory, put the content in the file docinfo-footer.html (for HTML output) or docinfo-footer.xml (for DocBook output). Then, set the attribute docinfo1 in the AsciiDoc source document to enable the feature.


If you want the document to look for either docinfo file, set the attribute docinfo2 in the AsciiDoc source document.

Resolves issue #486.

Additional enhancements
  • Attributes are substituted in the content of docinfo files (both header and footer). (#403)

  • The "Last updated" line in the footer can be disabled by unassigning the attribute last-update-label (#407)

Ignore front matter added for static-site generators

Many static site generators (i.e., Jekyll, Middleman, Awestruct) rely on "front matter" added to the top of the document to determine how to render the content. Front matter typically starts on the first line of a file and is bounded by block delimiters (e.g., ---).

Here’s an example of a document that contains front matter:

layout: default (2)
= Document Title

1 Front matter delimiters
2 Front matter data

The static site generator removes these lines before passing the document to the Asciidoctor processor to be rendered. Outside of the generator, however, these extra lines confuse the AsciiDoc processor.

If the skip-front-matter attribute is set, Asciidoctor 0.1.4 will recognize the front matter and consume it before parsing the document. Asciidoctor stores the content it removes in the front-matter attribute to make it available for integrations. Asciidoctor also removes front matter when reading include files.

Awestruct can get the information it needs directly from AsciiDoc attributes defined in the document header, eliminating the need to worry about front matter at all.

Resolves issue #502.

Backend boost

Stylesheets are embedded by default

In earlier versions of Asciidoctor, we linked to the stylesheet in the HTML output by default rather than embedding it—​the reverse of how AsciiDoc works. The reason we did it this way was to keep the HTML output document lightweight. What we found is that new users often don’t discover the default stylesheet and get confused when certain features, which rely on CSS, don’t work.

We’d rather have Asciidoctor “just work” out of the box. It’s a better experience for new users and we get to spend less time repeatedly answering the same forum post.

That’s why in Asciidoctor 0.1.4 (and going forward), stylesheets are embedded in the HTML output by default (i.e., linkcss is not set). If no stylesheet is specified, then it’s the default stylesheet that gets embedded. New users no longer have to fiddle with the linkcss or copycss attributes.

As it turns out, there’s another benefit to switching this default. We no longer have to rely on the copycss attribute at all. Now, if the linkcss attribute is set, stylesheets are copied to the stylesdir (inside the output directory) so the HTML document can find them. If you’re using the default stylesheet, you’ll see asciidoctor.css appear in this directory. To disable this behavior, just unset the copycss attribute (i.e., copycss!).

Asciidoctor does not yet copy a user-specified stylesheet when the linkcss stylesheet is set.

Resolves issue #428.

Auxiliary stylesheets

Asciidoctor will also embed the stylesheet that provides the theme for either the CodeRay or Pygments syntax highlighter by default.

For CodeRay

If the source-highlighter attribute is coderay and the coderay-css attribute is class, the CodeRay stylesheet is:

  • embedded if linkcss is not set (default behavior)

  • copied to the file asciidoctor-coderay.css inside the stylesdir folder within the output directory if linkcss is set

For Pygments

If the source-highlighter attribute is pygments and the pygments-css attribute is class, the Pygments stylesheet is:

  • embedded if linkcss is not set (default behavior)

  • copied to the file asciidoctor-pygments.css inside the stylesdir folder within the output directory if linkcss is set

Resolves issue #381.

Multiple custom template directories

Custom templates can now be stored in multiple directories. That means you can build on an existing backend by copying just the templates you want to modify. Then, simply pass both the directory holding the original templates and the directory containing your customized templates when you invoke Asciidoctor.

In the CLI, multiple template directories are specified by using the -T option multiple times.

$ asciidoctor -T /path/to/original/templates -T /path/to/modified/templates sample.adoc

In the API, multiple template directories are specified by passing an array to the template_dirs option:

Asciidoctor.render_file 'sample.adoc', :safe => :safe, :in_place => true,
    :template_dirs => ['/path/to/original/templates', '/path/to/modified/templates']

Hack away!

Resolves issue #437.

Additional improvements
  • The template engine option in the API (i.e., :template_engine) is now mapped as the --template-engine (long) or -E (short) option in the CLI. This option is used for resolving the location of backend templates relative to path specified using the --template-dir (long) or -T (short) option. (#406)

  • Backend templates are now cached so that they are not reloaded each time Asciidoctor is invoked in the same Ruby process. By default, Asciidoctor uses an internal cache, though a custom cache can be passed to the API using the option :template_cache. (#438)

Man pages in AsciiDoc

One of the most interesting uses of AsciiDoc is for creating man pages (short for manual pages) for Unix and Unix-like operating systems. A man page conforms to a special document structure. That structure is recognized by AsciiDoc, and now Asciidoctor, when the doctype attribute is set to manpage.

When reading an AsciiDoc document using the manpage doctype, Asciidoctor parses the following man page metadata:

  • mantitle

  • manvolnum

  • manname

  • manpurpose

The mantitle and manvolum are captured from the document title. The manname and manpurpose are taken from the first section of the document, which must be a level 1 section and have content in the format <manname> - <manpurpose>.

Here’s an example of a man page written in AsciiDoc:

= asciidoctor(1)
:doctype: manpage

asciidoctor - converts AsciiDoc source files...

*asciidoctor* ['OPTION']... 'FILE'...

From this document, Asciidoctor extracts the following man page-related attributes:








converts AsciiDoc source files…​

Refer to the AsciiDoc source of the Asciidoctor man page to see a complete example. The man pages for git are also produced from AsciiDoc documents, so you can use those as another example to follow.

Resolves issue #488.

Additional improvements
  • Asciidoctor produces the same output as AsciiDoc when rendering a man page to HTML using the html5 backend. (#489)

  • The Asciidoctor Backends repository hosts an early draft of a manpage backend, which is now used to generate the man page for Asciidoctor.


Ever since I started working on Asciidoctor, I’ve been eagerly awaiting the chance to work on the extensions API. That time has come. I’m excited to say that extensions are available as a technology preview in Asciidoctor 0.1.4.

Technology Preview

The extension API should be considered experimental and subject to change. This technology preview is intended for developers interested in playing around with it and helping to mature the design.

If you need the capabilities that extensions provide now, don’t be afraid to jump on board. Just keep in mind that you may need to rework parts of your extensions when you upgrade Asciidoctor.


The reason I’ve been looking forward to bringing extensions to Asciidoctor is because they’ve already proven to be central to the success of AsciiDoc and the Python implementation. Despite the success they’ve enjoyed, there’s still plenty of room for improvement.

Extensions in AsciiDoc (technically called filters) have a number of problems:

  • they are challenging to write because they work at such a low-level (read as: nasty regular expressions)

  • they are fragile since they rely on system commands to do anything significant

  • they are hard to distribute due to the lack of integration with a formal distribution system

The goal for Asciidoctor has always been to allow extensions to be written using the full power of a programming language (whether it be Ruby, Java, Groovy or JavaScript), similar to what we’ve done with the backend (rendering) mechanism. That way, you don’t have to shave yaks to get the functionality you want, and you can distribute the extension using defacto-standard packaging mechanisms (like RubyGems or JARs).

Extension points

Here are the extension points that are available in Asciidoctor 0.1.4.


Processes the raw source lines before they are passed to the parser.


Processes the Asciidoctor::Document (AST) once parsing is complete.


Processes the output after the document has been rendered, but before it’s written to disk.

Block processor

Processes a block of content marked with a custom block style (i.e., [custom]). (similar to an AsciiDoc filter)

Block macro processor

Registers a custom block macro and processes it (e.g., gist::12345[]).

Inline macro processor

Registers a custom inline macro and processes it (e.g., btn:[Save]).

Include processor

Processes the include::<filename>[] directive.

These extensions are registered per document using a callback that feels sort of like a DSL:

Asciidoctor::Extensions.register do |document|
  preprocessor FrontMatterPreprocessor
  treeprocessor TerminalCommandTreeprocessor
  postprocessor CustomFooterPostprocessor
  block :yell, YellBlock
  block_macro :gist, GistMacro if document.basebackend? 'html'
  inline_macro :man, ManpageMacro

You can register more than one processor of each type, though you can only have one processor per custom block or macro. Each registered class is instantiated when the Asciidoctor::Document is created.

There is currently no extension point for processing a built-in block, such as a normal paragraph. Look for that feature in a future Asciidoctor release.

For now, you need to use the Asciidoctor API (not the CLI) in order to register the extensions and invoke Asciidoctor. Eventually, we’ll be able to load extensions packaged in a RubyGem (Ruby) or JAR (Java) by scanning the LOAD_PATH (Ruby) or classpath (Java), respectively. We may also ship some built-in extensions that can be enabled using an attribute named extensions, similar to how Markdown processors work.

For those of you on the JVM, yes, you can write extensions in Java. We’ve prototyped it and it works. We’re still sorting out a few technical challenges and documentation to make it completely smooth, but we’ll get there. For details, follow the discussion in issue #97.

Resolves issues #97 and #100.

I’d like to recognize the authors of the libraries I used as inspiration for Asciidoctor’s extension API, most notably Middleman, Python Markdown and Kramdown.

Example extensions

Below are several examples of extensions and how they are registered.

Preprocessor example


Skim off front matter from the top of the document that gets used by site generators like Jekyll and Awestruct.
tags: [announcement, website]
= Document Title


.Captured front matter
require 'asciidoctor'
require 'asciidoctor/extensions'

class FrontMatterPreprocessor < Asciidoctor::Extensions::Preprocessor
  def process reader, lines
    return reader if lines.empty?
    front_matter = []
    if lines.first.chomp == '---'
      original_lines = lines.dup
      while !lines.empty? && lines.first.chomp != '---'
        front_matter << lines.shift

      if (first = lines.first).nil? || first.chomp != '---'
        lines = original_lines
        @document.attributes['front-matter'] = front_matter.join.chomp
        # advance the reader by the number of lines taken
        (front_matter.length + 2).times { reader.advance }
Asciidoctor::Extensions.register do |document|
  preprocessor FrontMatterPreprocessor

Asciidoctor.render_file '', :safe => :safe, :in_place => true

Treeprocessor example


Detect literal blocks that contain terminal commands, strip the prompt character and style the command using CSS in such a way that the prompt character cannot be selected (as seen on
 $ echo "Hello, World!"

 $ gem install asciidoctor
class TerminalCommandTreeprocessor < Asciidoctor::Extensions::Treeprocessor
  def process
    process_blocks @document if @document.blocks?

  def process_blocks node
    node.blocks.each_with_index do |block, i|
      if block.context == :literal && block.lines.first.start_with?('$ ')
        node.blocks[i] = convert_to_terminal_listing block
        process_blocks block if block.blocks?

  def convert_to_terminal_listing block
    attributes = block.attributes
    attributes['role'] = 'terminal'
    lines = do |line|
      line = block.sub_specialcharacters line.chomp
      if line.start_with? '$ '
        %(<span class="command">#{line[2..-1]}</span>)
    end @document, :listing, :content_model => :verbatim, :subs => [],
        :source => lines * "\n", :attributes => attributes
Asciidoctor::Extensions.register do |document|
  treeprocessor TerminalCommandTreeprocessor

Asciidoctor.render_file '', :safe => :safe, :in_place => true

Postprocessor example


Insert custom footer text.

class CustomFooterPostprocessor < Asciidoctor::Extensions::Postprocessor
  def process output
    content = 'Copyright Acme, Inc.'
    if @document.basebackend? 'html'
      replacement = %(<div id="footer-text">\\1<br>\n#{content}\n</div>)
      output = output.sub(/<div id="footer-text">(.*?)<\/div>/m, replacement)
    elsif @document.basebackend? 'docbook'
      replacement = %(<simpara>#{content}</simpara>\n\\1)
      output = output.sub(/(<\/(?:article|book)>)/, replacement)
Asciidoctor::Extensions.register do |document|
  postprocessor CustomFooterPostprocessor

Asciidoctor.render_file '', :safe => :safe, :in_place => true

Block processor example


Register a custom block style named yell that uppercases all the words and converts periods to exclamation points.
The time is now. Get a move on.
require 'asciidoctor'
require 'asciidoctor/extensions'

class YellBlock < Asciidoctor::Extensions::BlockProcessor
  option :contexts, [:paragraph]
  option :content_model, :simple

  def process parent, reader, attributes
    lines = {|line| line.upcase.gsub(/\.( |$)/, '!\\1') } parent, :paragraph, :source => lines, :attributes => attributes
Asciidoctor::Extensions.register do |document|
  block :yell, YellBlock

Asciidoctor.render_file '', :safe => :safe, :in_place => true

Block macro processor example


Create a block macro named gist for embedding a gist.
.My Gist
require 'asciidoctor'
require 'asciidoctor/extensions'

class GistMacro < Asciidoctor::Extensions::BlockMacroProcessor
  def process parent, target, attributes
    title = (attributes.has_key? 'title') ?
        %(\n<div class="title">#{attributes['title']}</div>) : nil
    source = %(<div class="gistblock">#{title}
<div class="content">
<script src="{target}.js"></script>
</div>) parent, :pass, :content_model => :raw, :source => source
Asciidoctor::Extensions.register do |document|
  if document.basebackend? 'html'
    block_macro :gist, GistMacro

Asciidoctor.render_file('', :safe => :safe, :in_place => true)

Inline macro processor example


Create an inline macro named man that links to a manpage.
See man:gittutorial[7] to get started.
require 'asciidoctor'
require 'asciidoctor/extensions'

class ManpageMacro < Asciidoctor::Extensions::InlineMacroProcessor
  option :pos_attrs, ['volnum']

  def process parent, target, attributes
    text = manname = target
    suffix = ''
    target = "#{manname}.html"
    if (volnum = attributes.fetch('volnum', nil))
      suffix = "(#{volnum})"
    @document.register(:links, target)
    %(#{, :anchor, text, :type => :link, :target => target).render}#{suffix})
Asciidoctor::Extensions.register do |document|
  inline_macro :man, ManpageMacro

Asciidoctor.render_file('', :safe => :safe, :in_place => true)

Include processor example


Include a file from a URI.
:source-highlighter: coderay

require 'asciidoctor'
require 'asciidoctor/extensions'
require 'uri-open'

class UriIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor
  def handles? target
    target.start_with?('http://') or target.start_with?('https://')

  def process reader, target, attributes
    content = open(target).readlines
    reader.push_include content, target, target, 1, attributes
Asciidoctor::Extensions.register do |document|
  include_processor UriIncludeProcessor

Asciidoctor.render_file('', :safe => :safe, :in_place => true)

AsciiDoc compatibility file updates

The following improvements have been made to the AsciiDoc compatibility file, compat/asciidoc.conf:

  • Added level 5 (<h6>) section titles

  • Recognize attributes in link macro when linkattrs is set

  • Removed linkcss attribute

  • Fixed detection of fenced code blocks

  • Recognize XML-style callouts

  • Don’t prepend imagesdir to image target if it is a URI or absolute path

  • Add float attribute to image inline macro

  • Calculate alt text from image filename in a manner consistent with Asciidoctor

  • Recognize markdown-style horizontal rules

Resolves issue #441 and other related issues.


The best part of Asciidoctor is its community. We’d like to thank the following people for contributing to and participating in this release:

We’d like to give a special shout out to Alex Soto and Xavier Coulon for making their first code contributions to the main Asciidoctor repository and to Per Anderssen for getting Asciidoctor into Debian and Ubuntu!

I (Dan) would also like to thank Sarah White for her monstrous effort to pull together the documentation and prepare a documentation workflow for the project.

Additional thanks to everyone who is using the project and those who have participated in the growing ecosystem of sub-projects. The mission of Asciidoctor is to help you write, publish and communicate your content successfully, and enjoy doing it! With your feedback and participation, we can achieve that goal together! We encourage you to ask questions and discuss any aspects of the project on the mailing list or IRC.

If you discover errors or omissions in the source code, documentation, or website content, please don’t hesitate to submit an issue or open a pull request with a fix. We’re always eager to learn about your experiences and how we can help improve them. Together, we’re going to make documentation fun, easy, and rewarding!

What’s next?

This release is just the beginning of the release train. Look for releases of the Java integration, Maven plugin, Gradle plugin and more recent additions, such as the editors.

The next release of Asciidoctor will be 1.5.0. The focus of release will be on improvements to the extension API, additional syntax conveniences and enhancements to the toolchain.

We’re making a shift in the version number scheme in the next release to make room for point releases and to get out from underneath 1.0.0.

We hope to keep the Asciidoctor 1.5.0 release a bit more manageable and turn around a release in ~2 months. With your participation and feedback, we can make it happen!

Appendix A: TL;DR

  • Stylesheets are embedded by default

  • Inter-document cross references (e.g., <<doc-b#section-a,Section A in Document B>>)

  • Implicit header row on tables

  • DocBook 5.0 backend (i.e., docbook5)

  • Icon inline macro (e.g, icon:heart[2x]), designed primarily for using font-based icons

  • Checklists

  • Developer and user-friendly callouts in code listings

  • Pygments syntax highlighter (e.g., source-highlighter=pygments)

  • Shorthand notation for block options (e.g., [%header%footer])

  • Shorthand notation for id and role on formatted text (e.g., [#id.role]_text_)

  • Roles for text enclosed in backticks (e.g., [role]`text`)

  • Docinfo files for the document footer (e.g., docinfo-footer.(html|xml))

  • Include file from URL using include::[] directive

  • Include file is resolved relative to current include file

  • Support for YouTube and Vimeo IDs in video macro (e.g., video::12345[youtube,480,360])

  • Missing attribute references (e.g., {bogus}) do not cause line to be dropped (by default)

  • Parse manpage metadata

  • TOC positioning (e.g., toc-position=right, toc=right or toc2=right)

  • Improved section numbering in document and in TOC

  • First draft of the Asciidoctor User Manual

  • Debian and Ubuntu packages (joining the Fedora package)

See the 0.1.4 Changelog for a complete list of changes.

Asciidoctor Maven plugin released!

by Jason Porter -

I’m proud to announce the Asciidoctor Maven plugin release! This is simply a bug fix release to correct some of the things I messed up with 0.1.3 (sorry about that). Like version 0.1.3 before it, it’s based on the same version of the Asciidoctor Java integration project and the Asciidoctor projects — 0.1.3.

Thank you to all the contributors for helping out.

Go forth and make great documentation once again!

Plugin artifact information
Group ID Artifact ID Latest versions Download



pom jar

Upgrading to (recommended) is simple. Just update the version in your Maven POM. All necessary dependencies should be pulled in via Maven.

For more information about issues fixed in this release, please see the milestone in the issue tracker!

Asciidoctor Maven plugin 0.1.3 released!

by Jason Porter -

It has taken me a little while longer to get this release out the door than I would have hoped, but it’s here at last! I’m proud to release Asciidoctor Maven plugin version 0.1.3! Like the other versions before it, it is based on the same version of the Asciidoctor Java integration project and the Asciidoctor projects — 0.1.3.

There’s very little new things for the end user in this release as the changes were mostly to use some of the new ease of use things from the Java Integration project.

I would like to call out the help of Brian Leathem in this release in helping me go through a few things and pushing me to release it. Also, thank you to all the contributors for helping out.

Go forth and make great documentation once again!

Plugin artifact information
Group ID Artifact ID Latest versions Download




pom jar

Upgrading to 0.1.3 (recommended) is simple. Just update the version in your Maven POM. All necessary dependencies should be pulled in via Maven.

For more information about issues fixed in this release, please see the 0.1.3 milestone in the issue tracker!

  • 1 of 2