-
Notifications
You must be signed in to change notification settings - Fork 20
Writing plugins
There are two types of Gobble plugin - directory transformers and file transformers. When you're writing a build definition (a.k.a. a [gobblefile](How to write a gobblefile)), you use both types of plugin the same way - with the node.transform()
method:
var gobble = require( 'gobble' );
var sourcenode = gobble( 'path/to/files' );
module.exports = sourcenode.transform( myplugin, options );
In both cases, the plugin is simply a function. Gobble distinguishes between directory transformers and file transformers based on how many arguments the function takes.
Directory transformers are those which take a set of files and produce one or more output files. The gobble-concat plugin is one example - it takes a folder of files and concatenates them into a single output file.
The function's signature is as illustrated here:
function myplugin ( inputdir, outputdir, options[, callback] ) {
/*
- `inputdir` is the path to a directory containing the
output from the input node (which is `sourceNode`
in this example)
- `outputdir` is the path to a directory that this plugin
must write files to (i.e. the `inputdir` for any
subsequent transformation)
- `options` is an object. it is shallow-cloned from the
user-supplied options object (if none is supplied, it
will be created as `{}`), so you can modify it safely
- `callback` must be called once the files have been
written. If something goes wrong, call it with an
error object. You can, if you prefer, return a Promise
rather than using a callback
*/
}
The function's name is used by Gobble to name temporary folders, for easier debugging. For that reason it's better to do...
function myplugin (...) {...}
...than...
var myplugin = function (...) {...}
...because the latter is an anonymous (rather than named) function.
If your plugin transforms files on a one-to-one basis (e.g. compiling templates), rather than transforming a directory on an N-to-N basis, you can use a simpler alternative syntax:
function myplugin ( input, options ) {
/*
- `input` is the contents of an individual file
- `options` is shallow-cloned from the user-supplied
options (plus the defaults, if specified. User
options override defaults)
*/
return output;
}
As well as being easier to write, this has performance advantages - Gobble is able to cache the result of successful transformations and only re-run them for the individual files that have changed.
Optionally, you can specify default options, which can include accept
and ext
properties:
myplugin.defaults = {
accept: [ '.abc', '.def' ], // can be string or array
ext: '.xyz'
};
In this example, the transformation would be applied to foo.abc
and bar.def
, which would become foo.xyz
and bar.xyz
respectively. Other files, such as baz.ghi
, would be passed through un-transformed. This is useful for doing this sort of thing:
if ( gobble.env() === 'production' ) {
node = node
.transform( 'uglifyjs' )
.transform( 'htmlmin' )
.transform( 'imagemin' );
}
With directory transformers, sourcemaps are easy - just write the .map
file to outputdir
and you're good to go.
With file transformers, you're not interacting with the filesystem, so there's no chance to write a .map
file. Instead, return an object from the transformer, with code
and map
properties, rather than a string. The gobble-coffee plugin is an example:
function coffee ( code, options ) {
var compiled;
options.sourceMap = true;
compiled = require( 'coffee-script' ).compile( code, options );
return {
code: compiled.js,
map: compiled.v3SourceMap
};
}
The map
property should be an object that meets the sourcemap spec, or a JSON representation thereof.
The file
, sources
and sourcesContent
properties of the sourcemap will be filled in by Gobble. Don't worry about being able to ingest sourcemaps from previous transformations - the sourcemaps can be combined later (e.g. with gobble-sorcery).
If you create a plugin that you think others would benefit from, please publish it to npm!
- The package name should follow the
gobble-myplugin
convention. This allows people to invoke it withnode.transform('myplugin',{...})
- Remember to include a README, with installation and basic usage instructions. See gobble-concat for an example README
- In the
keywords
property of your package.json, includegobble-plugin