From 5db16a08a9726b67b5bb96fd17f813fa1b74f568 Mon Sep 17 00:00:00 2001 From: Volpeon Date: Tue, 5 Jan 2021 10:58:04 +0100 Subject: Moved all metadata processing from the build script into a Pandoc Lua filter --- scripts/metadata_filter.lua | 225 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 scripts/metadata_filter.lua (limited to 'scripts/metadata_filter.lua') diff --git a/scripts/metadata_filter.lua b/scripts/metadata_filter.lua new file mode 100644 index 0000000..f31bc1f --- /dev/null +++ b/scripts/metadata_filter.lua @@ -0,0 +1,225 @@ +function format_date(date) + if date == nil then + return date + end + + date = pandoc.utils.normalize_date(pandoc.utils.stringify(date)) + local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") + if year == nil then + return nil + end + + local time = os.time({ + year = tonumber(year), + month = tonumber(month), + day = tonumber(day) + }) + return pandoc.MetaMap({ + yyyy_mm_dd = pandoc.MetaString(os.date("%F", time)), + yyyy = pandoc.MetaString(os.date("%Y", time)), + mm_dd = pandoc.MetaString(os.date("%m-%d", time)), + rfc3339 = pandoc.MetaString(os.date("%FT%T+00:00", time)) + }) +end + +function table_to_list(t, cmp) + local l = pandoc.MetaList({}) + + for key, value in pairs(t) do + l:insert(pandoc.MetaMap({ + key = key, + value = value + })) + end + + l:sort(cmp or function(i1, i2) + return i1.key < i2.key + end) + + return l +end + +function splitstr(input, sep) + sep = sep or "%s" + local t = {} + for str in input:gmatch("([^" .. sep .. "]+)") do + table.insert(t, str) + end + return t +end + +function relative_to(dir, target) + dir = splitstr(dir, "/") + target = splitstr(target, "/") + + local prefix = true + local path = "" + + for i = 1, math.min(#dir, #target) do + local t = target[i] + if prefix then + if dir[i] ~= t then + prefix = false + path = "../" .. t + end + else + path = "../" .. path .. "/" .. t + end + end + + if #dir < #target then + for i = #dir + 1, #target do + path = path .. (path == "" and "" or "/") .. target[i] + end + elseif #dir > #target then + for i = #target + 1, #dir do + path = "../" .. path + end + end + + return path +end + +function resolve_url(page_type, site_url, content_dir, base_dir, cur_file) + if page_type == "page" then + cur_file = cur_file:gsub("%.md$", ".html") + elseif page_type == "feed" then + cur_file = cur_file:gsub("%.md$", ".xml") + end + + local abs = cur_file:gsub("^" .. content_dir, ""):gsub("/index.html$", "/") + local rel = relative_to(base_dir, cur_file):gsub("/index.html$", "/") + + return pandoc.MetaMap({ + abs = pandoc.MetaString(abs), + rel = pandoc.MetaString(rel), + full = pandoc.MetaString(site_url .. abs) + }) +end + +function resolve_section(abs_url) + local section = abs_url:match("^/(.-)[/.]") or "index" + return pandoc.MetaMap({ + id = pandoc.MetaString(section), + ["is_" .. section] = pandoc.MetaBool(true) + }) +end + +function organize_subpages(site_url, content_dir, base_dir, pages, categories) + local categories_data = pandoc.MetaList({}) + + pages:sort(function(p1, p2) + if p1.date and p2.date then + return pandoc.utils.stringify(p1.date.yyyy_mm_dd) > pandoc.utils.stringify(p2.date.yyyy_mm_dd) + elseif p2.date then + return true + elseif p1.date then + return false + else + return pandoc.utils.stringify(p1.title) < pandoc.utils.stringify(p2.title) + end + end) + + local pages_data = pandoc.MetaMap({ + all = pages, + by_year = pandoc.MetaList({}), + last_update = nil + }) + + if pages then + local pages_by_year_map = {} + local categories_map = {} + + for i = 1, #pages do + local page = pages[i] + + if page.date then + local yyyy = pandoc.utils.stringify(page.date.yyyy) + local pages_by_yyyy = pages_by_year_map[yyyy] + + if not pages_by_yyyy then + pages_by_yyyy = pandoc.MetaList(pandoc.List()) + pages_by_year_map[yyyy] = pages_by_yyyy + end + + pages_by_yyyy:insert(page) + end + + if page.category and categories then + local category = pandoc.utils.stringify(page.category) + + if categories[category] then + local current_category = categories_map[category] + + if not current_category then + current_category = pandoc.MetaMap({ + name = pandoc.MetaString(categories[category]), + count = 0 + }) + categories_map[category] = current_category + end + + current_category.count = current_category.count + 1 + end + end + end + + pages_data.by_year = table_to_list(pages_by_year_map, function(i1, i2) + return i1.key > i2.key + end) + + categories_data = table_to_list(categories_map) + + for _, item in ipairs(categories_data) do + item.value.count = pandoc.MetaString(("%d"):format(item.value.count)) + end + + if #pages_data.by_year ~= 0 then + pages_data.last_update = pages_data.by_year[1].value[1].last_update + end + end + + return pages_data, categories_data +end + +function Meta(meta) + meta.content_dir = meta.content_dir:gsub("/$", "") + meta.site.url = pandoc.utils.stringify(meta.site.url):gsub("/$", "") + meta.base_dir = meta.base_file:gsub("^(.*)/.-$", "%1") + meta.type = meta.type or "page" + + meta.date = format_date(meta.date) + if meta.last_update ~= nil then + meta.last_update = format_date(meta.last_update) + else + meta.last_update = meta.date + end + + if meta.type == "feed" then + meta.page = pandoc.MetaMap({ + url = resolve_url("page", meta.site.url, meta.content_dir, meta.base_dir, meta.file) + }) + end + + meta.url = resolve_url(meta.type, meta.site.url, meta.content_dir, meta.base_dir, meta.file) + meta.section = resolve_section(meta.url.abs) + meta.categories = meta.categories[meta.section.id] + + if meta.menus and meta.menus.main then + for i = 1, #meta.menus.main do + local item = meta.menus.main[i] + item.active = pandoc.MetaBool(pandoc.utils.stringify(item.id) == meta.section.id) + end + end + + if meta.pages then + local pages, categories = organize_subpages(meta.site.url, meta.content_dir, meta.base_dir, meta.pages, + meta.categories) + meta.pages = pages + meta.categories = categories + else + meta.categories = nil + end + + return meta +end -- cgit v1.2.3-54-g00ecf