Non-HTML use-cases
------------------
Mustache templates are, by spec, expected to autoescape especial
HTML characters from variables, unless a raw variable is used.
From the `official manual`_:
All variables are HTML escaped by default.
If you want to return raw contents without escaping, use the triple mustache: {{{name}}}.
You can also use & to return its raw contents: {{& name}}.
.. _official manual: https://mustache.github.io/mustache.5.html#Variables
**mstache** is highly customizable and can be adapted for non-HTML use-cases
not covered by the reference specs and, so, rarely supported by any other
implementation. This page explains a few use-case scenarios.
JSON Template
=============
The following is an example on how integrate Mustache templating in a JSON
context, the customizations made are:
1. ``escape`` customized to disable HTML-escaping.
2. ``stringify`` replaces for JSON encoding.
3. ``tags`` customized to include quotes, replacing whole strings with JSON.
.. code:: python
import json
import textwrap
import mstache
print(mstache.render(
textwrap.dedent('''
{
"number": "{{int_value}}",
"string": "{{str_value}}",
"object": "{{dict_value}}"
}
'''),
{
'int_value': 1,
'str_value': 'string',
'dict_value': {},
},
stringify=lambda data, text: (
# JSONify values
json.dumps(data).encode()
),
escape=lambda x: x, # omit any escaping
tags=('"{{', '}}"'), # mstache tags to replace entire strings
))
# {
# "number": 1,
# "string": "string",
# "object": {}
# }
Binary template
===============
**mstache** is one of the few Mustache implementations supporting binary
templates, if any at all, where every byte is representative.
This is thanks to both its support for :class:`bytes` templates and high
customizability. For binary templates you will need to care of the following:
1. Your template would need to be of type :class:`bytes` for the rendering
output to be also in :class:`bytes`.
2. Ensure your string variables are either :class:`bytes` or expected to be
encoded as ``utf-8``.
3. ``virtuals`` can be used as encoding and utility helpers.
4. ``stringify`` can be used to customize how objects are turned into bytes.
Binary template example:
.. code:: python
import functools
import json
import mstache
output = mstache.render(
(
# bytes template
b'{{data.length_uint32}}{{data}}'
b'{{integer.as_uint32}}'
),
{
'data': 'hello world!\nsome bytes', # to be utf8-encoded
'integer': 5, # to be encoded as 4-byte big-endian uint
},
getter=functools.partial(
mstache.default_getter,
virtuals=mstache.default_virtuals | {
# virtual byte helpers
'length_uint32': lambda x: (
# byte-length as 4-byte big-endian uint
len(x.encode() if isinstance(x, str) else x)
.to_bytes(4)
),
'as_uint32': lambda x: (
# value as 4-byte big-endian uint
int(x).to_bytes(4)
),
},
),
escape=lambda x: x, # omit any escaping
keep_lines=True, # do not collapse block lines
)
print(output)
# b'\x00\x00\x00\x17hello world!\nsome bytes\x00\x00\x00\x05'
# addendum: extraction
size = int.from_bytes(output[:4])
print((size, output[4:4 + size], int.from_bytes(output[-4:])))
# (23, b'hello world!\nsome bytes', 5)