lua-resty-template is a compiling (1) (HTML) templating engine for Lua and OpenResty.
(1) with compilation we mean that templates are translated to Lua functions that you may call or string.dump
as a binary bytecode blobs to disk that can be later utilized with lua-resty-template or basic load and
loadfile standard Lua functions (see also Template Precompilation). Although,
generally you don't need to do that as lua-resty-template handles this behind the scenes.
Hello World with lua-resty-template
local template =require"resty.template"-- ORlocal template =require"resty.template.safe"-- return nil, err on errors-- Using template.newlocal view = template.new"view.html"
view.message="Hello, World!"
view:render()
-- Using template.render
template.render("view.html", { message ="Hello, World!" })
{{expression}}, writes result of expression - html escaped
{*expression*}, writes result of expression
{% lua code %}, executes Lua code
{(template)}, includes template file, you may also supply context for include file {(file.html, { message = "Hello, World" } )} (NOTE: you cannot use comma (,) in file.html, in that case use {["file,with,comma"]} instead)
{[expression]}, includes expression file (the result of expression), you may also supply context for include file {["file.html", { message = "Hello, World" } ]}
{-block-}...{-block-}, wraps inside of a {-block-} to a value stored in a blocks table with a key block (in this case), see using blocks. Don't use predefined block names verbatim and raw.
{-verbatim-}...{-verbatim-} and {-raw-}...{-raw-} are predefined blocks whose inside is not processed by the lua-resty-template but the content is outputted as is.
{# comments #} everything between {# and #} is considered to be commented out (i.e. not outputted or executed)
From templates you may access everything in context table, and everything in template table.
In templates you can also access context and template by prefixing keys.
If you don't want a particular template tag to be processed you may escape the starting tag with backslash \:
<h1>\{{message}}</h1>
This will output (instead of evaluating the message):
<h1>{{message}}</h1>
If you want to add backslash char just before template tag, you need to escape that as well:
<h1>\\{{message}}</h1>
This will output:
<h1>\[message-variables-content-here]</h1>
A Word About Complex Keys in Context Table
Say you have this kind of a context table:
local ctx = {["foo:bar"] ="foobar"}
And you want to render the ctx["foo:bar"]'s value foobar in your template. You have to specify it explicitly
by referencing the context in your template:
{# {*["foo:bar"]*} won't work, you need to use: #}
{*context["foo:bar"]*}
Only strings are escaped, functions are called without arguments (recursively) and results are returned as is,
other types are tostringified. nils and ngx.nulls are converted to empty strings "".
It is advised that you do not use these keys in your context tables:
___, holds the compiled template, if set you need to use {{context.___}}
context, holds the current context, if set you need to use {{context.context}}
echo, holds the echo helper function, if set you need to use {{context.echo}}
include, holds the include helper function, if set you need to use {{context.include}}
layout, holds the layout by which the view will be decorated, if set you need to use {{context.layout}}
blocks, holds the blocks, if set you need to use {{context.blocks}} (see: using blocks)
template, holds the template table, if set you need to use {{context.template}}
In addition to that with template.new you should not overwrite:
render, the function that renders a view, obviously ;-)
You should also not {(view.html)} recursively:
Lua
template.render"view.html"
view.html
{(view.html)}
You can load templates from "sub-directories" as well with {(syntax)}:
view.html
{(users/list.html)}
Also note that you can provide template either as a file path or as a string. If the file exists,
it will be used, otherwise the string is used. See also template.load.
Installation
Just place template.lua and
template directory somewhere in
your package.path, under resty directory. If you are using OpenResty, the default location would
be /usr/local/openresty/lualib/resty.
If none of these are set in Nginx configuration, ngx.var.document_root (aka root-directive) value is used.
If template_location is set, it will be used first, and if the location returns anything but 200 as
a status code, we do fallback to either template_root (if defined) or document_root.
With lua-resty-template2.0 it is possible to override $template_root and $template_location with
Lua code:
local template =require"resty.template".new({
root ="/templates",
location ="/templates"
})
Using document_root
This one tries to load file content with Lua code from html directory (relative to Nginx prefix).
You can setup template root by setting this variable which will be looked for template files:
local template =require"resty.template".new({
root ="/templates"
})
template.render_file("test.html")
This property overrides the one set in Nginx configuration (set $template_root /my-templates;)
template.location
This is what you can use with OpenResty as that will use ngx.location.capture to fetch templates
files in non-blocking fashion.
local template =require"resty.template".new({
location ="/templates"
})
template.render_file("test.html")
This property overrides the one set in Nginx configuration (set $template_location /my-templates;)
table template.new(view, layout)
Creates a new template instance that is used as a (default) context when rendered. A table that gets created has
only one method render, but the table also has metatable with __tostring defined. See the example below. Both
view and layout arguments can either be strings or file paths, but layout can also be a table created previously
with template.new.
With 2.0 the new can also be used without arguments, which creates a new template instance:
local template =require"resty.template".new()
You can also pass a table that is then modified to be a template:
local config = {
root ="/templates"
}
local template =require"resty.template".new(config)
This is handy as the template created by new does not share the cache with the global template returned
by require "resty.template" (this was reported with issue #25).
You can also pass a boolean true or false as a view parameter which means that either safe or un-safe
version of template is returned:
local unsafe =require"resty.template"local safe = unsafe.new(true)
There is also a default safe implementation available:
local safe =require"resty.template.safe"-- you can create instance of safe too:local safe_instance = safe.new()
safe version uses return nil, err Lua error handling pattern and unsafe just throws the errors, which you
can catch with pcall, xpcall or coroutine.wrap.
local template =require"resty.template"local view = template.new"view.html"
view.message="Hello, World!"
view:render()
-- You may also replace context on render
view:render{ title ="Testing lua-resty-template" }
-- If you want to include view context in replacement context
view:render(setmetatable({ title ="Testing lua-resty-template" }, { __index = view }))
-- To get rendered template as a string, you can use tostringlocal result =tostring(view)
boolean template.caching(boolean or nil)
This function enables or disables template caching, or if no parameters are passed, returns current state of
template caching. By default template caching is enabled, but you may want to disable it on development or
low-memory situations.
local template =require"resty.template"-- Get current state of template cachinglocal enabled = template.caching()
-- Disable template caching
template.caching(false)
-- Enable template caching
template.caching(true)
Please note that if the template was already cached when compiling a template, the cached version will be returned.
You may want to flush cache with template.cache = {} to ensure that your template really gets recompiled.
Parses, compiles and caches (if caching is enabled) a template and returns the compiled template as a function
that takes context as a parameter and returns rendered template as a string. Optionally you may pass cache_key that
is used as a cache key. If cache key is not provided view wil be used as a cache key. If cache key is no-cache
the template cache will not be checked and the resulting function will not be cached. You may also optionally
pass plain with a value of true if the view is plain text string (this will skip template.load and binary
chunk detection in template.parse phase). If plain is false the template is considered to be a file,
and all the issues with file reading are considered as errors. If the plain is set to nil (the default)
the template does not consider file reading errors as fatal, and returns back the view (usually the path of
the template).
local func = template.compile("template.html") -- orlocal func = template.compile([[<h1>{{message}}</h1>]])