2022-02-27 09:11:06 (UTC-03:00)
Marcel Rodrigues <marcelgmr@gmail.com>
template: escape HTML by default
diff --git a/src/template.lua b/src/template.lua index 4eb0a5d..245a628 100644 --- a/src/template.lua +++ b/src/template.lua @@ -1,3 +1,17 @@ +local function escape(str) + local esc_tab = {["&"]=38, ["<"]=60, [">"]=62, ["{"]=123, ["}"]=125} + local esc = "" + for i = 1, #str do + local c = str:sub(i, i) + local n = esc_tab[c] + if n ~= nil then + c = "&#" .. n .. ";" + end + esc = esc .. c + end + return esc +end + local function eval(str, env) local expr = str:gsub("%$(%w+)", "env.%1") local code = "return function(env) return "..expr.." end" @@ -29,7 +43,8 @@ end local function render_block(lines, first, last, env) local result = "" - local function sub(s) return eval(s, env) end + local function raw_sub(s) return eval(s, env) end + local function esc_sub(s) return escape(tostring(eval(s, env))) end local line_num = first while line_num <= last do local line = lines[line_num] @@ -66,9 +81,10 @@ local function render_block(lines, first, last, env) end line_num = block_end + 1 else - local computed = line:gsub("{{(.-)}}", sub) - if #computed > 0 then - result = result .. computed .. "\n" + local line = line:gsub("{{([^!].-)}}", esc_sub) + local line = line:gsub("{{!(.-)}}", raw_sub) + if #line > 0 then + result = result .. line .. "\n" end line_num = line_num + 1 end @@ -91,18 +107,4 @@ local function render_file(fname, env) return render_str(str, env) end -local function escape(str) - local esc_tab = {["&"]=38, ["<"]=60, [">"]=62} - local esc = "" - for i = 1, #str do - local c = str:sub(i, i) - local n = esc_tab[c] - if n ~= nil then - c = "&#" .. n .. ";" - end - esc = esc .. c - end - return esc -end - -return {render_str=render_str, render_file=render_file, escape=escape} +return {escape=escape, render_str=render_str, render_file=render_file} diff --git a/test/test_template.lua b/test/test_template.lua index cf72382..13d4cbc 100644 --- a/test/test_template.lua +++ b/test/test_template.lua @@ -80,4 +80,11 @@ function Suite.render_for() assert(r == "i = 2\ni = 3\ni = 5\n") end +function Suite.render_raw() + local env = {html="<p>foo</p>"} + local str = "{{$html}} --> {{!$html}}\n" + local r = render(str, env) + assert(r == "<p>foo</p> --> <p>foo</p>\n") +end + return Suite