local M = {} local filter = require "make4ht-filter" local mkutils = require "mkutils" local log = logging.new "staticsite" -- get the published file name local function get_slug(settings) local published_name = mkutils.remove_extension(settings.tex_file) .. ".published" local config = get_filter_settings "staticsite" local file_pattern = config.file_pattern or "%Y-%m-%d-${input}" local time = os.time() -- we must save the published date, so the subsequent compilations at different days -- use the same name if mkutils.file_exists(published_name) then local f = io.open(published_name, "r") local readtime = f:read("*line") time = tonumber(readtime) log:info("Already pubslished", os.date("%Y-%m-%d %H:%M", time)) f:close() else -- escape -- slug must contain the unescaped input name local f = io.open(published_name, "w") log:info("Publishing article", os.date("%Y-%m-%d %H:%M", time)) f:write(time) f:close() end -- set the updated and publishing times local updated -- the updated time will be set only when it is more than one day from the published time local newtime = os.time() if (newtime - time) > (24 * 3600) then updated = newtime end filter_settings "staticsite" { header = { time = time, updated = updated } } -- make the output file name in the format YYYY-MM-DD-old-filename.html local slug = os.date(file_pattern,time) % settings return slug end -- it is necessary to set correct -jobname in latex_par parameters field -- in order to the get correct HTML file name local function update_jobname(slug, latex_par) local latex_par = latex_par or "" if latex_par:match("%-jobname") then local firstchar=latex_par:match("%-jobname=.") local replace_pattern="%-jobname=[^%s]+" if firstchar == "'" or firstchar=='"' then replace_pattern = "%-jobname=".. firstchar .."[^%"..firstchar.."]+" end return latex_par:gsub(replace_pattern, "-jobname=".. slug) else return latex_par .. "-jobname="..slug end end -- execute the function passed as parameter only once, when the file matching -- starts local function insert_filter(make, pattern, fn) local insert_executed = false table.insert(make.matches, 1, { pattern=pattern, params = make.params or {}, command = function() if not insert_executed then fn() end insert_executed = true end }) end local function remove_maketitle(make) -- use DOM filter to remove \maketitle block local domfilter = require "make4ht-domfilter" local process = domfilter({ function(dom) local maketitles = dom:query_selector(".maketitle") for _, el in ipairs(maketitles) do log:debug("removing maketitle") el:remove_node() end return dom end }, "staticsite") make:match("html$", process) end local function copy_files(filename, par) local function prepare_path(dir, subdir) local f = filename if par.builddir then f = f:gsub("^" .. par.builddir .. "/", "") end local path = dir .. "/" .. subdir .. "/" .. f return path:gsub("//", "/") end -- get extension settings local site_settings = get_filter_settings "staticsite" local site_root = site_settings.site_root or par.outdir if site_root == "" then site_root = "./" end local map = site_settings.map or {} -- default path without subdir, will be used if the file is not matched -- by any pattern in the map local path = prepare_path(site_root, "") for pattern, destination in pairs(map) do if filename:match(pattern) then path = prepare_path(site_root, destination) break end end -- it is possible to use string extrapolation in path, for example for slug mkutils.copy(filename, path % par) end function M.modify_build(make) -- it is necessary to insert the filters for YAML header and file copying as last matches -- we use an bogus match which will be executed only once as the very first one to insert -- the filters -- I should make filter from this local process = filter({ "staticsite" }, "staticsite") -- detect if we should remove maketitle local site_settings = get_filter_settings "staticsite" -- \maketitle is removed by default, set `remove_maketitle=false` setting to disable that if site_settings.remove_maketitle ~= false then remove_maketitle(make) end local settings = make.params -- get the published file name local slug = get_slug(settings) for _, cmd in ipairs(make.build_seq) do -- all commands must use the published file name cmd.params.input = slug cmd.params.latex_par = update_jobname(slug, cmd.params.latex_par) end local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])' local mainfile = string.gsub(slug, quotepattern, "%%%1") -- run the following code once in the first match on the first file insert_filter(make, ".*", function() -- for _, match in ipairs(make.matches) do -- match.params.outdir = outdir -- print(match.pattern, match.params.outdir) -- end local params = make.params params.slug = slug make:match("html?$", process, params) make:match(".*", copy_files, params) end) return make end return M