Asciidoctor Gradle Plugin
The Asciidoctor Gradle Plugin is the official means of using Asciidoctor to convert all your AsciiDoc documentation using Gradle.
| This is a port of the Asciidoctor Maven Plugin project founded by @LightGuard and relies on AsciidoctorJ founded by @lordofthejars. |
Contributing
Are you interested in contributing to this project? If so please read HACKING before sending in a patch. Thank you!
Installation
Use the following snippet inside a Gradle build file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
}
}
apply plugin: 'org.asciidoctor.convert'
Usage
The plugin adds a new task named asciidoctor. You can configure this task using the following configuration properties and methods.
logDocuments | a boolean specifying if documents being processed should be logged on console. Type: boolean. Default: |
separateOutputDirs | specifies whether each backend should use a separate subfolder under |
sourceDir | where the asciidoc sources are. Use either |
sources | specify which Asciidoctor source files to include by using an Ant-style PatternSet. |
resources | specify which additional files (image etc.) must be copied to output directory using a CopySpec. |
outputDir | where generated docs go. Use either |
backends | the backends to use. Use |
gemPath | one or more gem installation directories (separated by the system path separator). Use |
requires | a set of Ruby modules to be included. Use |
options | a Map specifying different options that can be sent to Asciidoctor. Use |
attributes | a Map specifying various document attributes that can be sent to Asciidoctor Use |
To see examples of many of these configuration options used in practice, refer to the Asciidoctor Gradle Examples project.
Defining Sources
The plugin will search for sources under sourceDir
. Sources may have any of the following extensions in order to be discovered:
-
.adoc (preferred)
-
.asciidoc
-
.ad
-
.asc
To select only certain files, use the sources
method. This method takes a closure as an argument, which in turn configures an internal PatternSet.
To specify a custom output folder, use the outputDir
method.
asciidoctor {
sourceDir = file('docs')
sources {
include 'toplevel.adoc', 'another.adoc', 'third.adoc'
}
outputDir = file('build/docs')
}
Paths defined in this PatternSet are resolved relative to the sourceDir
.
Processing Auxiliary Files
Some backends require that additional files be copied across. The most common example are images for HTML backends. For this the resources
method is used. It is provided with a closure that configures an internal CopySpec
resources {
from('src/resources/images') {
include 'images/**/*.png'
exclude 'images/**/notThisOne.png'
}
from( "${
buildDir
}
/downloads" ) {
include 'deck.js/**'
}
into './images'
}
Files will be copied to below ${
outputDir
}
/${
backend
}
(or just ${
outputDir
}
if separateOutputDirs=false
)
Unlike sourceDir
files can be copied from anywhere in the filesystem.
If resources
is never set, the default behaviour is as if the following was called
resources {
from(sourceDir) {
include 'images/**'
}
}
If you do not want this behaviour, then it can be turned off by doing
resources {
}
Options & Attributes
The following options may be set using the task’s options
property
-
header_footer - boolean
-
template_dirs - List<String>
-
template_engine - String
-
doctype - String
Any key/values set on attributes
is sent as is to Asciidoctor. You may use this Map to specify a stylesheet for example. The following snippet shows a sample configuration defining attributes.
asciidoctor {
(1)
outputDir "${
buildDir
}
/docs"
options doctype: 'book', ruby: 'erubis'
attributes 'source-highlighter': 'coderay',
toc
: '',
idprefix
: '',
idseparator
: '-'
}
-
append below the line:
apply plugin: 'org.asciidoctor.convert'
The following attributes are automatically set by the asciidoctor
task:
-
project-name : matches
$project.name
-
project-version: matches
$project.version
(if defined). Empty String value if undefined -
project-group: matches
$project.group
(if defined). Empty String value if undefined
These attributes may be overridden by explicit user input.
You may need to include extra content into the head of the exported document. For example, you might want to include jQuery inside the <head>
element of the HTML export. To do so, first create a docinfo file src/docs/asciidoc/docinfo.html
containing the content to include, in this case the <script>
tag to load jQuery.
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.js"></script>
Then, add the docinfo1
attribute to the attributes list in the previous example:
attributes docinfo1: ''
Refer to the Asciidoctor documentation to learn more about these options and attributes.
Attribute values defined on the build file will win over values defined on the documents themselves. You can change this behavior by appending an @
at the end of the value when defined in the build file. Please refer to Attribute assignment precedence for more information.
Configuration
This plugin uses asciidoctorj-1.5.3.2
by default, however, you can change this by defining a value on the asciidoctorj
extension, like so
asciidoctorj {
version = '1.6.0-SNAPSHOT'
}
Do not forget to add an entry to the repositories
block pointing to Maven local if you’d like to run a local version of Asciidoctorj (such as an snapshot build for testing bleeding edge features). The following snippet is all you need.
repositories {
mavenLocal() (1)
jcenter()
(2)
}
asciidoctorj {
version = '1.6.0-MY_SNAPSHOT'
}
-
resolves artifacts in your local Maven repository
-
resolves artifacts in Bintray’s jcenter (where all other dependencies are found)
The plugin also adds Bintray’s JCenter as a default repository as the place to looks for asciidocotorj
. In some contexts this behaviour can be considered detrimental or unwanted. In such cases this behaviour can be turned off by doing
asciidoctorj {
noDefaultRepositories = true
}
Development
See HACKING.
Adding Custom Extensions
Starting with version 1.5.0 you’ll be able to write your own Asciidoctor extensions in Groovy, or any other JVM language for that matter. There are several options for you to make it happen.
As External Library
This is the most versatile option, as it allows you to reuse the same extension in different projects. An external library is just like any other Java/Groovy project. You simply define a dependency using the asciidoctor
configuration.
dependencies {
asciidoctor 'com.acme:asciidoctor-extensions:x.y.z'
}
As Project Dependency
The next option is to host the extension project in a multi-project build. This allows for a much quicker development cycle as you don’t have to publish the jar to a repository every time you make adjustments to the code. Take for example the following setup:
. ??? build.gradle ??? core ?
??? build.gradle ?
??? src ?
??? asciidoc ?
?
??? index.adoc ?
??? main ?
??? java ??? extension ?
??? build.gradle ?
??? src ?
??? main ?
??? groovy ?
?
??? org ?
?
??? asciidoctor ?
?
??? example ?
?
??? ExampleExtensionRegistry.groovy ?
?
??? YellBlock.groovy ?
??? resources ?
??? META-INF ?
??? services ?
??? org.asciidoctor.extension.spi.ExtensionRegistry ??? settings.gradle
The extension
project is a sibling for core
. The build file for the latter looks like this:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
}
}
apply plugin: 'org.asciidoctor.convert' repositories {
jcenter()
}
dependencies {
asciidoctor project(':extension')
}
As Inline Script
The next option is to define extensions directly in the build script. This approach is based on the project asciidoctorj-groovy-dsl that allows to define Asciidoctor extensions in Groovy. An extension is registered via the extensions
element.
asciidoctor {
extensions {
block(name: "BIG", contexts: [":paragraph"]) {
parent, reader, attributes ->
def upperLines = reader.readLines()
.collect {
it.toUpperCase()
}
.inject("") {
a, b -> a + '\n' + b
}
createBlock(parent, "paragraph", [upperLines], attributes, [:])
}
}
}
http://github.com/asciidoctor/asciidoctorj-groovy-dsl contains a description of the DSL itself.
Groovy extensions can also be included as files.
asciidoctor {
extensions new File('big.groovy')
}
block(name: "BIG", contexts: [":paragraph"]) {
parent, reader, attributes ->
def upperLines = reader.readLines()
.collect {
it.toUpperCase()
}
.inject("") {
a, b -> a + '\n' + b
}
createBlock(parent, "paragraph", [upperLines], attributes, [:])
}
As Build Dependency
The last option is to move the extension
project into Gradle’s buildSrc
directory. There are no additional dependencies to be defined on the consuming projects, as the extension will be automatically picked up by the asciidoctor
task, as the compiled extension is already in the task’s classpath.
Appendix A: Compatibility With Previous Releases
Task Properties
The following properties have been marked as deprecated. Developers are encouraged to migrate ASAP to the alternate properties.
sourceDocumentNames | an override to process multiple source files, which are relative to |
sourceDocumentName | an override to process a single source file. Use |
backend | the backend to use. Use |
Behavior
-
The default value for
sourceDir
has changed fromsrc/asciidoc
tosrc/docs/asciidoc
. -
Files specified in
sourceDocumentNames
must be relative tosourceDir
and fully contained insourceDir
, in other words, it’s no longer possible to process documents placed outside of the project’s sources. Attempts will be made to convert absolute paths to relative paths but conversion will not be guaranteed. Do not pass FileCollections as they will not convert correctly. -
Source files that are not reachable from
sourceDir
, will no longer cause a build exception, they will just be silently ignored. -
For backwards compatibility with older version, embedding
attributes
withinoptions
are still allowed, including legacy forms. -
Non-source files are no longer automatically copied, unless they are in the
images
folder andresources
was never called. -
Each backend will now write to a separate subfolder under
outputDir
. To have the old behaviour useseparateOutputDirs = false
.
Options & Attributes
// Map notation attributes: toc: 'right',
'source-highlighter': 'coderay',
'toc-title': 'Table of Contents' // List notation attributes: [
'toc=right',
'source-highlighter=coderay',
'toc-title=Table of Contents' ] // String notation attributes: 'toc=right source-highlighter=coderay toc-title=Table\\ of\\ Contents'
| Do not forget to transform Groovy strings into Strings (by explicitly invoking .toString() on them) when used as option values, otherwise the Ruby runtime will throw an exception. |
Notice how spaces are escaped in the last key/value pair.
Appendix B: Tips & Tricks
Pre-process and post-process
To make your own custom actions before or after asciidoctor processing, use doFirst
and doLast
. Check out chapters 14 and 17 in the Gradle docs to learn about the various actions you can perform.
asciidoctor.doFirst {
// pre-process
}
asciidoctor.doLast {
// post-process
}
As an example, here’s how to copy the generated index.html
file to the root of the project. This is useful in Windows systems where asciidoctor can’t output directly to the root.
asciidoctor.doLast {
copy {
from 'build/docs/html5'
into "$projectDir"
include 'index.html'
}
}
Force processing
If Gradle detects that there were no changes, asciidoctor processing will be skipped as UP-TO-DATE
. To force asciidoctor processing even if there were no changes:
asciidoctor.outputs.upToDateWhen {
false
}