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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
-- possible things that thing can be:
-- string: gets escaped
-- safe-str: returned as is
-- table list: concatentated
-- tag: printified
-- maths
local el=math.exp(-4.79)
function blorem() local o={} for i=1,math.random(25,150) do local i,u=0,1 repeat i=i+1 u=u*math.random() until u<el table.insert(o, ("b"):rep(i)) end return table.concat(o," ") end
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 function fmt_tag(tag)
local a = tag.attrs and fmt_attrs(tag.attrs) or ""
local bf
if type(tag.body) == "string" or (type(tag.body) == "table" and tag.body.tag) then
bf = "%s"
else
bf = "\n%s"
end
return ("<%s%s>"..bf.."</%s>"):format(tag.tname,a,html(tag.body),tag.tname)
end
function tag(tname, a1, a2)
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
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
function escape(s)
s=s:gsub("&","&")
s=s:gsub("<","<")
s=s:gsub(">",">")
s=s:gsub('"',""")
return safe(s)
end
function html(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
function tagfn(tname)
return function(a1,a2) return tag(tname,a1,a2) end
end
function qw(s)
local t = {}
for a in s:gmatch("%w+") do table.insert(t,a) end
return t
end
local tnames = qw"h1 h2 p b ul li dl dt dd div section header figure figcaption"
for _,n in ipairs(tnames) do
_G[n] = tagfn(n)
end
function a(b,href) return tag("a",{href=href},b) end
function readf(fname)
local f = io.open(fname,"r")
local c = f:read("a")
f:close()
return c
end
function safereadf(fname) return safe(readf(fname)) end
|