Layout
The {{ layout }} tag allows to capture some content in a template and render
it into another template under the variable content.
For example, let's say you have the following container.vto template:
<div class="container">
{{ content }}
</div>
You can pass content to this template easily with the layout tag:
{{ layout "container.vto" }}
<h1>Hello, world!</h1>
{{ /layout }}
Technically, the layout tag works a lot like the following:
{{ set content }}
<h1>Hello, world!</h1>
{{ /set }}
{{ include "container.vto" { content } }}
Data
In addition to the content variable, the layout inherits the same data as the
main file. You can pass additional data creating an object after the layout file
name.
{{ layout "container.vto" { size: "big" } }}
<h1>Hello, world!</h1>
{{ /layout }}
Now, the layout content has the size variable:
<div class="container size-{{ size }}">
{{ content }}
</div>
Pipes
You can use pipes to transform the content passed to the layout. For example:
{{ layout "container.vto" |> toUpperCase }}
<h1>Hello, world!</h1>
{{ /layout }}
This code outputs:
<div class="container">
<h1>HELLO, WORLD!</h1>
</div>
Slots
The {{ slot }} tag allows to split the content into different variables. For
example, let's say we have a layout that accepts the variables header and
content:
{{ layout "section.vto" { header: "<h1>Section title</h1>" } }}
<p>Content of the section</p>
{{ /layout }}
A more ergonomic way to define the header variable is using a slot:
{{ layout "section.vto" }}
{{ slot header }}
<h1>Section title</h1>
{{ /slot }}
<p>Content of the section</p>
{{ /layout }}
You can use pipes to transform the content of a specific slot. In this case, the
header variable is converted to upper case:
{{ layout "section.vto" }}
{{ slot header |> toUpperCase }}
<h1>Section title</h1>
{{ /slot }}
<p>Content of the section</p>
{{ /layout }}
If there are several slots with the same name, the content is concatenated. In
this example, the header variable will contain the value of the two slots:
{{ layout "section.vto" }}
{{ slot header }}<h1>Section title</h1>{{ /slot }}
{{ slot header }}<h2>Subsection title</h2>{{ /slot }}
<p>Content of the section</p>
{{ /layout }}
Unslotted content is assigned to the content variable by default. You can also
create slots named content, which behaves the same as leaving content
unslotted. This approach is useful if you want to apply a pipe or transformation
to a specific section of the content:
{{ layout "section.vto" }}
<p>Unslotted content</p>
{{ slot content |> toUpperCase}}
Uppercase content
{{ /slot }}
{{ /layout }}
Unclosed layouts
The closing tag {{ /layout }} is optional, and it's automatically added if
it's missing. This is a nice enhancement if you want to use a layout for the
entire page. For example:
{{ layout "./base.vto" {
title: "Page title",
} }}
{{ slot head }}
<script src="./index.js"></script>
{{ /slot }}
<h1>Hello world!</h1>
In this case the closing {{ /layout }} tag is added automatically at the end
of the page.