-
Notifications
You must be signed in to change notification settings - Fork 27
Plugin Framework for Serum
- 2019-02-26 11:32 — Initial draft
- 2019-04-10 15:38 — Uploaded to Gist
- 2019-04-10 16:11 — Split reading_files callback
- 2019-04-11 10:55 — Added version requirement callbacks
To allow experienced users and developers to make their own Serum plugins which can extend the functionality of Serum.
A Serum plugin can...
- Alter contents of input or output files,
- Execute arbitrary codes during some stages of site building,
- And optionally provide extra Mix tasks that extends Serum.
A Serum plugin is an Elixir module that implements Serum.Plugin
behaviour.
The Serum.Plugin
behaviour module defines several callbacks which are called
at some point of time:
All Serum plugin module must implement these four callbacks, otherwise the plugin may fail.
-
name() :: binary()
Name of the plugin
-
version() :: binary()
Version of the plugin. Must follow the semantic versioning scheme
-
elixir() :: binary()
serum() :: binary()
Version requirement of Elixir and Serum, respectively. Refer to this document for the string format
-
description() :: binary()
Short description about what the plugin does
-
implements() :: [atom()]
A list of names of optional callbacks that the plugin implements
These optional callbacks have default implementations which simply do nothing
and pass the input to the output as is. If some of these callbacks are to be
implemented, the names of those callbacks must be present in implements/0
, or
they will never be called.
-
build_started(src :: binary(), dest :: binary()) :: Result.t()
Called right after the build process has started. Some necessary OTP applications or processes should be started here.
-
reading_pages(files :: [binary()]) :: Result.t([binary()])
reading_posts(files :: [binary()]) :: Result.t([binary()])
reading_templates(files :: [binary()]) :: Result.t([binary()])
Called before reading input files. Plugins can manipulate the list of files to be read and pass it to the next plugin.
-
processing_page(file :: Serum.File.t()) :: Result.t(Serum.File.t())
processing_post(file :: Serum.File.t()) :: Result.t(Serum.File.t())
processing_template(file :: Serum.File.t()) :: Result.t(Serum.File.t())
These three callbacks above are called before Serum processes each input file. Plugins can alter the raw contents of input files here.
-
processed_page(page :: Serum.Page.t()) :: Result.t(Serum.Page.t())
processed_post(post :: Serum.Post.t()) :: Result.t(Serum.Post.t())
processed_template(template :: Serum.Template.t()) :: Result.t(Serum.Template.t())
processed_list(list :: Serum.PostList.t()) :: Result.t(Serum.PostList.t())
These four callbacks above are called after Serum has processed each input file and produced the resulting struct. Plugins can alter the processed contents (an AST in case of a template) and metadata here.
-
rendered_fragment(frag :: Serum.Fragment.t()) :: Result.t(Serum.Fragment.t())
Called after producing a HTML fragment for each page. Plugins can modify the contents and metadata of each fragment here.
-
rendered_page(file :: Serum.File.t()) :: Result.t(Serum.File.t)
Called when Serum has rendered a full page and it's about to write to an output file. Plugins can alter the raw contents of the page to be written.
-
wrote_file(file :: Serum.File.t()) :: Result.t()
Called after writing each output to a file.
-
build_succeeded(src :: binary(), dest :: binary()) :: Result.t()
Called if the whole build process has finished successfully.
-
build_failed(src :: binary(), dest :: binary(), result :: Result.t() | Result.t(term)) :: Result.t()
Called if the build process has failed for some reason.
-
finalizing(src :: binary(), dest :: binary()) :: Result.t()
Called right before Serum exits, whether the build has succeeded or not. This is the place where you should clean up any temporary resources created in
build_started/2
callback.