summaryrefslogtreecommitdiff
path: root/h.lua
blob: b36c8553fd274974e1490b5f0cc6f7e5820e5cdb (plain)
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("&","&amp;")
	s=s:gsub("<","&lt;")
	s=s:gsub(">","&gt;")
	s=s:gsub('"',"&quot;")
	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