A template engine for Pony with optional HTML-aware contextual auto-escaping.
Templates is beta-level software. As it gets used in more projects, we may make breaking changes.
- Install corral
corral add github.com/ponylang/templates.git --version 0.3.2corral fetchto fetch your dependenciesuse "templates"to include this packagecorral run -- ponycto compile your application
Parse a template, bind values, and render:
use "templates"
actor Main
new create(env: Env) =>
let template =
try
Template.parse("Hello {{ name }}")?
else
env.err.print("Could not parse template")
return
end
let values = TemplateValues
values("name") = "world"
try
env.out.print(template.render(values)?)
endFor HTML output, use HtmlTemplate to get automatic context-aware escaping:
let template =
try
HtmlTemplate.parse(
"<h1>{{ title }}</h1><p>{{ message }}</p>")?
else
env.err.print("Could not parse template")
return
end
let values = TemplateValues
values("title") = "Hello & welcome"
values("message") = "<script>alert('xss')</script>"
try
// Renders:
// <h1>Hello & welcome</h1>
// <p><script>alert('xss')</script></p>
env.out.print(template.render(values)?)
endSee the examples directory for more.
- Variables:
{{ some_var }}is replaced with the variable's value. A value can be aStringor aTemplateValue. ATemplateValueis either aStringor aSeq[TemplateValue]. - Properties:
{{ some_var.prop }}is replaced with valuesome_var's propertyprop. Properties are part ofTemplateValue: its constructor takes aMap[String, TemplateValue]that defines the value's properties. - Conditionals:
{{ if flag }}...{{ end }}renders content when the variable exists and, for sequences, is non-empty. Can check properties too. Supports{{ else }}and{{ elseif other_flag }}branches. - Negated conditionals:
{{ ifnot flag }}...{{ end }}renders content when the variable is absent or is an empty sequence. Supports{{ else }}and{{ elseif }}branches. - For loops:
{{ for x in xs }}{{ x }} {{ end }}iterates through the sequencexsand adds each element plus a space to the output. - Filters:
{{ name | upper }}pipes a value through one or more filters. Filters chain left-to-right:{{ name | trim | upper }}. The pipe source can be a template variable or a string literal:{{ "hello" | upper }}. Filter arguments can be string literals ("hello") or template variables (varname). Built-in filters:upper,lower,trim,capitalize,title,default("fallback"),replace("old", "new"). Custom filters can be registered viaTemplateContext. - Includes:
{{ include "header" }}inlines a named partial registered viaTemplateContext. Partials share the same variable scope as the surrounding template and can contain any block type. Circular includes are detected at parse time. - Template inheritance: A child template declares
{{ extends "base" }}as its first statement and overrides named blocks defined in the base with{{ block name }}...{{ end }}. Base templates are registered as partials viaTemplateContext. Blocks not overridden render their default content from the base. Multi-level inheritance is supported. Content outside{{ block }}definitions in a child template is silently ignored. Circular extends chains are detected at parse time. - Comments:
{{! this is a comment }}is ignored during rendering. Everything between!and}}is discarded. Trim markers work as expected:{{!- comment -}}. - Raw blocks:
{{raw}}...{{end}}emits everything between the tags as literal text, without interpreting{{ }}sequences. Useful when the template output itself contains delimiter syntax. Trim markers work on both tags:{{- raw -}}...{{- end -}}. The first{{ end }}closes the raw block, so literal{{ end }}cannot appear inside raw content. - Whitespace trimming:
{{- x }}strips trailing whitespace from the preceding literal,{{ x -}}strips leading whitespace from the following literal,{{- x -}}strips both. Useful for generating indentation-sensitive output (YAML, Python, Pony) without unwanted blank lines from control flow tags. - HTML auto-escaping:
HtmlTemplateautomatically escapes variable output based on HTML context — text content gets entity escaping, URL attributes get scheme filtering and percent-encoding, script contexts get JS string escaping, and so on. UseTemplateValue.unescapedorTemplateValues.unescapedto bypass escaping for trusted content.