login

<     >

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}} --&gt; {{!$html}}\n"
+    local r = render(str, env)
+    assert(r == "&#60;p&#62;foo&#60;/p&#62; --&gt; <p>foo</p>\n")
+end
+
 return Suite