1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
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
|