118 lines
2.9 KiB
Lua
118 lines
2.9 KiB
Lua
local arrr = require 'arrr'
|
|
local restia = require 'restia'
|
|
local shapeshift = require 'shapeshift'
|
|
local yaml = require 'lyaml'
|
|
local cmark = require 'cmark'
|
|
|
|
local params do
|
|
local is = shapeshift.is
|
|
local parse = arrr {
|
|
{ "Output directory", "--output", "-o", 'directory' };
|
|
{ "Input directory", "--input", "-i", 'directory' };
|
|
{ "Copy directory", "--copy", "-c", 'directory', 'repeatable' };
|
|
{ "Delete everything first", "--delete", "-d" };
|
|
}
|
|
local validate = shapeshift.table {
|
|
output = shapeshift.default("output", is.string);
|
|
input = shapeshift.default(".", is.string);
|
|
copy = shapeshift.default({}, shapeshift.all{
|
|
is.table,
|
|
shapeshift.each(is.string)
|
|
});
|
|
delete = shapeshift.default(false, shapeshift.is.boolean);
|
|
}
|
|
params = select(2, assert(validate(parse{...})))
|
|
end
|
|
package.loaded.params = params
|
|
|
|
local config = restia.config.bind('config', {
|
|
(require 'restia.config.readfile');
|
|
(require 'restia.config.lua');
|
|
(require 'restia.config.yaml');
|
|
})
|
|
package.loaded.config = config
|
|
|
|
local templates = restia.config.bind('templates', {
|
|
(require 'restia.config.skooma');
|
|
})
|
|
package.loaded.templates = templates
|
|
|
|
local function read_post(file)
|
|
local content = io.open(file):read("*a")
|
|
local head, body = restia.utils.frontmatter(content)
|
|
return {
|
|
head = head and yaml.load(head) or {};
|
|
body = cmark.render_html(cmark.parse_document(body, #body, cmark.OPT_DEFAULT), cmark.OPT_DEFAULT);
|
|
}
|
|
end
|
|
|
|
local posts = {}
|
|
package.loaded.posts = posts
|
|
|
|
local tree = {}
|
|
|
|
for i, path in ipairs(params.copy) do
|
|
restia.utils.deepinsert(tree, restia.utils.fs2tab(path), restia.utils.readdir(path))
|
|
end
|
|
|
|
local validate_head do
|
|
local is = shapeshift.is
|
|
validate_head = shapeshift.table {
|
|
__extra = 'keep';
|
|
title = is.string;
|
|
date = shapeshift.matches("%d%d%d%d%-%d%d%-%d%d");
|
|
file = is.string;
|
|
}
|
|
end
|
|
|
|
local function parsedate(date)
|
|
local year, month, day = date:match("(%d+)%-(%d+)%-(%d+)")
|
|
return os.time {
|
|
year = tonumber(year);
|
|
month = tonumber(month);
|
|
day = tonumber(day);
|
|
}
|
|
end
|
|
|
|
-- Load Posts
|
|
for file in restia.utils.files(params.input, "%.md$") do
|
|
local post = read_post(file)
|
|
post.head.file = file
|
|
|
|
assert(validate_head(post.head))
|
|
|
|
post.head.timestamp = parsedate(post.head.date)
|
|
|
|
post.head.slug = post.head.title
|
|
:gsub(' ', '_')
|
|
:lower()
|
|
:gsub('[^a-z0-9-_]', '')
|
|
|
|
post.head.uri = string.format("/%s/%s.html", post.head.date:gsub("%-", "/"), post.head.slug)
|
|
post.path = restia.utils.fs2tab(post.head.uri)
|
|
|
|
table.insert(posts, post)
|
|
end
|
|
|
|
table.sort(posts, function(a, b)
|
|
return a.head.timestamp > b.head.timestamp
|
|
end)
|
|
|
|
local function render(name, ...)
|
|
return templates.main(templates[name], ...)
|
|
end
|
|
|
|
-- Render Posts
|
|
for idx, post in ipairs(posts) do
|
|
local body = restia.utils.deepconcat(render("post", post.body, post.head))
|
|
|
|
restia.utils.deepinsert(tree, post.path, body)
|
|
end
|
|
|
|
tree["index.html"] = render("index", posts)
|
|
|
|
if params.delete then
|
|
restia.utils.delete(params.output)
|
|
end
|
|
|
|
restia.utils.builddir(params.output, tree)
|