Skip to content

Search tags, filters, functions and guides.

Language / Syntax

Language

Syntax

Delimiters, comments, strings and whitespace.

A Kiln template is ordinary text, usually HTML, with three kinds of delimiters mixed in. Everything outside them is output as written.

SyntaxUse
{{ expression }}Output the value of an expression
{% tag %}Run a tag, such as if or for
{# comment #}A comment. It produces no output
page.kiln
{# Greets the signed-in user #}
{% if user %}
	<p>Hello, {{ user.name }}. You have {{ messages }} messages.</p>
{% endif %}
Output
<p>Hello, Ada. You have 3 messages.</p>

Comments can span several lines, but they don't nest.

Whitespace

Kiln removes any line that holds only tags or comments, including its line break. Indent your tags to match your HTML, and the output still comes out clean.

page.kiln
<ul>
	{% for item in items %}
	<li>{{ item }}</li>
	{% endfor %}
</ul>
Output
<ul>
	<li>Tea</li>
	<li>Coffee</li>
</ul>

Output tags never remove their line, because they print something.

A byte order mark at the start of a template is ignored, so a file saved with one prints the same as a file without.

To remove whitespace by hand, add a - inside a delimiter. It removes all whitespace on that side, including line breaks.

page.kiln
<button>
	{{- label -}}
</button>
Output
<button>Save</button>

Every delimiter supports it: {{-, -}}, {%-, -%}, {#- and -#}.

Indentation

Kiln removes the extra indentation inside a tag, so you can indent a template for reading without it showing in the HTML.

page.kiln
<ul>
	{% for item in items %}
		<li>{{ item }}</li>
	{% endfor %}
</ul>
Output
<ul>
	<li>Tea</li>
	<li>Coffee</li>
</ul>
  • It applies when an opening tag, such as for or if, is on a line of its own.
  • Kiln removes the indentation that every line inside shares, beyond the tag's own. If one line is indented less, or uses tabs where the others use spaces, nothing is removed.
  • Blank lines don't count.
  • Nested tags each remove their own step.
  • Content that lines up with its tag, as in the example under Whitespace, is unchanged.
  • Only text in the template changes. Values you output keep their own whitespace.
  • It happens when the template is compiled, so rendering is no slower.

When an include, component, slot or block is on a line of its own, Kiln indents every line it inserts to line up with the tag.

page.kiln
<main>
	{% component "components/card" with { title: "Hello" } %}
		<p>Welcome back.</p>
	{% endcomponent %}
</main>
components/card.kiln
<article>
	<h2>{{ title }}</h2>
	{% slot %}{% endslot %}
</article>
Output
<main>
	<article>
		<h2>Hello</h2>
		<p>Welcome back.</p>
	</article>
</main>
  • It applies to the template that an include or component renders, the content passed to a slot, and the blocks a child template fills.
  • Nested insertions add up. A slot inside a component inside an include lines up with all three.
  • When the tag shares its line with other text, the inserted content is not indented any further.
  • Only text in templates is indented. Values you output keep their own whitespace, including what a macro returns and what set and apply capture.

Kiln never changes the indentation of lines inside a <pre> or <textarea>, because there the whitespace is part of the content. Content an include or component inserts there is not indented either. A <pre> inside an HTML comment, script or style doesn't count.

Strings

Strings use single or double quotes. Double-quoted strings can include expressions with #{ }:

page.kiln
{{ "Hello #{ user.name|title }, you have #{ count } new messages" }}
Output
Hello Ada, you have 2 new messages

Both quote styles support the escapes \\, \', \", \n, \r, \t and \u{hex}. In a double-quoted string, write \#{ for a literal #{. Single-quoted strings never interpolate, so '#{' is already literal there, and \# is an error.

Names

Variable, function and filter names start with a letter or underscore, followed by letters, digits or underscores. They are case-sensitive. Kiln's own names use camelCase, such as formatDate and loop.revIndex.

These words are reserved and can't be variable names: true, false, null, and, or, not, in, is, loop and slots.

Template names

Templates are named by their path, such as pages/home.kiln or components/card.

  • The .kiln extension is optional. A name whose last part already holds a dot, such as data/config.json, is used as written, so write partials/nav.main.kiln in full.
  • Names starting with ./ or ../ are relative to the current template.
  • Other names are relative to the loader's root folder.
  • A name can't point above the root folder, or name a folder, such as ./ or partials/.