Template Rendering using Lua Templates

Marc Balmer
4 min readJan 3, 2021

--

Lua Templates is a multi-purpose template rendering engine used to create output in various formats, e.g. HTML pages, plain text, or, LaTeX source files from a template. Lua Templates can contain Lua code or Lua expressions (whence the name), but there is also a powerful mechanism to extend existing templates by re-defining named blocks found in the base template (one could call this an “inheritance” mechanism, and it is actually similar to Django’s block mechanism.)

How Lua Templates Work

Lua Templates are converted to Lua source code, compiled to bytecode and executed when they are parsed for the first time. This generates the output, optionally escaping the output for the target format. On subsequent calls of the same template, the already compiled Lua code is executed directly to render the template. No new parsing is done. This way, templates are rendered fast and high transaction rates e.g. for web applications can be achieved.

For security reasons, the Lua code generated from a template is executed in a sandbox without access to values in the calling code. The normal operation mode is to provide the values that the template expects to the sandbox then call the Lua function that corresponds to the template being rendered.

The conversion from Lua Templates to Lua code is done in a Lua Templates specific reader function that is passed to a lua_load() call. This function is written in the C language.

Template Syntax

Lua Templates are textfiles in any encoding, containing markup in <%%> brackets. When rendering a template, the following rules apply:

  • Regular text, i.e. text not containing any markup, is output as is.
  • Text in <%%> brackets is interpreted as Lua code and executed when the template is rendered. There is normally no output.
  • Text in <%=%> brackets is interpreted as a Lua expression and the result of the expression is inserted in the output. After the equal sign, an optional format specifier conforming to string.format() format specifiers can be added, e.g. to create output with fixed width.
  • Text in <%=escaping%> brackets is interpreted as a Lua expression and the result of the expression is escaped according to escaping and then inserted in the output. For possible values of escaping, see the list below.

Template Commands

  • Text in <%!%> brackets is interpreted as a Lua Template command The following commands are currently defined:
  • block name. Define a named block.
  • endblock. End a block definition.
  • escape. Define the standard escaping for <%=%> expressions.
  • extends name. Indicate that this template extends the template name. The contents of blocks defined in this template with <%! block name %><%! endblock %> will replace the corresponding blocks in the template that is being extended.

Important: The extends command must be the first command in a template. There is no need to re-define all blocks in the base template, only those that are to be modified (e.g. a page title and the contents, but not the page header and footer). Multi-level extension of templates is possible (and usually makes sense).

  • include name. Insert a template in the output.

The name argument of the block, extends, and, include command can be put in single or double quotes or no quotes at all.

In Lua code, the function print() can be used to output arbitrary data. print() expects a single string as argument.

Available Output Escapings

  • html. Escape the output as HTML code.
  • xml. Escape the output as XML code .
  • latex. Escape the output as LaTeX code.
  • none. Don’t escape the output.
  • url. Escape the output as a URL.

Example

<html><body>
<% for n = 1, 5 do %>
This is line <%= n %> : <%=%20d n %><br>
<% end %>
</body></html>

Example output

<html><body>
This is line 1 : 1<br>
This is line 2 : 2<br>
This is line 3 : 3<br>
This is line 4 : 4<br>
This is line 5 : 5<br>
</body></html>

Extending a Template with “extends”

Template base.html as base template

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title><%! block title %>My amazing site<%! endblock %></title>
</head>
<body>
<div id="sidebar">
<%! block sidebar %>
<ul>
<li><a href="/">Home</a></li>
<li><ahref="/blog/">Blog</a></li>
</ul>
<%! endblock %>
</div>
<div id="content">
<%! block content %><%! endblock %>
</div>
</body>
</html>

Template child.html extends base.html

<%! extends base.html %><%! block title %>My amazing blog<%! endblock %><%! block content %><% for k, entry in pairs(blog_entries) do %>
<h2><%= entry.title %></h2>
<p><%= entry.body %></p>
<% end %>
<%! endblock %>

Using the “template” Lua Module

Lua templates are a Lua module that you must first load using the “require” command.

Once loaded, first a rendering context must be created. This context can then be used to render templates, passing data to the engine. The data passed to the rendering engine can change from call to call. Note that the template is processed only once, on the first call.

Rendered output goes to stdout by default. If the rendered data is to be collected to later output, a collection function must be provided when calling the rendering function.

local template = require 'template'local msg = {}local function collect(text)
msg[#msg + 1] = text
end
-- create a new rendering context
local ctx = template.context()
data = {
title = 'Hello, world!',
b = 42,
}
-- ctx:debug(true)
ctx:renderFile(arg[1] or 'sample.lt', data, collect)
print(table.concat(msg))
-- render a second time
ctx:renderFile(arg[1] or 'sample.lt', data)

Getting the Source Code

The source code for the Lua template rendering module and some examples can be found on Github at github.com/arcapos/luatemplate.

--

--

Written by Marc Balmer

Unix Developer. Loves PostgreSQL, C, Lua, and, Flutter. Uses HTML and CSS.

Responses (1)

Write a response