Text::Xslate::Syntax::TTerse - An alternative syntax compatible with Template Toolkit 2
use Text::Xslate;
my $tx = Text::Xslate->new(
syntax => 'TTerse',
);
print $tx->render_string(
'Hello, [% dialect %] world!',
{ dialect => 'TTerse' }
);
# PRE_PROCESS/POST_PROCESS
$tx = Text::Xslate->new(
syntax => 'TTerse',
header => ['header.tt'],
footer => ['footer.tt'],
);
TTerse is a subset of the Template-Toolkit 2 (and partially 3) syntax,
using [% ... %] tags and %% ... line code.
Note that TTerse itself has few methods and filters while Template-Toolkit 2
has a lot. See Text::Xslate::Bridge::* modules on CPAN which provide extra
methods and filters if you want to use those features.
(TODO: I should concentrate on the difference between Template-Toolkit 2 and
TTerse)
This supports a Template-Toolkit compatible syntax, although the details might be different.
Note that lower-cased keywords, which are inspired in Template-Toolkit 3,
are also allowed.
Scalar access:
[% var %]
[% $var %]
[% GET var # 'GET' is optional %]
Field access:
[% var.0 %]
[% var.field %]
[% var.accessor %]
[% var.$field ]%
[% var[$field] # TTerse specific %]
Variables may be HASH references, ARRAY references, or objects.
If $var is an object instance, you can call its methods.
[% $var.method() %]
[% $var.method(1, 2, 3) %]
[% $var.method(foo => [1, 2, 3]) %]
[% $var.method({ foo => 'bar' }) %]
Almost the same as the Text::Xslate::Syntax::Kolon manpage, but infix:<_> for
concatenation is supported for compatibility.
[% FOREACH item IN arrayref %]
* [% item %]
[% END %]
Loop iterators are partially supported.
[% FOREACH item IN arrayref %]
[%- IF loop.is_first -%]
<first>
[%- END -%]
* [% loop.index %] # 0 origin
* [% loop.count # loop.index + 1 %]
* [% loop.body # alias to arrayref %]
* [% loop.size # loop.body.size %]
* [% loop.max_index # loop.size - 1 %]
* [% loop.peek_next # loop.body[ loop.index + 1 %]
* [% loop.peek_prev # loop.body[ loop.index - 1 %]
[%- IF loop.is_last -%]
<last>
[%- END -%]
[% END %]
Unlike Template-Toolkit, FOREACH doesn't accept a HASH reference, so
you must convert HASH references to ARRAY references by keys(), values(), or kv() methods.
Template-Toolkit compatible names are also supported, but the use of them is
discouraged because they are not easy to understand:
loop.max # for loop.max_index
loop.next # for loop.peek_next
loop.prev # for loop.peek_prev
loop.first # for loop.is_first
loop.last # for loop.is_last
Loop control statements, namely NEXT and LAST, are also supported
in both FOR and WHILE loops.
[% FOR item IN data -%]
[% LAST IF item == 42 -%]
...
[% END -%]
[% IF logical_expression %]
Case 1
[% ELSIF logical_expression %]
Case 2
[% ELSE %]
Case 3
[% END %]
[% UNLESS logical_expression %]
Case 1
[% ELSE %]
Case 2
[% END %]
[% SWITCH expression %]
[% CASE case1 %]
Case 1
[% CASE case2 %]
Case 2
[% CASE DEFAULT %]
Case 3
[% END %]
[% var | f %]
[% f(var) %]
The INCLUDE statement is supported.
[% INCLUDE "file.tt" %]
[% INCLUDE $var %]
WITH variables syntax is also supported, although
the WITH keyword is optional in Template-Toolkit:
[% INCLUDE "file.tt" WITH foo = 42, bar = 3.14 %]
[% INCLUDE "file.tt" WITH
foo = 42
bar = 3.14
%]
The WRAPPER statement is also supported.
The argument of WRAPPER, however, must be string literals, because
templates will be statically linked while compiling.
[% WRAPPER "file.tt" %]
Hello, world!
[% END %]
%%# with variable
[% WRAPPER "file.tt" WITH title = "Foo!" %]
Hello, world!
[% END %]
The content will be set into content, but you can specify its name with
the INTO keyword.
[% WRAPPER "foo.tt" INTO wrapped_content WITH title = "Foo!" %]
...
[% END %]
This is a syntactic sugar to template cascading. Here is a counterpart of
the example in Kolon.
: macro my_content -> {
Hello, world!
: }
: cascade "file.tx" { content => my_content() }
Note that the WRAPPER option
(http://template-toolkit.org/docs/manual/Config.html#section_WRAPPER)
in Template-Toolkit is not supported directly. Instead, you can emulate
it with header and footer options as follows:
my %vpath = (
wrap_begin => '[% WRAPPER "base" %]',
wrap_end => '[% END %]',
base => 'Hello, [% content %] world!' . "\n",
content => 'Xslate',
);
my $tx = Text::Xslate->new(
syntax => 'TTerse',
path => \%vpath,
header => ['wrap_begin'],
footer => ['wrap_end'],
);
print $tx->render('content'); # => Hello, Xslate world!;
Definition:
[% MACRO foo BLOCK -%]
This is a macro.
[% END -%]
[% MACRO add(a, b) BLOCK -%]
[% a + b -%]
[% END -%]
Call:
[% foo() %]
[% add(1, 2) %]
Unlike Template-Toolkit, calling macros requires parens (()).
A few methods are supported in the Xslate core.
%% a.size();
%% a.join(", ");
%% a.reverse();
%% h.size();
%% h.keys();
%% h.values();
%% h.kv();
However, there is a bridge mechanism that allows you to use external methods.
For example, Text::Xslate::Bridge::TT2 provides the TT2 virtual methods for
Xslate, which bridges Template::VMethods implementation.
use Text::Xslate::Bridge::TT2;
my $tx = Text::Xslate->new(
syntax => 'TTerse',
module => [qw(Text::Xslate::Bridge::TT2)],
);
print $tx->render_string('[% "foo".length() %]'); # => 3
See the Text::Xslate::Bridge manpage, or search for Text::Xslate::Bridge::* on CPAN.
CALL evaluates expressions, but does not print it.
[% CALL expr %]
SET and assignments, although the use of them are strongly discouraged.
[% SET var1 = expr1, var2 = expr2 %]
[% var = expr %]
DEFAULT statements as a syntactic sugar to SET var = var // expr:
[% DEFAULT lang = "TTerse" %]
FILTER blocks to apply filters to text sections:
[% FILTER html -%]
Hello, <Xslate> world!
[% END -%]
There are some differences between TTerse and Template-Toolkit.
-
INCLUDE of TTerse requires an expression for the file name, while
that of Template-Toolkit allows a bare token:
[% INCLUDE foo.tt # doesn't work! %]
[% INCLUDE "foo.tt" # OK %]
-
FOREACH item = list is forbidden in TTerse. It must be FOREACH item IN list.
-
TTerse does not support plugins (i.e.
USE directive), but understands
the USE keyword as an alias to CALL, so you could use some simple
plugins which do not depend on the context object of Template-Toolkit.
use Template::Plugin::Math;
use Template::Plugin::String;
my $tt = Text::Xslate->new(...);
mt %vars = (
Math => Template::Plugin::Math->new(), # as a namespace
String => Template::Plugin::String->new(), # as a prototype
);
print $tt->render_string(<<'T', \%vars);
[% USE Math # does nothing actually, only for compatibility %]
[% USE String %]
[% Math.abs(-100) # => 100 %]
[% String.new("foo").upper # => FOO %]
-
The following directives are not supported:
INSERT, PROCESS, BLOCK as a named blocks, USE (but see above),
PERL, RAWPERL, TRY, THROW,
RETURN, STOP, CLEAR, META, TAGS, DEBUG, and VIEW.
Some might be supported in a future.
the Text::Xslate manpage
Template (Template::Toolkit)
the Template::Tiny manpage
the Text::Xslate::Bridge::TT2 manpage
the Text::Xslate::Bridge::TT2Like manpage
the Text::Xslate::Bridge::Alloy manpage
|