Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Names and data

The expressions in your tags use names: price, customer.name, text.upper. A name can come from four places.

The names you bind

A tag can bind names with = or :, and every later tag of the same template can use them. It is common to bind the values a template needs in a first tag:

<%
company = "Acme",
year = 2026,
copyright = "© " + text.from year + " " + company
%>Contact <% company %> for details.
<% copyright %>
Contact Acme for details.
© 2026 Acme

Functions work the same way. Define them once, and call them in later tags:

<% money = n -> "$" + text.from (math.round (n * 100) / 100) %>Subtotal: <% money 19.999 %>
Tax: <% money (19.999 * 0.2) %>
Subtotal: $20
Tax: $4

Built-in names

Every template can use the built-in library: text, list, math, time and the other namespaces, plus TRUE, FALSE, type and a few more. The engine adds the texl namespace, which imports other documents.

Data from the host

The program that renders your template can bind globals: names with the data the template needs. Which globals exist depends on the host, so a template usually documents what it expects, for example in a comment at the top:

<%
# Expects:
#   customer  {name, email}
#   orders    a list of {id, total}
%>

Values from the host become Swan values: strings become Text, numbers Numb, arrays List, objects namespaces, and functions Swan functions. See the host pages for how to pass globals: JavaScript and Rust. The command-line tool does not pass any.

Names from other documents

A document can import another document and use the names it binds. See Using a library.

Missing names

A name that is not bound anywhere is Nothing, which writes nothing. This is handy for optional data, but it also hides typos. Give optional names a default with ;:

Hello, <% reader ; "guest" %>!
Hello, guest!

Scopes of templates and documents

Each rendering of a template gets its own scope for the names it binds, below the globals and the built-ins. Binding a global or built-in name in a template hides it for the rest of that template only.

An imported document is rendered in a scope below the scope of the template that imports it, so it can read the importer's names (see Passing data to a partial).

Engine-wide names

bind binds a name in the global scope of the engine. The name is then visible in every template and document that the engine renders afterwards, not only in the current one. That is how a document shares a library with its importer (see Using a library), but it also means that two documents binding the same global name overwrite each other. Choose distinctive names for globals.