Skip to content

Search tags, filters, functions and guides.

JavaScript API / Functions, filters and tests

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") calls document("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, escape and defined, 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:

PropertyDescription
stateThe state passed to render
localeThe render's locale
timeZoneThe render's time zone
templateThe name of the template making the call
signalThe 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.