Cro

Cro::WebApp::Template

Templates are typically used to render some data into HTML. The template engine is designed with HTML in mind, and takes care to escape data as it should be escaped in HTML. Templates are compiled, typically on first use, for efficient rendering. The template language includes conditionals, iteration, subroutines, modules, and a number of other features.

Templates are typically stored either as files and referenced by path, or as resources (the latter being useful if the web application should be possible to install as a Raku distribution, for example using zef).

This document covers how to produce HTTP responses by rendering templates and how templates are located; further documents cover:

Basic usage from a Cro route block§

First, add the following use statement to the module containing the route block that you wish to use templates in:

use Cro::WebApp::Template;

Then, to produce a rendered template as the HTTP response, call template, passing the path to the template and, optionally, the data that the template should render:

get -> 'product', Int $id {
    my $product = $repository.lookup-product($id);
    template 'templates/product.crotmp', $product;
}

This is short for:

get -> 'product', Int $id {
    my $product = $repository.lookup-product($id);
    content 'text/html', render-template 'templates/product.crotmp', $product;
}

Where render-template renders the template and returns the result of doing so, and content is from Cro::HTTP::Router and sets the content type of the response along with the body.

While by default template sets a content type of text/html; this can be changed by passing the content-type named argument:

get -> 'product', Int $id {
    my $product = $repository.lookup-product($id);
    template 'templates/product.crotmp', $product,
        content-type => 'text/plain';
}

Template locations§

Templates may be served from files on disk or from distribution resources (the %?RESOURCES hash). Search locations for templates may be configured either at a route block level or globally (resources only at route-block level).

The global search location list starts out containing the current working directory. To add further template search locations using files, call the template-location function.

my $app = route {
    template-location 'templates/';

    get -> {
        # Will look for templates/index.crotmp first
        template 'index.crotmp';
    }
}

When template-location is called in a route block, it is scoped to the route handlers within that block and will also be considered by any route blocks that we include into this one (but not those we delegate to). When template-location is called outside of a route block, it adds to the global search paths. The search order is:

1. Any tempalate-locations in the current route block, tried in the order they were added 2. Any template-locations in route blocks that include us, transitively, innermost first 3. Any global template-locations

To serve templates from resources, first the resources should be associated with the enclosing route block using resources-from %?RESOURCES (this is not part of the template system, but rather a general mechanism of route blocks). Then, templates-from-resources should be called to indicate that the resources should be considered when searching for templates.

my $app = route {
    resources-from %?RESOURCES;
    templates-from-resources;
    get -> {
        template 'templates/index.crotmp'
    }
}

Applications using resources will often have many kinds of resource, and are likely to put templates in a directory within the resources. One can avoid having to write the templates/ prefix repeatedly by specifying it when calling the templates-from-resources function:

my $app = route {
    resources-from %?RESOURCES;
    templates-from-resources prefix => 'templates';
    get -> {
        template 'index.crotmp'
    }
}

Template auto-reload§

Templates are compiled on first use and cached for the rest of the process lifetime. To have them recompiled automatically on changes, set CRO_DEV=1 in the environment. This is useful in development for avoiding application restarts.

Template compilation§

Sometimes it may be desirable to compile all templates in advance. Passing :compile-all to the template-location function will immediately compile all of the templates and die if there are any errors. This could be put into a test case:

use Cro::WebApp::Template;
use Test;

lives-ok { template-location 'templates/', :compile-all },
    'All templates have valid syntax';

done-testing;