NAME

Text::Xslate::Syntax::Kolon - The default template syntax

SYNOPSIS

use Text::Xslate;
my $tx = Text::Xslate->new(
    syntax => 'Kolon', # optional
);

print $tx->render_string(
    'Hello, <: $dialect :> world!',
    { dialect => 'Kolon' }
);

DESCRIPTION

Kolon is the default syntax, using <: ... :> tags and : ... line code.

SYNTAX

Variable access

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.

If $var is an object instance, you can call its methods.

<: $var.method() :>
<: $var.method(1, 2, 3) :>

Expressions

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

Arithmetic operators (+ - * / % min max):

: $var * 10_000
: ($var % 10) == 0
: 10 min 20 min 30 # 10
: 10 max 20 max 30 # 30

Logical operators (! && || // not and or)

: $var >= 0 && $var <= 10 ? "ok" : "too smaller or too larger"
: $var // "foo" # as a default value

String operators (~)

: "[" ~ $var ~ "]" # concatination

Operator precedence is the same as Perl's:

. () []
* / %
+ - ~
< <= > >=
== !=
|
&&
|| // min max
?:
not
and
or

Loops

There are for and while loops.

: # $data must be an ARRAY reference
: for $data -> $item {
    [<: $item.field :>]
: }

: # $obj must be an iteratable object
: while $obj.fetch -> $item {
    [<: $item.field :>]
: }

while statements are not the same as Perl's. In fact, the above Xslate while code is the same as the following Perl while code:

while(defined(my $item = $obj->fetch)) {
    ...
}

Conditional statements

There are if-else and given-when conditional statements.

if-else:

: if $var == nil {
    $var is nil.
: }
: else if $var != "foo" { # elsif ... is okey
    $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:

: if ($var + 10) == 20 { } # OK

given-when:

: given $var {
:   when "foo" {
        it is foo.
:   }
:   when "bar" {
        it is bar.
:   }
:   default {
        it is not foo nor bar.
    }
: }

Note that you can use the topic variable.

: given $var -> $it {
:   when "foo" {
        it is foo.
:   }
:   when $it == "bar" or $it == "baz" {
        it is bar or baz.
:   }
: }

Functions and filters

Once you have registered functions, you can call them with () or |.

: f()        # without args
: f(1, 2, 3) # with args
: 42 | f     # the same as f(42)

Dynamic functions/filters:

# 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)

Template inclusion

Template inclusion is a traditional way to extend templates.

: include "foo.tx"

Xslate templates may be recursively included, but including depth is limited to 100.

Template cascading

Template cascading is another way to extend templates other than include.

: cascade myapp::base
: cascade myapp::base with myapp::role1, myapp::role2
: cascade with myapp::role1, myapp::role2

You can extend templates with block modifiers.

Base templates myapp/base.tx:

: block title -> { # with default
    [My Template!]
: }

: block body -> {;} # without default

Another derived template myapp/foo.tx:

: # cascade "myapp/base.tx" is also okey
: cascade myapp::base
: # use default title
: around body -> {
    My template body!
: }

Yet another derived template myapp/bar.tx:

: cascade myapp::foo
: around title -> {
    --------------
    : super
    --------------
: }
: before body -> {
    Before body!
: }
: after body -> {
    After body!
: }

Then, Perl code:

my $tx = Text::Xslate->new( file => 'myapp/bar.tx' );
$tx->render({});

Output:

--------------
[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!
--------------

Macro blocks

: 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)
: }

Note that return values of macros are values that their routines renders. That is, macros themselves output nothing.

SEE ALSO

Text::Xslate