Rendering Engine
lua_spa.renderer
The server-side template engine that converts .lspa templates into HTML before the page is sent to the browser.
Processing pipeline
Each pass operates on the string produced by the previous pass. This ordering ensures:
- Loop bodies can contain conditionals
- Conditionals can contain
{{ }}expressions - Expressions are always evaluated last on final content
render_template_with_directives(template, context)
Main entry point. Accepts a template string and a context dict (props, state, py).
html = render_template_with_directives(
"<p l-if=\"count > 0\">{{ count }}</p>",
{"state": {"count": 3}, "props": {}, "py": {}}
)
# "<p>3</p>"
Loop expansion (i-for)
Multi-target unpacking is supported:
<li i-for="i, item in enumerate(items)">{{ i }}: {{ item }}</li>
Nested loops work by re-running the pass until no more i-for attributes remain.
Conditional rendering (l-if)
Interpolation ({{ }})
All {{ expr }} tokens in the final string are replaced by evaluating expr in a safe Python context:
_SAFE_EVAL_GLOBALS = {
"__builtins__": {},
"range": range,
"len": len,
"enumerate": enumerate,
}
The template context adds state, props, and py on top of these globals.
Context object
context = {
"state": {...}, # from client() state spec
"props": {...}, # from parent or initial_props
"py": {...}, # from context(props) return value
}
build_python_context(props, component) and build_server_state(component) in renderer.py assemble this dict before rendering.