-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathruntime.lua
More file actions
116 lines (110 loc) · 3.42 KB
/
runtime.lua
File metadata and controls
116 lines (110 loc) · 3.42 KB
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
103
104
105
106
107
108
109
110
111
112
113
114
115
local markdown = require("markdown")
-- md renders a markdown string to an html string. This is mainly for convience in dealing with long form written posts.
-- They don't need to be part of the component rendering system
function md(s)
return {__safe=true, markdown(s)}
end
-- safe performs some basic escaping of html values so that text can be put in an html page without needing to worry about parsing issues.
-- I'm sure I missed some values in here that should be escaped I'll add them at a later point
local function safe(s)
s = string.gsub(s, "[&<>'\"]", {
["&"]="&",
["<"]="<",
[">"]=">",
["'"]="'",
["\""]=""",
})
return s
end
local selfClosing = {
area = true,
base = true,
br = true,
col = true,
embed = true,
hr = true,
img = true,
input = true,
link = true,
meta = true,
param = true,
source = true,
track = true,
wbr = true
}
-- render is the function that does all the work. It takes tables, and recursively uses the write function to render them.
-- the basic structure of the 'node' table is `{__name="div", child, child, arg1="value" arg2="value2"}`
function render(node, write)
-- if a name is set, then this is an html node, so lets render its opening tag with its parameters
-- This also allow us to nest tables and then unest them: {{{"some"}, "text"}, "content"}
if node.__name ~= nil then
-- write the start of the node "<div"
write("<",node.__name)
-- NOTE: we use pairs to grab all the key=value members
-- this lets us deal with only the attributes: {id="me"}
for idx, value in pairs(node) do
if type(idx) == "string" and idx ~= "__name" then
-- we can accept a table of strings and write all of them out.
-- this is to support setting multiple classes on a node:
-- class={"first", "second"}
-- This way we can dynamically add to the classes without needing to combine them into a single string
if type(value) == "table" then
-- " id="
write(' ',idx,'="')
local first = ""
for _,v in ipairs(value) do
write(first, safe(v))
first = " "
end
write('"')
else
-- just a simple value, lets write it out
write(' ',idx,'="',value,'"')
end
end
end
if selfClosing[node.__name] then
write("/")
end
write(">")
end
-- self closing elements, or void elements, can not have a body
if selfClosing[node.__name] then
return
end
-- Now we have an opening tag, we can continue and write out the children on this node.
-- NOTE: we are using ipairs to specifically loop over the table as if it was an array
-- this allows us to only deal with the children: {"asdf","foo"}
local first = ""
for idx, child in ipairs(node) do
if type(child) == "table" then
render(child, write)
elseif type(child) == "string" then
if node.__safe then
write(first, child)
else
write(first, safe(child))
end
end
first = " "
end
if node.__name ~= nil then
write("</",node.__name, ">")
end
end
local oldRequire = require
require = function(path)
return oldRequire("lua/endpoints/" .. path)
end
-- This sets up the global envrionment
local G = _G
local newGT = {}
setmetatable(newGT,{
__index= function(_, n)
return G[n] or function(params)
params.__name=n
return params
end
end,
})
setfenv(0, newGT)