Did you know ... Search Documentation:
Packs (add-ons) for SWI-Prolog

Package "simple_template"

Title:Logic-free text (HTML) templates
Rating:Not rated. Create the first rating!
Latest version:1.2.0
SHA1 sum:6a56fcc8ae329748b4321b4674d729cfa4a0af22
Author:Matthew Carter http://ahungry.com/
Raivo Laanemets http://rlaanemets.com/
Sando George http://sandogeorge.github.io/
Home page:https://github.com/rla/simple-template


No reviews. Create the first review!.

Details by download location



Text (HTML) template processor for SWI-Prolog. Works best for cases when you have mainly static HTML.

![Build Status](https://travis-ci.org/rla/simple-template)


Input markup (test.html file):

<h1>{{= title }}</h1>
{{ each items, item }}
    <h2>{{= item.title }}</h2>
    <div class="content">{{- item.content }}</div>
{{ end }}

rendering with data:


st_render_file(test, _{
    title: 'Hello',
    items: [
        _{ title: 'Item 1', content: 'Abc 1' },
        _{ title: 'Item 1', content: 'Abc 2' }
}, Out, []).



<h2>Item 1</h2>
<div class="content">Abc 1</div>

<h2>Item 1</h2>
<div class="content">Abc 2</div>

Alternate syntax: semblance

If you find your tools work better with a template tag syntax that more closely resembles other web templating engines, such as Django (Python) / Djula (Common Lisp) / Twig (PHP), you can also use an alternate frontend syntax called semblance:

Input markup (test.html file):

<h1>{{ title }}</h1>
{% each items, item %}
    <h2>{{ item.title }}</h2>
    <div class="content">{% unescape item.content %}</div>
{% end %}

rendering with data:


st_render_file(test, _{
    title: 'Hello',
    items: [
        _{ title: 'Item 1', content: 'Abc 1' },
        _{ title: 'Item 1', content: 'Abc 2' }
}, Out, _{ frontend: semblance }).



<h2>Item 1</h2>
<div class="content">Abc 1</div>

<h2>Item 1</h2>
<div class="content">Abc 2</div>

It is not possible to mix two syntaxes through a single render call.


Render template from string:

st_render_string(String, Data, Stream, File, Options).

Render template from file:

st_render_file(File, Data, Stream, Options).

Render template from codes:

st_render_codes(Codes, Data, Stream, File, Options).

Options accept the following:

  • encoding - default utf8.
  • extension - file name extension, default html.
  • cache - whether to use cache, default false.
  • strip - whether to try to strip whitespace from output, default false.
  • frontend - which syntax to use, currently simple (default) or semblance.
  • undefined - throw error on undefined variables - error (default) or false (evaluates to false).

Processing instructions

Processing instructions start with double opening curly braces ({{`) and end with double closing curly braces (`}}). Semblance syntax variations are described below.

There are 4 types of processing instructions.


There are two output instructions. `{{= expression }}` outputs the expression value and escapes the special HTML characters. {{- expression }} outputs the expression value but does not escape the output. There must be no space between `{{ and = or -`.


Includes use the syntax `{{ include path/to/file }}`. The path should be relative. The relative path is resolved against the current file location and the currently set file extension is added. All values from the current scope are available to the included file. There is also `{{ include path/to/file, expression }}` that sets the scope of the included file to the value of the expression (must be a dict).

Dynamic includes use the syntax `{{ dynamic_include expression }}`. The value of the expression must be a file path specifier. There is also a variant with the scope expression.

Includes are currently processed at runtime. You should enable caching if you include inside a loop otherwise the included file is parsed over and over again.


Conditional instructions have the following syntax:

{{ if cond_expression1 }}
{{ else if cond_expression2 }}
{{ else }}
{{ end }}

`else if and else` parts are optional.

Each loop

The each loop allows to process lists. The syntax for each loop:

{{ each expression, item_var, index_var, len_var }}
{{ end }}

The value of expression must be a list. item_var, index_var and len_var refer to current item, current item index and the length of the list. index_var and len_var are optional.

Semblance syntax

The semblance syntax has the following differences.

Output instruction: {{ variable }}.

Unescaped output: `{% unescape rawvar %}`.

Conditional instructions:

{% if cond_expression1 %}
{% else if cond_expression2 %}
{% else %}
{% end %}

Each loop:

{% each expression, item_var, index_var, len_var %}
{% end %}

Comments: `{# comment #}`.


Expressions are ground Prolog terms with the interpretation described below.

In most contexts, atoms are interpreted as scope entries ("variables"). An error is thrown when there is no suitable entry.

The following arithmetic operators and functions are supported: -, +, *, /, mod, rem, //, div, abs, sign, max, min, random, round, truncate, floor, ceiling, **, ^.

Boolean expressions include modified unification using the = operator. The operator provides coercion from atom to string when either of operands is an atom and the other is a string. For other types, no coercion is applied. Similarily works the \= operator. Supported boolean operators are: , (logical and), ; (logical or) and \+ (logical negation). Supported comparison operator are: `>, <, >=, =<,`.

Conditional expression if(expression, true_expr, false_expr) value is the value of true_expr when the expression evaluates to anything but 0 or false. Otherwise the value is the value of false_expr.

The + operator is overloaded to provide string or atom concatenation when the left side of the operator is an atom or string. The result is string.

The `.` operator is used for accessing values from dicts. Internally the `./3` predicate is used which means that user-defined functions on dicts will work as intended.

Compound terms that match none of the operators and constructs described above are treated as user-defined (see below) function calls. An error is thrown when there is no such function defined.

A special expression is atom(something). Its value is atom something. This is added to differentiate them from other atoms which are otherwise interpreted as scope entries.

Literal lists work as expected with the elements having the interpretation as the expressions above.

Undefined variables

The default behaviour when a variable that is not in the scope (template data dict) is encountered is to throw a no_entry error. This behaviour can be modified to set the variable value to false (default is error) by setting the undefined option to false when rendering templates. For example:

st_render_file(test, _{
    title: 'Hello',
    items: [
        _{ title: 'Item 1', content: 'Abc 1' },
        _{ title: 'Item 1', content: 'Abc 2' }
}, Out, _{ undefined: false }).

This is useful in situations where a developer may want to include a block in the template based on the existence of a variable. For example:

{% if page_header %}
{% end %}

Built-in functions

There are three single-argument functions to encode URI parts: encode_path, encode_query_value and encode_fragment. These call uri_encoded/3 with the respective first argument.

Global constants

Global constants can be set with the st_set_global/2 predicate by importing the st_expr module. When a scope contains an entry with the same name as a global then the local value is preferred.

User-defined functions

User-defined functions can be set with the st_set_function(Name, Arity, Goal) predicate in the st_expr module. Arity refers to the function arity. Goal must have arity Arity + 1.


Comment blocks start with `{{%` and end with `}}`. Comments do not appear in the output.


Template caching is enabled by setting option cache: true during rendering. This makes the system cache parsed templates. This is particulary useful when using includes in loops. To purge the current cache contents, use the st_cache_invalidate predicate.

Whitespace removal

Some (but not all) whitespace is removed by setting option strip: true during rendering. Line indents and some duplicate line ends are removed from the output. Whitespace removal is parse-time and does not incur any runtime penalty.


Encoding for template files can be specified by setting option encoding during rendering. Accepted values are all that are accepted by the encoding option of the read_file_to_codes/3 predicate.


This package requires SWI-Prolog 7.x.


API documentation

See http://packs.rlaanemets.com/simple-template/doc/.

Running tests

In the package root, insert into swipl:


Or if you cloned the repo:

make test

Bug reports/feature requests

Please send bug reports/feature request through the GitHub project page.


  • 2017-11-03 version 1.2.0. Option to deal with undefined variables.
  • 2015-12-28 version 1.1.0. Add alternate syntax: semblance.
  • 2015-11-07 version 1.0.0. Removal of global options. Backwards-incompatible.
  • 2014-05-09 version 0.3.0. Provide st_cache_invalidate/0, \= operator, comments.
  • 2014-05-07 version 0.2.0. Literal lists, encode_* functions.
  • 2014-03-02 version 0.1.0. Provided st_set_encoding/1.
  • 2014-01-30 version 0.0.1


The MIT License. See LICENSE file.

Contents of pack "simple_template"

Pack contains 25 files holding a total of 63.9K bytes.