template-sluz
Smarty-like templates for ZuzuScript.
Synopsis
from template/sluz import Sluz;
from std/io import Path;
const s := new Sluz(
auto_escape: true,
base_dir: [
new Path("templates"),
new Path("fallback-templates"),
],
);
s.assign("name", "Ada");
s.assign_all({
items: [ "one", "two", "three" ],
});
s.add_modifiers(
camelcase: function (value) {
return uc("" _ value);
},
);
say( s.parse_string("Hello {$name|escape}") );
const t := s.compile_string("Hello {$name|escape}");
say( t.render({ name: "Ada" }) );
say( t.render({ name: "Bob" }) );
Description
template/sluz is a ZuzuScript port of Scott Baker's Template::Sluz Perl module. It supports variables, dotted and bracket lookups, chained modifiers, if/elseif/else, foreach, includes, literal blocks, comments, automatic escaping, and custom delimiters.
Unlike the Perl module, custom modifiers need to be explicit:
s.add_modifiers(
trim: function (value) {
return trim("" _ value);
},
escape: function (value) {
return "[" _ value _ "]";
},
);
The built-in escape modifier performs HTML escaping, but it can be overridden with add_modifiers for non-HTML output. It also accepts an escape mode:
{$value|escape} // HTML escaping
{$value|escape:"html"} // HTML escaping
{$value|escape:"xml"} // XML escaping
{$value|escape:"url"} // URL component escaping
{$value|escape:"js"} // JavaScript string literal escaping
auto_escape may be true, false, or one of "html", "xml", "url", or "js". true uses HTML escaping.
Each Sluz instance registers these modifiers by default:
| Modifier | Behaviour |
|---|---|
escape |
Escapes scalar output as HTML, XML, URL, or JavaScript. |
noescape |
Returns the value unchanged and bypasses automatic escaping. |
raw |
Alias for noescape. |
default |
Returns a fallback for null or an empty String. |
count |
Counts arrays, bags, sets, dictionaries, pair lists, and scalar values. |
join |
Joins an Array, Bag, or Set with a separator, defaulting to ", ". |
uc |
Uppercases the value. |
upper |
Alias for uc. |
lc |
Lowercases the value. |
lower |
Alias for lc. |
ucfirst |
Uppercases the first character of the value. |
length |
Returns the string length of the value. |
substr |
Returns a substring. |
replace |
Replaces all occurrences of a string. |
first |
Returns the first array element or scalar character. |
last |
Returns the last array element or scalar character. |
trim |
Trims leading and trailing whitespace. |
normalize |
Trims leading/trailing whitespace and collapses internal whitespace runs. |
Modifiers can also be removed explicitly:
s.unset_modifiers("trim", "uc", "lc", "ucfirst");
Removing escape, noescape, or raw leaves the modifier defined as an identity function, allowing automatic escaping and explicit |noescape or |raw calls to continue to work without complaining.
Rendering
Use parse_string to render a template string. Use parse to render a template file; fetch is an alias for parse. display prints the result of parse, and display_string prints the result of parse_string.
Compiled templates
Use compile or compile_string when you want to parse a template once and render it repeatedly:
const s := new Sluz();
s.add_modifiers(
badge: function (value) {
return "[" _ value _ "]";
},
);
s.assign_all({ site: "Example" });
const t := s.compile(new Path("templates/profile.stpl"));
say( t.render({ name: "Ada" }) );
say( t.render({ name: "Bob" }) );
render accepts a Dict or PairList of values. Those values temporarily overlay variables assigned on the owning Sluz instance; missing variables fall back to assign and assign_all values. The owning Sluz instance's current modifiers, auto_escape, base_dir, and fallback assignments are used at render time.
The root template is loaded and parsed by compile, then reused. Includes in compiled templates are resolved lazily at render time: the first time a resolved include file is used, it is parsed and cached by path for that compiled template. Later renders reuse the cached include and do not observe changes to that included file. Dynamic include expressions may still choose different files, and each resolved file is cached independently.
Template delimiters are frozen at compile time for the root template and for compiled includes. parent_tpl is only applied by parse and its fetch alias; compile(path) compiles the named template directly.
Errors
template/sluz throws structured exceptions. All module exceptions inherit from SluzException, which inherits from Exception.
SluzException provides get_code() and get_details() methods. get_code() returns the stored numeric legacy Sluz error code for template-language errors and null for API usage errors. get_details() currently returns an empty Dict. The raw message slot stores only the bare error message; to_String() adds the template/sluz prefix and optional code.
The exception hierarchy is:
| Class | Parent | Meaning |
|---|---|---|
SluzException |
Exception |
Base class for all module exceptions. |
SluzUsageException |
SluzException |
Invalid API usage or renderer configuration. |
SluzArgumentException |
SluzUsageException |
Invalid argument shapes. |
SluzConfigurationException |
SluzUsageException |
Invalid renderer options. |
SluzDelimiterException |
SluzConfigurationException |
Invalid delimiter configuration. |
SluzLoadException |
SluzUsageException |
Template path lookup and loading errors. |
SluzTemplateException |
SluzException |
Errors in template content. |
SluzSyntaxException |
SluzTemplateException |
Template syntax and block structure errors. |
SluzExpressionException |
SluzTemplateException |
Template expression errors. |
SluzIncludeException |
SluzTemplateException |
Invalid include tags. |
SluzModifierException |
SluzTemplateException |
Unknown or invalid modifiers. |
SluzEscapeException |
SluzModifierException |
Invalid escaping modes. |
SluzInternalException |
SluzTemplateException |
Unexpected internal renderer states. |
Stringified errors begin with either template/sluz: for API usage errors or template/sluz error #...: for template-language errors.
Attribution
This port is based on Template::Sluz by Scott Baker: https://github.com/scottchiefbaker/perl-Template-Sluz
The ZuzuScript port is copyright Toby Inkster and is distributed under the GNU General Public License version 3 or later.