templa is a drop-in replacement for etlua built from the ground up for modern Lua 5.4+, delivering up to 34% faster rendering and 5x lower memory allocation per render call.
etlua relies on setfenv which does not exist in Lua 5.4. Its shim uses debug.upvaluejoin which breaks in sandboxed environments. templa uses load()'s fourth argument instead, the correct 5.4 approach, with no debug library required. It's dependence on MoonScript also makes it quite niche and makes people unwilling to contribute
measured on Lua 5.4, AMD Ryzen 7 5800X (Linux), 100k iterations.
| etlua | templa | delta | |
|---|---|---|---|
| render | 35,458/s | 46,411/s | +31% |
| compiled | 331,066/s | 442,434/s | +34% |
| compile time | 41,488/s | 56,268/s | +36% |
| gc pressure | 1.067 kb/iter | 0.216 kb/iter | 5x less |
| coroutine | 247,884/s | 306,787/s | +24% |
gc pressure is measured as kb allocated per render call with gc stopped. the 5x reduction comes from buffer reuse and coroutine-keyed data stores eliminating per-render allocations.
luarocks install templalocal templa = require("templa")
-- render a template directly
local result = templa.render("hello <%= name %>!", { name = "world" })
-- "hello world!"
-- compile once, render many times
local fn = templa.compile("hello <%= name %>!")
fn({ name = "alice" }) -- "hello alice!"
fn({ name = "bob" }) -- "hello bob!"| tag | behaviour |
|---|---|
<%= expr %> |
evaluate expression, html-escape and insert |
<%- expr %> |
evaluate expression, insert raw (no escaping) |
<% code %> |
execute code, insert nothing |
<% code -%> |
execute code, trim following newline |
renders a template string with optional data table. Returns the rendered string or nil, error.
compiles a template string into a reusable function. The returned function accepts a data table and returns the rendered string. Prefer this over render when the same template is rendered multiple times.
- Lua 5.4+ only, no LuaJIT support
- no
debuglibrary required, safe in sandboxed runtimes - coroutine-safe - compiled functions can be called concurrently from multiple coroutines
compileandrenderare the only public API -ParserandCompilerinternals are not exposed- errors are returned as
nil, errrather than thrown
MIT