/asciidoctor-gradle-plugin

A Gradle plugin that uses Asciidoctor via JRuby to process AsciiDoc source files within the project.

Primary LanguageGroovyApache License 2.0Apache-2.0

Asciidoctor Gradle Plugin

Build Status" Build Status Coverage Status Apache License 2 Download

The Asciidoctor Gradle Plugin is the official means of using Asciidoctor to render all your AsciiDoc documentation using Gradle.

This is a port of the Asciidoctor Maven Plugin project founded by @LightGuard. 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:

build.gradle
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. This task exposes a few properties as part of its configuration.

Properties
logDocuments

a boolean specifying if documents being processed should be logged on console. Type: boolean. Default: false.

separateOutputDirs

specifies whether each backend should use a separate subfolder under outputDir. Default: true

Methods
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 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 outputDir path, setOutputDir path or outputDir=path Type: File, but any object convertible with project.file can be passed. Default: $buildDir/asciidoc.

backends

the backends to use. Use backends to append. Use setBackends or backends=[] to overwrite Type: Set<String>, but any type can be converted to String can be used. Default: [html5].

gemPath

one or more gem installation directories (separated by the system path separator). Use gemPath to append. Use setGemPath or gemPath='path to overwrite. Use asGemPath to obtain a path string, separated by platform-specific separator. For backwards-compatibility, setGemPath and gePath='string' will accept a path string containing the platform-specific separator. Type: FileCollection, but any collection of objects convertible with project.files can be passed Default: empty

requires

a set of Ruby modules to be included. Use requires to append. Use setRequires or requires='name' to overwrite. Type: Set<String>. Default: empty.

options

a Map specifying different options that can be sent to Asciidoctor. Use options to append, Use setOptions or options= to overwrite.

attributes

a Map specifying various document attributes that can be sent to Asciidoctor Use attributes to append, Use setAttributes or attributes= to overwrite.

Sources

By default the plugin will search for sources under sourceDir. Sources may have any of the following extensions in order to be discovered:

  • .asciidoc

  • .adoc

  • .asc

  • .ad

To select only certain files use the sources method. This takes a closure which in turn configures an internal PatternSet

build.gradle
sources {
  include 'toplevel.adoc'
}

Source files are resolved relative to sourceDir. Source files are also not allowed to start with an underscore.

Handling additional 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

build.gradle
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}/$html5 (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
resources {
  from(sourceDir) {
    include 'images/**'
  }
}

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

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

build.gradle
asciidoctor { (1)
    outputDir "${buildDir}/docs"
    options doctype: 'book', ruby: 'erubis'

    attributes 'source-highlighter': 'coderay',
                toc                 : '',
                idprefix            : '',
                idseparator         : '-'
}
  1. 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.

src/docs/asciidoc/docinfo.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
attributes docinfo1: ''

Refer to the Asciidoctor documentation to learn more about these options and attributes.

Note

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.

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 sourceDir. Use sources { include 'name' } instead.

sourceDocumentName

an override to process a single source file. Use sources { include 'name' } instead.

backend

the backend to use. Use backends instead.

Behavior

  • The default value for sourceDir has changed from src/asciidoc to src/docs/asciidoc.

  • Files specified in sourceDocumentNames must be relative to sourceDir and fully contained in sourceDir, 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 within options are still allowed, including legacy forms.

  • Non-source files are no longer automatically copied, unless they are in the images folder and resources was never called.

  • Each backend will now write to a separate subfolder under outputDir. To have the old behaviour use separateOutputDirs = false.

Options & Attributes

build.gradle
// 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'
Important
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.

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

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

build.gradle
repositories {
    mavenLocal() // (1)
    jcenter()    // (2)
}

asciidoctorj {
    version = '1.6.0-MY_SNAPSHOT'
}
  1. resolves artifacts in your local Maven repository

  2. 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
}

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.

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
dependencies {
    asciidoctor 'com.acme:asciidoctor-extensions:x.y.z'
}

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
buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.3'
    }
}

apply plugin: 'org.asciidoctor.convert'

repositories {
    jcenter()
}

dependencies {
    asciidoctor project(':extension')
}

Inline extensions

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.

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

build.gradle
asciidoctor {
    extensions new File('big.groovy')
}
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, [:])
}

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.