Views¶
MVC::Keayl::View renders templates. It resolves a template by name, format, and
handler, compiles it through a pluggable handler, and caches the result. HAML is
the default handler, backed by Template::HAML.
1 2 3 4 5 | |
Template resolution¶
render-template resolves a name against each search path in turn, then by
handler extension, preferring a format-qualified file:
1 2 3 | |
The default format is html, overridable per call with :format. A :variant
prefers a variant-qualified file before the plain one, so phone resolves
show.html+phone.haml and falls back to show.html.haml. When the View is given
a controller, a name with no / is resolved relative to the controller's path
(UsersController resolves under users/).
Handlers¶
A handler compiles a template source and renders it with locals. The default
haml handler renders HAML. Register others by extension:
1 | |
A handler does the MVC::Keayl::View::Handler role: compile($source) returns a
compiled template, and render($compiled, %locals) produces the output.
Caching and reloading¶
Compiled templates are cached by file. reload (on by default) re-checks the
file's modification time and recompiles when it changes, which suits development.
Setting cache => False disables caching so every render recompiles:
1 | |
Inline rendering¶
render-inline renders a template string directly, without resolving a file.
Layouts¶
When an action renders a template, the rendered body is wrapped in a layout from
layouts/. With no layout chosen, the application layout is used if it exists;
otherwise the template renders on its own. Inside the layout, the wrapped body is
available through the yield helper:
1 2 3 | |
Choose a layout per action with the :layout option, or for every action of a
controller with the class-level layout declaration:
1 2 3 4 5 6 | |
The layout declaration also has an is layout trait form for the class header:
1 | |
An action-level :layout overrides a controller declaration, which overrides the
application default.
content-for and yield¶
A template captures named content with content-for, and the layout places it
with yield:
1 2 3 4 5 6 7 | |
yield() returns the main body; yield(name) returns the matching
content-for capture, or an empty string when none was set.
Partials¶
A partial is a template whose file name begins with an underscore. It is referred
to without the underscore. render-partial renders one with locals:
1 | |
A name with no path segment resolves under the controller's view path; a name
with a / resolves from the views root, so shared/menu renders
shared/_menu from any controller.
Inside a template, the partial helper embeds a partial. Use != so its HTML is
not escaped:
1 2 | |
Object partials¶
render-object derives the partial from an object. By default the partial name
and the local both come from the object's class name; an object can override the
path with a to-partial-path method:
1 2 3 4 5 | |
A controller renders an object directly with render($post).
Collection partials¶
render-collection renders a partial once per item. Each render receives the
item under the partial's local name and a zero-based {local}_counter:
1 2 | |
1 | |
A spacer partial renders between items:
1 | |
A controller renders a collection with render(:partial('line'), :collection(@lines)).
Output safety¶
HAML escapes interpolated values by default, so = $value is safe and != $value
emits raw HTML. MVC::Keayl::SafeString adds a safe-buffer type and helpers for
composing and cleaning HTML.
html-escape encodes the markup-significant characters. html-safe and raw
wrap a string as a SafeString, which reports is-html-safe and stringifies to
its raw content. Concatenation escapes anything that is not already safe:
1 2 | |
sanitize keeps an allowlist of tags and attributes, removes script and style
elements with their content, and strips event-handler attributes and
javascript: URLs:
1 2 | |
json-escape encodes the characters that could end a <script> block (<, >,
&, and the line and paragraph separators) as \uXXXX, for embedding JSON in a
script context.
In templates these are available as the escape, raw, sanitize, and json
helpers; pair sanitize/raw with != so the cleaned HTML is not escaped again.