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(namespace, main_menu) namespace = utils.stringify(namespace) local active_item = nil local items = pandoc.List() for i = 1, #main_menu do local item = main_menu[i] for j = 1, #item.match do if active_item then break end item.active = not not namespace:match(utils.stringify(item.match[j])) if item.active then active_item = item end 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_pages(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) for _, p in pairs(meta.pages.by_id) do process(global, build, p) end 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 } meta = meta.tree process(global, build, meta) local parts = utils.stringify(build.namespace):split('/'):skip(1) for i = 1, #parts do local part = parts[i] local p = meta.pages.by_id[part] meta.pages.by_id[part] = nil p.parent = meta meta = p end process_pages(global, build, meta) meta.list = generate_list(meta) if global.menus and global.menus.main then global.menus.main = prep_menu(meta.namespace.full, global.menus.main) end for key, value in pairs(global) do meta[key] = value end meta.build = build return meta end