## 5.3.1 Defining and Using Templates

By default, templates are loaded from the directory where the renderer module was imported from. In addition, the templates from each of the parent renderer class modules are also loaded. This makes it very easy to extend a renderer and add just a few new templates to support the additions that were made.

The template files in the module directories can either contain a single template, corresponding to a single type of node, or several templates. In the first case, the basename of the template file is used as the key to store the template in the renderer, and the extension specifies the template engine to use. Keep in mind that the names of the keys in the renderer correspond to the node names in the document object. The extensions used for all templating engines are shown in the table below.

Engine | Extension | Output Type
Jinja2 | .jinja2 | Any
ZPT | .html, .htm, .zpt | HTML
| .xhtml, .xhtm, .xml | XML/XHTML
Python string formatting | .pyt | Any
Python string templates | .st | Any
Kid | .kid | XML/XHTML
Cheetah | .che | XML/XHTML
Genshi | .gen | HTML

The file listing below is an example of a directory of template files. In this case the templates correspond to nodes in the document created by the description environment, the tabular environment, \textbf, and \textit.

    description.xml
    tabular.xml
    textbf.html
    textit.html

Since there are a lot of templates that are merely one line, it would be inconvenient to have to create a new file for each template. In cases like this, you can use the ‘.zpts’ extension for collections of ZPT templates, or the ‘.jinja2s’ extension for collections of Jinja2 templates, or more generally ‘.pts’ for collections of various template types. Files with this extension have multiple templates in them. Each template is separated from the next by the template metadata which includes things like the name of the template, the type (xml, html, or text), and can also alias template names to another template in the renderer. The following metadata names are currently supported.

Name | Purpose
engine | the name of the templating engine to use. At the time of this writing, the value could be jinja2, zpt, tal (same as zpt), html (ZPT HTML template), xml (ZPT XML template), jinja2, python (Python formatted string), string (Python string template), kid, cheetah, or genshi.
name | the name or names of the template that is to follow. This name is used as the key in the renderer, and also corresponds to the node name that will be rendered by the template. If more than one name is desired, they are simply separated by spaces.
type | the type of the template: xml, html, or text. XML templates must contain a well-formed XML fragment. HTML templates are more forgiving, but do not support all features of ZPT (see the SimpleTAL documentation).
alias | specifies the name of another template that the given names should be aliased to. This allows you to simply reference another template to use rather than redefining one. For example, you might create a new section heading called \introduction that should render the same way as \section. In this case, you would set the name to “introduction” and the alias to “section”.

There are also some defaults that you can set at the top of the file that get applied to the entire file unles overridden by the meta-data on a particular template.

Name | Purpose
default-engine | the name of the engine to use for all templates in the file.
default-type | the default template type for all templates in the file.

The code sample below shows the basic format of a jinja2s file.

    name: textbf bfseries
    <b>{{ obj }}</b>

    name: textit
    <i>{{ obj }}</i>

    name: introduction introduction*
    alias: section

    name: description
    <dl>
    {% for item in obj %}
      <dt>{{ item.attributes.term }}</dt>
      <dd>{{ item }}</dd>
    {% endfor %}
    </dl>

The code above is a jinja2s file that contains four templates. Each template begins when a line starts with “name:”. Other directives have the same format (i.e. the name of the directive followed by a colon) and must immediately follow the name directive. The first template definition actually applies to two types of nodes textbf and bfseries. You can specify ony number of names on the name line. The third template isn’t a template at all; it is an alias. When an alias is specified, the name (or names) given use the same template as the one specified in the alias directive. Notice also that starred versions of a macro can be specified separately. This means that they can use a different template than the un-starred versions of the command. The last template shows a loop example.

Here is an example of using various templates engines in a single file.

    name: equation
    engine: jinja2
    <div class="equation" id="{{ obj.id }}">
      <span class="equation_label">{{ obj.ref }}</span>
      {{ obj }}
    </div>

    name: textbf
    engine: python
    <b>%(self)s</b>

    name: textit
    engine: string
    <i>${self}</i>

    name: textsc
    engine: cheetah
    <span class="textsc">${here}</span>

    name: textrm
    engine: kid
    <span class="textrm" py:content="XML(str(here))">normal text</span>

    name: textup
    engine: genshi
    <span class="textup" py:content="markup(here)">upcase text</span>

There are several variables inserted into the template namespace. Here is a list of the variables and the templates that support them.

Object | ZPT/Python Formats/String Template | Jinja2 | Cheetah | Kid/Genshi
document node | self or here | obj | here | here
parent node | container | container | container | container
document config | config | config | config | config
template instance | template |  |  |
renderer instance | templates | templates | templates | templates
parent document |  | doc |  |

You’ll notice that Kid and Genshi templates require some extra processing of the variables in order to get the proper markup. By default, these templates escape characters like <, >, and &. In order to get HTML/XML markup from the variables you must wrap them in the code shown in the example above. Hopefully, this limitation will be removed in the future.

When using Jinja2 templates, the default configuration trims white spaces before and after template tags (see trim_blocks and lstrip_blocks in Jinja2’s documentation). Also, when developing Jinja2 templates, inserting `{{ debug() }}` will launch a python debugger session to allow inspection of the context variable during rendering.

### Template Overrides

It is possible to override the templates located in a renderer’s directory with templates defined elsewhere. This can be done using the `--extra-templates` option or using the *TEMPLATES environment variable. The “*” in the name *TEMPLATES is a wildcard and must be replaced by the name of the renderer. For example, if you are using the HTML5 renderer, the environment variable would be HTML5TEMPLATES. For the PageTemplate renderer, the environment variable would be PAGETEMPLATETEMPLATES.

The format of this variable is the same as that of the PATH environment variable which means that you can put multiple directory names in this variable. In addition, the environment variables for each of the parent renderers is also used, so that you can use multiple layers of template directories.

You can actually create an entire renderer just using overrides and the PT renderer. Since the PT renderer doesn’t actually define any templates, it is just a framework for defining other XML/HTML renderers, you can simply load the PT renderer and set the PAGETEMPLATETEMPLATES environment variable to the locations of your templates. This method of creating renderers will work for any XML/HTML that doesn’t require any special post-processing.