You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Depending on your needs, there are two different kinds of plugins available. PThis document provides a brief description of each, along with links to addtional information.
instance plugins: plugins that are used to add features and functionality to the app instance.
pipeline plugins: plugins that are used to transform vinyl files in a stream.
Instance plugins
Used to add features and functionality to the application instance (or app).
Type: Function
Method: .use
Usage: Plugin functions are invoked by the .use method and take the current application instance, or app, as the first argument.
Example
// --- my-plugin.js ---functionmyPlugin(app){// do stuff to `app`app.doubleStuff=function(num){returnnum*2;};}// --- index.js ---var{%= name %}=require('{%= name %}');varapp={%= name %}();app.use(require('./my-plugin'));varnum=app.doubleStuff(5);console.log(num);//=> 10
Pipeline plugins
Used to transform [vinyl][] files in a stream. All [gulp][] plugins are pipeline plugins.
Type: Stream
Method: .pipe
Usage: Pipeline plugins are registered with .pipe and are used on vinyl file objects in a stream.
Example
This example requires the [base-fs][] plugin (a wrapper for [vinyl-fs][], install with $ npm i base-fs):
varbase=require('base');varvfs=require('base-fs');// any gulp plugin can be usedvargulpPlugin=require('fictitious-gulp-plugin');app.src('foo.hbs').pipe(gulpPlugin())
Special note
If you're using [templates][] (or any application that inherits templates, like [assemble][] or [verb][]), all views are vinyl files (e.g. view is an instance of Vinyl).
By design, plugins are pretty simple to create and use in [base][]. This keeps application logic "light" and plugins as generic as possible.
In other words, we want to encourage plugins to keep any base-specific code to an absolute minimum. You should be able to write plain JavaScript, or use any npm module in your plugin.
Making plugins smarter
There are times when "generic" isn't good enough. In advanced use cases, it's nice to have greater control over how and when plugins are invoked.
This goal can be accomplished using the [base-plugins][] plugin, which adds functionality and enhancements to existing features for managing plugins.
Pit stop
Before we review these features, if you'd like to be able to follow along and run the examples in this document, you'll first need to install and register the [base-plugins][] plugin.
All of the following examples will assume the previous code has already been defined.
With that out of the way, let's get started!
Smart plugins
Adding [base-plugins][] to your application will enable the following features:
[.fns][] - used for storing functions returned by plugins
[.run][] - used for running plugins stored on the fns array
[.use][] - the use method is updated to take addtional arguments
Let's go through each in more detail.
.fns
Type:array
Description
If a plugin returns a function after being invoked by .use, the function is pushed onto a fns array (on app.fns), allowing the function to be called later by the .run method.
Example
// todo
.run
Type:function
Description
The .run method takes an object as its only argument and, when called, iterates over the fns array and calls each function in the array on the given object. Without [base-plugins][], plugins are only run once when the .use method is called, that's it. End of story.
Example
// todo
Note that the [base-plugins][] plugin must be the first plugin registered on your base application..
Instance plugins
Instance plugins are functions that are immediately invoked by the .use method.
Example
This is all you need to create an instance plugin:
vartemplates=require('{%= name %}');varapp=templatse();// create a pluginfunctionmyPlugin(app){// do stuff to "app"}// use the pluginapp.use(myPlugin);
app, collection, or view
Additionally, view collections and views
app.use(), collection.use() or view.use() methods.
Example instance plugin
var{%= name %}=require('{%= name %}');varapp={%= name %}();app.use(function(app){// do stuff to app ({%= name %} instance, also exposed as `this)});
Smart plugins
A "smart" plugin is an instance plugin that automatically registers itself on the correct instance (app, collection or view).
To make your plugin "smart", just check for the instance type and return the plugin function if the condition is not met.
When a plugin returns a function, the function is pushed onto an array.
add the following:
varisValid=require('is-valid-app');// by default `isValid` will only register plugins on `app`module.exports=function(app){if(!isValid(app,'my-plugin'))return;// do plugin stuff};
That's it. The is-valid-app plugin returns true if both of the following conditions are met:
app is an instance of Templates
the my-plugin plugin is not already registered.
If my-plugin is not already registered, isValid will automatically register the plugin it the first time it's called. Thus, the next time the check is done, isValid will return false (preventing the plugin from being registered twice).
Collection plugins
Collections themselves are like mini-application instances, and collection plugins are registered and used the same way as instance plugins, with the .use() method, but on a specific collection. Collection plugins are called immediately upon instantiation of the collection.
Example collection plugin
var{%= name %}=require('{%= name %}');varapp={%= name %}();// register a plugin to be used on all collectionsapp.use(function(app){// do stuff to app or `this` (the {%= name %} instance)// return a function to be use used as a collection pluginreturnfunction(collection){// do stuff to `collection`};});
The app.create() method (used for creating custom collections) returns the collection instance. So collection plugins can be chained from create as well.
app.use(function(){returnfunction(collection){// do stuff to (every) `collection`}});app.create('pages').use(function(pages){// do stuff to `pages` collection});app.create('posts').use(function(posts){// do stuff to `posts` collection});
Example view plugin
var{%= name %}=require('{%= name %}');varapp={%= name %}();// register a plugin to be used on all views, from all collectionsapp.use(function(app){returnfunction(collection){// return a function from a collection plugin to be used// as a view pluginreturnfunction(view){// do stuff to `view`};};});
Register view plugins on specific collections
app.use(function(app){// do stuff to `app`returnfunction(collection){// do stuff to (every) `collection`returnfunction(view){// do stuff to (every) `view`};};});app.create('pages').use(function(pages){returnfunction(page){// do stuff to `page`};});app.create('posts').use(function(posts){returnfunction(post){// do something to `post`};});
Use cases for collection/view plugins
Here are just a few examples
permalinks: You might have a permalink plugin that modifies the dest path a particular way for blog posts, and a different way for pages. You could register the same plugin with both collections, just using different settings/options. Also, you could implement this functionality at the view level or collection level, depending on how granular your plugin needs to be.
pagination
groups and lists
sorting
(this is for the templates docs, but it will help explain how plugins work in base. you obviously already know a lot about plugins, so this is for anyone who might find it useful)
Plugins
Overview of how Templates plugins work
App
The following example shows a plugin that will be invoked by the .use method. Example: app.use(plugin). When invoked, the plugin function is passed the application instance (app) as its only argument.
The plugin stops there and will not be called again, unless the plugin returns a function. If a function is returned it will be pushed onto the app.fns array and then called on each collection that is created using the app.create, app.collection, or app.list methods.
In the next example, a function is returned from the plugin so that it can be called again later.
Collection
The plugin stops there and will not be called again, unless the plugin returns a function. If a function is returned it will be pushed onto the collection.fns array and then called on each view that is added to the collection.
In the next example, we'll return a function inside the collection plugin, so that it can be called again later.
View
End of the line...
Short-circuit: "smart plugins"
Don't like all the function nesting? Want to register your plugin with app but only have it run on specific objects? No problem, just short-circuit the plugin!
Every class has a boolean .is* property that is useful for checking the instance name. For example, the Templates class has an isTemplates property, view collections have isViews, and views have isView. (all "apps", like Templates, Assemble, Generate, Verb, etc. also have isApp as a convenience).
To make your plugins "smarter" and eliminate the nesting, try the following: