TexturePacker & PhysicsEditor Template Language

TexturePacker templates have a syntax that is very similar to that of Django templates. If you are familiar with Django templates, then you will find TexturePacker templates to be very easy to learn.

Syntax of the templates

The syntax of templates contains four types of tokens:

  • plain text
  • comments
  • variables
  • control tags

A simple template might look like this:

{# A simple template example #}
Hello {{ person.name }},

{% if person.hasBirthday %}
Happy Birthday!
{% else %}
Have a nice day!
{% endif %}

Bye,
{{ myname }}
  • Content inside {# #} are comments and are not part of the output.
  • Content inside {{ }} are variables which are substitued when the template is rendered.
  • Content inside {% %} are control tags which can affect the rendering of the template.

TexturePacker and PhysicsEditor both support commonly used tags such as if, for, cycle and a host of others (see https://docs.djangoproject.com/en/1.10/ref/templates/builtins/). It is also possible for to define your their own tags.

Loops

The type of a variable determines how it can be used in templates. For example, treatment of items in an iterable context works as follows.

Lists work as expected:

{% for item in mylist %}
- {{ item }}
{% endfor %}

Truthiness

Truthiness of a variable is evaluated in a similar way to python. That is,

  • an empty string is false
  • 0 is false
  • an empty list is false
  • boolean false is false

Everything else is true.

{% if mylist %}
List items:
{% for item in mylist %}
- {{ item }}
{% endfor %}
{% else %}
The list ist empty.
{% endif %}

Variable lookups

So far we've mostly used simple variable lookups in variable tags, but the template system is capable of a lot more. Complex structures can be evaluated using the dot (.) character.

The dot can be used for list index lookup (Note that list lookup is 0-indexed):

The first item is {{ mylist.0 }}, and the fifth item is {{ mylist.4 }}.

It can also be used for key lookups:

The hash value is {{ myhash.mykey }}.

And it can retrieve properties from an object instances:

The object property is {{ myobj.myprop }}.

Filters

Filters can further affect the result of including a variable in a template. Filters are separated by the pipe (|) character.

Name is {{ name }}, and name in uppercase is {{ name|upper }}.

Which is rendered as

Name is Alice, and name in uppercase is ALICE.

Note that filters may be combined with dot-lookup. For example, if people is a list of Person objects, and Person objects have name properties:

First persons name: {{ people.0.name|upper }}.

Rendered as

First persons name: BOB.

Filters may also be chained. Here, 'Claire' is first uppercased, then lowercased:

Name is {{ name|upper|lower }}

Rendered as

First persons name: claire.

Filters may take one string argument, which is delimited by a colon (:).

If peoplestring contains "Dave and Ellen and Frank", we can cut the string and

The people are {{ peoplestring|cut:"and " }}

Rendered as:

The people are Dave Ellen Frank.

Internal filters are:

  • upper
  • lower
  • slice
  • truncate
  • join
  • split

Also see https://docs.djangoproject.com/en/1.10/ref/templates/builtins/

Auto-escaping in templates

When creating HTML string output it is necessary to consider escaping data inserted into the template. HTML escaping involves replacing < with < and & with & etc. The template engine automatically escapes string input before adding it to the output.

This is relevant when writing a variable from the context into the Template.

If the context object companies is a list containing (Burger King, Ben & Jerries, Ford), and it is used in a template such as:

{% for company in companies %}
- {{ company }}
{% endfor %}

The output would be

  • Burger King
  • Ben & Jerries
  • Ford

Notice that the & has been replaced with &, as is appropriate for html output.

Use the |safe filter to get the un-escaped content of the string:

{% for company in companies %}
- {{ company|safe }}
{% endfor %}

It is also possible to turn this auto-escaping feature off for a block in a template.

For example:

{% autoescape off %}
...
{% endautoescape %}

would not escape the content between the autoescape and endautoescape tags. This should only be used for content which is actually already safe.

Also see https://docs.djangoproject.com/en/1.10/ref/templates/language/#for-individual-variables

A better way to write exporters

We've created many of our first exporters using this template syntax but found it hard because the templates get quite unreadable if you want to create properly formatted output.

The newer exporters use a simple template like this for TexturePacker - here the Phaser exporter:

{% load phaser %}{{tp|exportData|safe}}

This practically disabled the template. All formatting is done in Javascript which is way more readable - and, since we can use JSON.stringify - always exports correct JSON data.

There's a file called grantlee/0.2/phaser.qs in the exporter that contains that code:

var exportTexture = function(...)
{
    ...
}

var exportData = function(root)
{
    var doc = {
        textures: exportTexture(root),
        meta: {
            app: "https://www.codeandweb.com/texturepacker",
            version: "3.0",
            smartupdate: root.smartUpdateKey
        }
    };
    return JSON.stringify(doc, null, "\t");
}

exportData.filterName = "exportData";
Library.addFilter("exportData");