The Asciidoctor Gradle Plugin Suite is the official means of using Asciidoctor to convert all your AsciiDoc documentation using Gradle.
This started as a port of the Asciidoctor Maven Plugin project founded by Jason Porter and relies on AsciidoctorJ which was founded by Alex Soto. In fact the 1.5.x series of the Asciidoctor Gradle plugin can still be considered a port. However, with 2.x series came a complete departure with functionality far exceeding any lightweight markup plugins for any other build tool. With the 3.x serious allows for even more flexibility and options for the creation of a true DocuOps pipeline by bringing together Gradle as a powerful and generic build tool, and Asciidoctor as an agile and lightweight document generator.
Compatibility
This collection of plugins requires at least Gradle 4.9, JDK 11.0 and AsciidoctorJ 2.0.0 to run. If you need prior Gradle, JDK or AsciidoctorJ support please use a plugin from the 1.5.x or 1.6.x release series.
Quick Start
To start you need to use one of the plugins from the following Gradle snippet
plugins {
id 'org.asciidoctor.jvm.convert' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.convert") version "4.0.2"
}
Task Configuration
All Asciidoctor tasks will have the following methods and properties:
asciidoctorj |
a task extension which allows a task to extend of override global configuration for Asciidoctor tasks.
This allow extensive flexibility. Any thing that can be configured in the global |
attributes |
A shortcut for |
baseDir |
Base directory for asciidoctor document conversion and root document inclusion. The base directory will be the project directory by default, but can be set to any other directory. |
baseDirFollowsSourceDir |
The base directory should be the same as the source directory even if the source directory is located within an intermediate working directory. |
baseDirFollowsSourceFile |
The base directory should be the same as the directory of each individual source file. |
baseDirIsProjectDir |
The base directory is always the current project directory. |
baseDirIsRootProjectDir |
The base directory is always the root project directory. |
configurations |
Specify additional configurations These configurations will be added to the classpath when the task is executed. |
copyAllResources |
Copy all resources to the output directory |
copyNoResources |
Do not copy any resources to the output directory |
copyResourcesOnlyIf |
Only copy resources if the backend matches the listed backend. |
executionMode |
Specifies whether Asciidoctor conversions should be run in-process or out-of-process.
Default: |
languages |
Invoke source language support but specifying one or more languages. |
logDocuments |
Specifies if documents being processed should be logged on console. Type: boolean. Default: |
options |
A shortcut to |
outputDir |
where generated docs go.
Use either |
parallelMode |
Specifies whether each backend or other variant of a converting tasks should be run in parallel or sequential.
Sequential conversions might have less initialisation overhead, but may suffer from |
resources |
specify which additional files (image etc.) must be copied to output directory using a
CopySpec.
secondarySources: Specify which source files should be monitor for change. These are typically files which are included by top-level files as well as doctype files.
Default: All files in sourceDir which matches |
sourceDir |
where the asciidoc sources are.
Use either |
sources |
Specify which Asciidoctor source files to include as toplevel documents. It uses an Ant-style PatternSet. |
useIntermediateWorkDir |
Use an intermediate work directory for sources ances.
Some extensions such as |
withIntermediateArtifacts |
Add intermediate artifacts to output directory.
If the document conversion process creates intermediate artifacts which needs to be added to the output directory, then the pattern set with a closure or |
You will have to configure the properties for each plugin as they are not inherited from one to another.
For example you will have to configure languages for both org.asciidoctor.jvm.convert and org.asciidoctor.jvm.pdf plugins if you want multi language pdf and html.
Otherwise it wil not work properly.
See This issue for more details.
|
The org.asciidoctor.jvm.convert
plugin has a conversion task type of org.asciidoctor.gradle.jvm.AsciidoctorTask
which, in addition the aforementioned will also have the following properties and methods which are configured via an outputOptions
closure or action:
AsciidoctorTask
backends |
the backends to use.
Use |
separateOutputDirs |
specifies whether each backend should use a separate subfolder under |
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 or an Action
as an argument, which in turn configures an org.asciidoctor.gradle.jvm.epub.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')
}
tasks {
"asciidoctor"(AsciidoctorTask::class) {
sourceDir = file("docs")
sources(delegateClosureOf<PatternSet> {
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 org.asciidoctor.gradle.jvm.epub.internal
CopySpec
resources {
from('src/resources/images') {
include 'images/**/*.png'
exclude 'images/**/notThisOne.png'
}
from( "${buildDir}/downloads" ) {
include 'deck.js/**'
}
into './images'
}
resources(delegateClosureOf<CopySpec> {
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/**'
}
}
In case of languages the default behaviour is
resources {
from(new File(sourceDir,"${langName}")) {
include 'images/**'
}
}
If you do not want this behaviour, then it can be turned off by doing
copyNoResources()
If you are using multiple languages and you have identical resource patterns for each languages within sourceDir/$
you need to explicitly declare those on a per-language basis:
resources 'en', {
from("${sourceDir}/en") {
include 'images/**'
}
}
resources 'es', {
from("${sourceDir}/es") {
include 'images/**'
}
}
Include directives and base directory
These plugins do not change the way include:: directive works, but it is important to note how setting baseDir
will affect top level includes. It is recommended that you always use {includedir}
as a prefix for the file path. This attribute is always set to the correct top-level folder where the sources will be located.
However it is not practical for everyone to use {includedir}
and as from 2.2.0 it is possible to add a strategy for controlling the base directory:
asciidoctor {
baseDirIsRootProjectDir() (1)
baseDirIsProjectDir() (2)
baseDirFollowsSourceDir() (3)
baseDirFollowsSourceFile() (4)
}
1 | The base directory is the root project directory. |
2 | The base directory is the current subproject directory. |
3 | The base directory will always the the same as the source directory. If an intermediate working directory is being used, the base directory will automatically point to that. |
4 | The base directory will be the same as the directory of each individual source file. |
Docinfo processing
When using the docinfo
attribute with html
and docbook
backends, it is recommended that baseDirFollowsSourceDir()
is always set. This will ensure that the docinfo files are picked up correctly from the same directory that is the source directory.
Source language support
Some scenarios work on a source set of documents in a primary language and then translations of those sources into other languages. The Gradle plugin simplifies this scenario by allowing a structure such as
│ └── src
│ ├── asciidoc
│ │ └── en
│ │ └── index.adoc
│ │ └── es
│ │ └── index.adoc
This can be enabled in the DSL by doing
asciidoctor {
languages 'en', 'es'
}
Gradle will then process both the en
and the es
source set and output to the output directory using the same languages names. Intermediate working directories and multiple backends are also covered. In this case the lang
attribute will be injected with the specific language as the value.
It is also possible to specify additional attributes that will only be added when a specific language is processed
asciidoctorj { (1)
attributesForLang 'en', langName : 'English'
attributesForLang 'ca', langName : 'Catala'
}
asciidoctorjs { (2)
attributesForLang 'en', langName : 'English'
attributesForLang 'ca', langName : 'Catala'
}
1 | Configuration when using AsciidoctorJ |
2 | Configuration when using Asciidoctor.js |
Choosing a Process Mode for AsciidoctorJ
All AsciidoctorJ-based tasks can control how Asciidoctor conversions are being run via the inProcess
property. This is early days, and a choice for your build will depend very much on your context, but the following has already become clear:
-
IN_PROCESS
andOUT_OF_PROCESS
should theoretically run faster, especially if you continuously rebuild the same documentation. Gradle workers are the underlying implementation for these two options -
The safe option is always
JAVA_EXEC
. For lower memory consumption this is by far the safer option. (It is also the only way we can get the Windows-based tests for this plugin to complete on Appveyor & Travis CI). It you run a lot of builds the penalty start-up time might become an issue for you.
In certain cases the plugin will overrule your choice as it has some built-in rules for special cases. In such cases it will log a warning that it has done that. |
AsciidoctorJ Base Plugin
This plugin is automatically applied by all AsciidoctorJ-based plugins.
Adds an extension for configuring which version of AsciidoctorJ and various other AsciidoctorJ backends.
This is very much similar to the one used in older versions of the Asciidoctor Gradle plugin, but now it also offers the ability to add the same functionality to a task thus allowing a task to override the default versions that has been set.
asciidoctorj {
version = '1.5.6' (1)
groovyDslVersion = '1.0.0.Alpha2' (2)
options doctype: 'book', ruby: 'erubis' (3)
attributes toclevel : 2 (4)
}
1 | Set the default version of AsciidoctorJ for all Asciidoctor tasks in a project. |
2 | Set the default version of the Groovy extensions DSL for all Asciidoctor tasks in a project. |
3 | Add options for all Asciidoctor tasks |
4 | Add attributes for all Asciidoctor tasks |
You can also override or extend select settings within a task using the same extension i.e.
asciidoctor {
asciidoctorj {
setOptions = [ doctype: 'article' ] (1)
attributes toc : left (2)
}
}
1 | Override any global options |
2 | Use these attributes in addition to the globally specified ones. |
The AsciidoctorJ-specific entities that can be set are:
docExtensions |
Groovy DSL and project-based extensions.
Use |
fatalWarnings |
Patterns for AsciidoctorJ log messages that should be treated as fatal errors.
The list is empty be default. Use |
jrubyVersion |
Minimum version of JRuby to be used. The exact version that will be used could be higher due to AsciidoctorJ having a transitive dependency that is newer. |
logLevel |
The log level at which AsciidoctorJ will log.
This is specified as a Gradle logging level. The plugin will translate it to the appropriate
AsciidoctorJ logging level. Default is whatever |
modules |
Configuration for version of specific components and converters that can be used. See AsciidoctorJ Modules for which modules are supported. |
options |
AsciidoctorJ options.
Use |
requires |
The set of Ruby modules to be included.
Use |
resolutionStrategy |
Strategies for resolving Asciidoctorj-related dependencies. AsciidoctorJ dependencies are held in a detached configuration. If for some special reason, you need to modify the way the dependency set is resolved, you can modify the behaviour by adding one or more strategies. |
version |
AsciidoctorJ version. If not specified a sane default version will be used. |
The following common entities can also be set:
attributes |
Asciidoctor attributes.
Use |
attributeProviders |
Additional sources where attributes can be obtained from. Attribute providers are useful for where changes should not cause a rebuild of the docs. |
attributesForLang |
Language-specific attributes. Specify additional attributes which will only be added if a source set for the specified language is being processed. |
safeMode |
Asciidoctor safe mode.
Set the Safe mode as either |
Options & Attributes
The following options may be set using the extension’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.
asciidoctorj { (1)
options doctype: 'book', ruby: 'erubis'
attributes 'source-highlighter': 'coderay',
toc : '',
idprefix : '',
idseparator : '-'
}
1 | This can be globally on the project extension or locally on the task’s extension. |
Or in the Gradle Kotlin DSL:
tasks {
"asciidoctor"(AsciidoctorTask::class) { (1)
options(mapOf("doctype" to "book", "ruby" to "erubis"))
attributes(
mapOf(
"source-highlighter" to "coderay",
"toc" to "",
"idprefix" to "",
"idseparator" to "-"
)
)
}
}
1 | This is an example of setting it on the task extension in Kotlin. |
The following attributes are automatically set by the asciidoctorj
extension:
-
gradle-project-name : matches
$project.name
-
gradle-project-version: matches
$project.version
(if defined). Empty String value if undefined -
gradle-project-group: matches
$project.group
(if defined). Empty String value if undefined
These attributes may be overridden by explicit user input.
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.
Versions of modules
The modules block currently supports four elements
asciidoctorj {
modules {
pdf { (1)
version '1.2.3'
}
epub { (2)
version '1.2.3'
}
diagram { (3)
version '1.2.3'
}
groovyDsl { (4)
version '1.2.3'
}
leanpub { (5)
version '1.2.3'
}
}
}
1 | Asciidoctorj-EPUB version. If not specified asciidoctorj-epub will not be on the classpath. If you plan to use the EPUB backend and not using the EPUB plugin, then you need to set a version here. |
2 | Asciidoctorj-PDF version. If not specified asciidoctorj-pdf will not be on the classpath. If you plan to use the PDF backend and not using the PDF plugin, then you need to set a version here. |
3 | See AsciidoctorJ Diagram, |
4 | Version of Groovy Extensions DSL. If not specified and no extensions are specified, Groovy DSL will not be used. However, if any extensions are added without setting an explicit version and default version will be used. |
5 | {asciidoctorj-leanpub-name} version. If not specified asciidoctorj-leanpub will not be on the classpath. If you plan to use the Leanpub backend and not using the Leanpub plugin, then you need to set a version here. |
When using the {kotlin-dsl} the same settings can be achieved use something similar getModules().getPdf().version("1.2.3")
. In a similar fashion shortcuts can be achieved in the {groovy-dsl}:
asciidoctorj {
modules {
pdf.version '1.2.3'
}
modules.pdf.version '1.2.3'
}
asciidoctorj {
getModules().getPdf().version("1.2.3") (1)
getModules().getPdf().use() (2)
}
1 | Set the Asciidoctorj-PDF version to 1.2.3 . |
2 | Use the default version of Asciidoctorj-PDF. |
Applying the AsciidoctorJ Base plugin on its own
If none of the default conventions work for you, the base plugin can be applied on its own.
plugins {
id 'org.asciidoctor.jvm.base' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.base") version "4.0.2"
}
The New AsciidoctorJ Plugin
plugins {
id 'org.asciidoctor.jvm.convert' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.convert") version "4.0.2"
}
When applying org.asciidoctor.jvm.convert
it creates a single task of type org.asciidoctor.gradle.jvm.AsciidoctorTask
called asciidoctor
.
By convention it sets the
* sourceDir
to src/docs/asciidoc
* outputDir
to ${buildDir}/docs/asciidoc
The AsciidoctorPdf Plugin
plugins {
id 'org.asciidoctor.jvm.pdf' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.pdf") version "4.0.2"
}
When applying org.asciidoctor.jvm.pdf
it creates a single task of type org.asciidoctor.gradle.jvm.pdf.AsciidoctorPdfTask
an extension called pdfThemes
.
The default task is named asciidoctorPdf
and is configured to:
-
Output source to "${buildDir}/docs/asciidocPdf"
-
Not to copy any resources to the output directory
-
It will set also a default version for
asciidoctorj-pdf
artifact. To override setasciidoctorj.pdfVersion
orasciidoctorPdf.asciidoctorj.pdfVersion
.
The AsciidoctorPdfTask
task type has the following additional methods:
fontsDirs |
Directories for custom PDF fonts.
Specify a directory in any form acceptable to |
theme |
Name of the theme to use.
Optional. When specifying a theme name it must match one registered via |
The pdfThemes
extension allows for themes to be registered from local copies or downloaded from GitHub or GitLab and has been inspired by earlier work of Florian Wilhelm (@fwilhe).
pdfThemes {
local 'basic', { (1)
themeDir = file('themes/basic') (2)
themeName = 'very-basic' (3)
}
}
1 | Local themes are registered using the local keyword and must be provided with a name |
2 | Directory for finding the theme. Specify a directory in any form acceptable to project.file . |
3 | Optional setting of the style name. If this is not set, the theme name provided previously will be used. |
pdfThemes {
github 'basic', { (1)
organisation = 'fwilhe2' (2)
repository = 'corporate-theme' (3)
relativePath = 'resources/themes' (4)
branch = 'master' (5)
tag = '1.0.1' (6)
commit = '4910271e8c3964b60e186a62f3e4339ed0752714' (7)
}
}
1 | Specify a GitHub repository which contains one or more themes. (For GitLab replace github with gitlab ). |
2 | GitHub/GitLab Organisation (or user). |
3 | Name of repository containing the theme(s). |
4 | Relative path inside the repository to where the theme is located. If not specified the theme is assumed to be in the root of the repository. |
5 | Specify the branch |
6 | Instead of a branch a tag can be used. |
7 | Instead of a branch or a tag, a very specific commit can be used. |
If a repository contains more than one theme, then the block will need to be repeated for each theme and the name
and relativePath
adjusted accordingly. Gradle will however, only download the repository once.
Kotlin users can use equivalent Action
-based configurations.
The AsciidoctorEpub Plugin
INFO: As from version 3.3 support for KindleGen is dropped as Amazon no longer has the binary available for download.
plugins {
id 'org.asciidoctor.jvm.epub' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.epub") version "4.0.2"
}
When applying org.asciidoctor.jvm.epub
it creates a single task of type org.asciidoctor.gradle.jvm.epub.AsciidoctorEpubTask
which is then configured to:
-
Output source to "${buildDir}/docs/asciidocEpub"
-
Not to copy any resources to the output directory
-
It will set also a default version for
asciidoctorj-epub
artifact. To override setasciidoctorj.epubVersion
orasciidoctorEpub.asciidoctorj.epubVersion
.
The AsciidoctorEpubTask
task type has the following additional methods:
ebookFormats |
The epub formats to generate.
Specify one of more strings. Anything that is supported by the Asciidoctor EPUB backend can be used. Constant |
The AsciidoctorJ Reveal.js Plugin
plugins {
id 'org.asciidoctor.jvm.revealjs' version '4.0.2'
}
plugins {
id("org.asciidoctor.jvm.revealjs") version "4.0.2"
}
When applying org.asciidoctor.jvm.revealjs
support is added for creating slides using Asciidoctor & Reveal.js. The plugin configures:
-
Create a task called
asciidoctorRevealJs
. -
Create an extension called
revealjs
which is used for configuring the version of Reveal.js as well as a template. -
Create an extension called
revealjsPlugins
which will allow for downloading additional Reveal.js plugins. -
Output source to "${buildDir}/docs/asciidocRevealJs"
-
Copy all resources to the output directory including Reveal.js templates.
-
Apply the
org.asciidoctor.jvm.gems
plugin as GEM support is required.
The AsciidoctorRevealJSTask
task type has the following additional methods:
revealjsOptions |
Configure special Reveal.js options. Can be configured via Closure or Action. See [RevealJSOptions] for more details. |
templateDir |
Location where the template directory will be located on disk before Asciidoctor processing starts. |
theme |
The Reveal.js theme to use. The theme must match one from the template. |
The version of the Reveal.js GEM and the Reveal.js template is configured via the revealjs
extension:
revealjs {
version = '1.1.3' (1)
templateGitHub { (2)
organisation = 'hakimel'
repository = 'reveal.js'
tag = '3.7.0'
}
}
1 | Reveal.js GEM version |
2 | Obtain the Reveal.js template from GitHub. |
If not specified, sensible defaults are provided.
Reveal.js Options
Various options can be configured for Reveal.js. Although these can be set as attributes directly, it is far better to set them on the task as advantage can be taken of Gradle task caching and file resolving.
asciidoctorRevealJs {
revealjsOptions { (1)
controls = true
}
}
1 | Use revealjsOptions block for configuration with any of the below options. |
autoslideInterval |
Delay in milliseconds between automatically proceeding to the next slide.
Disabled when set to |
autoSlideStoppable |
Stop auto-sliding after user input Type is boolean. |
backgroundTransition |
Transition style for full page slide backgrounds..
Can be a |
controls |
Display controls in the bottom right corner. Type is boolean. |
customThemeLocation |
A custom theme that is not in the template. Can be anything convertible to a file or URI. |
hideAddressBarOnMobile |
Hides the address bar on mobile devices. Type is boolean. |
flagEmbedded |
Flags if the presentation is running in an embedded mode ( contained within a limited portion of the screen ). Type is boolean. |
fragments |
Use fragments globally. Type is boolean. |
highlightJsThemeLocation |
Highlight.js theme location. Can be anything convertible to a file or URI. |
keyboardShortcuts |
Enable keyboard shortcuts for navigation. Type is boolean. |
loop |
Loop the presentation.. Type is boolean. |
mouseWheel |
Enable slide navigation via mouse wheel. Type is boolean. |
overviewMode |
Enable the slide overview mode. Type is boolean. |
parallaxBackgroundImageLocation |
Parallax background image. Can be anything convertible to a file or URI. |
parallaxBackgroundSize |
Parallax background size. Accepts any CSS syntax. Can be anything convertible to a string. |
previewLinks |
Opens links in an iframe preview overlay. Type is boolean. |
processBar |
Display a presentation progress bar. Type is boolean. |
pushToHistory |
Push each slide change to the browser history. Type is boolean. |
righttoLeft |
Change the presentation direction to be RTL. Type is boolean. |
slideNumber |
Display the slide number of the current slide.
Can be a |
touchMode |
Enables touch navigation on devices with touch input. Type is boolean. |
transition |
Slide transition mode.
Can be a |
transitionSpeed |
Slide transition speed.
Can be a |
verticalCenter |
Vertical centering of slides. Type is boolean. |
viewDistance |
Number of slides away from the current that are visible. Type is integer. |
Using AsciidoctorJ Diagram
The new plugins have built-in support for asciidoctorj-diagram
. Simply add the following to the project or task extension and
diagramming will be available. If it is not set the asciidoctorj-diagram
JAR will not be added to the classpath.
asciidoctorj {
modules {
diagram.use() (1)
diagram.version '1.5.16' (2)
}
}
1 | Enables diagram usage with whatever the default version of asciidoctorj-diagram is. |
2 | Enables usages, but set a specific version rather than the default suggested by the plugin. |
With this enhancement, there is also no longer a need to add requires 'asciidoctor-diagram'
.
If you using OpenJDK 9/10 on MacOS you might find an error such as below |
Caused by: java.lang.UnsatisfiedLinkError: /path/to/openjdk10/lib/libfontmanager.dylib: dlopen(/path/to/openjdk10/lib/libfontmanager.dylib, 1): Library not loaded: /Users/jenkins/workspace/openjdk10_build_x86-64_macos/openjdk/installedfreetype/lib/libfreetype.6.dylib Referenced from: /path/to/openjdk10/lib/libfontmanager.dylib Reason: image not found
The solution is to install freetype
via HomeBrew or MacPorts. You might also need to do something (ridiculous) such as
$ sudo mkdir -p /Users/jenkins/workspace/openjdk10_build_x86-64_macos/openjdk/installedfreetype
$ sudo ln -s /opt/local/lib /Users/jenkins/workspace/openjdk10_build_x86-64_macos/openjdk/installedfreetype/lib (1)
1 | opt/local/lib is the location for MacPorts. Change it accordingly for HomeBrew. |
Ruby GEM support
GEM support is simplified via the org.asciidoctor.jvm.gems
plugin.
plugins {
id 'org.asciidoctor.jvm.gems' version '4.0.2'
}
repositories {
ruby {
gems() (1)
}
}
dependencies {
asciidoctorGems 'rubygems:asciidoctor-revealjs:1.1.3' (2)
}
asciidoctorj {
requires 'asciidoctor-revealjs' (3)
}
1 | Always specify a GEM proxy. In this case use the internal proxy to https://rubygems.org. |
2 | Specify GEMs as per usual. |
3 | Add the GEM to the project-wide (or task-specific) list of requires . |
plugins {
id("org.asciidoctor.jvm.gems") version "4.0.2"
}
Adding Custom Extensions
Starting with version 1.5.0 you were able to write your own Asciidoctor extensions in Groovy, or any other JVM language for that matter. Now with the 2.0.0 you have even more flexibility in that extensions can be applied on a per task basis on globally. There are several options available 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.
configurations {
asciidoctorExt
}
dependencies {
asciidoctorExt 'com.acme:asciidoctor-extensions:x.y.z'
}
asciidoctor {
configurations 'asciidoctorExt'
}
val asciidoctorExt by configurations.creating
dependencies {
asciidoctorExt("com.acme:asciidoctor-extensions:x.y.z")
}
tasks.withType<AsciidoctorTask> {
configurations("asciidoctorExt")
}
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:
plugins {
id 'org.asciidoctor.jvm.convert' version '4.0.2'
}
repositories {
jcenter()
}
configurations {
asciidoctorExtensions
}
dependencies {
asciidoctorExtensions project(':extension')
}
asciidoctor {
configurations 'asciidoctorExtensions'
}
Alternatively you can add the project to the extension directly
plugins {
id 'org.asciidoctor.jvm.convert' version '4.0.2'
}
asciidoctorj {
docExtensions project(':extension')
}
In the less-common case where extension is not supplied via the default configuration, the latter shortcut will not work, and you will need to use the longer method described above.
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 docExtensions
element.
asciidoctorj {
docExtensions {
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.
asciidoctorj {
docExtensions 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, [:])
}
Working with Asciidoctor.js instead
Instead of AsciidoctorJ, Asciidoctor.js can be used as a rendering engine as from 3.0.
The configuration follows much the same as for AsciidoctorJ, but will a couple of differences.
-
Only HTML is supported out of the box
-
The configurating extension is called
asciidoctorjs
and is available at both task and project level. -
Docbook must be enabled via
asciidoctorjs.modules.docbook.use()
. -
The implementation runs node.js under the hood, but the user does not have to install anything. The plugin suite takes care of everything.
-
Additional NPM modules can be added via
asciidoctorj.require
.
The Asciidoctor Editor Config Plugin
plugins {
id 'org.asciidoctor.editorconfig' version '4.0.2'
}
plugins {
id("org.asciidoctor.editorconfig") version "4.0.2"
}
Writes an .asciidoctorconfig
file so that supporting IDEs can render Asciidoctor-based documentation correctly.
Adding attributes
asciidoctorEditorConfig {
attributes foo1: 'bar1', foo2: 'bar2' (1)
additionalAttributes asciidoctorj (2)
additionalAttributes 'src/docs/asciidoc/attributes.adoc' (3)
}
1 | Adds predefined attributes. These attributes are added first to the generated file. |
2 | Adds all attributes defined on the project extension to the generated file. These attributes are added after the predefined attributes. |
3 | Appends the context of the specified file to the generated file. Context such as this is added last. This method also allows you to define a number of attributes in your source directory and include them in your main Asciidoc file as well as send them to .asciidoctorconfig . |
Changing the output directory
asciidoctorEditorConfig {
destinationDir = 'docs'
}
Extra content for HTML & Docbook backends
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 in your source directory i.e. 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:
asciidoctorj { (1)
attribute 'docinfo1', ''
}
1 | Substitute asciidoctorjs if you are using the Asciidoctor.js engine. |
See Asciidoctor User Manual for more information on docinfo
and friends.
Upgrading From Older Versions of Asciidoctor
If you are still on a 1.5/1.6 version of the plugin, upgrade to the latest 2.x version first. |
If you are on 2.x version, upgrade to the latest 2.x first and ensure that you have corrected all of the deprecation warnings.
If you have AsciidoctorJ binary extensions you’ll need to recompile them against AsciidoctorJ v2.0+ in order to use them with the v.3x version of the plugins.
Old name |
New name |
Substituable |
Usage |
|
|
No |
The Gradle project directory which is running the Asciidoctor task. |
|
|
No |
The rootproject directory in a multi-project build. |
|
|
Yes |
The name of the current Gradle subproject. (Or the root project in case of a single project). |
|
|
Yes |
The project/artifact group if it is defined. |
|
|
Yes |
The project version if it is defined. |
- |
|
No |
The relative path from the parent of the current document that is being processed to the source document root. It is calcluated as moving from the current document towards the root. For instance |
Substitutable attributes means that the build script author can change those attributes by setting them explicitly.
Asciidoctor compatibility tasks
The Asciidoctor compatibility task has been removed. You need to use the Asciidoctor task from org.asciidoctor.jvm.convert
instead.
GEMs
If you used external GEMs via the JRuby Gradle plugin, you should switch over to using org.asciidoctor.jvm.gems
instead. You should also use the asciidoctorGems
configuration rather than the gems
configuration. Tasks should not depend on JRubyPrepare
, but on AsciidoctorGemsPrepare
instead.
If you have the following in your build
plugins {
id 'org.asciidoctor.jvm.gems' version '2.4.1'
id 'com.github.jruby-gradle.base' version '1.7.0'
}
repositories {
rubygems('https://rubygems.org')
}
then change it to
plugins {
id 'org.asciidoctor.jvm.gems' version '4.0.2'
}
repositories {
ruby.gems()
}
Reveal.js
Follows the same guidelines as for GEMS above.
Configurations
The asciidoctor
configuration is no longer available. If you used that before to make artifacts available on the classpath you should use the configurations
method on the task to add them. If you used it to manipulate versions of AsciidoctorJ and JRuby then you should rather use the explicit versions settings on asciidoctorj
.
Multiple Asciidoctor tasks
If you have more than one Asciidoctor task, decide which options
, attributes
and requires
should go in the asciidoctorj
global project extension block and which should be customised within the tasks asciidoctor
extension block.
Importantly, you probably did import org.asciidoctor.gradle.AsciidoctorTask
. You will need to change that to import org.asciidoctor.gradle.jvm.AsciidoctorTask
.
Extensions
Extensions on the Gradle classpath are no longer detected. You need to declare them explicitly. This includes any extensions created in buildSrc
.
Appendix A: Tips & Tricks
Issues with plugins that modify project.version
Plugins such as Nebula Release and Reckon modify project.version
with a non-serialisable object. This breaks the build.
The safest workaround is to set the revnumber
attribute to a delayed evaluation of project.version
in your build:
asciidoctorj {
attributes revnumber : { project.version.toString() }
}
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'
}
}
Using Pygments source highlighter
You need to have Python 2.x installed on a system or in a container for Pygments to work. |
plugins {
id 'org.asciidoctor.jvm.pdf' version '4.0.2'
id 'org.asciidoctor.jvm.gems' version '4.0.2'
}
repositories {
jcenter()
ruby.gems()
}
dependencies {
asciidoctorGems 'rubygems:pygments:1.2.1'
}
asciidoctorPdf {
dependsOn asciidoctorGemsPrepare
sourceDir 'docs'
asciidoctorj {
requires 'pygments'
attributes 'source-highlighter' : 'pygments'
}
}
Appendix B: Known Issues
These are the main ones we know about:
-
EPUB3 + KF8 in one task. Both formats in one task is currently failing. The exact failure message depends on which order (KF8+EPUB3 or EPUB3+KF8) the conversion takes place in.
-
KF8 conversions fails under Windows. (Related to AsciidoctorJ #659 & JRuby #4943.
-
Does not work with JDK9 (but does with JDK10).
-
DeckTape export to JPG/PNG does not work on Windows (issues-asciidoctorj}[AsciidoctorJ #381] & Decktape #181).
Appendix C: Development
The master branch represents the code for the latest 2.x release of these plugins. Development for for 2.x is against the development-2.0 branch. PRs are preferably taking against that branch. The 1.5.x & 1.6.x series of the plugin is now in maintenance only mode. PRs for these should be raised against the maintenance-1.5 and maintenance-1.6branch.
|