Text::Xslate::Syntax::Kolon - The default template syntax
use Text::Xslate; my $tx = Text::Xslate->new( syntax => 'Kolon', # optional ); print $tx->render_string( 'Hello, <: $dialect :> world!', { dialect => 'Kolon' } );
Kolon is the default syntax, using <: ... :> tags and : ... line code.
<: ... :>
: ...
Variable access:
<: $var :>
Field access:
<: $var.0 :> <: $var.field :> <: $var.accessor :> <: $var["field"] :> <: $var[0] :>
Variables may be HASH references, ARRAY references, or objects. Because $var.field and $var["field"] are the same semantics, $obj["accessor"] syntax may be call object methods.
$var.field
$var["field"]
$obj["accessor"]
Special:
: nil # indicates "nothing" : true # as the integer 1 : false # as the integer 0
String:
: "foo\n" # the same as perl : 'foo\n' # the same as perl
Number:
: 42 : 3.14 : 0xFF : 0b1010
Array:
: for [1, 2, 3] -> $i { ... }
Hash:
: foo({ foo => "bar" })
{ ... } is always parsed as hash literals, so you need not to use prefix + as Perl sometimes requires:
{ ... }
+
: {}.kv(); # ok : +{}.kv(); # also ok
Conditional operator (?:):
?:
: $var.value == nil ? "nil" : $var.value
Relational operators (== != < <= > >=):
== != < <= > >=
: $var == 10 ? "10" : "not 10" : $var != 10 ? "not 10" : "10"
Note that == and != are similar to Perl's eq and ne except that $var == nil is true iff $var is uninitialized, while other relational operators are numerical.
==
!=
eq
ne
$var == nil
Arithmetic operators (+ - * / % min max):
+ - * / % min max
: $var * 10_000 : ($var % 10) == 0 : 10 min 20 min 30 # 10 : 10 max 20 max 30 # 30
Bitwise operators (prefix:<+^> +& +| +^)
prefix:<+^> +& +| +^
: 0x1010 +| 0x3200 # bitwise or: 0x3210 : 0x1010 +& 0x3200 # bitwise and: 0x1000 : 0x1010 +^ 0x3200 # bitwise xor: 0x0210 : +^0x1010 # bitwise neg: 0xFFFFEFEF (on 32 bit system)
Logical operators (! && || // not and or)
! && || // not and or
: $var >= 0 && $var <= 10 ? "ok" : "too smaller or too larger" : $var // "foo" # as a default value
String operators (~)
~
: "[" ~ $var ~ "]" # concatination
The operator precedence is very like Perl's:
. () [] ! prefix:<+> prefix:<-> prefix:<+^> * / % +& + - ~ +| +^ prefix:<defined> < <= > >= == != | && || // min max ?: not and or
You can define lexical constants with constant, which requires a bare name, and my, which requires a variable name.
constant
my
: constant FOO = 42; : my $foo = 42;
These two statements has the same semantics, so you cannot modify $foo.
$foo
: my $foo = 42; $foo = 3.14; # compile error!
There is for loops that are like Perl's foreach.
for
foreach
: # $data must be an ARRAY reference : for $data -> $item { [<: $item.field :>] : }
You can get the iterator index in for statements as $~ITERATOR_VAR:
$~ITERATOR_VAR
: for $data -> $item { : if ($~item % 2) == 0 { Even (0, 2, 4, ...) : } : else { Odd (1, 3, 5, ...) : } : }
$~item is a pseudo object, so you can access its elements via the dot-name syntax.
$~item
: for $data -> $i { : $~i # iterator index (0, 1, 2, ...) : $~i.index # the same as $~i : $~i.count # the same as $~i + 1 : if ($~i.index % 2) == 0 { even : } : else { odd : } : $i~.cycle("even", "odd") # => "even" -> "odd" -> "even" -> "odd" ... : }
Supported iterator elements are index :Int, count :Int, body : ArrayRef, size : Int, max_index :Int, is_first :Bool, is_last :Bool, peek_next :Any, peek_prev :Any, cycle(...) :Any.
index :Int
count :Int
body : ArrayRef
size : Int
max_index :Int
is_first :Bool
is_last :Bool
peek_next :Any
peek_prev :Any
cycle(...) :Any
while loops are also supported in the same semantics as Perl's:
while
: # $obj might be an iteratable object : while $dbh.fetch() -> $item { [<: $item.field :>] : }
while defined expr -> $item is interpreted as while defined(my $item = expr) for convenience.
while defined expr -> $item
while defined(my $item = expr)
: while defined $obj.fetch() -> $item { [<: $item # $item can be false-but-defined:>] : }
There are if-else and given-when conditional statements.
if-else
given-when
if-else:
: if $var == nil { $var is nil. : } : else if $var != "foo" { # elsif is okay $var is not nil nor "foo". : } : else { $var is "foo". : } : if( $var >= 1 && $var <= 10 ) { $var is 1 .. 10 : }
Note that if doesn't require parens, so the following code is okay:
if
: if ($var + 10) == 20 { } # OK
given-when(also known as switch statement):
: given $var { : when "foo" { it is foo. : } : when ["bar", "baz" ] { it is either bar or baz. : } : default { it is not foo nor bar. } : }
You can specify the topic variable.
: given $var -> $it { : when "foo" { it is foo. : } : when $it == "bar" or $it == "baz" { it is either bar or baz. : } : }
You can register functions via function or module options for Text::Xslate->new().
function
module
Text::Xslate->new()
Once you have registered functions, you can call them with the () operator. infix:<|> is also supported as a syntactic sugar to ().
()
infix:<|>
: f() # without args : f(1, 2, 3) # with args : 42 | f # the same as f(42)
Functions are Perl's subroutines, so you can define dynamic functions:
# code sub mk_indent { my($prefix) = @_; return sub { my($str) = @_; $str =~ s/^/$prefix/xmsg; return $str; } } my $tx = Text::Xslate->new( function => { indent => \&mk_indent, }, ); :# template : $value | indent("> ") : indent("> ")($value)
There are several builtin functions, which you cannot redefine:
: $var | mark_raw # marks it as a raw string : $var | raw # synonym to mark_raw : $var | unmark_raw # removes "raw" marker from it : $var | html # does html-escape to it and marks it as raw : $var | dump # dumps it with Data::Dumper
Note that you should not use mark_raw in templates because it can make security hole easily just like as type casts in C. If you want to generate HTML components dynamically, e.g. by HTML form builders, application code should be responsible to make strings as marked raw.
mark_raw
raw
When $var is an object instance, you can call its methods with the dot operator.
<: $var.method() :> <: $var.method(1, 2, 3) :> <: $var.method( foo => [ 1, 2, 3 ] ) :>
There is an autoboxing mechanism that provides primitive types with builtin methods.
For any primitive types:
# note that if $any is an object, defined() will return nil # unless the object has defined() method. <: $any.defined() :>
For arrays:
<: $array.size() :> <: $array.join(",") :> <: $array.reverse() :> <: $array.map(-> $x { $x + 1 }) :> <: $array.sort(-> $x, $y { $x <=> $y }) :> <: $array.reduce(-> $x, $y { $x min $y }) :>
For hashes:
<: $hash.size() :> <: $hash.keys() # sorted by keys :> <: $hash.values() # sorted by keys :> <: for $hash.kv() -> $pair { # sorted by keys :> <: # $pair is a pair type with 'key' and 'value' fields -:> <: $pair.key :> = <: $pair.value :> <: } :>
You can define more methods with the function option. See Text::Xslate.
Template inclusion is a traditional way to extend templates.
: include "foo.tx"; : include "foo.tx" { var1 => value1, var2 => value2, ... };
Xslate templates may be recursively included, but the including depth is limited to 100.
Template cascading is another way to extend templates other than include.
include
First, make base templates myapp/base.tx:
: block title -> { # with default [My Template!] : } : block body -> { } # without default
Then extend from base templates with the cascade keyword:
cascade
: cascade myapp::base : cascade myapp::base { var1 => value1, var2 => value2, ...} : cascade myapp::base with myapp::role1, myapp::role2 : cascade with myapp::role1, myapp::role2
In derived templates, you may extend templates (e.g. myapp/foo.tx) with block modifiers before, around (or override) and after.
before
around
override
after
: # cascade "myapp/base.tx" is also okay : cascade myapp::base : # use default title : around body -> { My template body! : }
And, make yet another derived template myapp/bar.tx:
: cascade myapp::foo : around title -> { -------------- : super -------------- : } : before body -> { Before body! : } : after body -> { After body! : }
Then render it as usual.
my $tx = Text::Xslate->new( file => 'myapp/bar.tx' ); $tx->render({});
The result is something like this:
-------------- [My Template!] -------------- Before body! My template tody! After body!
You can also cascade templates just like Moose's roles:
: cascade myapp::base with myapp::role1, myapp::role2
You can omit the base template.
Given a file myapp/hello.tx:
: around hello -> { -------------- : super -------------- : }
Then the main template:
: cascade with myapp::hello : block hello -> { Hello, world! : }
Output:
-------------- Hello, world! --------------
In fact, you can omit the base template, and components can include any macros.
Given a file common.tx
: macro hello -> $lang { Hello, <: $lang :> world! : } : around title -> { -------------- : super -------------- : }
The main template:
: cascade with common : block title -> { Hello, world! : } : hello("Xslate")
-------------- Hello, world! -------------- Hello, Xslate world!
There is a limitation that you cannot pass variables to the cascade keyword, because template cascading is statically processed.
Macros are supported, which are called in the same way as functions and return a raw string. Macros returns what their bodies render, so macros cannot returns references nor objects including other macros.
: macro add ->($x, $y) { : $x + $y; : } : add(10, 20) : macro signeture -> { This is foo version <: $VERSION :> : } : signeture() : macro factorial -> $x { : $x == 0 ? 1 : $x * factorial($x-1) : } : factorial(1) # as a function : 1 | factorial # as a filter
If you want to html-escape the return values of macros, you can use unmark_raw to remove raw-ness from the values.
unmark_raw
raw-ness
: macro em -> $s { <em><: $s :></em> : } : em("foo") # renders "<em>foo</em>" : em("foo") | unmark_raw # renders "<em>foo<em>"
Macros are first-class objects, so you can bind them to symbols.
<: macro foo -> { "foo" } macro bar -> { "bar" } my $dispatcher = { foo => foo, bar => bar, }; -:> : $dispatcher{$key}()
Anonymous macros are also supported, although they can return only strings.
<: -> $x, $y { $x + $y }(1, 2) # => 3 :>
The block keyword is used to make a group of template code, and you can apply filters to that block with infix:<|>. Here is an example to embed HTML source code into templates.
block
Template: : block source | unmark_raw -> { <em>Hello, world!</em> : }
Output: <em>Hello, world!</em>
See also "Using FillInForm" in Text::Xslate::Cookbook for another example to use this block filter syntax.
Comments start from # to a new line or semicolon.
#
:# this is a comment <: # this is also a comment $foo # $foo is rendered :> <: $bar # this is ok :> <: # this is comment; $baz # $baz is rendered :>
Text::Xslate
Text::Xslate::Cookbook
To install Text::Xslate, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Text::Xslate
CPAN shell
perl -MCPAN -e shell install Text::Xslate
For more information on module installation, please visit the detailed CPAN module installation guide.