Template API¶
Zypher's template engine is a custom implementation with:
- Auto-escaping of HTML (use |safe filter to bypass)
- Dot notation for field access ({{ user.name }})
- List index access ({{ items.0 }})
- {% include %} directive
- {% extends %} / {% block %} inheritance
- {% if %} / {% elif %} / {% else %} conditionals
- {% for %} loops with forloop context
- Pipe filters ({{ name|upper|truncate(10) }})
Value¶
Union type representing template values.
Variants¶
string: []const u8int: i64float: f64bool: boollist: []const Valuemap: *Contextnull_val: void
Methods¶
value.format(writer)— format value to writer (formats lists as comma-separated, maps as key: value pairs)value.isTruthy() bool— string: non-empty, int/float: non-zero, bool: true, list: non-empty, map: always true, null: false
Context¶
Template variable context — a string-keyed map of Values.
Methods¶
Context.init(allocator) Context— create a new contextcontext.deinit()— free resourcescontext.put(key, value) !void— set a variablecontext.get(key) ?Value— get a variable
Template¶
A parsed template with cached AST.
Methods¶
Template.fromSource(allocator, source) !Template— parse template source into an AST (tokenizes, parses, takes ownership of nodes)template.deinit()— free all nodes and sourcetemplate.render(ctx, writer) !void— render the template with the given context; handles{% extends %},{% include %}, variables, filters, conditionals, and loops
Rendering Features¶
{% extends "base.html" %}— must be the first node; loads the base template and fills{% block %}slots{% include "partial.html" %}— includes another template (requires engine reference){{ var.field }}— dot notation for nested field access on maps{{ list.0 }}— numeric index access on lists{{ var|upper|truncate(10) }}— filter pipeline{% if condition %}...{% elif other %}...{% else %}...{% endif %}— conditionals (checks truthiness){% for item in list %}...{% endfor %}— loops withforloopcontext:counter0,counter,first,last
TemplateEngine¶
Template cache with load and render operations.
Methods¶
TemplateEngine.init(allocator) TemplateEngine— create a new engineengine.deinit()— free all cached templatesengine.load(name, source) !*Template— parse and cache a template; returns pointer to cached templateengine.render(name, ctx, writer) !void— render a cached template by nameengine.getTemplate(name) ?*Template— get a cached template by name
Lexer¶
Template source tokenizer.
Lexer.init(allocator, source) Lexer¶
Create a new lexer.
lexer.tokenize() !void¶
Tokenize the source into internal token list.
lexer.deinit()¶
Free tokens.
Parser¶
Template AST builder.
Parser.init(allocator, tokens) Parser¶
Create a parser from a token list.
parser.parse() !void¶
Parse tokens into AST nodes.
parser.deinit()¶
Free AST nodes.
Filters¶
Template filter functions for transforming values in expressions.
FilterResult¶
value: Value— the filtered valueowned: bool— whether the result owns allocated memory (must be freed)filterResult.deinit(gpa)— free owned memory
Application Functions¶
apply(gpa, name, value) !FilterResult— apply a filter by name (no argument)applyWithArg(gpa, name, value, arg) !FilterResult— apply a filter with a string argument
Built-in Filters¶
| Filter | Description | Example |
|---|---|---|
upper |
Convert to uppercase | {{ name|upper }} |
lower |
Convert to lowercase | {{ name|lower }} |
capitalize |
Capitalize first letter | {{ name|capitalize }} |
title |
Title case (capitalize each word) | {{ name|title }} |
trim |
Strip whitespace (spaces, tabs, newlines, carriage returns) | {{ name|trim }} |
length |
Get string length or list count | {{ name|length }} |
reverse |
Reverse string | {{ name|reverse }} |
escape |
HTML-escape a string explicitly (<>&"') |
{{ raw|escape }} |
safe |
Mark value as safe (bypass auto-escaping) | {{ html_content|safe }} |
join(sep) |
Join list items with separator | {{ list|join(", ") }} |
truncate(n) |
Truncate to n characters with ... |
{{ text|truncate(50) }} |
default(val) |
Default value if empty/null | {{ name|default("Guest") }} |
date(format) |
Format Unix timestamp as YYYY-MM-DD |
{{ timestamp|date }} |
Full Example¶
const std = @import("std");
const zypher = @import("zypher");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
var engine = zypher.template.renderer.TemplateEngine.init(gpa.allocator());
defer engine.deinit();
_ = try engine.load("hello.html", "<h1>Hello, {{ name|upper }}!</h1>");
var ctx = zypher.template.renderer.Context.init(gpa.allocator());
defer ctx.deinit();
try ctx.put("name", .{ .string = "world" });
var buf = std.ArrayList(u8).init(gpa.allocator());
defer buf.deinit();
try engine.render("hello.html", &ctx, buf.writer());
// buf.items == "<h1>Hello, WORLD!</h1>"
}