From af84b9db7fece90caa80d73b8faa9de75dd9e568 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 6 Nov 2019 23:34:03 +0000 Subject: make4ht (5nov19) git-svn-id: svn://tug.org/texlive/trunk@52666 c570f23f-e606-0410-a88d-b1316a301751 --- .../texk/texlive/linked_scripts/make4ht/make4ht | 2 +- .../texk/texlive/linked_scripts/texlive/tlmgr.pl | 8 +- .../texmf-dist/doc/support/make4ht/changelog.tex | 25 +- .../texmf-dist/doc/support/make4ht/make4ht-doc.pdf | Bin 126657 -> 127067 bytes .../make4ht/extensions/common_domfilters.lua | 36 --- .../scripts/make4ht/extensions/common_filters.lua | 26 -- .../scripts/make4ht/extensions/dvisvgm_hashes.lua | 269 --------------------- .../scripts/make4ht/extensions/join_colors.lua | 16 -- .../scripts/make4ht/extensions/latexmk_build.lua | 31 --- .../extensions/make4ht-ext-common_domfilters.lua | 36 +++ .../extensions/make4ht-ext-common_filters.lua | 26 ++ .../extensions/make4ht-ext-dvisvgm_hashes.lua | 269 +++++++++++++++++++++ .../make4ht/extensions/make4ht-ext-join_colors.lua | 16 ++ .../extensions/make4ht-ext-latexmk_build.lua | 31 +++ .../make4ht/extensions/make4ht-ext-mathjaxnode.lua | 16 ++ .../make4ht/extensions/make4ht-ext-odttemplate.lua | 16 ++ .../extensions/make4ht-ext-preprocess_input.lua | 108 +++++++++ .../make4ht/extensions/make4ht-ext-staticsite.lua | 136 +++++++++++ .../make4ht/extensions/make4ht-ext-tidy.lua | 58 +++++ .../scripts/make4ht/extensions/mathjaxnode.lua | 16 -- .../scripts/make4ht/extensions/odttemplate.lua | 16 -- .../make4ht/extensions/preprocess_input.lua | 108 --------- .../scripts/make4ht/extensions/staticsite.lua | 136 ----------- .../texmf-dist/scripts/make4ht/extensions/tidy.lua | 58 ----- .../texmf-dist/scripts/make4ht/formats/docbook.lua | 39 --- .../texmf-dist/scripts/make4ht/formats/html5.lua | 17 -- .../scripts/make4ht/formats/make4ht-docbook.lua | 39 +++ .../scripts/make4ht/formats/make4ht-html5.lua | 17 ++ .../scripts/make4ht/formats/make4ht-odt.lua | 224 +++++++++++++++++ .../scripts/make4ht/formats/make4ht-tei.lua | 14 ++ .../scripts/make4ht/formats/make4ht-xhtml.lua | 16 ++ Master/texmf-dist/scripts/make4ht/formats/odt.lua | 224 ----------------- Master/texmf-dist/scripts/make4ht/formats/tei.lua | 14 -- .../texmf-dist/scripts/make4ht/formats/xhtml.lua | 16 -- Master/texmf-dist/scripts/make4ht/make4ht | 2 +- .../scripts/make4ht/make4ht-odtfilter.lua | 33 +++ Master/texmf-dist/scripts/make4ht/mathnode.lua | 87 ------- Master/texmf-dist/scripts/make4ht/mkutils.lua | 6 +- Master/tlpkg/tlpsrc/latex-bin.tlpsrc | 2 +- 39 files changed, 1090 insertions(+), 1119 deletions(-) delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/common_domfilters.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/common_filters.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/dvisvgm_hashes.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/join_colors.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_domfilters.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_filters.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-dvisvgm_hashes.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-join_colors.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-mathjaxnode.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-odttemplate.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-staticsite.lua create mode 100644 Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/mathjaxnode.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/odttemplate.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/preprocess_input.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/extensions/tidy.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/formats/docbook.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/formats/html5.lua create mode 100644 Master/texmf-dist/scripts/make4ht/formats/make4ht-docbook.lua create mode 100644 Master/texmf-dist/scripts/make4ht/formats/make4ht-html5.lua create mode 100644 Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua create mode 100644 Master/texmf-dist/scripts/make4ht/formats/make4ht-tei.lua create mode 100644 Master/texmf-dist/scripts/make4ht/formats/make4ht-xhtml.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/formats/odt.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/formats/tei.lua delete mode 100644 Master/texmf-dist/scripts/make4ht/formats/xhtml.lua create mode 100755 Master/texmf-dist/scripts/make4ht/make4ht-odtfilter.lua delete mode 100755 Master/texmf-dist/scripts/make4ht/mathnode.lua diff --git a/Build/source/texk/texlive/linked_scripts/make4ht/make4ht b/Build/source/texk/texlive/linked_scripts/make4ht/make4ht index b1ff84f7006..fd153164cd7 100755 --- a/Build/source/texk/texlive/linked_scripts/make4ht/make4ht +++ b/Build/source/texk/texlive/linked_scripts/make4ht/make4ht @@ -29,7 +29,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.3" +local version = "v0.3b" mkparams.version_number = version local args = mkparams.get_args() diff --git a/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl b/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl index 447bca1ea77..b99d8423122 100755 --- a/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl +++ b/Build/source/texk/texlive/linked_scripts/texlive/tlmgr.pl @@ -4680,12 +4680,12 @@ sub action_option { } elsif ($what eq $TLPDBOptions{"backupdir"}->[2]) { info("$prg: setting option $what to $val.\n"); if (! -d $val) { - info("$prg: the directory $val does not exists, it has to be created\n"); + info("$prg: the directory $val does not exist; you must create it\n"); info("$prg: before backups can be done automatically.\n"); } $localtlpdb->option($opt, $val); } elsif ($what eq $TLPDBOptions{"w32_multi_user"}->[2]) { - # when running w32 do not allow that a non-admin users sets + # when running w32 do not allow that a non-admin user sets # this from false to true my $do_it = 0; if (win32()) { @@ -4758,6 +4758,8 @@ sub action_option { return ($F_ERROR); } } + my $local_location = $localtlpdb->location; + info("$prg: updating $local_location\n"); $localtlpdb->save; # now also save the TLPOBJ of 00texlive.installation my $tlpo = $localtlpdb->get_package("00texlive.installation"); @@ -7603,7 +7605,7 @@ between an option name and its value. Specify the package repository from which packages should be installed or updated, either a local directory or network location, as below. This -overridesthe default package repository found in the installation's TeX +overrides the default package repository found in the installation's TeX Live Package Database (a.k.a. the TLPDB, which is given entirely in the file C). diff --git a/Master/texmf-dist/doc/support/make4ht/changelog.tex b/Master/texmf-dist/doc/support/make4ht/changelog.tex index f2b0fd77353..723de6762bb 100644 --- a/Master/texmf-dist/doc/support/make4ht/changelog.tex +++ b/Master/texmf-dist/doc/support/make4ht/changelog.tex @@ -2,13 +2,36 @@ \section{Changelog}\label{changelog}} \begin{itemize} +\item + 2019/11/03 + + \begin{itemize} + \tightlist + \item + version \texttt{0.3b} + \item + use \texttt{make4ht-ext-} prefix for extensions to prevent filename + clashes with corresponding filters. + \end{itemize} +\item + 2019/11/01 + + \begin{itemize} + \tightlist + \item + version \texttt{0.3a} released. + \item + added \texttt{make4ht-} prefix to all extensions and formats + \item + removed the unused \texttt{mathjaxnode.lua} file. + \end{itemize} \item 2019/11/01 \begin{itemize} \tightlist \item - version 0.3 released + version \texttt{0.3} released. \item added \texttt{Make:makeindex}, \texttt{Make:xindex} and \texttt{Make:bibtex} commands. diff --git a/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf index 506be1df428..9676888d51d 100644 Binary files a/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf and b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf differ diff --git a/Master/texmf-dist/scripts/make4ht/extensions/common_domfilters.lua b/Master/texmf-dist/scripts/make4ht/extensions/common_domfilters.lua deleted file mode 100644 index 9399492d907..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/common_domfilters.lua +++ /dev/null @@ -1,36 +0,0 @@ -local M = {} - - --- this variable will hold the output format name -local current_format - -local filter = require "make4ht-domfilter" --- local process = filter {"fixinlines", "idcolons", "joincharacters" } - --- filters support only html formats -function M.test(format) - current_format = format - -- if format == "odt" then return false end - return true -end - -function M.modify_build(make) - -- number of filters that should be moved to the beginning - local count = 0 - if current_format == "odt" then - -- some formats doesn't make sense in the ODT format - local process = filter {"joincharacters"} - local charclasses = {mn = true, ["text:span"] = true} - make:match("4oo$", process, {charclasses= charclasses}) - -- match math documents - make:match("4om$", process, {charclasses= charclasses}) - count = 2 - else - local process = filter {"fixinlines", "idcolons", "joincharacters", "tablerows"} - make:match("html$", process) - count = 1 - end - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/common_filters.lua b/Master/texmf-dist/scripts/make4ht/extensions/common_filters.lua deleted file mode 100644 index 513fbed34ee..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/common_filters.lua +++ /dev/null @@ -1,26 +0,0 @@ -local M = {} - - -local filter = require "make4ht-filter" -local process = filter {"cleanspan-nat", "fixligatures", "hruletohr", "entities", "fix-links"} - --- filters support only html formats -function M.test(format) - if format == "odt" then return false end - return true -end - -function M.modify_build(make) - make:match("html$", process) - local matches = make.matches - -- the filters should be first match to be executed, especially if tidy - -- should be executed as well - if #matches > 1 then - local last = matches[#matches] - table.insert(matches, 1, last) - matches[#matches] = nil - end - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/dvisvgm_hashes.lua b/Master/texmf-dist/scripts/make4ht/extensions/dvisvgm_hashes.lua deleted file mode 100644 index 87f58abd57c..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/dvisvgm_hashes.lua +++ /dev/null @@ -1,269 +0,0 @@ -local dvireader = require "make4ht-dvireader" -local mkutils = require "mkutils" -local filter = require "make4ht-filter" -local log = logging.new "dvisvgm_hashes" - - -local dvisvgm_par = {} - -local M = {} --- mapping between tex4ht image names and hashed image names -local output_map = {} -local dvisvgm_options = "-n --exact -c ${scale},${scale}" -local parallel_size = 64 --- local parallel_size = 3 - -local function make_hashed_name(base, hash) - return base .. "-" ..hash..".svg" -end - --- detect the number of available processors -local cpu_cnt = 3 -- set a reasonable default for non-Linux systems - -if os.name == 'linux' then - cpu_cnt = 0 - local cpuinfo=assert(io.open('/proc/cpuinfo', 'r')) - for line in cpuinfo:lines() do - if line:match('^processor') then - cpu_cnt = cpu_cnt + 1 - end - end - -- set default number of threds if no CPU core have been found - if cpu_cnt == 0 then cpu_cnt = 1 end - cpuinfo:close() -elseif os.name == 'cygwin' or os.type == 'windows' then - -- windows has NUMBER_OF_PROCESSORS environmental value - local nop = os.getenv('NUMBER_OF_PROCESSORS') - if tonumber(nop) then - cpu_cnt = nop - end -end - - - --- process output of dvisvgm and find output page numbers and corresponding files -local function get_generated_pages(output, pages) - local pages = pages or {} - local pos = 1 - local pos, finish, page = string.find(output, "processing page (%d+)", pos) - while(pos) do - pos, finish, file = string.find(output, "output written to ([^\n]+)", finish) - pages[tonumber(page)] = file - if not finish then break end - pos, finish, page = string.find(output, "processing page (%d+)", finish) - end - return pages -end - -local function make_ranges(pages) - local newpages = {} - local start, stop - for i=1,#pages do - local current = pages[i] - local next_el = pages[i+1] or current + 100 -- just select a big number - local diff = next_el - current - if diff == 1 then - if not start then start = current end - else - local element - if start then - element = start .. "-" .. current - else - element = current - end - newpages[#newpages+1] = element - start = nil - end - end - return newpages -end - -local function read_log(dvisvgmlog) - local f = io.open(dvisvgmlog, "rb") - if not f then return nil, "Cannot read dvisvgm log" end - local output = f:read("*all") - f:close() - return output -end - --- test the existence of GNU Make, which can execute tasks in parallel -local function test_make() - local make = io.popen("make -v", "r") - if not make then return false end - local content = make:read("*all") - make:close() - return true -end - -local function save_file(filename, text) - local f = io.open(filename, "w") - f:write(text) - f:close() -end - - -local function make_makefile_command(idvfile, page_sequences) - local logs = {} - local all = {} -- list of targets in the "all:" makefile target - local targets = {} - local basename = idvfile:gsub(".idv$", "") - local makefilename = basename .. "-images" .. ".mk" - -- build make targets - for i, ranges in ipairs(page_sequences) do - local target = basename .. "-" .. i - local logfile = target .. ".dlog" - logs[#logs + 1] = logfile - all[#all+1] = target - local chunk = target .. ":\n\tdvisvgm -v4 " .. dvisvgm_options .. " -p " .. ranges .. " " .. idvfile .. " 2> " .. logfile .. "\n" - targets[#targets + 1] = chunk - end - -- construct makefile and save it - local makefile = "all: " .. table.concat(all, " ") .. "\n\n" .. table.concat(targets, "\n") - save_file(makefilename, makefile) - local command = "make -j" .. cpu_cnt .." -f " .. makefilename - return command, logs -end - -local function prepare_command(idvfile, pages) - local logs = {} - if #pages > parallel_size and test_make() then - local page_sequences = {} - for i=1, #pages, parallel_size do - local current_pages = {} - for x = i, i+parallel_size -1 do - current_pages[#current_pages + 1] = pages[x] - end - table.insert(page_sequences,table.concat(make_ranges(current_pages), ",")) - end - return make_makefile_command(idvfile, page_sequences) - end - -- else - local pagesequence = table.concat(make_ranges(pages), ",") - -- the stderr from dvisvgm must be redirected and postprocessed - local dvisvgmlog = idvfile:gsub("idv$", "dlog") - -- local dvisvgm = io.popen("dvisvgm -v4 -n --exact -c 1.15,1.15 -p " .. pagesequence .. " " .. idvfile, "r") - local command = "dvisvgm -v4 " .. dvisvgm_options .. " -p " .. pagesequence .. " " .. idvfile .. " 2> " .. dvisvgmlog - return command, {dvisvgmlog} - -- end -end - -local function execute_dvisvgm(idvfile, pages) - if #pages < 1 then return nil, "No pages to convert" end - local command, logs = prepare_command(idvfile, pages) - log:info(command) - os.execute(command) - local generated_pages = {} - for _, dvisvgmlog in ipairs(logs) do - local output = read_log(dvisvgmlog) - generated_pages = get_generated_pages(output, generated_pages) - end - return generated_pages -end - -local function get_dvi_pages(arg) - -- list of pages to convert in this run - local to_convert = {} - local idv_file = arg.input .. ".idv" - -- set extension options - local extoptions = mkutils.get_filter_settings "dvisvgm_hashes" or {} - dvisvgm_options = arg.options or extoptions.options or dvisvgm_options - parallel_size = arg.parallel_size or extoptions.parallel_size or parallel_size - cpu_cnt = arg.cpu_cnt or extoptions.cpu_cnt or cpu_cnt - dvisvgm_par.scale = arg.scale or extoptions.scale or 1.15 - dvisvgm_options = dvisvgm_options % dvisvgm_par - local f = io.open(idv_file, "rb") - if not f then return nil, "Cannot open idv file: " .. idv_file end - local content = f:read("*all") - f:close() - local dvi_pages = dvireader.get_pages(content) - -- we must find page numbers and output name sfor the generated images - local lg = mkutils.parse_lg(arg.input ..".lg") - for _, name in ipairs(lg.images) do - local page = tonumber(name.page) - local hash = dvi_pages[page] - local tex4ht_name = name.output - local output_name = make_hashed_name(arg.input, hash) - output_map[tex4ht_name] = output_name - if not mkutils.file_exists(output_name) then - log:debug("output file: ".. output_name) - to_convert[#to_convert+1] = page - end - end - local generated_files, msg = execute_dvisvgm(idv_file, to_convert) - if not generated_files then - return nil, msg - end - - -- rename the generated files to the hashed filenames - for page, file in pairs(generated_files) do - os.rename(file, make_hashed_name(arg.input, dvi_pages[page])) - end - -end - -function M.test(format) - -- ODT format doesn't support SVG - if format == "odt" then return false end - return true -end - -function M.modify_build(make) - -- this must be used in the .mk4 file as - -- Make:dvisvgm_hashes {} - make:add("dvisvgm_hashes", function(arg) - get_dvi_pages(arg) - end, - { - }) - - -- insert dvisvgm_hashes command at the end of the build sequence -- it needs to be called after t4ht - make:dvisvgm_hashes {} - - -- replace original image names with hashed names - local executed = false - make:match(".*", function(arg) - if not executed then - executed = true - local lgfiles = make.lgfile.files - for i, filename in ipairs(lgfiles) do - local replace = output_map[filename] - if replace then - lgfiles[i] = replace - end - end - -- tex4ebook process also the images table, so we need to replace generated filenames here as well - local lgimages = make.lgfile.images - for _, image in ipairs(lgimages) do - local replace = output_map[image.output] - if replace then - image.output = replace - end - end - end - end) - - -- fix src attributes - local process = filter { - function(str) - return str:gsub('src="([^"]+)', function(filename) - local newname = output_map[filename] or filename - log:debug("newname", newname) - return 'src="'.. newname - end) - end - } - - make:match("htm.?$", process) - - -- disable the image processing - for _,v in ipairs(make.build_seq) do - if v.name == "t4ht" then - local t4ht_par = v.params.t4ht_par or make.params.t4ht_par or "" - v.params.t4ht_par = t4ht_par .. " -p" - end - end - make:image(".", function() return "" end) - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/join_colors.lua b/Master/texmf-dist/scripts/make4ht/extensions/join_colors.lua deleted file mode 100644 index 182661fbdbc..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/join_colors.lua +++ /dev/null @@ -1,16 +0,0 @@ -local M = {} - -local filter = require "make4ht-domfilter" - --- filters support only html formats -function M.test(format) - if format == "odt" then return false end - return true -end - -function M.modify_build(make) - local process = filter {"joincolors"} - make:match("html$", process) - return make -end -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua b/Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua deleted file mode 100644 index bf4dcdde5a4..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/latexmk_build.lua +++ /dev/null @@ -1,31 +0,0 @@ --- use Latexmk in first LaTeX call --- only in the first call, because we don't need to execute biber, etc. in the subsequent --- LaTeX calls, these are only for resolving the cross-references -local M = {} -function M.modify_build(make) - local used = false - local first - local build_seq = make.build_seq - -- find first htlatex call in the build sequence - for pos,v in ipairs(build_seq) do - if v.name == "htlatex" and not first then - first = pos - end - end - -- if htlatex was found - if first then - -- add dummy latexmk call to the build sequence - make:latexmk {} - -- replace name, command and type in the first htlatex - -- call with values from the dummy latexmk call - local replaced = build_seq[first] - local latexmk = build_seq[#build_seq] - replaced.name = latexmk.name - replaced.command = latexmk.command - replaced.type = latexmk.type - -- remove the dummy latexmk - table.remove(build_seq) - end - return make -end -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_domfilters.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_domfilters.lua new file mode 100644 index 00000000000..9399492d907 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_domfilters.lua @@ -0,0 +1,36 @@ +local M = {} + + +-- this variable will hold the output format name +local current_format + +local filter = require "make4ht-domfilter" +-- local process = filter {"fixinlines", "idcolons", "joincharacters" } + +-- filters support only html formats +function M.test(format) + current_format = format + -- if format == "odt" then return false end + return true +end + +function M.modify_build(make) + -- number of filters that should be moved to the beginning + local count = 0 + if current_format == "odt" then + -- some formats doesn't make sense in the ODT format + local process = filter {"joincharacters"} + local charclasses = {mn = true, ["text:span"] = true} + make:match("4oo$", process, {charclasses= charclasses}) + -- match math documents + make:match("4om$", process, {charclasses= charclasses}) + count = 2 + else + local process = filter {"fixinlines", "idcolons", "joincharacters", "tablerows"} + make:match("html$", process) + count = 1 + end + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_filters.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_filters.lua new file mode 100644 index 00000000000..513fbed34ee --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-common_filters.lua @@ -0,0 +1,26 @@ +local M = {} + + +local filter = require "make4ht-filter" +local process = filter {"cleanspan-nat", "fixligatures", "hruletohr", "entities", "fix-links"} + +-- filters support only html formats +function M.test(format) + if format == "odt" then return false end + return true +end + +function M.modify_build(make) + make:match("html$", process) + local matches = make.matches + -- the filters should be first match to be executed, especially if tidy + -- should be executed as well + if #matches > 1 then + local last = matches[#matches] + table.insert(matches, 1, last) + matches[#matches] = nil + end + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-dvisvgm_hashes.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-dvisvgm_hashes.lua new file mode 100644 index 00000000000..87f58abd57c --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-dvisvgm_hashes.lua @@ -0,0 +1,269 @@ +local dvireader = require "make4ht-dvireader" +local mkutils = require "mkutils" +local filter = require "make4ht-filter" +local log = logging.new "dvisvgm_hashes" + + +local dvisvgm_par = {} + +local M = {} +-- mapping between tex4ht image names and hashed image names +local output_map = {} +local dvisvgm_options = "-n --exact -c ${scale},${scale}" +local parallel_size = 64 +-- local parallel_size = 3 + +local function make_hashed_name(base, hash) + return base .. "-" ..hash..".svg" +end + +-- detect the number of available processors +local cpu_cnt = 3 -- set a reasonable default for non-Linux systems + +if os.name == 'linux' then + cpu_cnt = 0 + local cpuinfo=assert(io.open('/proc/cpuinfo', 'r')) + for line in cpuinfo:lines() do + if line:match('^processor') then + cpu_cnt = cpu_cnt + 1 + end + end + -- set default number of threds if no CPU core have been found + if cpu_cnt == 0 then cpu_cnt = 1 end + cpuinfo:close() +elseif os.name == 'cygwin' or os.type == 'windows' then + -- windows has NUMBER_OF_PROCESSORS environmental value + local nop = os.getenv('NUMBER_OF_PROCESSORS') + if tonumber(nop) then + cpu_cnt = nop + end +end + + + +-- process output of dvisvgm and find output page numbers and corresponding files +local function get_generated_pages(output, pages) + local pages = pages or {} + local pos = 1 + local pos, finish, page = string.find(output, "processing page (%d+)", pos) + while(pos) do + pos, finish, file = string.find(output, "output written to ([^\n]+)", finish) + pages[tonumber(page)] = file + if not finish then break end + pos, finish, page = string.find(output, "processing page (%d+)", finish) + end + return pages +end + +local function make_ranges(pages) + local newpages = {} + local start, stop + for i=1,#pages do + local current = pages[i] + local next_el = pages[i+1] or current + 100 -- just select a big number + local diff = next_el - current + if diff == 1 then + if not start then start = current end + else + local element + if start then + element = start .. "-" .. current + else + element = current + end + newpages[#newpages+1] = element + start = nil + end + end + return newpages +end + +local function read_log(dvisvgmlog) + local f = io.open(dvisvgmlog, "rb") + if not f then return nil, "Cannot read dvisvgm log" end + local output = f:read("*all") + f:close() + return output +end + +-- test the existence of GNU Make, which can execute tasks in parallel +local function test_make() + local make = io.popen("make -v", "r") + if not make then return false end + local content = make:read("*all") + make:close() + return true +end + +local function save_file(filename, text) + local f = io.open(filename, "w") + f:write(text) + f:close() +end + + +local function make_makefile_command(idvfile, page_sequences) + local logs = {} + local all = {} -- list of targets in the "all:" makefile target + local targets = {} + local basename = idvfile:gsub(".idv$", "") + local makefilename = basename .. "-images" .. ".mk" + -- build make targets + for i, ranges in ipairs(page_sequences) do + local target = basename .. "-" .. i + local logfile = target .. ".dlog" + logs[#logs + 1] = logfile + all[#all+1] = target + local chunk = target .. ":\n\tdvisvgm -v4 " .. dvisvgm_options .. " -p " .. ranges .. " " .. idvfile .. " 2> " .. logfile .. "\n" + targets[#targets + 1] = chunk + end + -- construct makefile and save it + local makefile = "all: " .. table.concat(all, " ") .. "\n\n" .. table.concat(targets, "\n") + save_file(makefilename, makefile) + local command = "make -j" .. cpu_cnt .." -f " .. makefilename + return command, logs +end + +local function prepare_command(idvfile, pages) + local logs = {} + if #pages > parallel_size and test_make() then + local page_sequences = {} + for i=1, #pages, parallel_size do + local current_pages = {} + for x = i, i+parallel_size -1 do + current_pages[#current_pages + 1] = pages[x] + end + table.insert(page_sequences,table.concat(make_ranges(current_pages), ",")) + end + return make_makefile_command(idvfile, page_sequences) + end + -- else + local pagesequence = table.concat(make_ranges(pages), ",") + -- the stderr from dvisvgm must be redirected and postprocessed + local dvisvgmlog = idvfile:gsub("idv$", "dlog") + -- local dvisvgm = io.popen("dvisvgm -v4 -n --exact -c 1.15,1.15 -p " .. pagesequence .. " " .. idvfile, "r") + local command = "dvisvgm -v4 " .. dvisvgm_options .. " -p " .. pagesequence .. " " .. idvfile .. " 2> " .. dvisvgmlog + return command, {dvisvgmlog} + -- end +end + +local function execute_dvisvgm(idvfile, pages) + if #pages < 1 then return nil, "No pages to convert" end + local command, logs = prepare_command(idvfile, pages) + log:info(command) + os.execute(command) + local generated_pages = {} + for _, dvisvgmlog in ipairs(logs) do + local output = read_log(dvisvgmlog) + generated_pages = get_generated_pages(output, generated_pages) + end + return generated_pages +end + +local function get_dvi_pages(arg) + -- list of pages to convert in this run + local to_convert = {} + local idv_file = arg.input .. ".idv" + -- set extension options + local extoptions = mkutils.get_filter_settings "dvisvgm_hashes" or {} + dvisvgm_options = arg.options or extoptions.options or dvisvgm_options + parallel_size = arg.parallel_size or extoptions.parallel_size or parallel_size + cpu_cnt = arg.cpu_cnt or extoptions.cpu_cnt or cpu_cnt + dvisvgm_par.scale = arg.scale or extoptions.scale or 1.15 + dvisvgm_options = dvisvgm_options % dvisvgm_par + local f = io.open(idv_file, "rb") + if not f then return nil, "Cannot open idv file: " .. idv_file end + local content = f:read("*all") + f:close() + local dvi_pages = dvireader.get_pages(content) + -- we must find page numbers and output name sfor the generated images + local lg = mkutils.parse_lg(arg.input ..".lg") + for _, name in ipairs(lg.images) do + local page = tonumber(name.page) + local hash = dvi_pages[page] + local tex4ht_name = name.output + local output_name = make_hashed_name(arg.input, hash) + output_map[tex4ht_name] = output_name + if not mkutils.file_exists(output_name) then + log:debug("output file: ".. output_name) + to_convert[#to_convert+1] = page + end + end + local generated_files, msg = execute_dvisvgm(idv_file, to_convert) + if not generated_files then + return nil, msg + end + + -- rename the generated files to the hashed filenames + for page, file in pairs(generated_files) do + os.rename(file, make_hashed_name(arg.input, dvi_pages[page])) + end + +end + +function M.test(format) + -- ODT format doesn't support SVG + if format == "odt" then return false end + return true +end + +function M.modify_build(make) + -- this must be used in the .mk4 file as + -- Make:dvisvgm_hashes {} + make:add("dvisvgm_hashes", function(arg) + get_dvi_pages(arg) + end, + { + }) + + -- insert dvisvgm_hashes command at the end of the build sequence -- it needs to be called after t4ht + make:dvisvgm_hashes {} + + -- replace original image names with hashed names + local executed = false + make:match(".*", function(arg) + if not executed then + executed = true + local lgfiles = make.lgfile.files + for i, filename in ipairs(lgfiles) do + local replace = output_map[filename] + if replace then + lgfiles[i] = replace + end + end + -- tex4ebook process also the images table, so we need to replace generated filenames here as well + local lgimages = make.lgfile.images + for _, image in ipairs(lgimages) do + local replace = output_map[image.output] + if replace then + image.output = replace + end + end + end + end) + + -- fix src attributes + local process = filter { + function(str) + return str:gsub('src="([^"]+)', function(filename) + local newname = output_map[filename] or filename + log:debug("newname", newname) + return 'src="'.. newname + end) + end + } + + make:match("htm.?$", process) + + -- disable the image processing + for _,v in ipairs(make.build_seq) do + if v.name == "t4ht" then + local t4ht_par = v.params.t4ht_par or make.params.t4ht_par or "" + v.params.t4ht_par = t4ht_par .. " -p" + end + end + make:image(".", function() return "" end) + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-join_colors.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-join_colors.lua new file mode 100644 index 00000000000..182661fbdbc --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-join_colors.lua @@ -0,0 +1,16 @@ +local M = {} + +local filter = require "make4ht-domfilter" + +-- filters support only html formats +function M.test(format) + if format == "odt" then return false end + return true +end + +function M.modify_build(make) + local process = filter {"joincolors"} + make:match("html$", process) + return make +end +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua new file mode 100644 index 00000000000..bf4dcdde5a4 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua @@ -0,0 +1,31 @@ +-- use Latexmk in first LaTeX call +-- only in the first call, because we don't need to execute biber, etc. in the subsequent +-- LaTeX calls, these are only for resolving the cross-references +local M = {} +function M.modify_build(make) + local used = false + local first + local build_seq = make.build_seq + -- find first htlatex call in the build sequence + for pos,v in ipairs(build_seq) do + if v.name == "htlatex" and not first then + first = pos + end + end + -- if htlatex was found + if first then + -- add dummy latexmk call to the build sequence + make:latexmk {} + -- replace name, command and type in the first htlatex + -- call with values from the dummy latexmk call + local replaced = build_seq[first] + local latexmk = build_seq[#build_seq] + replaced.name = latexmk.name + replaced.command = latexmk.command + replaced.type = latexmk.type + -- remove the dummy latexmk + table.remove(build_seq) + end + return make +end +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-mathjaxnode.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-mathjaxnode.lua new file mode 100644 index 00000000000..cbad897d4ec --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-mathjaxnode.lua @@ -0,0 +1,16 @@ +local M = {} + + +local filter = require "make4ht-filter" +function M.test(format) + if format == "odt" then return false end + return true +end + +function M.modify_build(make) + local mathjax = filter { "mathjaxnode"} + make:match("html$",mathjax) + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-odttemplate.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-odttemplate.lua new file mode 100644 index 00000000000..3b0af2a6999 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-odttemplate.lua @@ -0,0 +1,16 @@ +local M = {} + +local filter = require "make4ht-filter" + +-- this extension only works for the ODT format +M.test = function(format) + return format=="odt" +end + +M.modify_build = function(make) + local process = filter {"odttemplate"} + make:match("4oy$", process) + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua new file mode 100644 index 00000000000..3155a8a7810 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua @@ -0,0 +1,108 @@ +-- preprocess R literate sources or Markdown files to LaTeX +local M = {} +local log = logging.new "preprocess_input" +local mkutils = require "mkutils" + +local commands = { + knitr = { command = 'Rscript -e "library(knitr); knit(\'${tex_file}\', output=\'${tmp_file}\')"'}, + pandoc = { command = 'pandoc -f ${input_format} -s -o \'${tmp_file}\' -t latex \'${tex_file}\''} +} +local filetypes = { + rnw = {sequence = {"knitr"} }, + rtex = {sequence = {"knitr"}}, + rmd = {sequence = {"knitr", "pandoc"}, options = {input_format = "markdown"}}, + rrst = {sequence = {"knitr", "pandoc"}, options = {input_format = "rst"}}, + md = {sequence = {"pandoc"}, options = {input_format = "markdown"}}, + rst = {sequence = {"pandoc"}, options = {input_format = "rst"}}, +} + + +local function execute_sequence(sequence, arg, make) + -- keep track of all generated tmp files + local temp_files = {} + -- the temporary file for the current compilation step + -- should become the tex_file for the next one. It doesn't + -- matter that it isn't TeX file in some cases + local previous_temp + for _, cmd_name in ipairs(sequence) do + local tmp_name = os.tmpname() + temp_files[#temp_files+1] = tmp_name + -- make the temp file name accessible to the executed commands + arg.tmp_file = tmp_name + -- the current temporary file should become tex_file in the next step + -- in the first execution of the compilation sequence we will use the + -- actual input file name + arg.tex_file = previous_temp or arg.tex_file + previous_temp = tmp_name + -- get the command to execute + local cmd = commands[cmd_name] + -- fill the command template with make4ht arguments and execute + local command = cmd.command % arg + log:info(command) + mkutils.execute(command) + end + return temp_files +end + +local function get_preprocessing_pipeline(input_file) + -- detect the file extension + local extension = input_file:match("%.(.-)$") + if not extension then return nil, "Cannot get extension: " .. input_file end + -- the table with file actions is case insensitive + -- the extension is converted to lowercase in order + -- to support both .rnw and .Rnw + extension = string.lower(extension) + local matched = filetypes[extension] + if not matched then return nil, "Unsupported extension: " .. extension end + return matched +end + +-- join the make4ht params and command options tables +local function make_options(arg, command_options) + local options = {} + local command_options = command_options or {} + for k,v in pairs(arg) do options[k] = v end + for k,v in pairs(command_options) do options[k] = v end + return options +end + +M.modify_build = function(make) + + -- get access to the main argumens + local arg = make.params + -- get the execution sequence for the input format + local matched, msg = get_preprocessing_pipeline(arg.tex_file) + if not matched then + log:error("preprocess_input error: ".. msg) + return + end + -- prepare options + local options = make_options(arg, matched.options) + -- run the execution sequence + local temp_files = execute_sequence(matched.sequence or {}, options, make) + -- the last temporary file contains the actual TeX file + local last_temp_file = temp_files[#temp_files] + -- remove the intermediate temp files + if #temp_files > 2 then + for i = 1, #temp_files - 1 do + log:debug("Removing temporary file", temp_files[i]) + os.remove(temp_files[i]) + end + end + if last_temp_file then + -- update all commands in the .mk4 file with the temp file as tex_file + local update_params = function(cmd) + local params = cmd.params + params.tex_file = last_temp_file + params.is_tmp_file = true + end + for _, cmd in ipairs(make.build_seq) do + update_params(cmd) + end + -- also update the main params + update_params(make) + end + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-staticsite.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-staticsite.lua new file mode 100644 index 00000000000..a4204bc1733 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-staticsite.lua @@ -0,0 +1,136 @@ +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", 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/extensions/make4ht-ext-tidy.lua b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua new file mode 100644 index 00000000000..b381a05a8fb --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua @@ -0,0 +1,58 @@ +local M = {} + +local log = logging.new "tidy" +function M.test(format) + if format == "odt" then return false end + return true +end + +local empty_elements = { + area=true, + base=true, + br=true, + col=true, + embed=true, + hr=true, + img=true, + input=true, + keygen=true, + link=true, + meta=true, + param=true, + source=true, + track=true, + wbr=true, +} + +-- LuaXML cannot read HTML with unclosed tags (like ) +-- Tidy removes end slashes in the HTML output, so +-- this function will add them back +local function close_tags(s) + return s:gsub("<(%w+)([^>]-)>", function(tag, rest) + local endslash = "" + if empty_elements[tag] then endslash = " /" end + return string.format("<%s%s%s>", tag, rest, endslash) + end) +end + + + +function M.modify_build(make) + make:match("html$", function(filename, par) + local settings = get_filter_settings "tidy" or {} + par.options = par.options or settings.options or "-utf8 -w 512 -ashtml -q" + local command = "tidy ${options} ${filename}" % par + log:info("running tidy: ".. command) + -- os.execute(command) + local run = io.popen(command, "r") + local result = run:read("*all") + run:close() + result = close_tags(result) + local f = io.open(filename, "w") + f:write(result) + f:close() + end) + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/mathjaxnode.lua b/Master/texmf-dist/scripts/make4ht/extensions/mathjaxnode.lua deleted file mode 100644 index cbad897d4ec..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/mathjaxnode.lua +++ /dev/null @@ -1,16 +0,0 @@ -local M = {} - - -local filter = require "make4ht-filter" -function M.test(format) - if format == "odt" then return false end - return true -end - -function M.modify_build(make) - local mathjax = filter { "mathjaxnode"} - make:match("html$",mathjax) - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/odttemplate.lua b/Master/texmf-dist/scripts/make4ht/extensions/odttemplate.lua deleted file mode 100644 index 3b0af2a6999..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/odttemplate.lua +++ /dev/null @@ -1,16 +0,0 @@ -local M = {} - -local filter = require "make4ht-filter" - --- this extension only works for the ODT format -M.test = function(format) - return format=="odt" -end - -M.modify_build = function(make) - local process = filter {"odttemplate"} - make:match("4oy$", process) - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/preprocess_input.lua b/Master/texmf-dist/scripts/make4ht/extensions/preprocess_input.lua deleted file mode 100644 index 3155a8a7810..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/preprocess_input.lua +++ /dev/null @@ -1,108 +0,0 @@ --- preprocess R literate sources or Markdown files to LaTeX -local M = {} -local log = logging.new "preprocess_input" -local mkutils = require "mkutils" - -local commands = { - knitr = { command = 'Rscript -e "library(knitr); knit(\'${tex_file}\', output=\'${tmp_file}\')"'}, - pandoc = { command = 'pandoc -f ${input_format} -s -o \'${tmp_file}\' -t latex \'${tex_file}\''} -} -local filetypes = { - rnw = {sequence = {"knitr"} }, - rtex = {sequence = {"knitr"}}, - rmd = {sequence = {"knitr", "pandoc"}, options = {input_format = "markdown"}}, - rrst = {sequence = {"knitr", "pandoc"}, options = {input_format = "rst"}}, - md = {sequence = {"pandoc"}, options = {input_format = "markdown"}}, - rst = {sequence = {"pandoc"}, options = {input_format = "rst"}}, -} - - -local function execute_sequence(sequence, arg, make) - -- keep track of all generated tmp files - local temp_files = {} - -- the temporary file for the current compilation step - -- should become the tex_file for the next one. It doesn't - -- matter that it isn't TeX file in some cases - local previous_temp - for _, cmd_name in ipairs(sequence) do - local tmp_name = os.tmpname() - temp_files[#temp_files+1] = tmp_name - -- make the temp file name accessible to the executed commands - arg.tmp_file = tmp_name - -- the current temporary file should become tex_file in the next step - -- in the first execution of the compilation sequence we will use the - -- actual input file name - arg.tex_file = previous_temp or arg.tex_file - previous_temp = tmp_name - -- get the command to execute - local cmd = commands[cmd_name] - -- fill the command template with make4ht arguments and execute - local command = cmd.command % arg - log:info(command) - mkutils.execute(command) - end - return temp_files -end - -local function get_preprocessing_pipeline(input_file) - -- detect the file extension - local extension = input_file:match("%.(.-)$") - if not extension then return nil, "Cannot get extension: " .. input_file end - -- the table with file actions is case insensitive - -- the extension is converted to lowercase in order - -- to support both .rnw and .Rnw - extension = string.lower(extension) - local matched = filetypes[extension] - if not matched then return nil, "Unsupported extension: " .. extension end - return matched -end - --- join the make4ht params and command options tables -local function make_options(arg, command_options) - local options = {} - local command_options = command_options or {} - for k,v in pairs(arg) do options[k] = v end - for k,v in pairs(command_options) do options[k] = v end - return options -end - -M.modify_build = function(make) - - -- get access to the main argumens - local arg = make.params - -- get the execution sequence for the input format - local matched, msg = get_preprocessing_pipeline(arg.tex_file) - if not matched then - log:error("preprocess_input error: ".. msg) - return - end - -- prepare options - local options = make_options(arg, matched.options) - -- run the execution sequence - local temp_files = execute_sequence(matched.sequence or {}, options, make) - -- the last temporary file contains the actual TeX file - local last_temp_file = temp_files[#temp_files] - -- remove the intermediate temp files - if #temp_files > 2 then - for i = 1, #temp_files - 1 do - log:debug("Removing temporary file", temp_files[i]) - os.remove(temp_files[i]) - end - end - if last_temp_file then - -- update all commands in the .mk4 file with the temp file as tex_file - local update_params = function(cmd) - local params = cmd.params - params.tex_file = last_temp_file - params.is_tmp_file = true - end - for _, cmd in ipairs(make.build_seq) do - update_params(cmd) - end - -- also update the main params - update_params(make) - end - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua b/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua deleted file mode 100644 index a4204bc1733..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/staticsite.lua +++ /dev/null @@ -1,136 +0,0 @@ -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", 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/extensions/tidy.lua b/Master/texmf-dist/scripts/make4ht/extensions/tidy.lua deleted file mode 100644 index b381a05a8fb..00000000000 --- a/Master/texmf-dist/scripts/make4ht/extensions/tidy.lua +++ /dev/null @@ -1,58 +0,0 @@ -local M = {} - -local log = logging.new "tidy" -function M.test(format) - if format == "odt" then return false end - return true -end - -local empty_elements = { - area=true, - base=true, - br=true, - col=true, - embed=true, - hr=true, - img=true, - input=true, - keygen=true, - link=true, - meta=true, - param=true, - source=true, - track=true, - wbr=true, -} - --- LuaXML cannot read HTML with unclosed tags (like ) --- Tidy removes end slashes in the HTML output, so --- this function will add them back -local function close_tags(s) - return s:gsub("<(%w+)([^>]-)>", function(tag, rest) - local endslash = "" - if empty_elements[tag] then endslash = " /" end - return string.format("<%s%s%s>", tag, rest, endslash) - end) -end - - - -function M.modify_build(make) - make:match("html$", function(filename, par) - local settings = get_filter_settings "tidy" or {} - par.options = par.options or settings.options or "-utf8 -w 512 -ashtml -q" - local command = "tidy ${options} ${filename}" % par - log:info("running tidy: ".. command) - -- os.execute(command) - local run = io.popen(command, "r") - local result = run:read("*all") - run:close() - result = close_tags(result) - local f = io.open(filename, "w") - f:write(result) - f:close() - end) - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/docbook.lua b/Master/texmf-dist/scripts/make4ht/formats/docbook.lua deleted file mode 100644 index 3bd79eb83ed..00000000000 --- a/Master/texmf-dist/scripts/make4ht/formats/docbook.lua +++ /dev/null @@ -1,39 +0,0 @@ -local M = {} -local mkutils = require "mkutils" -local lfs = require "lfs" -local os = require "os" -local kpse = require "kpse" -local filter = require "make4ht-filter" -local domfilter = require "make4ht-domfilter" -local xtpipeslib = require "make4ht-xtpipes" -local log = logging.new "docbook" - -function M.prepare_parameters(settings, extensions) - settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",docbook" - settings = mkutils.extensions_prepare_parameters(extensions, settings) - return settings -end - -local move_matches = xtpipeslib.move_matches - --- call xtpipes from Lua -local function call_xtpipes(make) - -- we must find root of the TeX distribution - local selfautoparent = xtpipeslib.get_selfautoparent() - - if selfautoparent then - local matchfunction = xtpipeslib.get_xtpipes(selfautoparent) - make:match("xml$", matchfunction) - move_matches(make) - else - log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution" - end -end - -function M.modify_build(make) - -- use xtpipes to fix some common docbook issues - call_xtpipes(make) - return make -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/html5.lua b/Master/texmf-dist/scripts/make4ht/formats/html5.lua deleted file mode 100644 index 633a45e7f34..00000000000 --- a/Master/texmf-dist/scripts/make4ht/formats/html5.lua +++ /dev/null @@ -1,17 +0,0 @@ -local M = {} - -local mkutils = require "mkutils" - -function M.prepare_extensions(extensions) - -- return mkutils.add_extensions("+common_domfilters", extensions) - return extensions --mkutils.add_extensions("+tidy", extensions) -end - -function M.prepare_parameters(parameters,extensions) - parameters.tex4ht_sty_par = parameters.tex4ht_sty_par .. ",html5" - parameters = mkutils.extensions_prepare_parameters(extensions,parameters) - return parameters -end - - -return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/make4ht-docbook.lua b/Master/texmf-dist/scripts/make4ht/formats/make4ht-docbook.lua new file mode 100644 index 00000000000..3bd79eb83ed --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/formats/make4ht-docbook.lua @@ -0,0 +1,39 @@ +local M = {} +local mkutils = require "mkutils" +local lfs = require "lfs" +local os = require "os" +local kpse = require "kpse" +local filter = require "make4ht-filter" +local domfilter = require "make4ht-domfilter" +local xtpipeslib = require "make4ht-xtpipes" +local log = logging.new "docbook" + +function M.prepare_parameters(settings, extensions) + settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",docbook" + settings = mkutils.extensions_prepare_parameters(extensions, settings) + return settings +end + +local move_matches = xtpipeslib.move_matches + +-- call xtpipes from Lua +local function call_xtpipes(make) + -- we must find root of the TeX distribution + local selfautoparent = xtpipeslib.get_selfautoparent() + + if selfautoparent then + local matchfunction = xtpipeslib.get_xtpipes(selfautoparent) + make:match("xml$", matchfunction) + move_matches(make) + else + log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution" + end +end + +function M.modify_build(make) + -- use xtpipes to fix some common docbook issues + call_xtpipes(make) + return make +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/make4ht-html5.lua b/Master/texmf-dist/scripts/make4ht/formats/make4ht-html5.lua new file mode 100644 index 00000000000..633a45e7f34 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/formats/make4ht-html5.lua @@ -0,0 +1,17 @@ +local M = {} + +local mkutils = require "mkutils" + +function M.prepare_extensions(extensions) + -- return mkutils.add_extensions("+common_domfilters", extensions) + return extensions --mkutils.add_extensions("+tidy", extensions) +end + +function M.prepare_parameters(parameters,extensions) + parameters.tex4ht_sty_par = parameters.tex4ht_sty_par .. ",html5" + parameters = mkutils.extensions_prepare_parameters(extensions,parameters) + return parameters +end + + +return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua b/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua new file mode 100644 index 00000000000..c515a154a1b --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua @@ -0,0 +1,224 @@ +local M = {} +local mkutils = require "mkutils" +local lfs = require "lfs" +local os = require "os" +local kpse = require "kpse" +local filter = require "make4ht-filter" +local domfilter = require "make4ht-domfilter" +local xtpipeslib = require "make4ht-xtpipes" +local log = logging.new "odt" + + +function M.prepare_parameters(settings, extensions) + settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",ooffice" + settings.tex4ht_par = settings.tex4ht_par .. " ooffice/! -cmozhtf" + -- settings.t4ht_par = settings.t4ht_par .. " -cooxtpipes -coo " + -- settings.t4ht_par = settings.t4ht_par .. " -cooxtpipes " + settings = mkutils.extensions_prepare_parameters(extensions, settings) + return settings +end + +-- object for working with the ODT file +local Odtfile = {} +Odtfile.__index = Odtfile + +Odtfile.new = function(archivename) + local self = setmetatable({}, Odtfile) + -- create a temporary file + local tmpname = os.tmpname() + -- remove a temporary file, we are interested only in the unique file name + os.remove(tmpname) + -- get the unique dir name + tmpname = tmpname:match("([a-zA-Z0-9_%-%.]+)$") + local status, msg = lfs.mkdir(tmpname) + if not status then return nil, msg end + -- make picture dir + lfs.mkdir(tmpname .. "/Pictures") + self.archivelocation = tmpname + self.name = archivename + return self +end + +function Odtfile:copy(src, dest) + mkutils.cp(src, self.archivelocation .. "/" .. dest) +end + +function Odtfile:move(src, dest) + mkutils.mv(src, self.archivelocation .. "/" .. dest) +end + +function Odtfile:create_dir(dir) + local currentdir = lfs.currentdir() + lfs.chdir(self.archivelocation) + lfs.mkdir(dir) + lfs.chdir(currentdir) +end + +function Odtfile:make_mimetype() + self.mimetypename = "mimetype" + local m = io.open(self.mimetypename, "w") + m:write("application/vnd.oasis.opendocument.text") + m:close() +end + +function Odtfile:remove_mimetype() + os.remove(self.mimetypename) +end + + +function Odtfile:pack() + local currentdir = lfs.currentdir() + local zip_command = mkutils.find_zip() + lfs.chdir(self.archivelocation) + -- make temporary mime type file + self:make_mimetype() + mkutils.execute(zip_command .. " -q0X " .. self.name .. " " .. self.mimetypename) + -- remove it, so the next command doesn't overwrite it + self:remove_mimetype() + mkutils.execute(zip_command .." -r " .. self.name .. " *") + lfs.chdir(currentdir) + mkutils.cp(self.archivelocation .. "/" .. self.name, self.name) + mkutils.delete_dir(self.archivelocation) +end + +-- escape string to be used in the gsub search +local function escape_file(filename) + local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])' + return filename:gsub(quotepattern, "%%%1") +end + +local move_matches = xtpipeslib.move_matches + +-- call xtpipes from Lua +local function call_xtpipes(make) + -- we must find root of the TeX distribution + local selfautoparent = xtpipeslib.get_selfautoparent() + + if selfautoparent then + local matchfunction = xtpipeslib.get_xtpipes(selfautoparent) + make:match("4oo", matchfunction) + make:match("4om", matchfunction) + -- move last match to a first place + -- we need to move last two matches, for 4oo and 4om files + move_matches(make) + move_matches(make) + else + log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution" + end +end + +-- sort output files according to their extensions +local function prepare_output_files(lgfiles) + local groups = {} + for _, name in ipairs(lgfiles) do + local basename, extension = name:match("(.-)%.([^%.]+)$") + local group = groups[extension] or {} + table.insert(group, basename) + groups[extension] = group + log:debug("prepare output file", basename, extension) + end + return groups +end + +-- execute function on all files in the group +-- function fn takes current filename and table with various attributes +local function exec_group(groups, name, fn) + for _, basename in ipairs(groups[name] or {}) do + fn{basename = basename, extension=name, filename = basename .. "." .. name} + end +end + +function M.modify_build(make) + local executed = false + -- execute xtpipes from the build file, instead of t4ht. this fixes issues with wrong paths + -- expanded in tex4ht.env in Miktex or Debian + call_xtpipes(make) + -- fix the image dimensions wrongly set by xtpipes + local domfilters = domfilter {"t4htlinks", "odtpartable"} + make:match("4oo$", domfilters) + -- execute it before xtpipes, because we don't want xtpipes to mess with t4htlink elements + move_matches(make) + -- convert XML entities for Unicode characters produced by Xtpipes to characters + local fixentities = filter {"entities-to-unicode"} + make:match("4oo", fixentities) + make:match("4om", fixentities) + + -- build the ODT file. This match must be executed as a last one + -- this will be executed as a first match, just to find the last filename + -- in the lgfile + make:match(".*", function() + -- execute it only once + if not executed then + -- this is list of processed files + local lgfiles = make.lgfile.files + -- find the last file and escape it so it can be used + -- in filename match + local lastfile = escape_file(lgfiles[#lgfiles]) .."$" + -- make match for the last file + -- odt packing will be done here + make:match(lastfile, function() + local groups = prepare_output_files(make.lgfile.files) + local basename = groups.odt[1] + local odtname = basename .. ".odt" + local odt,msg = Odtfile.new(odtname) + if not odt then + log:error("Cannot create ODT file: " .. msg) + end + -- helper function for simple file moving + local function move_file(group, dest) + exec_group(groups, group, function(par) + odt:move("${filename}" % par, dest) + end) + end + + -- the document text + exec_group(groups, "4oo", function(par) + odt:move("${filename}" % par, "content.xml") + odt:create_dir("Pictures") + end) + + -- manifest + exec_group(groups, "4of", function(par) + odt:create_dir("META-INF") + odt:move("${filename}" % par, "META-INF/manifest.xml") + end) + + -- math + exec_group(groups, "4om", function(par) + odt:create_dir(par.basename) + odt:move("${filename}" % par, "${basename}/content.xml" % par) + -- copy the settings file to math subdir + local settings = groups["4os"][1] + odt:copy(settings .. ".4os", "${basename}/settings.xml" % par) + end) + + -- these files are created only once, so it doesn't matter that they are + -- copied to one file + move_file("4os", "settings.xml") + move_file("4ot", "meta.xml") + move_file("4oy", "styles.xml") + + -- pictures + exec_group(groups, "4og", function(par) + -- add support for images in the TEXMF tree + if not mkutils.file_exists(par.basename) then + par.basename = kpse.find_file(par.basename, "graphic/figure") + if not par.basename then return nil, "Cannot find picture" end + end + -- the Pictues dir is flat, without subdirs + odt:copy("${basename}" % par, "Pictures") + end) + + -- remove some spurious file + exec_group(groups, "4od", function(par) + os.remove(par.filename) + end) + + odt:pack() + end) + end + executed = true + end) + return make +end +return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/make4ht-tei.lua b/Master/texmf-dist/scripts/make4ht/formats/make4ht-tei.lua new file mode 100644 index 00000000000..f81953a8b31 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/formats/make4ht-tei.lua @@ -0,0 +1,14 @@ +local M = {} +local xtpipeslib = require "make4ht-xtpipes" + +function M.prepare_parameters(settings, extensions) + settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",tei" + settings = mkutils.extensions_prepare_parameters(extensions, settings) + return settings +end + +function M.prepare_extensions(extensions) + return extensions +end + +return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/make4ht-xhtml.lua b/Master/texmf-dist/scripts/make4ht/formats/make4ht-xhtml.lua new file mode 100644 index 00000000000..4a4ac6689ca --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/formats/make4ht-xhtml.lua @@ -0,0 +1,16 @@ +local M = {} + +local mkutils = require "mkutils" + +function M.prepare_extensions(extensions) + -- return mkutils.add_extensions("+common_domfilters", extensions) + return extensions +end + +function M.prepare_parameters(parameters,extensions) + parameters = mkutils.extensions_prepare_parameters(extensions,parameters) + return parameters +end + + +return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/odt.lua b/Master/texmf-dist/scripts/make4ht/formats/odt.lua deleted file mode 100644 index c515a154a1b..00000000000 --- a/Master/texmf-dist/scripts/make4ht/formats/odt.lua +++ /dev/null @@ -1,224 +0,0 @@ -local M = {} -local mkutils = require "mkutils" -local lfs = require "lfs" -local os = require "os" -local kpse = require "kpse" -local filter = require "make4ht-filter" -local domfilter = require "make4ht-domfilter" -local xtpipeslib = require "make4ht-xtpipes" -local log = logging.new "odt" - - -function M.prepare_parameters(settings, extensions) - settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",ooffice" - settings.tex4ht_par = settings.tex4ht_par .. " ooffice/! -cmozhtf" - -- settings.t4ht_par = settings.t4ht_par .. " -cooxtpipes -coo " - -- settings.t4ht_par = settings.t4ht_par .. " -cooxtpipes " - settings = mkutils.extensions_prepare_parameters(extensions, settings) - return settings -end - --- object for working with the ODT file -local Odtfile = {} -Odtfile.__index = Odtfile - -Odtfile.new = function(archivename) - local self = setmetatable({}, Odtfile) - -- create a temporary file - local tmpname = os.tmpname() - -- remove a temporary file, we are interested only in the unique file name - os.remove(tmpname) - -- get the unique dir name - tmpname = tmpname:match("([a-zA-Z0-9_%-%.]+)$") - local status, msg = lfs.mkdir(tmpname) - if not status then return nil, msg end - -- make picture dir - lfs.mkdir(tmpname .. "/Pictures") - self.archivelocation = tmpname - self.name = archivename - return self -end - -function Odtfile:copy(src, dest) - mkutils.cp(src, self.archivelocation .. "/" .. dest) -end - -function Odtfile:move(src, dest) - mkutils.mv(src, self.archivelocation .. "/" .. dest) -end - -function Odtfile:create_dir(dir) - local currentdir = lfs.currentdir() - lfs.chdir(self.archivelocation) - lfs.mkdir(dir) - lfs.chdir(currentdir) -end - -function Odtfile:make_mimetype() - self.mimetypename = "mimetype" - local m = io.open(self.mimetypename, "w") - m:write("application/vnd.oasis.opendocument.text") - m:close() -end - -function Odtfile:remove_mimetype() - os.remove(self.mimetypename) -end - - -function Odtfile:pack() - local currentdir = lfs.currentdir() - local zip_command = mkutils.find_zip() - lfs.chdir(self.archivelocation) - -- make temporary mime type file - self:make_mimetype() - mkutils.execute(zip_command .. " -q0X " .. self.name .. " " .. self.mimetypename) - -- remove it, so the next command doesn't overwrite it - self:remove_mimetype() - mkutils.execute(zip_command .." -r " .. self.name .. " *") - lfs.chdir(currentdir) - mkutils.cp(self.archivelocation .. "/" .. self.name, self.name) - mkutils.delete_dir(self.archivelocation) -end - --- escape string to be used in the gsub search -local function escape_file(filename) - local quotepattern = '(['..("%^$().[]*+-?"):gsub("(.)", "%%%1")..'])' - return filename:gsub(quotepattern, "%%%1") -end - -local move_matches = xtpipeslib.move_matches - --- call xtpipes from Lua -local function call_xtpipes(make) - -- we must find root of the TeX distribution - local selfautoparent = xtpipeslib.get_selfautoparent() - - if selfautoparent then - local matchfunction = xtpipeslib.get_xtpipes(selfautoparent) - make:match("4oo", matchfunction) - make:match("4om", matchfunction) - -- move last match to a first place - -- we need to move last two matches, for 4oo and 4om files - move_matches(make) - move_matches(make) - else - log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution" - end -end - --- sort output files according to their extensions -local function prepare_output_files(lgfiles) - local groups = {} - for _, name in ipairs(lgfiles) do - local basename, extension = name:match("(.-)%.([^%.]+)$") - local group = groups[extension] or {} - table.insert(group, basename) - groups[extension] = group - log:debug("prepare output file", basename, extension) - end - return groups -end - --- execute function on all files in the group --- function fn takes current filename and table with various attributes -local function exec_group(groups, name, fn) - for _, basename in ipairs(groups[name] or {}) do - fn{basename = basename, extension=name, filename = basename .. "." .. name} - end -end - -function M.modify_build(make) - local executed = false - -- execute xtpipes from the build file, instead of t4ht. this fixes issues with wrong paths - -- expanded in tex4ht.env in Miktex or Debian - call_xtpipes(make) - -- fix the image dimensions wrongly set by xtpipes - local domfilters = domfilter {"t4htlinks", "odtpartable"} - make:match("4oo$", domfilters) - -- execute it before xtpipes, because we don't want xtpipes to mess with t4htlink elements - move_matches(make) - -- convert XML entities for Unicode characters produced by Xtpipes to characters - local fixentities = filter {"entities-to-unicode"} - make:match("4oo", fixentities) - make:match("4om", fixentities) - - -- build the ODT file. This match must be executed as a last one - -- this will be executed as a first match, just to find the last filename - -- in the lgfile - make:match(".*", function() - -- execute it only once - if not executed then - -- this is list of processed files - local lgfiles = make.lgfile.files - -- find the last file and escape it so it can be used - -- in filename match - local lastfile = escape_file(lgfiles[#lgfiles]) .."$" - -- make match for the last file - -- odt packing will be done here - make:match(lastfile, function() - local groups = prepare_output_files(make.lgfile.files) - local basename = groups.odt[1] - local odtname = basename .. ".odt" - local odt,msg = Odtfile.new(odtname) - if not odt then - log:error("Cannot create ODT file: " .. msg) - end - -- helper function for simple file moving - local function move_file(group, dest) - exec_group(groups, group, function(par) - odt:move("${filename}" % par, dest) - end) - end - - -- the document text - exec_group(groups, "4oo", function(par) - odt:move("${filename}" % par, "content.xml") - odt:create_dir("Pictures") - end) - - -- manifest - exec_group(groups, "4of", function(par) - odt:create_dir("META-INF") - odt:move("${filename}" % par, "META-INF/manifest.xml") - end) - - -- math - exec_group(groups, "4om", function(par) - odt:create_dir(par.basename) - odt:move("${filename}" % par, "${basename}/content.xml" % par) - -- copy the settings file to math subdir - local settings = groups["4os"][1] - odt:copy(settings .. ".4os", "${basename}/settings.xml" % par) - end) - - -- these files are created only once, so it doesn't matter that they are - -- copied to one file - move_file("4os", "settings.xml") - move_file("4ot", "meta.xml") - move_file("4oy", "styles.xml") - - -- pictures - exec_group(groups, "4og", function(par) - -- add support for images in the TEXMF tree - if not mkutils.file_exists(par.basename) then - par.basename = kpse.find_file(par.basename, "graphic/figure") - if not par.basename then return nil, "Cannot find picture" end - end - -- the Pictues dir is flat, without subdirs - odt:copy("${basename}" % par, "Pictures") - end) - - -- remove some spurious file - exec_group(groups, "4od", function(par) - os.remove(par.filename) - end) - - odt:pack() - end) - end - executed = true - end) - return make -end -return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/tei.lua b/Master/texmf-dist/scripts/make4ht/formats/tei.lua deleted file mode 100644 index f81953a8b31..00000000000 --- a/Master/texmf-dist/scripts/make4ht/formats/tei.lua +++ /dev/null @@ -1,14 +0,0 @@ -local M = {} -local xtpipeslib = require "make4ht-xtpipes" - -function M.prepare_parameters(settings, extensions) - settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",tei" - settings = mkutils.extensions_prepare_parameters(extensions, settings) - return settings -end - -function M.prepare_extensions(extensions) - return extensions -end - -return M diff --git a/Master/texmf-dist/scripts/make4ht/formats/xhtml.lua b/Master/texmf-dist/scripts/make4ht/formats/xhtml.lua deleted file mode 100644 index 4a4ac6689ca..00000000000 --- a/Master/texmf-dist/scripts/make4ht/formats/xhtml.lua +++ /dev/null @@ -1,16 +0,0 @@ -local M = {} - -local mkutils = require "mkutils" - -function M.prepare_extensions(extensions) - -- return mkutils.add_extensions("+common_domfilters", extensions) - return extensions -end - -function M.prepare_parameters(parameters,extensions) - parameters = mkutils.extensions_prepare_parameters(extensions,parameters) - return parameters -end - - -return M diff --git a/Master/texmf-dist/scripts/make4ht/make4ht b/Master/texmf-dist/scripts/make4ht/make4ht index b1ff84f7006..fd153164cd7 100755 --- a/Master/texmf-dist/scripts/make4ht/make4ht +++ b/Master/texmf-dist/scripts/make4ht/make4ht @@ -29,7 +29,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.3" +local version = "v0.3b" mkparams.version_number = version local args = mkparams.get_args() diff --git a/Master/texmf-dist/scripts/make4ht/make4ht-odtfilter.lua b/Master/texmf-dist/scripts/make4ht/make4ht-odtfilter.lua new file mode 100755 index 00000000000..97f0b8df670 --- /dev/null +++ b/Master/texmf-dist/scripts/make4ht/make4ht-odtfilter.lua @@ -0,0 +1,33 @@ +local mkutils = require "mkutils" +local zip = require "zip" + + +-- use function to change contents of the ODT file +local function update_odt(odtfilename, file_path, fn) + -- get name of the odt file + local odtname = mkutils.remove_extension(odtfilename) .. ".odt" + -- open and read contents of the requested file inside ODT file + local odtfile = zip.open(odtname) + local local_file = odtfile:open(file_path) + local content = local_file:read("*all") + local_file:close() + odtfile:close() + -- update the content using user function + content = fn(content) + -- write the updated file + local local_file_file = io.open(file_path,"w") + local_file_file:write(content) + local_file_file:close() + os.execute("zip " .. odtname .. " " .. file_path) + os.remove(file_path) +end + +Make:match("tmp$", function(name, par) + update_odt(name, "content.xml", function(content) + return content:gsub("%&%#x([A-Fa-f0-9]+);", function(entity) + -- convert hexadecimal entity to Unicode + print(entity,utfchar(tonumber(entity, 16))) + return utfchar(tonumber(entity, 16)) + end) + end) +end) diff --git a/Master/texmf-dist/scripts/make4ht/mathnode.lua b/Master/texmf-dist/scripts/make4ht/mathnode.lua deleted file mode 100755 index 6d054ad7b85..00000000000 --- a/Master/texmf-dist/scripts/make4ht/mathnode.lua +++ /dev/null @@ -1,87 +0,0 @@ --- local mathnodepath = os.getenv "mathjaxnodepath" --- --- print("mathnode", mathnodepath) -local mkutils = require "mkutils" --- other possible value is page2svg -local mathnodepath = "page2html" --- options for MathJax command -local options = "--format MathML" --- math fonts position --- don't alter fonts if not set -local fontdir = nil --- if we copy fonts -local fontdest = nil -local fontformat = "otf" - -local function compile(src) - local tmpfile = os.tmpname() - local filename = src - print("Compile using MathJax") - local command = mathnodepath .. " ".. options .. " < " .. filename .. " > " .. tmpfile - print(command) - local status = os.execute(command) - print("Result written to: ".. tmpfile) - mkutils.cp(tmpfile, src) - os.remove(tmpfile) -end - -local function extract_css(file) - local f = io.open(file, "r") - local contents = f:read("*all") - f:close() - local css = "" - local filename = "" - contents = contents:gsub('', function(name, style) - css = style - filename = (name or "") .. ".css" - return '' - end) - local x = assert(io.open(file, "w")) - x:write(contents) - x:close() - return filename, css -end - --- -local function use_fonts(css) - local family_pattern = "font%-family:%s*(.-);.-%/([^%/]+)%.".. fontformat - local family_build = "@font-face {font-family: %s; src: url('%s/%s.%s') format('%s')}" - local fontdir = fontdir:gsub("/$","") - css = css:gsub("(@font%-face%s*{.-})", function(face) - -- if not face:match("url%(") then return face end - if not face:match("url%(") then return "" end - -- print(face) - local family, filename = face:match(family_pattern) - print(family, filename) - local newfile = string.format("%s/%s.%s", fontdir, filename, fontformat) - Make:add_file(newfile) - return family_build:format(family, fontdir, filename, fontformat, fontformat) - -- return face - end) - return css -end - - -local function save_css(filename, css) - local f = io.open(filename, "w") - f:write(css) - f:close() -end - -return function(text, arguments) - -- if arguments.prg then mathnodepath = arguments.prg end - mathnodepath = arguments.prg or mathnodepath - options = arguments.options or options - fontdir = arguments.fontdir or fontdir - fontdest = arguments.fontdest or fontdest - fontformat = arguments.fontformat or fontformat - compile(text) - filename, css = extract_css(text) - if fontdir then - css = use_fonts(css) - end - save_css(filename, css) - Make:add_file(filename) - -- print(css) - print(filename) -end diff --git a/Master/texmf-dist/scripts/make4ht/mkutils.lua b/Master/texmf-dist/scripts/make4ht/mkutils.lua index ba1cd6cbb9f..0ea85c7b56b 100755 --- a/Master/texmf-dist/scripts/make4ht/mkutils.lua +++ b/Master/texmf-dist/scripts/make4ht/mkutils.lua @@ -443,7 +443,7 @@ env.Make:add("bibtex", "bibtex ${input}") --- load the output format plugins function load_output_format(format_name) - local format_library = "make4ht.formats."..format_name + local format_library = "make4ht.formats.make4ht-"..format_name local is_format_file = find_lua_file(format_library) if is_format_file then local format = assert(require(format_library)) @@ -486,11 +486,11 @@ end -- @param format current output format function load_extension(name,format) -- first test if the extension exists - local extension_library = "make4ht.extensions." .. name + local extension_library = "make4ht.extensions.make4ht-ext-" .. name local is_extension_file = find_lua_file(extension_library) -- don't try to load the extension if it doesn't exist if not is_extension_file then return nil end - local extension = require("make4ht.extensions.".. name) + local extension = require("make4ht.extensions.make4ht-ext-".. name) -- extensions can test if the current output format is supported local test = extension.test if test then diff --git a/Master/tlpkg/tlpsrc/latex-bin.tlpsrc b/Master/tlpkg/tlpsrc/latex-bin.tlpsrc index ae94e2528bc..2faaf4ddacb 100644 --- a/Master/tlpkg/tlpsrc/latex-bin.tlpsrc +++ b/Master/tlpkg/tlpsrc/latex-bin.tlpsrc @@ -7,7 +7,7 @@ depend latex tlpsetvar fmtcomm babel,cm,hyphen-base,latex,latex-fonts,tex-ini-files tlpsetvar luafmtdeps unicode-data,luaotfload -# + binpattern f bin/${ARCH}/latex execute AddFormat name=latex engine=pdftex \ patterns=language.dat \ -- cgit v1.2.3