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/content.lua | 27 ++++++ scripts/lib/common.lua | 10 +++ scripts/lib/sort.lua | 36 ++++++++ scripts/metadata.lua | 211 +++++-------------------------------------- scripts/page.lua | 222 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/pages_content.lua | 27 ------ 6 files changed, 316 insertions(+), 217 deletions(-) create mode 100644 scripts/content.lua create mode 100644 scripts/lib/sort.lua create mode 100644 scripts/page.lua delete mode 100644 scripts/pages_content.lua (limited to 'scripts') diff --git a/scripts/content.lua b/scripts/content.lua new file mode 100644 index 0000000..d77759d --- /dev/null +++ b/scripts/content.lua @@ -0,0 +1,27 @@ +local path = require 'pandoc.path' + +local namespace = '' +local siteUrl = '' + +function meta(meta) + namespace = pandoc.utils.stringify(meta.namespace) + siteUrl = pandoc.utils.stringify(meta.site.url):gsub("/$", "") +end + +function image(el) + if path.is_relative(el.src) and not el.src:match("^https?://") then + el.src = siteUrl .. path.join({ namespace, el.src }) + end + + return el +end + +function link(el) + if path.is_relative(el.target) and not el.target:match("^https?://") then + el.target = siteUrl .. path.join({ namespace, el.target }) + end + + return el +end + +return { { Meta = meta }, { Image = image, Link = link } } diff --git a/scripts/lib/common.lua b/scripts/lib/common.lua index 80b81ba..5ed3e31 100644 --- a/scripts/lib/common.lua +++ b/scripts/lib/common.lua @@ -49,6 +49,16 @@ function pandoc.List:take(n) return result end +function pandoc.List:skip(n) + local result = pandoc.List() + + if n >= #self then return result end + + for i = n + 1, #self do result:insert(self[i]) end + + return result +end + return { dump = dump } diff --git a/scripts/lib/sort.lua b/scripts/lib/sort.lua new file mode 100644 index 0000000..393e5d5 --- /dev/null +++ b/scripts/lib/sort.lua @@ -0,0 +1,36 @@ +local utils = require 'pandoc.utils' + +function page_sort(order, pages) + order = order and utils.stringify(order) + + return function(ref1, ref2) + local p1 = pages and pages[utils.stringify(ref1)] or ref1 + local p2 = pages and pages[utils.stringify(ref2)] or ref2 + + if p1.position then + if p2.position then + return tonumber(utils.stringify(p1.position)) < tonumber(utils.stringify(p2.position)) + else + return true + end + elseif p2.position then + return false + elseif order == "date_desc" then + if p1.last_update then + if p2.last_update then + return utils.stringify(p1.last_update.yyyy_mm_dd) > utils.stringify(p2.last_update.yyyy_mm_dd) + else + return true + end + else + return false + end + else + return utils.stringify(p1.title):upper() < utils.stringify(p2.title):upper() + end + end +end + +return { + page_sort = page_sort +} diff --git a/scripts/metadata.lua b/scripts/metadata.lua index 6aa679a..5157677 100644 --- a/scripts/metadata.lua +++ b/scripts/metadata.lua @@ -1,31 +1,7 @@ local path = require 'pandoc.path' +local utils = require 'pandoc.utils' local common = require 'scripts.lib.common' - -function page_sort(order) - return function(p1, p2) - if p1.position then - if p2.position then - return p1.position < p2.position - else - return true - end - elseif p2.position then - return false - elseif order == "date_desc" then - if p1.last_update then - if p2.last_update then - return p1.last_update.yyyy_mm_dd > p2.last_update.yyyy_mm_dd - else - return true - end - else - return false - end - else - return p1.title:upper() < p2.title:upper() - end - end -end +local sort = require 'scripts.lib.sort' function slug(str) return str:lower():gsub("[^ a-z]", ""):gsub("[ ]+", "-") @@ -34,7 +10,7 @@ end function format_date(date) if not date then return date end - date = pandoc.utils.normalize_date(pandoc.utils.stringify(date)) + date = pandoc.utils.normalize_date(utils.stringify(date)) local year, month, day = date:match("(%d%d%d%d)-(%d%d)-(%d%d)") if not year then return nil end @@ -54,17 +30,6 @@ function make_absolute(rel, base) return path.is_absolute(rel) and rel or path.join({ path.directory(base), rel }) end -function resolve_url(site_url, ref_file, target_file) - target_file = 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 resolve_layout(depth) local layout = "categorized_list" @@ -78,12 +43,12 @@ function resolve_layout(depth) end function prep_layout(layout) - layout = pandoc.utils.stringify(layout) + layout = utils.stringify(layout) return { id = layout, ["is_" .. layout] = true } end -function resolve_namespace(namespace) - namespace = pandoc.utils.stringify(namespace) +function prep_namespace(namespace) + namespace = utils.stringify(namespace) local root = "index" if namespace ~= "" then root = namespace:gsub("^/([^/]*).*$", "%1") end @@ -97,7 +62,7 @@ function prep_menu(active_id, main_menu) for i = 1, #main_menu do local item = main_menu[i] - local active = pandoc.utils.stringify(item.id) == active_id + 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 @@ -107,22 +72,20 @@ function prep_menu(active_id, main_menu) end function process_pages(global, build, meta) - local order = meta.list_order - local pages_all = pandoc.List() local pages_date_desc = pandoc.List() - for _, p in pairs(meta.pages) do + for id, p in pairs(meta.pages) do process(global, build, p) if not p.unlisted then - pages_all:insert(p) - if p.last_update then pages_date_desc:insert(p) end + pages_all:insert(id) + if p.last_update then pages_date_desc:insert(id) end end end - pages_all:sort(page_sort(order)) - pages_date_desc:sort(page_sort("date_desc")) + pages_all:sort(sort.page_sort(meta.list_order, meta.pages)) + pages_date_desc:sort(sort.page_sort("date_desc", meta.pages)) meta.pages = { all = pages_all, date_desc = pages_date_desc, by_id = meta.pages } end @@ -145,35 +108,11 @@ function find_depth(meta) meta.depth = depth 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 - - -- for _, p in pairs(meta.pages.by_id) do - -- resolve_urls(global, build, p) - -- end -end - function resolve_dates(meta) if meta.last_update then meta.last_update = format_date(meta.last_update) elseif #meta.pages.date_desc ~= 0 then - meta.last_update = meta.pages.date_desc[1].last_update + meta.last_update = meta.pages.by_id[meta.pages.date_desc[1]].last_update elseif meta.date then meta.last_update = format_date(meta.date) end @@ -187,125 +126,23 @@ function resolve_dates(meta) meta.was_updated = meta.date and meta.last_update and meta.date.yyyy_mm_dd ~= meta.last_update.yyyy_mm_dd 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(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(build, meta) - meta.namespace = resolve_namespace(meta.namespace) - meta.file_out = pandoc.utils.stringify(meta.file_out) + meta.namespace = prep_namespace(meta.namespace) + meta.file_out = utils.stringify(meta.file_out) meta.unlisted = meta.unlisted or (meta.draft and build.mode ~= "dev") meta.redirect = meta.url and true - meta.url = meta.url and pandoc.utils.stringify(meta.url) or meta.file_out - meta.title = meta.title and pandoc.utils.stringify(meta.title) or "" + meta.url = meta.url or meta.file_out + meta.title = meta.title and utils.stringify(meta.title) or "" meta.slug = slug(meta.title) - meta.schema_type = meta.schema_type and pandoc.utils.stringify(meta.schema_type) or "CreativeWork" - meta.list_order = meta.list_order and pandoc.utils.stringify(meta.list_order) + meta.schema_type = meta.schema_type or "CreativeWork" meta.list_layout = prep_layout(meta.list_layout or "list") - meta.list_limit = meta.list_limit and tonumber(pandoc.utils.stringify(meta.list_limit)) - meta.position = meta.position and tonumber(pandoc.utils.stringify(meta.position)) - meta.thumbnail = meta.thumbnail and make_absolute("thumbnail." .. pandoc.utils.stringify(meta.thumbnail), meta.file_out) + meta.position = meta.position and tonumber(utils.stringify(meta.position)) + meta.thumbnail = meta.thumbnail and make_absolute("thumbnail." .. utils.stringify(meta.thumbnail), meta.file_out) meta.layout = prep_layout(meta.layout or (meta.redirect and "redirect") or resolve_layout(meta.depth)) end function process(global, build, meta) process_base(build, meta) - resolve_urls(global, build, meta) process_pages(global, build, meta) resolve_dates(meta) end @@ -322,16 +159,10 @@ function Meta(meta) end end - meta.site.url = pandoc.utils.stringify(meta.site.url):gsub("/$", "") + meta.site.url = utils.stringify(meta.site.url):gsub("/$", "") find_depth(meta) process(meta, build, meta) - meta.list = generate_list(meta) - - if meta.menus and meta.menus.main then - meta.menus.main = prep_menu(meta.namespace.root.id, meta.menus.main) - end - return meta end 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 diff --git a/scripts/pages_content.lua b/scripts/pages_content.lua deleted file mode 100644 index b753b1e..0000000 --- a/scripts/pages_content.lua +++ /dev/null @@ -1,27 +0,0 @@ -local path = require 'pandoc.path' - -local namespace = '' -local siteUrl = '' - -function meta(meta) - namespace = pandoc.utils.stringify(meta.namespace.full) - siteUrl = pandoc.utils.stringify(meta.site.url):gsub("/$", "") -end - -function image(el) - if path.is_relative(el.src) and not el.src:match("^https?://") then - el.src = siteUrl .. path.join({ namespace, el.src }) - end - - return el -end - -function link(el) - if path.is_relative(el.target) and not el.target:match("^https?://") then - el.target = siteUrl .. path.join({ namespace, el.target }) - end - - return el -end - -return { { Meta = meta }, { Image = image, Link = link } } -- cgit v1.2.3-70-g09d2