summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-07-03 23:24:59 +0000
committerKarl Berry <karl@freefriends.org>2015-07-03 23:24:59 +0000
commitf1073f0dfaaeabd2edda00c472a3d814fad132fa (patch)
treef72e3d8d9e989b6fa399a13600be3d88168eebca /Master
parent0562fc367d1605303c6b2674d0d6b73b37d1d888 (diff)
make4ht (29jul15)
git-svn-id: svn://tug.org/texlive/trunk@37750 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
l---------Master/bin/alpha-linux/make4ht1
l---------Master/bin/amd64-freebsd/make4ht1
l---------Master/bin/amd64-netbsd/make4ht1
l---------Master/bin/armel-linux/make4ht1
l---------Master/bin/armhf-linux/make4ht1
l---------Master/bin/i386-cygwin/make4ht1
l---------Master/bin/i386-freebsd/make4ht1
l---------Master/bin/i386-linux/make4ht1
l---------Master/bin/i386-netbsd/make4ht1
l---------Master/bin/i386-solaris/make4ht1
l---------Master/bin/mipsel-linux/make4ht1
l---------Master/bin/powerpc-linux/make4ht1
l---------Master/bin/sparc-solaris/make4ht1
l---------Master/bin/universal-darwin/make4ht1
-rwxr-xr-xMaster/bin/win32/make4ht.exebin0 -> 1536 bytes
l---------Master/bin/x86_64-cygwin/make4ht1
l---------Master/bin/x86_64-darwin/make4ht1
l---------Master/bin/x86_64-linux/make4ht1
l---------Master/bin/x86_64-solaris/make4ht1
-rw-r--r--Master/texmf-dist/doc/support/make4ht/README.md297
-rw-r--r--Master/texmf-dist/doc/support/make4ht/changelog.tex11
-rw-r--r--Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdfbin0 -> 61644 bytes
-rw-r--r--Master/texmf-dist/doc/support/make4ht/make4ht-doc.tex24
-rw-r--r--Master/texmf-dist/doc/support/make4ht/readme.tex322
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan-nat.lua12
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan.lua33
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-entities.lua14
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-filter.lua41
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-fixligatures.lua16
-rw-r--r--Master/texmf-dist/scripts/make4ht/filters/make4ht-hruletohr.lua11
-rwxr-xr-xMaster/texmf-dist/scripts/make4ht/lapp-mk4.lua317
-rwxr-xr-xMaster/texmf-dist/scripts/make4ht/make4ht62
-rwxr-xr-xMaster/texmf-dist/scripts/make4ht/make4ht-lib.lua204
-rwxr-xr-xMaster/texmf-dist/scripts/make4ht/mkparams.lua135
-rwxr-xr-xMaster/texmf-dist/scripts/make4ht/mkutils.lua290
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check3
-rwxr-xr-xMaster/tlpkg/libexec/ctan2tds2
-rw-r--r--Master/tlpkg/tlpsrc/collection-binextra.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/make4ht.tlpsrc1
39 files changed, 1813 insertions, 1 deletions
diff --git a/Master/bin/alpha-linux/make4ht b/Master/bin/alpha-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/alpha-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/amd64-freebsd/make4ht b/Master/bin/amd64-freebsd/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/amd64-freebsd/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/amd64-netbsd/make4ht b/Master/bin/amd64-netbsd/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/amd64-netbsd/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/armel-linux/make4ht b/Master/bin/armel-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/armel-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/armhf-linux/make4ht b/Master/bin/armhf-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/armhf-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/i386-cygwin/make4ht b/Master/bin/i386-cygwin/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/i386-cygwin/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/i386-freebsd/make4ht b/Master/bin/i386-freebsd/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/i386-freebsd/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/i386-linux/make4ht b/Master/bin/i386-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/i386-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/i386-netbsd/make4ht b/Master/bin/i386-netbsd/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/i386-netbsd/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/i386-solaris/make4ht b/Master/bin/i386-solaris/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/i386-solaris/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/mipsel-linux/make4ht b/Master/bin/mipsel-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/mipsel-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/powerpc-linux/make4ht b/Master/bin/powerpc-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/powerpc-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/sparc-solaris/make4ht b/Master/bin/sparc-solaris/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/sparc-solaris/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/universal-darwin/make4ht b/Master/bin/universal-darwin/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/universal-darwin/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/win32/make4ht.exe b/Master/bin/win32/make4ht.exe
new file mode 100755
index 00000000000..5777d90a17a
--- /dev/null
+++ b/Master/bin/win32/make4ht.exe
Binary files differ
diff --git a/Master/bin/x86_64-cygwin/make4ht b/Master/bin/x86_64-cygwin/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/x86_64-cygwin/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/x86_64-darwin/make4ht b/Master/bin/x86_64-darwin/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/x86_64-darwin/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/x86_64-linux/make4ht b/Master/bin/x86_64-linux/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/x86_64-linux/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/bin/x86_64-solaris/make4ht b/Master/bin/x86_64-solaris/make4ht
new file mode 120000
index 00000000000..ff701ecdc0a
--- /dev/null
+++ b/Master/bin/x86_64-solaris/make4ht
@@ -0,0 +1 @@
+../../texmf-dist/scripts/make4ht/make4ht \ No newline at end of file
diff --git a/Master/texmf-dist/doc/support/make4ht/README.md b/Master/texmf-dist/doc/support/make4ht/README.md
new file mode 100644
index 00000000000..13840cd2e58
--- /dev/null
+++ b/Master/texmf-dist/doc/support/make4ht/README.md
@@ -0,0 +1,297 @@
+# Introduction
+
+`make4ht` is a simple build system for tex4ht. It is both executable which
+simplifies `tex4ht` execution and a library which can be used to create
+customized conversion programs. An example of such conversion program is [tex4ebook](https://github.com/michal-h21/tex4ebook)
+
+## License
+
+Permission is granted to copy, distribute and/or modify this software
+under the terms of the LaTeX Project Public License, version 1.3.
+
+How it works
+------------
+
+Default compilation script for `tex4ht`, named `htlatex` compiles LaTeX files to `HTML` with this command sequence:
+
+ latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+ latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+ latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+ tex4ht options filename
+ t4ht options filename
+
+The problem is that this is inefficient when you need to run program which
+interact with LaTeX, such as `Makeindex` or `Bibtex`. In that case, you need to
+create new script based on the default one, or run `htlatex` twice, which means
+six LaTeX runs.
+
+Another problem is with `t4ht` application. It reads file `filename.lg`,
+generated by `tex4ht`, where are instructions about generated files, `CSS`
+instructions, calls to external applications, instructions for image
+conversions etc. It can be instructed to copy generated files to some output
+directory, but it doesn't preserve directory structure, so when you
+have images in some subdirectory, they will be copied to the output directory,
+but links will be pointing to non existing subdirectory.
+
+Image conversion is directed with the
+[env file](http://www.tug.org/applications/tex4ht/mn35.html#index35-73001),
+with really strange syntax based on whitespace and
+[os dependent](http://www.tug.org/applications/tex4ht/mn-unix.html#index27-69005).
+With `make4ht` build files, we have simple mean to fix these issues. We can
+change image conversion parameters without need to modify the `env file`,
+and call actions on the output files. These actions can be either external
+programs such as `xslt` processors or `HTML tidy` or `Lua` functions.
+
+The idea is to make system controlled by a build file. Because `Lua`
+interpreter is included in modern TeX distributions and `Lua` is ideal language
+for such task, it was chosen as language in which build script are written.
+
+
+# Build files
+
+## Commands
+
+By default, build file is saved in file named `filename + .mk4 extension`.
+You can choose different build file with `-e` or `--build-file` command line
+option.
+
+Sample:
+
+ Make:htlatex()
+ Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
+
+ `Make:htlatex()` is preconfigured command for calling LaTeX with `tex4ht` loaded on the input file. In this case it will be called one time. After compilation, `tidy` command is executed on the output `html` file.
+
+Note that you don't have to call `tex4ht` and `t4ht` commands explicitly in the build file, they are called automatically.
+
+You can add more commands like `Make:htlatex` with
+
+ Make:add("name", "command", {parameters}, repetition)
+
+
+it can be called with
+
+ Make:name()
+
+`command` can be text template, or function:
+
+ Make:add("text", "hello, input file: ${input}")
+ Make:add("function", function(params) for k, v in pairs(params) do print(k..": "..v) end)
+
+`parameters` is a table or `nil` value.
+
+Default parameters are:
+
+htlatex
+
+: used compiler
+
+input
+
+: input file
+
+latex_par
+
+: parameters to `latex`
+
+tex4ht_sty_par
+
+: parameters to `tex4ht.sty`
+
+tex4ht_par
+
+: parameters to `tex4ht` application
+
+t4ht_par
+
+: parameters to `t4ht` application
+
+outdir
+
+: output directory
+
+repetition
+
+: limit number of command execution.
+
+correct_exit
+
+: expected `exit code` from the command.
+
+
+You may add your own parameters, they will be accessible in templates and
+functions.
+
+With `repetition`, you can limit number of command executions. Its value
+should be number or `nil`. This is used in the case of `tex4ht` and `t4ht`
+commands, as they should be executed only once and they would be executed
+multiple times if you include them in the build file, because they would be
+called also by `make4ht`. With `repetition`, second execution is blocked.
+
+You can set expected exit code from a command with `correct_exit`. Compilation
+is stopped when command returns different exit code. Situation is little bit
+difficult with LaTeX (all engines and formats in fact), because it doesn't
+differentiate between fatal and non fatal errors and returns same exit code
+in all cases. Log parsing is used because of that, error code `1` is returned
+in the case of fatal error, `0` is used otherwise.
+
+## File matches
+
+Other type of action which can be specified in the build file are
+matches which may be called on the generated files:
+
+ Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
+
+It tests filenames with `Lua` pattern matching and on matched items will
+execute command or function, specified in the second argument. Parameters are
+the same as in previous section, except `filename`, which contains generated
+output name.
+
+### Filters
+
+Some default match actions which you can use are in the `filter` module. It
+contains some functions which ares useful for fixing some `tex4ht` bugs or
+shortcomings.
+
+Example:
+
+ local filter = require "make4ht-filter"
+ local process = filter{"cleanspan", "fixligatures", "hruletohr"}
+ Make:htlatex()
+ Make:htlatex()
+ Make:match("html$",process)
+
+
+Filter module is located in `make4ht-filter`. Function is returned,
+which is used for building filter chains then.
+
+Built-in filters are:
+
+cleanspan
+
+: clean spurious span elements when accented characters are used
+
+cleanspan-nat
+
+: alternative clean span filter, provided by Nat Kuhn
+
+fixligatures
+
+: decompose ligatures to base characters
+
+hruletohr
+
+: `\hrule` commands are translated to series of underscore characters
+ by `tex4ht`, this filter translate these underscores to `<hr>` elements
+entites
+
+: convert prohibited named entities to numeric entities (currently, only `&nbsp;`, as it causes validation errors, and `tex4ht` is producing it sometimes
+
+
+Function `filter` accepts also function arguments, in this case this function
+takes file contents as parameter and modified contents are returned.
+
+Example:
+
+ local filter = require "make4ht-filter"
+ local changea = function(s) return s:gsub("a","z") end
+ local process = filter{"cleanspan", "fixligatures", changea}
+ Make:htlatex()
+ Make:htlatex()
+ Make:match("html$",process)
+
+In this case, spurious span elements are joined, ligatures are decomposed,
+and then all letters 'a' are replaced with 'z' letters.
+
+## Image conversion
+
+It is possible to convert parts of LaTeX input to pictures, it is used
+for example for math or diagrams in `tex4ht`.
+
+These pictures are stored in special `dvi` file, on which `dvi to image`
+commands are called.
+
+This conversion is normally configured in the `env file`,
+which is system dependent and which has a little bit unintuitive syntax.
+This configuration is processed by `t4ht` application and conversion
+commands are called for all pictures.
+
+It is possible to disable `t4ht` image processing and configure image
+conversion in the make file:
+
+ Make:image("png$",
+ "dvipng -bg Transparent -T tight -o ${output} -pp ${page} ${source}")
+
+
+`Make:image` takes two parameters, pattern to match image name and action.
+Action can be either string template with conversion command,
+or function which takes table with parameters as argument.
+
+There are three parameters:
+
+ - output - output image file name
+ - source - `dvi` file with the pictures
+ - page - page number of the converted image
+
+## `mode` variable
+
+Variable `mode` contains contents of `-mode` command line option.
+It can be used to run some commands conditionally. For example:
+
+ if mode == "draft" then
+ Make:htlatex{}
+ else
+ Make:htlatex{}
+ Make:htlatex{}
+ Make:htlatex{}
+ end
+
+In this example (which is default configuration used by `make4ht`),
+LaTeX is called only once when `make4ht` is called with
+
+ make4ht -m draft filename
+
+
+# Command line options
+
+ make4ht - build system for tex4ht
+ Usage:
+ make4ht [options] filename ["tex4ht.sty op." "tex4ht op."
+ "t4ht op" "latex op"]
+ -b,--backend (default tex4ht) Backend used for xml generation.
+ possible values: tex4ht or lua4ht
+ -c,--config (default xhtml) Custom config file
+ -d,--output-dir (default "") Output directory
+ -e,--build-file (default nil) If build file name is different
+ than `filename`.mk4
+ -l,--lua Use lualatex for document compilation
+ -m,--mode (default default) Switch which can be used in the makefile
+ -n,--no-tex4ht Disable dvi file processing with tex4ht command
+ -s,--shell-escape Enables running external programs from LaTeX
+ -u,--utf8 For output documents in utf8 encoding
+ -x,--xetex Use xelatex for document compilation
+ <filename> (string) Input file name
+
+
+You can still use `make4ht` in same way as `htlatex`
+
+ make4ht filename "customcfg, charset=utf-8" " -cunihtf -utf8" " -dfoo"
+
+Note that this will not use `make4ht` routines for output dir making and
+copying If you want to use them, change the line above to:
+
+ make4ht filename "customcfg, charset=utf-8" " -cunihtf -utf8" -d foo
+
+This call has the same effect as following:
+
+ make4ht -u -c customcfg -d foo filename
+
+Output directory doesn't have to exist, it will be created automatically.
+Specified path can be relative to current directory, or absolute:
+
+ make4ht -d use/current/dir/ filename
+ make4ht -d ../gotoparrentdir filename
+ make4ht -d ~/gotohomedir filename
+ make4ht -d c:\documents\windowspathsareworkingtoo filename
+
+
diff --git a/Master/texmf-dist/doc/support/make4ht/changelog.tex b/Master/texmf-dist/doc/support/make4ht/changelog.tex
new file mode 100644
index 00000000000..8687ad10ec9
--- /dev/null
+++ b/Master/texmf-dist/doc/support/make4ht/changelog.tex
@@ -0,0 +1,11 @@
+\section{Changelog}\label{changelog}
+
+\subsection{2015/06/26}\label{section}
+
+\begin{itemize}
+\itemsep1pt\parskip0pt\parsep0pt
+\item
+ added Makefile
+\item
+ moved INSTALL instructions from README to INSTALL
+\end{itemize}
diff --git a/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf
new file mode 100644
index 00000000000..cca309660e2
--- /dev/null
+++ b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/support/make4ht/make4ht-doc.tex b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.tex
new file mode 100644
index 00000000000..e89626c7a96
--- /dev/null
+++ b/Master/texmf-dist/doc/support/make4ht/make4ht-doc.tex
@@ -0,0 +1,24 @@
+\documentclass{ltxdoc}
+
+
+\usepackage[english]{babel}
+\usepackage{hyperref}
+\ifdefined\HCode
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\else
+\usepackage{fontspec}
+\setmainfont{TeX Gyre Schola}
+\fi
+\usepackage{microtype}
+
+\title{The \texttt{make4ht} build system}
+\author{Michal Hoftich\footnote{\url{michal.h21@gmail.com}}}
+\date{Version 0.1\\29/06/2015}
+\begin{document}
+\maketitle
+\tableofcontents
+\input{readme}
+
+\input{changelog}
+\end{document}
diff --git a/Master/texmf-dist/doc/support/make4ht/readme.tex b/Master/texmf-dist/doc/support/make4ht/readme.tex
new file mode 100644
index 00000000000..fc2f72727f3
--- /dev/null
+++ b/Master/texmf-dist/doc/support/make4ht/readme.tex
@@ -0,0 +1,322 @@
+\section{Introduction}\label{introduction}
+
+\texttt{make4ht} is a simple build system for tex4ht. It is both
+executable which simplifies \texttt{tex4ht} execution and a library
+which can be used to create customized conversion programs. An example
+of such conversion program is
+\href{https://github.com/michal-h21/tex4ebook}{tex4ebook}
+
+\subsection{License}\label{license}
+
+Permission is granted to copy, distribute and/or modify this software
+under the terms of the LaTeX Project Public License, version 1.3.
+
+\subsection{How it works}\label{how-it-works}
+
+Default compilation script for \texttt{tex4ht}, named \texttt{htlatex}
+compiles LaTeX files to \texttt{HTML} with this command sequence:
+
+\begin{verbatim}
+latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+latex $latex_options 'code for loading tex4ht.sty \input{filename}'
+tex4ht options filename
+t4ht options filename
+\end{verbatim}
+
+The problem is that this is inefficient when you need to run program
+which interact with LaTeX, such as \texttt{Makeindex} or
+\texttt{Bibtex}. In that case, you need to create new script based on
+the default one, or run \texttt{htlatex} twice, which means six LaTeX
+runs.
+
+Another problem is with \texttt{t4ht} application. It reads file
+\texttt{filename.lg}, generated by \texttt{tex4ht}, where are
+instructions about generated files, \texttt{CSS} instructions, calls to
+external applications, instructions for image conversions etc. It can be
+instructed to copy generated files to some output directory, but it
+doesn't preserve directory structure, so when you have images in some
+subdirectory, they will be copied to the output directory, but links
+will be pointing to non existing subdirectory.
+
+Image conversion is directed with the
+\href{http://www.tug.org/applications/tex4ht/mn35.html\#index35-73001}{env
+file}, with really strange syntax based on whitespace and
+\href{http://www.tug.org/applications/tex4ht/mn-unix.html\#index27-69005}{os
+dependent}. With \texttt{make4ht} build files, we have simple mean to
+fix these issues. We can change image conversion parameters without need
+to modify the \texttt{env file}, and call actions on the output files.
+These actions can be either external programs such as \texttt{xslt}
+processors or \texttt{HTML tidy} or \texttt{Lua} functions.
+
+The idea is to make system controlled by a build file. Because
+\texttt{Lua} interpreter is included in modern TeX distributions and
+\texttt{Lua} is ideal language for such task, it was chosen as language
+in which build script are written.
+
+\section{Build files}\label{build-files}
+
+\subsection{Commands}\label{commands}
+
+By default, build file is saved in file named
+\texttt{filename + .mk4 extension}. You can choose different build file
+with \texttt{-e} or \texttt{-{}-build-file} command line option.
+
+Sample:
+
+\begin{verbatim}
+Make:htlatex()
+Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
+\end{verbatim}
+
+\texttt{Make:htlatex()} is preconfigured command for calling LaTeX with
+\texttt{tex4ht} loaded on the input file. In this case it will be called
+one time. After compilation, \texttt{tidy} command is executed on the
+output \texttt{html} file.
+
+Note that you don't have to call \texttt{tex4ht} and \texttt{t4ht}
+commands explicitly in the build file, they are called automatically.
+
+You can add more commands like \texttt{Make:htlatex} with
+
+\begin{verbatim}
+Make:add("name", "command", {parameters}, repetition)
+\end{verbatim}
+
+it can be called with
+
+\begin{verbatim}
+Make:name()
+\end{verbatim}
+
+\texttt{command} can be text template, or function:
+
+\begin{verbatim}
+Make:add("text", "hello, input file: ${input}")
+Make:add("function", function(params) for k, v in pairs(params) do print(k..": "..v) end)
+\end{verbatim}
+
+\texttt{parameters} is a table or \texttt{nil} value.
+
+Default parameters are:
+
+\begin{description}
+\item[htlatex]
+used compiler
+\item[input]
+input file
+\item[latex\_par]
+parameters to \texttt{latex}
+\item[tex4ht\_sty\_par]
+parameters to \texttt{tex4ht.sty}
+\item[tex4ht\_par]
+parameters to \texttt{tex4ht} application
+\item[t4ht\_par]
+parameters to \texttt{t4ht} application
+\item[outdir]
+output directory
+\item[repetition]
+limit number of command execution.
+\item[correct\_exit]
+expected \texttt{exit code} from the command.
+\end{description}
+
+You may add your own parameters, they will be accessible in templates
+and functions.
+
+With \texttt{repetition}, you can limit number of command executions.
+Its value should be number or \texttt{nil}. This is used in the case of
+\texttt{tex4ht} and \texttt{t4ht} commands, as they should be executed
+only once and they would be executed multiple times if you include them
+in the build file, because they would be called also by
+\texttt{make4ht}. With \texttt{repetition}, second execution is blocked.
+
+You can set expected exit code from a command with
+\texttt{correct\_exit}. Compilation is stopped when command returns
+different exit code. Situation is little bit difficult with LaTeX (all
+engines and formats in fact), because it doesn't differentiate between
+fatal and non fatal errors and returns same exit code in all cases. Log
+parsing is used because of that, error code \texttt{1} is returned in
+the case of fatal error, \texttt{0} is used otherwise.
+
+\subsection{File matches}\label{file-matches}
+
+Other type of action which can be specified in the build file are
+matches which may be called on the generated files:
+
+\begin{verbatim}
+Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
+\end{verbatim}
+
+It tests filenames with \texttt{Lua} pattern matching and on matched
+items will execute command or function, specified in the second
+argument. Parameters are the same as in previous section, except
+\texttt{filename}, which contains generated output name.
+
+\subsubsection{Filters}\label{filters}
+
+Some default match actions which you can use are in the \texttt{filter}
+module. It contains some functions which ares useful for fixing some
+\texttt{tex4ht} bugs or shortcomings.
+
+Example:
+
+\begin{verbatim}
+local filter = require "make4ht-filter"
+local process = filter{"cleanspan", "fixligatures", "hruletohr"}
+Make:htlatex()
+Make:htlatex()
+Make:match("html$",process)
+\end{verbatim}
+
+Filter module is located in \texttt{make4ht-filter}. Function is
+returned, which is used for building filter chains then.
+
+Built-in filters are:
+
+\begin{description}
+\item[cleanspan]
+clean spurious span elements when accented characters are used
+\item[cleanspan-nat]
+alternative clean span filter, provided by Nat Kuhn
+\item[fixligatures]
+decompose ligatures to base characters
+\item[hruletohr]
+\texttt{\textbackslash{}hrule} commands are translated to series of
+underscore characters by \texttt{tex4ht}, this filter translate these
+underscores to \texttt{\textless{}hr\textgreater{}} elements
+\item[entites]
+convert prohibited named entities to numeric entities (currently, only
+\texttt{\&nbsp;}, as it causes validation errors, and \texttt{tex4ht} is
+producing it sometimes
+\end{description}
+
+Function \texttt{filter} accepts also function arguments, in this case
+this function takes file contents as parameter and modified contents are
+returned.
+
+Example:
+
+\begin{verbatim}
+local filter = require "make4ht-filter"
+local changea = function(s) return s:gsub("a","z") end
+local process = filter{"cleanspan", "fixligatures", changea}
+Make:htlatex()
+Make:htlatex()
+Make:match("html$",process)
+\end{verbatim}
+
+In this case, spurious span elements are joined, ligatures are
+decomposed, and then all letters `a' are replaced with `z' letters.
+
+\subsection{Image conversion}\label{image-conversion}
+
+It is possible to convert parts of LaTeX input to pictures, it is used
+for example for math or diagrams in \texttt{tex4ht}.
+
+These pictures are stored in special \texttt{dvi} file, on which
+\texttt{dvi to image} commands are called.
+
+This conversion is normally configured in the \texttt{env file}, which
+is system dependent and which has a little bit unintuitive syntax. This
+configuration is processed by \texttt{t4ht} application and conversion
+commands are called for all pictures.
+
+It is possible to disable \texttt{t4ht} image processing and configure
+image conversion in the make file:
+
+\begin{verbatim}
+Make:image("png$",
+"dvipng -bg Transparent -T tight -o ${output} -pp ${page} ${source}")
+\end{verbatim}
+
+\texttt{Make:image} takes two parameters, pattern to match image name
+and action. Action can be either string template with conversion
+command, or function which takes table with parameters as argument.
+
+There are three parameters:
+
+\begin{itemize}
+\itemsep1pt\parskip0pt\parsep0pt
+\item
+ output - output image file name
+\item
+ source - \texttt{dvi} file with the pictures
+\item
+ page - page number of the converted image
+\end{itemize}
+
+\subsection{\texttt{mode} variable}\label{mode-variable}
+
+Variable \texttt{mode} contains contents of \texttt{-mode} command line
+option. It can be used to run some commands conditionally. For example:
+
+\begin{verbatim}
+ if mode == "draft" then
+ Make:htlatex{}
+ else
+ Make:htlatex{}
+ Make:htlatex{}
+ Make:htlatex{}
+ end
+\end{verbatim}
+
+In this example (which is default configuration used by
+\texttt{make4ht}), LaTeX is called only once when \texttt{make4ht} is
+called with
+
+\begin{verbatim}
+make4ht -m draft filename
+\end{verbatim}
+
+\section{Command line options}\label{command-line-options}
+
+\begin{verbatim}
+make4ht - build system for tex4ht
+Usage:
+make4ht [options] filename ["tex4ht.sty op." "tex4ht op."
+ "t4ht op" "latex op"]
+-b,--backend (default tex4ht) Backend used for xml generation.
+ possible values: tex4ht or lua4ht
+-c,--config (default xhtml) Custom config file
+-d,--output-dir (default "") Output directory
+-e,--build-file (default nil) If build file name is different
+ than `filename`.mk4
+-l,--lua Use lualatex for document compilation
+-m,--mode (default default) Switch which can be used in the makefile
+-n,--no-tex4ht Disable dvi file processing with tex4ht command
+-s,--shell-escape Enables running external programs from LaTeX
+-u,--utf8 For output documents in utf8 encoding
+-x,--xetex Use xelatex for document compilation
+<filename> (string) Input file name
+\end{verbatim}
+
+You can still use \texttt{make4ht} in same way as \texttt{htlatex}
+
+\begin{verbatim}
+make4ht filename "customcfg, charset=utf-8" " -cunihtf -utf8" " -dfoo"
+\end{verbatim}
+
+Note that this will not use \texttt{make4ht} routines for output dir
+making and copying If you want to use them, change the line above to:
+
+\begin{verbatim}
+make4ht filename "customcfg, charset=utf-8" " -cunihtf -utf8" -d foo
+\end{verbatim}
+
+This call has the same effect as following:
+
+\begin{verbatim}
+make4ht -u -c customcfg -d foo filename
+\end{verbatim}
+
+Output directory doesn't have to exist, it will be created
+automatically. Specified path can be relative to current directory, or
+absolute:
+
+\begin{verbatim}
+make4ht -d use/current/dir/ filename
+make4ht -d ../gotoparrentdir filename
+make4ht -d ~/gotohomedir filename
+make4ht -d c:\documents\windowspathsareworkingtoo filename
+\end{verbatim}
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan-nat.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan-nat.lua
new file mode 100644
index 00000000000..896132160c1
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan-nat.lua
@@ -0,0 +1,12 @@
+-- cleanspan function submitted by Nat Kuhn
+-- http://www.natkuhn.com/
+
+local function filter(s)
+ local pattern = "(<span%s+([^>]+)>[^<]*)</span>(%s*)<span%s+%2>"
+ repeat
+ s, n = s:gsub(pattern, "%1%3")
+ until n == 0
+ return s
+end
+
+return filter
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan.lua
new file mode 100644
index 00000000000..ede5c6c74e6
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-cleanspan.lua
@@ -0,0 +1,33 @@
+-- make4ht-cleanspan4ht.lua
+-- fixes spurious <span> elements in tex4ht output
+
+
+function filter(input)
+ local parse_args = function(s)
+ local at = {}
+ s:gsub("(%w+)%s*=%s*\"([^\"]-)\"", function(k,w)
+ at[k]=w
+ end)
+ return at
+ end
+ -- local pattern = "(<?/?[%w]*>?)<span[%s]*class=\"([^\"]+)\"[%s]*>"
+ local pattern = "(<?/?[%w]*>?)([%s]*)<span[%s]*([^>]-)>"
+ local last_class = ""
+ local depth = 0
+ return input:gsub(pattern, function(tag,space, args)
+ local attr = parse_args(args) or {}
+ local class = attr["class"] or ""
+ if tag == "</span>" then
+ if class == last_class and class~= "" then
+ last_class = class
+ return space .. ""
+ end
+ elseif tag == "" then
+ class=""
+ end
+ last_class = class
+ return tag ..space .. '<span '..args ..'>'
+ end)
+end
+
+return filter
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-entities.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-entities.lua
new file mode 100644
index 00000000000..f9f6c883d1f
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-entities.lua
@@ -0,0 +1,14 @@
+-- Fix bad entities
+-- Sometimes, tex4ht produce named xml entities, which are prohobited in epub
+-- &nbsp;, for example
+function filter(s)
+ local replaces = {
+ nbsp = "#160"
+ }
+ return s:gsub("&(%w+);",function(x)
+ local m = replaces[x] or x
+ return "&"..m..";"
+ end)
+end
+
+return filter
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-filter.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-filter.lua
new file mode 100644
index 00000000000..4c7ce409a07
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-filter.lua
@@ -0,0 +1,41 @@
+local filters = {}
+
+local function load_filter(filtername)
+ return require("filters.make4ht-"..filtername)
+end
+
+function filter(filters)
+ local sequence = {}
+ if type(filters) == "string" then
+ table.insert(sequence,load_filter(filters))
+ elseif type(filters) == "table" then
+ for _,n in pairs(filters) do
+ if type(n) == "string" then
+ table.insert(sequence,load_filter(n))
+ elseif type(n) == "function" then
+ table.insert(sequence, n)
+ end
+ end
+ elseif type(filters) == "function" then
+ table.insert(sequence, filters)
+ else
+ return false, "Argument to filter must be either\ntable with filter names, or single filter name"
+ end
+ return function(filename)
+ if not filename then return false, "filters: no filename" end
+ local input = nil
+
+ if filename then
+ local file = io.open(filename,"r")
+ input = file:read("*all")
+ file:close()
+ end
+ for _,f in pairs(sequence) do
+ input = f(input)
+ end
+ local file = io.open(filename,"w")
+ file:write(input)
+ file:close()
+ end
+end
+return filter
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-fixligatures.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-fixligatures.lua
new file mode 100644
index 00000000000..01b31ed3067
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-fixligatures.lua
@@ -0,0 +1,16 @@
+-- fix ligatures
+-- replace ligatures produced by tex4ht with their components
+-- this prevents problems with some readers
+local gsub = unicode.utf8.gsub
+function filter(s)
+ local replaces = {
+ ["fi"] = "fi",
+ ["ffi"] = "ffi",
+ ["fl"] = "fl",
+ ["ffl"] = "ffl",
+ ["ff"] = "ff"
+ }
+ return gsub(s, "([fiffiflfflff])",function (x) return replaces[x] or x end)
+end
+
+return filter
diff --git a/Master/texmf-dist/scripts/make4ht/filters/make4ht-hruletohr.lua b/Master/texmf-dist/scripts/make4ht/filters/make4ht-hruletohr.lua
new file mode 100644
index 00000000000..a9c0c5e9df2
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/filters/make4ht-hruletohr.lua
@@ -0,0 +1,11 @@
+-- hruletohr
+-- \hrule primitive is impossible to redefine catching all possible arguments
+-- with tex4ht, it is converted as series of underscores
+-- it seems that these underscores are always part of previous paragraph
+-- this assumption may be wrong, needs more real world testing
+
+local hruletohr = function(s)
+ return s:gsub("___+(.-)</p>","%1</p>\n<hr class=\"hrule\" />")
+end
+
+return hruletohr
diff --git a/Master/texmf-dist/scripts/make4ht/lapp-mk4.lua b/Master/texmf-dist/scripts/make4ht/lapp-mk4.lua
new file mode 100755
index 00000000000..71ed3704077
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/lapp-mk4.lua
@@ -0,0 +1,317 @@
+-- lapp.lua
+-- Simple command-line parsing using human-readable specification
+-----------------------------
+--~ -- args.lua
+--~ local args = require ('lapp') [[
+--~ Testing parameter handling
+--~ -p Plain flag (defaults to false)
+--~ -q,--quiet Plain flag with GNU-style optional long name
+--~ -o (string) Required string option
+--~ -n (number) Required number option
+--~ -s (default 1.0) Option that takes a number, but will default
+--~ <start> (number) Required number argument
+--~ <input> (default stdin) A parameter which is an input file
+--~ <output> (default stdout) One that is an output file
+--~ ]]
+--~ for k,v in pairs(args) do
+--~ print(k,v)
+--~ end
+-------------------------------
+--~ > args -pq -o help -n 2 2.3
+--~ input file (781C1B78)
+--~ p true
+--~ s 1
+--~ output file (781C1B98)
+--~ quiet true
+--~ start 2.3
+--~ o help
+--~ n 2
+--------------------------------
+
+lapp = {}
+
+local append = table.insert
+local usage
+local open_files = {}
+local parms = {}
+local aliases = {}
+local parmlist = {}
+
+local filetypes = {
+ stdin = {io.stdin,'file-in'}, stdout = {io.stdout,'file-out'},
+ stderr = {io.stderr,'file-out'}
+}
+
+local function quit(msg,no_usage)
+ if msg then
+ io.stderr:write(msg..'\n\n')
+ end
+ if not no_usage then
+ io.stderr:write(usage)
+ end
+ os.exit(1);
+end
+
+local function error(msg,no_usage)
+ quit(arg[0]:gsub('.+[\\/]','')..':'..msg,no_usage)
+end
+
+local function ltrim(line)
+ return line:gsub('^%s*','')
+end
+
+local function rtrim(line)
+ return line:gsub('%s*$','')
+end
+
+local function trim(s)
+ return ltrim(rtrim(s))
+end
+
+local function open (file,opt)
+ local val,err = io.open(file,opt)
+ if not val then error(err,true) end
+ append(open_files,val)
+ return val
+end
+
+local function xassert(condn,msg)
+ if not condn then
+ error(msg)
+ end
+end
+
+local function range_check(x,min,max,parm)
+ xassert(min <= x and max >= x,parm..' out of range')
+end
+
+local function xtonumber(s)
+ local val = tonumber(s)
+ if not val then error("unable to convert to number: "..s) end
+ return val
+end
+
+local function is_filetype(type)
+ return type == 'file-in' or type == 'file-out'
+end
+
+local types = {}
+
+local function convert_parameter(ps,val)
+ if ps.converter then
+ val = ps.converter(val)
+ end
+ if ps.type == 'number' then
+ val = xtonumber(val)
+ elseif is_filetype(ps.type) then
+ val = open(val,(ps.type == 'file-in' and 'r') or 'w' )
+ elseif ps.type == 'boolean' then
+ val = true
+ end
+ if ps.constraint then
+ ps.constraint(val)
+ end
+ return val
+end
+
+function lapp.add_type (name,converter,constraint)
+ types[name] = {converter=converter,constraint=constraint}
+end
+
+local function force_short(short)
+ xassert(#short==1,short..": short parameters should be one character")
+end
+
+function process_options_string(str)
+ local res = {}
+ local varargs
+
+ local function check_varargs(s)
+ local res,cnt = s:gsub('%.%.%.$','')
+ varargs = cnt > 0
+ return res
+ end
+
+ local function set_result(ps,parm,val)
+ if not ps.varargs then
+ res[parm] = val
+ else
+ if not res[parm] then
+ res[parm] = { val }
+ else
+ append(res[parm],val)
+ end
+ end
+ end
+
+ usage = str
+
+ for line in str:gmatch('([^\n]*)\n') do
+ local optspec,optparm,i1,i2,defval,vtype,constraint
+ line = ltrim(line)
+ -- flags: either -<short> or -<short>,<long>
+ i1,i2,optspec = line:find('^%-(%S+)')
+ if i1 then
+ optspec = check_varargs(optspec)
+ local short,long = optspec:match('([^,]+),(.+)')
+ if short then
+ optparm = long:sub(3)
+ aliases[short] = optparm
+ force_short(short)
+ else
+ optparm = optspec
+ force_short(optparm)
+ end
+ else -- is it <parameter_name>?
+ i1,i2,optparm = line:find('(%b<>)')
+ if i1 then
+ -- so <input file...> becomes input_file ...
+ optparm = check_varargs(optparm:sub(2,-2)):gsub('%A','_')
+ append(parmlist,optparm)
+ end
+ end
+ if i1 then -- this is not a pure doc line
+ local last_i2 = i2
+ local sval
+ line = ltrim(line:sub(i2+1))
+ -- do we have (default <val>) or (<type>)?
+ i1,i2,typespec = line:find('^%s*(%b())')
+ if i1 then
+ typespec = trim(typespec:sub(2,-2)) -- trim the parens and any space
+ sval = typespec:match('default%s+(.+)')
+ if sval then
+ local val = tonumber(sval)
+ if val then -- we have a number!
+ defval = val
+ vtype = 'number'
+ elseif filetypes[sval] then
+ local ft = filetypes[sval]
+ defval = ft[1]
+ vtype = ft[2]
+ else
+ defval = sval
+ vtype = 'string'
+ end
+ else
+ local min,max = typespec:match '([^%.]+)%.%.(.+)'
+ if min then -- it's (min..max)
+ vtype = 'number'
+ min = xtonumber(min)
+ max = xtonumber(max)
+ constraint = function(x)
+ range_check(x,min,max,optparm)
+ end
+ else -- () just contains type of required parameter
+ vtype = typespec
+ end
+ end
+ else -- must be a plain flag, no extra parameter required
+ defval = false
+ vtype = 'boolean'
+ end
+ local ps = {
+ type = vtype,
+ defval = defval,
+ required = defval == nil,
+ comment = line:sub((i2 or last_i2)+1) or optparm,
+ constraint = constraint,
+ varargs = varargs
+ }
+ if types[vtype] then
+ local converter = types[vtype].converter
+ if type(converter) == 'string' then
+ ps.type = converter
+ else
+ ps.converter = converter
+ end
+ ps.constraint = types[vtype].constraint
+ end
+ parms[optparm] = ps
+ end
+ end
+ -- cool, we have our parms, let's parse the command line args
+ local iparm = 1
+ local iextra = 1
+ local i = 1
+ local parm,ps,val
+ while i <= #arg do
+ -- look for a flag, -<short flags> or --<long flag>
+ local i1,i2,dash,parmstr = arg[i]:find('^(%-+)(%a.*)')
+ if i1 then -- we have a flag
+ if #dash == 2 then -- long option
+ parm = parmstr
+ else -- short option
+ if #parmstr == 1 then
+ parm = parmstr
+ else -- multiple flags after a '-',?
+ parm = parmstr:sub(1,1)
+ if parmstr:find('^%a%d+') then
+ -- a short option followed by a digit? (exception for AW ;))
+ -- push ahead into the arg array
+ table.insert(arg,i+1,parmstr:sub(2))
+ else
+ -- push multiple flags into the arg array!
+ for k = 2,#parmstr do
+ table.insert(arg,i+k-1,'-'..parmstr:sub(k,k))
+ end
+ end
+ end
+ end
+ if parm == 'h' or parm == 'help' then
+ quit()
+ end
+ if aliases[parm] then parm = aliases[parm] end
+ ps = parms[parm]
+ if not ps then error("unrecognized parameter: "..parm) end
+ if ps.type ~= 'boolean' then -- we need a value! This should follow
+ val = arg[i+1]
+ i = i + 1
+ xassert(val,parm.." was expecting a value")
+ end
+ else -- a parameter
+ parm = parmlist[iparm]
+ if not parm then
+ -- extra unnamed parameters are indexed starting at 1
+ parm = iextra
+ iextra = iextra + 1
+ ps = { type = 'string' }
+ else
+ ps = parms[parm]
+ end
+ if not ps.varargs then
+ iparm = iparm + 1
+ end
+ val = arg[i]
+ end
+ ps.used = true
+ val = convert_parameter(ps,val)
+ set_result(ps,parm,val)
+ if is_filetype(ps.type) then
+ set_result(ps,parm..'_name',arg[i])
+ end
+ if lapp.callback then
+ lapp.callback(parm,arg[i],res)
+ end
+ i = i + 1
+ end
+ -- check unused parms, set defaults and check if any required parameters were missed
+ for parm,ps in pairs(parms) do
+ if not ps.used then
+ if ps.required then error("missing required parameter: "..parm) end
+ set_result(ps,parm,ps.defval)
+ end
+ end
+ return res
+end
+
+setmetatable(lapp, {
+ __call = function(tbl,str) return process_options_string(str) end,
+ __index = {
+ open = open,
+ quit = quit,
+ error = error,
+ assert = xassert,
+ }
+})
+
+return lapp
diff --git a/Master/texmf-dist/scripts/make4ht/make4ht b/Master/texmf-dist/scripts/make4ht/make4ht
new file mode 100755
index 00000000000..22b2e7cf2fb
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/make4ht
@@ -0,0 +1,62 @@
+#!/usr/bin/env texlua
+kpse.set_program_name("luatex")
+
+
+local make4ht = require("make4ht-lib")
+local lapp = require("lapp-mk4")
+local mkutils = require("mkutils")
+local mkparams = require("mkparams")
+-- args string is here just as sample, we dont pass it it to
+-- mkparams.get_args() so default args string is used
+local args = [[
+make4ht - build system for tex4ht
+Usage:
+make4ht [options] filename ["tex4ht.sty op." "tex4ht op." "t4ht op" "latex op"]
+-c,--config (default xhtml) Custom config file
+-d,--output-dir (default nil) Output directory
+-l,--lua Use lualatex for document compilation
+-s,--shell-escape Enables running external programs from LaTeX
+-u,--utf8 For output documents in utf8 encoding
+-x,--xetex Use xelatex for document compilation
+<filename> (string) Input file name
+]]
+
+local args = mkparams.get_args()
+
+local parameters = mkparams.process_args(args)
+
+local mode = parameters.mode
+local build_file = parameters.build_file
+
+local make = mkutils.load_config(parameters, build_file)["Make"]
+make.params = parameters
+if make:length() < 1 then
+ if mode == "draft" then
+ make:htlatex()
+ else
+ make:htlatex()
+ make:htlatex()
+ make:htlatex()
+ end
+end
+
+
+if not args["no-tex4ht"] then
+ make:tex4ht()
+end
+
+local ext = args.xetex and "xdv" or "dvi"
+if #make.image_patterns > 0 then
+ make.params.t4ht_par = make.params.t4ht_par .. " -p"
+end
+make:t4ht {ext = ext}
+make:match("tmp$", function() return false,"tmp file" end)
+make:match(".*",function(filename,par)
+ local outdir = '' --par["outdir"] and par["outdir"] .."/" or ''
+ if par['outdir'] ~= "" then outdir = par['outdir'] .. '/' end
+ print("outdir: "..outdir)
+ local outfilename = outdir .. filename
+ mkutils.copy(filename,outfilename)
+ return true
+end)
+make:run()
diff --git a/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua b/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua
new file mode 100755
index 00000000000..3b550b9995c
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/make4ht-lib.lua
@@ -0,0 +1,204 @@
+-- Simple make system for tex4ht
+--kpse.set_program_name("luatex")
+-- module(...,package.seeall)
+local m = {}
+
+Make = {}
+--Make.params = {}
+Make.build_seq = {}
+-- Patterns for matching output filenames
+Make.matches = {}
+Make.image_patterns = {}
+Make.run_count = {}
+
+Make.add = function(self,name,fn,par,rep)
+ local par = par or {}
+ self.params = self.params or {}
+ Make[name] = function(self,p,typ)
+ local params = {}
+ for k,v in pairs(self.params) do params[k] = v end
+ for k,v in pairs(par) do params[k] = v; print("setting param "..k) end
+ local typ = typ or "make"
+ local p = p or {}
+ local fn = fn
+ for k,v in pairs(p) do
+ params[k]=v
+ print("Adding: ",k,v)
+ end
+ -- print( fn % params)
+ local command = {
+ name=name,
+ type=typ,
+ command = fn,
+ params = params,
+ repetition = rep
+ }
+ table.insert(self.build_seq,command)
+ end
+end
+
+Make.length = function(self)
+ return #self.build_seq
+end
+
+Make.match = function(self, pattern, command, params)
+ local params = params or {}
+ table.insert(self.matches,{pattern = pattern, command = command, params = params})
+end
+
+Make.run_command = function(self,filename,s)
+ local command = s.command
+ local params = s.params
+ params["filename"] = filename
+ print("parse_lg process file: "..filename)
+ --for k,v in pairs(params) do print(k..": "..v) end
+ if type(command) == "function" then
+ return command(filename,params)
+ elseif type(command) == "string" then
+ local run = command % params
+ print("Execute: " .. run)
+ return os.execute(run)
+ end
+ return false, "parse_lg: Command is not string or function"
+end
+
+Make.image = function(self, pattern, command, params)
+ local tab = {
+ pattern = pattern,
+ command = command,
+ params = params
+ }
+ table.insert(self.image_patterns, tab)
+end
+
+Make.image_convert = function(self, images)
+ local image_patterns = self.image_patterns or {}
+ for i, r in pairs(image_patterns) do
+ local p = self.params or {}
+ local v = r.params or {}
+ for k,v in pairs(v) do
+ p[k]= v
+ end
+ image_patterns[i].params = p
+ end
+ for _,i in pairs(images) do
+ local output = i.output
+ for _, x in pairs(image_patterns) do
+ local pattern = x.pattern
+ if output:match(pattern) then
+ local command = x.command
+ local p = x.params or {}
+ p.output = output
+ p.page= i.page
+ p.source = i.source
+ if type(command) == "function" then
+ command(p)
+ elseif type(command) == "string" then
+ local c = command % p
+ print("Make4ht convert: "..c)
+ os.execute(c)
+ end
+ break
+ end
+ end
+ end
+end
+
+Make.file_matches = function(self, files)
+ local statuses = {}
+ -- First make params for all matchers
+ for k,v in pairs(self.matches) do
+ local v = self.matches[k].params or {}
+ local p = self.params or {}
+ for i,j in pairs(p) do
+ v[i] = j
+ end
+ self.matches[k].params = v
+ end
+ -- Loop over files, run command on matched
+ for _, file in pairs(files)do
+ statuses[file] = {}
+ for _, s in pairs(self.matches) do
+ local pattern= s.pattern
+ if file:match(pattern) then
+ local status, msg = self:run_command(file,s)
+ msg = msg or "No message given"
+ table.insert(statuses[file],status)
+ if status == false then
+ print(msg)
+ break
+ end
+ end
+ end
+ end
+ return statuses
+end
+
+Make.run = function(self)
+ local return_codes = {}
+ local params = self.params or {}
+ for _,v in ipairs(self.build_seq) do
+ --print("sekvence: "..v.name)
+ for p,n in pairs(v.params) do params[p] = n end
+ --for c,_ in pairs(params) do print("build param: "..c) end
+ if type(v.command)=="function" then
+ table.insert(return_codes,{name=v.name,status = v.command(params)})
+ elseif type(v.command) =="string" then
+ local command = v.command % params
+ -- Some commands should be executed only limited times, typicaly once
+ -- tex4ht or t4ht for example
+ local run_count = self.run_count[v.command] or 0
+ run_count = run_count + 1
+ self.run_count[v.command] = run_count
+ local repetition = v.repetition
+ if repetition and run_count > repetition then
+ print ("Make4ht: ".. command .." can be executed only "..repetition .."x")
+ else
+ print("Make4ht: " .. command)
+ local status = os.execute(command)
+ table.insert(return_codes,{name=v.name,status=status})
+ end
+ else
+ print("Unknown command type, must be string or function - " ..v.name..": "..type(v.command))
+ end
+ local correct_exit = params.correct_exit or nil
+ if correct_exit then
+ local last_return = return_codes[#return_codes] or {}
+ local current_status = last_return.status or 0
+ if current_status ~= correct_exit then
+ local last_name = last_return.name or "unknown"
+ print("Make4ht: Fatal error. Command "..last_name .." returned exit code "..current_status)
+ os.exit(1)
+ end
+ end
+ end
+ local lgfile = params.input and params.input .. ".lg" or nil
+ if lgfile then
+ local lg = mkutils.parse_lg(lgfile)
+ -- First convert images from lg files
+ self:image_convert(lg["images"])
+ -- Then run file matchers on lg files and converted images
+ local files = lg["files"]
+ for _,v in pairs(lg["images"]) do
+ local v = v.output
+ -- print(v)
+ table.insert(files,v)
+ end
+ self:file_matches(files)
+ else
+ print("No lg file. tex4ht run failed?")
+ end
+ return return_codes
+end
+
+m.Make = Make
+
+return m
+
+--[[Make:add("hello", "hello ${world}", {world = "world"})
+Make:add("ajaj", "ajaj")
+Make:hello()
+Make:hello{world="světe"}
+Make:hello()
+Make:run()
+--]]
diff --git a/Master/texmf-dist/scripts/make4ht/mkparams.lua b/Master/texmf-dist/scripts/make4ht/mkparams.lua
new file mode 100755
index 00000000000..5b614192029
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/mkparams.lua
@@ -0,0 +1,135 @@
+local lapp = require "lapp-mk4"
+local mkutils = require "mkutils"
+local m = {} -- use ugly module system for new lua versions support
+
+m.optiontext = [[
+${progname} - build system for tex4ht
+Usage:
+${progname} [options] filename ["tex4ht.sty op." "tex4ht op." "t4ht op" "latex op"]
+-b,--backend (default tex4ht) Backend used for xml generation.
+ possible values: tex4ht or lua4ht
+-c,--config (default xhtml) Custom config file
+-d,--output-dir (default nil) Output directory
+-e,--build-file (default nil) If build file is different than `filename`.mk4
+-l,--lua Use lualatex for document compilation
+-m,--mode (default default) Switch which can be used in the makefile
+-n,--no-tex4ht Disable dvi file processing with tex4ht command
+-s,--shell-escape Enables running external programs from LaTeX
+-u,--utf8 For output documents in utf8 encoding
+-x,--xetex Use xelatex for document compilation
+]]
+local function get_args(parameters, optiontext)
+ local parameters = parameters or {}
+ parameters.progname = parameters.progname or "make4ht"
+ parameters.postparams = parameters.postparams or ""
+ local optiontext = optiontext or m.optiontext
+ parameters.postfile = parameters.postfile or ""
+ optiontext = optiontext .. parameters.postparams .."<filename> (string) Input file name\n" .. parameters.postfile
+ --print("--------------\n" .. optiontext .."--------------\n")
+ return lapp(optiontext % parameters)
+end
+
+
+local function process_args(args)
+ local function get_inserter(args,tb)
+ return function(key, value)
+ --local v = args[key] and value or ""
+ local v = ""
+ if args[key] then v = value end
+ table.insert(tb,v)
+ end
+ end
+
+ local outdir = ""
+ local packages = ""
+
+ if args["output-dir"] ~= "nil" then
+ outdir = args["output-dir"]
+ outdir = outdir:gsub('\\','/')
+ outdir = outdir:gsub('/$','')
+ end
+
+ if args.backend == "lua4ht" then
+ args.lua = true
+ args.xetex = nil
+ args.utf8 = true
+ args["no-tex4ht"] = true
+ packages = packages .."\\RequirePackage{lua4ht}"
+ end
+
+
+ local compiler = args.lua and "dvilualatex" or args.xetex and "xelatex --no-pdf" or "latex"
+ local input = mkutils.remove_extension(args.filename)
+
+ local latex_params = {}
+ local insert_latex = get_inserter(args,latex_params)
+ insert_latex("shell-escape","-shell-escape")
+ table.insert(latex_params,"-jobname="..input)
+ table.insert(latex_params,args[4] or "")
+ --table.insert(latex_params,args["shell-escape"] and "-shell-escape")
+
+
+ local t4sty = args[1] or ""
+ -- test if first option is custom config file
+ local cfg_tmp = t4sty:match("([^,^ ]+)")
+ if cfg_tmp and cfg_tmp ~= args.config then
+ local fn = cfg_tmp..".cfg"
+ local f = io.open(fn,"r")
+ if f then
+ args.config = cfg_tmp
+ f:close()
+ end
+ end
+ --[[if args[1] and args[1] ~= "" then
+ t4sty = args[1]
+ else
+ --]]
+ -- Different behaviour from htlatex
+ local utf = args.utf8 and ",charset=utf-8" or ""
+ t4sty = args.config .. "," .. t4sty .. utf
+ --end
+
+ local tex4ht = ""
+ if args[2] and args[2] ~="" then
+ tex4ht = args[2]
+ else
+ tex4ht = args.utf8 and " -cunihtf -utf8" or ""
+ local xdv = args.xetex and " -.xdv" or ""
+ tex4ht = tex4ht .. xdv
+ end
+
+ local t4ht = args[3] or ""
+
+ local mode = args.mode or "default"
+
+ local build_file = input.. ".mk4"
+
+ if args["build-file"] and args["build-file"] ~= "nil" then
+ build_file = args["build-file"]
+ end
+
+ local parameters = {
+ htlatex = compiler
+ ,input=input
+ ,packages=packages
+ ,latex_par=table.concat(latex_params," ")
+ --,config=ebookutils.remove_extension(args.config)
+ ,tex4ht_sty_par=t4sty
+ ,tex4ht_par=tex4ht
+ ,t4ht_par=t4ht
+ ,mode = mode
+ ,build_file = build_file
+ --,t4ht_dir_format=t4ht_dir_format
+ }
+ if outdir then parameters.outdir = outdir end
+ print("Output dir: ",outdir)
+ print("Compiler: ", compiler)
+ print("Latex options: ", table.concat(latex_params," "))
+ print("tex4ht.sty :",t4sty)
+ print("tex4ht",tex4ht)
+ print("build_file", build_file)
+ return parameters
+end
+m.get_args = get_args
+m.process_args = process_args
+return m
diff --git a/Master/texmf-dist/scripts/make4ht/mkutils.lua b/Master/texmf-dist/scripts/make4ht/mkutils.lua
new file mode 100755
index 00000000000..ca9e2ff208a
--- /dev/null
+++ b/Master/texmf-dist/scripts/make4ht/mkutils.lua
@@ -0,0 +1,290 @@
+module(...,package.seeall)
+
+local make4ht = require("make4ht-lib")
+--template engine
+function interp(s, tab)
+ local tab = tab or {}
+ return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
+end
+--print( interp("${name} is ${value}", {name = "foo", value = "bar"}) )
+
+function addProperty(s,prop)
+ if prop ~=nil then
+ return s .." "..prop
+ else
+ return s
+ end
+end
+getmetatable("").__mod = interp
+getmetatable("").__add = addProperty
+
+--print( "${name} is ${value}" % {name = "foo", value = "bar"} )
+-- Outputs "foo is bar"
+
+function string:split(sep)
+ local sep, fields = sep or ":", {}
+ local pattern = string.format("([^%s]+)", sep)
+ self:gsub(pattern, function(c) fields[#fields+1] = c end)
+ return fields
+end
+
+function remove_extension(path)
+ local found, len, remainder = string.find(path, "^(.*)%.[^%.]*$")
+ if found then
+ return remainder
+ else
+ return path
+ end
+end
+
+--
+
+function file_exists(file)
+ local f = io.open(file, "rb")
+ if f then f:close() end
+ return f ~= nil
+end
+
+-- searching for converted images
+function parse_lg(filename)
+ print("Parse LG")
+ local outputimages,outputfiles,status={},{},nil
+ local fonts, used_fonts = {},{}
+ if not file_exists(filename) then
+ print("Cannot read log file: "..filename)
+ else
+ local usedfiles={}
+ for line in io.lines(filename) do
+ --- needs --- pokus.idv[1] ==> pokus0x.png ---
+ -- line:gsub("needs --- (.+?)[([0-9]+) ==> ([%a%d%p%.%-%_]*)",function(name,page,k) table.insert(outputimages,k)end)
+ line:gsub("needs %-%-%- (.+)%[([0-9]+)%] ==> ([%a%d%p%.%-%_]*)",
+ function(file,page,output)
+ local rec = {
+ source = file,
+ page=page,
+ output = output
+ }
+ table.insert(outputimages,rec)
+ end
+ )
+ line:gsub("File: (.*)", function(k)
+ if not usedfiles[k] then
+ table.insert(outputfiles,k)
+ usedfiles[k] = true
+ end
+ end)
+ line:gsub("htfcss: ([^%s]+)(.*)",function(k,r)
+ local fields = {}
+ r:gsub("[%s]*([^%:]+):[%s]*([^;]+);",function(c,v)
+ fields[c] = v
+ end)
+ fonts[k] = fields
+ end)
+
+ line:gsub('Font("([^"]+)","([%d]+)","([%d]+)","([%d]+)"',function(n,s1,s2,s3)
+ table.insert(used_fonts,{n,s1,s2,s3})
+ end)
+
+ end
+ status=true
+ end
+ return {files = outputfiles, images = outputimages},status
+end
+
+
+local cp_func = os.type == "unix" and "cp" or "copy"
+function cp(src,dest)
+ local command = string.format('%s %s %s', cp_func, src, dest)
+ if cp_func == "copy" then command = command:gsub("/",'\\') end
+ print("Copy: "..command)
+ os.execute(command)
+end
+
+local used_dir = {}
+
+function prepare_path(path)
+ --local dirs = path:split("/")
+ local dirs = {}
+ if path:match("^/") then dirs = {""}
+ elseif path:match("^~") then
+ local home = os.getenv "HOME"
+ dirs = home:split "/"
+ path = path:gsub("^~/","")
+ table.insert(dirs,1,"")
+ end
+ if path:match("/$")then path = path .. " " end
+ for _,d in pairs(path:split "/") do
+ table.insert(dirs,d)
+ end
+ table.remove(dirs,#dirs)
+ return dirs,table.concat(dirs,"/")
+end
+
+-- Find which part of path already exists
+-- and which directories have to be created
+function find_directories(dirs, pos)
+ local pos = pos or #dirs
+ -- we tried whole path and no dir exist
+ if pos < 1 then return dirs end
+ local path = ""
+ -- in the case of unix absolute path, empty string is inserted in dirs
+ if pos == 1 and dirs[pos] == "" then
+ path = "/"
+ else
+ path = table.concat(dirs,"/", 1,pos) .. "/"
+ end
+ if not lfs.chdir(path) then -- recursion until we succesfully changed dir
+ -- or there are no elements in the dir table
+ return find_directories(dirs,pos - 1)
+elseif pos ~= #dirs then -- if we succesfully changed dir
+ -- and we have dirs to create
+ local p = {}
+ for i = pos+1, #dirs do
+ table.insert(p, dirs[i])
+ end
+ return p
+else -- whole path exists
+ return {}
+end
+end
+
+function mkdirectories(dirs)
+ if type(dirs) ~="table" then
+ return false, "mkdirectories: dirs is not table"
+ end
+ for _,d in pairs(dirs) do
+ local stat,msg = lfs.mkdir(d)
+ if not stat then return false, "makedirectories error: "..msg end
+ lfs.chdir(d)
+ end
+ return true
+end
+
+function copy_filter(src,dest, filter)
+ local src_f=io.open(src,"rb")
+ local dst_f=io.open(dest,"w")
+ local contents = src_f:read("*all")
+ local filter = filter or function(s) return s end
+ src_f:close()
+ dst_f:write(filter(contents))
+ dst_f:close()
+end
+
+
+
+function copy(filename,outfilename)
+ local currdir = lfs.currentdir()
+ if filename == outfilename then return true end
+ local parts, path = prepare_path(outfilename)
+ if not used_dir[path] then
+ local to_create, msg = find_directories(parts)
+ if not to_create then
+ print(msg)
+ return false
+ end
+ used_dir[path] = true
+ local stat, msg = mkdirectories(to_create)
+ if not stat then print(msg) end
+ end
+ lfs.chdir(currdir)
+ cp(filename, path)
+ return true
+end
+
+-- Config loading
+local function run(untrusted_code, env)
+ if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end
+ local untrusted_function = nil
+ if not loadstring then
+ untrusted_function, message = load(untrusted_code, nil, "t",env)
+ else
+ untrusted_function, message = loadstring(untrusted_code)
+ end
+ if not untrusted_function then return nil, message end
+ if not setfenv then setfenv = function(a,b) return true end end
+ setfenv(untrusted_function, env)
+ return pcall(untrusted_function)
+end
+
+local main_settings = {}
+main_settings.fonts = {}
+local env = {}
+
+-- We make sandbox for make script, all functions must be explicitely declared
+-- Function declarations:
+env.pairs = pairs
+env.ipairs = ipairs
+env.print = print
+env.split = split
+env.string = string
+env.table = table
+env.copy = copy
+env.mkdirectories = mkdirectories
+env.require = require
+env.texio = texio
+env.type = type
+env.lfs = lfs
+env.os = os
+env.io = io
+env.unicode = unicode
+env.Font = function(s)
+ local font_name = s["name"]
+ if not font_name then return nil, "Cannot find font name" end
+ env.settings.fonts[font_name] = s
+end
+
+env.Make = make4ht.Make
+env.Make.params = env.settings
+env.Make:add("test","no takže ${tex4ht_sty_par} ${htlatex} ${input} ${config}")
+--env.Make:add("htlatex", "${htlatex} ${latex_par} '\\\makeatletter\\def\\HCode{\\futurelet\\HCode\\HChar}\\def\\HChar{\\ifx\"\\HCode\\def\\HCode\"##1\"{\\Link##1}\\expandafter\\HCode\\else\\expandafter\\Link\\fi}\\def\\Link#1.a.b.c.{\\g@addto@macro\\@documentclasshook{\\RequirePackage[#1,html]{tex4ht}\\let\\HCode\\documentstyle\\def\\documentstyle{\\let\\documentstyle\\HCode\\expandafter\\def\\csname tex4ht\\endcsname{#1,html}\\def\\HCode####1{\\documentstyle[tex4ht,}\\@ifnextchar[{\\HCode}{\\documentstyle[tex4ht]}}}\\makeatother\\HCode '${config}${tex4ht_sty_par}'.a.b.c.\\input ' ${input}")
+env.Make:add("htlatex",function(par)
+ local command =
+"${htlatex} ${latex_par} '\\makeatletter"..
+"\\def\\HCode{\\futurelet\\HCode\\HChar}\\def\\HChar{\\ifx\"\\HCode"..
+"\\def\\HCode\"##1\"{\\Link##1}\\expandafter\\HCode\\else"..
+"\\expandafter\\Link\\fi}\\def\\Link#1.a.b.c.{\\g@addto@macro"..
+"\\@documentclasshook{\\RequirePackage[#1,html]{tex4ht}${packages}}"..
+"\\let\\HCode\\documentstyle\\def\\documentstyle{\\let\\documentstyle"..
+"\\HCode\\expandafter\\def\\csname tex4ht\\endcsname{#1,html}\\def"..
+"\\HCode####1{\\documentstyle[tex4ht,}\\@ifnextchar[{\\HCode}{"..
+"\\documentstyle[tex4ht]}}}\\makeatother\\HCode ${tex4ht_sty_par}.a.b.c."..
+"\\input ${input}'"
+ if os.type == "windows" then
+ command = command:gsub("'",'')
+ end
+ command = command % par
+ print("LaTeX call: "..command)
+ os.execute(command)
+ local logfile = par.input .. ".log"
+ local f = io.open(logfile,"r")
+ if not f then
+ print("Make4ht: cannot open log file "..logfile)
+ return 1
+ end
+ local len = f:seek("end")
+
+ f:seek("set", len - 256)
+ local text = f:read("*a")
+ f:close()
+ if text:match("No pages of output") then return 1 end
+ return 0
+end
+,{correct_exit=0})
+env.Make:add("tex4ht","tex4ht ${tex4ht_par} ${input}", nil, 1)
+env.Make:add("t4ht","t4ht ${t4ht_par} ${input}.${ext}",{ext="dvi"},1)
+
+function load_config(settings, config_name)
+ local settings = settings or main_settings
+ env.settings = settings
+ env.mode = settings.mode
+ local config_name = config_name or "config.lua"
+ local f = io.open(config_name,"r")
+ if not f then return env, "Cannot open config file" end
+ local code = f:read("*all")
+ local fn, msg = run(code,env)
+ if not fn then print(msg) end
+ assert(fn)
+ return env
+end
+
+
diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check
index e9872152619..01db7d7c76c 100755
--- a/Master/tlpkg/bin/tlpkg-ctan-check
+++ b/Master/tlpkg/bin/tlpkg-ctan-check
@@ -353,7 +353,8 @@ my @TLP_working = qw(
luasseq luatexbase luatexja luatexko luatextra luatodonotes luaxml
lxfonts ly1
m-tx macros2e macroswap mafr magaz mailing mailmerge
- makebarcode makebox makecell makecirc makecmds makedtx makeglos makeplot
+ make4ht makebarcode makebox makecell makecirc makecmds
+ makedtx makeglos makeplot
makeshape mandi manfnt manfnt-font manuscript margbib
marginfix marginnote marvosym
matc3 matc3mem match_parens
diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds
index eea4c8c345e..79129c18ef4 100755
--- a/Master/tlpkg/libexec/ctan2tds
+++ b/Master/tlpkg/libexec/ctan2tds
@@ -2579,6 +2579,7 @@ $standardttf = '\.ttf|\.TTC';
'luaindex' => '\.lua$',
'lualatex-math' => '\.lua$',
'luasseq' => '\.lua$',
+ 'make4ht' => 'filters|\.lua$',
'mycv' => 'mycv_split_contents\.pl',
'pgfmolbio' => '\.lua$',
'placeat' => '\.lua$',
@@ -2631,6 +2632,7 @@ $standardttf = '\.ttf|\.TTC';
'ltximg' => 'ltximg\.pl$',
'lua2dox' => 'lua2dox_filter?$',
'luaotfload' => 'luaotfload-tool',
+ 'make4ht' => 'make4ht$',
'match_parens' => '^match_parens$',
'mathspic' => '^mathspic\.pl$',
'multibibliography' => '\.pl$',
diff --git a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
index f9cf3050f79..e17312fc9ab 100644
--- a/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
+++ b/Master/tlpkg/tlpsrc/collection-binextra.tlpsrc
@@ -47,6 +47,7 @@ depend latexindent
depend ltxfileinfo
depend ltximg
depend listings-ext
+depend make4ht
depend match_parens
depend mkjobtexmf
depend patgen
diff --git a/Master/tlpkg/tlpsrc/make4ht.tlpsrc b/Master/tlpkg/tlpsrc/make4ht.tlpsrc
new file mode 100644
index 00000000000..dca338c719c
--- /dev/null
+++ b/Master/tlpkg/tlpsrc/make4ht.tlpsrc
@@ -0,0 +1 @@
+binpattern f bin/${ARCH}/${PKGNAME}