1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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("&","&")
s=s:gsub("<","<")
s=s:gsub(">",">")
s=s:gsub('"',""")
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,
}
|