-
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-mypluginconvention. 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
keywordsproperty of your package.json, includegobble-plugin