summaryrefslogtreecommitdiff
path: root/html.lua
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-10-31 04:02:07 +0000
committerubq323 <ubq323@ubq323.website>2024-10-31 04:02:07 +0000
commit664f471c774d6182efb0f9c4d4c9af9857b1bf52 (patch)
tree3a5194457841cce4f3e2d7acfe0a53e24a2d39cf /html.lua
initial commit
Diffstat (limited to 'html.lua')
-rw-r--r--html.lua87
1 files changed, 87 insertions, 0 deletions
diff --git a/html.lua b/html.lua
new file mode 100644
index 0000000..87ecc53
--- /dev/null
+++ b/html.lua
@@ -0,0 +1,87 @@
+local function fmt_attrs(attrs)
+ local function fmt_attr(k,v)
+ if v == true then
+ return k
+ else
+ if type(v) == "table" then v = table.concat(v," ") end
+ return ('%s="%s"'):format(k,v)
+ end
+ end
+
+ local o = ""
+ for k,v in pairs(attrs) do
+ o = o .. " " .. fmt_attr(k,v)
+ end
+ return o
+end
+
+local html
+local function fmt_tag(tag)
+ local attrs = tag.attrs and fmt_attrs(tag.attrs) or ""
+ local selfclosing = (tag.body == "")
+ local sameline = type(tag.body) == "string" or (type(tag.body) == "table" and tag.body.tag)
+ local maybenl = sameline and "" or "\n"
+ if selfclosing then
+ return ("<%s%s/>"):format(tag.tname,attrs)
+ else
+ return ("<%s%s>%s%s</%s>"):format(tag.tname,attrs,maybenl,html(tag.body),tag.tname)
+ end
+end
+
+local function tag(tname, a1, a2)
+ -- tag(tname,body) or tag(tname,attrs,body)
+ local body, attrs
+ if a2 then attrs=a1 body=a2 else attrs=nil body=a1 end
+ return setmetatable({tag=true,tname=tname,attrs=attrs,body=body},{__tostring=fmt_tag})
+end
+
+-- instead of tag('ul', {x, y, z})
+-- you can do T.ul{ x, y, z}
+local T = setmetatable({}, {__index=function(_,tname)
+ return function (...)
+ return tag(tname, ...)
+ end
+end})
+
+local function safe(s)
+ -- marks s as safe, doesn't escape it
+ assert(type(s) == "string","can only mark string as safe")
+ return setmetatable({safe=true,s=s},{__tostring=function(x)return x.s end})
+end
+
+local function escape(s)
+ s=s:gsub("&","&amp;")
+ s=s:gsub("<","&lt;")
+ s=s:gsub(">","&gt;")
+ s=s:gsub('"',"&quot;")
+ return safe(s)
+end
+
+
+html = function (x)
+ if type(x) == "string" then
+ return escape(x)
+ elseif type(x) == "table" then
+ if x.safe then
+ -- safestr. already escaped
+ return x
+ elseif x.tag then
+ -- it's a tag
+ return safe( tostring(x) )
+ else
+ -- just a regular list
+ local o = ""
+ for _,item in ipairs(x) do
+ o = o .. tostring(html(item)) .. "\n"
+ end
+ return safe(o)
+ end
+ end
+end
+
+return {
+ html = html,
+ tag = tag,
+ safe = safe,
+ T = T,
+}