diff options
author | Karl Berry <karl@freefriends.org> | 2018-05-03 21:04:48 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2018-05-03 21:04:48 +0000 |
commit | d20905e40a1f1c00c8b4d268ecaafcef47953e7a (patch) | |
tree | 904da60a00b88366bbc0b5aef7adc62c08838164 /Master/texmf-dist/scripts | |
parent | 14d1c94af4e8acce4d5d6854b6988834d8ab4dac (diff) |
make4ht (3may18)
git-svn-id: svn://tug.org/texlive/trunk@47598 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts')
-rw-r--r-- | Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua (renamed from Master/texmf-dist/scripts/make4ht/extensions/latexmk.lua) | 0 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua | 135 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/make4ht/filters/make4ht-staticsite.lua | 98 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/make4ht/make4ht | 2 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/make4ht/make4ht-filterlib.lua | 2 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/make4ht/make4ht-lib.lua | 6 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/make4ht/mkutils.lua | 30 |
7 files changed, 261 insertions, 12 deletions
diff --git a/Master/texmf-dist/scripts/make4ht/extensions/latexmk.lua b/Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua index bf4dcdde5a4..bf4dcdde5a4 100644 --- a/Master/texmf-dist/scripts/make4ht/extensions/latexmk.lua +++ b/Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua diff --git a/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua b/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua new file mode 100644 index 00000000000..fcb6c09e17d --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua @@ -0,0 +1,135 @@ +local M = {} +local filter = require "make4ht-filter" +local mkutils = require "mkutils" + +-- 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) + print("Already pubslished", slug) + f:close() + else + -- escape + -- slug must contain the unescaped input name + local f = io.open(published_name, "w") + 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 = {}, + command = function() + if not insert_executed then + fn() + end + insert_executed = true + end + }) +end + + +local function copy_files(filename, par) + local function prepare_path(dir, subdir) + local path = dir .. "/" .. subdir .. "/" .. filename + return path:gsub("//", "/") + end + -- get extension settings + local site_settings = get_filter_settings "staticsite" + local site_root = site_settings.site_root + 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" + } + 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 + -- make the YAML header only for the main HTML file + make:match(mainfile .. ".html", process) + make:match(".*", copy_files, {slug=slug}) + end) + + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-staticsite.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-staticsite.lua new file mode 100644 index 00000000000..6378f0440aa --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-staticsite.lua @@ -0,0 +1,98 @@ +local domobj = require "luaxml-domobject" +-- save the header settings in YAML format +local function make_yaml(tbl, level) + local t = {} + local level = level or 0 + local indent = string.rep(" ", level) + -- indentation for multilen strings + local str_indent = string.rep(" ", level + 1) + for k,v in pairs(tbl) do + if type(v)=="string" then + -- detect multiline strings + if v:match("\n") then + table.insert(t, string.format(indent .. "%s: |", k)) + table.insert(t, str_indent .. (v:gsub("\n", "\n".. str_indent))) + else + v = v:gsub("'", "''") + table.insert(t, string.format(indent .. "%s: '%s'", k,v)) + end + elseif type(v) == "table" then + table.insert(t,string.format(indent .. "%s:", k)) + -- we need to differently process array and hash table + -- we don't support mixing types + if #v > 0 then + for x,y in ipairs(v) do + if type(y) == "string" then + -- each string can be printed on it's own line + table.insert(t, indent .. string.format("- '%s'", y)) + else + -- subtables need to be indented + -- table.insert(t, indent .. "-") + local subtable = make_yaml(y, level + 1) + -- we must insert dash at a correct place + local insert_dash = subtable:gsub("^(%s*)%s%s", "%1- ") + table.insert(t, insert_dash) + end + end + else + -- print indented table + table.insert(t, make_yaml(v,level + 1)) + end + else + -- convert numbers and other values to string + table.insert(t, string.format(indent .. "%s: %s", k,tostring(v))) + end + + end + return table.concat(t, "\n") +end + +local function update_properties(properties, dom) + -- enable properties update from the config or build file + local settings = get_filter_settings "staticsite" or {} + local header = settings.header or {} + for field, rule in pairs(header) do + -- it is possible to pass function as a rule, it will be executed with properties as a parameter + if type(rule) == "function" then + properties[field] = rule(properties, dom) + else + -- otherwise set properties + properties[field] = rule + end + end + return properties +end + +local function get_header(tbl) + local yaml = make_yaml(tbl) + return "---\n".. yaml.. "\n---\n" +end + +return function(s,par) + print(os.getenv "blog_home") + local dom = domobj.parse(s) + local properties = {} + local head = dom:query_selector("head")[1] + properties.title = head:query_selector("title")[1]:get_text() + local styles = {} + for _, link in ipairs(head:query_selector("link")) do + local typ = link:get_attribute("type") + if typ == "text/css" then + table.insert(styles, link:get_attribute("href")) + end + end + properties.styles = styles + local metas = {} + for _, meta in ipairs(head:query_selector("meta")) do + print(meta:serialize()) + table.insert(metas, {charset= meta:get_attribute("charset"), content = meta:get_attribute("content"), property = meta:get_attribute("property"), name = meta:get_attribute("name")}) + end + properties.meta = metas + properties = update_properties(properties, dom) + + + local body = dom:query_selector("body")[1] + print(get_header(properties)) + -- return s + return get_header(properties) .. body:serialize():gsub("<body.->", ""):gsub("</body>", "") +end diff --git a/Master/texmf-dist/scripts/make4ht/make4ht b/Master/texmf-dist/scripts/make4ht/make4ht index 0da3c30549c..10b277d2a73 100755 --- a/Master/texmf-dist/scripts/make4ht/make4ht +++ b/Master/texmf-dist/scripts/make4ht/make4ht @@ -27,7 +27,7 @@ make4ht [options] filename ["tex4ht.sty op." "tex4ht op." "t4ht op" "latex op"] -- set version number. the template should be replaced by the -- actual version number by the build script -local version = "v0.2" +local version = "0.2a" mkparams.version_number = version local args = mkparams.get_args() diff --git a/Master/texmf-dist/scripts/make4ht/make4ht-filterlib.lua b/Master/texmf-dist/scripts/make4ht/make4ht-filterlib.lua index 33cb3530a85..3c2e63cf69d 100755 --- a/Master/texmf-dist/scripts/make4ht/make4ht-filterlib.lua +++ b/Master/texmf-dist/scripts/make4ht/make4ht-filterlib.lua @@ -6,7 +6,7 @@ function M.load_filters(filters, load_filter) if type(filters) == "string" then table.insert(sequence,load_filter(filters)) elseif type(filters) == "table" then - for _,n in pairs(filters) do + for _,n in ipairs(filters) do if type(n) == "string" then table.insert(sequence,load_filter(n)) elseif type(n) == "function" then diff --git a/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua b/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua index 918343f20ca..2ada398f869 100755 --- a/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua +++ b/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua @@ -81,9 +81,9 @@ Make.image_convert = function(self, images) end image_patterns[i].params = p end - for _,i in pairs(images) do + for _,i in ipairs(images) do local output = i.output - for _, x in pairs(image_patterns) do + for _, x in ipairs(image_patterns) do local pattern = x.pattern if output:match(pattern) then local command = x.command @@ -107,7 +107,7 @@ end Make.file_matches = function(self, files) local statuses = {} -- First make params for all matchers - for k,v in pairs(self.matches) do + for k,v in ipairs(self.matches) do local v = self.matches[k].params or {} local p = self.params or {} for i,j in pairs(p) do diff --git a/Master/texmf-dist/scripts/make4ht/mkutils.lua b/Master/texmf-dist/scripts/make4ht/mkutils.lua index 88b456fe9da..7dab423bc9b 100755 --- a/Master/texmf-dist/scripts/make4ht/mkutils.lua +++ b/Master/texmf-dist/scripts/make4ht/mkutils.lua @@ -22,6 +22,19 @@ getmetatable("").__add = addProperty --print( "${name} is ${value}" % {name = "foo", value = "bar"} ) -- Outputs "foo is bar" + +-- merge two tables recursively +function merge(t1, t2) + for k, v in pairs(t2) do + if (type(v) == "table") and (type(t1[k] or false) == "table") then + merge(t1[k], t2[k]) + else + t1[k] = v + end + end + return t1 +end + function string:split(sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) @@ -157,7 +170,7 @@ function mkdirectories(dirs) if type(dirs) ~="table" then return false, "mkdirectories: dirs is not table" end - for _,d in pairs(dirs) do + for _,d in ipairs(dirs) do local stat,msg = lfs.mkdir(d) if not stat then return false, "makedirectories error: "..msg end lfs.chdir(d) @@ -269,10 +282,7 @@ function env.filter_settings(name) local filters = settings.filter or {} local filter_options = filters[name] or {} return function(par) - for k,v in pairs(par) do - filter_options[k] = v - end - filters[name] = filter_options + filters[name] = merge(filter_options, par) settings.filter = filters end end @@ -458,13 +468,19 @@ end function load_extensions(extensions, format) local module_names = {} local extension_table = {} + local extension_sequence = {} -- process the extension table. it contains type field, which can enable or -- diable the extension for _, v in ipairs(extensions) do local enable = v.type == "+" and true or nil - module_names[v.name] = enable + -- don't load extensions multiple times + if not module_names[v.name] then + module_names[v.name] = enable + -- load extenisons in a correct order + table.insert(extension_sequence, v.name) + end end - for name, _ in pairs(module_names) do + for _, name in ipairs(extension_sequence) do local extension = load_extension(name,format) if extension then table.insert(extension_table, extension) |