---
title: Asciidoctor Gradle Plugin Suite
updated: 2022-04-20 20:47:03Z
created: 2022-04-20 20:47:03Z
tags:
  - IT
  - Development/Gradle
  - Development/Gradle/Plugin
  - Development/Asciidoctor
source: >-
  https://asciidoctor.github.io/asciidoctor-gradle-plugin/development-3.x/user-guide/
---

The Asciidoctor Gradle Plugin Suite is the official means of using [Asciidoctor](http://asciidoctor.org/) to convert all your [AsciiDoc](http://asciidoc.org/) documentation using [Gradle](http://gradle.org/).

This started as a port of the [Asciidoctor Maven Plugin](https://github.com/asciidoctor/asciidoctor-maven-plugin) project founded by [Jason Porter](https://github.com/LightGuard) and relies on [AsciidoctorJ](https://github.com/asciidoctor/asciidoctorj) which was founded by [Alex Soto](https://github.com/lordofthejars). 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 8.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

build.gradle

```groovy
plugins {
    id 'org.asciidoctor.jvm.convert' version '3.1.0'
}
```

build.gradle.kts

```kotlin
plugins {
    id("org.asciidoctor.jvm.convert") version "3.1.0"
}
```

## Task Configuration

All Asciidoctor tasks will have the following methods and properties:

Properties and methods common all AsciidoctorJ tasks

|     |     |
| --- | --- |
| 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 `asciidoctorj` extension can also be configured here. |
| attributes | A shortcut for `asciidoctorj.attributes` and `asciidoctorjs.attributes`. |
| 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. |
| languages | Invoke source language support but specifying one or more languages. |
| inProcess | Specifies whether Asciidoctor conversions should be run in-process or out-of-process. Default: `true` (in-process). |
| logDocuments | Specifies if documents being processed should be logged on console. Type: boolean. Default: `false`. |
| options | A shortcut to\`asciidoctorj.options\`. |
| outputDir | where generated docs go. Use either `outputDir path`, `setOutputDir path` or `outputDir=path` Type: File, but any object convertible with `project.file` can be passed. Default: `$buildDir/asciidoc`. |
| 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 `gemPath` and extension pollution. Default: `true` (parallel). |
| resources | specify which additional files (image etc.) must be copied to output directory using a [CopySpec](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/CopySpec.html). 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 `getDefaultSourceDocumentPattern()` as well as doctype files. |
| sourceDir | where the asciidoc sources are. Use either `sourceDir path`, `setSourceDir path` or `sourceDir=path` Type: File, but any object convertible with `project.file` can be passed. Default: `src/docs/asciidoc`. |
| sources | Specify which Asciidoctor source files to include as toplevel documents. It uses an [Ant-style PatternSet](http://www.gradle.org/docs/current/javadoc/org/gradle/api/tasks/util/PatternSet.html). |
| useIntermediateWorkDir | Use an intermediate work directory for sources ances. Some extensions such as `ditaa` will write content into the source directory. In order to keep the project source directory pristine an intermediate work directory can be used. All sources and resources will be copied there prior the executing Asciidoctor. |
| 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 `Action`. This implies `useIntermediateWorkDir`. An example of such a case is the use of `ditaa`. |

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:

Properties & methods for configuring generic `AsciidoctorTask`

|     |     |
| --- | --- |
| backends | the backends to use. Use `backends` to append. Use `setBackends` or `backends=[]` to overwrite Type: Set&lt;String&gt;, but any type can be converted to String can be used. Default: \[`html5`\]. |
| separateOutputDirs | specifies whether each backend should use a separate subfolder under `outputDir`. Default: `true` |

### 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](http://www.gradle.org/docs/current/javadoc/org/gradle/api/tasks/util/PatternSet.html).

To specify a custom output folder, use the `outputDir` method.

build.gradle
```groovy
asciidoctor {
  sourceDir  file('docs')
  sources {
    include 'toplevel.adoc', 'another.adoc', 'third.adoc'
  }
  outputDir  file('build/docs')
}
```

build.gradle.kts
```kotlin
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](http://www.gradle.org/docs/current/javadoc/org/gradle/api/file/CopySpec.html)

build.gradle
```groovy
resources {
  from('src/resources/images') {
    include 'images/**/*.png'
    exclude 'images/**/notThisOne.png'
  }

  from( "${buildDir}/downloads" ) {
    include 'deck.js/**'
  }

  into './images'
}
```

build.gradle.kts
```kotlin
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

build.gradle
```groovy
resources {
  from(sourceDir) {
    include 'images/**'
  }
}
```

In case of languages the default behaviour is

build.gradle
```groovy
resources {
  from(new File(sourceDir,"${langName}")) {
    include 'images/**'
  }
}
```

If you do not want this behaviour, then it can be turned off by doing

If you are using multiple languages and you have identical resource patterns for each languages within `sourceDir/${lang}` you need to explictly declare those on a per-language basis:

build.gradle
```groovy
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::](https://asciidoctor.org/docs/user-manual/#include-resolution) 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:

build.gradle
```groovy
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

```groovy
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

```groovy
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` and `OUT_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.

```groovy
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.

```groovy
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 `docExtensions` to add one or more extensions. Use `setDocExtensions` to replace the current set of extensions with a new set. Extensions can be any kind of object that is serialisable, although in most cases they will be strings or files. If extensions are detached dependencies, they will not be serialised, but rather will be placed on the classpath in order that AsciidoctorJ can pick them up automatically. See &lt;asciidoctorj-extensions&gt;> for more details. |
| fatalWarnings | Patterns for AsciidoctorJ log messages that should be treated as fatal errors. The list is empty be default. Use `setFatalWarnings` to clear any existing patterns or to decouple a task’s configuration from the global configuration. Use `fatalWarnings` to add more patterns. Pass `missingIncludes()` to add the common use-case of missing include files. |
| gemPaths | One or more gem installation directories (separated by the system path separator). Use `gemPaths` to append. Use `setGemPaths` or `gemPaths=['path1','path2']` to overwrite. Use `asGemPath` to obtain a path string, separated by platform-specific separator. Type: `FileCollection`, but any collection of objects convertible with `project.files` can be passed Default: empty |
| 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 `project.logger.level` is at the time of execution. |
| modules | Configuration for version of specific components and converters that can be used. See [AsciidoctorJ Modules](#asciidoctorj-modules) for which moduels are supported. |
| options | AsciidoctorJ options. Use `options` to append and `setOptions` to replace any current options with a new set. Options are evaluated as late as possible. See [Setting Options](#options) for more details. |
| requires | The set of Ruby modules to be included. Use `requires` to append. Use `setRequires` or `requires=['name']` to overwrite. Default: empty. |
| 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. |
| onConfiguration | Additional actions to be performed when the detached configuration for the AsciidoctorJ is created. |
| 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 `attributes` to append and `setAttributes` to replace any current attributes with a new set. Attribute values are lazy-evaluated to strings. See [\[attributes\]](#attributes) for more detail. |
| 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 `UNSAFE`, `SAFE`, `SERVER`, `SECURE`. Can be a number (0, 1, 10, 20), a string, or the entity name |

### Options & Attributes

The following options may be set using the extension’s `options` property

- header_footer - boolean
- template_dirs - List&lt;String&gt;
- 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.

build.gradle
```groovy
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. |

build.gradle.kts
```kotlin
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.

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](http://asciidoctor.org/docs/user-manual/#attribute-assignment-precedence) for more information.

### Versions of modules

The modules block currently supports four elements

build.gradle
```groovy
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](#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 achived in the {groovy-dsl}:

build.gradle
```groovy
asciidoctorj {
  modules {
    pdf.version '1.2.3'
  }

  modules.pdf.version '1.2.3'
}
```

build.gradle.kts
```kotlin
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.

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.base' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.base") version "3.1.0"
}
```

## The New AsciidoctorJ Plugin

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.convert' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.convert") version "3.1.0"
}
```

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

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.pdf' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.pdf") version "3.1.0"
}
```

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 set `asciidoctorj.pdfVersion` or `asciidoctorPdf.asciidoctorj.pdfVersion`.

The `AsciidoctorPdfTask` task type has the following additional methods:

|     |     |
| --- | --- |
| fontsDir | Directory for custom PDF fonts. Specify a directory in any form acceptable to `project.file`. Using this instead of directly setting the `pdf-fontsdir` attribute means that Gradle will be able to check out of date status dependent on the content of this folder. |
| theme | Name of the theme to use. Optional. When specifying a theme name it must match one registered via `pdfThemes`. |

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).

Registering a local theme

```groovy
pdfThemes {
    local 'basic', { (1)
        styleDir = file('themes/basic') (2)
        styleName = '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. |

Registering a GitHub or GitLab theme

```groovy
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 speciified 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 downlaod the repository once.

Kotlin users can use equivalent `Action`-based configurations.

## The AsciidoctorEpub Plugin

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.epub' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.epub") version "3.1.0"
}
```

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 set `asciidoctorj.epubVersion` or `asciidoctorEpub.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. Constants `EPUB3` and `KF8` are available for convenience. To override any previous set fomrats use `setEbookFormats`. To add to the existing list use `eBookFormats`. |

|     |     |
| --- | --- |
|     | KF8 formats cannot be generated under Windows at present. |

## The AsciidoctorJ Reveal.js Plugin

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.revealjs' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.revealjs") version "3.1.0"
}
```

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\]](#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:

```groovy
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.

```groovy
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 `0` (the default). This value can still be overwritten on a per-slide basis by setting a `data-autoslide` attribute on a slide. Type is integer. |
| autoSlideStoppable | Stop auto-sliding after user input Type is boolean. |
| backgroundTransition | Transition style for full page slide backgrounds.. Can be a `RevealJSOptions.Transition` or string value. |
| 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 `RevealJSOptions.SlideNumber`, a string value or a boolean. |
| touchMode | Enables touch navigation on devices with touch input. Type is boolean. |
| transition | Slide transition mode. Can be a `RevealJSOptions.Transition` or string value. |
| transitionSpeed | Slide transition speed. Can be a `RevealJSOptions.TransitionSpeed` or string value. |
| verticalCenter | Vertical centering of slides. Type is boolean. |
| viewDistance | Number of slides away from the current that are visible. Type is integer. |

## The AsciidoctorLeanpub Plugin

When applying `org.asciidoctor.jvm.leanpub` it creates a single task of type `org.asciidoctor.gradle.jvm.epub.AsciidoctorLeanTask` which is then configured to:

- Output source to "${buildDir}/docs/asciidocLeanpub"
- Set also a default version for `asciidoctor-leanpub-backend` artifact. To override set `asciidoctorj.leanpubVersion` or `asciidoctorLeanpub.asciidoctorj.leanpubVersion`.

If you use the traditional Dropbox mechanism of synchronising your writing to Dropbox you can apply the ``org.asciidoctor.jvm.leanpub.dropbox-copy' plugn which will add a `copyAsciidocToDropbox`` task which can copy your generated Leanpub content to the Dropbox folder which Leanpub has created for you.

## 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 nto be added to the classpath.

```groovy
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.

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.jvm.gems' version '3.1.0'
}

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](https://rubygems.org/). |
| **2** | Specify GEMs as per usual. |
| **3** | Add the GEM to the project-wide (or task-specific) list of `requires`. |

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.jvm.gems") version "3.1.0"
}
```

## Kindlegen plugin

build.gradle
```groovy
plugins {
    id 'org.asciidoctor.kindlegen.base' version '3.1.0'
}
```

build.gradle.kts
```kotlin
plugins {
    id("org.asciidoctor.kindlegen.base") version "3.1.0"
}
```

Producing KF* formats via the EPUB extension requires `kindlegen` to be installed. This plugin provides the capability of bootstrapping `kindlegen` on Windows, Mac & Linux without the user having to do anything.

There is a base plugin `org.asciidoctor.kindlegen.base` which just provides a `kindlegen` extension. In order to use it you will need to agree to the Amazon terms of usage. To confirm this you need to configure

```groovy
kindlegen {
  agreeToTermsOfUse = true
}
```

If you do not, then the plugin will refuse to bootstrap `kindlegen`.

|     |     |
| --- | --- |
|     | The base plugin is automatically applied by the EPUB plugin. If you only produce EPUB3 formats with the EPUB plugin you do not have to agree to the usage of `kindlegen`. |

## 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.

build.gradle
```groovy
configurations {
    asciidoctorExt
}

dependencies {
    asciidoctorExt 'com.acme:asciidoctor-extensions:x.y.z'
}

asciidoctor {
    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:

build.gradle
```groovy
plugins {
   id 'org.asciidoctor.jvm.convert' version '3.1.0'
}

repositories {
    jcenter()
}

configuration {
    asciidoctorExtensions
}

dependencies {
    asciidoctorExtensions project(':extension')
}

asciidoctor {
    configurations 'asciidoctorExtensions'
}
```

Alternatively you can add the project to the extension directly

build.gradle
```groovy
plugins {
   id 'org.asciidoctor.jvm.convert' version '3.1.0'
}

asciidoctorj {
    docExtensions project(':extension')
}
```

In the less-common case where extension is not supplied via the default configuration, he latter shortcur 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.

build.gradle
```groovy
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, [:])
        }
    }
}
```

Groovy extensions can also be included as files.

build.gradle
```groovy
asciidoctorj {
    docExtensions file('big.groovy')
}
```

big.groovy
```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`.

## 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.

src/docs/asciidoc/docinfo.html
```html
<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:

build.gradle
```groovy
asciidoctorj { (1)
    attribute 'docinfo1', ''
}
```

|     |     |
| --- | --- |
| **1** | Substitute `asciidoctorjs` if you are using the Asciidoctor.js engine. |

## 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, upgradle 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** |
| `projectdir` | `gradle-projectdir` | No  | The Gradle project directory which is running the Asciidoctor task. |
| `rootdir` | `gradle-rootdir` | No  | The rootproject directory in a multi-project build. |
| `project-name` | `gradle-project-name` | Yes | The name of the current Gradle subproject. (Or the root project in case of a single project). |
| `project-group` | `gradle-project-group` | Yes | The project/artifact group if it is defined. |
| `project-version` | `revnumber` | Yes | The project version if it is defined. |
| -   | `gradle-relative-srcdir` | 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 `src/docs/asciidoc/subdir/sample.adoc` will set this attribute to `..` if `sourceDir` == `src/docs/asciidoc`. |

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](http://jruby-gradle.github.io/), 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

```groovy
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

```groovy
plugins {
    id 'org.asciidoctor.jvm.gems' version '3.1.0'
}

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](https://github.com/nebula-plugins/nebula-release-plugin) and [Reckon](https://github.com/ajoberstar/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:

```groovy
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](https://docs.gradle.org/current/userguide/tutorial_using_tasks.html) and [17](https://docs.gradle.org/current/userguide/more_about_tasks.html) in the Gradle docs to learn about the various actions you can perform.

build.gradle
```groovy
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.

build.gradle
```groovy
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. |

```groovy
plugins {
  id 'org.asciidoctor.jvm.pdf' version '3.1.0'
  id 'org.asciidoctor.jvm.gems' version '3.1.0'
}

repositories {
    jcenter()
    ruby.gems()
}

dependencies {
  asciidoctorGems 'rubygems:pygments:1.2.1'
}

asciidoctorPdf {
  dependsOn asciidoctorGemsPrepare
  sourceDir 'docs'

  asciidoctorj {
    requires 'pygments'
    attributes 'source-highlighter' : 'pygments'
  }
}
```

### Resolving AsciidoctorJ dependencies against a specific repository

```groovy
repositories {
    maven {
        name = 'asciidoctorj'
        url = 'https://some.repo.example'
    }
}

asciidoctorj {
    onConfiguration { cfg ->
        repositories.getByName('asciidoctorj').mavenContent { descriptor ->
            descriptor.onlyForConfigurations(cfg.name)
        }
    }
}
```

## 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](https://github.com/asciidoctor/asciidoctorj/issues/659) & [JRuby #4943](https://github.com/asciidoctor/asciidoctorj/issues/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](https://github.com/astefanutti/decktape/issues)).

## 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](https://github.com/asciidoctor/asciidoctor-gradle-plugin/tree/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](https://github.com/asciidoctor/asciidoctor-gradle-plugin/tree/maintenance-1.5) and [maintenance-1.6](https://github.com/asciidoctor/asciidoctor-gradle-plugin/tree/maintenance-1.6)branch. |