limitations under the License.
]]--
+
+--- LuCI template library.
module("luci.template", package.seeall)
require("luci.config")
require("luci.util")
require("luci.fs")
+require("luci.sys")
require("luci.http")
luci.config.template = luci.config.template or {}
-viewdir = luci.config.template.viewdir or luci.sys.libpath() .. "/view"
-compiledir = luci.config.template.compiledir or luci.sys.libpath() .. "/view"
+viewdir = luci.config.template.viewdir or luci.util.libpath() .. "/view"
+compiledir = luci.config.template.compiledir or luci.util.libpath() .. "/view"
-- Compile modes:
include = function(name) Template(name):render(getfenv(2)) end,
}
--- Compiles a given template into an executable Lua module
+--- Manually compile a given template into an executable Lua function
+-- @param template LuCI template
+-- @return Lua template function
function compile(template)
- -- Search all <% %> expressions (remember: Lua table indexes begin with #1)
- local function expr_add(command)
+ -- Search all <% %> expressions
+ local function expr_add(ws1, skip1, command, skip2, ws2)
table.insert(expr, command)
- return "<%" .. tostring(#expr) .. "%>"
+ return ( #skip1 > 0 and "" or ws1 ) ..
+ "<%" .. tostring(#expr) .. "%>" ..
+ ( #skip2 > 0 and "" or ws2 )
end
-- As "expr" should be local, we have to assign it to the "expr_add" scope
luci.util.extfenv(expr_add, "expr", expr)
-- Save all expressiosn to table "expr"
- template = template:gsub("<%%(.-)%%>", expr_add)
+ template = template:gsub("(%s*)<%%(%-?)(.-)(%-?)%%>(%s*)", expr_add)
local function sanitize(s)
- s = luci.util.escape(s)
- s = luci.util.escape(s, "'")
- s = luci.util.escape(s, "\n")
- return s
+ s = string.format("%q", s)
+ return s:sub(2, #s-1)
end
-- Escape and sanitize all the template (all non-expressions)
template = sanitize(template)
-- Template module header/footer declaration
- local header = "write('"
- local footer = "')"
+ local header = 'write("'
+ local footer = '")'
template = header .. template .. footer
-- Replacements
- local r_include = "')\ninclude('%s')\nwrite('"
- local r_i18n = "'..translate('%1','%2')..'"
- local r_i18n2 = "'..translate('%1', '')..'"
- local r_pexec = "'..(%s or '')..'"
- local r_exec = "')\n%s\nwrite('"
+ local r_include = '")\ninclude("%s")\nwrite("'
+ local r_i18n = '"..translate("%1","%2").."'
+ local r_i18n2 = '"..translate("%1", "").."'
+ local r_pexec = '"..(%s or "").."'
+ local r_exec = '")\n%s\nwrite("'
-- Parse the expressions
for k,v in pairs(expr) do
local p = v:sub(1, 1)
+ v = v:gsub("%%", "%%%%")
local re = nil
if p == "+" then
re = r_include:format(sanitize(string.sub(v, 2)))
end
elseif p == "=" then
re = r_pexec:format(v:sub(2))
+ elseif p == "#" then
+ re = ""
else
re = r_exec:format(v)
end
return loadstring(template)
end
--- Oldstyle render shortcut
+--- Render a certain template.
+-- @param name Template name
+-- @param scope Scope to assign to template
function render(name, scope, ...)
scope = scope or getfenv(2)
local s, t = luci.util.copcall(Template, name)
if source then
local compiled, err = compile(source)
- luci.fs.writefile(compiledfile, luci.util.dump(compiled))
+ luci.fs.writefile(compiledfile, luci.util.get_bytecode(compiled))
self.template = compiled
end
else