Skip to content

Creating Plugins

Maximilian Franzke edited this page Nov 6, 2021 · 14 revisions
Reference Implementation

You can find the first Node plugin at https://github.com/pattern-lab/patternlab-node/tree/master/packages/plugin-tab which is well-commented and covers both frontend and backend needs. It will be used as an example throughout the rest of this page.

Backend Plugin Anatomy

Installation

To add the Tab Plugin to your project using npm type:

npm install plugin-node-tab --save

Or add it directly to your project's package.json file and run npm install

if you author your own plugin, they need to be on npm or locally npm linked

postinstall instructions are fed to patternlab-core to look for any plugins installed within node_modules/

  //determine if any plugins are already installed
  var plugin_manager = new pm(config, configPath);
  var foundPlugins = plugin_manager.detect_plugins();

  if (foundPlugins && foundPlugins.length > 0) {

    for (var i = 0; i < foundPlugins.length; i++) {
      console.log('Found plugin', foundPlugins[i]);
      plugin_manager.install_plugin(foundPlugins[i]);
    }
  }

"Installing" ultimately adds an entry to the patternlab-config.json file, which will look like this:

{
...
"plugin-node-tab": false
...
}

This config entry is also what let's us disable the plugin if we want to momentarily turn it off (by deleting this entry).

Initialization

Plugins are then loaded similarly to installation during patternlab.js startup:

/**
 * Finds and calls the main method of any found plugins.
 * @param patternlab - global data store
 */
function initializePlugins(patternlab) {
  var plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json'));
  var foundPlugins = plugin_manager.detect_plugins();

  if (foundPlugins && foundPlugins.length > 0) {

    for (var i = 0; i < foundPlugins.length; i++) {
      var plugin = plugin_manager.load_plugin(foundPlugins[i]);
      plugin(patternlab);
    }
  }
}

plugin(patternlab) calls the plugin's pluginInit() method inside index.js, having full access to the the patternlab object. It shuffles files to the frontend when needed, and most importantly, registers events.

Events

Events are registered in one place within the index.js file, and the following code works together:

const tab_loader = require('./src/tab-loader');

function onPatternIterate(patternlab, pattern) {
  tab_loader(patternlab, pattern);
}

/**
 * Define what events you wish to listen to here
 * For a full list of events - check out https://github.com/pattern-lab/patternlab-node/wiki/Creating-Plugins#events
 * @param patternlab - global data store which has the handle to the event emitter
   */
function registerEvents(patternlab) {
  //register our handler at the appropriate time of execution
  patternlab.events.on('patternlab-pattern-write-end', onPatternIterate);
}

tab_loader() does all our heavy lifting after this point.

The list of events emitted can be found here.

Any more events may be considered and assessed via pull request

Special Note: Plugin-specific postinstall

This plugin has a postinstall script defined in its package.json file because it requires user-input. Know that not all plugins will require this.

Frontend Plugin Anatomy

Plugins need to output their configuration and files to the Pattern Lab frontend in order to be found and initialized. Study plugin-loader.js to better understand how to load templates, stylesheets, and javascript from your plugin.

Plugins will be installed into the public/patternlab-components/pattern-lab/ directory.

Frontend plugin output

Let's discuss both files and how they got there.

plugin-node-tab.json
{
  "name": "pattern-lab/plugin-node-tab",
  "templates": [],
  "stylesheets": [],
  "javascripts": [
    "patternlab-components/pattern-lab/plugin-node-tab/js/plugin-node-tab.js"
  ],
  "onready": "PluginTab.init()",
  "callback": ""
}

This file is heart of the configuration. It is output here and inside the plugins array for consumption alongside other plugins.

  • name: The name of the plugin, (for this case) the github org and repo name

  • templates: An array of template files to load. These are expected to be mustache files. Will be available to javascript as <<plugin-name>>-filename-template

  • stylesheets: An array of css files to load.

    • Because of the way stylesheets are programmatically loaded via plugin, you must the path carefully. Try the following (for a fictional css file included in the plugin. You won't find one in the reference implementation):

    "stylesheets": [
      "/../../../pattern-lab/plugin-node-tab/css/plugin-node-tab.css"
    ],
    
  • javascripts: An array of javascript files to load. Any callback or onready functions you reference need to be defined within a file here.

    • Because of the way javascripts are programmaticaly loaded via plugin, you must specify the path carefully. Try the following:

    "javascripts": [
      "patternlab-components/pattern-lab/plugin-node-tab/js/plugin-node-tab.js"
    ],
    
  • onready: The function to be called when the plugin is finished loading all of its assets.

  • callback: The function to be called when the plugin is finished executing. testing needed

plugin-node-tab.js

This file is copied from the plugin's dist/ folder and placed under patternlab-components/pattern-lab/<<plugin-name>>/ Any other files or structure under dist/ will be copied in similar fashion during plugin backend processing. This is done in the plugin's index.js file.