local path = require 'pandoc.path' local utils = require 'pandoc.utils' local common = require 'scripts.lib.common' local sort = require 'scripts.lib.sort' function slug(str) return str:lower():gsub("[^ a-z]", ""):gsub("[ ]+", "-") end function format_date(date) if not date then return date end 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 local time = os.time({ year = tonumber(year), month = tonumber(month), day = tonumber(day) }) return { yyyy_mm_dd = os.date("%F", time), yyyy = os.date("%Y", time), mm = os.date("%m", time), dd = os.date("%d", time), rfc3339 = os.date("%FT%T+00:00", time), long = os.date("%B %d, %Y", time), short = os.date("%b %d, %Y", time), } end function make_absolute(rel, base) return path.is_absolute(rel) and rel or path.join({ path.directory(base), rel }) end function resolve_layout(depth) local layout = "categorized_list" if depth == 0 then layout = "page" elseif depth == 1 then layout = "list" end return layout end function prep_namespace(namespace) namespace = utils.stringify(namespace) local root = "index" if namespace ~= "" then root = namespace:gsub("^/([^/]*).*$", "%1") end return { root = { id = root, ["is_" .. root] = true }, full = namespace } end function prep_menu(active_id, main_menu) 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(meta) local pages_all = pandoc.List() local pages_date_desc = pandoc.List() for id, p in pairs(meta.pages) do if not p.unlisted then pages_all:insert(id) if p.last_update then pages_date_desc:insert(id) end end end 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 function find_depth(meta) if meta.depth then meta.depth = tonumber(meta.depth) end local depth = 0 for _, p in pairs(meta.pages) do find_depth(p) if not p.unlisted then local d = p.depth + 1 if d > depth then depth = d end end end meta.depth = depth 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.by_id[meta.pages.date_desc[1]].last_update elseif meta.date then meta.last_update = format_date(meta.date) end if meta.date then meta.date = format_date(meta.date) elseif meta.last_update then meta.date = meta.last_update end meta.was_updated = meta.date and meta.last_update and meta.date.yyyy_mm_dd ~= meta.last_update.yyyy_mm_dd end function process_base(build, meta) meta.namespace = prep_namespace(meta.namespace) meta.id = meta.namespace.full:gsub("^.*/(.-)$", "%1") 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 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 or "CreativeWork" meta.list_layout = common.prep_layout(meta.list_layout or "list") 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 make_absolute("thumbnail." .. utils.stringify(meta.thumbnail), meta.file_out) meta.layout = common.prep_layout(meta.layout or (meta.redirect and "redirect") or resolve_layout(meta.depth)) meta.show_date = meta.parent and meta.parent.list_order == "date_desc" meta.category = meta.parent and meta.parent.title meta.icon = meta.icon or (meta.parent and meta.parent.icon) meta.post_icon = meta.post_icon or (meta.parent and meta.parent.list_post_icon) or (meta.parent and meta.parent.parent and meta.parent.parent.list_post_icon) meta.indicator = meta.parent and meta.parent.list_read_indicators meta.content = meta.content:filter(function (el) return el.tag ~= "LineBreak" end) end function process(global, build, meta) process_base(build, meta) for _, p in pairs(meta.pages) do p.parent = meta process(global, build, p) p.parent = nil end process_pages(meta) resolve_dates(meta) end function find_pos(meta) for _, p in pairs(meta.pages.by_id) do p.parent = meta find_pos(p) p.parent = nil end if not meta.parent then return end local pages = meta.parent.list_order == "date_desc" and meta.parent.pages.date_desc or meta.parent.pages.all local _, index = pages:find(meta.id) if index == nil then return end meta.prev = index <= #pages - 1 and pages[index + 1] or nil meta.next = index >= 2 and pages[index - 1] or nil 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 meta.site.url = utils.stringify(meta.site.url):gsub("/$", "") find_depth(meta) process(meta, build, meta) find_pos(meta) return meta end