template

Fill in text templates. {{name}} inserts a value (HTML-escaped, so it is safe in web pages), {{{name}}} inserts it as is, {{#items}}...{{/items}} repeats for each item of a list (or shows the part when the value is true/non-empty), {{^items}}...{{/items}} shows when it is empty or false, {{name|upper}} applies a filter, {{a.b.c}} reaches into maps, {{.}} is the current item and {{! note }} is a comment. Filters: upper lower title capitalize trim len first last reverse sort join:", " round:2 default:"-" truncate:40 pad_left:8 pad_right:8 date:"%Y-%m-%d" json escape urlencode number yes_no raw.

import template

Example

import template

let page = "<h1>{{title|upper}}</h1>{{#alerts}}<li>{{rule}} from {{ip}}</li>{{/alerts}}{{^alerts}}<p>No alerts</p>{{/alerts}}"
say(
  template.render(page, {
    "title": "Alerts",
    "alerts": [{"rule": "Brute force", "ip": "203.0.113.42"}, {"rule": "<script>", "ip": "x"}],
  }),
)
say(template.render("Hello {{name}}!", {"name": "Tanisha"}))

Functions

render(text, values?, options?)

returns text

Fill the template with values (a map): template.render("Hi {{name}}!", {"name": "Tanisha"}).

Values are HTML-escaped, unless

  • they are written {{{like this}}},
  • they are given the raw filter,
  • or options is {"escape": false} (for plain text, emails or config files).
Visualizehow template.render works

template.render("<p>Hi {{name}}, {{count}} new alerts</p>", {"name": "<Ada>", "count": 3}, {}) gives "<p>Hi &lt;Ada&gt;, 3 new alerts</p>"

template.render: inputs flowing into the function and the resulttext<p>Hi {{name}}, {{count}} newalerts</p>values?name"<Ada>"count3options?{} (empty map)template.renderthe gaps filled in<p>Hi &lt;Ada&gt;, 3 new alerts</p>text<p>Hi {{name}}, {{count}} newalerts</p>values?name"<Ada>"count3options?escapefalsetemplate.renderthe gaps filled in<p>Hi <Ada>, 3 new alerts</p>

Real result: worked out by running this example with TB while the site was built.

file(path, values, options?)

returns text

Read a template file and fill it in, like render(). Relative paths start where you ran tb.

Visualizehow template.file works

template.file("page.html", {"title": "Weekly report"}) gives "<h1>Weekly report</h1>\n"

template.file: inputs flowing into the function and the resultpath"page.html"page.html holds<h1>{{title}}</h1>valuestitle"Weekly repor…options?left out (same asrender())template.filethe file, filled in<h1>Weekly report</h1>

Real result: worked out by running this example with TB while the site was built.

check(text)

returns list

Problems in a template without rendering it (unclosed sections, unknown filters), as a list of text messages; empty when it is fine.

Visualizehow template.check works

template.check("Hi {{name}}") gives []

template.check: inputs flowing into the function and the resulttextHi {{name}}template.checkproblems found (empty: fine)[] (empty list)text{{#items}} opentemplate.checkproblems found (empty: fine)"line 1: the section …text{{name|shout}}template.checkproblems found (empty: fine)"line 1: I don't know…

Real result: worked out by running this example with TB while the site was built.

names(text)

returns list

The value names a template uses (top-level, sorted): names("{{a}} {{#b}}{{c}}{{/b}}") is ["a", "b"].

Visualizehow template.names works

template.names("{{title}}: {{#alerts}}{{rule}} {{/alerts}} by {{user.name}}") gives ["alerts", "title", "user"]

template.names: inputs flowing into the function and the resulttext{{title}}: {{#alerts}}{{rule}}{{/alerts}} by {{user.name}}template.namesthe top-level names it needs"alerts""title""user"

Real result: worked out by running this example with TB while the site was built.

escape(text)

returns text

Text made safe for HTML: < > & " become entities.

Visualizehow template.escape works

template.escape("Tom & <Jerry>") gives "Tom &amp; &lt;Jerry&gt;"

template.escape: inputs flowing into the function and the resulttext"Tom & <Jerry>"template.escapesafe inside HTMLTom &amp; &lt;Jerry&gt;

Real result: worked out by running this example with TB while the site was built.

Values

NameValueWhat it is
template.filters["capitalize", "date", "default", "escape", "first", "join", "json", "last", ...

The filter names {{name|filter}} understands.

Visualizehow template.filters works

template.filters gives ["capitalize", "date", "default", "escape", "first", "join", "json", "last", "l…

The value template.filterstemplate.filters"capitalize""date""default""escape""first""join""json""last""len""length""lower""number""pad_left""pad_right"+10 morewhat it isThe filter names {{name|filter}}understands.

No inputs: call it as it is.

Real value, read from TB while the site was built.