mirror of
https://github.com/lxsang/antd-web-apps
synced 2024-12-25 17:08:22 +01:00
blog now use silk
This commit is contained in:
parent
1f57e18fc7
commit
914bff3498
@ -1,8 +1,6 @@
|
||||
<?lua
|
||||
local args = {...}
|
||||
local views = args[1]
|
||||
local main = views.__main__
|
||||
local jsclass = main:get("jsclass")
|
||||
local jsclass = __main__:get("jsclass")
|
||||
if jsclass == nil then jsclass = "" end
|
||||
?>
|
||||
<html>
|
||||
@ -28,7 +26,7 @@ if jsclass == nil then jsclass = "" end
|
||||
<div id="desktop">
|
||||
<?lua
|
||||
|
||||
main:render()
|
||||
__main__:render()
|
||||
?>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -1,10 +1,10 @@
|
||||
BUILDDIR = ../build/blog
|
||||
|
||||
copyfiles = *.html assets *.lua view robot.txt
|
||||
copyfiles = assets views models controllers router.lua
|
||||
|
||||
main:
|
||||
- mkdir $(BUILDDIR)
|
||||
cp -rf $(copyfiles) $(BUILDDIR)
|
||||
- cp -rf $(copyfiles) $(BUILDDIR)
|
||||
- cd $(BUILDDIR) && ln -s ../grs ./rst
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
131
blog/api.lua
131
blog/api.lua
@ -1,131 +0,0 @@
|
||||
local get = {}
|
||||
get.fetch = function(user, cnd, limit, order)
|
||||
local db = require("db.model").get(user,"blogs",nil)
|
||||
if not db then return nil end
|
||||
local exp = {}
|
||||
exp[1] = {["="] = { publish = 1 }}
|
||||
if cnd then
|
||||
exp[2] = cnd
|
||||
else
|
||||
|
||||
end
|
||||
|
||||
local cond = {
|
||||
exp = {["and"] = exp },
|
||||
order = { ctime = "DESC" },
|
||||
fields = {
|
||||
"id", "title", "utime", "ctime", "utimestr", "ctimestr", "rendered", "tags"
|
||||
}
|
||||
}
|
||||
if limit then
|
||||
cond.limit = limit
|
||||
end
|
||||
if order then
|
||||
cond.order = order
|
||||
end
|
||||
local data, sort = db:find(cond)
|
||||
db:close()
|
||||
return data, sort
|
||||
end
|
||||
get.top = function(user, limit)
|
||||
return get.fetch(user, nil, limit)
|
||||
end
|
||||
|
||||
get.id = function(user, id)
|
||||
return get.fetch(user, { ["="] = { id = id } }, nil)
|
||||
end
|
||||
|
||||
get.minid = function(user)
|
||||
local db = require("db.model").get(user,"blogs",nil)
|
||||
local cond = { fields = { "MIN(id)" } }
|
||||
local data = db:find(cond)
|
||||
db:close()
|
||||
return data[1]["MIN(id)"]
|
||||
end
|
||||
|
||||
get.maxid = function(user)
|
||||
local db = require("db.model").get(user,"blogs",nil)
|
||||
local cond = { fields = { "MAX(id)" }}
|
||||
cond.exp = {["="] = { publish = 1 }}
|
||||
local data = db:find(cond)
|
||||
db:close()
|
||||
return data[1]["MAX(id)"]
|
||||
end
|
||||
|
||||
get.afterof = function(user, id, limit)
|
||||
local data, sort = get.fetch(user, { [">"] = { id = id } }, limit, { ctime = "ASC" })
|
||||
table.sort(sort, function(a, b) return a > b end)
|
||||
return data, sort
|
||||
end
|
||||
|
||||
get.beforeof = function(user, id, limit)
|
||||
return get.fetch(user, { ["<"] = { id = id } }, limit)
|
||||
end
|
||||
|
||||
get.nextof = function(user, id)
|
||||
return get.afterof(user, id, 1)
|
||||
end
|
||||
|
||||
get.prevof = function(user, id)
|
||||
return get.beforeof(user, id, 1)
|
||||
end
|
||||
|
||||
get.bytag = function(user, b64tag, limit, action, id)
|
||||
LAST_QUERY = b64tag
|
||||
local tag = bytes.__tostring(std.b64decode(b64tag.."=="))
|
||||
local cond = { ["LIKE"] = { tags = "%%"..tag.."%%" } }
|
||||
local order = nil
|
||||
if action == "before" then
|
||||
cond = { ["and"] = { cond, { ["<"] = {id = id} } } }
|
||||
elseif action == "after" then
|
||||
cond = { ["and"] = { cond, { [">"] = {id = id} } } }
|
||||
order = { ctime = "ASC" }
|
||||
end
|
||||
local data, sort = get.fetch(user, cond, limit, order)
|
||||
if(action == "after") then
|
||||
table.sort(sort, function(a, b) return a > b end)
|
||||
end
|
||||
return data, sort
|
||||
end
|
||||
|
||||
get.analyse = function(user, n)
|
||||
if not n then n = 5 end
|
||||
local path = "/home/mrsang/aiws/blog-clustering"
|
||||
local gettext = loadfile(path.."/gettext.lua")()
|
||||
local cluster = loadfile(path.."/cluster.lua")()
|
||||
local data = gettext.get({publish=1})
|
||||
local documents = {}
|
||||
if data then
|
||||
local sw = gettext.stopwords(path.."/stopwords.txt")
|
||||
for k,v in pairs(data) do
|
||||
local bag = cluster.bow(data[k].content, sw)
|
||||
documents[data[k].id] = bag
|
||||
end
|
||||
cluster.tfidf(documents)
|
||||
--local v = cluster.search("arm", documents)
|
||||
--echo(JSON.encode(v))
|
||||
local vectors, maxv, size = cluster.get_vectors(documents)
|
||||
local sample_data = {pid = 1, sid = 2, score = 0.1}
|
||||
local db = require("db.model").get(user, "st_similarity", sample_data)
|
||||
if db then
|
||||
-- purge the table
|
||||
db:delete({["="] = {["1"] = 1}})
|
||||
-- get similarity and put to the table
|
||||
for id,v in pairs(vectors) do
|
||||
local top = cluster.top_similarity(id,vectors,n)
|
||||
for a,b in pairs(top) do
|
||||
local record = {pid = id, sid = a, score = b}
|
||||
db:insert(record)
|
||||
end
|
||||
end
|
||||
db:close()
|
||||
return "<h3>Analyse complete</h3>"
|
||||
else
|
||||
return "<h3>Cannot get database objectw/h3>"
|
||||
end
|
||||
else
|
||||
return "<h3>Cannot find data to analyse</h3>"
|
||||
end
|
||||
end
|
||||
|
||||
return get
|
167
blog/controllers/PostController.lua
Normal file
167
blog/controllers/PostController.lua
Normal file
@ -0,0 +1,167 @@
|
||||
BaseController:subclass(
|
||||
"PostController",
|
||||
{
|
||||
registry = {},
|
||||
models = {"blog", "analytical"}
|
||||
}
|
||||
)
|
||||
|
||||
function PostController:index(...)
|
||||
return self:top(table.unpack({...}))
|
||||
end
|
||||
|
||||
function PostController:top(limit)
|
||||
limit = limit or POST_LIMIT
|
||||
local data, order = self.blog:fetch(nil, limit)
|
||||
if not data or #order == 0 then
|
||||
return self:notfound("No entry found")
|
||||
end
|
||||
self:list(data, order)
|
||||
return true
|
||||
end
|
||||
|
||||
function PostController:afterof(id, limit)
|
||||
limit = limit or POST_LIMIT
|
||||
local data, order = self.blog:fetch({[">"] = {id = id}}, limit, {ctime = "ASC"})
|
||||
if not data or #order == 0 then
|
||||
return self:notfound("No entry found")
|
||||
end
|
||||
table.sort(
|
||||
order,
|
||||
function(a, b)
|
||||
return a > b
|
||||
end
|
||||
)
|
||||
self:list(data, order)
|
||||
return true
|
||||
end
|
||||
|
||||
function PostController:beforeof(id, limit)
|
||||
limit = limit or POST_LIMIT
|
||||
local data, order = self.blog:fetch({["<"] = {id = id}}, limit)
|
||||
if not data or #order == 0 then
|
||||
return self:notfound("No entry found")
|
||||
end
|
||||
self:list(data, order)
|
||||
return true
|
||||
end
|
||||
|
||||
-- this is a private function, should not be called by user
|
||||
function PostController:list(data, order)
|
||||
self.template:setView("posts")
|
||||
self.template:set("posts", data)
|
||||
self.template:set("order", order)
|
||||
self.template:set("title", "Blog Home")
|
||||
self.template:set("minid", self.blog:minid())
|
||||
self.template:set("maxid", self.blog:maxid())
|
||||
return false
|
||||
end
|
||||
|
||||
function PostController:bytag(b64tag, limit, action, id)
|
||||
local tag = bytes.__tostring(std.b64decode(b64tag .. "=="))
|
||||
local cond = {["LIKE"] = {tags = "%%" .. tag .. "%%"}}
|
||||
local order = nil
|
||||
limit = limit or POST_LIMIT
|
||||
if action == "before" then
|
||||
cond = {["and"] = {cond, {["<"] = {id = id}}}}
|
||||
elseif action == "after" then
|
||||
cond = {["and"] = {cond, {[">"] = {id = id}}}}
|
||||
order = {ctime = "ASC"}
|
||||
end
|
||||
local data, sort = self.blog:fetch(cond, limit, order)
|
||||
if not data or #sort == 0 then
|
||||
return self:notfound("No entry found")
|
||||
end
|
||||
|
||||
if (action == "after") then
|
||||
table.sort(
|
||||
sort,
|
||||
function(a, b)
|
||||
return a > b
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
self.template:set("query", b64tag)
|
||||
self.template:set("action", "bytag")
|
||||
self:list(data, sort)
|
||||
return true
|
||||
end
|
||||
|
||||
function PostController:id(pid)
|
||||
local data, order = self.blog:fetch({["="] = {id = pid}})
|
||||
if not data or #order == 0 then
|
||||
return self:notfound("No post found")
|
||||
end
|
||||
data = data[1]
|
||||
data.rendered = bytes.__tostring(std.b64decode(data.rendered)):gsub("%%", "%%%%")
|
||||
local a, b = data.rendered:find("<[Hh]1[^>]*>")
|
||||
if a then
|
||||
local c, d = data.rendered:find("</[Hh]1>")
|
||||
if c then
|
||||
self.template:set("title", data.rendered:sub(b + 1, c - 1))
|
||||
end
|
||||
end
|
||||
-- get similarity post
|
||||
local st_records = self.analytical:similarof(data.id)
|
||||
local similar_posts = {}
|
||||
for k, v in pairs(st_records) do
|
||||
similar_posts[k] = {st = v, post = self.blog:get(v.sid)}
|
||||
end
|
||||
self.template:set("post", data)
|
||||
self.template:set("similar_posts", similar_posts)
|
||||
self.template:set("render", true)
|
||||
self.template:set("tags", data.tags)
|
||||
self.template:set("url", HTTP_ROOT .. "/post/id/" .. pid)
|
||||
self.template:setView("detail")
|
||||
return true
|
||||
end
|
||||
|
||||
function PostController:notfound(...)
|
||||
local args = {...}
|
||||
self.template:set("title", "404 not found")
|
||||
self.template:set("error", args[1])
|
||||
self.template:setView("notfound")
|
||||
return true
|
||||
end
|
||||
|
||||
function PostController:actionnotfound(...)
|
||||
local args = {...}
|
||||
return self:notfound("Action [" .. args[1] .. "] not found")
|
||||
end
|
||||
|
||||
function PostController:analyse(n)
|
||||
if not n then
|
||||
n = 5
|
||||
end
|
||||
local path = "/home/mrsang/aiws/blog-clustering"
|
||||
local gettext = loadfile(path .. "/gettext.lua")()
|
||||
local cluster = loadfile(path .. "/cluster.lua")()
|
||||
local data = gettext.get({publish = 1})
|
||||
local documents = {}
|
||||
if data then
|
||||
local sw = gettext.stopwords(path .. "/stopwords.txt")
|
||||
for k, v in pairs(data) do
|
||||
local bag = cluster.bow(data[k].content, sw)
|
||||
documents[data[k].id] = bag
|
||||
end
|
||||
cluster.tfidf(documents)
|
||||
--local v = cluster.search("arm", documents)
|
||||
--echo(JSON.encode(v))
|
||||
local vectors, maxv, size = cluster.get_vectors(documents)
|
||||
-- purge the table
|
||||
self.analytical:delete({["="] = {["1"] = 1}})
|
||||
-- get similarity and put to the table
|
||||
for id, v in pairs(vectors) do
|
||||
local top = cluster.top_similarity(id, vectors, n)
|
||||
for a, b in pairs(top) do
|
||||
local record = {pid = id, sid = a, score = b}
|
||||
self.analytical:create(record)
|
||||
end
|
||||
end
|
||||
self.template:set(message, "Analyse complete")
|
||||
else
|
||||
self.template:set(message, "Cannotto analyse")
|
||||
end
|
||||
return true
|
||||
end
|
@ -1 +0,0 @@
|
||||
require("blog.router")
|
13
blog/models/AnalyticalModel.lua
Normal file
13
blog/models/AnalyticalModel.lua
Normal file
@ -0,0 +1,13 @@
|
||||
BaseModel:subclass("AnalyticalModel",{
|
||||
registry = {},
|
||||
name = "st_similarity",
|
||||
fields = {
|
||||
pid = "NUMERIC",
|
||||
sid = "NUMERIC",
|
||||
score = "NUMERIC"
|
||||
}
|
||||
})
|
||||
|
||||
function AnalyticalModel:similarof(id)
|
||||
return self:find({ exp = {["="] = {pid = id}}, order = {score = "DESC"}})
|
||||
end
|
52
blog/models/BlogModel.lua
Normal file
52
blog/models/BlogModel.lua
Normal file
@ -0,0 +1,52 @@
|
||||
BaseModel:subclass("BlogModel",{
|
||||
registry = {},
|
||||
name = "blogs",
|
||||
fields = {
|
||||
tags = "TEXT",
|
||||
content = "TEXT",
|
||||
utime = "NUMERIC",
|
||||
rendered = "TEXT",
|
||||
title = "TEXT",
|
||||
utimestr = "TEXT",
|
||||
ctime = "NUMERIC",
|
||||
ctimestr = "TEXT",
|
||||
publish = "INTEGER DEFAULT 0"
|
||||
}
|
||||
})
|
||||
|
||||
function BlogModel:fetch(cnd, limit, order)
|
||||
local exp = {}
|
||||
exp[1] = {["="] = { publish = 1 }}
|
||||
if cnd then
|
||||
exp[2] = cnd
|
||||
else
|
||||
|
||||
end
|
||||
|
||||
local cond = {
|
||||
exp = {["and"] = exp },
|
||||
order = { ctime = "DESC" },
|
||||
fields = {
|
||||
"id", "title", "utime", "ctime", "utimestr", "ctimestr", "rendered", "tags"
|
||||
}
|
||||
}
|
||||
if limit then
|
||||
cond.limit = limit
|
||||
end
|
||||
if order then
|
||||
cond.order = order
|
||||
end
|
||||
return self:find(cond)
|
||||
end
|
||||
|
||||
function BlogModel:minid()
|
||||
local cond = { fields = { "MIN(id)" } }
|
||||
local data = self:find(cond)
|
||||
return data[1]["MIN(id)"]
|
||||
end
|
||||
|
||||
function BlogModel:maxid()
|
||||
local cond = { fields = { "MAX(id)" } }
|
||||
local data = self:find(cond)
|
||||
return data[1]["MAX(id)"]
|
||||
end
|
@ -1,2 +0,0 @@
|
||||
User-agent: *
|
||||
Allow: /
|
100
blog/router.lua
100
blog/router.lua
@ -1,42 +1,60 @@
|
||||
BLOG_ROOT = __ROOT__.."/blog"
|
||||
MAX_ENTRY = 15
|
||||
LAST_QUERY = nil
|
||||
BLOG_ADMIN = "mrsang"
|
||||
local user = BLOG_ADMIN
|
||||
local handle = function(p)
|
||||
local args = {}
|
||||
local sort = {}
|
||||
local i = 1
|
||||
for s in p:gmatch("%:*([^%:]*)") do
|
||||
args[i] = s
|
||||
table.insert(sort, i)
|
||||
i = i+1
|
||||
end
|
||||
table.sort(sort)
|
||||
local api = require("blog.api")
|
||||
local minid = api.minid(user)
|
||||
local maxid = api.maxid(user)
|
||||
if #args == 0 or api == nil then
|
||||
echo("Unknow request "..p)
|
||||
elseif not api[args[1]] then
|
||||
echo("Unknow action.."..args[1])
|
||||
else
|
||||
local action = args[1]
|
||||
args[1] = user
|
||||
local data, sort = api[action](table.unpack(args))
|
||||
if data == nil then
|
||||
echo("Cannot query data")
|
||||
else
|
||||
require("blog.view").render(action, data, sort, minid, maxid)
|
||||
end
|
||||
end
|
||||
end
|
||||
std.html()
|
||||
local action = REQUEST.query.action
|
||||
if not action then action = "r:top:"..MAX_ENTRY end
|
||||
local r, s = action:find("^r:")
|
||||
if r then
|
||||
handle(action:sub(s+1))
|
||||
else
|
||||
echo("Unknow action "..action)
|
||||
|
||||
-- the rewrite rule for the framework
|
||||
-- should be something like this
|
||||
-- ^\/apps\/+(.*)$ = /apps/router.lua?r=<1>&<query>
|
||||
-- some global variables
|
||||
DIR_SEP = "/"
|
||||
WWW_ROOT = "/opt/www/htdocs/blog"
|
||||
HTTP_ROOT = "https://blog.localhost:9195"
|
||||
-- class path: path.to.class
|
||||
BASE_FRW = ""
|
||||
-- class path: path.to.class
|
||||
CONTROLLER_ROOT = BASE_FRW.."blog.controllers"
|
||||
MODEL_ROOT = BASE_FRW.."blog.models"
|
||||
-- file path: path/to/file
|
||||
VIEW_ROOT = WWW_ROOT..DIR_SEP.."views"
|
||||
LOG_ROOT = WWW_ROOT..DIR_SEP.."logs"
|
||||
POST_LIMIT = 2
|
||||
-- require needed library
|
||||
require(BASE_FRW.."silk.api")
|
||||
|
||||
if REQUEST.query.r then
|
||||
REQUEST.query.r = REQUEST.query.r:gsub("%:", "/")
|
||||
end
|
||||
|
||||
-- registry object store global variables
|
||||
local REGISTRY = {}
|
||||
-- set logging level
|
||||
REGISTRY.logger = Logger:new{ levels = {INFO = true, ERROR = true, DEBUG = true}}
|
||||
REGISTRY.db = DBHelper:new{db="mrsang"}
|
||||
REGISTRY.layout = 'default'
|
||||
|
||||
REGISTRY.db:open()
|
||||
local router = Router:new{registry = REGISTRY}
|
||||
REGISTRY.router = router
|
||||
router:setPath(CONTROLLER_ROOT)
|
||||
--router:route('edit', 'post/edit', "ALL" )
|
||||
|
||||
-- example of depedencies to the current main route
|
||||
-- each layout may have different dependencies
|
||||
--[[ local default_routes_dependencies = {
|
||||
user = {
|
||||
url = "user/index",
|
||||
visibility = "ALL"
|
||||
},
|
||||
toc = {
|
||||
url = "toc/index",
|
||||
visibility = {
|
||||
shown = true,
|
||||
routes = {
|
||||
["index/index"] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} ]]
|
||||
router:route('default', default_routes_dependencies )
|
||||
router:remap("index", "post")
|
||||
router:remap("r", "post")
|
||||
router:delegate()
|
||||
if REGISTRY.db then REGISTRY.db:close() end
|
||||
|
||||
|
@ -1,144 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Hi, I'm Xuan Sang LE</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="rst/ubuntu-regular.css" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/font-awesome.css" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/hermit-light.css" />
|
||||
<link rel="stylesheet" type="text/css" href="assets/style.css" />
|
||||
<script src="rst/gscripts/jquery-3.2.1.min.js"> </script>
|
||||
</head>
|
||||
<body>
|
||||
<div id = "top">
|
||||
<div id = "navbar">
|
||||
<div class = "logo"></div>
|
||||
<ul>
|
||||
<li ><i class = "fa fa-address-card"></i><a href="https://info.lxsang.me" target="_blank">Porfolio</a></li>
|
||||
<li><i class = "fa fa-newspaper-o"></i><a href="https://blog.lxsang.me" target="_blank">Blog</a></li>
|
||||
<li><i class = "fa fa-paper-plane"></i><a href="#" onclick="" >Contact</a></li>
|
||||
<li > <i class = "fa fa-globe"></i><a href = "https://os.lxsang.me" target="_blank">Web OS</a></li>
|
||||
</ul>
|
||||
<input type = "text" class = "search-box"></input>
|
||||
<div class= "search-icon"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id = "center">
|
||||
<div id = "container">
|
||||
<div class = "card">
|
||||
<div class = "side">
|
||||
<span class = "date">24 July 2017</span>
|
||||
<span class = "tags">
|
||||
<a href= "#">ROS</a>,
|
||||
<a href= "#">distributed system</a>,
|
||||
<a href= "#">middleware</a>,
|
||||
<a href= "#">robotic</a>,
|
||||
<a href= "#">SLAM</a>,
|
||||
<a href= "#">autonomous exploration</a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class = "blogentry">
|
||||
<h1>What is Lorem Ipsum?</h1>
|
||||
<div class = "shortcontent">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
|
||||
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsumhas been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It ha
|
||||
</div>
|
||||
<div class = "detail">
|
||||
<span></span>
|
||||
<a href="#" ></a>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class = "card">
|
||||
<div class = "side">
|
||||
<span class = "date">24 July 2017</span>
|
||||
<span class = "tags">
|
||||
<a href= "#">ROS</a>,
|
||||
<a href= "#">distributed system</a>,
|
||||
<a href= "#">middleware</a>,
|
||||
<a href= "#">robotic</a>,
|
||||
<a href= "#">SLAM</a>,
|
||||
<a href= "#">autonomous exploration</a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class = "blogentry">
|
||||
<h1>What is Lorem Ipsum?</h1>
|
||||
<div class = "shortcontent">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
|
||||
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsumhas been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It ha
|
||||
</div>
|
||||
<div class = "detail">
|
||||
<span></span>
|
||||
<a href="#" ></a>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class = "card">
|
||||
<div class = "side">
|
||||
<span class = "date">24 July 2017</span>
|
||||
<span class = "tags">
|
||||
<a href= "#">ROS</a>,
|
||||
<a href= "#">distributed system</a>,
|
||||
<a href= "#">middleware</a>,
|
||||
<a href= "#">robotic</a>,
|
||||
<a href= "#">SLAM</a>,
|
||||
<a href= "#">autonomous exploration</a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class = "blogentry">
|
||||
<h1>What is Lorem Ipsum?</h1>
|
||||
<div class = "shortcontent">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
|
||||
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsumhas been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It ha
|
||||
</div>
|
||||
<div class = "detail">
|
||||
<span></span>
|
||||
<a href="#" ></a>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class = "card">
|
||||
<div class = "side">
|
||||
<span class = "date">24 July 2017</span>
|
||||
<span class = "tags">
|
||||
<a href= "#">ROS</a>,
|
||||
<a href= "#">distributed system</a>,
|
||||
<a href= "#">middleware</a>,
|
||||
<a href= "#">robotic</a>,
|
||||
<a href= "#">SLAM</a>,
|
||||
<a href= "#">autonomous exploration</a>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class = "blogentry">
|
||||
<h1>What is Lorem Ipsum?</h1>
|
||||
<div class = "shortcontent">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum
|
||||
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsumhas been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It ha
|
||||
</div>
|
||||
<div class = "detail">
|
||||
<span></span>
|
||||
<a href="#" ></a>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id = "bottom">
|
||||
Powered by antd server, (c) 2017 - 2018 Xuan Sang LE
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,40 +0,0 @@
|
||||
local view = {}
|
||||
|
||||
view.html = function(name)
|
||||
local path = BLOG_ROOT.."/view/"..name..".html"
|
||||
if unix.exists(path) then
|
||||
std.f(path)
|
||||
else
|
||||
echo("Cannot find "..path)
|
||||
end
|
||||
end
|
||||
|
||||
view.render = function(action, data, sort, min, max)
|
||||
local path = BLOG_ROOT.."/view"
|
||||
local fn = nil
|
||||
local e
|
||||
if action == "id" then
|
||||
--echo(bytes.__tostring(std.b64decode(data[0].rendered)):gsub("%%","%%%%"))
|
||||
--return true
|
||||
fn, e = loadscript(path.."/detail.ls")
|
||||
--echo(data[0].rendered)
|
||||
--fn = require("blog.view.compiledd")
|
||||
elseif action == "analyse" then
|
||||
fn, e = loadscript(path.."/analyse.ls")
|
||||
else
|
||||
--fn = require("blog.view.compiledd")
|
||||
|
||||
fn, e = loadscript(path.."/entries.ls")
|
||||
end
|
||||
if fn then
|
||||
local r,o = pcall(fn, data, sort, min, max, action)
|
||||
if not r then
|
||||
echo(o)
|
||||
end
|
||||
else
|
||||
loadscript(path.."/top.ls")("Welcome to my blog")
|
||||
echo(e)
|
||||
end
|
||||
view.html("bot")
|
||||
end
|
||||
return view
|
@ -1,6 +0,0 @@
|
||||
<?lua
|
||||
local arg = {...}
|
||||
local data = arg[1]
|
||||
loadscript(BLOG_ROOT.."/view/top.ls")("Welcome to my blog", false)
|
||||
echo(data)
|
||||
?>
|
@ -1,7 +0,0 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id = "bottom">
|
||||
Powered by antd server, (c) 2017 - 2018 Xuan Sang LE
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,9 +1,10 @@
|
||||
|
||||
|
||||
<?lua
|
||||
local arg = {...}
|
||||
local title = arg[1]
|
||||
local render = arg[2]
|
||||
local url = arg[3]
|
||||
local tags = arg[4]
|
||||
local title = __main__:get("title")
|
||||
local render = __main__:get("render")
|
||||
local url = __main__:get("url")
|
||||
local tags = __main__:get("tags")
|
||||
local cls = ""
|
||||
if HEADER.mobile then
|
||||
cls = "navmobile"
|
||||
@ -14,16 +15,15 @@
|
||||
<head>
|
||||
<title><?=title?></title>
|
||||
<meta charset="UTF-8">
|
||||
<!--meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' https://platform.twitter.com/widgets.js https://connect.facebook.net/en_US/sdk.js https://apis.google.com/js/plusone.js https://platform.twitter.com/js/button.556f0ea0e4da4e66cfdc182016dbd6db.js https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.fr.G6aVHqjZQ7w.O/m=plusone/rt=j/sv=1/d=1/ed=1/am=AQE/rs=AGLTcCM3jVZaR98LsOLZhkxFJYLRGgZQ6A/cb=gapi.loaded_0 https://apis.google.com/_/scs/apps-static/_/js/k=oz.gapi.fr.G6aVHqjZQ7w.O/m=auth/exm=plusone/rt=j/sv=1/d=1/ed=1/am=AQE/rs=AGLTcCM3jVZaR98LsOLZhkxFJYLRGgZQ6A/cb=gapi.loaded_1"-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="rst/ubuntu-regular.css" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/font-awesome.css" />
|
||||
<link rel="stylesheet" type="text/css" href="assets/style.css" />
|
||||
<script src="rst/gscripts/riot.min.js"> </script>
|
||||
<script src="rst/resources/antos_tags.js"></script>
|
||||
<script src="rst/gscripts/jquery-3.2.1.min.js"> </script>
|
||||
<script src="rst/main.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/rst/ubuntu-regular.css" />
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/rst/font-awesome.css" />
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/assets/style.css" />
|
||||
<script src="<?=HTTP_ROOT?>/rst/gscripts/riot.min.js"> </script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/resources/antos_tags.js"></script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/gscripts/jquery-3.2.1.min.js"> </script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/main.js"></script>
|
||||
<meta property="og:image" content="" />
|
||||
<?lua if render then ?>
|
||||
<meta name="twitter:card" content="summary" />
|
||||
@ -33,17 +33,17 @@
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="<?=title?>" />
|
||||
<meta property="og:description" content="<?=tags?>" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/hljs/github.css" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/katex/katex.min.css" />
|
||||
<script src="rst/hljs/highlight.pack.js"> </script>
|
||||
<script src="rst/hljs/highlightjs-line-numbers.min.js"> </script>
|
||||
<script src="rst/katex/katex.min.js"> </script>
|
||||
<script src="rst/katex/auto-render.min.js"> </script>
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/rst/hljs/github.css" />
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/rst/katex/katex.min.css" />
|
||||
<script src="<?=HTTP_ROOT?>/rst/hljs/highlight.pack.js"> </script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/hljs/highlightjs-line-numbers.min.js"> </script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/katex/katex.min.js"> </script>
|
||||
<script src="<?=HTTP_ROOT?>/rst/katex/auto-render.min.js"> </script>
|
||||
<?lua else ?>
|
||||
<meta property="og:url" content="https://blog.lxsang.me" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content="Xuan Sang LE's blog" />
|
||||
<meta property="og:description" content="My personal space" />
|
||||
<meta property="og:description" content="Blog Home" />
|
||||
<?lua end ?>
|
||||
<script>
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
<div id = "navbar" class = "<?=cls?>">
|
||||
<div class = "logo"><a href = "https://lxsang.me"></a></div>
|
||||
<ul>
|
||||
<li><i class = "fa fa-home"></i><a href="./">Home</a></li>
|
||||
<li><i class = "fa fa-home"></i><a href="<?=HTTP_ROOT?>">Home</a></li>
|
||||
<li ><i class = "fa fa-address-card"></i><a href="https://info.lxsang.me" >Porfolio</a></li>
|
||||
<li><i class = "fa fa-envelope"></i><a href="#" onclick="mailtoMe('rst')" >Contact</a></li>
|
||||
<?lua
|
||||
@ -118,4 +118,13 @@
|
||||
</div>
|
||||
<div id = "desktop">
|
||||
<div id = "container">
|
||||
|
||||
<?lua
|
||||
__main__:render()
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<div id = "bottom">
|
||||
Powered by antd server, (c) 2017 - 2018 Xuan Sang LE
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
8
blog/views/default/notfound/index.ls
Normal file
8
blog/views/default/notfound/index.ls
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
<div class = "notfound">
|
||||
<p><?=error?></p>
|
||||
<blockquote>
|
||||
“In many ways my life has been rather like a record of the lost and found. Perhaps all lives are like that.”
|
||||
<span>― Lucy Foley, The Book of Lost and Found</span>
|
||||
</blockquote >
|
||||
</div>
|
3
blog/views/default/post/analyse.ls
Normal file
3
blog/views/default/post/analyse.ls
Normal file
@ -0,0 +1,3 @@
|
||||
<?lua
|
||||
echo("<h3>"..message.."</h3>")
|
||||
?>
|
@ -1,56 +1,10 @@
|
||||
<?lua
|
||||
local arg = {...}
|
||||
local data = arg[1]
|
||||
local order = arg[2]
|
||||
local content = nil;
|
||||
local url = nil
|
||||
local topview = loadscript(BLOG_ROOT.."/view/top.ls")
|
||||
local data = post
|
||||
local class = "card"
|
||||
if HEADER.mobile then
|
||||
class = "card mobile"
|
||||
end
|
||||
local title = "Welcome to my blog"
|
||||
if not #data or #order == 0 then
|
||||
topview(title, false)
|
||||
?>
|
||||
<div class = "notfound">
|
||||
<p>No entry found</p>
|
||||
<blockquote>
|
||||
“In many ways my life has been rather like a record of the lost and found. Perhaps all lives are like that.”
|
||||
<span>― Lucy Foley, The Book of Lost and Found</span>
|
||||
</blockquote >
|
||||
</div>
|
||||
<?lua
|
||||
return
|
||||
else
|
||||
data = data[1]
|
||||
content = bytes.__tostring(std.b64decode(data.rendered)):gsub("%%","%%%%")
|
||||
local a,b = content:find("<[Hh]1[^>]*>")
|
||||
if a then
|
||||
local c,d = content:find("</[Hh]1>")
|
||||
if c then
|
||||
title = content:sub(b+1, c-1)
|
||||
end
|
||||
end
|
||||
url = "https://blog.lxsang.me/r:id:"..data.id
|
||||
topview(title, true, url, data.tags)
|
||||
end
|
||||
-- fetch the similar posts from database
|
||||
local db = require("db.model").get(BLOG_ADMIN,"st_similarity", nil)
|
||||
local similar_posts = nil
|
||||
if db then
|
||||
local records = db:find({ exp = {["="] = {pid = data.id}}, order = {score = "DESC"}})
|
||||
--echo("records size is #"..#records)
|
||||
local pdb = require("db.model").get(BLOG_ADMIN,"blogs", nil)
|
||||
if(pdb) then
|
||||
similar_posts = {}
|
||||
for k,v in pairs(records) do
|
||||
similar_posts[k] = { st = v, post = pdb:get(v.sid) }
|
||||
end
|
||||
pdb:close()
|
||||
end
|
||||
db:close()
|
||||
end
|
||||
local content = data.rendered
|
||||
?>
|
||||
<div class = "<?=class?>">
|
||||
<div class = "side">
|
||||
@ -63,7 +17,7 @@
|
||||
tag = std.trim(tag, " ")
|
||||
if tag ~= "" then
|
||||
local b64tag = std.b64encode(tag)
|
||||
atags[i] = '<a href = "./r:bytag:'..b64tag:gsub("=","")..':'..MAX_ENTRY..'">'..tag.."</a>"
|
||||
atags[i] = '<a href = "'..HTTP_ROOT..'/post/bytag/'..b64tag:gsub("=","")..'/'..POST_LIMIT..'">'..tag.."</a>"
|
||||
i = i+ 1
|
||||
end
|
||||
end
|
8
blog/views/default/post/notfound.ls
Normal file
8
blog/views/default/post/notfound.ls
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
<div class = "notfound">
|
||||
<p><?=error?></p>
|
||||
<blockquote>
|
||||
“In many ways my life has been rather like a record of the lost and found. Perhaps all lives are like that.”
|
||||
<span>― Lucy Foley, The Book of Lost and Found</span>
|
||||
</blockquote >
|
||||
</div>
|
@ -1,30 +1,12 @@
|
||||
<?lua
|
||||
local arg = {...}
|
||||
local datas = arg[1]
|
||||
local order = arg[2]
|
||||
local minid = arg[3]
|
||||
local maxid = arg[4]
|
||||
local action = arg[5]
|
||||
local datas = posts
|
||||
local class = "card"
|
||||
local first_id = nil
|
||||
local last_id = nil
|
||||
if HEADER.mobile then
|
||||
class = "card mobile"
|
||||
end
|
||||
loadscript(BLOG_ROOT.."/view/top.ls")("Welcome to my blog", false)
|
||||
if #order == 0 then
|
||||
?>
|
||||
<div class = "notfound">
|
||||
<p>No entry found</p>
|
||||
<blockquote>
|
||||
“In many ways my life has been rather like a record of the lost and found. Perhaps all lives are like that.”
|
||||
<span>― Lucy Foley, The Book of Lost and Found</span>
|
||||
</blockquote >
|
||||
</div>
|
||||
<?lua
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
for idx,v in pairs(order) do
|
||||
local data = datas[v]
|
||||
if not last_id then last_id = data.id end
|
||||
@ -41,12 +23,12 @@
|
||||
tag = std.trim(tag, " ")
|
||||
if tag ~= "" then
|
||||
local b64tag = std.b64encode(tag)
|
||||
atags[i] = '<a href = "./r:bytag:'..b64tag:gsub("=","")..':'..MAX_ENTRY..'">'..tag.."</a>"
|
||||
atags[i] = '<a href = "'..HTTP_ROOT..'/post/bytag/'..b64tag:gsub("=","")..'/'..POST_LIMIT..'">'..tag.."</a>"
|
||||
i = i+ 1
|
||||
end
|
||||
end
|
||||
echo(table.concat(atags, ", "))
|
||||
local url = "https://blog.lxsang.me/r:id:"..data.id
|
||||
local url = HTTP_ROOT.."/post/id/"..data.id
|
||||
?>
|
||||
</span>
|
||||
<div class="fb-like" data-href="<?=url?>" data-layout="button_count" data-action="like" data-size="small" data-show-faces="true" data-share="true"></div>
|
||||
@ -72,7 +54,7 @@
|
||||
end
|
||||
if title then
|
||||
echo(content:sub(0, b))
|
||||
echo("<a class = 'title_link' href='./r:id:"..data.id.."'>"..title.."</a>")
|
||||
echo("<a class = 'title_link' href='"..HTTP_ROOT.."/post/id/"..data.id.."'>"..title.."</a>")
|
||||
echo(content:sub(c))
|
||||
else
|
||||
echo(content)
|
||||
@ -81,18 +63,18 @@
|
||||
</div>
|
||||
<div class = "detail">
|
||||
<span></span>
|
||||
<?='<a href="./r:id:'..data.id..'" ></a>'?>
|
||||
<?='<a href="'..HTTP_ROOT..'/post/id/'..data.id..'" ></a>'?>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?lua
|
||||
end
|
||||
local beforelk = "./r:beforeof:"..first_id..":"..MAX_ENTRY
|
||||
local afterlk = "./r:afterof:"..last_id..":"..MAX_ENTRY
|
||||
local beforelk = HTTP_ROOT.."/post/beforeof/"..first_id.."/"..POST_LIMIT
|
||||
local afterlk = HTTP_ROOT.."/post/afterof/"..last_id.."/"..POST_LIMIT
|
||||
if action == "bytag" or action == "search" then
|
||||
beforelk = "./r:"..action..":"..LAST_QUERY..":"..MAX_ENTRY..":before:"..first_id
|
||||
afterlk = "./r:"..action..":"..LAST_QUERY..":"..MAX_ENTRY..":after:"..last_id
|
||||
beforelk = HTTP_ROOT.."/post/"..action.."/"..query.."/"..POST_LIMIT.."/before/"..first_id
|
||||
afterlk = HTTP_ROOT.."/post/"..action.."/"..query.."/"..POST_LIMIT.."/after/"..last_id
|
||||
end
|
||||
?>
|
||||
<div class = "time-travel">
|
@ -1,6 +1,4 @@
|
||||
<?lua
|
||||
local args = {...}
|
||||
local data = args[1].data
|
||||
if not data then return end
|
||||
|
||||
for k,v in pairs(data) do
|
||||
|
@ -1,24 +1,20 @@
|
||||
<?lua
|
||||
local args = {...}
|
||||
local views = args[1]
|
||||
?>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="rst/gscripts/showdown.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="rst/font-awesome.css" />
|
||||
<script type="text/javascript" src="<?=HTTP_ROOT?>/rst/gscripts/showdown.min.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/style.css" />
|
||||
<link rel="stylesheet" type="text/css" href="<?=HTTP_ROOT?>/rst/font-awesome.css" />
|
||||
<title>Porfolio</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<div class = "cv-content">
|
||||
<?lua
|
||||
if views.user then
|
||||
views.user:render()
|
||||
if user then
|
||||
user:render()
|
||||
end
|
||||
if views.__main__ then
|
||||
views.__main__:render()
|
||||
if __main__ then
|
||||
__main__:render()
|
||||
end
|
||||
?>
|
||||
<div class = "container">
|
||||
@ -27,9 +23,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<?lua
|
||||
if views.toc then
|
||||
views.toc:set("data", views.__main__:get("toc"))
|
||||
views.toc:render()
|
||||
if toc then
|
||||
toc:set("data", __main__:get("toc"))
|
||||
toc:render()
|
||||
end
|
||||
?>
|
||||
</div>
|
||||
|
@ -1,7 +1,5 @@
|
||||
<?lua
|
||||
if HEADER.mobile then return end
|
||||
local args = {...}
|
||||
local data = args[1].data
|
||||
if not data then return end
|
||||
?>
|
||||
<div class = "cv-toc">
|
||||
|
@ -1,8 +1,3 @@
|
||||
<?lua
|
||||
local args = {...}
|
||||
local data = args[1].data
|
||||
?>
|
||||
|
||||
<h1>
|
||||
<span class="name"><?=data.fullname?></span>
|
||||
<span class="cv">Curriculum Vitae</span>
|
||||
|
@ -75,6 +75,11 @@ BaseController:subclass("NotfoundController",{ registry = {}, models = {} })
|
||||
function NotfoundController:index(...)
|
||||
local args = {...}
|
||||
local error = args[2] or ""
|
||||
if self.template:path() then
|
||||
self.template:set("error", error)
|
||||
self.template:set("title", "404 not found")
|
||||
return true
|
||||
end
|
||||
self:error("404: Controller "..args[1].." not found : "..error)
|
||||
return false
|
||||
end
|
||||
@ -102,7 +107,7 @@ function AssetController:get(...)
|
||||
self:error("Access forbidden: "..path)
|
||||
end
|
||||
else
|
||||
self:error("Assset file not found: "..path)
|
||||
self:error("Asset file not found: "..path)
|
||||
end
|
||||
return false
|
||||
end
|
@ -38,6 +38,12 @@ function BaseModel:find(cond)
|
||||
return false
|
||||
end
|
||||
|
||||
function BaseModel:get(id)
|
||||
local data, order = self:find({exp = {["="] = { id = id}} })
|
||||
if not data or #order == 0 then return false end
|
||||
return data[1]
|
||||
end
|
||||
|
||||
function BaseModel:findAll()
|
||||
if self.db then
|
||||
return self.db:getAll(self.name)
|
||||
|
@ -6,6 +6,7 @@ end
|
||||
|
||||
function Router:initialize()
|
||||
self.routes = {}
|
||||
self.remaps = {}
|
||||
end
|
||||
|
||||
--function Router:setArgs(args)
|
||||
@ -23,7 +24,7 @@ function Router:infer(url)
|
||||
-- c,d,e is parameters
|
||||
-- if user dont provide the url, try to infer it
|
||||
-- from the REQUEST
|
||||
url = url or REQUEST.query.r
|
||||
url = url or REQUEST.query.r or ""
|
||||
url = std.trim(url, "/")
|
||||
local args = explode(url, "/")
|
||||
local data = {
|
||||
@ -41,6 +42,10 @@ function Router:infer(url)
|
||||
end
|
||||
end
|
||||
|
||||
-- remap if needed
|
||||
if self.remaps[data.name] ~= nil then
|
||||
data.name = self.remaps[data.name]
|
||||
end
|
||||
-- find the controller class and init it
|
||||
local controller_name = firstToUpper(data.name) .. "Controller"
|
||||
local controller_path = self.path .. "." .. controller_name
|
||||
@ -84,7 +89,7 @@ function Router:delegate()
|
||||
data.controller.main = true
|
||||
views.__main__ = self:call(data)
|
||||
if not views.__main__ then
|
||||
--self:error("No main template is set")
|
||||
--self:error("No view available for this action")
|
||||
return
|
||||
end
|
||||
-- get all visible routes
|
||||
@ -94,16 +99,23 @@ function Router:delegate()
|
||||
views[k] = self:call(data)
|
||||
end
|
||||
-- now require the main page to put the view
|
||||
local view_args = {}
|
||||
local view_argv = {}
|
||||
for k,v in pairs(views) do
|
||||
table.insert( view_args, k )
|
||||
table.insert( view_argv, v )
|
||||
end
|
||||
|
||||
local fn, e = loadscript(VIEW_ROOT .. DIR_SEP .. self.registry.layout .. DIR_SEP .. "layout.ls")
|
||||
local fn, e = loadscript(VIEW_ROOT .. DIR_SEP .. self.registry.layout .. DIR_SEP .. "layout.ls", view_args)
|
||||
html()
|
||||
if fn then
|
||||
local r, o = pcall(fn, views)
|
||||
local r, o = pcall(fn, table.unpack(view_argv))
|
||||
if not r then
|
||||
self:error(o)
|
||||
end
|
||||
else
|
||||
self:error("The index page is not found for layout: " .. self.registry.layout)
|
||||
e = e or ""
|
||||
self:error("The index page is not found for layout: " .. self.registry.layout..": "..e)
|
||||
end
|
||||
end
|
||||
|
||||
@ -142,6 +154,10 @@ function Router:call(data)
|
||||
end
|
||||
end
|
||||
|
||||
function Router:remap(from, to)
|
||||
self.remaps[from] = to
|
||||
end
|
||||
|
||||
function Router:route(layout, dependencies)
|
||||
self.routes[layout] = dependencies
|
||||
end
|
||||
|
@ -31,14 +31,24 @@ function Template:path()
|
||||
if ulib.exists(path) then
|
||||
return path
|
||||
else
|
||||
self:error("View not found: "..path)
|
||||
return false, path
|
||||
end
|
||||
end
|
||||
-- render the page
|
||||
function Template:render()
|
||||
local fn, e = loadscript(self:path())
|
||||
local path, err = self:path()
|
||||
if not path then
|
||||
return self:error("View not found: "..err)
|
||||
end
|
||||
local args = {}
|
||||
local argv = {}
|
||||
for k, v in pairs(self.vars) do
|
||||
table.insert( args, k )
|
||||
table.insert( argv,v )
|
||||
end
|
||||
local fn, e = loadscript(self:path(), args)
|
||||
if fn then
|
||||
local r,o = pcall(fn, self.vars)
|
||||
local r,o = pcall(fn, table.unpack(argv))
|
||||
if not r then
|
||||
self:error(o)
|
||||
end
|
||||
|
@ -16,6 +16,7 @@ POLICY.mimes = {
|
||||
["application/javascript"] = true,
|
||||
["image/bmp"] = true,
|
||||
["image/jpeg"] = true,
|
||||
["image/png"] = true,
|
||||
["text/css"] = true,
|
||||
["text/markdown"] = true,
|
||||
["text/csv"] = true,
|
||||
@ -49,4 +50,8 @@ function html()
|
||||
std.chtml(SESSION)
|
||||
HEADER_FLAG = true
|
||||
end
|
||||
end
|
||||
|
||||
function import(module)
|
||||
return require(BASE_FRW.."silk.api."..module)
|
||||
end
|
Loading…
Reference in New Issue
Block a user