1
0
mirror of https://github.com/lxsang/antd-web-apps synced 2024-12-28 02:08:22 +01:00
antd-web-apps/doc/controllers/doccontroller.lua

280 lines
10 KiB
Lua
Raw Normal View History

2020-06-22 22:14:52 +02:00
BaseController:subclass("DocController")
local getpath = function(vfspath, controller)
2020-09-13 15:41:39 +02:00
return vfspath:gsub(controller.path_map.vfs_path,
controller.path_map.local_path)
end
local pre_process_md = function(str, obj)
local content = str
for capture in str:gmatch("(%[%[@book:image:[^\n%]]*%]%])") do
local apath = capture:match("%[%[@book:image:([^\n%]]*)%]%]")
2020-09-22 17:58:37 +02:00
local pattern = capture:gsub("%[", "%%["):gsub("%]", "%%]"):gsub("%-",
"%%-")
2020-09-13 15:41:39 +02:00
if apath then
apath = apath:gsub(" ", "%%%%20")
print(apath)
2020-09-13 15:41:39 +02:00
content = str:gsub(pattern,
"![](" .. HTTP_ROOT .. "/" .. obj.name ..
"/asset/" .. apath .. ")")
end
end
return content
2020-06-22 22:14:52 +02:00
end
local post_process_md = function(str, obj)
local content = str
local has_model = false
2020-09-15 10:28:36 +02:00
-- 3D model
for capture in str:gmatch("(%[%[@book:3dmodel:[^\n%]]*%]%])") do
local apath = capture:match("%[%[@book:3dmodel:([^\n%]]*)%]%]")
2020-09-22 17:58:37 +02:00
local pattern = capture:gsub("%[", "%%["):gsub("%]", "%%]"):gsub("%-",
"%%-")
if apath then
2020-09-22 17:58:37 +02:00
-- apath = utils.urlencode(apath):gsub("%%", "%%%%")
apath = apath:gsub(" ", "%%20")
content = str:gsub(pattern,
"<model-viewer src=\"" .. HTTP_ROOT .. "/" ..
obj.name .. "/asset/" .. apath ..
"\" auto-rotate camera-controls></model-viewer>")
has_model = true
end
end
2020-09-15 10:28:36 +02:00
-- Youtube video
for capture in str:gmatch("(%[%[youtube:[^\n%]]*%]%])") do
local apath = capture:match("%[%[youtube:([^\n%]]*)%]%]")
2020-09-22 17:58:37 +02:00
local pattern = capture:gsub("%[", "%%["):gsub("%]", "%%]"):gsub("%-",
"%%-")
2020-09-15 10:28:36 +02:00
if apath then
2020-09-15 10:29:39 +02:00
content = content:gsub(pattern,
2020-09-22 17:58:37 +02:00
"<iframe style='width:100%%;height: auto;min-height: 400px;' src=\"https://www.youtube.com/embed/" ..
apath .. "\"> </iframe>")
2020-09-15 10:28:36 +02:00
end
2020-09-22 17:58:37 +02:00
end
2020-09-15 10:28:36 +02:00
return content, has_model
end
2020-06-22 22:14:52 +02:00
function DocController:loadTOC()
2020-09-13 15:41:39 +02:00
local path = self.path_map.local_path .. "/meta.json"
local result = {error = false}
2020-06-22 22:14:52 +02:00
if ulib.exists(path) then
local bmeta = JSON.decodeFile(path)
if bmeta == nil then
result.error = true
result.data = "Unable to read book meta.json"
else
result.data = {
name = bmeta.name,
2020-09-13 15:41:39 +02:00
path = self.path_map.vfs_path .. "/INTRO.md",
2020-06-24 19:00:41 +02:00
entries = {},
parent = nil
2020-06-22 22:14:52 +02:00
}
-- read all the entries
2020-09-13 15:41:39 +02:00
for kc, vc in pairs(bmeta.entries) do
local cpath = getpath(vc.path, self) .. "/meta.json"
2020-06-22 22:14:52 +02:00
if ulib.exists(cpath) then
local cmeta = JSON.decodeFile(cpath)
if cmeta then
local chapter = {
name = cmeta.name,
2020-09-13 15:41:39 +02:00
path = vc.path .. "/INTRO.md",
2020-06-24 19:00:41 +02:00
tpath = vc.path,
entries = {},
parent = result.data,
id = kc
2020-06-22 22:14:52 +02:00
}
-- read all sections
2020-09-13 15:41:39 +02:00
for ks, vs in pairs(cmeta.entries) do
local spath = getpath(vs.path, self) .. "/meta.json"
2020-06-22 22:14:52 +02:00
local smeta = JSON.decodeFile(spath)
if smeta then
2020-09-13 15:41:39 +02:00
local section =
{
name = smeta.name,
path = vs.path .. "/INTRO.md",
tpath = vs.path,
entries = {},
parent = chapter,
id = ks
}
2020-06-22 22:14:52 +02:00
-- read all files
2020-09-13 15:41:39 +02:00
for kf, vf in pairs(smeta.entries) do
2020-06-22 22:14:52 +02:00
local fpath = getpath(vf.path, self)
if ulib.exists(fpath) then
local file = io.open(fpath, "r")
io.input(file)
local line = io.read()
io.close()
if line then
2020-09-13 15:41:39 +02:00
local file =
{
name = std.trim(
std.trim(line, "#"), " "),
path = vf.path,
tpath = vf.path,
parent = section,
id = kf
}
table.insert(section.entries, file)
2020-06-22 22:14:52 +02:00
end
end
end
2020-09-13 15:41:39 +02:00
table.insert(chapter.entries, section)
2020-06-22 22:14:52 +02:00
end
end
2020-09-13 15:41:39 +02:00
table.insert(result.data.entries, chapter)
2020-06-22 22:14:52 +02:00
end
end
end
end
else
result.error = true
result.data = "No meta-data found"
end
return result
end
function DocController:index(...)
local args = {...}
local toc = self:loadTOC()
toc.controller = self.name
self.template:set("toc", toc)
2020-06-24 19:19:20 +02:00
self.template:set("elinks", self.elinks)
2020-06-22 22:14:52 +02:00
-- read data from the parameter
local path = nil
if args[1] then
local b64text = args[1]
if b64text then
local p = bytes.__tostring(std.b64decode(b64text .. "=="))
if p then
2020-06-24 19:00:41 +02:00
toc.cpath = p
2020-06-22 22:14:52 +02:00
path = getpath(p, self)
2020-09-22 17:58:37 +02:00
if path and ulib.exists(path) then
self.template:set("url", HTTP_ROOT .. '/' .. self.name ..
'/' ..
std.b64encode(toc.cpath):gsub("=", ""))
end
2020-06-22 22:14:52 +02:00
end
end
else
2020-06-24 19:00:41 +02:00
toc.cpath = self.path_map.vfs_path
2020-09-13 15:41:39 +02:00
path = self.path_map.local_path .. "/INTRO.md"
2020-06-22 22:14:52 +02:00
end
if path and ulib.exists(path) then
local has_3d = false
2020-06-22 22:14:52 +02:00
local file = io.open(path, "r")
2020-09-01 17:38:55 +02:00
local content = ""
2020-09-01 17:37:44 +02:00
local md = require("md")
local callback = function(s) content = content .. s end
md.to_html(pre_process_md(file:read("*a"), self), callback)
2020-06-22 22:14:52 +02:00
file.close()
content, has_3d = post_process_md(content, self)
2020-09-13 15:41:39 +02:00
-- replace some display plugins
2020-06-22 22:14:52 +02:00
self.template:setView("index", "index")
self.template:set("data", content)
self.template:set("has_3d", has_3d)
2020-06-22 22:14:52 +02:00
else
self.template:setView("notfound", "index")
end
return true
end
2020-06-24 19:00:41 +02:00
function DocController:search(...)
local args = {...}
local query = REQUEST.q
if query then
local cmd = "grep -ri --include=\\*.md "
local arr = explode(query, " ")
local patterns = {}
2020-09-13 15:41:39 +02:00
for k, v in ipairs(arr) do
2020-06-24 19:00:41 +02:00
local world = std.trim(v, " ")
if v and v ~= "" then
2020-09-13 15:41:39 +02:00
cmd = cmd .. " -e '" .. v .. "' "
table.insert(patterns, v:lower())
2020-06-24 19:00:41 +02:00
end
end
if #patterns > 0 then
local toc = self:loadTOC()
toc.controller = self.name
self.template:set("toc", toc)
self.template:setView("search", "index")
2020-09-13 15:41:39 +02:00
cmd = cmd .. self.path_map.local_path
2020-06-24 19:00:41 +02:00
local handle = io.popen(cmd)
local result = {}
for line in handle:lines() do
file = line:match("^[^:]*")
if file then
if not result[file] then
result[file] = {}
end
2020-09-13 15:41:39 +02:00
local content = line:gsub("^[^:]*:", ""):lower()
for k, p in ipairs(patterns) do
content = content:gsub(p,
"<span class='pattern'>" .. p ..
"</span>")
2020-06-24 19:00:41 +02:00
end
2020-09-13 15:41:39 +02:00
table.insert(result[file], content)
2020-06-24 19:00:41 +02:00
end
end
handle:close()
-- process the result
self.template:set("data", result)
self.template:set("controller", self.name)
self.template:set("map", self.path_map)
2020-06-24 19:19:20 +02:00
self.template:set("elinks", self.elinks)
2020-06-24 19:00:41 +02:00
else
return self:actionnotfound(table.unpack(args))
end
else
return self:actionnotfound(table.unpack(args))
end
return true
end
2020-09-13 15:41:39 +02:00
function DocController:asset(...)
local args = {...}
if #args == 0 then return self:actionnotfound(table.unpack(args)) end
local path = self.path_map.local_path .. "/" .. implode(args, DIR_SEP)
if self.registry.fileaccess and ulib.exists(path) then
local mime = std.mimeOf(path)
if POLICY.mimes[mime] then
std.sendFile(path)
else
self:error("Access forbidden: " .. path)
end
else
self:error("Asset file not found or access forbidden: " .. path)
end
return false
end
2020-06-24 19:49:19 +02:00
function DocController:api(...)
local args = {...}
if not self.path_map.api_path then
2020-09-13 15:41:39 +02:00
return self:actionnotfound(table.unpack(args))
2020-06-24 19:49:19 +02:00
end
local rpath = "index.html"
2020-09-13 15:41:39 +02:00
if #args ~= 0 then rpath = implode(args, "/") end
local path = self.path_map.api_path .. "/" .. rpath
2020-06-24 19:49:19 +02:00
if ulib.exists(path) then
local mime = std.mimeOf(path)
if POLICY.mimes[mime] then
std.sendFile(path)
2020-09-13 15:41:39 +02:00
else
self:error("Access forbidden: " .. path)
2020-06-24 19:49:19 +02:00
end
else
2020-09-13 15:41:39 +02:00
self:error("File not found or access forbidden: " .. path)
2020-06-24 19:49:19 +02:00
end
return false
end
2020-06-22 22:14:52 +02:00
function DocController:actionnotfound(...)
local args = {...}
return self:index(table.unpack(args))
2020-09-13 15:41:39 +02:00
end