Creating plugins

Guide to create your own plugins to extend Lume

Lume is a static site generator that can be extended easily by adding more loaders, engines, processors etc. Plugins provide an easy interface to extend Lume without writing too much code in the _config.ts file.

A plugin is just a function that receives a lume instance in the first argument, in order to configure and register new elements to it.

Simple plugin example

Let's say we have this code in our _config.ts file to add a copyright banner to all CSS pages:

// _config.ts

import lume from "lume/mod.ts";

const site = lume();

function addBanner(content: string): string {
  const banner = "/* © This code belongs to ACME inc. */";
  return $banner + "\n" + content;
}

site.process([".css"], (page) => {
  page.content = addBanner(page.content as string);
});

export default site;

We can encapsulate this code inside a plugin and even include some configuration:

// my-plugins/css_banner.ts

interface Options {
  message: string;
}

export default function (options: Options) {
  function addBanner(content: string): string {
    const banner = `/* ${options.message} */`;
    return $banner + "\n" + content;
  }

  return (site: Site) => {
    site.process([".css"], (page) => {
      page.content = addBanner(page.content as string);
    });
  };
}

And now, we can use it in the _config.ts file in this way:

import lume from "lume/mod.ts";
import cssBanner from "./my-plugins/css_banner.ts";

const site = lume();

site.use(cssBanner({
  message: "© This code belongs to ACME inc.",
}));

export default site;

Plugins can't do anything that you couldn't do in the _config.ts file, but they provide a better interface to organize and reuse your code. And better: share it with others.

Take a look to the repository of Lume plugins for more advanced examples.

Hooks

Some plugins expose hooks that can be invoked by other plugins or in the _config.ts file. A hook is only a function that can do arbitrary things, like changing a configuration of a plugin. Hooks are stored in site.hooks. Let's create a hook in our css_banner plugin to change the message:

// my-plugins/css_banner.ts

interface Options {
  message: string;
}

export default function (options: Options) {
  function addBanner(content: string): string {
    const banner = `/* ${options.message} */`;
    return $banner + "\n" + content;
  }

  return (site: Site) => {
    // Add a hook to change the message
    site.hooks.changeCssBanner = (message: string) => {
      options.message = message;
    };

    site.process([".css"], (page) => {
      page.content = addBanner(page.content as string);
    });
  };
}

Now the message can be changed after the plugin installation:

import lume from "lume/mod.ts";
import cssBanner from "./my-plugins/css_banner.ts";

const site = lume();

site.use(cssBanner({
  message: "© This code belongs to ACME inc.",
}));

site.hooks.changeCssBanner("This code is open source");

export default site;

Or we can invoke this hook from other plugin:

// my-plugins/open_source.ts

export default function () {
  return (site: Site) => {
    if (!site.hooks.changeCssBanner) {
      throw new Error("This plugin requires css_banner to be installed before");
    }

    site.hooks.changeCssBanner("This code is open source");
  };
}
import lume from "lume/mod.ts";
import cssBanner from "./my-plugins/css_banner.ts";
import openSource from "./my-plugins/open_source.ts";

const site = lume();

site.use(cssBanner({
  message: "© This code belongs to ACME inc.",
}));

site.use(openSource());

export default site;