-- 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"):format(tag.tname,attrs) else return ("<%s%s>%s%s"):format(tag.tname,attrs,maybenl,html(tag.body),tag.tname) end end 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 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 h3 p b i ul ol li dl dt dd div section header figure figcaption img title nav" 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 function mkhead(t,nositename) -- includes css and stuff, and title element if not nositename then t = t .. ' - ubq323.website' end return { safereadf "head.html", title(t), } end function mktopbox(imgsrc,name,rest) return header({class="big-header"}, { img({id='me',src=imgsrc},''), h1(name), rest }) end function mksmalltopbox(words) return header ({class="small-header"}, { h1(words) }) end function bcrumb(items) -- items are {text,href} local lis = {} for _,it in ipairs(items) do if it[2] then table.insert(lis, li(a(it[1],it[2]))) else table.insert(lis,li(it[1])) end end return nav( {class='breadcrumb',['aria-label']='Breadcrumb'}, ol(lis) ) end function blogpost(meta,content) local head = mkhead(meta.title.." - rebecca blog") local top = header { img({id='me',src='/me.png'},''), h1 'rebecca blog', p [[ there is some text here ]], } local breadcrumbs = bcrumb { {'⌂ home','/'}, {'rebecca blog','/blog'}, {meta.title}, } return html{head,top,breadcrumbs,content} end -- the box at the top with the cool picture of me in, etc -- presumably the same on all pages site_top = mktopbox('/me.png',"ubq323's website", p [[rebecca, "ubq323" (she/her, 20s) - effervescently engromulent]] )