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