JavaScript API
Functions, filters and tests
Add your own functions, filters, tests and globals.
Add your own functions, filters and tests when you create the environment. They are plain JavaScript functions, and they can be async.
const kiln = createKiln({
loader,
functions: {
document: (collection: string, query: { slug: string }) =>
db.find(collection, query),
},
filters: {
readingTime: (text: string) => Math.ceil(text.split(" ").length / 200),
},
tests: {
external: (url: string) => !url.startsWith("/"),
},
});
{% set post = document("post", slug: route.slug) %}
<p>{{ post.body|readingTime }} min read</p>
{% if post.link is external %}<a href="{{ post.link }}" rel="noopener">Visit</a>{% endif %}
How arguments arrive
- A filter gets the filtered value first, then its arguments.
- Named arguments arrive as one plain object at the end.
document("post", slug: "hello")callsdocument("post", { slug: "hello" }). - Arrays arrive as arrays and hashes as plain objects.
- Arrow functions arrive as plain functions. They return a promise if their body calls something async.
- A test should return a boolean, or a promise of one.
Names
- Names start with a letter or underscore, followed by letters, digits or underscores. Test names can be two words, such as
divisible by. - Functions, filters and tests have separate names, so a filter and a function can share one.
- Your own function, filter or test replaces a built-in one with the same name. The exceptions are
parent,block,default,raw,escapeanddefined, which Kiln reserves.
Async functions
Any function, filter or test can return a promise. Kiln waits for it where it is called and carries on. See Async data.
Throwing an error stops the render. The render error's cause is your error, so you can throw your own error types to signal a 404 or a redirect and catch them in your server.
Request data
Some functions need data about the current request, such as the visitor's language or whether they are previewing drafts. Wrap them in withRender, and pass the data as state when you render.
import { createKiln, withRender } from "@lucidkiln/core";
type State = { locale: string; preview: boolean };
const kiln = createKiln<State>({
loader,
functions: {
document: withRender((render, collection: string, query: { slug: string }) =>
db.find(collection, {
...query,
locale: render.state.locale,
drafts: render.state.preview,
}),
),
},
});
await kiln.render("pages/page", context, {
state: { locale: "en", preview: false },
});
The first argument describes the render:
| Property | Description |
|---|---|
state | The state passed to render |
locale | The render's locale |
timeZone | The render's time zone |
template | The name of the template making the call |
signal | The render's abort signal, if there is one |
With a State type, TypeScript makes state a required render option, so you can't forget it.
Globals
Globals are variables every template can read, including included templates, components and macros. Use them for data that is the same on every page, such as the site's name.
const kiln = createKiln({
loader,
globals: { site: { name: "Acme", url: "https://acme.example" } },
});
Templates can't assign to globals. Values are not awaited, so pass data that is ready, or a function.