-
Notifications
You must be signed in to change notification settings - Fork 428
Plugins
Plugins extend ReLaXed with new features, providing Pug commands or Javascript or styling frameworks to your documents, or post-processing filters. This page describes how to use and how to write plugins.
This section explains how to activate a plugin. It does not cover the plugins which are activated by default in ReLaXed, since these can be considered "features" of relaxed.
To activate plugins, create a config.yml
in the same folder as your master document, with the following content:
plugins:
- some-plugin-name
- some-other-plugin
Some plugin may accept optional parameters, at which case you must add :
after the plugin name, and then provide parameter values:
plugins:
- some-plugin-name:
parameter-one: 90
parameter-two: Jean-Paul
For instance, here is how you activate the svg
plugin, and specify that when optimizing pictures it should use a compression quality of 90:
plugins:
- svg:
jpeg-quality: 90
Note that when running in an interactive session, the plugins are reloaded automatically when the config.yml
is updated.
ReLaXed has a few plugins "out of the box", such as mathjax
for mathematical equations (see this section on how to use it). Note that some of these plugins may not be built-in in the future.
External ReLaXed plugins are released on NPM under names such as relaxed-pluginName
, for instance relaxed-svg
. They can be installed via
npm install -g relaxed-pluginName
This provides the pluginName
plugin which you can use in your config.yml
file:
plugins:
- pluginName
Note that plugins do not have to be installed via an online NPM repository, you can also have a plugin on your computer, installed globally using npm link
(this isn't tested on every platform though, please open an issue if this doesn't work for you).
It is also possible to define a custom plugin as a standalone file for use in just one or two projects. Just have a file with a .plugin.js
extension in the same directory as your master document. e.g. say-my-name.plugin.js
and activate it in config.yml
:
plugins:
- say-my-name:
name: Heisenberg
For illustration sake, assume that the say-my-name.plugin.js
contains the following miminal plugin definition, which adds the variable name
to the Pug environment.
exports.constructor = async function (pluginDefinition) {
return {
pugHeaders: [`- var name = "${pluginDefinition.name}"`]
}
}
Then your master Pug document can use this variable
p Say my name ! #{name} // will print "Heisenberg"
the next section explains every possible actions offered by plugins.
A ReLaXed Plugin is a Javascript module exporting a (possibly async) function constructor(parameters) => hooks
, where the "hooks" are lists of routines that will be applied at various times of the document creation.
So the master file of your plugin will look something like this:
exports.constructor = async function (parameters) {
var hooks = {
watchers: [...],
pugHeaders: [...],
pugFilters: [...],
htmlHead: [...],
htmlModifiers: [...],
pageModifiers: [...],
postPDF: [...]
}
return hooks
}
See section Hooks below for a detailed description of the different kinds of hooks.
As explained in the Using plugins section, a plugin can be either used by , or published online with NPM. To release the plugin on NPM, the package name must be prefixed by relaxed-
, e.g. relaxed-pluginName
.
If you need inspiration, have a look at:
- The ReLaXed built-in plugins, which are simple plugins like any other, except that they come packaged with ReLaXed.
- The
relaxed-svg
plugin.
This section describes in detail all the different categories of hooks. For a summary of all hooks, see the schema at the end of this section.
A plugin can omit any category of hooks, for instance a plugin providing only some pug headers will look like this:
exports.constructor = async function (pluginDefinition) {
return { pugHeaders: ["header 1", "header 2"] }
}
For each category, a plugin can provide either a single hook or a list of hooks, so you can write for instance
pugHeaders: ["header 1", "header 2"]
\\ or
pugHeaders: "header"
Watchers are not involved in the creation of the final PDF, but are instead meant to trigger actions when files with special extensions are modified, in the watched directory.
A common usage of watchers
is the interactive creation of assets (images, tables, etc.). For instance the chartjs
watches files with the .chart.js
extension. Every time a file with such extension is read, the plugin reads the javascript content (which defines a chart) and creates a PNG image from it.
A plugin's list of watchers is defined as follows:
watchers: [
{
extensions: ['.ext', '.other.ext', etc.],
handler: async function (filepath, page)
},
{
extensions: ['.ext', '.other.ext', etc.],
handler: async function (filepath, page)
},
...
]
Each watcher reacts to the provided extensions
by calling a handler
function, with parameters filepath
(the file that was just modified) and page
(a controllable Puppeteer page, which can be used to render an asset with Chromium).
Pug headers are strings of Pug code that will be added at the top of your master document's Pug before rendering to HTML. These are useful to define variables or Pug mixins (which can be seen as "macros". "commands" in LaTeX).
A typical plugin providing headers could look like this (we assume there is a my_mixins.pug
document in the plugin's directory):
const fs = require('fs')
const path = require('path')
exports.constructor = async function (params) {
return {
pugHeaders: [
"- var myParameter = 834",
fs.readFileSync(path.join(__dirname, 'my_mixins.pug'), 'utf8')
]
}
}
A list of text-transforming functions that will be available in Pug as filters (see here for more infos on Pug filters).
For instance if the plugin provide these filters
pugFilters: {
uppercase: function (text, options) { return text.toUpperCase }
"add-suffix": function (text, options) { return text + options.suffix }
}
Then your Pug code can look like this:
p I am a normal paragraph
p:uppercase
I will be an upper-case paragraph
p
:add-suffix(suffix=" I will be added at the end")
I am some text and a suffix will be added to me.
Two important remarks:
- These functions cannot be asynchronous.
- The options (like
suffix
above) must be constants, you cannot write:add-suffix(suffix=someVariable)
. If you need non-constant options, use a Pug mixin instead of a filter.
HTML elements to be added to the head
section of the HTML page that will be rendered. This can be useful to add metadata, styles, javascript scripts to the page. for instance
htmlHead: [
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/katex.min.css"/>',
'<script src="./myscript.js"/>',
]
Functions (synchronous or asynchronous) which will modify the final HTML, just before it is sent to Chromium: they will be executed in the order given.
htmlModifiers: [
function (html) { ... return modifiedHtml},
async function (html) = {... return modifiedHtml},
...
]
to be written
to be written