Skip to content
Noob Saibot edited this page Nov 28, 2019 · 27 revisions




build statistics meta
travis:
appveyor:
github:
issues:
quality:
loc:
commits:
editor:
platform:

table of contents

simple c++ example

in the following example a datastructure is created and put into the engine's context. the subsequent call of templ_render is given the created datastructure to render the string template.

#include "templ.cpp"

int
main(int argc, char **argv) {
    using namespace templ::api;

    templ_init(MB(100), MB(100), MB(100));

    Templ_Vars vars = templ_vars();
    Templ_Var *name = templ_var("name", "noob");
    templ_vars_add(&vars, name);

    Templ *templ = templ_compile_string("hello {{ name }}");
    char *result = templ_render(templ, &vars);

    os_file_write("test.html", result, utf8_strlen(result));
    if ( status_is_error() ) {
        for ( int i = 0; i < status_num_errors(); ++i ) {
            Status *error = status_error_get(i);
            fprintf(stderr, "%s in %s line %lld\n", status_message(error),
                status_filename(error), status_line(error));
        }

        for ( int i = 0; i < status_num_warnings(); ++i ) {
            Status *warning = status_warning_get(i);
            fprintf(stderr, "%s in %s line %lld\n", status_message(warning),
                status_filename(warning), status_line(warning));
        }

        status_reset();
    }

    templ_reset();

    return 0;
}

jinja template examples

data folder contains a couple jinja templates with statements that are supported by the implementation so far.

{% extends "template.tpl" if true %}

{% block title %}
    main - {{ default_title }}
{% endblock %}

{% block main %}
    {{ super() }}

    {% include "literals.tpl" without context %}
    {% include "exprs.tpl"    with    context %}
    {% include "stmts.tpl"    without context %}
    {% include "utf8.tpl"     without context %}
    {% include "filter.tpl"   with    context %}
    {% include "tests.tpl"    without context %}
    {% include "macros.tpl"   without context %}
{% endblock main %}

{% block custom %}
    <div>custom content</div>
{% endblock %}

json

there's a simple, and built-in support for json which is implemented in the src/json.cpp. the json_parse method, will parse a given json string, and return a list Json_Node ** of Json_Node * elements, which in return can be transformed into a Templ_Var and be given to the render method, as shown in the example below.

    Json_Node **nodes = json_parse("{ \"Accept-Language\": \"en-US,en;q=0.8\", \"Host\": \"headers.jsontest.com\", \"Accept-Charset\": \"ISO-8859-1,utf-8;q=0.7,*;q=0.3\", \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\" }");
    Templ *templ = templ_compile_string("{{ header[\"Accept-Language\"] }}: {{ header.Host }} in {{ header.Accept }}");

    Templ_Var *http_header = templ_var("header", nodes[0]);
    Templ_Vars http_vars = templ_vars();
    templ_vars_add(&http_vars, http_header);

    char *result = templ_render(templ, &http_vars);

unicode

templ supports unicode with the utf-8 encoding for string literals as well as names. be aware though that right now only limited amount of transformation in filters is supported.

below is a list of character ranges which have lower-/uppercase conversion support.

ABCDEFGHIJKLMNOPQRSTUVWXYZÄÜÖẞ
АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ
ÆÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞĀĂĄĆĈĊČĎĐĒĔĖĘĚĜĞĠĢĤĦĨĪĬĮİIJĴĶŸ
ŁŃŅŇ

abcdefghijklmnopqrstuvwxyzäüöß
абвгдеёжзийклмнопрстуфхцчшщъыьэюя
æåçèéêëìíîïðñòóôõöøùúûüýþāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıijĵķÿ
łńņň

characters that are not supported will be printed back as they are.

table with all character blocks.

template

{% set シ个 = "原ラ掘聞" %}
{{ シ个 }}
{% set приветствие = "здравствуйте" %}
{{ приветствие }}
{{ "🤩✨🥰" * 10 }}

output

原ラ掘聞
здравствуйте
🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰🤩✨🥰

expressions

below is a list of expressions that are supported right now

literals

string literals

string literals are supported with quotation marks as well as with apostrophe.

"string literal"
'also string literal'

numbers

integer and floating point numbers are supported.

42
42.0

lists

list literals start with an opening bracket and contain a comma separated list of elements, which in turn have to be a valid jinja expression.

['europe', 'asia', 'australia']

lists can be assigned as a value to a variable and be used in a for statement as both, literals and variables.

{% for it in ['europe', 'asia', 'australia'] %}
    {{ it }}
{% endfor %}

{% set continents = ['europe', 'asia', 'australia'] %}
{% for it in continents %}
    {{ it }}
{% endfor %}

tuple

tuple are basically lists with the exception of being read-only.

('x', 'y')

dictionaries

dictionaries are supported as expressions in assignments and in expression in for loops.

{% set d = {'name': 'adam', 'age': '30'} %}

{% for it in {'name': 'eve', 'age': '25'} %}
    ...
{% endfor %}

booleans

boolean values

true
false

math

3+5*7/2

below is a list of supported math operations

+
-
*
**
/
//
%

statements

list of supported statements

if

flow control statement if is supported with elif and else branches.

{% if <condition> %}
    <statements>
{% elif <condition> %}
    <statements>
{% else %}
    <statements>
{% endif %}

you can use any valid jinja and supported expressions as condition that have a boolean value as result.

true
false
1 < 2
a is eq "foo"
firstname == "arminius" and lastname == "der cherusker"

for

for statement supports multiple return values, else branch, almost all loop variables, break and continue statements.

{% for <iterator> in <menge> %}
    <anweisungen>
{% else %}
    <anweisungen>
{% endfor %}

the following loop variables can be used inside a for loop:

  • loop.index
  • loop.index0
  • loop.revindex
  • loop.revindex0
  • loop.first
  • loop.last
  • loop.length
  • loop.cycle
  • loop.depth
  • loop()

block

blocks are supported with an optional name in the endblock statement. as the inheritance of templates is also supported, parent block's content can be overwritten entirely, or be included alongside your own content with the super() method.

{% block <name> %}
{% endblock <name> %}

include

additional templates can be included into a template. include statement supports if expression, and the additional annotations with context, without context, ignore missing.

{% include "<template>" <if ausdruck> %}

import

{% import "<template>" as <sym> %}
{% from "<template>" import <sym1> as <alias1> %}

extends

{% extends "<template>" <if expr> %}

filter

{% filter <name1> | <name2> %}
    <anweisungen>
{% endfilter %}

macro

{% macro <name>(parameter, ...) %}
{% endmarcro %}

raw

{% raw %}
{% endraw %}

filter

ongoing process of implementing the vast amount of filters. the following filters are implemented in dev:

  • abs
  • attr
  • capitalize
  • center
  • default
  • dictsort
  • escape
  • filesizeformat
  • first
  • float
  • format
  • lower
  • truncate
  • upper

tests

most of the tests present in the jinja2 spec are already implemented in dev.

  • callable
  • defined
  • devisibleby
  • equal
  • even
  • ge
  • gt
  • in
  • iterable
  • le
  • lt
  • mapping
  • ne
  • none
  • number
  • odd
  • sameas
  • sequence
  • string
  • undefined