From 347d7c0da13079fefce6d8741a5604adb89eb97c Mon Sep 17 00:00:00 2001 From: Volpeon Date: Thu, 4 Aug 2022 10:26:57 +0200 Subject: Overhauled metadata handling --- scripts/page.lua | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 scripts/page.lua (limited to 'scripts/page.lua') diff --git a/scripts/page.lua b/scripts/page.lua new file mode 100644 index 0000000..e846dd5 --- /dev/null +++ b/scripts/page.lua @@ -0,0 +1,222 @@ +local path = require 'pandoc.path' +local utils = require 'pandoc.utils' +local common = require 'scripts.lib.common' +local sort = require 'scripts.lib.sort' + +function resolve_url(site_url, ref_file, target_file) + site_url = utils.stringify(site_url) + ref_file = utils.stringify(ref_file) + target_file = utils.stringify(target_file):gsub("/index%.html$", "/") + + local ref_base_dir = path.directory(ref_file) + local abs = target_file + local rel = path.make_relative(abs, ref_base_dir, true) + local full = (abs:sub(1, 1) == "/" and (site_url .. abs)) or abs + + return { abs = abs, rel = rel, full = full } +end + +function prep_menu(active_id, main_menu) + active_id = utils.stringify(active_id) + + local active_item = nil + local items = pandoc.List() + + for i = 1, #main_menu do + local item = main_menu[i] + local active = utils.stringify(item.id) == active_id + item.active = active + if active then active_item = item end + if not item.hidden or item.active then items:insert(item) end + end + + return { items = items, active = active_item } +end + +function process_pages(global, build, meta) + for _, p in pairs(meta.pages.by_id) do + process(global, build, p) + end + + meta.pages = { + all = meta.pages.all:map(utils.stringify):map(function (ref) return meta.pages.by_id[ref] end), + date_desc = meta.pages.date_desc:map(utils.stringify):map(function (ref) return meta.pages.by_id[ref] end), + by_id = meta.pages.by_id + } +end + +function resolve_urls(global, build, meta) + meta.url = resolve_url(global.site.url, build.file_out, meta.url) + + if meta.feed then + if meta.file_out:match(".html$") then + meta.feed = { + url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".html$", ".xml")), + } + else + meta.page = { + url = resolve_url(global.site.url, build.file_out, meta.file_out:gsub(".xml$", ".html")), + } + end + end + + if meta.thumbnail then + meta.thumbnail = resolve_url(global.site.url, build.file_out, meta.thumbnail) + end +end + +function d1_page_to_list_item(meta, p) + return { + title = p.title, + subtitle = p.subtitle, + date = p.date, + last_update = p.last_update, + show_date = meta.list_order == "date_desc", + schema_type = p.schema_type, + draft = p.draft, + position = p.position, + url = p.url, + rel = p.rel, + slug = p.slug, + thumbnail = p.thumbnail, + icon = p.icon or meta.icon, + post_icon = p.post_icon or meta.list_post_icon, + indicator = meta.list_read_indicators, + } +end + +function d2_page_to_list_item(meta, cat, p, set_cat_title) + return { + title = p.title, + subtitle = p.subtitle, + category = set_cat_title and cat.title, + date = p.date, + last_update = p.last_update, + show_date = cat.list_order == "date_desc", + schema_type = p.schema_type, + draft = p.draft, + position = p.position, + url = p.url, + rel = p.rel, + slug = p.slug, + thumbnail = p.thumbnail, + icon = p.icon or cat.icon, + post_icon = p.post_icon or cat.list_post_icon or meta.list_post_icon, + indicator = cat.list_read_indicators, + } +end + +function cat_to_list_cat(cat, allItems) + local limit = cat.list_limit or 9999 + local items = allItems:take(limit) + local omitted = #allItems - #items + + return { + title = cat.title, + description = (cat.description and pandoc.MetaBlocks(pandoc.Para(cat.description))) or + (not cat.no_description and cat.content), + last_update = cat.last_update, + schema_type = cat.schema_type, + url = cat.url, + slug = cat.slug, + layout = cat.list_layout, + items = items, + total = tostring(#allItems), + omitted = omitted ~= 0 and tostring(omitted), + } +end + +function generate_list(meta) + if meta.depth < 1 then return pandoc.List() end + + if meta.depth == 1 then + return meta.pages.all:map(function(p) return d1_page_to_list_item(meta, p) end) + end + + if meta.depth == 2 then + return meta.pages.all + :map(function(cat) + local allItems = cat.pages.all:map(function(p) return d2_page_to_list_item(meta, cat, p, false) end) + + return cat_to_list_cat(cat, allItems) + end) + :filter(function(cat) return #cat.items ~= 0 end) + end + + if meta.depth == 3 then + local list = meta.pages.all + :map(function(cat) + local allItems = cat.pages.all:flatMap(function(c) + if cat.list_flatten and c.depth ~= 0 then + return c.pages.all:map(function(p) return d2_page_to_list_item(cat, c, p, true) end) + else + return pandoc.List({ d1_page_to_list_item(cat, c) }) + end + end) + + allItems:sort(sort.page_sort(cat.list_order)) + + return cat_to_list_cat(cat, allItems) + end) + :filter(function(cat) return #cat.items ~= 0 end) + + return list + end +end + +function process_base(meta) + meta.depth = tonumber(utils.stringify(meta.depth)) + meta.file_out = utils.stringify(meta.file_out) + meta.url = utils.stringify(meta.url) + meta.title = utils.stringify(meta.title) + meta.list_limit = meta.list_limit and tonumber(utils.stringify(meta.list_limit)) + meta.list_order = meta.list_order and utils.stringify(meta.list_order) + meta.position = meta.position and tonumber(utils.stringify(meta.position)) + meta.thumbnail = meta.thumbnail and utils.stringify(meta.thumbnail) +end + +function process(global, build, meta) + process_base(meta) + resolve_urls(global, build, meta) + process_pages(global, build, meta) +end + +function Meta(meta) + local build = {} + + for key, value in pairs(meta) do + local suffix = key:match('^build.(.*)$') + + if suffix then + build[suffix] = value + meta[key] = nil + end + end + + local global = { + assets = meta.assets, + site = meta.site, + menus = meta.menus + } + + process(global, build, meta) + + local parts = utils.stringify(build.namespace):split('/'):skip(1) + for i = 1, #parts do + meta = meta.pages.by_id[parts[i]] + end + + meta.list = generate_list(meta) + + if global.menus and global.menus.main then + global.menus.main = prep_menu(meta.namespace.root.id, global.menus.main) + end + + for key, value in pairs(global) do + meta[key] = value + end + + meta.build = build + + return meta +end -- cgit v1.2.3-54-g00ecf