template-toolkit-0.1.0.1: Template Toolkit implementation for Haskell

Copyright(c) Dzianis Kabanau 2017
Maintainerkobargh@gmail.com
Safe HaskellSafe
LanguageHaskell2010

Text.TemplateToolkitLang

Contents

Description

Template Toolkit is a template processing system originally written in Perl by Andy Wardley. Below is the complete documentation of features implemented in Haskell version of the system. Original documentation is available here, but be warned that not all features are realized in Haskell version.

Synopsis

Tags

Character sequences [% %] are used to enclose directive tags within a template.

 Hello [% user.name %]!

If directive tag starts by [%- then all spaces before the tag are stripped. With -%] all spaces after the tag are removed.

Multiple directives may be enclosed within one tag. In this case they must be separated by ;

Comments are started by #

 [%
   FOREACH x = [0,15,100];
     x;     # Comments here
   END;
 %]

Variables

There are three types of variables implemented: SCALARS, ARRAYS and HASHES.

Dots are used to traverse hashes and arrays: [% my_hash.key1 %], [% my_array.0 %].

Arrays may be represented in range form: [% xs = [1..10] %]

Actually arrays and hashes are kind-of Perl's arrayrefs and hashrefs. So, for example, if two variables refer to one hash, modifying one variable affects another too. Assignment to undefined hashes and arrays autovivificates needed structures.

 [%
   # scalar
   int = 100;
   flt = 0.2;
   str = "Hello \"guest\""; # backslash is used to escape characters " ' \ $ and to type newlines \n and tabs \t.
   
   # array
   arr = [1,2,"three"];
   rng = [1..10];       # [1,2,3,4,5,6,7,8,9,10]
   
   # hash
   foo = {
     k1 => 1,
     k2 => "value 2",
     k3 => [1,2,3],
     k4 => {
        subk1 => 10,
        subk2 => 20,
     }
   };
   
   bar = foo.k4;
   bar.subk1 = "this is ten";
   foo.k4.subk1;        # 'this is ten'
   
   bazarray.10.k1 = 1; # autovivification of array 'bazarray' and hash 'bazarray.10'
   
 %]

Variables may be interpolated in double-quoted strings and in complex dotted variables (hashes or arrays).

$ character is used to precede interpolated variable: "$var". Complex variables may be enclosed in curly braces: "${myhash.k1.0}".

Single-qouted strings do not interpolate variables.

 [%
   i = 2;
   kbar = 'bar';
   arr = ['one','two','three','four','five'];
   hsh = {foo => 10, bar => 20};
   arr.$i; # 'three'
   "Foo is ${hsh.foo}.0";         # 'Foo is 10.0'
   hsh.$kbar; # 20
 %]

Operators

Arithmetic operators

 [%
   15 + 3.14;    # 18.14
   12 - 10;      # 2
   2 * 2;        # 4
   10 / 4;       # 2.5

   5 % 2;        # 1       modulus (remainder) of division
                 #         'mod' - synonym of '%'
   13 mod 5;     # 3

   +7;           # 7       unary positive
   -7;           # -7      unary negative
 %]

Logical operators

0 and empty strings are false values. Everything else is true. Internal representation of true/false is 1/0 respectively.

If both operands of comparison are strings, then they are compared as strings. Otherwise string operand is parsed as number.

 [%
   100 > 99;            # 1        true
   100 >= 101;          # 0        false
   100 < 100;           # 0        false
   100 <= 100;          # 1        true
   100 == 100;          # 1        true
   100 != 100;          # 0        false
   !0;                  # 1        unary negation
   
   "100" > 2;           # 1        true - numeric comparison
   "100" > "2";         # 0        false - string comparison
   
   0 || 100;            # 100
                        # 'or' - synonym of '||'
   30 or '';            # 30
   
   'fox' && 'dog';      # 'dog'
                        # 'and' - synonym of '&&'
   'fox' and "";        # 0        evaluates to false value
   
   # operations group with ( )
   ("string" && 0) ? "snow" : "rain";      # 'rain'
   # cond ? val_true : val_false          ternary condition operator
   # complex operands of ternary condition operator must be enclosed in parentheses:
   (!loop.last) ? 'not last' : 'last' # 'not last' or 'last'
   !loop.last ? 'not last' : 'last' # always evals to 0 - same as !(loop.last ? 'not last' : 'last')
 %]

String concatenation

Underscore _ separated by spaces is used to concatenate strings.

 [%
   name = "Zork";
   "Hello," _ name;        # 'Hello, Zork'
 %]

Directives

Conditionals

IF ... [ELSIF...] [ELSE...] END

[% IF user.name == 'root' %]

Hello, Admin!

[% ELSIF user.status > 1 %]

Welcome, master [% user.name %]!

[% ELSE %]

Hi, [% user.name %]!

[% END %]

Loops

FOREACH x = ... END

Special variable loop is used to save information about foreach loop and current iteration.

[% FOREACH i = [10..15] %]

 I is [% i %]

 [%
   IF i == 12;
     loop.index; # 2       current index
     loop.count; # 3       iteration count - index+1
     loop.first; # 10      first loop element
     loop.last;  # 15      last loop element
     loop.prev;  # 11      previous loop element
     loop.next;  # 13      next loop element
     loop.odd;   # 1       true if iteration count is odd
     loop.even;  # 0       true if iteration count is even
   END;
 %]

[% END %]

WHILE ... END

[%
  x = 1;
  WHILE x <= 20;

    "| X$x ";
    x = x + 1; IF x > 3; LAST; END;

    FOREACH y = [1..10];
      IF y > 2 && y < 9; NEXT; END;
      "y$y ";
    END;
    
  END;
  # Output: | X1 y1 y2 y9 y10 | X2 y1 y2 y9 y10 | X3 y1 y2 y9 y10
%]

LAST is used to immediately break current loop. NEXT - to skip to the next iteration.

Processing template files and blocks

PROCESS blockname_or_filename [var1 = ... var2 = ... varN = ...]

BLOCK blockname ... END

<html>
  [% PROCESS header.tt title = 'Homepage' descr = 'Homepage description' keyw = 'homepage,home,firstpage' %]

  <p>Hello, [% user.name %]!
  
  [% BLOCK foobarbazzer %]
    <p>Foo[% word %]barbaz
  [% END %]
  
  [%
    FOREACH w = ['fox', 'dog', 'cat'];
      PROCESS foobarbazzer word = w; # <p>Foofoxbarbaz <p>Foodogbarbaz <p>Foocatbarbaz
    END;
  %]
  
  [% PROCESS footer.tt %]
</html>

Variable may be passed to PROCESS or WRAPPER directive as a name using $: [% PROCESS $template %]

Wrapper

WRAPPER wrapper_block_or_filename [var1 = ... var2 = ... varN = ...] ... END

The WRAPPER block evaluates its content and passes the result in the variable content to wrapper_block_or_filename. This is very useful for web templates with the same skeleton.

FILE index.tt
[% WRAPPER html_wrap.tt title = 'Barbaz homepage!' %]
<p>Welcome to Barbaz home!
[% END %]


FILE html_wrap.tt
<html>
<head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <title>[% title %]</title>
</head>
<body>
[% content %]
</body>
</html>

Virtual methods

Virtual methods are applied to the variables to get new values or to modify array or hash variable.

[% my_array.size %] - Get the number of elements in my_array.

[% karr = my_hash.keys %] - Create array karr. The elements are the keys of my_hash.

[% my_array.push("Baz") %] - Modify array my_array appending scalar "Baz" to the end of the array.

Methods that use regular expressions are based on pcre patterns, e.g. [% bar.match('(?i)^baz\\d$') %].

Below is the list of implemented virtual methods. You can also take a look at the original documentation: Template Toolkit VMethods.

Scalar vmethods

.collapse
Returns the string with trailing and leading spaces removed and internal multiple spaces converted to single space.
.defined
Returns true if the value is defined.
.lcfirst
Returns the string with first character converted to lower case.
.length
Returns the length of the string.
.lower
Returns the string converted to lower case.
.match(pattern, global)
Returns the array of captured substrings from regexing target string with pattern. If pattern-match fails, returns false. Optional global is used for global pattern-match to return all captured substrings.
.replace(old, new)
Returns the string with all occurrences of old replaced by new.
.split(pattern)
Returns the array produced by splitting the string by pattern.
.trim
Returns the string with leading and trailing spaces removed.
.ucfirst
Returns the string with first character converted to upper case.
.upper
Returns the string converted to upper case.

Array vmethods

.first
Returns the first element of the array.
.grep(pattern)
Returns the array of elements that match pattern.
.import(arr1, arr2, arrN)
Imports to the target array elements of all passed arrays. Target array is modified.
.join(separator)
Returns the string created by joining all elements of the array separated by separator.
.last
Returns the last element of the array.
.nsort
Returns the array sorted numerically.
.pop
Removes the last element from the array. Target array is modified.
.push(el1, el2, elN)
Appends element(s) to the end of the array. Target array is modified.
.reverse
Returns reversed version of the array.
.shift
Removes the first element from the array. Target array is modified.
.size
Returns the number of elements in the array.
.slice(from, to)
Returns the array of elements idexing in the range from..to of the original array. If to is omitted, then to the last element.
.sort
Returns the array sorted alphabetically.
.splice(offset,length,insertarray)
Powerful array-modification method that behaves just like Perl's splice. Removes from the array length elements starting from offset index, replacing them with insertarray. If insertarray is omitted - just removes elements. If length is omitted removes everything up to the end of the array. length may be 0 - no elements are removed. offset may be negative - counts index from the end of the array, e.g. -2 - penultimate element's index. Target array is modified.
.unique
Returns the array of only unique elements.
.unshift(el1, el2, elN)
Prepends element(s) to the beginning of the array. Target array is modified.

Hash vmethods

.delete(key1, key2, keyN)
Deletes items identified by the keys from the hash. Target hash is modified.
.each
Returns keys and values of the hash in one array - [key1, val1, key2, val2, ... keyN, valN].
.keys
Returns the array of the hash keys.
.import(hash1, hash2, hashN)
Imports to the target hash items of all passed hashes. Existing items get new values, new items are added. Target hash is modified.
.item(key)
Returns the value of hash item identified by key. This is useful to get values with keys that contain any characters. E.g. [% hash.item('complex $ key.') %] or [% hash.item('12') %].
.pairs
Returns the array of key-value pairs of the hash. The pairs are hashes each with two keys: key and value.
.size
Returns the number of items in the hash.
.values
Returns the array of the hash values.

Sometimes a hash may have items whith keys that conflict with the above method names. In this situation parentheses may be used to force method call.

[%
  my_car = {
    'keys' => 'lost',
    'mileage' => 150000,
  };
  my_car.keys; # 'lost'
  my_car.keys(); # ['keys', 'mileage']
%]

Filters

Filters transform text of a block. Filter may be applied as a directive:

FILTER filter_name ... END

Or in piped form (multiple filters may be chained):

expr | filter_name [| filter_name]/

[% FILTER collapse %]
[% PROCESS body.tt %]
[% END %]

The same:

[% PROCESS body.tt | collapse %]

Below is the list of implemented filters.

collapse
Removes leading and trailing spaces. Internal multiple spaces are converted to single space.
html
Replaces all <, >, &, " with &lt;, &gt;, &amp;, &quot; respectively.
lcfirst
Converts the first character to lower case.
lcfirst
Converts all characters to lower case.
null
Discards the text of block
replace(old, new)
Replaces all occurrences of old with new.
trim
Removes leading and trailing spaces.
ucfirst
Converts the first character to upper case.
upper
Converts all characters to upper case.
uri
URI-encodes text.