Templates
Views are pluggable engines registered with the views keyword; the
first registered is the default. Punk ships
Template::Stencil, a fast
C-backed engine.
views Stencil => {
template_dir => 'root/templates',
wrapper => 'layout.tmpl',
};
Or, equivalently, from config/punk.yml:
views Stencil template_dir: root/templates wrapper: layout.tmpl
The engine is constructed at boot, so bad options fail before the app serves. Templates themselves hot-reload through Stencil's mtime cache - no restart while you edit.
Rendering
sub view {
my ($c) = @_;
return $c->render('book/view', { book => $book });
}
Template names resolve against template_dir with .tmpl inferred, and
render inside the wrapper layout: book/view becomes
root/templates/book/view.tmpl wrapped by layout.tmpl. Options
override per call:
$c->render('feed', \%data, type => 'application/atom+xml', status => 200);
$c->render('email/welcome', \%data, engine => 'Other');
Stencil syntax
<h1>{% title | upper %}</h1>
<ul>
{% for item in items %}<li>{% item.name %}</li>
{% end %}
</ul>
{% if admin %}<a href="/admin">admin</a>{% end %}
{% raw trusted_html %}
Values are HTML-escaped by default; {% raw %} opts out for values you
built yourself. Filters chain with |, and dotted paths walk hashes and
method-less objects. The wrapper receives the page as {% content %}.
Layouts
A wrapper is an ordinary template around the page:
<!doctype html>
<html lang="en">
<head><title>{% title | default('MyApp') %}</title></head>
<body>
<main>
{% content %}
</main>
</body>
</html>
Other engines
Register any class with the engine contract as a view engine, by name or
with a literal +Class:
views '+My::View::TT' => { ... };
See Punk::Views for the contract.