template-toolkit-0.1.1.0: Template Toolkit implementation for Haskell

Copyright(c) Dzianis Kabanau 2018
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.