Text::...okbook(3pm)
π Text::Xslate::Manual::Cookbook (3pm) β the recipe book, but make it cute
okay so bestie, this is the cookbook page from the Text::Xslate manual, straight out of the User Contributed Perl Documentation section. Think of it as the group chat where Xslate shows you how to actually cook with it. π
πΈ NAME πΈ
Text::Xslate::Manual::Cookbook β how to cook Xslate templates, fr fr. π
β¨ DESCRIPTION β¨
The Xslate cookbook is literally just a set of recipes showing off Xslate features. no cap. π
π RECIPES π
π§ How to manage HTML forms
Managing HTML forms is a whole thing for web apps, bestie. and the vibe check says: you're way better off using modules that manage HTML forms than raw-dogging it yourself in your templates. π this section proposes two basic solutions β using FillInForm, and using HTML form builders.
In both solutions: do not use the mark_raw filter in templates, because that easily creates security holes. instead, your application code should be the one responsible for calling the mark_raw function that Text::Xslate can export. periodt. π«Ά
π¦ Using FillInForm
One solution to manage HTML forms is to use FillInForm modules with the block filter syntax. iconic.
Example code using HTML::FillInForm:
#!perl -w
use strict;
use Text::Xslate qw(html_builder);
use HTML::FillInForm; # HTML::FillInForm::Lite is okay
sub fillinform {
my($q) = @_;
my $fif = HTML::FillInForm->new();
return html_builder {
my($html) = @_;
return $fif->fill(\$html, $q);
};
}
my $tx = Text::Xslate->new(
function => {
fillinform => \&fillinform,
},
);
my %vars = (
q => { foo => "<filled value>" },
);
print $tx->render_string(<<'T', \%vars);
FillInForm:
: block form | fillinform($q) -> {
<form>
<input type="text" name="foo" />
</form>
: }
T
Output:
FillInForm:
<form>
<input type="text" name="foo" value="<filled value>" />
</form>
Because HTML::FillInForm::Lite provides a fillinform function, it becomes even simpler β slay:
use HTML::FillInForm::Lite qw(fillinform);
my $tx = Text::Xslate->new(
function => { fillinform => html_builder(\&fillinform) },
);
From 1.5018 on, html_builder_module is supported for HTML builder modules like HTML::FillInForm. Just import HTML builder functions with the html_builder_module option. β¨
my $tx = Text::Xslate->new(
html_builder_module => [ 'HTML::FillInForm::Lite' => [qw(fillinform)] ],
);
See also HTML::FillInForm or HTML::FillInForm::Lite for details. π
π Using HTML form builders
Another solution to manage HTML forms is to use form builders. In those cases, all you have to do is apply mark_raw() to HTML parts. that's it. that's the whole job.
Here is a PSGI application that uses HTML::Shakan:
#!psgi
use strict;
use warnings;
use Text::Xslate qw(mark_raw);
use HTML::Shakan;
use Plack::Request;
my $tx = Text::Xslate->new();
sub app {
my($env) = @_;
my $req = Plack::Request->new($env);
my $shakan = HTML::Shakan->new(
request => $req,
fields => [ TextField(name => 'name', label => 'Your name: ') ],
);
my $res = $req->new_response(200);
# do mark_raw here, not in templates
my $form = mark_raw($shakan->render());
$res->body( $tx->render_string(<<'T', { form => $form }) );
<!doctype html>
<html>
<head><title>Building form</title></head>
<body>
<form>
<p>
Form:<br />
<: $form :>
</p>
</body>
</html>
T
return $res->finalize();
}
return \&app;
Output:
<!doctype html>
<html>
<head><title>Building form</title></head>
<body>
<form>
<p>
Form:<br />
<label for="id_name">Your name</label>
<input id="id_name" name="name" type="text" value="<Xslate>" />
</p>
</body>
</html>
See also HTML::Shakan for details. π
π How to use Template Toolkit's WRAPPER feature in Kolon
Use template cascading, bestie β it's a super-set of the WRAPPER directive. lowkey better.
wrapper.tx:
<div class="wrapper">
block content -> { }
</div>
content.tx
: cascade wrapper
: override content -> {
Hello, world!
: }
Output:
<div class="wrapper">
Hello, world!
</div>
π« Template cascading
Xslate supports template cascading, which lets you extend templates with block modifiers. It's like traditional template inclusion, but more powerful. it's giving glow-up. π₯
This mechanism is also called template inheritance.
See also "Template cascading" in Text::Xslate. π
π§ How to map __DATA__ sections to the include path
Use Data::Section::Simple, plus the path option of new(), which accepts HASH references containing a $file_name => $content mapping. obsessed with this trick ngl.
use Text::Xslate;
use Data::Section::Simple;
my $vpath = Data::Section::Simple->new()->get_data_section();
my $tx = Text::Xslate->new(
path => [$vpath],
);
print $tx->render('child.tx');
__DATA__
@@ base.tx
<html>
<body><: block body -> { :>default body<: } :></body>
</html>
@@ child.tx
: cascade base;
: override body -> {
child body
: } # endblock body
This feature is directly inspired by Text::MicroTemplate::DataSection, and originated from Mojolicious. main character energy from day one. π
See also Data::Section::Simple, Text::MicroTemplate::DataSection, and Mojolicious. π¦
π How to interpolate data into JavaScript sections without XSS
Because Xslate escapes only HTML meta characters, you must escape JavaScript meta characters yourself when you put data into <script> ... </script> sections. you. yes you. π
The JSON module is not suitable because it doesn't escape some meta characters such as </script>.
It is better to use utilities proven to be secure for JavaScript escaping to avoid XSS. JavaScript::Value::Escape helps you in this regard. πΈ
my $tx = Text::Xslate->new(
module => ['JavaScript::Value::Escape' => [qw(js)]],
);
my %params = (
user_input => '</script><script>alert("XSS")</script>',
);
print $tx->render_string(<<'T', \%params);
<script>
document.write('<: $user_input | html | js :>');
var user_input = '<: $user_input | js :>';
</script>
T
You'd better to consult the security experts on more complex cases. fr fr, ask the professionals. π
π‘οΈ How to interpolate structured texts into HTML without XSS
There's no silver bullet to parse structured texts in secure ways. You'd better to consult the security experts to do so. no shortcuts, bestie. π
Some CPAN module might help you. See String::Filter for example.
π How to manage localization in templates
You can register any functions including _(), so no specific techniques are required. easy peasy. β¨
For example:
use I18N::Handle;
# I18N::Handle installs the locale function "_" to the global namespace.
# (remember the symbol *_ is global)
I18N::Handle->new( ... )->speak('zh_tw');
my $tx = Text::Xslate->new(
function => {
_ => \&_,
},
);
Then in your templates:
<: _('Hello %1', $john ) :>
See also: I18N::Handle, App::I18N. π
π° How to load templates before fork()ing?
It is a good idea to load templates in preforking-model applications. Here is an example to load all the templates which is in a given path:
use File::Find;
my $path = ...;
my $tx = Text::Xslate->new(
path => [$path],
cache_dir => $path,
);
# pre-load files
find sub {
if(/\.tx$/) {
my $file = $File::Find::name;
$file =~ s/\Q$path\E .//xsm; # fix path names
$tx->load_file($file);
}
}, $path;
# fork and render ...
load it before you fork, so every child gets the goods. π
π SEE ALSO π
Text::XslateText::Xslate::ManualText::Xslate::Manual::FAQ
and that's the whole cookbook, bestie!! π«Ά this page is perl v5.42.3, dated 2026-08-22, served up fresh from the good folks who contribute to Perl's documentation. go forth and render responsibly. π β¨π
π¦ where this page comes from
- ubuntu stonking: libtext-xslate-perl 3.5.9-2build2 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms