NAME
Punk::Views - the pluggable view engine registry (XS)
DESCRIPTION
Each views $name => \%opts call in the DSL registers one engine. $name resolves to Punk::View::$name; '+Full::Class' uses the class as written. The engine contract is two methods and nothing more - adding view backends never touches the dispatch path:
my $engine = Engine->new(\%opts);
my $bytes = $engine->render($template_name, \%data);
my $bytes = $engine->render($template_name, \%data, \%opts); # see below
The first registered engine is the default; $c->render($tpl, \%data, engine => 'Other') selects per render, type => '...' overrides the content type, status => ... the status, and layout => ... the wrapper. Everything resolves and croaks at to_app, never per request. An override not in that list croaks at the render, naming the four that are: an option that is silently skipped is one that looks like it worked.
layout
$c->render('panel/logs', \%data, layout => undef); # no wrapper
$c->render('mail/reset', \%data, layout => 'mail'); # another one
A template name (resolved like any other, with or without its extension) renders inside that wrapper instead of the configured one; undef renders with none. The option reaches the engine as a third argument, { wrapper => $name | undef }, and only when it was given - an engine written to the two-argument call sees nothing new until a caller asks for a layout, and then ignores it. Punk::View::Stencil honours it; an engine of your own that wants to has the hashref. Everything else about the render is unchanged: the per-request values a plugin binds (csp_nonce, locale) are there, the application's filters run, the pending status and headers fold in.
$c->fragment ("fragment" in Punk::Context) is this with undef and a Cache-Control of private, no-store, for the partial that is one user's data.
Implemented entirely in C (include/punk/punk_views.h): the object is a blessed IV-ref to the engine registry, and render - the hot path - looks the engine up, calls its render, and assembles the PSGI triplet in C, so a rendered page crosses the Perl boundary only for the engine's own render (itself XS in Template::Stencil).
METHODS
new(\@pairs)
Compile the registry from [ [ $name, \%opts ], ... ]. Resolves, loads and instantiates each engine; the first is the default. Duplicate names, a class that will not load, or one missing new/render croak.
engine($name?)
The named (or default) engine instance; unknown names croak listing what is registered.
default
The default engine's name.
render($c, $template, \%data, %overrides)
A finished PSGI triplet around the engine's bytes, folding in any status and headers pending on the context $c (which may be undef). Overrides: status, type, engine, layout; any other croaks, as does an override name with no value after it.
AUTHOR
LNATION <email@lnation.org>
LICENSE AND COPYRIGHT
This software is Copyright (c) 2026 by LNATION <email@lnation.org>.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)