Loaders and engines
How to add custom loaders and template engines to Lume.
Loaders are functions that read and return the content of files. There are different loaders for different formats, like json
, yaml
, JavaScript modules or plain text.
Creating a loader
Creating a custom loader is really easy: you only have to create a function that reads the content of a file and returns a data object.
Let's say you want to add support for the toml
format, using the toml Deno std module:
import { parse } from "https://deno.land/std/encoding/toml.ts";
async function tomlLoader(path) {
const content = await Deno.readTextFile(path);
return parse(content);
}
Register a data loader
If you want to use the TOML loader to load data files, use the site.loadData()
method in the _config.ts
file:
site.loadData([".toml"], tomlLoader);
Now you can use the TOML format to save data files (_data.toml
or _data/*.toml
).
Register a page loader
To generate pages using TOML format, use the loadPages
function:
site.loadPages([".toml"], tomlLoader);
Now, any *.toml
file in your site will be loaded and used to render a page. For example, the file /about-us.toml
would be loaded and saved as /about-us/index.html
. You can also pass a (custom) template engine that will be used for rendering it.
As loadPages()
is intended to generate .html
pages, the given extension (here .toml
) is removed and replaced by .html
(or /index.html
for pretty urls).
You may want to load TOML files, process them and export as .toml
files, not .html
files. To do that, you can use loadAssets()
:
site.loadAssets([".toml"], tomlLoader);
Now, the *.toml
files are loaded and saved as toml
. The function loadAssets
is useful to load assets files, like css
, js
, svg
, that you want to transform (bundle, minify...) and save them while keeping the same extension, instead of renaming them to html
.
Note: you can't use the same extension to generate pages and assets, so a way to have support for both is adding a sub-extension (like tmpl
) for pages. Example:
// Use *.html.toml extension for pages
site.loadPages([".html.toml"], tomlLoader);
// And any other *.toml files for assets
site.loadAssets([".toml"], tomlLoader);
This is the same strategy used for JavaScript/TypeScript modules (*.tmpl.js
for pages and *.js
for JavaScript assets).
The textLoader
is used by default if you don't pass any loader. For example: site.loadPages([".html"])
or site.loadAssets([".css", ".js"])
. {.tip}
Template engines
Lume supports several template engines to render your pages, like Nunjucks, Pug or Eta. It's easy to extend this support for more template engines: you only need to create a class extending the Engine
interface. Let's see an example using handlebars:
import HandlebarsJS from "https://dev.jspm.io/handlebars@4.7.6";
import { Data, Engine } from "lume/core.ts";
export default class HandlebarsEngine implements Engine {
/** Render the content (sync or async) */
render(content: string, data: Data): string {
return this.renderSync(content, data, filename);
}
/** Render sync (used only for components) */
renderSync(content: string, data: Data): string {
const template = HandlebarsJS.compile(content);
return template(data);
}
/** Register helpers */
addHelper() {}
/** Delete cache */
deleteCache() {}
}
To use this template engine, pass it as the third argument of the loadPages
function:
import textLoader from "lume/loaders/text.ts";
import HandlebarsEngine from "./handlebars-engine.ts";
site.loadPages([".hbs"], textLoader, new HandlebarsEngine(site));
Now, all files with the .hbs
extension will be loaded using the textLoader
and rendered using the Handlebars engine.
This is a very basic implementation only as an example. You can see the code of the available template engines in Lume for real examples. {.tip}