htmltmpl: templating engine for separation of code and HTML

This is a description of the templating language used by htmltmpl.


HTML::Template compatibility

Templates created for HTML::Template can be used with this engine in case they do not violate character case rules of htmltmpl.

WARNING: Template statements and their parameters must always be in uppercase. Variable names must always be in lowercase. Loop names must be in lowercase, but capitalized.

WARNING: All included templates must be located in a directory named 'inc' which must be a subdirectory of the directory in which the main template file is located. You must refer to these templates only by their filename, ie. without the 'inc' part of the path.

This engine offers all features of HTML::Template except:

The engine also offers some additional features:


Syntax overview

Statements

The control statements of the templating language look like HTML tags. They can be written in two forms:

There must be exactly one space after the opening "<!--" and before the closing "-->" if you use the longer form.

All statements except TMPL_VAR should be placed on a separate line.

All tabs and spaces on a line before a statement are removed, if there are no other characters except tabs and spaces between beginning of the line and the statement.

A trailing newline after a statement is removed if there are no other characters between the newline and the statement.

The white-space removing described above is a Good Thing, because it keeps the HTML nicely formatted, especially when loops are involved. If you want to preserve the newline after a statement, just add a space or a tab after the statement.

The statements do not need to follow HTML validity rules. For example, following usage of TMPL_VAR is absolutely valid:

    
            <img src="<TMPL_VAR image>" />
    

Unrecognized TMPL_* statements are detected and TemplateError is raised when one is found.

Statements must be completely in uppercase: for example "TMPL_VAR". It improves readability of the templates a lot. It makes the statements easily distinguishable from normal XHTML tags, that are always in lowercase.

Templates must not contain the '\0' character (ASCII code zero).


Parameters of the statements

Parameters can be written in two forms:

There must not be any space between the "=" character and the name or the value of the parameter.

Parameter names must be completely in uppercase: ESCAPE="HTML".

Predefined special values of parameters (like for example the "HTML", "URL" and "NONE" values of the ESCAPE parameter) must be completely in uppercase.

Parameter names and values can contain only alphanumeric characters (non-locale) plus some additional characters: dash, dot, underscore, colon, slash, backslash. They must NOT contain any spaces.


Identifiers

There are three types of identifiers:

Names of loops and variables can contain ASCII (non-locale) alphanumeric characters, underscores and dashes. Names of loops and variables are further restricted by the character case rules described below.

Template filenames in TMPL_INCLUDE statements can contain only the same characters that are allowed in values of parameters(see above). They must NOT contain any spaces.

Minimum length of an identifier is one character. Names of variables and loops can be specified in two ways:

Following character case rules apply to the names of variables and loops:


Valid statements and parameters

TMPL_INCLUDE NAME
TMPL_VAR NAME, ESCAPE, GLOBAL
TMPL_IF NAME, GLOBAL
TMPL_UNLESS NAME, GLOBAL
TMPL_ELSE  
/TMPL_IF  
/TMPL_UNLESS  
TMPL_LOOP NAME
/TMPL_LOOP  
TMPL_BOUNDARY  
TMPL_STATIC NAME, ESCAPE


Template comments

Comments are in form of "### some comment". Everything that follows these four characters - "### " - is removed before the template is processed. The ending space in "### " IS significant. Comments can be disabled using the 'comments' parameter.


Examples:

        <TMPL_VAR myname>    ### first comment
        <TMPL_VAR hisname>   ### second comment
    

Statements

Template inclusion

The <TMPL_INCLUDE> statement includes a template directly into the current template at the point where the statement is found. The included template contents are used exactly as if its contents were physically included in the main template.

All included templates must be located in a directory named 'inc' which must be a subdirectory of the directory in which the main template file is located. You must refer to these templates only by their filename, ie. without the 'inc' part of the path.

Examples:

In this example, the file header.tmpl must be located in the 'inc' subdirectory of the directory in which the main template file is located.

        <TMPL_INCLUDE header.tmpl>
        <TMPL_INCLUDE NAME="header.tmpl">
    

Variables

TODO

Variables defined by the TMPL_VAR statements are substituted with values associated with them by the set() method of TemplateProcessor.

Escaping of variables

All variables are automatically HTML escaped. This can be disabled using the 'html_escape' parameter. Escaping of variables can also be specified on a per variable basis using the ESCAPE parameter. This parameter overrides the default escaping setting. It can have three values:

The ESCAPE parameter can be used with both TMPL_VAR and TMPL_STATIC statements. TMPL_STATIC variables are by default always HTML-escaped.

Global look-up of variables

All variables that are inside a loop are local to that loop. If you want to reference a "global" variable from inside a loop, then you must either enable the 'global_vars' parameter or use the GLOBAL parameter to override 'global_vars' setting on a per variable basis.

Examples:

    <TMPL_VAR name>
    <TMPL_VAR NAME="city">
    <TMPL_VAR NAME="text1" ESCAPE="HTML">
    <TMPL_VAR NAME="text2" ESCAPE="NONE" GLOBAL="0">
    <TMPL_VAR address GLOBAL="1">
    <!-- TMPL_VAR test ESCAPE=URL -->
    

Conditionals

TODO

The TMPL_IF, /TMPL_IF, TMPL_ELSE, TMPL_UNLESS and /TMPL_UNLESS statements are conditionals. They mark start and end of a block that is included in the output only when the condition is true. Only names of variables or loops can be used in the condition. Conditional blocks may contain other nested conditional blocks.

If name of a loop is used in a condition, then the condition is true if the content of the loop will be included in the output at least once.

Examples:

    <TMPL_IF myvar>
        This block appears in the output if myvar is true.
    <TMPL_ELSE>
        This block appears in the output if myvar is false.
    </TMPL_IF>

    <TMPL_UNLESS hisvar>
        This block appears in the output if hisvar is false.
    <TMPL_ELSE>
        This block appears in the output if hisvar is true.
    </TMPL_UNLESS>
    

Loops

TODO

The TMPL_LOOP and /TMPL_LOOP statements mark start and end of a block which is printed once for each mapping in the list of mappings associated with the corresponding loop.

Loops can contain other nested loops. Every loop introduces its own namespace (scope) for variables. Variables located inside a loop cannot reference variables located outside the loop unless the 'global_vars' parameter is true, or unless this parameter is overridden for this variable using the 'GLOBAL' parameter of the corresponding TMPL_VAR statement.

Loop names used as variables in TMPL_VAR statements produce total number of passes in the corresponding loop.

examples

    <TMPL_LOOP Myloop>
        This block appears in the output
        once for every pass of the loop.
        <TMPL_VAR myvar>   ### Local variable.
    </TMPL_LOOP>
    

Magic loop variables

Magic context variables are automatically defined in every loop. They can be used the same way as normal variables. Their names always start with two underscores. Values of these variables are always integers (true = 1, false = 0).

Following list lists all recognized magic variables. Any other variable name which starts with two underscores is invalid. The TemplateError exception is raised when such a variable name is found.

__FIRST__

This variable is true if current pass is the first pass.

__LAST__

This variable is true if current pass is the last pass.

__INNER__

This variable is true if current pass is neither first nor last pass.

__ODD__

This variable is true if number of current pass is odd. That means it's true in the first, third, fifth, seventh ..... pass.

__PASS__

Value of this variable is the number of current pass. Passes are counted from one. Value of this variable is one in the first pass, two in the second pass etc.

__PASSTOTAL__

Value of this variable is total number of passes in current loop.

__EVERY__x

Where 'x' must be an integer. It can consist of more than one digit. This variable is true if number of current pass modulo 'x' equals to zero. The variable is never true in first or last pass, even if the condition above is true in such a pass. This variable can be used to put separators between every 'x' items of a list.


Multipart templates

Multipart templates can be created using the <TMPL_BOUNDARY> directive. This directive has no parameters.

Multipart templates are useful when you need to process and output a part of the template before all data needed to process the whole template are ready.

This can be useful to improve perceived responsiveness of web applications by sending the top part of a page to the client before the web application for example sends a slow query to the database and generates rest of the page from results of the query. Keep in mind that you probably will have to flush the output stream to achieve the desired effect. This can usually be done by calling sys.stdout.flush() in Python or flush() in PHP.

Multipart templates must follow this rule: every part itself must be a syntactically valid template. It means that boundaries between the parts must not be located inside a conditional block or inside a loop block.

The boundaries are processed after template inclusions are processed. It's possible to put the boundaries into the included templates, tough it's not recommended.

Please consult API documentation of the TemplateProcessor.process() method to find out how to correctly use multipart templates in your applications.

examples

    This is part one.
    <TMPL_BOUNDARY>
    This is part two.
    <TMPL_BOUNDARY>    
    This is part three.
    

Static template variables (TMPL_STATIC)

Static template variables are similar to TMPL_VARs, but are intended to represent static values, that never change. They can be useful when some string appears many times in a template, or in various different templates.

Static variables are in some way similar to TMPL_INCLUDE statements, except that they are processed much more faster and are typically used for short strings.

Typical usage of static variables is to emulate CSS classes, when you cannot use CSS because of some browser compatibility problems. You can, for example, define a static variable called "lightred2" and use it in all places where you need to assign that color. This provides an easy way to change it later from single place.

Static variables are resolved during compilation phase and cannot be changed without template recompilation.

You can use the static_data() method of the TemplataManager class to define static variables. If you decide to store values of your static variables in a separate file, than you should also look at the watch_files() method. This method can be used to monitor any changes of that file, and thus force recompilation of the template, when you change value of a static variable.


Example

template.tmpl

<html>
    <head>
        <title><TMPL_VAR title></title>
    </head>
    <body>
        <h1>Customers:</h1>
        <p>
            Total: <TMPL_VAR Customers>
        </p>

        ### this comment will be removed

        <table>
            <TMPL_LOOP Customers>
                <tr>
                    <TMPL_IF new>
                        <td>new customer</td> 
                    <TMPL_ELSE>
                        <td>old customer</td>
                    </TMPL_IF>
                    <td><TMPL_VAR __PASS__></td>
                    <td><TMPL_VAR name></td>
                    <td><TMPL_VAR city></td>
                </tr>
            </TMPL_LOOP>            
        </table>
    </body>
</html>