Crates.io | templar_macros |
lib.rs | templar_macros |
version | 0.5.0 |
source | src |
created_at | 2021-01-18 05:44:31.541561 |
updated_at | 2021-01-18 05:44:31.541561 |
description | Lightweight, fast, and powerful templating engine |
homepage | |
repository | https://github.com/proctorlabs/templar |
max_upload_size | |
id | 343375 |
size | 13,576 |
Templar is both a Rust library and a CLI tool for working with templates. The usage and style is inspired by both Jinja2 and Ansible, though it is not intended to be a clone of either of these.
The goal of the project is to provide fast and flexible dynamic templating, particularly for use with configurations and local tooling. Despite this, it likely can be adapted for HTML and front end rendering as well.
The templating syntax is likely familiar considering the frameworks that it is based on. For instance, a simple template may look like this:
user_name={{ user.name }} {# Replace with the context property 'name' in 'user' #}
full_context={{ . | json("pretty") }} {# Dump the entire context as JSON, '.' is the root node #}
password={{ script('echo hunter2 | md5sum') }} {# Execute a shell command and calculate the MD5 sum #}
In addition to simple replacements, more complex expressions can be used.
The calculated result is {{ 100 * 5 / 10 }} {#- Prints '50' #}
Today's guest list:
{%- for person in ['Bob', 'Joe', 'Jen', 'Amy')] %}
* {{ person }} will come to the party!
{%- endfor %} {#- This will loop everyone in the inline array above, but they array could also come from the context #}
Well... yes.
There are many great templating frameworks out there, however they are mostly intended for web or HTML rendering. This leads to a few drawbacks when used for other purposes.
{% if user.isRoot %} {{ do_something() }} {% end if %}
would change if the user.isRoot
value changes.Much of the syntax is based on the wonderful Jinja2 project. Here are some of the currently supported features.
{{ }}
syntax.
{{ some.value.path }}
.
allowing things like {{ . | json }}
to be used to dump the entire context as JSON{{ .['565'] }}
. This also allows array access and identifier of non-standard types (such as boolean).{{ [1,2,3,4] }}
and complex nesting also possible e.g. {{ [1,2, script("echo 'hello world!'"), (5 + 5 | base64)] }}
{{ {'key': 'value', 'otherKey': { 'nested': 'map' } } }}
{% %}
syntax
{% if 10/2 == 5 %}The world is sane!{% else if false %}What universe are we in?{% end if %}
{% scope %}I'm in a scope!{% end scope %}
{% for thing in lots.of.stuff %} {{ thing['name'] }} {% end for %}
. For loops always enter a new scope.{# #}
syntax and will be remitted from the output.-
to any of the above blocks e.g. {{- 'no whitespace! -}}
.
-
on it will be removed as if the block is immediately next to the other element.As documentation is still in progress, see the kitchen sink for examples of template usage.
Everything inside the standard {{ }}
block is an expression. Each block holds exactly one expression, but that expression can be chained with
many individual operations. A quick overview:
+ - * / %
these operations are only valid with numeric types== != < <= > >= && ||
=
the left side of this operation must be some identifier e.g. {{ some.val.path = 'hello world!' }}
~
e.g. {{ 'Hello' ~ ' ' ~ 'world!' }}
prints "Hello world!"ident()
e.g. {{ env('USER') }}
would retrieve the value of the environment variable "USER".|
e.g. {{ 'hello world' | upper }}
would use the 'upper' filter to print "HELLO WORLD"As documentation is still in progress, see the expression tests for examples of expression usage.
Templar prefers rendering performance over parsing performance. While you should take most benchmarks with a grain of salt, simple templates render in a few microseconds. On my AMD Ryzen 2700U processor, I can render a simple template about 300,000 times a second on a single thread.
Templates vary a lot though and templates that call out to shell commands or do other complex things will get less performance.
Full API documentation can be found on docs.rs