藤 吾郎 > Text-Xslate-2.0002 > Text::Xslate::Manual::Cookbook

Download:
Text-Xslate-2.0002.tar.gz

Annotate this POD

Website

View/Report Bugs
Source   Latest Release: Text-Xslate-3.2.5

NAME ^

Text::Xslate::Manual::Cookbook - How to cook Xslate templates

DESCRIPTION ^

The Xslate cookbook is a set of recipes showing Xslate features.

RECIPES ^

How to manage HTML forms

Managing HTML forms is an important issue on web applications. You'd better to use modules that manage HTML forms, rather than do something with templates by yourself. This section proposes two basic solutions: using FillInForm and HTML form builders.

In both solutions, one should not use the mark_raw filter in templates, which easily makes security holes. Instead, application code should be responsible to call the mark_raw function that Text::Xslate can export.

Using FillInForm

One solution to manage HTML forms is to use FillInForm modules with the block filter syntax.

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="&lt;filled value&gt;" />
    </form>

Because HTML::FillInForm::Lite provides fillinform function, it becomes more simple:

    use HTML::FillInForm::Lite qw(fillinform);

    my $tx = Text::Xslate->new(
        function => { fillinform => html_builder(\&fillinform) },
    );

From 1.5018 on, html_builder_module are supported for HTML builder modules like HTML::FillInForm. Just import HTML builder functions with 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 such cases, all you have to do is to apply mark_raw() to HTML parts.

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="&lt;Xslate&gt;" />
    </p>
    </body>
    </html>

See also HTML::Shakan for details.

How to use Template Toolkit's WRAPPER feature in Kolon

Use template cascading, which is a super-set of the WRAPPER directive.

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 allows you to extend templates with block modifiers. It is like traditional template inclusion, but is more powerful.

This mechanism is also called as template inheritance.

See also "Template cascading" in Text::Xslate.

How to map __DATA__ sections to the include path

Use Data::Section::Simple, and the path option of new(), which accepts HASH references which contain $file_name => $content mapping.

    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.

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 by yourself when you put data into <script> ... </script> sections.

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 for this aim.

    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.

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.

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.

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 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 ...

How to pre-process templates?

You can override slurp_template() in Text::Xslate to process contents before parsing them:

    {
        package MyTemplate;
        use parent qw(Text::Xslate);

        sub slurp_template {
            my($self, $input_layer, $fullpath) = @_;

            my $content = $self->SUPER::slurp_template(
                            $input_layer,
                            $fullpath,
            );
            ### process $content ###
            return $content;
        }
    }

The first argument $self is an Text::Xslate instance; the second is the argument of input_layer option (default to :utf8); the third is the full path of a template file to load.

slurp_template may return both text strings and byte strings.

Note that this hook is provided for pre-processing template contents, so you should call SUPER::slurp_template to load templates into the memory.

SEE ALSO ^

Text::Xslate

Text::Xslate::Manual

Text::Xslate::Manual::FAQ

syntax highlighting: