Define an Extension

An Antora pipeline extension is a JavaScript function named register that is invoked by Antora after the playbook is built. This function then registers event listeners that listen for zero or more Antora pipeline events. The event listeners hook into the execution of the Antora site generator and other components to do the bulk of the work of the extension.

To define an extension, start by creating a new JavaScript file (herein: script). We’ll name this extension my-extension.js. In this file, define a function named register and configure it to be exported so it can be called by Antora.

Example 1. my-extension.js
'use strict'

module.exports.register = () => {
}

You can also separate the function definition from the export statement, if you prefer that style.

Example 2. my-extension.js
'use strict'

const register = () => {
}

module.exports = { register }

It’s good practice to start your extension file (a JavaScript module) with the statement 'use strict'. This statement enables strict mode across all versions of Node.js. Strict mode activates a restricted variant of JavaScript that catches common programming errors. We’ll exclude it from the remaining examples in this area of the documentation, but assume it’s present.

This example defines the register function using the arrow function syntax. You can also use the more formal function () {} syntax.

Put the script in your playbook repository. Later, you can publish it to a package repository such as npmjs.com to share it between sites or site branches.

So far, our extension doesn’t actually do anything. Since the register method is a listener, itself, you can use it as an opportunity to perform an action immediately after the playbook is built. Let’s say hi.

Example 3. my-extension.js
module.exports.register = () => {
  console.log('Antora is running!')
}

While that’s a fun trick, it’s not really what we’re after. What we want is to tie deeper into Antora’s pipeline and do some work, perhaps even modify the content Antora is processing. For that, we need to grab the Pipeline object. The first positional parameter of the register function is pipeline, which is how the extension gets a reference to the Pipeline object.

Example 4. my-extension.js
module.exports.register = (pipeline) => {
  pipeline.on(...)
}

The Pipeline object is what you use to register event listeners. Before we get there, let’s look at the second positional parameter.

The second positional parameter of the register function is an object of variables, which includes the playbook and extension config. You should use object destructuring to pick individual variables out of this object. All event listeners can retrieve the playbook, but it could come in handy when registering listeners. Here’s how to access it from the register function:

Example 5. my-extension.js
module.exports.register = (pipeline, { playbook }) => {
  console.log(`Antora is building the ${playbook.site.title}.`)
}

Now, let’s get into registering our extension and adding a listener.