commit 2c0fd5eccb29c9aa9d1c502eb050fe35deaae519
parent 375f7b1a871f379a04d013e8f04d4c246fe8c4e1
Author: Hugo Soucy <hugo@soucy.cc>
Date: Sun, 4 Apr 2021 15:45:07 -0400
Refactor to increase speed of the build process
Diffstat:
9 files changed, 233 insertions(+), 75 deletions(-)
diff --git a/satelito-dev-1.rockspec b/satelito-dev-1.rockspec
@@ -14,6 +14,7 @@ dependencies = {
---
"argparse >= 0.7.1-1",
"etlua >= 0.6.0",
+ "md5 >= 1.3-1",
"mimetypes >= 1.0.0-2",
"lua-discount >= 1.2.10.1-1",
"luafilesystem >= 1.8.0-1",
diff --git a/satelito/assets.lua b/satelito/assets.lua
@@ -11,9 +11,12 @@ function assets.export(filepath)
local config = assert(site.set_config(filepath), "Sorry, the site configuration can't be set")
local mtypes = assert(config.mimetypes)
local siblings = assert(lume.array(lfs.dir(file.get_dirname(filepath))))
+ local function is_in_mimetypes(f)
+ return lume.any(mtypes, function(mtype) return mtype == mimetypes.guess(f) end)
+ end
for _, sibling in ipairs(siblings) do
- if lume.any(mtypes, function(mtype) return mtype == mimetypes.guess(sibling) end) then
+ if is_in_mimetypes(sibling) then
local content_dir = site.get_root(filepath) .. '/' .. config.paths.content
local public_dir = site.get_root(filepath) .. '/' .. config.paths.public_html
local src_dir = file.get_dirname(filepath)
diff --git a/satelito/feed.lua b/satelito/feed.lua
@@ -4,7 +4,6 @@ local feed = {}
local lume = require 'satelito.lib.lume.lume'
local file = require 'satelito.file'
local list = require 'satelito.list'
-local model = require 'satelito.model'
local site = require 'satelito.site'
local template = require 'satelito.template'
diff --git a/satelito/file.lua b/satelito/file.lua
@@ -4,11 +4,11 @@ local file = {}
local lfs = require 'lfs'
local mimetypes = require 'mimetypes'
local lume = require 'satelito.lib.lume.lume'
+local dirtree = require 'satelito.dirtree'
-- Check if a file exists
function file.exists(filepath)
local _file = io.open(filepath, 'r')
- local is_file = _file ~= nil and true or false
if _file ~= nil then
_file:close()
@@ -58,6 +58,26 @@ function file.get_relpath(filepath, dirname)
return filepath:sub((dirname):len() + 1)
end
+function file.get_rellink(filepath, dirname)
+ if file.is_index(filepath) then
+ return file.get_dirname(file.get_relpath(filepath, dirname))
+ else
+ return '/' .. file.get_relpath(filepath, dirname):match('(.+)%..*') .. '.html'
+ end
+end
+
+function file.get_permalink(filepath, dirname, url)
+ return url .. '/' .. file.get_relpath(filepath, dirname):match('(.+)%..*') .. '.html'
+end
+
+function file.get_exportlink(filepath, dirname, htmlpath)
+ return htmlpath .. file.get_relpath(filepath, dirname):match('(.+)%..*') .. '.html'
+end
+
+function file.get_metafile(filepath)
+ return dofile(filepath:match('(.+)%..*') .. '.lua')
+end
+
-- Get the modified file from a list of paths
function file.get_lastmodified(filelist)
return math.max(table.unpack(lume.map(filelist,
@@ -77,6 +97,22 @@ function file.is_index(filepath)
return (file.get_basename(filepath) == 'index.md')
end
+--
+function file.get_collection(filepath, dirname)
+ local collection = {}
+
+ for subfilepath in dirtree.get(file.get_dirname(filepath)) do
+ if subfilepath
+ and file.is_markdown(subfilepath)
+ and not file.is_index(subfilepath)
+ then
+ collection[#collection+1] = file.get_relpath(subfilepath, dirname)
+ end
+ end
+
+ return collection
+end
+
-- Create a dirtree
function file.mkdir(filepath)
local sep, pStr = package.config:sub(1, 1), ''
diff --git a/satelito/init.lua b/satelito/init.lua
@@ -15,8 +15,6 @@ local parser = argparse()
:name 'satelito'
:description 'Satelito is a static site generator in lua script.'
:epilog 'For more info, see https://soucy.cc/git/satelito/file/README.md.html'
-local init
-local make
local args
parser:mutex(
@@ -25,8 +23,9 @@ parser:mutex(
)
parser:flag('-e --export', 'Export the outputed HTML in the *paths.public_html* folder.')
-init = parser:command('init', 'Init the sample website in your $HOME folder.')
-make = parser:command('make', 'Explicitly process the content in site mode instead of the default page mode.')
+local init = parser:command('init', 'Init the sample website in your $HOME folder.')
+local make = parser:command('make', 'Explicitly process the content in site mode instead of the default page mode.')
+local test = parser:command('test', 'Test some features')
args = parser:parse()
@@ -90,13 +89,18 @@ end
if args['make'] then
local config
- local content
+ local contentdir
if file.exists('config.lua') then
-- Add the currentdir to the package.path
package.path = package.path .. ';'.. lfs.currentdir() ..'/?.lua'
+
+ local counter = 0
+ local timestart = os.time()
+
-- Set config.lua in a table
config = require 'config'
+
-- Absolute path to the content directory
contentdir = lfs.currentdir() .. '/' .. config.paths.content
@@ -106,6 +110,8 @@ if args['make'] then
local html, html_path = page.build(filepath, filemeta)
local feed_xml, feed_xml_path
+ counter = counter+1
+
if args['export'] then
page.export(html_path, html)
@@ -121,6 +127,51 @@ if args['make'] then
end
end
end
+
+ print('Satelito builded ' .. counter .. ' HTML pages in ' .. os.difftime(os.time(), timestart) .. ' seconds.')
+ else
+ print('There is no "config.lua" here.')
+ os.exit()
+ end
+end
+
+if args['test'] then
+ local config
+
+ if file.exists('config.lua') then
+ -- Add the currentdir to the package.path
+ package.path = package.path .. ';'.. lfs.currentdir() ..'/?.lua'
+
+ local timestart = os.time()
+ local sitemap = {}
+
+ -- Set config.lua in a table
+ config = require 'config'
+
+ -- Absolute path to the 'content/' directory
+ local contentdir = lfs.currentdir() .. '/' .. config.paths.content
+
+ -- Array of templates
+ local templates = lume.array(dirtree.get(lfs.currentdir() .. '/' .. config.paths.templates))
+
+ for filepath in dirtree.get(contentdir) do
+ if file.is_markdown(filepath) then
+ local meta = model.set(filepath, config, contentdir)
+
+ sitemap[meta.relpath] = lume.extend({}, meta)
+ end
+ end
+
+ for _, v in pairs(sitemap) do
+ v.site = sitemap
+ local html, html_path = page.make(v, templates)
+
+ page.export(html_path, html)
+ end
+
+ --print(inspect(sitemap))
+
+ print('Satelito builded in ' .. os.difftime(os.time(), timestart) .. ' second(s).')
else
print('There is no "config.lua" here.')
os.exit()
diff --git a/satelito/list.lua b/satelito/list.lua
@@ -23,7 +23,7 @@ function list.build(filepath)
local child_content = { content = assert(markdown(file.read(child))) }
local child_parameters = assert(model.get(child))
- table.insert(_list, lume.extend({}, child_content, child_parameters))
+ _list[#_list+1] = lume.extend({}, child_content, child_parameters)
end
end
end
diff --git a/satelito/model.lua b/satelito/model.lua
@@ -7,53 +7,90 @@ local dirtree = require 'satelito.dirtree'
local file = require 'satelito.file'
local site = require 'satelito.site'
local inspect = require 'inspect'
+local markdown = require 'discount' -- lua-discount
+
+function model.set(filepath, config, contentdir)
+ local pagemeta = file.get_metafile(filepath) or {}
+ local time_created = (pagemeta.date..pagemeta.datetime):gsub('%W','')
+
+ -- If required properties are nil
+ if pagemeta.title == nil then
+ pagemeta.title = file.get_basename(filepath):match('(.+)%..*')
+ end
+
+ if pagemeta.date == nil then
+ pagemeta.date = os.date('%Y-%m-%d', lfs.attributes(filepath).change)
+ end
+
+ if pagemeta.datetime == nil then
+ pagemeta.datetime = os.date('%H:%M:%S', lfs.attributes(filepath).change)
+ end
+ --
+
+ -- Path properties
+ pagemeta.relpath = file.get_relpath(filepath, contentdir)
+
+ -- Link properties
+ pagemeta.rellink = file.get_rellink(filepath, contentdir)
+ pagemeta.permalink = file.get_permalink(filepath, contentdir, config.url)
+ pagemeta.exportlink = file.get_exportlink(filepath, contentdir, config.paths.public_html)
+ pagemeta.dirlink = file.get_permalink(filepath, contentdir, config.url):match("(.*/)")
+
+ -- Time properties
+ pagemeta.time_created = time_created
+ pagemeta.time_modification = lfs.attributes(filepath).modification
+ pagemeta.time_modified_child = file.get_lastmodified(lume.array(dirtree.get(file.get_dirname(filepath))))
+
+ -- Unique page ID for the Atom feed
+ pagemeta.id = 'tag:' .. config.domainname .. ',' .. pagemeta.date .. ':' .. pagemeta.rellink
+
+ -- HTML content
+ pagemeta.content = markdown(file.read(filepath))
+
+ -- List
+ if file.is_index(filepath) and pagemeta.list ~= false then
+ pagemeta.list = file.get_collection(filepath, contentdir)
+ end
+
+ -- Templates
+ pagemeta.template = pagemeta.template or pagemeta.posttype or 'default'
+ pagemeta.layout = pagemeta.layout or 'layout'
+ pagemeta.head = pagemeta.head or 'head'
+ pagemeta.nav = pagemeta.nav or 'navigation'
+
+ return lume.extend({}, pagemeta, config)
+end
function model.get(filepath, siteconfig)
-- The site config.lua file
local config = (siteconfig or site.set_config(filepath))
- -- The metadata file of a filepath
- local parameters_file = lfs.attributes(filepath:match('(.+)%..*') .. '.lua')
- and dofile(filepath:match('(.+)%..*') .. '.lua')
- or {}
+ local contentdir = assert(site.get_root(filepath) .. '/' .. config.paths.content)
+ local metafile = file.get_metafile(filepath)
+ local rellink = file.get_rellink(filepath, contentdir)
+ local id = assert('tag:' .. config.domainname .. ',' .. metafile.date .. ':' .. rellink)
-- If there's no parameter file for the markdown
-- Then set the minimum from the markdown file itself
- if next(parameters_file) == nil then
+ if next(metafile) == nil then
print(filepath:match('(.+)%..*') .. '.lua' .. ' is missing.')
print('You should create it to be able to add metadata.')
- parameters_file['title'] = file.get_basename(filepath):match('(.+)%..*')
- parameters_file['date'] = os.date('%Y-%m-%d', lfs.attributes(filepath).change)
- parameters_file['datetime'] = os.date('%H:%M:%S', lfs.attributes(filepath).change)
+ metafile['title'] = file.get_basename(filepath):match('(.+)%..*')
+ metafile['date'] = os.date('%Y-%m-%d', lfs.attributes(filepath).change)
+ metafile['datetime'] = os.date('%H:%M:%S', lfs.attributes(filepath).change)
end
- local contentdir = site.get_root(filepath) .. '/' .. config.paths.content
- local relpath = assert(file.get_relpath(filepath, contentdir))
- local rellink = assert(
- file.is_index(filepath)
- and file.get_dirname(file.get_relpath(filepath, contentdir))
- or '/' .. relpath:match('(.+)%..*') .. '.html'
- )
- local permalink = assert(config.url .. '/' .. relpath:match('(.+)%..*') .. '.html')
- local directory = assert(filepath:match("(.*/)"))
- local time_modified_child = assert(file.get_lastmodified(lume.array(dirtree.get(directory))))
- local id = assert('tag:' .. config.domainname .. ',' .. parameters_file.date .. ':' .. rellink)
return lume.extend({},
config,
- parameters_file,
- {directory = directory},
- {directory = directory},
- {path = filepath},
- {relpath = relpath},
- {rellink = rellink},
- {permalink = permalink},
- {dirlink = permalink:match("(.*/)")},
- {time_created = (parameters_file.date..parameters_file.datetime):gsub('%W','')},
- {time_updated = lfs.attributes(filepath).modification},
- {time_change = lfs.attributes(filepath).change},
+ metafile,
+ {relpath = file.get_relpath(filepath, contentdir)},
+ {rellink = file.get_rellink(filepath, contentdir)},
+ {permalink = file.get_permalink(filepath, contentdir, config.url)},
+ {dirlink = file.get_permalink(filepath, contentdir, config.url):match("(.*/)")},
+ {time_created = (metafile.date..metafile.datetime):gsub('%W','')},
{time_modification = lfs.attributes(filepath).modification},
- {time_modified_child = time_modified_child},
+ {time_modified_child = file.get_lastmodified(lume.array(dirtree.get(file.get_dirname(filepath))))},
{id = id}
)
end
diff --git a/satelito/page.lua b/satelito/page.lua
@@ -1,6 +1,7 @@
local page = {}
--
local markdown = require 'discount' -- lua-discount
+local etlua = require 'etlua'
local lume = require 'satelito.lib.lume.lume'
local file = require 'satelito.file'
local list = require 'satelito.list'
@@ -55,6 +56,23 @@ function page.build(filepath, filemeta)
end
end
+function page.make(filemeta, templates)
+ local post = etlua.compile(file.read(template.find(templates, filemeta.template)))
+ local head = etlua.compile(file.read(template.find(templates, filemeta.head)))
+ local navigation = etlua.compile(file.read(template.find(templates, filemeta.nav)))
+ local layout = etlua.compile(file.read(template.find(templates, filemeta.layout)))
+ local html = layout(
+ lume.extend({},
+ {post = post(lume.extend({}, filemeta))},
+ {head = head(lume.extend({}, filemeta))},
+ {navigation = navigation(lume.extend({}, filemeta))}
+ )
+ )
+ local html_path = filemeta.exportlink
+
+ return html, html_path
+end
+
--- Export an HTML file to a specific location
-- @name page.export
-- @param htmlpath a pathname to the HTML file
diff --git a/satelito/template.lua b/satelito/template.lua
@@ -6,64 +6,77 @@ local lume = require 'satelito.lib.lume.lume'
local dirtree = require 'satelito.dirtree'
local file = require 'satelito.file'
local site = require 'satelito.site'
+local inspect = require 'inspect'
-- Find the path to a template file from his name
local function find_template(templatedir, templatename)
- return lume.match(
- -- Make an array with all template files
- lume.array(dirtree.get(templatedir)),
- function(tpl)
- -- Try to find a match
- return string.gsub(tpl, '(.*/)(.*)', '%2') == templatename .. '.html'
- end
- )
+ return lume.match(
+ -- Make an array with all template files
+ lume.array(dirtree.get(templatedir)),
+ function(tpl)
+ -- Try to find a match
+ return string.gsub(tpl, '(.*/)(.*)', '%2') == templatename .. '.html'
+ end
+ )
+end
+
+function template.find(templates, templatename)
+ local _template = lume.match(
+ templates,
+ function(tpl)
+ -- Try to find a match
+ return string.gsub(tpl, '(.*/)(.*)', '%2') == templatename .. '.html'
+ end
+ )
+
+ return _template
end
function template.set_post(parameters, filepath)
- local config = assert(site.set_config(filepath))
- local post_template = assert(parameters.posttype and parameters.posttype or parameters.template or 'default')
- local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
- local template_file = assert(
- find_template(templates_dir, post_template) or find_template(templates_dir, 'default'),
- 'The template of this type of post (' .. post_template .. '.html) is missing!'
- )
+ local config = assert(site.set_config(filepath))
+ local post_template = assert(parameters.posttype and parameters.posttype or parameters.template or 'default')
+ local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
+ local template_file = assert(
+ find_template(templates_dir, post_template) or find_template(templates_dir, 'default'),
+ 'The template of this type of post (' .. post_template .. '.html) is missing!'
+ )
- return etlua.compile(file.read(template_file))
+ return etlua.compile(file.read(template_file))
end
function template.set_layout(parameters, filepath)
- local config = assert(site.set_config(filepath))
- local layout = assert(parameters.layout and parameters.layout or 'layout')
- local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
- local template_file = assert(find_template(templates_dir, layout), 'The "layout.html" template is missing!')
+ local config = assert(site.set_config(filepath))
+ local layout = assert(parameters.layout and parameters.layout or 'layout')
+ local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
+ local template_file = assert(find_template(templates_dir, layout), 'The "layout.html" template is missing!')
- return etlua.compile(file.read(template_file))
+ return etlua.compile(file.read(template_file))
end
function template.set_head(filepath)
- local config = assert(site.set_config(filepath))
- local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
- local template_file = assert(find_template(templates_dir, 'head'), 'The "head.html" template is missing!')
+ local config = assert(site.set_config(filepath))
+ local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
+ local template_file = assert(find_template(templates_dir, 'head'), 'The "head.html" template is missing!')
- return etlua.compile(file.read(template_file))
+ return etlua.compile(file.read(template_file))
end
function template.set_navigation(filepath)
- local config = assert(site.set_config(filepath))
- local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
- local template_file = assert(
- find_template(templates_dir, 'navigation'), 'The "navigation.html" template is missing!'
- )
+ local config = assert(site.set_config(filepath))
+ local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
+ local template_file = assert(
+ find_template(templates_dir, 'navigation'), 'The "navigation.html" template is missing!'
+ )
- return etlua.compile(file.read(template_file))
+ return etlua.compile(file.read(template_file))
end
function template.set_feed(filepath)
- local config = assert(site.set_config(filepath))
- local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
- local template_file = assert(find_template(templates_dir, 'feed.xml'), 'The "feed.xml" template is missing!')
+ local config = assert(site.set_config(filepath))
+ local templates_dir = assert(site.get_root(filepath) .. '/' .. config.paths.templates)
+ local template_file = assert(find_template(templates_dir, 'feed.xml'), 'The "feed.xml" template is missing!')
- return etlua.compile(file.read(template_file))
+ return etlua.compile(file.read(template_file))
end
return template