Zero dependency, single file template engine for Lua 5.1+ with builtin sandbox support.
It compiles a template string to a function that generates the final string by substituting values by the ones in a sandboxed environment.
There are 3 constructs templates recognize:
- Literals: Content that will be copied unmodified to the final string. Read the note on long strings
- Value: A value processed by Lua and appended to the final string,
stringified by
tostring
- Statement: A Lua code block to be copied unmodified to the generated code, used for variable assignments, repetitions, conditions, etc. It doesn't directly generate contents for the final string
Values are delimited by matching {{
and }}
, statements by {%
and
%}
, and everything else is considered literal. Delimiter characters {
,
}
and %
can be escaped using a leading backslash. If you want literal }}
or %}
in your template, they must be escaped, or molde will return
error.
Example:
NOTE: This is not a valid molde template for educational purposes.
By default, everything is copied unmodified to the final string.
Values are just Lua expressions:
- Hello {{ "world" }}
"Hello world"
- {{ 5 + 3 * 4 }}
"17"
- {{ nil or "default" }}
"default"
- You are using {{ _VERSION }}
"You are using Lua 5.3" (You may use Lua 5.1 and 5.2 as well)
- Line 1{{ "\n" }}Line 2
"Line 1
Line 2"
- Escaping \{{ Hi! \}} (Note that you MUST escape the closing '}}')
"Escaping {{ Hi! }}"
- Escaping is characterwise, so \{{ is as valid as {\{
"Escaping is characterwise, so {{ is as valid as {{"
- table.insert is used in values {{ so they must be a valid expression! }}
Error: ')' expected near 'they'
Statements are Lua statements:
- {% for i = 1, 5 do %}{{ i }} {% end %}
"1 2 3 4 5 "
- {% -- this is just a comment, y'know %}
""
- {{ unbound_variable }}{% unbound_variable = "Hi!" %} {{ unbound_variable }}
"nil Hi!"
- {% if false then %}This will never be printed{% else %}Conditionals!{% end %}
"Conditionals!"
- \{% Escaping works \%} {\% here as well %\} (You MUST escape closing '%}' too)
"{% Escaping works %} {% here as well %}"
- {% if without_then %}Statements must form valid Lua code!{% end %}
Error: 'then' expected near 'table'
The lua reference manual says:
For convenience, when the opening long bracket is immediately
followed by a newline, the newline is not included in the string.
The code generated by molde to insert literals uses long strings, so newlines that come immediately after a closing value or statement will not be considered in the final string.
Using LuaRocks:
# luarocks install molde
Or you may copy the only source file molde.lua
to your Lua path
local molde = require 'molde'
-- molde.load and molde.loadfile return a function that receives a table
-- with the values to substitute, and the optional environment (default: _G)
hello_template = molde.load([[Hello {{ name or "world" }}]])
print(hello_template()) -- "Hello world"
print(hello_template{name = "gilzoide"}) -- "Hello gilzoide"
name = "gilzoide"
print(hello_template({}, _ENV or getfenv())) -- "Hello gilzoide"
-- load the template from a file (same template)
hello_template = molde.loadfile("hello_template")
name = nil
print(hello_template()) -- "Hello world"
Run automated tests using busted:
$ busted
The API is documented using LDoc and is available at github pages.
To generate:
$ ldoc . -d docs
- 2.0.0 - Removed dependency on LPegLabel in favor of a pure streaming parser,
added
molde.tokenize
, changedmolde.parse
function to be an iterator instead of returning table, move doc comments to source file, changedstring_bracket_level
to be a function argument instead of module-wide configuration, changemolde.load
to returnnil
+ error instead of raising. - 1.0.1 - Fix error handling for matching on LpegLabel v1.5
- 1.0.0 - Updated to use LpegLabel version 1.5+
- 0.1.6 - Support for Lua 5.1