Luma API Documentation
Complete API reference for the Luma template engine.
Table of Contents
Core API
luma.render(template, context, options)
Render a template string with context data.
Parameters:
template(string): Template source codecontext(table): Variables to pass to templateoptions(table, optional): Rendering optionssyntax(string): “auto”, “jinja”, or “luma” (default: “auto”)no_jinja_warning(boolean): Suppress Jinja2 syntax warningname(string): Template name for error messages
Returns: (string) Rendered output
Example:
local luma = require("luma")
local result = luma.render("Hello, $name!", {name = "World"})
print(result) -- "Hello, World!"
Error Handling:
local ok, result = pcall(function()
return luma.render(template, context)
end)
if not ok then
print("Error:", result)
end
luma.compile(template, options)
Compile a template for reuse.
Parameters:
template(string): Template source codeoptions(table, optional): Compilation optionssyntax(string): Template syntax modename(string): Template name
Returns: (table) Compiled template object
Example:
local luma = require("luma")
-- Compile once
local compiled = luma.compile("Hello, $name!")
-- Render many times
local filters = require("luma.filters")
local runtime = require("luma.runtime")
for _, user in ipairs(users) do
local result = compiled:render(
{name = user.name},
filters.get_all(),
runtime
)
print(result)
end
Performance: Compiling and reusing templates is 50-100x faster than rendering from source each time.
luma.new_environment(options)
Create a template environment with shared state.
Parameters:
options(table, optional): Environment optionspaths(table): Template search pathsfilters(table): Custom filtersglobals(table): Global variables
Returns: (table) Environment object
Methods:
env:render(template, context)- Render template stringenv:render_file(name, context)- Render template fileenv:compile(template)- Compile template
Example:
local luma = require("luma")
local env = luma.new_environment({
paths = {"/templates", "."},
globals = {site_name = "My Site"},
})
local result = env:render_file("page.luma", {title = "Home"})
Compiler API
compiler.compile(source, options)
Low-level template compilation.
Parameters:
source(string): Template source codeoptions(table): Compilation options
Returns: (table) Compiled template with metadata
Example:
local compiler = require("luma.compiler")
local compiled = compiler.compile(source, {name = "mytemplate"})
-- Access metadata
print("Template name:", compiled.name)
print("Source:", compiled.source) -- Generated Lua code
print("Dependencies:", #compiled.dependencies)
compiled:render(context, filters, runtime, macros, tests)
Render a compiled template.
Parameters:
context(table): Template variablesfilters(table): Available filtersruntime(table): Runtime utilitiesmacros(table, optional): Pre-defined macrostests(table, optional): Test functions
Returns: (string) Rendered output
Runtime API
runtime.escape(value, column)
HTML-escape a value.
Parameters:
value(any): Value to escapecolumn(number, optional): Column for error reporting
Returns: (string) HTML-escaped string
Example:
local runtime = require("luma.runtime")
local escaped = runtime.escape("<script>alert('xss')</script>")
-- Returns: "<script>alert('xss')</script>"
runtime.set_paths(paths)
Set template search paths.
Parameters:
paths(table): Array of directory paths
Example:
local runtime = require("luma.runtime")
runtime.set_paths({"/usr/share/templates", "./templates", "."})
runtime.load_source(name)
Load template source by name.
Parameters:
name(string): Template name or path
Returns:
-
source(stringnil): Template source -
error(stringnil): Error message if not found
Example:
local runtime = require("luma.runtime")
local source, err = runtime.load_source("layout.luma")
if not source then
error("Template not found: " .. err)
end
runtime.namespace(initial)
Create a mutable namespace object for templates.
Parameters:
initial(table, optional): Initial values
Returns: (table) Namespace object
Example (in template):
{% set ns = namespace(count=0) %}
{% for item in items %}
{% do ns.count = ns.count + 1 %}
{% endfor %}
Total: {{ ns.count }}
Filters API
Built-in Filters
String Filters
upper - Convert to uppercase
{{ "hello" | upper }} -- "HELLO"
lower - Convert to lowercase
{{ "HELLO" | lower }} -- "hello"
title - Title case
{{ "hello world" | title }} -- "Hello World"
capitalize - Capitalize first letter
{{ "hello" | capitalize }} -- "Hello"
trim - Remove whitespace
{{ " hello " | trim }} -- "hello"
truncate(length, end) - Truncate string
{{ "Long text" | truncate(5) }} -- "Long..."
{{ "Long text" | truncate(5, "…") }} -- "Long…"
replace(old, new) - Replace substring
{{ "hello world" | replace("world", "Lua") }} -- "hello Lua"
List Filters
length - Get length
{{ items | length }} -- number of items
join(sep) - Join list elements
{{ ["a", "b", "c"] | join(", ") }} -- "a, b, c"
first - First element
{{ items | first }}
last - Last element
{{ items | last }}
sort - Sort list
{{ [3, 1, 2] | sort }} -- [1, 2, 3]
reverse - Reverse list
{{ [1, 2, 3] | reverse }} -- [3, 2, 1]
Numeric Filters
abs - Absolute value
{{ -5 | abs }} -- 5
round(precision) - Round number
{{ 3.14159 | round(2) }} -- 3.14
format(fmt) - Format number
{{ 1234.5 | format("%.2f") }} -- "1234.50"
Date/Time Filters
date(format) - Format timestamp
{{ timestamp | date("%Y-%m-%d") }}
Misc Filters
default(value) - Default if nil/empty
{{ var | default("N/A") }}
escape - HTML escape (alias: e)
{{ "<script>" | escape }} -- "<script>"
Custom Filters
Define custom filter:
local filters = require("luma.filters")
filters.add("double", function(value)
return value * 2
end)
filters.add("greet", function(name, greeting)
greeting = greeting or "Hello"
return greeting .. ", " .. name .. "!"
end)
Use in template:
{{ 5 | double }} -- 10
{{ "Alice" | greet }} -- "Hello, Alice!"
{{ "Bob" | greet("Hi") }} -- "Hi, Bob!"
Python Bindings
Template Class
from luma import Template
# Create template
template = Template("Hello, {{ name }}!", syntax="jinja")
# Render with kwargs
result = template.render(name="World")
# Render with dict
result = template.render_dict({"name": "World"})
# String representation
print(repr(template)) # <Template source="...">
Environment Class
from luma import Environment
from luma.loaders import FileSystemLoader
# Create environment
env = Environment(
loader=FileSystemLoader("/path/to/templates"),
autoescape=True
)
# Set globals
env.globals["site_name"] = "My Site"
# Add filter
env.filters["double"] = lambda x: x * 2
# Render template
template = env.get_template("page.html")
result = template.render(title="Home", items=[1, 2, 3])
Loaders
FileSystemLoader:
from luma.loaders import FileSystemLoader
loader = FileSystemLoader("/templates", encoding="utf-8")
DictLoader:
from luma.loaders import DictLoader
loader = DictLoader({
"index.html": "Hello, {{ name }}!",
"about.html": "About page",
})
PackageLoader:
from luma.loaders import PackageLoader
loader = PackageLoader("myapp", "templates")
Exceptions
from luma.exceptions import (
TemplateError,
TemplateSyntaxError,
TemplateNotFoundError,
)
try:
result = template.render(**data)
except TemplateSyntaxError as e:
print(f"Syntax error: {e}")
except TemplateError as e:
print(f"Template error: {e}")
Error Handling
Compilation Errors
local luma = require("luma")
local ok, compiled = pcall(function()
return luma.compile(template_source)
end)
if not ok then
-- compiled contains error message
print("Compilation failed:", compiled)
end
Runtime Errors
local ok, result = pcall(function()
return compiled:render(context, filters, runtime)
end)
if not ok then
print("Runtime error:", result)
end
Error Messages
Luma provides detailed error messages with:
- Line and column numbers
- Context snippet
- Error description
- Stack trace
Example error:
ParseError: Expected 'end' after 'for' block
at template.luma:15:1
13 | @for item in items
14 | - {{ item }}
> 15 | @if condition
Performance Tips
-
Compile Once, Reuse Many Times
local compiled = luma.compile(template) for i = 1, 1000 do compiled:render(data, filters, runtime) end50-100x faster than re-compiling each time
- Use Native Syntax
- Luma native syntax is cleaner and slightly faster
- Jinja2 syntax has minimal overhead
- Pre-structure Data
- Prepare data before rendering
- Avoid complex transformations in templates
-
Cache Compiled Templates
local cache = {} function get_template(name) if not cache[name] then local source = load_template_source(name) cache[name] = luma.compile(source) end return cache[name] end
Thread Safety
- Compiled templates are read-only and thread-safe
- Context data should be unique per render
- Filters and runtime are stateless and safe to share
Multi-threaded example (conceptual):
local compiled = luma.compile(template) -- Shared
local filters = require("luma.filters").get_all() -- Shared
local runtime = require("luma.runtime") -- Shared
-- In each thread:
local result = compiled:render(
{user = thread_specific_user}, -- Thread-local context
filters,
runtime
)