Skip to content

Latest commit

 

History

History
151 lines (114 loc) · 3.49 KB

File metadata and controls

151 lines (114 loc) · 3.49 KB

Plugins

Plugins can be used to modify the config object and it's properties at each "stage" of normalization or transformation.

Why use plugins?

The advantage of using plugins is that any transformations you might need to do to the returned object can be performed without having to recurse over the object again. As a result, it could be faster than other options, and it also provides an easy way to modify specific properties.

How do plugins work?

A plugin is a function that takes config as its only parameter.

Plugins must be registered before the configuration is expanded, which means that instead of passing the config object to the constructor, you'll need to:

  1. create an instance by doing var config = new Config()
  2. add your plugins
  3. call the expand method on the object you want to expand after plugins are registered.

Example

var config = new Config({cwd: 'foo'});

config
  .use(foo)
  .use(bar)
  .use(baz);

config.expand({
  site: {
    src: '*.js',
    dest: ''
  }
});

Working example

var config = new Files();
config.use(function(obj) {
  obj.foo = 'bar';
});
console.log(config.expand({src: '*.js'}));

Results in an object that looks something like:

{
  options: {},
  foo: 'bar', //<= our added property
  files: [{
    options: {},
    src: ['examples.js', 'gulpfile.js', 'index.js', 'utils.js'],
    dest: '' }
  ]
}

Nodes

It's also possible to modify individual files nodes as they're created on the files array. To do so, simply return a function in the plugin and it will be called on each node.

Examples

var config = new Files();
function updateNode(config) {
  config.foo = 'bar';

  return function fn(node) {
    if (!node.filesNode) return fn;
    // return the plugin function if it's not a filesNode
    // this way we know with certainty that `node`
    // will be a filesNode
    node.options.one = 'two';
    node.dest = 'baz/';
    node.abc = 'xyz';
  };
}
config.use(updateNode);
console.log(config.expand({src: '*.js'}));

Results in an object that looks something like:

{
  options: {},
  foo: 'bar', //<= our added `config` property
  files: [{
    options: { one: 'two' },
    src: ['examples.js', 'gulpfile.js', 'index.js', 'utils.js'],
    dest: 'baz/',
    abc: 'xyz' }
  ]
}

Additionally, you can either modify the node before it's normalized or after, by checking for the rawNode property or filesNode respectively.

Writing plugins

Plugins are just functions where the only parameter exposed is the current "context", which is either the configuration object you passed in, or some property on that object - before or after it's transformed.

Examples

In the following plugin, config is the target instance:

target.use(function(config) {
  config.foo = 'bar';
});
console.log(target.foo);
//=> 'bar'

To have the plugin called in a "child" context, like for iterating over files nodes as they're expanded, just return the plugin function until you get the node you want:

target.use(function fn(config) {
  if (!config.node) return fn;
  console.log(config);
});

Contexts

To see all available contexts, just do the following:

target.use(function fn(config) {
  console.log('-----', config._name, '----');
  console.log(config);
  console.log('---------------------------');
  return fn;
});

This is a list of all possible contexts:

  • config
    • task
      • target
        • normalized
          • rawNode
          • filesNode
        • expanded