summaryrefslogtreecommitdiff
path: root/support
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-11-02 03:01:48 +0000
committerNorbert Preining <norbert@preining.info>2019-11-02 03:01:48 +0000
commit3479a92321ed7fe7e2133d3daec2d4f5fd53fbc6 (patch)
treef81c77e1742124279f68e41484d9e53ad40248ff /support
parent61b8d58232b999b6cc966aee9152fb86bbb759cd (diff)
CTAN sync 201911020301
Diffstat (limited to 'support')
-rw-r--r--support/make4ht/README1168
-rw-r--r--support/make4ht/changelog.tex258
-rw-r--r--support/make4ht/domfilters/make4ht-aeneas.lua3
-rw-r--r--support/make4ht/domfilters/make4ht-collapsetoc.lua198
-rw-r--r--support/make4ht/domfilters/make4ht-joincharacters.lua8
-rw-r--r--support/make4ht/domfilters/make4ht-joincolors.lua3
-rw-r--r--support/make4ht/domfilters/make4ht-odtimagesize.lua3
-rw-r--r--support/make4ht/domfilters/make4ht-odtpartable.lua9
-rw-r--r--support/make4ht/domfilters/make4ht-tablerows.lua58
-rw-r--r--support/make4ht/extensions/common_domfilters.lua29
-rw-r--r--support/make4ht/extensions/dvisvgm_hashes.lua7
-rw-r--r--support/make4ht/extensions/preprocess_input.lua108
-rw-r--r--support/make4ht/extensions/staticsite.lua3
-rw-r--r--support/make4ht/extensions/tidy.lua3
-rw-r--r--support/make4ht/filters/make4ht-domfilter.lua7
-rw-r--r--support/make4ht/filters/make4ht-entities-to-unicode.lua8
-rw-r--r--support/make4ht/filters/make4ht-mathjaxnode.lua11
-rw-r--r--support/make4ht/filters/make4ht-staticsite.lua6
-rw-r--r--support/make4ht/filters/make4ht-svg-height.lua4
-rw-r--r--support/make4ht/formats/docbook.lua3
-rw-r--r--support/make4ht/formats/odt.lua23
-rwxr-xr-xsupport/make4ht/make4ht32
-rw-r--r--support/make4ht/make4ht-doc.pdfbin110638 -> 126657 bytes
-rw-r--r--support/make4ht/make4ht-doc.tex17
-rw-r--r--support/make4ht/make4ht-errorlogparser.lua97
-rw-r--r--support/make4ht/make4ht-htlatex.lua75
-rw-r--r--support/make4ht/make4ht-indexing.lua190
-rw-r--r--support/make4ht/make4ht-lib.lua29
-rw-r--r--support/make4ht/make4ht-logging.lua105
-rw-r--r--support/make4ht/make4ht-xtpipes.lua15
-rw-r--r--support/make4ht/mkparams.lua134
-rw-r--r--support/make4ht/mkutils.lua131
-rw-r--r--support/make4ht/readme.tex1353
-rw-r--r--support/tex4ebook/README139
-rw-r--r--support/tex4ebook/changelog.tex100
-rw-r--r--support/tex4ebook/exec_epub.lua372
-rw-r--r--support/tex4ebook/exec_epub3.lua129
-rw-r--r--support/tex4ebook/exec_mobi.lua3
-rw-r--r--support/tex4ebook/readme.tex137
-rwxr-xr-xsupport/tex4ebook/tex4ebook99
-rw-r--r--support/tex4ebook/tex4ebook-doc.pdfbin73368 -> 78095 bytes
-rw-r--r--support/tex4ebook/tex4ebook.4ht20
-rw-r--r--support/tex4ebook/tex4ebook.sty45
43 files changed, 3566 insertions, 1576 deletions
diff --git a/support/make4ht/README b/support/make4ht/README
index a99a108d69..df14833239 100644
--- a/support/make4ht/README
+++ b/support/make4ht/README
@@ -2,93 +2,209 @@
# Introduction
-`make4ht` is a simple build system for `tex4ht`, \TeX\ to XML converter. It provides a command line tool
-that drive the conversion process. It also provides a library which can be used to create
-customized conversion tools. An example of such conversion tool is
-[tex4ebook](https://github.com/michal-h21/tex4ebook) for conversion of \TeX\ to
+`make4ht` is a build system for \TeX4ht, \TeX\ to XML converter. It provides a command line tool
+that drives the conversion process. It also provides a library that can be used to create
+customized conversion tools. An example of such a tool is
+[tex4ebook](https://github.com/michal-h21/tex4ebook), a tool for conversion from \TeX\ to
ePub and other e-book formats.
-## How it works
+The basic conversion from \LaTeX\ to `HTML` using `make4ht` can be executed using the following command:
-### The issues with default `tex4ht` conversion commands
+ $ make4ht filename.tex
+It will produce a file named `filename.html` if the compilation goes without fatal errors.
-`tex4ht` system supports several output formats, most notably `XHTML`, `HTML 5` and `ODT`.
-The conversion can be invoked using several commands. These commands invoke LaTeX\ or Plain TeX
-with special instructions to load `tex4ht.sty` package. The \TeX\ run produces special `DVI` file
-which contains the code for desired output format. Produced `DVI` file is then processed and
-desired output files are created.
-The basic command provided by `tex4ht` is named `htlatex`. It compiles \LaTeX\
+# Command line options {#clioptions}
+\label{sec:clioptions}
+
+ make4ht - build system for TeX4ht
+ Usage:
+ make4ht [options] filename ["tex4ht.sty op." "tex4ht op."
+ "t4ht op" "latex op"]
+ -a,--loglevel (default status) Set log level.
+ possible values: debug, info, status, warning, error, fatal
+ -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 filename is different
+ than `filename`.mk4
+ -f,--format (default nil) Output file format
+ -j,--jobname (default nil) Set the jobname
+ -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
+ -v,--version Print version number
+ <filename> (string) Input filename
+
+
+It is still possible to invoke `make4ht` in the same way as is invoked `htlatex`:
+
+ $ make4ht filename "customcfg, charset=utf-8" "-cunihtf -utf8" "-dfoo"
+
+Note that this will not use `make4ht` routines for the output directory handling.
+See section \ref{sec:output-dir} for more information about this issue.
+To use these routines, change the previous listing to:
+
+ $ make4ht -d foo filename "customcfg, charset=utf-8" "-cunihtf -utf8"
+
+This call has the same effect as the 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 the current directory, or absolute:
+
+ $ make4ht -d use/current/dir/ filename
+ $ make4ht -d ../gotoparrentdir filename
+ $ make4ht -d ~/gotohomedir filename
+ $ make4ht -d c:\documents\windowspathsareworkingtoo filename
+
+The short options that don't take parameters can be collapsed:
+
+
+ $ make4ht -ulc customcfg -d foo filename
+
+
+To pass output from the other commands to `make4ht` use the `-` character as a
+filename. It is best to use this feature together with the `--jobname` or `-j`
+option.
+
+ $ cat hello.tex | make4ht -j world -
+
+By default, `make4ht` tries to be quiet, so it hides most of the command line
+messages and the output from the executed commands. It will display only status
+messages, warnings and errors. The logging level can be selected using the
+`--loglevel` or `-a` options. If the compilation fails, it may be useful to display more
+information using the `info` or `debug` levels.
+
+
+ $ make4ht -a debug faulty.tex
+
+
+
+# Why `make4ht`? -- `htlatex` issues
+
+
+\TeX4ht\ system supports several output formats, most notably `XHTML`, `HTML 5`
+and `ODT`, but it also supports `TEI` or `Docbook`.
+
+The conversion can be invoked using several scripts, which are distributed with \TeX4ht.
+They differ in parameters passed to the underlying commands.
+
+These scripts invoke \LaTeX\ or Plain \TeX\ with special instructions to load
+the `tex4ht.sty` package. The \TeX\ run produces a special `DVI` file
+that contains the code for the desired output format. The produced `DVI` file
+is then processed using the `tex4ht` command, which in conjunction with the
+`t4ht` command produces the desired output files.
+
+## Passing command line arguments
+
+The basic conversion script provided by \TeX4ht\ system is named `htlatex`. It 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 $tex4ht_options filename
- t4ht $t4ht_options filename
+ $ 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 $tex4ht_options filename
+ $ t4ht $t4ht_options filename
The options for various parts of the system can be passed on the command line:
- htlatex filename "tex4ht.sty options" "tex4ht_options" "t4ht_options" "latex_options"
+ $ htlatex filename "tex4ht.sty options" "tex4ht_options" "t4ht_options" "latex_options"
For basic `HTML` conversion it is possible to use the most basic invocation:
- htlatex filename.tex
+ $ htlatex filename.tex
-It can be much more involved for `HTML 5` output in `UTF-8` encoding:
+It can be much more involved for the `HTML 5` output in `UTF-8` encoding:
- htlatex filename.tex "xhtml,html5,charset=utf-8" "-cmozhtf -utf8"
+ $ htlatex filename.tex "xhtml,html5,charset=utf-8" " -cmozhtf -utf8"
`make4ht` can simplify it:
- make4ht -uf html5 filename.tex
+ $ make4ht -u filename.tex
+
+The `-u` option requires the `UTF-8` encoding. `HTML 5` is used as the default
+output format by `make4ht`.
+
+More information about the command line arguments can be found in section
+\ref{sec:clioptions}.
+
+
+## Compilation sequence
-Another issue is the fixed compilation order and hard-coded number of LaTeX invocations.
+`htlatex` has a fixed compilation order and a hard-coded number of \LaTeX\ invocations.
-When you need to run a program which interact with LaTeX, such as `Makeindex`
-or `Bibtex`, you need to create a new script based on `htlatex`, or run
-`htlatex` twice, which means that LaTeX will be invoked six times.
-This can lead to significantly long compilation times. `make4ht` provides build files and
-extensions, which can be used for interaction with external tools.
+It is not possible to execute additional commands during the compilation.
+When we want to run a program that interacts with \LaTeX, such as `Makeindex`
+or `Bibtex`, we have two options. The first option is to create a new script based on
+`htlatex` and add the wanted commands to the modified script. The second option
+is to execute `htlatex`, then the additional and then `htlatex` again. The
+second option means that \LaTeX\ will be invoked six times, as each call to
+`htlatex` executes three calls to \LaTeX. This can lead to significantly long
+compilation times.
-It is also possible to have several compilation modes. When you just add new text to a document,
-which doesn't contain cross-references, don't add new stuff to the table of contents, etc.,
-it is possible to use the `draft` mode which will invoke LaTeX only once. It
-can save quite a lot of the compilation time:
+`make4ht` provides a solution for this issue using a build file, or extensions.
+These can be used for interaction with external tools.
- make4ht -um draft -f html5 filename.tex
+`make4ht` also provides compilation modes, which enables to select commands that
+should be executed using a command line option.
-There are also issues with a behaviour of the `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 a subdirectory, they will be copied to the output directory.
+There is a built-in `draft` mode, which invokes \LaTeX\ only once, instead of
+the default three invocations. It is useful for the compilations of the
+document before its final stage, when it is not important that all
+cross-references work. It can save quite a lot of the compilation time:
+
+ $ make4ht -um draft filename.tex
+
+More information about the build files can be found in section \ref{sec:buildfiles}.
+
+## Handling of the generated files
+\label{sec:output-dir}
+
+There are also issues with the behavior of the `t4ht` application. It reads the
+`.lg` file generated by the `tex4ht` command. This file contains
+information about the generated files, `CSS` instructions, calls to the external
+applications, instructions for image conversions, etc.
+
+
+`t4ht` can be instructed to copy the generated files to an output directory, but
+it doesn't preserve the directory structure. When the images are placed in a
+subdirectory, they will be copied to the output directory, losing the directory structure.
Links will be pointing to a non-existing subdirectory. The following command
should copy all output files to the correct destinations.
- make4ht -d outputdir filename.tex
+ $ make4ht -d outputdir filename.tex
+
+## Image conversion and post-processing of the generated files
+
+\TeX4ht\ can convert parts of the document to images. This is useful
+for diagrams or complicated math, for example.
-The image conversion is configured in the
-[env file](http://www.tug.org/applications/tex4ht/mn35.html#index35-73001),
-which has really strange syntax based and the rules are
-[os dependent](http://www.tug.org/applications/tex4ht/mn-unix.html#index27-69005).
+By default, the image conversion is configured in a
+[`.env` file](http://www.tug.org/applications/tex4ht/mn35.html#index35-73001).
+It has a bit of strange syntax, with
+[operating system dependent](http://www.tug.org/applications/tex4ht/mn-unix.html#index27-69005) rules.
`make4ht` provides simpler means for the image conversion in the build files.
+It is possible to change the image conversion parameters without a need to modify the `.env` file.
+The process is described in section \ref{sec:imageconversion}.
+
+It is also possible to post-process the generated output files. The post-processing can be done
+either using external programs such as `XSLT` processors and `HTML Tidy` or
+using `Lua` functions. More information can be found in section \ref{sec:postprocessing}.
-With `make4ht` build files, we have simple mean to fix these issues. We can
-change image conversion parameters without the need to modify the `env file`,
-or execute 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 the build scripts are written.
# Output file formats and extensions
-The default output format used by `make4ht` is `html5`. Different
+The default output format used by `make4ht` is `html5`. A different
format can be requested using the `--format` option. Supported formats are:
- `xhtml`
@@ -107,22 +223,10 @@ may post-process the output files or request additional commands for the compila
The extensions can be enabled or disabled by appending `+EXTENSION` or `-EXTENSION` after
the output format name:
- make4ht -uf html5+tidy filename.tex
+ $ make4ht -uf html5+tidy filename.tex
Available extensions:
-latexmk_build
-
-: use `Latexmk` for \LaTeX\ compilation.
-
-tidy
-
-: clean the `HTML` files using the `tidy` command.
-
-dvisvgm_hashes
-
-: efficient generation of SVG pictures using Dvisvgm. It can utilize
-multiple processor cores and generates only changed images.
common\_filters
@@ -131,13 +235,22 @@ common\_filters
common\_domfilters
: clean the HTML file using DOM filters. It is more powerful than
-`common_filters`. Used DOM filters are `fixinlines`, `idcolons` and
-`joincharacters`.
+`common_filters`. Used DOM filters are `fixinlines`, `idcolons`,
+`joincharacters`, and `tablerows`.
+
+dvisvgm\_hashes
+
+: efficient generation of SVG pictures using Dvisvgm. It can utilize
+multiple processor cores and generates only changed images.
join\_colors
: load the `joincolors` domfilter for all HTML files.
+latexmk\_build
+
+: use [Latexmk](https://ctan.org/pkg/latexmk?lang=en) for the \LaTeX\ compilation.
+
mathjaxnode
: use [mathjax-node-page](https://github.com/pkra/mathjax-node-page/) to
@@ -146,21 +259,35 @@ mathjaxnode
odttemplate
-: automatically load the `odttemplate` filter.
+: it automatically loads the `odttemplate` filter (page \pageref{sec:odttemplate}).
+
+preprocess\_input
+
+: compilation of the formats
+ supported by [Knitr](https://yihui.name/knitr/) (`.Rnw`, `.Rtex`, `.Rmd`, `.Rrst`)
+ and also Markdown and reStructuredText formats. It requires
+[R](https://www.r-project.org/) + [Knitr](https://yihui.name/knitr/)
+installation, it requires also [Pandoc](https://pandoc.org/) for formats based on Markdown or
+reStructuredText.
staticsite
-: build the document in form suitable for static site generators like [Jekyll](https://jekyllrb.com/).
+: build the document in a form suitable for static site generators like [Jekyll](https://jekyllrb.com/).
+
+tidy
+
+: clean the `HTML` files using the `tidy` command.
# Build files
+\label{sec:buildfiles}
-`make4ht` supports build files. These are `Lua` scripts which can adjust
-the build process. You can request external applications like `bibtex` or `makeindex`,
+`make4ht` supports build files. These are `Lua` scripts that can adjust
+the build process. They can request external applications like `BibTeX` or `Makeindex`,
pass options to the commands, modify the image conversion process, or post-process the
generated files.
`make4ht` tries to load default build file named as `filename + .mk4 extension`.
-You can choose different build file with `-e` or `--build-file` command line
+It is possible to select a different build file with `-e` or `--build-file` command line
option.
Sample build file:
@@ -168,185 +295,205 @@ Sample build file:
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, the `tidy` command is executed on the output `HTML` file.
+`Make:htlatex()` is preconfigured command for calling \LaTeX\ with the `tex4ht.sty` package
+loaded. In this example, it will be executed only once. After the
+compilation, the `tidy` command is executed on the output `HTML` files.
-Note that you don't have to call `tex4ht` and `t4ht` commands explicitly in the
+Note that it is not necessary to call `tex4ht` and `t4ht` commands explicitly in the
build file, they are called automatically.
## User commands
-You can add more commands like `Make:htlatex` using `Make:add` command:
+It is possible to add more commands like `Make:htlatex` using the `Make:add` command:
- Make:add("name", "command", {parameters}, repetition)
+ Make:add("name", "command", {settings table}, repetition)
-The `name` and `command` parameters are required, rest of the parameters are optional.
+This defines the `name` command, which can be then executed using `Make:name()`
+command in the build file.
-This defines `name` command, which can be then executed as `Make:name()` command.
+The `name` and `command` parameters are required, the rest of the parameters are optional.
-### Provided commands
+The defined command receives a table with settings as a parameter at the call time.
+The default settings are provided by `make4ht`. Additional settings can be
+declared in the `Make:add` commands, user can also override the default settings
+when the command is executed in the build file:
-`Make:htlatex`
+ Make:name({hello="world"})
-: One call to TeX engine with special configuration for `tex4ht` loading.
+More information about settings, including the default settings provided by
+`make4ht`, can be found in section \ref{sec:settings} on page
+\pageref{sec:settings}.
-`Make:latexmk`
-: Use `Latexmk` for the document compilation. `tex4ht` will be loaded automatically.
+### The `command` function
+\label{sec:commandfunction}
-`Make:tex4ht`
+The `command` parameter can be either a string template or function:
-: Process the `DVI` file and creates the output files.
+ Make:add("text", "echo hello, input file: ${input}")
-`Make:t4ht`
+The template can get a variable value from the parameters table using a
+`${var_name}` placeholder. Templates are executed using the operating system, so
+they should invoke existing OS commands.
-: Creates the CSS file.
-### Command function
-The `command` parameter can be either string template or function:
- Make:add("text", "echo hello, input file: ${input}")
- Make:add("function", function(params)
+### The `settings table` table
+
+
+The `settings table` parameter is optional. If it is present, it should be
+a table with new settings available in the command. It can also override the default
+`make4ht` settings for the defined command.
+
+ Make:add("sample_function", function(params)
for k, v in pairs(params) do
print(k..": "..v)
end, {custom="Hello world"}
)
-The template can get variable value from the parameters table using a
-`${var_name}` placeholder. Templates are executed using operating system, so
-they should invoke existing OS commands. Function commands may execute system
-commands using `os.execute` function.
-
-
-### Parameters table
-`parameters` parameter is optional, it can be table or `nil` value, which
-should be used if you want to use the `repetition` parameter, but don't want to
-modify the parameters table.
+### Repetition
-The table with default parameters is passed to all commands, they can be accessed from command functions
-or templates. When you specify your own parameters in the command definition, these additional
-parameters are added to the default parameters table for this particular
-command. You can override the default parameters in the parameters table.
+The `repetition` parameter specifies the maximum number of executions of the
+particular command. This is used for instance for `tex4ht` and `t4ht`
+commands, as they should be executed only once in the compilation. They would
+be executed multiple times when they are included in the build file, as they
+are called by `make4ht` by default. Because these commands allow only one
+`repetition`, the second execution is blocked.
+### Expected exit code
+You can set the expected exit code from a command with a `correct_exit` key in the
+settings table. The compilation will be terminated when the command returns a
+different exit code.
-The default parameters are following:
+ Make:add("biber", "biber ${input}", {correct_exit=0})
-`htlatex`
+Commands that execute lua functions can return the numerical values using the `return` statement.
-: used compiler
-`input`
+This mechanism isn't used for \TeX, because it doesn't differentiate between fatal and non-fatal errors.
+It returns the same exit code in all cases. Because of this, log parsing is used for a fatal error detection instead.
+Error code value `1` is returned in the case of a fatal error, `0` is used
+otherwise. The `Make.testlogfile` function can be used in the build file to
+detect compilation errors in the TeX log file.
-: it is output file name in fact
-`tex_file`
+## Provided commands
-: input TeX file
+`Make:htlatex`
-`latex_par`
+: One call to the TeX engine with special configuration for loading of the `tex4ht.sty` package.
-: parameters to `latex`
+`Make:latexmk`
-`packages`
+: Use `Latexmk` for the document compilation. `tex4ht.sty` will be loaded automatically.
-: insert additional LaTeX code which is inserted before `\documentclass`.
- Useful for passing options to packages or additional packages loading
+`Make:tex4ht`
-`tex4ht_sty_par`
+: Process the `DVI` file and create output files.
-: parameters to `tex4ht.sty`
+`Make:t4ht`
-`tex4ht_par`
+: Create the CSS file and generate images.
-: parameters to the `tex4ht` application
+`Make:biber`
-`t4ht_par`
+: Process bibliography using the `biber` command.
-: parameters to the `t4ht` application
+`Make:bibtex`
-`outdir`
+: Process bibliography using the `bibtex` command.
-: the output directory
+`Make:xindy`
-`repetition`
+: Generate index using Xindy index processor.
-: limit number of command execution.
+`Make:makeindex`
-`correct_exit`
+: Generate index using the Makeindex command.
-: expected `exit code` from the command. The compilation will be terminated
- if the command `exit code` is different.
+`Make:xindex`
+: Generate index using the Xindex command.
-### Repetition
-Repetition is number which specifies a maximal number of executions of the
-particular command. This is used for instance for `tex4ht` and `t4ht`
-commands, as they should be executed only once in the compilation. They would
-be executed multiple times if you include them in the build file because they
-are called by `make4ht` by default. Because these commands allow only one
-`repetition`, the second execution will be blocked.
+## File matches
+\label{sec:postprocessing}
-### Expected exit code
+Another type of action that can be specified in the build file is
+`Make:match`. It can be used to post-process the generated files:
-You can set the expected exit code from a command with a `correct_exit` key in the
-parameters table. The compilation will be stopped when the command returns a
-different exit code.
+ Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
-This mechanism isn't used for LaTeX (for all TeX engines and formats, in
-fact), because it doesn't differentiate between fatal and non-fatal errors, and
-it returns the 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. The `Make.testlogfile` function can be used in the build file to
-detect compilation errors in the TeX log file.
+The above example will clean all output `HTML` files using the `tidy` command.
-## File matches
+The `Make:match` action tests output filenames using a `Lua` pattern matching function.
+It executes a command or a function, specified in the second argument, on files
+whose filenames match the pattern.
-Another type of action which can be specified in the build file is
-`match`. It can be called on the generated files:
+The commands to be executed can be specified as strings. They can contain
+`${var_name}` placeholders, which are replaced with corresponding variables
+from the `settings` table. The templating system was described in
+subsection \ref{sec:commandfunction}. There is an additional variable
+available in this table, called `filename`. It contains the name of the current
+output file.
- Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
-It tests output file names with `Lua` pattern matching and on matched items will
-execute a command or a function, specified in the second argument. Commands may be
-specified as strings, the templates will be expanded, `${var_name}` placeholders
-will be replaced with corresponding variables from the `parameters` table,
-described in the previous subsection. One additional variable is available:
-`filename`. It contains the name of the current output file.
+If a function is used instead, it will get two parameters. The first one is the
+current filename, the second one is the `settings` table.
-The above example will clean all output `HTML` files using the `tidy` command.
+ Make:match("html$", function(filename, settings)
+ print("Post-processing file: ".. filename)
+ print("Available settings")
+ for k,v in pairs(settings)
+ print(k,v)
+ end
+ return true
+ end)
-If function is used instead, it will get two parameters.
-The first one is a current filename, the second one
-table with parameters.
+Multiple post-processing actions can be executed on each filename. The Lua
+action functions can return an exit code. If the exit code is false, the execution
+of the post-processing chain for the current file will be terminated.
+### Filters
+\label{sec:filters}
+To make it easier to post-process the generated files using the `match`
+actions, `make4ht` provides a filtering mechanism thanks to the
+`make4ht-filter` module.
-### Filters
+The `make4ht-filter` module returns a function that can be used for the filter
+chain building. Multiple filters can be chained into a pipeline. Each filter
+can modify the string that is passed to it from the previous filters. The
+changes are then saved to the processed file.
-Some default `match` actions which can be used are available from the
-`make4ht-filter` module. It contains some functions which are useful for
-fixing some `tex4ht` bugs or shortcomings.
+Several built-in filters are available, it is also possible to create new ones.
-Example:
+Example that use only the built-in filters:
local filter = require "make4ht-filter"
local process = filter{"cleanspan", "fixligatures", "hruletohr"}
Make:htlatex()
+ Make:match("html$",process)
+
+Function `filter` accepts also function arguments, in this case this function
+takes file contents as a parameter and modified contents are returned.
+
+Example with custom filter:
+
+ local filter = require "make4ht-filter"
+ local changea = function(s) return s:gsub("a","z") end
+ local process = filter{"cleanspan", "fixligatures", changea}
Make:htlatex()
Make:match("html$",process)
-The `make4ht-filter` module return a function which can be used for the filter
-chain building. Multiple filters can be chained, each of them can modify the string
-which was modified by the previous filters. The changes are then saved to the
-processed file.
+In this example, spurious span elements are joined, ligatures are decomposed,
+and then all letters "a" are replaced with "z" letters.
-Built-in filters are:
+Built-in filters are the following:
cleanspan
@@ -363,19 +510,18 @@ fixligatures
hruletohr
: `\hrule` commands are translated to series of underscore characters
- by `tex4ht`, this filter translate these underscores to `<hr>` elements
+ by \TeX4ht, this filter translates 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)
+: convert prohibited named entities to numeric entities (only
+ `&nbsp;` currently).
fix-links
: replace colons in local links and `id` attributes with underscores. Some
cross-reference commands may produce colons in internal links, which results in
- validation error.
+ a validation error.
mathjaxnode
@@ -388,36 +534,24 @@ odttemplate
: use styles from another `ODT` file serving as a template in the current
document. It works for the `styles.xml` file in the `ODT` file. During
the compilation, this file is named as `\jobname.4oy`.
+ \label{sec:odttemplate}
staticsite
-: create HTML files in format suitable for static site generators such as [Jekyll](https://jekyllrb.com/)
+: create HTML files in a format suitable for static site generators such as [Jekyll](https://jekyllrb.com/)
svg-height
: some SVG images produced by `dvisvgm` seem to have wrong dimensions. This filter
tries to set the correct image size.
-Function `filter` accepts also function arguments, in this case this function
-takes file contents as a 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 example, spurious span elements are joined, ligatures are decomposed,
-and then all letters 'a' are replaced with 'z' letters.
### DOM filters
-DOM filters use the [`LuaXML`](https://ctan.org/pkg/luaxml) library to modify
+DOM filters are variants of filters that use the
+[`LuaXML`](https://ctan.org/pkg/luaxml) library to modify
directly the XML object. This enables more powerful
-operations than the regex based filters from the previous section.
+operations than the regex-based filters from the previous section.
Example:
@@ -431,7 +565,11 @@ Available DOM filters:
aeneas
: [Aeneas](https://www.readbeyond.it/aeneas/) is a tool for automagical synchronization of text and audio.
- This filter modifies the HTML code to support the synchronization.
+ This filter modifies the HTML code to support synchronization.
+
+collapsetoc
+
+: collapse table of contents to contain only top-level sectioning level and sections on the current page.
fixinlines
@@ -443,296 +581,350 @@ idcolons
joincharacters
-: join consecutive `<span>` or `<mn>` elements.
+: join consecutive `<span>` or `<mn>` elements. This DOM filter supersedes the `cleanspan` filter.
joincolors
-: many `<span>` elements with unique `id` attribute are created when \LaTeX\ colors are being used in the document.
- CSS rule is added for each of these elements, which may result in
- substantial grow of the CSS file. This filter replace these rules with a
+: many `<span>` elements with unique `id` attributes are created when \LaTeX\ colors are being used in the document.
+ A CSS rule is added for each of these elements, which may result in
+ substantial growth of the CSS file. This filter replaces these rules with a
common one for elements with the same color value.
odtimagesize
: set correct dimensions for images in the ODT format. It is loaded by default for the ODT output.
+odtpartable
+
+: resolve tables nested inside paragraphs, which is invalid in the ODT format.
+
+tablerows
+
+: remove spurious rows from HTML tables.
+
t4htlinks
: fix hyperlinks in the ODT format.
-### make4ht-aeneas-config package
-Companion for the `aeneas` DOM filter is the `make4ht-aeneas-config` plugin. It
-can be used to write Aeneas configuration file or execute Aeneas on the
-generated HTML files.
-Available functions:
+## Image conversion
+\label{sec:imageconversion}
-write\_job(parameters)
+It is possible to convert parts of the \LaTeX\ input as pictures. It can be used
+for preserving the appearance of math or diagrams, for example.
-: write Aenas job configuration to `config.xml` file. See the [Aeneas
- documentation](https://www.readbeyond.it/aeneas/docs/clitutorial.html#processing-jobs)
- for more information about jobs.
+These pictures are stored in a special `DVI` file, which can be processed by
+a `DVI` to image commands, such as `dvipng` or `dvisvgm`.
-execute(parameters)
+This conversion is normally configured in the `tex4ht.env` file. This file
+is system dependent and it has quite an unintuitive syntax.
+The configuration is processed by the `t4ht` application and the conversion
+command is called for all pictures.
-: execute Aeneas.
+It is possible to disable `t4ht` image processing and configure image
+conversion in the build file using the `image` action:
-process\_files(parameters)
+ Make:image("png$",
+ "dvipng -bg Transparent -T tight -o ${output} -pp ${page} ${source}")
-: process the audio and generated subtitle files.
+`Make:image` takes two parameters, a `Lua` pattern to match the image name, and
+the action.
-By default, the `smil` file is created. It is assumed that there is audio file
-in `mp3` format named as the TeX file. It is possible to use different formats
-and file names using mapping.
+Action can be either a string template with the conversion command
+or a function that takes a table with parameters as an argument.
-The configuration options can be passed directly to the functions or set using
-`filter_settings "aeneas-config" {parameters}` function.
+There are three parameters:
+ - `output` - output image filename
+ - `source` - `DVI` file with the pictures
+ - `page` - page number of the converted image
-Available parameters:
+## The `mode` variable
+The `mode` variable available in the build process contains
+contents of the `--mode` command line option. It can be used to run some commands
+conditionally. For example:
-lang
+ if mode == "draft" then
+ Make:htlatex{}
+ else
+ Make:htlatex{}
+ Make:htlatex{}
+ Make:htlatex{}
+ end
-: document language. It is interfered from the HTML file, so it is not necessary to set it.
+In this example (which is the default configuration used by `make4ht`),
+\LaTeX\ is called only once when `make4ht` is called with the `draft` mode:
+
+ make4ht -m draft filename
-map
+## The `settings` table
+\label{sec:settings}
-: mapping between HTML, audio and subtitle files. More info bellow.
+It is possible to access the parameters outside commands, file matches
+and image conversion functions. For example, to convert the document to
+the `OpenDocument Format (ODT)`, the following settings can be used. They are
+based on the `oolatex` command:
-text\_type
+ 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 "
-: type of the input. The `aeneas` DOM filter produces `unparsed` text type.
+(Note that it is possible to use the `--format odt` option
+which is superior to the previous code. This example is intended just as an
+illustration)
-id\_sort
+There are some functions to simplify access to the settings:
-: sorting of id attributes. Default value is `numeric`.
+`set_settings{parameters}`
-id\_regex
+: overwrite settings with values from a passed table
-: regular expression to parse the id attributes.
+`settings_add{parameters}`
-sub\_format
+: add values to the current settings
-: generated subtitle format. Default `smil`.
+`filter_settings "filter name" {parameters}`
+: set settings for a filter
-Additional parameters for the job configuration file:
+`get_filter_settings(name)`
-- description
-- prefix
-- config\_name
-- keep\_config
+: get settings for a filter
+For example, it is possible to simplify the sample from the previous code listings:
-It is possible to generate multiple HTML files from the LaTeX source. For
-example, `tex4ebook` generates separate file for each chapter or section. It is
-possible to set options for each HTML file, in particular names of the
-corresponding audio files. This mapping is done using `map` parameter.
+ settings_add {
+ tex4ht_sty_par =",ooffice",
+ tex4ht_par = " ooffice/! -cmozhtf",
+ t4ht_par = " -cooxtpipes -coo "
+ }
-Example:
+Settings for filters and extensions can be set using `filter_settings`:
- filter_settings "aeneas-config" {
- map = {
- ["sampleli1.html"] = {audio_file="sample.mp3"},
- ["sample.html"] = false
- }
+
+ filter_settings "test" {
+ hello = "world"
}
-Table keys are the configured file names. It is necessary to insert them as
-`["filename.html"]`, because of Lua syntax rules.
+These settings can be retrieved in the extensions and filters using the `get_filter_settings` function:
-This example maps audio file `sample.mp3` to a section subpage. The main HTML
-file, which may contain title and table of contents doesn't have a
-corresponding audio file.
+ function test(input)
+ local options = get_filter_settings("test")
+ print(options.hello)
+ return input
+ end
+
+### Default settings
-Filenames of the sub files corresponds to the chapter numbers, so they are not
-stable when a new chapter is added. It is possible to request file names
-interfered from the chapter titles using the `sec-filename` option or `tex4ht`.
+The default parameters are the following:
-Available `map` options:
+`htlatex`
+: used \TeX\ engine
-audio\_file
+`input`
-: the corresponding audio file
+: content of `\jobname`, see also the `tex_file` parameter.
-sub\_file
+`interaction`
-: name of the generated subtitle file
+: interaction mode for the \TeX\ engine. The default value is `batchmode` to
+ suppress user input on compilation errors. It also suppresses most of the \TeX\
+ compilation log output. Use the `errorstopmode` for the default behavior.
-The following options are same as their counter-parts from the main parameters table and generally don't need to be set:
+`tex_file`
-- prefix
-- file\_desc
-- file\_id
-- text\_type
-- id\_sort
-- id\_prefix
-- sub\_format
+: input \TeX\ filename
+`latex_par`
-Full example:
+: command line parameters to the \TeX\ engine
+`packages`
- local domfilter = require "make4ht-domfilter"
- local aeneas_config = require "make4ht-aeneas-config"
-
- filter_settings "aeneas-config" {
- map = {
- ["krecekli1.xhtml"] = {audio_file="krecek.mp3"},
- ["krecek.xhtml"] = false
- }
- }
-
- local process = domfilter {"aeneas"}
- Make:match("html$", process)
+: additional \LaTeX\ code inserted before `\documentclass`.
+ Useful for passing options to packages used in the document or to load additional packages.
- if mode == "draft" then
- aeneas_config.process_files {}
- else
- aeneas_config.execute {}
- end
+`tex4ht_sty_par`
+: options for `tex4ht.sty`
+`tex4ht_par`
+: command line options for the `tex4ht` command
-## Image conversion
+`t4ht_par`
-It is possible to convert parts of LaTeX input to pictures, it is used
-for example for math or diagrams in `tex4ht`.
+: command line options for the `t4ht` command
-These pictures are stored in a special `dvi` file, which can be processed by
-the `dvi to image` commands.
+`outdir`
-This conversion is normally configured in the `env file`,
-which is system dependent and which has a bit unintuitive syntax.
-This configuration is processed by the `t4ht` application and conversion
-commands are called for all pictures.
+: the output directory
-It is possible to disable `t4ht` image processing and configure image
-conversion in the build file:
+`correct_exit`
- Make:image("png$",
- "dvipng -bg Transparent -T tight -o ${output} -pp ${page} ${source}")
+: expected `exit code` from the command. The compilation will be terminated
+ if the exit code of the executed command has a different value.
-`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 a table with parameters as an argument.
+# Configuration file {#configfile}
-There are three parameters:
+It is possible to globally modify the build settings using the configuration
+file. It is a special version of a build file where the global settings can be set.
- - `output` - output image file name
- - `source` - `dvi` file with the pictures
- - `page` - page number of the converted image
+Common tasks for the configuration file can be a declaration of the new commands,
+loading of the default filters or specification of a default build sequence.
-## The `mode` variable
+One additional functionality not available in the build files are commands for
+enabling and disabling of extensions.
-There is global `mode` variable available in the build file. It contains
-contents of the `--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
+## Location
-In this example (which is the default configuration used by `make4ht`),
-LaTeX is called only once when `make4ht` is called with `draft` mode:
-
- make4ht -m draft filename
+The configuration file can be saved either in the
+`$HOME/.config/make4ht/config.lua` file, or in the `.make4ht` file placed in
+the current directory or it's parent directories (up to the `$HOME` directory).
-## The `settings` table
+## Additional commands
-You may want to access to the parameters also outside commands, file matches
-and image conversion functions. For example, if you want to convert your file to
-the `OpenDocument Format (ODT)`, you can use the following settings, based on the `oolatex`
-command:
+There are two additional commands:
- 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 "
+`Make:enable_extension(name)`
-There are some functions to ease access to the settings:
+: require extension
-`set_settings{parameters}`
+`Make:disable_extension(name)`
-: overwrite settings with values from a passed table
+: disable extension
-`settings_add{parameters}`
+## Example
-: add values to the current settings
+The following example of the configuration file adds support for the `biber` command, requires
+`common_domfilters` extension and requires MathML
+output for math.
-`filter_settings "filter name" {parameters}`
+ Make:add("biber", "biber ${input}")
+ Make:enable_extension "common_domfilters"
+ settings_add {
+ tex4ht_sty_par =",mathml"
+ }
-: set settings for a filter
+<!--
+# Development
-`get_filter_settings(name)`
+## Custom filters
-: get settings for a filter
+## New extensions
+## How to add a new output format
-Using these functions, it is possible to simplify the settings for the `ODT` format:
+-->
- settings_add {
- tex4ht_sty_par =",ooffice",
- tex4ht_par = " ooffice/! -cmozhtf",
- t4ht_par = " -cooxtpipes -coo "
- }
+# List of available settings for filters and extensions.
-Settings for filters and extensions can be set using `filter_settings`:
+These settings may be set using `filter_settings` function in a build file or in the `make4ht` configuration file.
-
- filter_settings "test" {
- hello = "world"
- }
-These settings can be read in the extensions and filters using `get_filter_settings`:
- function test(input)
- local options = get_filter_settings("test")
- print(options.hello)
- return input
- end
-
-## List of available settings for filters and extensions.
+## Indexing commands
+
+The indexing commands (like `xindy` or `makeindex`) use some common settings.
+
+idxfile
+
+: name of the `.idx` file. Default value is `\jobname.idx`.
+
+indfile
+
+: name of the `.ind` file. Default value is the same as `idxfile` with the file extension changed to `.ind`.
+
+Each indexing command can have some additional settings.
+
+### The `xindy` command
+
+encoding
+
+: text encoding of the `.idx` file. Default value is `utf8`.
+
+language
+
+: index language. Default language is English.
+
+modules
+
+: table with names of additional `Xindy` modules to be used.
+
+### The `makeindex` command
+
+options
-These settings may be set using `filter_settings` function.
-### The `tidy` extension
+: additional command line options for the Makeindex command.
+
+### The `xindex` command
+
+options
+
+
+: additional command line options for the Xindex command.
+
+language
+
+: document language
+
+## The `tidy` extension
options
: command line options for the `tidy` command. Default value is `-m -utf8 -w 512 -q`.
-### The `fixinlines` dom filter
+## The `collapsetoc` dom filter
+
+`toc_query`
+
+: CSS selector for selecting the table of contents container.
+
+`title_query`
+
+: CSS selector for selecting all elements that contain the section ID attribute.
+
+`toc_levels`
+
+: table containing a hierarchy of classes used in TOC
+
+Default values:
+
+ filter_settings "collapsetoc" {
+ toc_query = ".tableofcontents",
+ title_query = ".partHead a, .chapterHead a, .sectionHead a, .subsectionHead a",
+ toc_levels = {"partToc", "chapterToc", "sectionToc", "subsectionToc", "subsubsectionToc"}
+ }
+
+## The `fixinlines` dom filter
inline\_elements
-: table of inline elements which shouldn't be direct descendants of the `body` element. The element names should be table keys, the values should be true.
+: table of inline elements that shouldn't be direct descendants of the `body` element. The element names should be table keys, the values should be true.
Example
filter_settings "fixinlines" {inline_elements = {a = true, b = true}}
-### The `joincharacters` dom filter
+## The `joincharacters` dom filter
-charelements
+charclasses
-: table of elements which should be joined if several instances with the same value of `class` attribute are side by side.
+: table of elements that should be concatenated when two or more of such elements with the same value of the `class` attribute are placed one after another.
Example
- filter_settings "joincharacters" { charclases = { span=true, mn = true}}
+ filter_settings "joincharacters" { charclasses = { span=true, mn = true}}
-### The `mathjaxnode` filter {#mathjaxsettings}
+## The `mathjaxnode` filter {#mathjaxsettings}
options
@@ -746,12 +938,12 @@ Example
cssfilename
-: `mjpage` puts some CSS code into the HTML pages. `mathjaxnode` extracts this information and saves it to a standalone CSS file. Default CSS filename is `mathjax-chtml.css`
+: the `mjpage` command puts some CSS code into the HTML pages. `mathjaxnode` extracts this information and saves it to a standalone CSS file. Default CSS filename is `mathjax-chtml.css`
fontdir
-: directory with MathJax font files. This option enables use of local fonts, which
- is usefull in Epub conversion, for example. The font directory should be
+: directory with MathJax font files. This option enables the use of local fonts, which
+ is useful in the conversion to ePub, for example. The font directory should be
sub-directory of the current directory. Only TeX font is supported at the moment.
Example
@@ -761,21 +953,8 @@ Example
fontdir="fonts/TeX/woff/"
}
-### The `aeneas` filter
-
-skip\_elements
-
-: List of CSS selectors that match elements which shouldn't be processed. Default value: `{ "math", "svg"}`.
-
-id\_prefix
-
-: prefix used in the ID attribute forming.
-
-sentence\_match
-
-: Lua pattern used to match a sentence. Default value: `"([^%.^%?^!]*)([%.%?!]?)"`.
-### The `staticsite` filter and extension
+## The `staticsite` filter and extension
site\_root
@@ -783,15 +962,22 @@ site\_root
map
-: table where keys are patterns that match filenames, value contains destination directoryfor matched files, relative to the `site_root` (it is possible to use `..` to swich to parent directory).
+: a hash table where keys contain patterns that match filenames and values contain
+destination directory for the matched files. The destination directories are
+relative to the `site_root` (it is possible to use `..` to switch to a parent
+directory).
file\_pattern
-: pattern used for filename generation. It is possible to use string templates and format strings for `os.date` function. Default value of `%Y-%m-%d-${input}` creates names in the form of `YYYY-MM-DD-file_name`.
+: a pattern used for filename generation. It is possible to use string templates
+and format strings for `os.date` function. The default pattern `%Y-%m-%d-${input}`
+creates names in the form of `YYYY-MM-DD-file_name`.
header
-: table with variables to be set in the YAML header in HTML files. If the table value is a function, it is executed with current parameters and HTML page DOM object as arguments.
+: table with variables to be set in the YAML header in HTML files. If the
+table value is a function, it is executed with current parameters and HTML page
+DOM object as arguments.
Example:
@@ -811,7 +997,7 @@ Example:
}
}
-### The `dvisvgm_hashes` extension
+## The `dvisvgm_hashes` extension
options
@@ -819,108 +1005,182 @@ options
cpu_cnt
-: number of processor cores used for conversion. The extension tries to detect the available cores automatically by default.
+: the number of processor cores used for the conversion. The extension tries to detect the available cores automatically by default.
parallel_size
-: number of pages used in each Dvisvgm call. The extension detects changed pages in the DVI file and construct multiple calls to Dvisvgm with only changed pages.
+: the number of pages used in each Dvisvgm call. The extension detects changed
+pages in the DVI file and constructs multiple calls to Dvisvgm with only changed
+pages.
scale
: SVG scaling.
-### The `odttemplate` filter and extension
+## The `odttemplate` filter and extension
template
: filename of the template `ODT` file
-`odttemplate` can also get the template filename from the `odttemplate` option from `tex4ht_sty_par` parameter. It can be set useing following command line call, for example:
+`odttemplate` can also get the template filename from the `odttemplate` option from `tex4ht_sty_par` parameter. It can be set using the following command line call:
make4ht -f odt+odttemplate filename.tex "odttemplate=template.odt"
+## The `aeneas` filter
+skip\_elements
-# Configuration file {#configfile}
+: List of CSS selectors that match elements that shouldn't be processed. Default value: `{ "math", "svg"}`.
-It is possible to globally modify the build settings using the configuration
-file. New compilation commands can be added, extensions can be loaded or
-disabled and settings can be set.
+id\_prefix
-## Location
+: prefix used in the ID attribute forming.
-The configuration file can be saved either in
-`$HOME/.config/make4ht/config.lua` or in `.make4ht` in the current directory or
-it's parents (up to `$HOME`).
+sentence\_match
-## Additional commands
+: Lua pattern used to match a sentence. Default value: `"([^%.^%?^!]*)([%.%?!]?)"`.
-There are two additional commands:
+## The `make4ht-aeneas-config` package
-`Make:enable_extension(name)`
+Companion for the `aeneas` DOM filter is the `make4ht-aeneas-config` plugin. It
+can be used to write the Aeneas configuration file or execute Aeneas on the
+generated HTML files.
-: require extension
+Available functions:
-`Make:disable_extension(name)`
+write\_job(parameters)
-: disable extension
+: write Aenas job configuration to `config.xml` file. See the [Aeneas
+ documentation](https://www.readbeyond.it/aeneas/docs/clitutorial.html#processing-jobs)
+ for more information about jobs.
-## Example
+execute(parameters)
-The following configuration add support for the `biber` command, requires
-`common_domfilters` extension and requires MathML
-output for math.
+: execute Aeneas.
- Make:add("biber", "biber ${input}")
- Make:enable_extension "common_domfilters"
- settings_add {
- tex4ht_sty_par =",mathml"
+process\_files(parameters)
+
+: process the audio and generated subtitle files.
+
+
+By default, a `SMIL` file is created. It is assumed that there is an audio file
+in the `mp3` format, named as the \TeX\ file. It is possible to use different formats
+and filenames using mapping.
+
+The configuration options can be passed directly to the functions or set using
+`filter_settings "aeneas-config" {parameters}` function.
+
+
+### Available parameters
+
+
+lang
+
+: document language. It is interfered from the HTML file, so it is not necessary to set it.
+
+map
+
+: mapping between HTML, audio and subtitle files. More info below.
+
+text\_type
+
+: type of input. The `aeneas` DOM filter produces an `unparsed` text type.
+
+id\_sort
+
+: sorting of id attributes. The default value is `numeric`.
+
+id\_regex
+
+: regular expression to parse the id attributes.
+
+sub\_format
+
+: generated subtitle format. The default value is `smil`.
+
+
+### Additional parameters for the job configuration file
+
+- description
+- prefix
+- config\_name
+- keep\_config
+
+
+
+It is possible to generate multiple HTML files from the \LaTeX\ source. For
+example, `tex4ebook` generates a separate file for each chapter or section. It is
+possible to set options for each HTML file, in particular names of the
+corresponding audio files. This mapping is done using the `map` parameter.
+
+Example:
+
+ filter_settings "aeneas-config" {
+ map = {
+ ["sampleli1.html"] = {audio_file="sample.mp3"},
+ ["sample.html"] = false
+ }
}
-# Command line options
+Table keys are the configured filenames. It is necessary to insert them as
+`["filename.html"]`, because of Lua syntax rules.
- 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
- -f,--format (default nil) Output file format
- -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
- -v,--version Print version number
- -x,--xetex Use xelatex for document compilation
- <filename> (string) Input file name
+This example maps audio file `sample.mp3` to a section subpage. The main HTML
+file, which may contain title and table of contents doesn't have a
+corresponding audio file.
+
+Filenames of the subfiles correspond to the chapter numbers, so they are not
+stable when a new chapter is added. It is possible to request filenames
+derived from the chapter titles using the `sec-filename` option for `tex4ht.sty`.
+### Available `map` options
-You can still invoke `make4ht` in the same way as `htlatex`:
- make4ht filename "customcfg, charset=utf-8" "-cunihtf -utf8" "-dfoo"
+audio\_file
-Note that this will not use `make4ht` routines for output directory making and
-copying. If you want to use them, change the line above to:
+: the corresponding audio file
- make4ht -d foo filename "customcfg, charset=utf-8" "-cunihtf -utf8"
+sub\_file
-This call has the same effect as the following:
+: name of the generated subtitle file
+
+The following options are the same as their counterparts from the main parameters table and generally, don't need to be set:
+
+- prefix
+- file\_desc
+- file\_id
+- text\_type
+- id\_sort
+- id\_prefix
+- sub\_format
+
+
+### Full example
+
+
+ local domfilter = require "make4ht-domfilter"
+ local aeneas_config = require "make4ht-aeneas-config"
+
+ filter_settings "aeneas-config" {
+ map = {
+ ["krecekli1.xhtml"] = {audio_file="krecek.mp3"},
+ ["krecek.xhtml"] = false
+ }
+ }
+
+ local process = domfilter {"aeneas"}
+ Make:match("html$", process)
+
+ if mode == "draft" then
+ aeneas_config.process_files {}
+ else
+ aeneas_config.execute {}
+ end
- 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
# Troubleshooting
@@ -932,24 +1192,26 @@ Sometimes, you may get a similar error:
It may be caused by a following `make4ht` invocation:
- make4ht hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8" -d foo
+ $ make4ht hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8" -d foo
The command line option parser is confused by mixing options for `make4ht` and
-`tex4ht` in this case and tries to interpret the `-cunihtf -utf8`, which are
-options for `tex4ht` command as `make4ht` options. To fix that, you can either
-move the `-d foo` directly after `make4ht` command:
+\TeX4ht\ in this case. It tries to interpret the `-cunihtf -utf8`, which are
+options for the `tex4ht` command, as `make4ht` options. To fix that, try to
+move the `-d foo` directly after the `make4ht` command:
- make4ht -d foo hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8"
+ $ make4ht -d foo hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8"
-Another option is to add a space before `tex4ht` options:
+Another option is to add a space before the `tex4ht` options:
- make4ht hello.tex "customcfg,charset=utf-8" " -cunihtf -utf8" -d foo
+ $ make4ht hello.tex "customcfg,charset=utf-8" " -cunihtf -utf8" -d foo
The former way is preferable, though.
## Filenames containing spaces
-`tex4ht` cannot handle filenames containing spaces. `make4ht` thus replaces spaces in input file names with underscores, so generated XML files use underscores instead of spaces as well.
+`tex4ht` command cannot handle filenames containing spaces. to fix this issue, `make4ht`
+replaces spaces in the input filenames with underscores. The generated
+XML filenames use underscores instead of spaces as well.
## Filenames containing non-ASCII characters
diff --git a/support/make4ht/changelog.tex b/support/make4ht/changelog.tex
index 8d46424dec..f2b0fd7735 100644
--- a/support/make4ht/changelog.tex
+++ b/support/make4ht/changelog.tex
@@ -3,6 +3,262 @@
\begin{itemize}
\item
+ 2019/11/01
+
+ \begin{itemize}
+ \tightlist
+ \item
+ version 0.3 released
+ \item
+ added \texttt{Make:makeindex}, \texttt{Make:xindex} and
+ \texttt{Make:bibtex} commands.
+ \end{itemize}
+\item
+ 2019/10/25
+
+ \begin{itemize}
+ \tightlist
+ \item
+ modified the \texttt{Make:xindy} command to use the indexing
+ mechanism.
+ \end{itemize}
+\item
+ 2019/10/24
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added functions for preparing and cleaning of the index files in
+ \texttt{make4ht-indexing.lua}.
+ \end{itemize}
+\item
+ 2019/10/23
+
+ \begin{itemize}
+ \tightlist
+ \item
+ replaced \texttt{os.execute} function with \texttt{mkutils.execute}.
+ It uses the logging mechanism for the output.
+ \item
+ finished transforming of filters, extensions and formats to the
+ logging system.
+ \end{itemize}
+\item
+ 2019/10/22
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added \texttt{tablerows} domfilter.
+ \item
+ added the \texttt{tablerows} domfilter to the
+ \texttt{common\_domfilters} extension.
+ \item
+ converted most of the filters to use the logging mechanism.
+ \end{itemize}
+\item
+ 2019/10/20
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added \texttt{status} log level.
+ \end{itemize}
+\item
+ 2019/10/18
+
+ \begin{itemize}
+ \tightlist
+ \item
+ converted most print commands to use the logging mechanism.
+ \item
+ added \texttt{output} log level used for printing of the commands
+ output.
+ \end{itemize}
+\item
+ 2019/10/17
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added \texttt{-\/-loglevel} CLI parameter.
+ \item
+ added logging mechanism.
+ \item
+ moved \texttt{htlatex} related code to \texttt{make4ht-htlatex.lua}
+ from \texttt{mkutils.lua}
+ \end{itemize}
+\item
+ 2019/10/11
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added \texttt{xindy} settings.
+ \item
+ added simple regular expression to detect errors in the log file,
+ because log parsing can be slow.
+ \end{itemize}
+\item
+ 2019/10/09
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added the \texttt{interaction} parameter for the \texttt{htlatex}
+ command. The default value is \texttt{batchmode} to suppress the
+ user input on errors, and to suppress full log output to the
+ terminal.
+ \item
+ added the \texttt{make4ht-errorlogparser} module. It is used to
+ parse errors in the \texttt{htlatex} run unless \texttt{interaction}
+ is set to \texttt{errorstopmode}.
+ \end{itemize}
+\item
+ 2019/10/08
+
+ \begin{itemize}
+ \tightlist
+ \item
+ set up Github Actions pipeline to compile the documentation to HTML
+ and publish it at https://www.kodymirus.cz/make4ht/make4ht-doc.html.
+ \end{itemize}
+\item
+ 2019/10/07
+
+ \begin{itemize}
+ \tightlist
+ \item
+ don't move the \texttt{common\_domfilters} extension to the first
+ place in the file matches pipeline. We may want to run \texttt{tidy}
+ or regex filters first, to fix XML validation errors.
+ \end{itemize}
+\item
+ 2019/10/04
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added HTML documentation.
+ \end{itemize}
+\item
+ 2019/09/27
+
+ \begin{itemize}
+ \tightlist
+ \item
+ don't convert Latin 1 entities to Unicode in the
+ \texttt{entities\_to\_unicode} extension.
+ \end{itemize}
+\item
+ 2019/09/20
+
+ \begin{itemize}
+ \tightlist
+ \item
+ fixed bugs in the temporary directory handling for the ODT output.
+ \end{itemize}
+\item
+ 2019/09/13
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added \texttt{preprocess\_input} extension. It enables compilation
+ of formats supported by \href{https://yihui.name/knitr/}{Knitr}
+ (\texttt{.Rnw}, \texttt{.Rtex}, \texttt{.Rmd}, \texttt{.Rrst}) and
+ also Markdown and reStructuredText formats.
+ \end{itemize}
+\item
+ 2019/09/12
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for the ODT files in \texttt{common\_domfilters}
+ extension.
+ \item
+ renamed \texttt{charclases} option for the \texttt{joincharacters}
+ DOM filter to \texttt{charclasses}.
+ \item
+ don't execute the \texttt{fixentities} filter before Xtpipes, it
+ makes no sense.
+ \end{itemize}
+\item
+ 2019/09/11
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for Biber in the build files.
+ \end{itemize}
+\item
+ 2019/08/28
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for input from \texttt{stdin}.
+ \end{itemize}
+\item
+ 2019/08/27
+
+ \begin{itemize}
+ \tightlist
+ \item
+ fixed \texttt{-jobname} detection regex.
+ \item
+ added function \texttt{handle\_jobname}.
+ \item
+ added the \texttt{-\/-jobname} command line option.
+ \end{itemize}
+\item
+ 2019/08/26
+
+ \begin{itemize}
+ \tightlist
+ \item
+ quote file names and paths in \texttt{xtpipes} and \texttt{tidy}
+ invocation.
+ \end{itemize}
+\item
+ 2019/08/25
+
+ \begin{itemize}
+ \tightlist
+ \item
+ the issue tracker link in the help message is now configurable.
+ \item
+ fixed bug in the XeTeX handling: the \texttt{.xdv} argument for
+ \texttt{tex4ht} wasn't used if command line arguments for
+ \texttt{tex4ht} were present.
+ \end{itemize}
+\item
+ 2019/07/03
+
+ \begin{itemize}
+ \tightlist
+ \item
+ new DOM filter: \texttt{odtpartable}. It fixes tables nested in
+ paragraphs in the ODT format.
+ \end{itemize}
+\item
+ 2019/06/13
+
+ \begin{itemize}
+ \tightlist
+ \item
+ new DOM extension: \texttt{collapsetoc}.
+ \end{itemize}
+\item
+ 2019/05/29
+
+ \begin{itemize}
+ \tightlist
+ \item
+ new module: \texttt{make4ht-indexing} for working with index files.
+ \end{itemize}
+\item
2019/05/24
\begin{itemize}
@@ -18,7 +274,7 @@
\begin{itemize}
\tightlist
\item
- fixed infinite loop bug in the \texttt{dvisvgm\_hashes} extension
+ fixed infinite loop bug in the \texttt{dvisvgm\_hashes} extension.
\end{itemize}
\item
2019/04/09
diff --git a/support/make4ht/domfilters/make4ht-aeneas.lua b/support/make4ht/domfilters/make4ht-aeneas.lua
index 0b93c95840..4a21c89332 100644
--- a/support/make4ht/domfilters/make4ht-aeneas.lua
+++ b/support/make4ht/domfilters/make4ht-aeneas.lua
@@ -5,6 +5,7 @@
--
local cssquery = require "luaxml-cssquery"
local mkutils = require "mkutils"
+local log = logging.new "aeneas"
-- Table of CSS selectors to be skipped.
local skip_elements = { "math", "svg"}
@@ -111,7 +112,7 @@ local function aeneas(dom, par)
then
local idtitle
idtitle, id = make_id(id, id_prefix)
- print(el._name, first_child._text)
+ log:debug(el._name, first_child._text)
el:set_attribute("id", idtitle)
return el
end
diff --git a/support/make4ht/domfilters/make4ht-collapsetoc.lua b/support/make4ht/domfilters/make4ht-collapsetoc.lua
new file mode 100644
index 0000000000..0b77b9dbbb
--- /dev/null
+++ b/support/make4ht/domfilters/make4ht-collapsetoc.lua
@@ -0,0 +1,198 @@
+local domobject = require "luaxml-domobject"
+
+local filter = require "make4ht-filter"
+local log = logging.new "collapsetoc"
+
+
+local toc_levels = {"partToc", "chapterToc", "sectionToc", "subsectionToc", "subsubsectionToc"}
+
+local debug_print = function(...) log:debug(...) end
+
+
+-- return toc element type and it's id
+local function get_id(el)
+ local name = el:get_attribute "class"
+ local id
+ local a = el:query_selector "a" or {}
+ local first = a[1]
+ if first then
+ local href = first:get_attribute "href"
+ id = href:match("#(.+)$")
+ end
+ return name, id
+end
+
+local function remove_sections(part_elements, currentpart)
+ -- we need to remove toc entries from the previous part if the
+ -- current document isn't part of it
+ if currentpart == false then
+ for _, part in ipairs(part_elements) do
+ part:remove_node()
+ end
+ end
+end
+
+local function make_toc_selector(toc_levels)
+ local level_classes = {}
+ for _, l in ipairs(toc_levels) do
+ level_classes[#level_classes+1] = "." .. l
+ end
+ return table.concat(level_classes, ", ")
+end
+
+local function find_toc_levels(toc)
+ -- find toc levels used in the document
+ -- it ecpects that sectioning levels appears in the TOC in the descending order
+ local levels, used = {}, {}
+ local level = 1
+ -- we still expect the standard class names
+ local toc_selector = make_toc_selector(toc_levels)
+ for _, el in ipairs(toc:query_selector(toc_selector)) do
+ local class = el:get_attribute("class")
+ if not used[class] then
+ table.insert(levels, class)
+ used[class] = level
+ level = level + 1
+ end
+ end
+ return levels, used
+end
+
+local function remove_levels(toc, matched_ids)
+ -- sort the matched sections according to their levels
+ local levels, level_numbers = find_toc_levels(toc)
+ debug_print("remove levels", #levels)
+ -- for _, level in ipairs(levels) do
+ -- print(level, level_numbers[level], matched_ids[level])
+ -- end
+ local keep_branch = false
+ local matched_levels = {}
+ local toc_selector = make_toc_selector(toc_levels)
+ for _, el in ipairs(toc:query_selector(toc_selector)) do
+ local name, id = get_id(el)
+ -- get the current toc hiearchy level
+ local level = level_numbers[name]
+ -- get the matched id for the current level
+ local level_id = matched_ids[name]
+ local matched = level_id == id
+ local remove = true
+ -- we will use this for toc elements at lower hiearchy than is the top sectioning level on the page
+ if matched then keep_branch = true end
+ -- find the parent level to the current section level
+ local parent_level = toc_levels[level - 1]
+ local parent_matched = matched_levels[parent_level]
+ if matched then
+ debug_print("match",name, id, level_id, level, #levels)
+ keep_branch = true
+ remove = false
+ elseif level==1 then
+ -- don't remove the top level
+ debug_print("part",name, id, level_id, level)
+ remove = false
+ matched_levels = {}
+ if not matched then keep_branch = false end
+ elseif keep_branch then
+ -- if level >= (#levels - 1) then
+ if level > matched_ids._levels then
+ debug_print("level",name, id, level_id, level, parent_level, parent_matched)
+ remove = false
+ elseif matched_ids.ids[id] then
+ debug_print("matched id",name, id, level_id, level, parent_level, parent_matched)
+ remove = false
+ elseif parent_matched then
+ debug_print("parent_matched",name, id, level_id, level, parent_level, parent_matched)
+ keep_branch = false
+ remove = false
+ end
+ -- else
+ -- print("remove", name, id, level_id, level, #matched_ids)
+ -- end
+ elseif parent_matched then
+ debug_print("parent_matched alternative",name, id, level_id, level, parent_level, parent_matched)
+ remove = false
+ else
+ debug_print("else",name, id, level_id, level, keep_branch)
+ keep_branch = false
+ end
+ matched_levels[name] = matched
+ if remove then
+ el:remove_node()
+ --print(name,id, level_id, matched)
+ end
+ end
+
+end
+
+
+
+
+
+-- local process = filter{ function(s)
+ -- local dom = domobject.parse(s)
+local function collapse_toc(dom, par)
+ -- set options
+ local options = get_filter_settings "collapsetoc"
+ local toc_query = par.toc_query or options.toc_query or ".tableofcontents"
+ local title_query = par.title_query or options.title_query or ".partHead a, .chapterHead a, .sectionHead a, .subsectionHead a"
+ toc_levels = par.toc_levels or options.toc_levels or toc_levels
+ -- keep track of current id of each sectioning level
+ local current_ids, matched_ids = {}, {_levels = 0, ids = {}}
+ -- search sectioning elements
+ local titles = dom:query_selector(title_query)
+ local section_ids = {}
+ for _, x in ipairs(titles) do
+ -- get their id attributes and save them in a table
+ section_ids[#section_ids+1] = x:get_attribute("id")
+ end
+
+ -- we need to retrieve the first table of contents
+ local toctables = dom:query_selector(toc_query) or {}
+ -- process only when we got a TOC
+ debug_print("toc query", toc_query, #toctables)
+ if #toctables > 0 then
+ local tableofcontents = toctables[1]
+ -- all toc entries are in span elements
+ local toc = tableofcontents:query_selector("span")
+ local currentpart = false
+ local part_elements = {}
+ for _, el in ipairs(toc) do
+ -- get sectioning level and id of the current TOC entry
+ local name, id = get_id(el)
+ -- set the id of the current sectioning level
+ current_ids[name] = id
+ for _, sectid in ipairs(section_ids) do
+ -- detect if the current TOC entry match some sectioning element in the current document
+ if id == sectid then
+ currentpart = true
+ -- save the current id as a matched id
+ matched_ids.ids[id] = true
+ -- copy the TOC hiearchy for the current toc level
+ for i, level in ipairs(toc_levels) do
+ -- print("xxx",i, level, current_ids[level])
+ matched_ids[level] = current_ids[level]
+ -- set the maximum matched level
+ if i > matched_ids._levels then matched_ids._levels = i end
+ if level == name then break end
+ end
+ debug_print("match", id)
+ end
+ end
+ end
+ remove_levels(tableofcontents, matched_ids)
+
+ -- remove sections from the last part
+ -- remove_sections(part_elements,currentpart)
+ -- remove unneeded br elements
+ local br = tableofcontents:query_selector("br")
+ for _, el in ipairs(br) do el:remove_node() end
+ -- remove unneded whitespace
+ for _, el in ipairs(tableofcontents:get_children()) do
+ if el:is_text() then el:remove_node() end
+ end
+ end
+ return dom
+end
+
+return collapse_toc
+
+-- Make:match("html$", process)
diff --git a/support/make4ht/domfilters/make4ht-joincharacters.lua b/support/make4ht/domfilters/make4ht-joincharacters.lua
index 99d3058d7d..30ed6e1382 100644
--- a/support/make4ht/domfilters/make4ht-joincharacters.lua
+++ b/support/make4ht/domfilters/make4ht-joincharacters.lua
@@ -1,4 +1,4 @@
-local charclases = {
+local charclasses = {
span=true,
mn = true,
}
@@ -8,7 +8,7 @@ local function join_characters(obj,par)
-- tex4ht to just one object.
local par = par or {}
local options = get_filter_settings "joincharacters"
- local charclases = options.charclases or par.charclases or charclases
+ local charclasses = options.charclasses or par.charclasses or charclasses
obj:traverse_elements(function(el)
local get_name = function(curr)
@@ -18,7 +18,7 @@ local function join_characters(obj,par)
return next_el:get_attribute("class")
end
local is_span = function(next_el)
- return charclases[get_name(next_el)]
+ return charclasses[get_name(next_el)]
end
local function get_next(curr, class)
@@ -33,7 +33,7 @@ local function join_characters(obj,par)
end
end
-- loop over all elements and test if the current element is in a list of
- -- processed elements (charclases)
+ -- processed elements (charclasses)
if is_span(el) then
local next_el = get_next(el)
-- loop over the following elements and test whether they are of the same type
diff --git a/support/make4ht/domfilters/make4ht-joincolors.lua b/support/make4ht/domfilters/make4ht-joincolors.lua
index 94a3a054e6..730f66a7a0 100644
--- a/support/make4ht/domfilters/make4ht-joincolors.lua
+++ b/support/make4ht/domfilters/make4ht-joincolors.lua
@@ -1,4 +1,5 @@
local cssfiles = {}
+local log = logging.new "joincolors"
-- keep mapping between span ids and colors
@@ -45,7 +46,7 @@ local function process_css_files(dom)
for _, el in ipairs(dom:query_selector("link")) do
local href = el:get_attribute("href") or ""
if not cssfiles[href] and href:match("css$") then
- print("Load CSS file ", href)
+ log:debug("Load CSS file ", href)
cssfiles[href] = true
process_css(href)
end
diff --git a/support/make4ht/domfilters/make4ht-odtimagesize.lua b/support/make4ht/domfilters/make4ht-odtimagesize.lua
index 4ce8f0d92e..2b87372fdb 100644
--- a/support/make4ht/domfilters/make4ht-odtimagesize.lua
+++ b/support/make4ht/domfilters/make4ht-odtimagesize.lua
@@ -1,3 +1,4 @@
+local log = logging.new "odtimagesize"
-- set correct dimensions to frames around images
return function(dom)
local frames = dom:query_selector("draw|frame")
@@ -9,7 +10,7 @@ return function(dom)
local height = image:get_attribute("svg:height")
if widht then frame:set_attribute("svg:width", width) end
if height then frame:set_attribute("svg:height", height) end
- print("image dimensions", width, height)
+ log:debug("image dimensions", width, height)
end
end
return dom
diff --git a/support/make4ht/domfilters/make4ht-odtpartable.lua b/support/make4ht/domfilters/make4ht-odtpartable.lua
new file mode 100644
index 0000000000..f4e84b55d9
--- /dev/null
+++ b/support/make4ht/domfilters/make4ht-odtpartable.lua
@@ -0,0 +1,9 @@
+-- find all tables inside paragraphs, replace the found paragraphs with the child table
+return function(dom)
+ for _,table in ipairs(dom:query_selector("text|p table|table")) do
+ -- replace the paragraph by its child element
+ local parent = table:get_parent()
+ parent:replace_node(table)
+ end
+ return dom
+end
diff --git a/support/make4ht/domfilters/make4ht-tablerows.lua b/support/make4ht/domfilters/make4ht-tablerows.lua
new file mode 100644
index 0000000000..155c24529a
--- /dev/null
+++ b/support/make4ht/domfilters/make4ht-tablerows.lua
@@ -0,0 +1,58 @@
+local log = logging.new ("tablerows")
+return function(dom)
+ local is_empty_row = function(row)
+ local not_empty = false
+ local element_count = 0
+ -- ignore hline rows
+ local row_class = row:get_attribute("class")
+ if row_class == "hline" or row_class == "cline" then return false end
+ -- detect if the row contain only one empty child
+ for _,child in ipairs(row:get_children() or {}) do
+ if child:is_element() then
+ element_count = element_count + 1
+ -- empty rows contain only one element, it is not empty otherwise
+ if element_count > 1 then return false end
+ -- detect if it contains only whitespace
+ not_empty = child:get_text():gsub("%s","") ~= "" or not_empty
+ end
+ end
+ -- print("element count", element_count, not_empty)
+ return element_count == 1 and not_empty == false
+ end
+ local is_not_styled = function(row, css)
+ -- get the id attribute and escape it, so it can be used in regexp
+ local id = row:get_attribute("id")
+ if not id then return true end -- no styling without id
+ local search_term = "%#" .. id:gsub("%-", "%%-")
+ -- if the CSS file contains the row id (<td> elements can also have id
+ -- that matches this pattern, so we should keep the row if we match them too)
+ return not css:match(search_term)
+ end
+ local load_css_files = function()
+ -- the empty rows can be styled using CSS, for example configuration for
+ -- Booktabs does that. We shouldn't remove such rows.
+ local cssfiles = {}
+ for _, link in ipairs(dom:query_selector("head link")) do
+ local src = link:get_attribute("href")
+ if src then
+ local f = io.open(src, "r")
+ if f then
+ local contents = f:read("*all")
+ f:close()
+ table.insert(cssfiles, contents)
+ end
+ end
+ end
+ return table.concat(cssfiles, "\n")
+ end
+ local css = load_css_files()
+ for _, tbl in ipairs(dom:query_selector("table")) do
+ -- find the empty rows
+ for _, row in ipairs(tbl:query_selector("tr")) do
+ if is_empty_row(row) and is_not_styled(row, css) then row:remove_node() end
+ end
+
+ end
+ return dom
+end
+
diff --git a/support/make4ht/extensions/common_domfilters.lua b/support/make4ht/extensions/common_domfilters.lua
index 7c9a2dfaea..9399492d90 100644
--- a/support/make4ht/extensions/common_domfilters.lua
+++ b/support/make4ht/extensions/common_domfilters.lua
@@ -1,25 +1,34 @@
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)
- if format == "odt" then return false end
+ current_format = format
+ -- if format == "odt" then return false end
return true
end
function M.modify_build(make)
- local process = filter {"fixinlines", "idcolons", "joincharacters"}
- 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
+ -- 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
diff --git a/support/make4ht/extensions/dvisvgm_hashes.lua b/support/make4ht/extensions/dvisvgm_hashes.lua
index 83010ac388..87f58abd57 100644
--- a/support/make4ht/extensions/dvisvgm_hashes.lua
+++ b/support/make4ht/extensions/dvisvgm_hashes.lua
@@ -1,6 +1,7 @@
local dvireader = require "make4ht-dvireader"
local mkutils = require "mkutils"
local filter = require "make4ht-filter"
+local log = logging.new "dvisvgm_hashes"
local dvisvgm_par = {}
@@ -149,7 +150,7 @@ 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)
- print(command)
+ log:info(command)
os.execute(command)
local generated_pages = {}
for _, dvisvgmlog in ipairs(logs) do
@@ -184,7 +185,7 @@ local function get_dvi_pages(arg)
local output_name = make_hashed_name(arg.input, hash)
output_map[tex4ht_name] = output_name
if not mkutils.file_exists(output_name) then
- print(output_name)
+ log:debug("output file: ".. output_name)
to_convert[#to_convert+1] = page
end
end
@@ -246,7 +247,7 @@ function M.modify_build(make)
function(str)
return str:gsub('src="([^"]+)', function(filename)
local newname = output_map[filename] or filename
- print("newname", newname)
+ log:debug("newname", newname)
return 'src="'.. newname
end)
end
diff --git a/support/make4ht/extensions/preprocess_input.lua b/support/make4ht/extensions/preprocess_input.lua
new file mode 100644
index 0000000000..3155a8a781
--- /dev/null
+++ b/support/make4ht/extensions/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/support/make4ht/extensions/staticsite.lua b/support/make4ht/extensions/staticsite.lua
index fcb6c09e17..a4204bc173 100644
--- a/support/make4ht/extensions/staticsite.lua
+++ b/support/make4ht/extensions/staticsite.lua
@@ -1,6 +1,7 @@
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)
@@ -15,7 +16,7 @@ local function get_slug(settings)
local f = io.open(published_name, "r")
local readtime = f:read("*line")
time = tonumber(readtime)
- print("Already pubslished", slug)
+ log:info("Already pubslished", slug)
f:close()
else
-- escape
diff --git a/support/make4ht/extensions/tidy.lua b/support/make4ht/extensions/tidy.lua
index cf8ea9785a..b381a05a8f 100644
--- a/support/make4ht/extensions/tidy.lua
+++ b/support/make4ht/extensions/tidy.lua
@@ -1,5 +1,6 @@
local M = {}
+local log = logging.new "tidy"
function M.test(format)
if format == "odt" then return false end
return true
@@ -41,7 +42,7 @@ function M.modify_build(make)
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
- print("execute: ".. command)
+ log:info("running tidy: ".. command)
-- os.execute(command)
local run = io.popen(command, "r")
local result = run:read("*all")
diff --git a/support/make4ht/filters/make4ht-domfilter.lua b/support/make4ht/filters/make4ht-domfilter.lua
index 27d9ed871d..f6df769d60 100644
--- a/support/make4ht/filters/make4ht-domfilter.lua
+++ b/support/make4ht/filters/make4ht-domfilter.lua
@@ -1,6 +1,7 @@
local filter_lib = require "make4ht-filterlib"
local dom = require "luaxml-domobject"
local mkutils = require "mkutils"
+local log = logging.new "domfilter"
local function load_filter(filtername)
return require("domfilters.make4ht-"..filtername)
@@ -42,8 +43,8 @@ local function filter(filters, name)
return dom.parse(input)
end)
if not status then
- print("DOM parsing of " .. filename .. " failed:")
- print(domobject)
+ log:warning("DOM parsing of " .. filename .. " failed:")
+ log:warning(domobject)
return nil, "DOM parsing failed"
end
for _,f in pairs(sequence) do
@@ -53,7 +54,7 @@ local function filter(filters, name)
if output then
filter_lib.save_input_file(filename, output)
else
- print("DOM filter failed on ".. filename)
+ log:warning("DOM filter failed on ".. filename)
end
-- mark the filename as processed
processed_files[filename] = true
diff --git a/support/make4ht/filters/make4ht-entities-to-unicode.lua b/support/make4ht/filters/make4ht-entities-to-unicode.lua
index fb921a631a..4bf106a79f 100644
--- a/support/make4ht/filters/make4ht-entities-to-unicode.lua
+++ b/support/make4ht/filters/make4ht-entities-to-unicode.lua
@@ -6,10 +6,12 @@ local disabled = { ["&"] = "&amp;", ["<"] = "&lt;", [">"] = "&gt;"}
return function(content)
local content = content:gsub("%&%#x([A-Fa-f0-9]+);", function(entity)
-- convert hexadecimal entity to Unicode
- local newchar = utfchar(tonumber(entity, 16))
+ local char_number = tonumber(entity, 16)
+ -- fix for non-breaking spaces, LO cannot open file when they are present as Unicode
+ if char_number == 160 then return "&#xA0;" end
+ local newchar = utfchar(char_number)
-- we don't want to break XML validity with forbidden characters
return disabled[newchar] or newchar
end)
- -- the non-breaking space character cause issues in the ODT opening
- return content:gsub(string.char(160), "&#xA0;")
+ return content
end
diff --git a/support/make4ht/filters/make4ht-mathjaxnode.lua b/support/make4ht/filters/make4ht-mathjaxnode.lua
index 2b453e4255..748ecfd483 100644
--- a/support/make4ht/filters/make4ht-mathjaxnode.lua
+++ b/support/make4ht/filters/make4ht-mathjaxnode.lua
@@ -1,4 +1,5 @@
local mkutils = require "mkutils"
+local log = logging.new("mathjaxnode")
-- other possible value is page2svg
local mathnodepath = "mjpage"
-- options for MathJax command
@@ -13,13 +14,13 @@ local cssfilename = "mathjax-chtml.css"
local function compile(text)
local tmpfile = os.tmpname()
- print("Compile using MathJax")
+ log:info("Compile using MathJax")
local command = mathnodepath .. " ".. options .. " > " .. tmpfile
- print(command)
+ log:info(command)
local commandhandle = io.popen(command,"w")
commandhandle:write(text)
commandhandle:close()
- print("Result written to: ".. tmpfile)
+ log:info("Result written to: ".. tmpfile)
local f = io.open(tmpfile)
local content = f:read("*all")
f:close()
@@ -53,7 +54,7 @@ local function use_fonts(css)
if not face:match("url%(") then return face end
-- print(face)
local family, filename = face:match(family_pattern)
- print(family, filename)
+ log:info("use font: ",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)
@@ -89,6 +90,6 @@ return function(text, arguments)
save_css(cssfile, css)
Make:add_file(cssfile)
-- print(css)
- print(cssfile)
+ log:info("CSS file: " .. cssfile)
return newtext
end
diff --git a/support/make4ht/filters/make4ht-staticsite.lua b/support/make4ht/filters/make4ht-staticsite.lua
index 6378f0440a..969d47ecaa 100644
--- a/support/make4ht/filters/make4ht-staticsite.lua
+++ b/support/make4ht/filters/make4ht-staticsite.lua
@@ -1,4 +1,5 @@
local domobj = require "luaxml-domobject"
+local log = logging.new("staticsite")
-- save the header settings in YAML format
local function make_yaml(tbl, level)
local t = {}
@@ -69,7 +70,6 @@ local function get_header(tbl)
end
return function(s,par)
- print(os.getenv "blog_home")
local dom = domobj.parse(s)
local properties = {}
local head = dom:query_selector("head")[1]
@@ -84,7 +84,7 @@ return function(s,par)
properties.styles = styles
local metas = {}
for _, meta in ipairs(head:query_selector("meta")) do
- print(meta:serialize())
+ log:debug("parsed meta: " .. meta:serialize())
table.insert(metas, {charset= meta:get_attribute("charset"), content = meta:get_attribute("content"), property = meta:get_attribute("property"), name = meta:get_attribute("name")})
end
properties.meta = metas
@@ -92,7 +92,7 @@ return function(s,par)
local body = dom:query_selector("body")[1]
- print(get_header(properties))
+ log:debug(get_header(properties))
-- return s
return get_header(properties) .. body:serialize():gsub("<body.->", ""):gsub("</body>", "")
end
diff --git a/support/make4ht/filters/make4ht-svg-height.lua b/support/make4ht/filters/make4ht-svg-height.lua
index 44e98748ea..bb9f8dbdc6 100644
--- a/support/make4ht/filters/make4ht-svg-height.lua
+++ b/support/make4ht/filters/make4ht-svg-height.lua
@@ -1,6 +1,8 @@
+local log = logging.new("svg-height")
-- Make:image("svg$", "dvisvgm -n -a -p ${page} -b preview -c 1.4,1.4 -s ${source} > ${output}")
+
local max = function(a,b)
return a > b and a or b
end
@@ -34,7 +36,7 @@ return function(svg)
max_height = get_max_height(path, max_height)
end
-- update the height only if the max_height is larger than height set in the SVG file
- print(max_height, height)
+ log:debug("max height and height", max_height, height)
if max_height > height then
svg = update_height(svg, max_height)
end
diff --git a/support/make4ht/formats/docbook.lua b/support/make4ht/formats/docbook.lua
index 9e5ffe9488..3bd79eb83e 100644
--- a/support/make4ht/formats/docbook.lua
+++ b/support/make4ht/formats/docbook.lua
@@ -6,6 +6,7 @@ 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"
@@ -25,7 +26,7 @@ local function call_xtpipes(make)
make:match("xml$", matchfunction)
move_matches(make)
else
- print "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution"
+ log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution"
end
end
diff --git a/support/make4ht/formats/odt.lua b/support/make4ht/formats/odt.lua
index 64b8793e2a..c515a154a1 100644
--- a/support/make4ht/formats/odt.lua
+++ b/support/make4ht/formats/odt.lua
@@ -6,6 +6,7 @@ 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)
@@ -23,9 +24,12 @@ Odtfile.__index = Odtfile
Odtfile.new = function(archivename)
local self = setmetatable({}, Odtfile)
- -- create temporary directory
+ -- create a temporary file
local tmpname = os.tmpname()
- tmpname = tmpname:match("([a-zA-Z0-9_%-]+)$")
+ -- 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
@@ -68,10 +72,10 @@ function Odtfile:pack()
lfs.chdir(self.archivelocation)
-- make temporary mime type file
self:make_mimetype()
- os.execute(zip_command .. " -q0X " .. self.name .. " " .. self.mimetypename)
+ mkutils.execute(zip_command .. " -q0X " .. self.name .. " " .. self.mimetypename)
-- remove it, so the next command doesn't overwrite it
self:remove_mimetype()
- os.execute(zip_command .." -r " .. self.name .. " *")
+ mkutils.execute(zip_command .." -r " .. self.name .. " *")
lfs.chdir(currentdir)
mkutils.cp(self.archivelocation .. "/" .. self.name, self.name)
mkutils.delete_dir(self.archivelocation)
@@ -99,7 +103,7 @@ local function call_xtpipes(make)
move_matches(make)
move_matches(make)
else
- print "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution"
+ log:warning "Cannot locate xtpipes. Try to set TEXMFROOT variable to a root directory of your TeX distribution"
end
end
@@ -111,7 +115,7 @@ local function prepare_output_files(lgfiles)
local group = groups[extension] or {}
table.insert(group, basename)
groups[extension] = group
- print(basename, extension)
+ log:debug("prepare output file", basename, extension)
end
return groups
end
@@ -130,7 +134,7 @@ function M.modify_build(make)
-- expanded in tex4ht.env in Miktex or Debian
call_xtpipes(make)
-- fix the image dimensions wrongly set by xtpipes
- local domfilters = domfilter {"t4htlinks"}
+ 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)
@@ -138,9 +142,6 @@ function M.modify_build(make)
local fixentities = filter {"entities-to-unicode"}
make:match("4oo", fixentities)
make:match("4om", fixentities)
- -- execute fixentities as first
- move_matches(make)
- move_matches(make)
-- 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
@@ -161,7 +162,7 @@ function M.modify_build(make)
local odtname = basename .. ".odt"
local odt,msg = Odtfile.new(odtname)
if not odt then
- print("Cannot create ODT file: " .. msg)
+ log:error("Cannot create ODT file: " .. msg)
end
-- helper function for simple file moving
local function move_file(group, dest)
diff --git a/support/make4ht/make4ht b/support/make4ht/make4ht
index 564bc6e7a0..b1ff84f700 100755
--- a/support/make4ht/make4ht
+++ b/support/make4ht/make4ht
@@ -3,8 +3,10 @@
-- This package is subject of LPPL license, version 1.3
kpse.set_program_name("luatex")
-
-
+-- logging should be globally available
+logging = require "make4ht-logging"
+if os.type == "windows" then logging.use_colors = false end
+local log = logging.new("make4ht")
local make4ht = require("make4ht-lib")
local lapp = require("lapp-mk4")
local mkutils = require("mkutils")
@@ -13,7 +15,7 @@ local mk_config = require("make4ht-config")
-- 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
+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
@@ -27,13 +29,16 @@ 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.2g"
+local version = "v0.3"
mkparams.version_number = version
local args = mkparams.get_args()
local parameters = mkparams.process_args(args)
+log:status("Conversion started")
+log:status("Input file: " .. parameters.tex_file)
+
local mode = parameters.mode
local build_file = parameters.build_file
@@ -48,7 +53,7 @@ if allowed_output_formats[ output_format ] then
else
-- load html5 as default output format
if output_format then
- print("Cannot load output format: ".. output_format)
+ log:warning("Cannot load output format: ".. output_format)
end
formatter = mkutils.load_output_format("html5")
end
@@ -56,7 +61,7 @@ end
local configname = "make4ht"
local conffile = mk_config.find_config(configname) or mk_config.find_xdg_config(configname)
if conffile then
- print("Using configuration file: " .. conffile)
+ log:info("Using configuration file: " .. conffile)
mkutils.load_config(parameters, conffile)
end
local extensions = formatter.prepare_extensions(parameters.extensions)
@@ -96,15 +101,26 @@ end
-- allow output formats to modify the build process at the end
make = formatter.modify_build(make) or make
+make:match("tmp$", function(filename,params)
+ -- remove the temporary tex file created when the input comes from the standard input
+ if params.is_tmp_file then
+ log:info("removing temp file", params.tex_file)
+ os.remove(params.tex_file)
+ end
+ -- prevent copying of the temporary file to the outdir
+ return false,"tmp file" end
+)
-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)
+ log:info("outdir: "..outdir)
local outfilename = outdir .. filename
mkutils.copy(filename,outfilename)
return true
end)
make:run()
+
+log:status("Conversion finished")
+
diff --git a/support/make4ht/make4ht-doc.pdf b/support/make4ht/make4ht-doc.pdf
index 0b7dd091ea..506be1df42 100644
--- a/support/make4ht/make4ht-doc.pdf
+++ b/support/make4ht/make4ht-doc.pdf
Binary files differ
diff --git a/support/make4ht/make4ht-doc.tex b/support/make4ht/make4ht-doc.tex
index 6815e50606..24f94aa131 100644
--- a/support/make4ht/make4ht-doc.tex
+++ b/support/make4ht/make4ht-doc.tex
@@ -3,19 +3,24 @@
\usepackage[english]{babel}
\usepackage{hyperref}
+\newcommand\authormail[1]{\footnote{\textless\url{#1}\textgreater}}
\ifdefined\HCode
-\usepackage[T1]{fontenc}
-\usepackage[utf8]{inputenc}
-\else
+\renewcommand\authormail[1]{\space\textless\Link[#1]{}{}#1\EndLink\textgreater}
+\fi
+
\usepackage{fontspec}
\setmainfont{TeX Gyre Schola}
-\setmonofont[Scale=MatchLowercase]{Inconsolatazi4}
-\fi
+% \setmonofont[Scale=MatchLowercase]{Inconsolatazi4}
+\IfFontExistsTF{Noto Sans Mono Regular}{%
+ \setmonofont[Scale=MatchLowercase]{Noto Sans Mono Regular}
+}{\setmonofont{NotoMono-Regular.ttf}}
+\usepackage{upquote}
+
\usepackage{microtype}
\providecommand\tightlist{\relax}
\title{The \texttt{make4ht} build system}
-\author{Michal Hoftich\footnote{\url{michal.h21@gmail.com}}}
+\author{Michal Hoftich\authormail{michal.h21@gmail.com}}
\date{Version \version\\\gitdate}
\begin{document}
\maketitle
diff --git a/support/make4ht/make4ht-errorlogparser.lua b/support/make4ht/make4ht-errorlogparser.lua
new file mode 100644
index 0000000000..b48957c651
--- /dev/null
+++ b/support/make4ht/make4ht-errorlogparser.lua
@@ -0,0 +1,97 @@
+local m = {}
+
+local function get_filename(chunk)
+ local filename = chunk:match("([^\n^%(]+)")
+ local first = filename:match("^[%./\\]+")
+ if first then return filename end
+ return false
+end
+
+local function get_chunks(text)
+ -- parse log for particular included files
+ local chunks = {}
+ -- each file is enclosed in matching () brackets
+ local newtext = text:gsub("(%b())", function(a)
+ local chunk = string.sub(a,2,-2)
+ -- if no filename had been found in the chunk, it is probably not file chunk
+ -- so just return the original text
+ local filename = get_filename(chunk)
+ if not filename then return a end
+ local children, text = get_chunks(chunk)
+ table.insert(chunks, {filename = filename, text = text, children = children})
+ return ""
+ end)
+ return chunks, newtext
+end
+
+
+function print_chunks(chunks, level)
+ local level = level or 0
+ local indent = string.rep(" ", level)
+ for k,v in ipairs(chunks) do
+ print(indent .. (v.filename or "?"), string.len(v.text))
+ print_chunks(v.children, level + 1)
+ end
+end
+
+local function parse_errors(text)
+ local lines = {}
+ local errors = {}
+ local find_line_no = false
+ local error_lines = {}
+ for line in text:gmatch("([^\n]+)") do
+ lines[#lines+1] = line
+ end
+ for i = 1, #lines do
+ local line = lines[i]
+ -- error lines start with !
+ local err = line:match("^!(.+)")
+ -- error lines can be on following lines
+ -- the format is l.number
+ local lineno = line:match("^l%.([0-9]+)")
+ if err then
+ errors[#errors+1] = err
+ -- we didn't find error line number since previous error, insert
+ if find_line_no then
+ error_lines[#error_lines+1] = false
+ end
+ find_line_no = true
+ elseif lineno then
+ find_line_no = false
+ error_lines[#error_lines+1] = tonumber(lineno)
+ end
+ i = i + 1
+ end
+ return errors, error_lines
+end
+
+
+local function get_errors(chunks, errors)
+ local errors = errors or {}
+ for _, v in ipairs(chunks) do
+ local current_errors, error_lines = parse_errors(v.text)
+ for i, err in ipairs(current_errors) do
+ table.insert(errors, {filename = v.filename, error = err, line = error_lines[i] })
+ end
+ errors = get_errors(v.children, errors)
+ end
+ return errors
+end
+
+
+function m.parse(log)
+ local chunks, newtext = get_chunks(log)
+ -- save the unparsed text that contains system messages
+ table.insert(chunks, {text = newtext, children = {}})
+ -- print_chunks(chunks)
+ local errors = get_errors(chunks)
+ -- for _,v in ipairs(errors) do
+ -- print("error", v.filename, v.line, v.error)
+ -- end
+ return errors, chunks
+end
+
+
+m.print_chunks = print_chunks
+
+return m
diff --git a/support/make4ht/make4ht-htlatex.lua b/support/make4ht/make4ht-htlatex.lua
new file mode 100644
index 0000000000..214972e8bb
--- /dev/null
+++ b/support/make4ht/make4ht-htlatex.lua
@@ -0,0 +1,75 @@
+local log = logging.new "htlatex"
+
+local error_logparser = require("make4ht-errorlogparser")
+
+local Make = Make or {}
+-- this function reads the LaTeX log file and tries to detect fatal errors in the compilation
+local function testlogfile(par)
+ local logfile = par.input .. ".log"
+ local f = io.open(logfile,"r")
+ if not f then
+ log:warning("Make4ht: cannot open log file "..logfile)
+ return 1
+ end
+ local content = f:read("*a")
+ -- test only the end of the log file, no need to run search functions on everything
+ local text = content:sub(-1256)
+ f:close()
+ -- parse log file for all errors in non-interactive modes
+ if par.interaction~="errorstopmode" then
+ -- the error log parsing can be slow, so detect errors first
+ if content:match("\n!") then
+ local errors, chunks = error_logparser.parse(content)
+ if #errors > 0 then
+ log:error("Compilation errors in the htlatex run")
+ log:error("Filename", "Line", "Message")
+ for _, err in ipairs(errors) do
+ log:error(err.filename or "?", err.line or "?", err.error)
+ end
+ end
+ end
+ end
+ -- test for fatal errors
+ if text:match("No pages of output") or text:match("TeX capacity exceeded, sorry") or text:match("That makes 100 errors") or text:match("Emergency stop") then return 1 end
+ return 0
+end
+
+
+-- Make this function available in the build files
+Make.testlogfile = testlogfile
+--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}")
+
+-- template for calling LaTeX with tex4ht loaded
+Make.latex_command = "${htlatex} --interaction=${interaction} ${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 \"\\detokenize{${tex_file}}\"'"
+
+
+local m = {}
+
+function m.htlatex(par)
+ local command = Make.latex_command
+ local devnull = " > /dev/null 2>&1"
+ if os.type == "windows" then
+ command = command:gsub("'",'')
+ devnull = " > nul 2>&1"
+ end
+ par.interaction = par.interaction or "batchmode"
+ -- remove all terminal output from the batchmode
+ if par.interaction == "batchmode" then
+ command = command .. devnull
+ end
+ command = command % par
+ log:info("LaTeX call: "..command)
+ os.execute(command)
+ return Make.testlogfile(par)
+end
+
+return m
diff --git a/support/make4ht/make4ht-indexing.lua b/support/make4ht/make4ht-indexing.lua
new file mode 100644
index 0000000000..5801df509b
--- /dev/null
+++ b/support/make4ht/make4ht-indexing.lua
@@ -0,0 +1,190 @@
+
+local M = {}
+local log = logging.new "indexing"
+
+-- Handle accented characters in files created with \usepackage[utf]{inputenc}
+-- this code was originally part of https://github.com/michal-h21/iec2utf/
+local enc = {}
+
+local licrs = {}
+local codepoint2utf = unicode.utf8.char
+local used_encodings = {}
+
+-- load inputenc encoding file
+local function load_encfiles(f)
+ local file= io.open(f,"r")
+ local encodings = file:read("*all")
+ file:close()
+ for codepoint, licr in encodings:gmatch('DeclareUnicodeCharacter(%b{})(%b{})') do
+ local codepoint = codepoint2utf(tonumber(codepoint:sub(2,-2),16))
+ local licr= licr:sub(2,-2):gsub('@tabacckludge','')
+ licrs[licr] = codepoint
+ end
+end
+
+local function sanitize_licr(l)
+ return l:gsub(" (.)",function(s) if s:match("[%a]") then return " "..s else return s end end):sub(2,-2)
+end
+
+local load_enc = function(enc)
+ -- use default encodings if used doesn't provide one
+ enc = enc or {"T1","T2A","T2B","T2C","T3","T5", "LGR"}
+ for _,e in pairs(enc) do
+ local filename = e:lower() .. "enc.dfu"
+ -- don't process an enc file multiple times
+ if not used_encodings[filename] then
+ local dfufile = kpse.find_file(filename)
+ if dfufile then
+ load_encfiles(dfufile)
+ end
+ end
+ used_encodings[filename] = true
+ end
+end
+
+
+
+local cache = {}
+
+local get_utf8 = function(input)
+ local output = input:gsub('\\IeC[%s]*(%b{})',function(iec)
+ -- remove \protect commands
+ local iec = iec:gsub("\\protect%s*", "")
+ local code = cache[iec] or licrs[sanitize_licr(iec)] or '\\IeC '..iec
+ -- print(iec, code)
+ cache[iec] = code
+ return code
+ end)
+ return output
+end
+
+
+-- parse the idx file produced by tex4ht
+-- it replaces the document page numbers by index entry number
+-- each index entry can then link to place in the HTML file where the
+-- \index command had been used
+
+local parse_idx = function(content)
+ -- index entry number
+ local current_entry = 0
+ -- map between index entry number and corresponding HTML file and destination
+ local map = {}
+ local buffer = {}
+
+ for line in content:gmatch("([^\n]+)") do
+ if line:match("^\\beforeentry") then
+ -- increment index entry number
+ current_entry = current_entry + 1
+ local file, dest = line:match("\\beforeentry{(.-)}{(.-)}")
+ map[current_entry] = {file = file, dest = dest}
+ elseif line:match("^\\indexentry") then
+ -- replace the page number with the current
+ -- index entry number
+ local result = line:gsub("{[0-9]+}", "{"..current_entry .."}")
+ buffer[#buffer+1] = get_utf8(result)
+ else
+ buffer[#buffer+1] = line
+ end
+ end
+ -- return table with page to dest map and updated idx file
+ return {map = map, idx = table.concat(buffer, "\n")}
+end
+
+-- replace page numbers in the ind file with hyperlinks
+local fix_idx_pages = function(content, idxobj)
+ local buffer = {}
+ local entries = idxobj.map
+ for line in content:gmatch("([^\n]+)") do
+ local line = line:gsub("(%s*\\%a+.-%,)(.+)$", function(start,rest)
+ return start .. rest:gsub("(%d+)", function(page)
+ local entry = entries[tonumber(page)]
+ if entry then
+ -- construct link to the index entry
+ return "\\Link[" .. entry.file .."]{".. entry.dest .."}{}" .. page .."\\EndLink{}"
+ else
+ return page
+ end
+ end)
+ end)
+ buffer[#buffer+1] = line
+ end
+ return table.concat(buffer, "\n")
+end
+
+-- prepare the .idx file produced by tex4ht
+-- for use with Xindy or Makeindex
+local prepare_idx = function(filename)
+ local f = io.open(filename, "r")
+ if not f then return nil, "Cannot open file :".. tostring(filename) end
+ local content = f:read("*all")
+ local idx = parse_idx(content)
+ local idxname = os.tmpname()
+ local f = io.open(idxname, "w")
+ f:write(idx.idx)
+ f:close()
+ -- return the object with mapping between dummy page numbers
+ -- and link destinations in the files, and the temporary .idx file
+ -- these can be used for the processing with the index processor
+ return idx, idxname
+end
+
+-- add links to a index file
+local process_index = function(indname, idx)
+ local f = io.open(indname, "r")
+ if not f then return nil, "Cannot open .ind file: " .. tostring(indname) end
+ local content = f:read("*all")
+ f:close()
+
+ local newcontent = fix_idx_pages(content, idx)
+ local f = io.open(indname,"w")
+ f:write(newcontent)
+ f:close()
+ return true
+end
+
+local prepare_tmp_idx = function(par)
+ par.idxfile = par.idxfile or par.input .. ".idx"
+ -- construct the .ind name, based on the .idx name
+ par.indfile = par.indfile or par.idxfile:gsub("idx$", "ind")
+ load_enc()
+ -- save hyperlinks and clean the .idx file
+ local idxdata, newidxfile = prepare_idx(par.idxfile)
+ if not idxdata then
+ -- if the prepare_idx function returns nil, the second reuturned value contains error msg
+ return nil, newidxfile
+ end
+ return newidxfile, idxdata
+end
+
+local run_indexing_command = function(command, par)
+ -- detect command name from the command. It will be the first word
+ local cmd_name = command:match("^[%a]+") or "indexing"
+ local xindylog = logging.new(cmd_name)
+ local newidxfile, idxdata = prepare_tmp_idx(par)
+ if not newidxfile then
+ -- the idxdata will contain error message in the case of error
+ xindylog:warning(idxdata)
+ return false
+ end
+ par.newidxfile = newidxfile
+ xindylog:debug("Prepared temporary idx file: ", newidxfile)
+ -- prepare modules
+ local xindy_call = command % par
+ xindylog:info(xindy_call)
+ local status = mkutils.execute(xindy_call)
+ -- insert correct links to the index
+ local status, msg = process_index(par.indfile, idxdata)
+ if not status then xindylog:warning(msg) end
+ -- remove the temporary idx file
+ os.remove(newidxfile)
+end
+
+M.get_utf8 = get_utf8
+M.load_enc = load_enc
+M.parse_idx = parse_idx
+M.fix_idx_pages = fix_idx_pages
+M.prepare_idx = prepare_idx
+M.process_index = process_index
+M.prepare_tmp_idx = prepare_tmp_idx
+M.run_indexing_command = run_indexing_command
+return M
diff --git a/support/make4ht/make4ht-lib.lua b/support/make4ht/make4ht-lib.lua
index 2ada398f86..91418d18b5 100644
--- a/support/make4ht/make4ht-lib.lua
+++ b/support/make4ht/make4ht-lib.lua
@@ -2,6 +2,7 @@
--kpse.set_program_name("luatex")
-- module(...,package.seeall)
local m = {}
+local log = logging.new "make4ht-lib"
Make = {}
--Make.params = {}
@@ -17,13 +18,13 @@ Make.add = function(self,name,fn,par,rep)
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
+ for k,v in pairs(par) do params[k] = v; log:info("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)
+ log:info("Adding: ",k,v)
end
-- print( fn % params)
local command = {
@@ -50,14 +51,14 @@ Make.run_command = function(self,filename,s)
local command = s.command
local params = s.params
params["filename"] = filename
- print("parse_lg process file: "..filename)
+ log:info("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)
+ log:info("Execute: " .. run)
+ return mkutils.execute(run)
end
return false, "parse_lg: Command is not string or function"
end
@@ -95,8 +96,8 @@ Make.image_convert = function(self, images)
command(p)
elseif type(command) == "string" then
local c = command % p
- print("Make4ht convert: "..c)
- os.execute(c)
+ log:info("Make4ht convert: "..c)
+ mkutils.execute(c)
end
break
end
@@ -125,7 +126,7 @@ Make.file_matches = function(self, files)
msg = msg or "No message given"
table.insert(statuses[file],status)
if status == false then
- print(msg)
+ log:info(msg)
break
end
end
@@ -173,14 +174,14 @@ Make.run = function(self)
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")
+ log:warning (command .." can be executed only "..repetition .."x")
else
- print("Make4ht: " .. command)
- local status = os.execute(command)
+ log:info("executing: " .. command)
+ local status = mkutils.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))
+ log:warning("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
@@ -188,7 +189,7 @@ Make.run = function(self)
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)
+ log:fatal("Fatal error. Command "..last_name .." returned exit code "..current_status)
os.exit(1)
end
end
@@ -208,7 +209,7 @@ Make.run = function(self)
end
self:file_matches(files)
else
- print("No lg file. tex4ht run failed?")
+ log:warning("No lg file. tex4ht run failed?")
end
return return_codes
end
diff --git a/support/make4ht/make4ht-logging.lua b/support/make4ht/make4ht-logging.lua
new file mode 100644
index 0000000000..c1d2b24a57
--- /dev/null
+++ b/support/make4ht/make4ht-logging.lua
@@ -0,0 +1,105 @@
+-- logging system for make4ht
+-- inspired by https://github.com/rxi/log.lua
+local logging = {}
+
+local levels = {}
+-- level of bugs that should be shown
+local show_level = 1
+local max_width = 0
+
+logging.use_colors = true
+
+logging.modes = {
+ {name = "debug", color = 34},
+ {name = "info", color = 32},
+ {name = "status", color = 37},
+ {name = "warning", color = 33},
+ {name = "error", color = 31},
+ {name = "fatal", color = 35}
+}
+
+-- prepare table with mapping between mode names and corresponding levels
+
+function logging.prepare_levels(modes)
+ local modes = modes or logging.modes
+ logging.modes = modes
+ for level, mode in ipairs(modes) do
+ levels[mode.name] = level
+ mode.level = level
+ max_width = math.max(string.len(mode.name), max_width)
+ end
+end
+
+-- the logging level is set once
+function logging.set_level(name)
+ local level = levels[name] or 1
+ show_level = level
+end
+
+function logging.print_msg(header, message, color)
+ local color = color or 0
+ -- use format for collors depending on the use_colors option
+ local header = "[" .. header .. "]"
+ local color_format = logging.use_colors and string.format("\27[%im%%s\27[0m%%s", color) or "%s%s"
+ -- the padding is maximal mode name width + brackets + space
+ local padded_header = string.format("%-".. max_width + 3 .. "s", header)
+ print(string.format(color_format, padded_header, message))
+end
+
+--
+function logging.new(module)
+ local obj = {
+ module = module,
+ output = function(self, output)
+ -- used for printing of output of commands
+ if show_level <= (levels[debug] or 1) then
+ print(output)
+ end
+ end
+ }
+ obj.__index = obj
+ -- make a function for each mode
+ for _, mode in ipairs(logging.modes) do
+ local name = mode.name
+ local color = mode.color
+ obj[name] = function(self, ...)
+ -- max width is saved in logging.prepare_levels
+ if mode.level >= show_level then
+ -- support variable number of parameters
+ local table_with_holes = table.pack(...)
+ local table_without_holes = {}
+ -- trick used to support the nil values in the varargs
+ -- https://stackoverflow.com/a/7186820/2467963
+ for i= 1, table_with_holes.n do
+ table.insert(table_without_holes, tostring(table_with_holes[i]) or "")
+ end
+ local msg = table.concat(table_without_holes, "\t")
+ logging.print_msg(string.upper(name), string.format("%s: %s", self.module, msg), color)
+ end
+ end
+ end
+ return setmetatable({}, obj)
+
+end
+
+
+-- prepare default levels
+logging.prepare_levels()
+
+-- for _, mode in ipairs(logging.modes) do
+-- logging.print_msg(mode.name,"xxxx", mode.color)
+-- end
+
+-- local cls = logging.new("sample")
+-- cls:warning("hello")
+-- cls:error("world")
+-- cls:info("set new level")
+-- logging.set_level("error")
+-- cls:info("level set")
+-- cls:error("just print the error")
+
+
+return logging
+
+
+
diff --git a/support/make4ht/make4ht-xtpipes.lua b/support/make4ht/make4ht-xtpipes.lua
index 78014baff1..3f5b51e07b 100644
--- a/support/make4ht/make4ht-xtpipes.lua
+++ b/support/make4ht/make4ht-xtpipes.lua
@@ -1,5 +1,6 @@
local M = {}
+local log = logging.new "xtpipes"
-- find if tex4ht.jar exists in a path
local function find_tex4ht_jar(path)
local jar_file = path .. "/tex4ht/bin/tex4ht.jar"
@@ -38,7 +39,7 @@ end
function M.get_xtpipes(selfautoparent)
-- make pattern using TeX distro path
- local pattern = string.format("java -classpath %s/tex4ht/bin/tex4ht.jar xtpipes -i %s/tex4ht/xtpipes/ -o ${outputfile} ${filename}", selfautoparent, selfautoparent)
+ local pattern = string.format('java -classpath "%s/tex4ht/bin/tex4ht.jar" xtpipes -i "%s/tex4ht/xtpipes/" -o "${outputfile}" "${filename}"', selfautoparent, selfautoparent)
-- call xtpipes on a temporary file
local matchfunction = function(filename)
-- move the matched file to a temporary file, xtpipes will write it back to the original file
@@ -46,19 +47,19 @@ function M.get_xtpipes(selfautoparent)
local tmpfile = basename ..".tmp"
mkutils.mv(filename, tmpfile)
local command = pattern % {filename = tmpfile, outputfile = filename}
- print(command)
- local status = os.execute(command)
+ log:info("execute: " ..command)
+ local status = mkutils.execute(command)
if status > 0 then
-- if xtpipes failed to process the file, it may mean that it was bad-formed xml
-- we can try to make it well-formed using Tidy
- local tidy_command = "tidy -utf8 -xml -asxml -q -o ${filename} ${tmpfile}" % {tmpfile = tmpfile, filename = filename}
- print("xtpipes failed trying tidy")
- print(tidy_command)
+ local tidy_command = 'tidy -utf8 -xml -asxml -q -o "${filename}" "${tmpfile}"' % {tmpfile = tmpfile, filename = filename}
+ log:warning("xtpipes failed trying tidy")
+ log:debug(tidy_command)
local status = os.execute(tidy_command)
if status > 0 then
-- if tidy failed as well, just use the original file
-- it will probably produce corrupted ODT file though
- print("Tidy failed as well")
+ log:warning("Tidy failed as well")
mkutils.mv(tmpfile, filename)
end
end
diff --git a/support/make4ht/mkparams.lua b/support/make4ht/mkparams.lua
index 4db967f270..eff8c99670 100644
--- a/support/make4ht/mkparams.lua
+++ b/support/make4ht/mkparams.lua
@@ -1,6 +1,7 @@
local lapp = require "lapp-mk4"
local mkutils = require "mkutils"
local m = {} -- use ugly module system for new lua versions support
+local log = logging.new "mkparams"
-- these two variables will be used in the version number
-- progname will be set in get_args
@@ -9,25 +10,28 @@ m.progname = "make4ht"
m.version_number = "v0.1"
m.optiontext = [[
-${progname} - build system for tex4ht
+${progname} - build system for TeX4ht
Usage:
${progname} [options] filename ["tex4ht.sty op."] ["tex4ht op."] ["t4ht op"] ["latex op"]
Available options:
+ -a,--loglevel (default status) Set log level.
+ possible values: debug, info, status, warning, error, fatal
-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
-f,--format (default html5) Output file format
- -h,-- help Display this message
+ -h,--help Display this message
+ -j,--jobname (default nil) Set the jobname
-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
+ -n,--no-tex4ht Disable dvi file processing with the 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
-v,--version Display version number
+ -x,--xetex Use xelatex for document compilation
]]
-- test if the current command line argument should be passed to tex4ht, t4ht or latex
@@ -36,11 +40,12 @@ local function is_escapedargument(arg)
local ignored_options = {["-h"]=true, ["--help"]=true, ["-v"] = true, ["--version"]=true}
if ignored_options[arg] then return false end
-- in other cases, match if the argument starts with "-" character
- return arg:match("^%-")
+ return arg:match("^%-.+")
end
local function get_args(parameters, optiontext)
local parameters = parameters or {}
parameters.progname = parameters.progname or "make4ht"
+ parameters.issue_tracker = parameters.issue_tracker or "https://github.com/michal-h21/make4ht/issues"
parameters.postparams = parameters.postparams or ""
local optiontext = optiontext or m.optiontext
parameters.postfile = parameters.postfile or ""
@@ -54,7 +59,7 @@ Positional optional argumens:
Documentation: https://tug.org/applications/tex4ht/mn.html
Issue tracker for tex4ht bugs: https://puszcza.gnu.org.ua/bugs/?group=tex4ht
-Issue tracker for make4ht bugs: https://github.com/michal-h21/make4ht/issues
+Issue tracker for ${progname} bugs: ${issue_tracker}
]] .. parameters.postfile
-- we can pass arguments for tex4ht and t4ht after filename, but it will confuse lapp, thinking that these
-- options are for make4ht. this may result in execution error or wrong option parsing
@@ -88,6 +93,61 @@ local function get_format_extensions(format_string)
return format, extensions
end
+-- detect if user specified -jobname in arguments to the TeX engine
+-- or used the --jobname option for make4ht
+local function handle_jobname(input, args)
+ -- parameters to the TeX engine
+ local latex_params = {}
+ local latex_cli_params = args[4] or ""
+ -- use the jobname as input name if it is specified
+ local jobname = args.jobname ~="nil" and args.jobname or nil
+ if jobname or not latex_cli_params:match("%-jobname") then
+ -- prefer jobname over input
+ input = jobname or input
+ -- we must strip out directories from jobname when full path to document is given
+ input = input:match("([^%/^%\\]+)$")
+ -- input also cannot contain spaces, replace them with underscores
+ input = input:gsub("%s", "_")
+ table.insert(latex_params,"-jobname="..input)
+ else
+ -- when user specifies -jobname, we must change name of the input file,
+ -- in order to be able to process correct dvi file with tex4ht and t4ht
+ local newinput
+ -- first contains quotation character or first character of the name
+ local first, rest = latex_cli_params:match("%-jobname%s*=?%s*(.)(.*)")
+ if first=='"' then
+ newinput=rest:match('([^"]+)')
+ elseif first=="'" then
+ newinput=rest:match("([^']+)")
+ elseif type(first)== "string" then
+ -- if the jobname is unquoted, it cannot contain space
+ -- join the first character and rest
+ rest = first.. rest
+ newinput = rest:match("([^ ]+)")
+ end
+ if newinput then
+ input = newinput
+ end
+ end
+ --
+ table.insert(latex_params, latex_cli_params)
+ return latex_params, input
+end
+
+-- use standard input instead of file if the filename is just `-`
+-- return the filename and status if it is a tmp name
+local function handle_input_file(filename)
+ -- return the original file name if it isn't just dash
+ if filename ~= "-" then return filename, false end
+ -- generate the temporary name. the added extension is important
+ local tmp_name = os.tmpname()
+ local contents = io.read("*all")
+ local f = io.open(tmp_name, "w")
+ f:write(contents)
+ f:close()
+ return tmp_name, true
+end
+
local function process_args(args)
local function get_inserter(args,tb)
return function(key, value)
@@ -98,6 +158,14 @@ local function process_args(args)
end
end
+ -- set error log level
+ logging.set_level(args.loglevel)
+ -- the default LaTeX --interaction parameter
+ local interaction = "batchmode"
+ if args.loglevel == "debug" then
+ interaction = "errorstopmode"
+ end
+
if args.version ==true then
print(string.format("%s version %s", m.progname, m.version_number))
os.exit()
@@ -122,36 +190,12 @@ local function process_args(args)
local compiler = args.lua and "dvilualatex" or args.xetex and "xelatex --no-pdf" or "latex"
- local tex_file = args.filename
- local input = mkutils.remove_extension(args.filename)
- local latex_params = {}
+ local tex_file, is_tmp_file = handle_input_file(args.filename)
+ local input = mkutils.remove_extension(tex_file)
+ -- the output file name can be influneced using -jobname parameter passed to the TeX engine
+ local latex_params, input = handle_jobname(input, args)
local insert_latex = get_inserter(args,latex_params)
insert_latex("shell-escape","-shell-escape")
- local latex_cli_params = args[4] or ""
- if not latex_cli_params:match("%-jobname") then
- -- we must strip out directories from jobname when full path to document is given
- input = input:match("([^%/^%\\]+)$")
- -- input also cannot contain spaces, replace them with underscores
- input = input:gsub("%s", "_")
- table.insert(latex_params,"-jobname="..input)
- else
- -- when user specifies -jobname, we must change name of the input file,
- -- in order to be able to process correct dvi file with tex4ht and t4ht
- local newinput
- local first, rest = latex_cli_params:match("%-jobname=(.)(.*)")
- if first=='"' then
- newinput=rest:match('([^"]+)')
- elseif first=="'" then
- newinput=rest:match("([^']+)")
- elseif type(first)== "string" then
- rest = first.. rest
- newinput = rest:match("([^ ]+)")
- end
- if newinput then
- input = newinput
- end
- end
- table.insert(latex_params, latex_cli_params)
--table.insert(latex_params,args["shell-escape"] and "-shell-escape")
@@ -181,9 +225,9 @@ local function process_args(args)
tex4ht = args[2]
else
tex4ht = args.utf8 and " -cmozhtf -utf8" or ""
- if args.xetex then tex4ht = tex4ht .. " -.xdv" end
- -- tex4ht = tex4ht .. xdv
end
+ -- set the correct extension for tex4ht if xetex is used
+ if args.xetex then tex4ht = tex4ht .. " -.xdv" end
local t4ht = args[3] or ""
@@ -215,19 +259,21 @@ local function process_args(args)
,build_file = build_file
,output_format = outformat
,extensions = extensions
+ ,is_tmp_file = is_tmp_file
+ ,interaction = interaction
--,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)
+ log:info("Output dir: "..outdir)
+ log:info("Compiler: "..compiler)
+ log:info("Latex options: ".. table.concat(latex_params," "))
+ log:info("tex4ht.sty: "..t4sty)
+ log:info("tex4ht: "..tex4ht)
+ log:info("build_file: ".. build_file)
if outformat~="nil" then
- print("Output format", outformat)
+ log:info("Output format: ".. outformat)
for _, ex in ipairs(extensions) do
- print("Extension", ex.type .. ex.name)
+ log:info("Extension: ".. ex.type .. ex.name)
end
end
return parameters
diff --git a/support/make4ht/mkutils.lua b/support/make4ht/mkutils.lua
index fd32c91e08..ba1cd6cbb9 100644
--- a/support/make4ht/mkutils.lua
+++ b/support/make4ht/mkutils.lua
@@ -1,7 +1,10 @@
module(...,package.seeall)
+local log = logging.new("mkutils")
+
local make4ht = require("make4ht-lib")
local mkparams = require("mkparams")
+local indexing = require("make4ht-indexing")
--template engine
function interp(s, tab)
local tab = tab or {}
@@ -61,11 +64,11 @@ end
-- searching for converted images
function parse_lg(filename)
- print("Parse LG")
+ log:info("Parse LG")
local outputimages,outputfiles,status={},{},nil
local fonts, used_fonts = {},{}
if not file_exists(filename) then
- print("Cannot read log file: "..filename)
+ log:warning("Cannot read log file: "..filename)
else
local usedfiles={}
for line in io.lines(filename) do
@@ -114,7 +117,7 @@ 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)
+ log:info("Copy: "..command)
os.execute(command)
end
@@ -123,7 +126,7 @@ function mv(src, dest)
local command = string.format('%s "%s" "%s"', mv_func, src, dest)
-- fix windows paths
if mv_func == "move" then command = command:gsub("/",'\\') end
- print("Move: ".. command)
+ log:info("Move: ".. command)
os.execute(command)
end
@@ -211,18 +214,32 @@ function copy(filename,outfilename)
if not used_dir[path] then
local to_create, msg = find_directories(parts)
if not to_create then
- print(msg)
+ log:warning(msg)
return false
end
used_dir[path] = true
local stat, msg = mkdirectories(to_create)
- if not stat then print(msg) end
+ if not stat then log:warning(msg) end
end
lfs.chdir(currdir)
cp(filename, path)
return true
end
+function execute(command)
+ local f = io.popen(command, "r")
+ local output = f:read("*all")
+ -- rc will contain return codes of the executed command
+ local rc = {f:close()}
+ -- the status code is on the third position
+ -- https://stackoverflow.com/a/14031974/2467963
+ local status = rc[3]
+ -- print the command line output only when requested through
+ -- log level
+ log:output(output)
+ return status, output
+end
+
-- find the zip command
function find_zip()
if io.popen("zip -v","r"):close() then
@@ -269,6 +286,7 @@ env.os = os
env.io = io
env.math = math
env.unicode = unicode
+env.logging = logging
-- it is necessary to use the settings table
@@ -317,57 +335,14 @@ env.Make = make4ht.Make
env.Make.params = env.settings
env.Make:add("test","test the variables: ${tex4ht_sty_par} ${htlatex} ${input} ${config}")
--- this function reads the LaTeX log file and tries to detect fatal errors in the compilation
-local function testlogfile(par)
- 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")
- -- test only the end of the log file, no need to run search functions on everything
- local newlen = len - 1256
- -- but the value to seek must be greater than 0
- newlen = (newlen > 0) and newlen or 0
- f:seek("set", newlen)
- local text = f:read("*a")
- f:close()
- if text:match("No pages of output") or text:match("TeX capacity exceeded, sorry") then return 1 end
- return 0
-end
-
-
--- Make this function available in the build files
-Make.testlogfile = testlogfile
---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}")
-
--- template for calling LaTeX with tex4ht loaded
-Make.latex_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 \"\\detokenize{${tex_file}}\"'"
-
-env.Make:add("htlatex",function(par)
- local command = Make.latex_command
- if os.type == "windows" then
- command = command:gsub("'",'')
- end
- command = command % par
- print("LaTeX call: "..command)
- os.execute(command)
- return testlogfile(par)
-end
+local htlatex = require "make4ht-htlatex"
+env.Make:add("htlatex", htlatex.htlatex
,{correct_exit=0})
env.Make:add("latexmk", function(par)
+ local settings = get_filter_settings "htlatex" or {}
+ par.interaction = par.interaction or settings.interaction or "batchmode"
local command = Make.latex_command
par.expanded = command % par
-- quotes in latex_command must be escaped, they cause Latexmk error
@@ -407,13 +382,13 @@ function load_config(settings, config_name)
end
local f = io.open(config_name,"r")
if not f then
- print("Cannot open config file", config_name)
+ log:info("Cannot open config file", config_name)
return env
end
- print("Using build file", config_name)
+ log:info("Using build file", config_name)
local code = f:read("*all")
local fn, msg = run(code,env)
- if not fn then print(msg) end
+ if not fn then log:warning(msg) end
assert(fn)
-- reload extensions from command line arguments for the "format" parameter
for _,v in ipairs(saved_extensions) do
@@ -423,25 +398,49 @@ function load_config(settings, config_name)
end
env.Make:add("xindy", function(par)
- -- par.encoding = par.encoding or "utf8"
- -- par.language = par.language or "english"
- par.idxfile = par.idxfile or par.input .. ".idx"
- local modules = par.modules or {par.input}
+ local xindylog = logging.new "xindy"
+ local settings = get_filter_settings "xindy" or {}
+ par.encoding = settings.encoding or par.encoding or "utf8"
+ par.language = settings.language or par.language or "english"
+ local modules = settings.modules or par.modules or {}
local t = {}
for k,v in ipairs(modules) do
+ xindylog:debug("Loading module: " ..v)
t[#t+1] = "-M ".. v
end
par.moduleopt = table.concat(t, " ")
- local xindy_call = "xindy -L ${language} -C ${encoding} ${moduleopt} ${idxfile}" % par
- print(xindy_call)
- return os.execute(xindy_call)
-end, { language = "english", encoding = "utf8"})
+ return indexing.run_indexing_command("texindy -L ${language} -C ${encoding} ${moduleopt} -o ${indfile} ${newidxfile}", par)
+end, {})
+
+env.Make:add("makeindex", function(par)
+ local makeindxcall = "makeindex ${options} -t ${ilgfile} -o ${indfile} ${newidxfile}"
+ local settings = get_filter_settings "makeindex" or {}
+ par.options = settings.options or par.options or ""
+ par.ilgfile = par.input .. ".ilg"
+ local status = indexing.run_indexing_command(makeindxcall, par)
+ return status
+end, {})
+
+env.Make:add("xindex", function(par)
+ local xindex_call = "xindex -l ${language} ${options} -o ${indfile} ${newidxfile}"
+ local settings = get_filter_settings "xindex" or {}
+ par.options = settings.options or par.options or ""
+ par.language = settings.language or par.language or "en"
+ local status = indexing.run_indexing_command(xindex_call, par)
+ return status
+end, {})
+
+
local function find_lua_file(name)
local extension_path = name:gsub("%.", "/") .. ".lua"
return kpse.find_file(extension_path, "lua")
end
+-- for the BibLaTeX support
+env.Make:add("biber", "biber ${input}")
+env.Make:add("bibtex", "bibtex ${input}")
+
--- load the output format plugins
function load_output_format(format_name)
local format_library = "make4ht.formats."..format_name
@@ -532,10 +531,10 @@ function load_extensions(extensions, format)
if module_names[name] == true then
local extension = load_extension(name,format)
if extension then
- print("Load extension", name)
+ log:info("Load extension", name)
table.insert(extension_table, extension)
else
- print("Cannot load extension: ".. name)
+ log:warning("Cannot load extension: ".. name)
end
end
end
diff --git a/support/make4ht/readme.tex b/support/make4ht/readme.tex
index c9fc0a2f3e..ff1d942d18 100644
--- a/support/make4ht/readme.tex
+++ b/support/make4ht/readme.tex
@@ -1,125 +1,267 @@
\hypertarget{introduction}{%
\section{Introduction}\label{introduction}}
-\texttt{make4ht} is a simple build system for \texttt{tex4ht}, \TeX~to
-XML converter. It provides a command line tool that drive the conversion
-process. It also provides a library which can be used to create
-customized conversion tools. An example of such conversion tool is
-\href{https://github.com/michal-h21/tex4ebook}{tex4ebook} for conversion
-of \TeX~to ePub and other e-book formats.
-
-\hypertarget{how-it-works}{%
-\subsection{How it works}\label{how-it-works}}
-
-\hypertarget{the-issues-with-default-tex4ht-conversion-commands}{%
-\subsubsection{\texorpdfstring{The issues with default \texttt{tex4ht}
-conversion
-commands}{The issues with default tex4ht conversion commands}}\label{the-issues-with-default-tex4ht-conversion-commands}}
-
-\texttt{tex4ht} system supports several output formats, most notably
-\texttt{XHTML}, \texttt{HTML\ 5} and \texttt{ODT}. The conversion can be
-invoked using several commands. These commands invoke LaTeX~or Plain TeX
-with special instructions to load \texttt{tex4ht.sty} package. The
-\TeX~run produces special \texttt{DVI} file which contains the code for
-desired output format. Produced \texttt{DVI} file is then processed and
-desired output files are created.
-
-The basic command provided by \texttt{tex4ht} is named \texttt{htlatex}.
-It compiles \LaTeX~ files to \texttt{HTML} with this command sequence:
+\texttt{make4ht} is a build system for \TeX4ht, \TeX~to XML converter.
+It provides a command line tool that drives the conversion process. It
+also provides a library that can be used to create customized conversion
+tools. An example of such a tool is
+\href{https://github.com/michal-h21/tex4ebook}{tex4ebook}, a tool for
+conversion from \TeX~to ePub and other e-book formats.
+
+The basic conversion from \LaTeX~to \texttt{HTML} using \texttt{make4ht}
+can be executed using the following command:
+
+\begin{verbatim}
+$ make4ht filename.tex
+\end{verbatim}
+
+It will produce a file named \texttt{filename.html} if the compilation
+goes without fatal errors.
+
+\hypertarget{clioptions}{%
+\section{Command line options}\label{clioptions}}
+
+\label{sec:clioptions}
+
+\begin{verbatim}
+make4ht - build system for TeX4ht
+Usage:
+make4ht [options] filename ["tex4ht.sty op." "tex4ht op."
+ "t4ht op" "latex op"]
+-a,--loglevel (default status) Set log level.
+ possible values: debug, info, status, warning, error, fatal
+-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 filename is different
+ than `filename`.mk4
+-f,--format (default nil) Output file format
+-j,--jobname (default nil) Set the jobname
+-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
+-v,--version Print version number
+<filename> (string) Input filename
+\end{verbatim}
+
+It is still possible to invoke \texttt{make4ht} in the same way as is
+invoked \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 the output
+directory handling. See section \ref{sec:output-dir} for more
+information about this issue. To use these routines, change the previous
+listing to:
+
+\begin{verbatim}
+$ make4ht -d foo filename "customcfg, charset=utf-8" "-cunihtf -utf8"
+\end{verbatim}
+
+This call has the same effect as the 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 the 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}
+
+The short options that don't take parameters can be collapsed:
+
+\begin{verbatim}
+$ make4ht -ulc customcfg -d foo filename
+\end{verbatim}
+
+To pass output from the other commands to \texttt{make4ht} use the
+\texttt{-} character as a filename. It is best to use this feature
+together with the \texttt{-\/-jobname} or \texttt{-j} option.
+
+\begin{verbatim}
+$ cat hello.tex | make4ht -j world -
+\end{verbatim}
+
+By default, \texttt{make4ht} tries to be quiet, so it hides most of the
+command line messages and the output from the executed commands. It will
+display only status messages, warnings and errors. The logging level can
+be selected using the \texttt{-\/-loglevel} or \texttt{-a} options. If
+the compilation fails, it may be useful to display more information
+using the \texttt{info} or \texttt{debug} levels.
\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 $tex4ht_options filename
-t4ht $t4ht_options filename
+$ make4ht -a debug faulty.tex
+\end{verbatim}
+
+\hypertarget{why-make4ht-htlatex-issues}{%
+\section{\texorpdfstring{Why \texttt{make4ht}? -- \texttt{htlatex}
+issues}{Why make4ht? -- htlatex issues}}\label{why-make4ht-htlatex-issues}}
+
+\TeX4ht~system supports several output formats, most notably
+\texttt{XHTML}, \texttt{HTML\ 5} and \texttt{ODT}, but it also supports
+\texttt{TEI} or \texttt{Docbook}.
+
+The conversion can be invoked using several scripts, which are
+distributed with \TeX4ht. They differ in parameters passed to the
+underlying commands.
+
+These scripts invoke \LaTeX~or Plain \TeX~with special instructions to
+load the \texttt{tex4ht.sty} package. The \TeX~run produces a special
+\texttt{DVI} file that contains the code for the desired output format.
+The produced \texttt{DVI} file is then processed using the
+\texttt{tex4ht} command, which in conjunction with the \texttt{t4ht}
+command produces the desired output files.
+
+\hypertarget{passing-command-line-arguments}{%
+\subsection{Passing command line
+arguments}\label{passing-command-line-arguments}}
+
+The basic conversion script provided by \TeX4ht~system is named
+\texttt{htlatex}. It 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 $tex4ht_options filename
+$ t4ht $t4ht_options filename
\end{verbatim}
The options for various parts of the system can be passed on the command
line:
\begin{verbatim}
-htlatex filename "tex4ht.sty options" "tex4ht_options" "t4ht_options" "latex_options"
+$ htlatex filename "tex4ht.sty options" "tex4ht_options" "t4ht_options" "latex_options"
\end{verbatim}
For basic \texttt{HTML} conversion it is possible to use the most basic
invocation:
\begin{verbatim}
-htlatex filename.tex
+$ htlatex filename.tex
\end{verbatim}
-It can be much more involved for \texttt{HTML\ 5} output in
+It can be much more involved for the \texttt{HTML\ 5} output in
\texttt{UTF-8} encoding:
\begin{verbatim}
-htlatex filename.tex "xhtml,html5,charset=utf-8" "-cmozhtf -utf8"
+$ htlatex filename.tex "xhtml,html5,charset=utf-8" " -cmozhtf -utf8"
\end{verbatim}
\texttt{make4ht} can simplify it:
\begin{verbatim}
-make4ht -uf html5 filename.tex
+$ make4ht -u filename.tex
\end{verbatim}
-Another issue is the fixed compilation order and hard-coded number of
-LaTeX invocations.
+The \texttt{-u} option requires the \texttt{UTF-8} encoding.
+\texttt{HTML\ 5} is used as the default output format by
+\texttt{make4ht}.
+
+More information about the command line arguments can be found in
+section \ref{sec:clioptions}.
+
+\hypertarget{compilation-sequence}{%
+\subsection{Compilation sequence}\label{compilation-sequence}}
+
+\texttt{htlatex} has a fixed compilation order and a hard-coded number
+of \LaTeX~invocations.
-When you need to run a program which interact with LaTeX, such as
-\texttt{Makeindex} or \texttt{Bibtex}, you need to create a new script
-based on \texttt{htlatex}, or run \texttt{htlatex} twice, which means
-that LaTeX will be invoked six times. This can lead to significantly
-long compilation times. \texttt{make4ht} provides build files and
-extensions, which can be used for interaction with external tools.
+It is not possible to execute additional commands during the
+compilation. When we want to run a program that interacts with \LaTeX,
+such as \texttt{Makeindex} or \texttt{Bibtex}, we have two options. The
+first option is to create a new script based on \texttt{htlatex} and add
+the wanted commands to the modified script. The second option is to
+execute \texttt{htlatex}, then the additional and then \texttt{htlatex}
+again. The second option means that \LaTeX~will be invoked six times, as
+each call to \texttt{htlatex} executes three calls to \LaTeX. This can
+lead to significantly long compilation times.
-It is also possible to have several compilation modes. When you just add
-new text to a document, which doesn't contain cross-references, don't
-add new stuff to the table of contents, etc., it is possible to use the
-\texttt{draft} mode which will invoke LaTeX only once. It can save quite
-a lot of the compilation time:
+\texttt{make4ht} provides a solution for this issue using a build file,
+or extensions. These can be used for interaction with external tools.
+
+\texttt{make4ht} also provides compilation modes, which enables to
+select commands that should be executed using a command line option.
+
+There is a built-in \texttt{draft} mode, which invokes \LaTeX~only once,
+instead of the default three invocations. It is useful for the
+compilations of the document before its final stage, when it is not
+important that all cross-references work. It can save quite a lot of the
+compilation time:
\begin{verbatim}
-make4ht -um draft -f html5 filename.tex
+$ make4ht -um draft filename.tex
\end{verbatim}
-There are also issues with a behaviour of the \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 a
-subdirectory, they will be copied to the output directory. Links will be
-pointing to a non-existing subdirectory. The following command should
-copy all output files to the correct destinations.
+More information about the build files can be found in section
+\ref{sec:buildfiles}.
+
+\hypertarget{handling-of-the-generated-files}{%
+\subsection{Handling of the generated
+files}\label{handling-of-the-generated-files}}
+
+\label{sec:output-dir}
+
+There are also issues with the behavior of the \texttt{t4ht}
+application. It reads the \texttt{.lg} file generated by the
+\texttt{tex4ht} command. This file contains information about the
+generated files, \texttt{CSS} instructions, calls to the external
+applications, instructions for image conversions, etc.
+
+\texttt{t4ht} can be instructed to copy the generated files to an output
+directory, but it doesn't preserve the directory structure. When the
+images are placed in a\\
+subdirectory, they will be copied to the output directory, losing the
+directory structure. Links will be pointing to a non-existing
+subdirectory. The following command should copy all output files to the
+correct destinations.
\begin{verbatim}
-make4ht -d outputdir filename.tex
+$ make4ht -d outputdir filename.tex
\end{verbatim}
-The image conversion is configured in the
-\href{http://www.tug.org/applications/tex4ht/mn35.html\#index35-73001}{env
-file}, which has really strange syntax based and the rules are
-\href{http://www.tug.org/applications/tex4ht/mn-unix.html\#index27-69005}{os
-dependent}. \texttt{make4ht} provides simpler means for the image
-conversion in the build files.
+\hypertarget{image-conversion-and-post-processing-of-the-generated-files}{%
+\subsection{Image conversion and post-processing of the generated
+files}\label{image-conversion-and-post-processing-of-the-generated-files}}
+
+\TeX4ht~can convert parts of the document to images. This is useful for
+diagrams or complicated math, for example.
-With \texttt{make4ht} build files, we have simple mean to fix these
-issues. We can change image conversion parameters without the need to
-modify the \texttt{env\ file}, or execute 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.
+By default, the image conversion is configured in a
+\href{http://www.tug.org/applications/tex4ht/mn35.html\#index35-73001}{\texttt{.env}
+file}. It has a bit of strange syntax, with
+\href{http://www.tug.org/applications/tex4ht/mn-unix.html\#index27-69005}{operating
+system dependent} rules. \texttt{make4ht} provides simpler means for the
+image conversion in the build files. It is possible to change the image
+conversion parameters without a need to modify the \texttt{.env} file.
+The process is described in section \ref{sec:imageconversion}.
-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 the build scripts are written.
+It is also possible to post-process the generated output files. The
+post-processing can be done either using external programs such as
+\texttt{XSLT} processors and \texttt{HTML\ Tidy} or using \texttt{Lua}
+functions. More information can be found in section
+\ref{sec:postprocessing}.
\hypertarget{output-file-formats-and-extensions}{%
\section{Output file formats and
extensions}\label{output-file-formats-and-extensions}}
-The default output format used by \texttt{make4ht} is \texttt{html5}.
-Different format can be requested using the \texttt{-\/-format} option.
+The default output format used by \texttt{make4ht} is \texttt{html5}. A
+different format can be requested using the \texttt{-\/-format} option.
Supported formats are:
\begin{itemize}
@@ -149,50 +291,63 @@ The extensions can be enabled or disabled by appending
\texttt{+EXTENSION} or \texttt{-EXTENSION} after the output format name:
\begin{verbatim}
- make4ht -uf html5+tidy filename.tex
+ $ make4ht -uf html5+tidy filename.tex
\end{verbatim}
Available extensions:
\begin{description}
-\item[latexmk\_build]
-use \texttt{Latexmk} for \LaTeX~compilation.
-\item[tidy]
-clean the \texttt{HTML} files using the \texttt{tidy} command.
-\item[dvisvgm\_hashes]
-efficient generation of SVG pictures using Dvisvgm. It can utilize
-multiple processor cores and generates only changed images.
\item[common\_filters]
clean the output HTML files using filters.
\item[common\_domfilters]
clean the HTML file using DOM filters. It is more powerful than
\texttt{common\_filters}. Used DOM filters are \texttt{fixinlines},
-\texttt{idcolons} and \texttt{joincharacters}.
+\texttt{idcolons}, \texttt{joincharacters}, and \texttt{tablerows}.
+\item[dvisvgm\_hashes]
+efficient generation of SVG pictures using Dvisvgm. It can utilize
+multiple processor cores and generates only changed images.
\item[join\_colors]
load the \texttt{joincolors} domfilter for all HTML files.
+\item[latexmk\_build]
+use \href{https://ctan.org/pkg/latexmk?lang=en}{Latexmk} for the
+\LaTeX~compilation.
\item[mathjaxnode]
use \href{https://github.com/pkra/mathjax-node-page/}{mathjax-node-page}
to convert from MathML code to HTML + CSS or SVG. See
\protect\hyperlink{mathjaxsettings}{the available settings}.
\item[odttemplate]
-automatically load the \texttt{odttemplate} filter.
+it automatically loads the \texttt{odttemplate} filter (page
+\pageref{sec:odttemplate}).
+\item[preprocess\_input]
+compilation of the formats supported by
+\href{https://yihui.name/knitr/}{Knitr} (\texttt{.Rnw}, \texttt{.Rtex},
+\texttt{.Rmd}, \texttt{.Rrst}) and also Markdown and reStructuredText
+formats. It requires \href{https://www.r-project.org/}{R} +
+\href{https://yihui.name/knitr/}{Knitr} installation, it requires also
+\href{https://pandoc.org/}{Pandoc} for formats based on Markdown or
+reStructuredText.
\item[staticsite]
-build the document in form suitable for static site generators like
+build the document in a form suitable for static site generators like
\href{https://jekyllrb.com/}{Jekyll}.
+\item[tidy]
+clean the \texttt{HTML} files using the \texttt{tidy} command.
\end{description}
\hypertarget{build-files}{%
\section{Build files}\label{build-files}}
+\label{sec:buildfiles}
+
\texttt{make4ht} supports build files. These are \texttt{Lua} scripts
-which can adjust the build process. You can request external
-applications like \texttt{bibtex} or \texttt{makeindex}, pass options to
+that can adjust the build process. They can request external
+applications like \texttt{BibTeX} or \texttt{Makeindex}, pass options to
the commands, modify the image conversion process, or post-process the
generated files.
\texttt{make4ht} tries to load default build file named as
-\texttt{filename\ +\ .mk4\ extension}. You can choose different build
-file with \texttt{-e} or \texttt{-\/-build-file} command line option.
+\texttt{filename\ +\ .mk4\ extension}. It is possible to select a
+different build file with \texttt{-e} or \texttt{-\/-build-file} command
+line option.
Sample build file:
@@ -201,184 +356,228 @@ 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, the \texttt{tidy} command is
-executed on the output \texttt{HTML} file.
+\texttt{Make:htlatex()} is preconfigured command for calling \LaTeX~with
+the \texttt{tex4ht.sty} package loaded. In this example, it will be
+executed only once. After the compilation, the \texttt{tidy} command is
+executed on the output \texttt{HTML} files.
-Note that you don't have to call \texttt{tex4ht} and \texttt{t4ht}
+Note that it is not necessary to call \texttt{tex4ht} and \texttt{t4ht}
commands explicitly in the build file, they are called automatically.
\hypertarget{user-commands}{%
\subsection{User commands}\label{user-commands}}
-You can add more commands like \texttt{Make:htlatex} using
+It is possible to add more commands like \texttt{Make:htlatex} using the
\texttt{Make:add} command:
\begin{verbatim}
-Make:add("name", "command", {parameters}, repetition)
+Make:add("name", "command", {settings table}, repetition)
\end{verbatim}
-The \texttt{name} and \texttt{command} parameters are required, rest of
-the parameters are optional.
+This defines the \texttt{name} command, which can be then executed using
+\texttt{Make:name()} command in the build file.
-This defines \texttt{name} command, which can be then executed as
-\texttt{Make:name()} command.
+The \texttt{name} and \texttt{command} parameters are required, the rest
+of the parameters are optional.
-\hypertarget{provided-commands}{%
-\subsubsection{Provided commands}\label{provided-commands}}
+The defined command receives a table with settings as a parameter at the
+call time. The default settings are provided by \texttt{make4ht}.
+Additional settings can be declared in the \texttt{Make:add} commands,
+user can also override the default settings when the command is executed
+in the build file:
-\begin{description}
-\item[\texttt{Make:htlatex}]
-One call to TeX engine with special configuration for \texttt{tex4ht}
-loading.
-\item[\texttt{Make:latexmk}]
-Use \texttt{Latexmk} for the document compilation. \texttt{tex4ht} will
-be loaded automatically.
-\item[\texttt{Make:tex4ht}]
-Process the \texttt{DVI} file and creates the output files.
-\item[\texttt{Make:t4ht}]
-Creates the CSS file.
-\end{description}
+\begin{verbatim}
+Make:name({hello="world"})
+\end{verbatim}
+
+More information about settings, including the default settings provided
+by \texttt{make4ht}, can be found in section \ref{sec:settings} on page
+\pageref{sec:settings}.
-\hypertarget{command-function}{%
-\subsubsection{Command function}\label{command-function}}
+\hypertarget{the-command-function}{%
+\subsubsection{\texorpdfstring{The \texttt{command}
+function}{The command function}}\label{the-command-function}}
-The \texttt{command} parameter can be either string template or
+\label{sec:commandfunction}
+
+The \texttt{command} parameter can be either a string template or
function:
\begin{verbatim}
Make:add("text", "echo hello, input file: ${input}")
-Make:add("function", function(params)
- for k, v in pairs(params) do
- print(k..": "..v)
- end, {custom="Hello world"}
-)
\end{verbatim}
-The template can get variable value from the parameters table using a
-\texttt{\$\{var\_name\}} placeholder. Templates are executed using
-operating system, so they should invoke existing OS commands. Function
-commands may execute system commands using \texttt{os.execute} function.
-
-\hypertarget{parameters-table}{%
-\subsubsection{Parameters table}\label{parameters-table}}
+The template can get a variable value from the parameters table using a
+\texttt{\$\{var\_name\}} placeholder. Templates are executed using the
+operating system, so they should invoke existing OS commands.
-\texttt{parameters} parameter is optional, it can be table or
-\texttt{nil} value, which should be used if you want to use the
-\texttt{repetition} parameter, but don't want to modify the parameters
-table.
+\hypertarget{the-settings-table-table}{%
+\subsubsection{\texorpdfstring{The \texttt{settings\ table}
+table}{The settings table table}}\label{the-settings-table-table}}
-The table with default parameters is passed to all commands, they can be
-accessed from command functions or templates. When you specify your own
-parameters in the command definition, these additional parameters are
-added to the default parameters table for this particular command. You
-can override the default parameters in the parameters table.
+The \texttt{settings\ table} parameter is optional. If it is present, it
+should be a table with new settings available in the command. It can
+also override the default \texttt{make4ht} settings for the defined
+command.
-The default parameters are following:
-
-\begin{description}
-\item[\texttt{htlatex}]
-used compiler
-\item[\texttt{input}]
-it is output file name in fact
-\item[\texttt{tex\_file}]
-input TeX file
-\item[\texttt{latex\_par}]
-parameters to \texttt{latex}
-\item[\texttt{packages}]
-insert additional LaTeX code which is inserted before
-\texttt{\textbackslash{}documentclass}. Useful for passing options to
-packages or additional packages loading
-\item[\texttt{tex4ht\_sty\_par}]
-parameters to \texttt{tex4ht.sty}
-\item[\texttt{tex4ht\_par}]
-parameters to the \texttt{tex4ht} application
-\item[\texttt{t4ht\_par}]
-parameters to the \texttt{t4ht} application
-\item[\texttt{outdir}]
-the output directory
-\item[\texttt{repetition}]
-limit number of command execution.
-\item[\texttt{correct\_exit}]
-expected \texttt{exit\ code} from the command. The compilation will be
-terminated if the command \texttt{exit\ code} is different.
-\end{description}
+\begin{verbatim}
+Make:add("sample_function", function(params)
+ for k, v in pairs(params) do
+ print(k..": "..v)
+ end, {custom="Hello world"}
+)
+\end{verbatim}
\hypertarget{repetition}{%
\subsubsection{Repetition}\label{repetition}}
-Repetition is number which specifies a maximal number of executions of
-the particular command. This is used for instance for \texttt{tex4ht}
-and \texttt{t4ht} commands, as they should be executed only once in the
-compilation. They would be executed multiple times if you include them
-in the build file because they are called by \texttt{make4ht} by
-default. Because these commands allow only one \texttt{repetition}, the
-second execution will be blocked.
+The \texttt{repetition} parameter specifies the maximum number of
+executions of the particular command. This is used for instance for
+\texttt{tex4ht} and \texttt{t4ht} commands, as they should be executed
+only once in the compilation. They would be executed multiple times when
+they are included in the build file, as they are called by
+\texttt{make4ht} by default. Because these commands allow only one
+\texttt{repetition}, the second execution is blocked.
\hypertarget{expected-exit-code}{%
\subsubsection{Expected exit code}\label{expected-exit-code}}
You can set the expected exit code from a command with a
-\texttt{correct\_exit} key in the parameters table. The compilation will
-be stopped when the command returns a different exit code.
-
-This mechanism isn't used for LaTeX (for all TeX engines and formats, in
-fact), because it doesn't differentiate between fatal and non-fatal
-errors, and it returns the 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. The \texttt{Make.testlogfile}
+\texttt{correct\_exit} key in the settings table. The compilation will
+be terminated when the command returns a different exit code.
+
+\begin{verbatim}
+Make:add("biber", "biber ${input}", {correct_exit=0})
+\end{verbatim}
+
+Commands that execute lua functions can return the numerical values
+using the \texttt{return} statement.
+
+This mechanism isn't used for \TeX, because it doesn't differentiate
+between fatal and non-fatal errors. It returns the same exit code in all
+cases. Because of this, log parsing is used for a fatal error detection
+instead. Error code value \texttt{1} is returned in the case of a fatal
+error, \texttt{0} is used otherwise. The \texttt{Make.testlogfile}
function can be used in the build file to detect compilation errors in
the TeX log file.
+\hypertarget{provided-commands}{%
+\subsection{Provided commands}\label{provided-commands}}
+
+\begin{description}
+\item[\texttt{Make:htlatex}]
+One call to the TeX engine with special configuration for loading of the
+\texttt{tex4ht.sty} package.
+\item[\texttt{Make:latexmk}]
+Use \texttt{Latexmk} for the document compilation. \texttt{tex4ht.sty}
+will be loaded automatically.
+\item[\texttt{Make:tex4ht}]
+Process the \texttt{DVI} file and create output files.
+\item[\texttt{Make:t4ht}]
+Create the CSS file and generate images.
+\item[\texttt{Make:biber}]
+Process bibliography using the \texttt{biber} command.
+\item[\texttt{Make:bibtex}]
+Process bibliography using the \texttt{bibtex} command.
+\item[\texttt{Make:xindy}]
+Generate index using Xindy index processor.
+\item[\texttt{Make:makeindex}]
+Generate index using the Makeindex command.
+\item[\texttt{Make:xindex}]
+Generate index using the Xindex command.
+\end{description}
+
\hypertarget{file-matches}{%
\subsection{File matches}\label{file-matches}}
-Another type of action which can be specified in the build file is
-\texttt{match}. It can be called on the generated files:
+\label{sec:postprocessing}
+
+Another type of action that can be specified in the build file is
+\texttt{Make:match}. It can be used to post-process the generated files:
\begin{verbatim}
Make:match("html$", "tidy -m -xml -utf8 -q -i ${filename}")
\end{verbatim}
-It tests output file names with \texttt{Lua} pattern matching and on
-matched items will execute a command or a function, specified in the
-second argument. Commands may be specified as strings, the templates
-will be expanded, \texttt{\$\{var\_name\}} placeholders will be replaced
-with corresponding variables from the \texttt{parameters} table,
-described in the previous subsection. One additional variable is
-available: \texttt{filename}. It contains the name of the current output
-file.
-
The above example will clean all output \texttt{HTML} files using the
\texttt{tidy} command.
-If function is used instead, it will get two parameters. The first one
-is a current filename, the second one table with parameters.
+The \texttt{Make:match} action tests output filenames using a
+\texttt{Lua} pattern matching function.\\
+It executes a command or a function, specified in the second argument,
+on files whose filenames match the pattern.
+
+The commands to be executed can be specified as strings. They can
+contain \texttt{\$\{var\_name\}} placeholders, which are replaced with
+corresponding variables from the \texttt{settings} table. The templating
+system was described in subsection \ref{sec:commandfunction}. There is
+an additional variable available in this table, called
+\texttt{filename}. It contains the name of the current output file.
+
+If a function is used instead, it will get two parameters. The first one
+is the current filename, the second one is the \texttt{settings} table.
+
+\begin{verbatim}
+Make:match("html$", function(filename, settings)
+ print("Post-processing file: ".. filename)
+ print("Available settings")
+ for k,v in pairs(settings)
+ print(k,v)
+ end
+ return true
+\end{verbatim}
+
+end)
+
+Multiple post-processing actions can be executed on each filename. The
+Lua action functions can return an exit code. If the exit code is false,
+the execution of the post-processing chain for the current file will be
+terminated.
\hypertarget{filters}{%
\subsubsection{Filters}\label{filters}}
-Some default \texttt{match} actions which can be used are available from
-the \texttt{make4ht-filter} module. It contains some functions which are
-useful for fixing some \texttt{tex4ht} bugs or shortcomings.
+\label{sec:filters}
-Example:
+To make it easier to post-process the generated files using the
+\texttt{match} actions, \texttt{make4ht} provides a filtering mechanism
+thanks to the \texttt{make4ht-filter} module.
+
+The \texttt{make4ht-filter} module returns a function that can be used
+for the filter chain building. Multiple filters can be chained into a
+pipeline. Each filter can modify the string that is passed to it from
+the previous filters. The changes are then saved to the processed file.
+
+Several built-in filters are available, it is also possible to create
+new ones.
+
+Example that use only the built-in filters:
\begin{verbatim}
local filter = require "make4ht-filter"
local process = filter{"cleanspan", "fixligatures", "hruletohr"}
Make:htlatex()
+Make:match("html$",process)
+\end{verbatim}
+
+Function \texttt{filter} accepts also function arguments, in this case
+this function takes file contents as a parameter and modified contents
+are returned.
+
+Example with custom filter:
+
+\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:match("html$",process)
\end{verbatim}
-The \texttt{make4ht-filter} module return a function which can be used
-for the filter chain building. Multiple filters can be chained, each of
-them can modify the string which was modified by the previous filters.
-The changes are then saved to the processed file.
+In this example, spurious span elements are joined, ligatures are
+decomposed, and then all letters ``a'' are replaced with ``z'' letters.
-Built-in filters are:
+Built-in filters are the following:
\begin{description}
\item[cleanspan]
@@ -389,16 +588,15 @@ alternative clean span filter, provided by Nat Kuhn
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
+underscore characters by \TeX4ht, this filter translates 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)
+convert prohibited named entities to numeric entities (only
+\texttt{\&nbsp;} currently).
\item[fix-links]
replace colons in local links and \texttt{id} attributes with
underscores. Some cross-reference commands may produce colons in
-internal links, which results in validation error.
+internal links, which results in a validation error.
\item[mathjaxnode]
use \href{https://github.com/pkra/mathjax-node-page/}{mathjax-node-page}
to convert from MathML code to HTML + CSS or SVG. See
@@ -407,39 +605,22 @@ to convert from MathML code to HTML + CSS or SVG. See
use styles from another \texttt{ODT} file serving as a template in the
current document. It works for the \texttt{styles.xml} file in the
\texttt{ODT} file. During the compilation, this file is named as
-\texttt{\textbackslash{}jobname.4oy}.
+\texttt{\textbackslash{}jobname.4oy}. \label{sec:odttemplate}
\item[staticsite]
-create HTML files in format suitable for static site generators such as
-\href{https://jekyllrb.com/}{Jekyll}
+create HTML files in a format suitable for static site generators such
+as \href{https://jekyllrb.com/}{Jekyll}
\item[svg-height]
some SVG images produced by \texttt{dvisvgm} seem to have wrong
dimensions. This filter tries to set the correct image size.
\end{description}
-Function \texttt{filter} accepts also function arguments, in this case
-this function takes file contents as a 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 example, spurious span elements are joined, ligatures are
-decomposed, and then all letters `a' are replaced with `z' letters.
-
\hypertarget{dom-filters}{%
\subsubsection{DOM filters}\label{dom-filters}}
-DOM filters use the \href{https://ctan.org/pkg/luaxml}{\texttt{LuaXML}}
-library to modify directly the XML object. This enables more powerful
-operations than the regex based filters from the previous section.
+DOM filters are variants of filters that use the
+\href{https://ctan.org/pkg/luaxml}{\texttt{LuaXML}} library to modify
+directly the XML object. This enables more powerful operations than the
+regex-based filters from the previous section.
Example:
@@ -455,7 +636,10 @@ Available DOM filters:
\item[aeneas]
\href{https://www.readbeyond.it/aeneas/}{Aeneas} is a tool for
automagical synchronization of text and audio. This filter modifies the
-HTML code to support the synchronization.
+HTML code to support synchronization.
+\item[collapsetoc]
+collapse table of contents to contain only top-level sectioning level
+and sections on the current page.
\item[fixinlines]
put all inline elements which are direct children of the
\texttt{\textless{}body\textgreater{}} elements to a paragraph.
@@ -464,198 +648,65 @@ replace the colon (\texttt{:}) character in internal links and
\texttt{id} attributes. They cause validation issues.
\item[joincharacters]
join consecutive \texttt{\textless{}span\textgreater{}} or
-\texttt{\textless{}mn\textgreater{}} elements.
+\texttt{\textless{}mn\textgreater{}} elements. This DOM filter
+supersedes the \texttt{cleanspan} filter.
\item[joincolors]
many \texttt{\textless{}span\textgreater{}} elements with unique
-\texttt{id} attribute are created when \LaTeX~colors are being used in
-the document. CSS rule is added for each of these elements, which may
-result in substantial grow of the CSS file. This filter replace these
+\texttt{id} attributes are created when \LaTeX~colors are being used in
+the document. A CSS rule is added for each of these elements, which may
+result in substantial growth of the CSS file. This filter replaces these
rules with a common one for elements with the same color value.
\item[odtimagesize]
set correct dimensions for images in the ODT format. It is loaded by
default for the ODT output.
+\item[odtpartable]
+resolve tables nested inside paragraphs, which is invalid in the ODT
+format.
+\item[tablerows]
+remove spurious rows from HTML tables.
\item[t4htlinks]
fix hyperlinks in the ODT format.
\end{description}
-\hypertarget{make4ht-aeneas-config-package}{%
-\subsubsection{make4ht-aeneas-config
-package}\label{make4ht-aeneas-config-package}}
-
-Companion for the \texttt{aeneas} DOM filter is the
-\texttt{make4ht-aeneas-config} plugin. It can be used to write Aeneas
-configuration file or execute Aeneas on the generated HTML files.
-
-Available functions:
-
-\begin{description}
-\item[write\_job(parameters)]
-write Aenas job configuration to \texttt{config.xml} file. See the
-\href{https://www.readbeyond.it/aeneas/docs/clitutorial.html\#processing-jobs}{Aeneas
-documentation} for more information about jobs.
-\item[execute(parameters)]
-execute Aeneas.
-\item[process\_files(parameters)]
-process the audio and generated subtitle files.
-\end{description}
-
-By default, the \texttt{smil} file is created. It is assumed that there
-is audio file in \texttt{mp3} format named as the TeX file. It is
-possible to use different formats and file names using mapping.
-
-The configuration options can be passed directly to the functions or set
-using \texttt{filter\_settings\ "aeneas-config"\ \{parameters\}}
-function.
-
-Available parameters:
-
-\begin{description}
-\item[lang]
-document language. It is interfered from the HTML file, so it is not
-necessary to set it.
-\item[map]
-mapping between HTML, audio and subtitle files. More info bellow.
-\item[text\_type]
-type of the input. The \texttt{aeneas} DOM filter produces
-\texttt{unparsed} text type.
-\item[id\_sort]
-sorting of id attributes. Default value is \texttt{numeric}.
-\item[id\_regex]
-regular expression to parse the id attributes.
-\item[sub\_format]
-generated subtitle format. Default \texttt{smil}.
-\end{description}
-
-Additional parameters for the job configuration file:
-
-\begin{itemize}
-\tightlist
-\item
- description
-\item
- prefix
-\item
- config\_name
-\item
- keep\_config
-\end{itemize}
-
-It is possible to generate multiple HTML files from the LaTeX source.
-For example, \texttt{tex4ebook} generates separate file for each chapter
-or section. It is possible to set options for each HTML file, in
-particular names of the corresponding audio files. This mapping is done
-using \texttt{map} parameter.
-
-Example:
-
-\begin{verbatim}
-filter_settings "aeneas-config" {
- map = {
- ["sampleli1.html"] = {audio_file="sample.mp3"},
- ["sample.html"] = false
- }
-}
-\end{verbatim}
-
-Table keys are the configured file names. It is necessary to insert them
-as \texttt{{[}"filename.html"{]}}, because of Lua syntax rules.
-
-This example maps audio file \texttt{sample.mp3} to a section subpage.
-The main HTML file, which may contain title and table of contents
-doesn't have a corresponding audio file.
-
-Filenames of the sub files corresponds to the chapter numbers, so they
-are not stable when a new chapter is added. It is possible to request
-file names interfered from the chapter titles using the
-\texttt{sec-filename} option or \texttt{tex4ht}.
-
-Available \texttt{map} options:
-
-\begin{description}
-\item[audio\_file]
-the corresponding audio file
-\item[sub\_file]
-name of the generated subtitle file
-\end{description}
-
-The following options are same as their counter-parts from the main
-parameters table and generally don't need to be set:
-
-\begin{itemize}
-\tightlist
-\item
- prefix
-\item
- file\_desc
-\item
- file\_id
-\item
- text\_type
-\item
- id\_sort
-\item
- id\_prefix
-\item
- sub\_format
-\end{itemize}
-
-Full example:
-
-\begin{verbatim}
-local domfilter = require "make4ht-domfilter"
-local aeneas_config = require "make4ht-aeneas-config"
-
-filter_settings "aeneas-config" {
- map = {
- ["krecekli1.xhtml"] = {audio_file="krecek.mp3"},
- ["krecek.xhtml"] = false
- }
-}
-
-local process = domfilter {"aeneas"}
-Make:match("html$", process)
-
-if mode == "draft" then
- aeneas_config.process_files {}
-else
- aeneas_config.execute {}
-end
-\end{verbatim}
-
\hypertarget{image-conversion}{%
\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}.
+\label{sec:imageconversion}
-These pictures are stored in a special \texttt{dvi} file, which can be
-processed by the \texttt{dvi\ to\ image} commands.
+It is possible to convert parts of the \LaTeX~input as pictures. It can
+be used for preserving the appearance of math or diagrams, for example.
-This conversion is normally configured in the \texttt{env\ file}, which
-is system dependent and which has a bit unintuitive syntax. This
-configuration is processed by the \texttt{t4ht} application and
-conversion commands are called for all pictures.
+These pictures are stored in a special \texttt{DVI} file, which can be
+processed by a \texttt{DVI} to image commands, such as \texttt{dvipng}
+or \texttt{dvisvgm}.
+
+This conversion is normally configured in the \texttt{tex4ht.env} file.
+This file is system dependent and it has quite an unintuitive syntax.
+The configuration is processed by the \texttt{t4ht} application and the
+conversion command is called for all pictures.
It is possible to disable \texttt{t4ht} image processing and configure
-image conversion in the build file:
+image conversion in the build file using the \texttt{image} action:
\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 a table with parameters as an argument.
+\texttt{Make:image} takes two parameters, a \texttt{Lua} pattern to
+match the image name, and the action.
+
+Action can be either a string template with the conversion command or a
+function that takes a table with parameters as an argument.
There are three parameters:
\begin{itemize}
\tightlist
\item
- \texttt{output} - output image file name
+ \texttt{output} - output image filename
\item
- \texttt{source} - \texttt{dvi} file with the pictures
+ \texttt{source} - \texttt{DVI} file with the pictures
\item
\texttt{page} - page number of the converted image
\end{itemize}
@@ -664,9 +715,9 @@ There are three parameters:
\subsection{\texorpdfstring{The \texttt{mode}
variable}{The mode variable}}\label{the-mode-variable}}
-There is global \texttt{mode} variable available in the build file. It
-contains contents of the \texttt{-\/-mode} command line option. It can
-be used to run some commands conditionally. For example:
+The \texttt{mode} variable available in the build process contains
+contents of the \texttt{-\/-mode} command line option. It can be used to
+run some commands conditionally. For example:
\begin{verbatim}
if mode == "draft" then
@@ -679,8 +730,8 @@ be used to run some commands conditionally. For example:
\end{verbatim}
In this example (which is the default configuration used by
-\texttt{make4ht}), LaTeX is called only once when \texttt{make4ht} is
-called with \texttt{draft} mode:
+\texttt{make4ht}), \LaTeX~is called only once when \texttt{make4ht} is
+called with the \texttt{draft} mode:
\begin{verbatim}
make4ht -m draft filename
@@ -690,10 +741,12 @@ make4ht -m draft filename
\subsection{\texorpdfstring{The \texttt{settings}
table}{The settings table}}\label{the-settings-table}}
-You may want to access to the parameters also outside commands, file
-matches and image conversion functions. For example, if you want to
-convert your file to the \texttt{OpenDocument\ Format\ (ODT)}, you can
-use the following settings, based on the \texttt{oolatex} command:
+\label{sec:settings}
+
+It is possible to access the parameters outside commands, file matches
+and image conversion functions. For example, to convert the document to
+the \texttt{OpenDocument\ Format\ (ODT)}, the following settings can be
+used. They are based on the \texttt{oolatex} command:
\begin{verbatim}
settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",ooffice"
@@ -701,7 +754,11 @@ settings.tex4ht_par = settings.tex4ht_par .. " ooffice/! -cmozhtf"
settings.t4ht_par = settings.t4ht_par .. " -cooxtpipes -coo "
\end{verbatim}
-There are some functions to ease access to the settings:
+(Note that it is possible to use the \texttt{-\/-format\ odt} option
+which is superior to the previous code. This example is intended just as
+an illustration)
+
+There are some functions to simplify access to the settings:
\begin{description}
\item[\texttt{set\_settings\{parameters\}}]
@@ -714,8 +771,8 @@ set settings for a filter
get settings for a filter
\end{description}
-Using these functions, it is possible to simplify the settings for the
-\texttt{ODT} format:
+For example, it is possible to simplify the sample from the previous
+code listings:
\begin{verbatim}
settings_add {
@@ -734,8 +791,8 @@ filter_settings "test" {
}
\end{verbatim}
-These settings can be read in the extensions and filters using
-\texttt{get\_filter\_settings}:
+These settings can be retrieved in the extensions and filters using the
+\texttt{get\_filter\_settings} function:
\begin{verbatim}
function test(input)
@@ -746,14 +803,153 @@ end
\end{verbatim}
+\hypertarget{default-settings}{%
+\subsubsection{Default settings}\label{default-settings}}
+
+The default parameters are the following:
+
+\begin{description}
+\item[\texttt{htlatex}]
+used \TeX~engine
+\item[\texttt{input}]
+content of \texttt{\textbackslash{}jobname}, see also the
+\texttt{tex\_file} parameter.
+\item[\texttt{interaction}]
+interaction mode for the \TeX~engine. The default value is
+\texttt{batchmode} to suppress user input on compilation errors. It also
+suppresses most of the \TeX~ compilation log output. Use the
+\texttt{errorstopmode} for the default behavior.
+\item[\texttt{tex\_file}]
+input \TeX~filename
+\item[\texttt{latex\_par}]
+command line parameters to the \TeX~engine
+\item[\texttt{packages}]
+additional \LaTeX~code inserted before
+\texttt{\textbackslash{}documentclass}. Useful for passing options to
+packages used in the document or to load additional packages.
+\item[\texttt{tex4ht\_sty\_par}]
+options for \texttt{tex4ht.sty}
+\item[\texttt{tex4ht\_par}]
+command line options for the \texttt{tex4ht} command
+\item[\texttt{t4ht\_par}]
+command line options for the \texttt{t4ht} command
+\item[\texttt{outdir}]
+the output directory
+\item[\texttt{correct\_exit}]
+expected \texttt{exit\ code} from the command. The compilation will be
+terminated if the exit code of the executed command has a different
+value.
+\end{description}
+
+\hypertarget{configfile}{%
+\section{Configuration file}\label{configfile}}
+
+It is possible to globally modify the build settings using the
+configuration file. It is a special version of a build file where the
+global settings can be set.
+
+Common tasks for the configuration file can be a declaration of the new
+commands, loading of the default filters or specification of a default
+build sequence.
+
+One additional functionality not available in the build files are
+commands for enabling and disabling of extensions.
+
+\hypertarget{location}{%
+\subsection{Location}\label{location}}
+
+The configuration file can be saved either in the
+\texttt{\$HOME/.config/make4ht/config.lua} file, or in the
+\texttt{.make4ht} file placed in the current directory or it's parent
+directories (up to the \texttt{\$HOME} directory).
+
+\hypertarget{additional-commands}{%
+\subsection{Additional commands}\label{additional-commands}}
+
+There are two additional commands:
+
+\begin{description}
+\item[\texttt{Make:enable\_extension(name)}]
+require extension
+\item[\texttt{Make:disable\_extension(name)}]
+disable extension
+\end{description}
+
+\hypertarget{example}{%
+\subsection{Example}\label{example}}
+
+The following example of the configuration file adds support for the
+\texttt{biber} command, requires \texttt{common\_domfilters} extension
+and requires MathML output for math.
+
+\begin{verbatim}
+Make:add("biber", "biber ${input}")
+Make:enable_extension "common_domfilters"
+settings_add {
+ tex4ht_sty_par =",mathml"
+}
+\end{verbatim}
+
\hypertarget{list-of-available-settings-for-filters-and-extensions.}{%
-\subsection{List of available settings for filters and
+\section{List of available settings for filters and
extensions.}\label{list-of-available-settings-for-filters-and-extensions.}}
-These settings may be set using \texttt{filter\_settings} function.
+These settings may be set using \texttt{filter\_settings} function in a
+build file or in the \texttt{make4ht} configuration file.
+
+\hypertarget{indexing-commands}{%
+\subsection{Indexing commands}\label{indexing-commands}}
+
+The indexing commands (like \texttt{xindy} or \texttt{makeindex}) use
+some common settings.
+
+\begin{description}
+\item[idxfile]
+name of the \texttt{.idx} file. Default value is
+\texttt{\textbackslash{}jobname.idx}.
+\item[indfile]
+name of the \texttt{.ind} file. Default value is the same as
+\texttt{idxfile} with the file extension changed to \texttt{.ind}.
+\end{description}
+
+Each indexing command can have some additional settings.
+
+\hypertarget{the-xindy-command}{%
+\subsubsection{\texorpdfstring{The \texttt{xindy}
+command}{The xindy command}}\label{the-xindy-command}}
+
+\begin{description}
+\item[encoding]
+text encoding of the \texttt{.idx} file. Default value is \texttt{utf8}.
+\item[language]
+index language. Default language is English.
+\item[modules]
+table with names of additional \texttt{Xindy} modules to be used.
+\end{description}
+
+\hypertarget{the-makeindex-command}{%
+\subsubsection{\texorpdfstring{The \texttt{makeindex}
+command}{The makeindex command}}\label{the-makeindex-command}}
+
+options
+
+: additional command line options for the Makeindex command.
+
+\hypertarget{the-xindex-command}{%
+\subsubsection{\texorpdfstring{The \texttt{xindex}
+command}{The xindex command}}\label{the-xindex-command}}
+
+options
+
+: additional command line options for the Xindex command.
+
+\begin{description}
+\item[language]
+document language
+\end{description}
\hypertarget{the-tidy-extension}{%
-\subsubsection{\texorpdfstring{The \texttt{tidy}
+\subsection{\texorpdfstring{The \texttt{tidy}
extension}{The tidy extension}}\label{the-tidy-extension}}
\begin{description}
@@ -762,13 +958,37 @@ command line options for the \texttt{tidy} command. Default value is
\texttt{-m\ -utf8\ -w\ 512\ -q}.
\end{description}
+\hypertarget{the-collapsetoc-dom-filter}{%
+\subsection{\texorpdfstring{The \texttt{collapsetoc} dom
+filter}{The collapsetoc dom filter}}\label{the-collapsetoc-dom-filter}}
+
+\begin{description}
+\item[\texttt{toc\_query}]
+CSS selector for selecting the table of contents container.
+\item[\texttt{title\_query}]
+CSS selector for selecting all elements that contain the section ID
+attribute.
+\item[\texttt{toc\_levels}]
+table containing a hierarchy of classes used in TOC
+\end{description}
+
+Default values:
+
+\begin{verbatim}
+filter_settings "collapsetoc" {
+ toc_query = ".tableofcontents",
+ title_query = ".partHead a, .chapterHead a, .sectionHead a, .subsectionHead a",
+ toc_levels = {"partToc", "chapterToc", "sectionToc", "subsectionToc", "subsubsectionToc"}
+}
+\end{verbatim}
+
\hypertarget{the-fixinlines-dom-filter}{%
-\subsubsection{\texorpdfstring{The \texttt{fixinlines} dom
+\subsection{\texorpdfstring{The \texttt{fixinlines} dom
filter}{The fixinlines dom filter}}\label{the-fixinlines-dom-filter}}
\begin{description}
\item[inline\_elements]
-table of inline elements which shouldn't be direct descendants of the
+table of inline elements that shouldn't be direct descendants of the
\texttt{body} element. The element names should be table keys, the
values should be true.
\end{description}
@@ -780,23 +1000,24 @@ filter_settings "fixinlines" {inline_elements = {a = true, b = true}}
\end{verbatim}
\hypertarget{the-joincharacters-dom-filter}{%
-\subsubsection{\texorpdfstring{The \texttt{joincharacters} dom
+\subsection{\texorpdfstring{The \texttt{joincharacters} dom
filter}{The joincharacters dom filter}}\label{the-joincharacters-dom-filter}}
\begin{description}
-\item[charelements]
-table of elements which should be joined if several instances with the
-same value of \texttt{class} attribute are side by side.
+\item[charclasses]
+table of elements that should be concatenated when two or more of such
+elements with the same value of the \texttt{class} attribute are placed
+one after another.
\end{description}
Example
\begin{verbatim}
-filter_settings "joincharacters" { charclases = { span=true, mn = true}}
+filter_settings "joincharacters" { charclasses = { span=true, mn = true}}
\end{verbatim}
\hypertarget{mathjaxsettings}{%
-\subsubsection{\texorpdfstring{The \texttt{mathjaxnode}
+\subsection{\texorpdfstring{The \texttt{mathjaxnode}
filter}{The mathjaxnode filter}}\label{mathjaxsettings}}
\begin{description}
@@ -815,12 +1036,12 @@ filter_settings "mathjaxnode" {
\begin{description}
\item[cssfilename]
-\texttt{mjpage} puts some CSS code into the HTML pages.
+the \texttt{mjpage} command puts some CSS code into the HTML pages.
\texttt{mathjaxnode} extracts this information and saves it to a
standalone CSS file. Default CSS filename is \texttt{mathjax-chtml.css}
\item[fontdir]
-directory with MathJax font files. This option enables use of local
-fonts, which is usefull in Epub conversion, for example. The font
+directory with MathJax font files. This option enables the use of local
+fonts, which is useful in the conversion to ePub, for example. The font
directory should be sub-directory of the current directory. Only TeX
font is supported at the moment.
\end{description}
@@ -833,37 +1054,22 @@ filter_settings "mathjaxnode" {
}
\end{verbatim}
-\hypertarget{the-aeneas-filter}{%
-\subsubsection{\texorpdfstring{The \texttt{aeneas}
-filter}{The aeneas filter}}\label{the-aeneas-filter}}
-
-\begin{description}
-\item[skip\_elements]
-List of CSS selectors that match elements which shouldn't be processed.
-Default value: \texttt{\{\ "math",\ "svg"\}}.
-\item[id\_prefix]
-prefix used in the ID attribute forming.
-\item[sentence\_match]
-Lua pattern used to match a sentence. Default value:
-\texttt{"({[}\^{}\%.\^{}\%?\^{}!{]}*)({[}\%.\%?!{]}?)"}.
-\end{description}
-
\hypertarget{the-staticsite-filter-and-extension}{%
-\subsubsection{\texorpdfstring{The \texttt{staticsite} filter and
+\subsection{\texorpdfstring{The \texttt{staticsite} filter and
extension}{The staticsite filter and extension}}\label{the-staticsite-filter-and-extension}}
\begin{description}
\item[site\_root]
directory where generated files should be copied.
\item[map]
-table where keys are patterns that match filenames, value contains
-destination directoryfor matched files, relative to the
-\texttt{site\_root} (it is possible to use \texttt{..} to swich to
-parent directory).
+a hash table where keys contain patterns that match filenames and values
+contain destination directory for the matched files. The destination
+directories are relative to the \texttt{site\_root} (it is possible to
+use \texttt{..} to switch to a parent directory).
\item[file\_pattern]
-pattern used for filename generation. It is possible to use string
-templates and format strings for \texttt{os.date} function. Default
-value of \texttt{\%Y-\%m-\%d-\$\{input\}} creates names in the form of
+a pattern used for filename generation. It is possible to use string
+templates and format strings for \texttt{os.date} function. The default
+pattern \texttt{\%Y-\%m-\%d-\$\{input\}} creates names in the form of
\texttt{YYYY-MM-DD-file\_name}.
\item[header]
table with variables to be set in the YAML header in HTML files. If the
@@ -891,7 +1097,7 @@ filter_settings "staticsite" {
\end{verbatim}
\hypertarget{the-dvisvgm_hashes-extension}{%
-\subsubsection{\texorpdfstring{The \texttt{dvisvgm\_hashes}
+\subsection{\texorpdfstring{The \texttt{dvisvgm\_hashes}
extension}{The dvisvgm\_hashes extension}}\label{the-dvisvgm_hashes-extension}}
\begin{description}
@@ -899,18 +1105,18 @@ extension}{The dvisvgm\_hashes extension}}\label{the-dvisvgm_hashes-extension}}
command line options for Dvisvgm. The default value is
\texttt{-n\ -\/-exact\ -c\ 1.15,1.15}.
\item[cpu\_cnt]
-number of processor cores used for conversion. The extension tries to
-detect the available cores automatically by default.
+the number of processor cores used for the conversion. The extension
+tries to detect the available cores automatically by default.
\item[parallel\_size]
-number of pages used in each Dvisvgm call. The extension detects changed
-pages in the DVI file and construct multiple calls to Dvisvgm with only
-changed pages.
+the number of pages used in each Dvisvgm call. The extension detects
+changed pages in the DVI file and constructs multiple calls to Dvisvgm
+with only changed pages.
\item[scale]
SVG scaling.
\end{description}
\hypertarget{the-odttemplate-filter-and-extension}{%
-\subsubsection{\texorpdfstring{The \texttt{odttemplate} filter and
+\subsection{\texorpdfstring{The \texttt{odttemplate} filter and
extension}{The odttemplate filter and extension}}\label{the-odttemplate-filter-and-extension}}
\begin{description}
@@ -920,108 +1126,175 @@ filename of the template \texttt{ODT} file
\texttt{odttemplate} can also get the template filename from the
\texttt{odttemplate} option from \texttt{tex4ht\_sty\_par} parameter. It
-can be set useing following command line call, for example:
+can be set using the following command line call:
\begin{verbatim}
make4ht -f odt+odttemplate filename.tex "odttemplate=template.odt"
\end{verbatim}
-\hypertarget{configfile}{%
-\section{Configuration file}\label{configfile}}
+\hypertarget{the-aeneas-filter}{%
+\subsection{\texorpdfstring{The \texttt{aeneas}
+filter}{The aeneas filter}}\label{the-aeneas-filter}}
-It is possible to globally modify the build settings using the
-configuration file. New compilation commands can be added, extensions
-can be loaded or disabled and settings can be set.
+\begin{description}
+\item[skip\_elements]
+List of CSS selectors that match elements that shouldn't be processed.
+Default value: \texttt{\{\ "math",\ "svg"\}}.
+\item[id\_prefix]
+prefix used in the ID attribute forming.
+\item[sentence\_match]
+Lua pattern used to match a sentence. Default value:
+\texttt{"({[}\^{}\%.\^{}\%?\^{}!{]}*)({[}\%.\%?!{]}?)"}.
+\end{description}
-\hypertarget{location}{%
-\subsection{Location}\label{location}}
+\hypertarget{the-make4ht-aeneas-config-package}{%
+\subsection{\texorpdfstring{The \texttt{make4ht-aeneas-config}
+package}{The make4ht-aeneas-config package}}\label{the-make4ht-aeneas-config-package}}
-The configuration file can be saved either in
-\texttt{\$HOME/.config/make4ht/config.lua} or in \texttt{.make4ht} in
-the current directory or it's parents (up to \texttt{\$HOME}).
+Companion for the \texttt{aeneas} DOM filter is the
+\texttt{make4ht-aeneas-config} plugin. It can be used to write the
+Aeneas configuration file or execute Aeneas on the generated HTML files.
-\hypertarget{additional-commands}{%
-\subsection{Additional commands}\label{additional-commands}}
+Available functions:
-There are two additional commands:
+\begin{description}
+\item[write\_job(parameters)]
+write Aenas job configuration to \texttt{config.xml} file. See the
+\href{https://www.readbeyond.it/aeneas/docs/clitutorial.html\#processing-jobs}{Aeneas
+documentation} for more information about jobs.
+\item[execute(parameters)]
+execute Aeneas.
+\item[process\_files(parameters)]
+process the audio and generated subtitle files.
+\end{description}
+
+By default, a \texttt{SMIL} file is created. It is assumed that there is
+an audio file in the \texttt{mp3} format, named as the \TeX~file. It is
+possible to use different formats and filenames using mapping.
+
+The configuration options can be passed directly to the functions or set
+using \texttt{filter\_settings\ "aeneas-config"\ \{parameters\}}
+function.
+
+\hypertarget{available-parameters}{%
+\subsubsection{Available parameters}\label{available-parameters}}
\begin{description}
-\item[\texttt{Make:enable\_extension(name)}]
-require extension
-\item[\texttt{Make:disable\_extension(name)}]
-disable extension
+\item[lang]
+document language. It is interfered from the HTML file, so it is not
+necessary to set it.
+\item[map]
+mapping between HTML, audio and subtitle files. More info below.
+\item[text\_type]
+type of input. The \texttt{aeneas} DOM filter produces an
+\texttt{unparsed} text type.
+\item[id\_sort]
+sorting of id attributes. The default value is \texttt{numeric}.
+\item[id\_regex]
+regular expression to parse the id attributes.
+\item[sub\_format]
+generated subtitle format. The default value is \texttt{smil}.
\end{description}
-\hypertarget{example}{%
-\subsection{Example}\label{example}}
+\hypertarget{additional-parameters-for-the-job-configuration-file}{%
+\subsubsection{Additional parameters for the job configuration
+file}\label{additional-parameters-for-the-job-configuration-file}}
+
+\begin{itemize}
+\tightlist
+\item
+ description
+\item
+ prefix
+\item
+ config\_name
+\item
+ keep\_config
+\end{itemize}
-The following configuration add support for the \texttt{biber} command,
-requires \texttt{common\_domfilters} extension and requires MathML
-output for math.
+It is possible to generate multiple HTML files from the \LaTeX~source.
+For example, \texttt{tex4ebook} generates a separate file for each
+chapter or section. It is possible to set options for each HTML file, in
+particular names of the corresponding audio files. This mapping is done
+using the \texttt{map} parameter.
+
+Example:
\begin{verbatim}
-Make:add("biber", "biber ${input}")
-Make:enable_extension "common_domfilters"
-settings_add {
- tex4ht_sty_par =",mathml"
+filter_settings "aeneas-config" {
+ map = {
+ ["sampleli1.html"] = {audio_file="sample.mp3"},
+ ["sample.html"] = false
+ }
}
\end{verbatim}
-\hypertarget{command-line-options}{%
-\section{Command line options}\label{command-line-options}}
+Table keys are the configured filenames. It is necessary to insert them
+as \texttt{{[}"filename.html"{]}}, because of Lua syntax rules.
-\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
--f,--format (default nil) Output file format
--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
--v,--version Print version number
--x,--xetex Use xelatex for document compilation
-<filename> (string) Input file name
-\end{verbatim}
+This example maps audio file \texttt{sample.mp3} to a section subpage.
+The main HTML file, which may contain title and table of contents
+doesn't have a corresponding audio file.
-You can still invoke \texttt{make4ht} in the same way as
-\texttt{htlatex}:
+Filenames of the subfiles correspond to the chapter numbers, so they are
+not stable when a new chapter is added. It is possible to request
+filenames derived from the chapter titles using the
+\texttt{sec-filename} option for \texttt{tex4ht.sty}.
-\begin{verbatim}
-make4ht filename "customcfg, charset=utf-8" "-cunihtf -utf8" "-dfoo"
-\end{verbatim}
+\hypertarget{available-map-options}{%
+\subsubsection{\texorpdfstring{Available \texttt{map}
+options}{Available map options}}\label{available-map-options}}
-Note that this will not use \texttt{make4ht} routines for output
-directory making and copying. If you want to use them, change the line
-above to:
+\begin{description}
+\item[audio\_file]
+the corresponding audio file
+\item[sub\_file]
+name of the generated subtitle file
+\end{description}
-\begin{verbatim}
-make4ht -d foo filename "customcfg, charset=utf-8" "-cunihtf -utf8"
-\end{verbatim}
+The following options are the same as their counterparts from the main
+parameters table and generally, don't need to be set:
-This call has the same effect as the following:
+\begin{itemize}
+\tightlist
+\item
+ prefix
+\item
+ file\_desc
+\item
+ file\_id
+\item
+ text\_type
+\item
+ id\_sort
+\item
+ id\_prefix
+\item
+ sub\_format
+\end{itemize}
+
+\hypertarget{full-example}{%
+\subsubsection{Full example}\label{full-example}}
\begin{verbatim}
-make4ht -u -c customcfg -d foo filename
-\end{verbatim}
+local domfilter = require "make4ht-domfilter"
+local aeneas_config = require "make4ht-aeneas-config"
-Output directory doesn't have to exist, it will be created
-automatically. Specified path can be relative to current directory, or
-absolute:
+filter_settings "aeneas-config" {
+ map = {
+ ["krecekli1.xhtml"] = {audio_file="krecek.mp3"},
+ ["krecek.xhtml"] = false
+ }
+}
-\begin{verbatim}
-make4ht -d use/current/dir/ filename
-make4ht -d ../gotoparrentdir filename
-make4ht -d ~/gotohomedir filename
-make4ht -d c:\documents\windowspathsareworkingtoo filename
+local process = domfilter {"aeneas"}
+Make:match("html$", process)
+
+if mode == "draft" then
+ aeneas_config.process_files {}
+else
+ aeneas_config.execute {}
+end
\end{verbatim}
\hypertarget{troubleshooting}{%
@@ -1041,23 +1314,23 @@ make4ht:unrecognized parameter: i
It may be caused by a following \texttt{make4ht} invocation:
\begin{verbatim}
-make4ht hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8" -d foo
+$ make4ht hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8" -d foo
\end{verbatim}
The command line option parser is confused by mixing options for
-\texttt{make4ht} and \texttt{tex4ht} in this case and tries to interpret
-the \texttt{-cunihtf\ -utf8}, which are options for \texttt{tex4ht}
-command as \texttt{make4ht} options. To fix that, you can either move
-the \texttt{-d\ foo} directly after \texttt{make4ht} command:
+\texttt{make4ht} and \TeX4ht~in this case. It tries to interpret the
+\texttt{-cunihtf\ -utf8}, which are options for the \texttt{tex4ht}
+command, as \texttt{make4ht} options. To fix that, try to move the
+\texttt{-d\ foo} directly after the \texttt{make4ht} command:
\begin{verbatim}
-make4ht -d foo hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8"
+$ make4ht -d foo hello.tex "customcfg,charset=utf-8" "-cunihtf -utf8"
\end{verbatim}
-Another option is to add a space before \texttt{tex4ht} options:
+Another option is to add a space before the \texttt{tex4ht} options:
\begin{verbatim}
-make4ht hello.tex "customcfg,charset=utf-8" " -cunihtf -utf8" -d foo
+$ make4ht hello.tex "customcfg,charset=utf-8" " -cunihtf -utf8" -d foo
\end{verbatim}
The former way is preferable, though.
@@ -1066,10 +1339,10 @@ The former way is preferable, though.
\subsection{Filenames containing
spaces}\label{filenames-containing-spaces}}
-\texttt{tex4ht} cannot handle filenames containing spaces.
-\texttt{make4ht} thus replaces spaces in input file names with
-underscores, so generated XML files use underscores instead of spaces as
-well.
+\texttt{tex4ht} command cannot handle filenames containing spaces. to
+fix this issue, \texttt{make4ht} replaces spaces in the input filenames
+with underscores. The generated XML filenames use underscores instead of
+spaces as well.
\hypertarget{filenames-containing-non-ascii-characters}{%
\subsection{Filenames containing non-ASCII
diff --git a/support/tex4ebook/README b/support/tex4ebook/README
index 951dad5a57..796445674a 100644
--- a/support/tex4ebook/README
+++ b/support/tex4ebook/README
@@ -2,24 +2,22 @@
# Introduction
-`TeX4ebook` is bundle of Lua scripts and `LaTeX` packages for conversion of
-LaTeX files to ebook formats, for example `epub`, `mobi` and `epub3`. `tex4ht`
-is used as conversion engine.
+`TeX4ebook` is a tool for conversion from \LaTeX\ to
+ebook formats, such as EPUB, MOBI and EPUB 3.
+It is based on `TeX4ht`^[https://tug.org/tex4ht/],
+which provides instructions for the actual \LaTeX\ to HTML conversion,
+and on `make4ht`^[https://ctan.org/pkg/make4ht?lang=en].
-Note that while `mobi` is supported by Amazon Kindle, most widespread ebook
-reader, it doesn't support `mathml` and this means that math must re represented
-as images. The same is true for `epub`. This is not a good thing, especially
-for inline math, as you may experience wrong baselines. If your ebook contains
-math, the only correct solution is to produce `epub3`, as it supports `mathml`.
-The issue with `epub3` is, that majority of `e-ink` ebook readers doesn't
-support this format, reader applications exists mainly for Android and Apple
-devices. For books which contains mainly prose, all formats should be suitable,
-but `epub3` supports most features from web standards, such as `CSS`.
-As with `tex4ht`, the emphasis is on conversion of document's logical structure
-and metadata, basic visual appearance is preserved as well, but you should use
+The conversion is focused on the logical structure of the converted document
+and metadata. Basic visual appearance is preserved as well, but you should use
custom configurations if you want to make the document more visually appealing.
-You can include custom `CSS` or fonts in configuration files.
+You can include custom `CSS` or fonts in a configuration file.
+
+`TeX4ebook` supports the same features as `make4ht`, in particular build files and extensions.
+These may be used for post-processing of the generated HTML files, or to configure the image conversion.
+See the `make4ht` documentation to see the supported features.
+
## License
@@ -38,6 +36,7 @@ You don't have to modify your source files unless you want to use commands
defined by `tex4ebook` in the document, or when your document uses a
package which causes a compilation error.
+
If you want to use `tex4ebook` commands, add this line to your document
preamble:
@@ -51,9 +50,13 @@ But it is optional. You shouldn't need to modify your \TeX\ files
# Command line options
+`-a,--loglevel`
+
+: Set message log level. Possible values: debug, info, status, warning, error, fatal. Default: status.
+
`-c,--config`
-: specify custom config file for `tex4ht`
+: specify custom config file for `TeX4ht`
**example config file**: File `sample.cfg`
@@ -78,7 +81,11 @@ But it is optional. You shouldn't need to modify your \TeX\ files
`-f,--format (default epub)`
-: Output format. Epub, Epub3 and Mobi formats are supported.
+: Output format. Possible values are `epub`, `epub3` and `mobi`.
+
+`-j,--jobname`
+
+: Specify the output file name, without file extension.
`-l,--lua`
@@ -97,7 +104,7 @@ But it is optional. You shouldn't need to modify your \TeX\ files
`-s,--shell-escape`
-: Enable shell escape in htlatex run. This may be needed if you run external
+: Enable shell escape in the `htlatex` run. This is necessary for the execution of the external
commands from your source files.
`-t,--tidy`
@@ -112,12 +119,11 @@ But it is optional. You shouldn't need to modify your \TeX\ files
`-v,--version`
: Print the version number.
-
# Configuration
-`tex4ebook` uses `tex4ht`^[http://www.tug.org/tex4ht/] for conversion from LaTeX
-to html. `tex4ht` is highly configurable using config files. Basic config file
+`TeX4ebook` uses `TeX4ht`^[http://www.tug.org/tex4ht/] for conversion from LaTeX
+to html. `TeX4ht` is highly configurable using config files. Basic config file
structure is
\Preamble{xhtml, comma separated list of options}
@@ -127,16 +133,16 @@ structure is
\EndPreamble
Basic info about command configurations can be found in a
-work-in-progres *tex4ht tutorial*^[https://github.com/michal-h21/helpers4ht/wiki/tex4ht-tutorial],
-*tex4ht documentation*^[http://www.tug.org/applications/tex4ht/mn11.html],
+work-in-progres *TeX4ht tutorial*^[https://github.com/michal-h21/helpers4ht/wiki/tex4ht-tutorial],
+*TeX4ht documentation*^[http://www.tug.org/applications/tex4ht/mn11.html],
and in series of blogposts on CV Radhakrishnan's blog:
-*Configure part 1*^[http://www.cvr.cc/?p=323],
-*Configure part 2*^[http://www.cvr.cc/?p=362],
-*Low level commands*^[http://www.cvr.cc/?p=482].
+*Configure part 1*^[https://web.archive.org/web/20180908234227/http://www.cvr.cc/?p=323],
+*Configure part 2*^[https://web.archive.org/web/20180908201057/http://www.cvr.cc/?p=362],
+*Low level commands*^[https://web.archive.org/web/20180909101325/http://cvr.cc/?p=482].
Available options for `\Preamble` command are listed in the article
-*TeX4ht: options*^[http://www.cvr.cc/?p=504]. *Comparison of tex4ebook and Pandoc output*^[https://github.com/richelbilderbeek/travis_tex_to_epub_example_1]
+*TeX4ht: options*^[https://web.archive.org/web/20180813043722/http://cvr.cc/?p=504]. *Comparison of tex4ebook and Pandoc output*^[https://github.com/richelbilderbeek/travis_tex_to_epub_example_1]
-Great source of tips for `tex4ht` configuring is *tex4ht tag on TeX.sx*^[http://tex.stackexchange.com/questions/tagged/tex4ht], there is also a *tag for tex4ebook*^[http://tex.stackexchange.com/questions/tagged/tex4ebook].
+A great source of tips for `TeX4ht` configuration is *tex4ht tag on TeX.sx*^[http://tex.stackexchange.com/questions/tagged/tex4ht]. There is also a *tag for tex4ebook*^[http://tex.stackexchange.com/questions/tagged/tex4ebook].
Examples of interesting questions are
*including images and fonts in ebooks*^[http://tex.stackexchange.com/a/213165/2891]
@@ -149,7 +155,7 @@ or *setting image size in em units instead of pt*^[http://tex.stackexchange.com/
\Configure{UniqueIdentifier}{identifier}
-Every epub file should have unique identifier, like ISBN, DOI, URI etc.
+Every EPUB file should have unique identifier, like ISBN, DOI, URI etc.
Default identifier is URI, with value `http://example.com/\jobname`.
\Configure{@author}{\let\footnote\@gobble}
@@ -161,7 +167,7 @@ which don't belongs here, such as `\footnote`.
\Configure{OpfScheme}{URI}
Type of unique identifier, default type is URI. It is
-used only in `epub`, it is deprecated for `epub3`
+used only in the EPUB format, it is deprecated for EPUB 3.
\Configure{resettoclevels}{list of section types in descending order}
@@ -170,7 +176,7 @@ value is the whole document hierarchy, from `\part` to `\paragraph`.
\Configure{DocumentLanguage}{language code}
-Each ePub file must declare the document language. It is inferred from `babel` main
+Each EPUB file must declare the document language. It is inferred from `babel` main
language by default, but you can configure it when it doesn't work correctly.
The `language code` should be in [ISO
639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) form.
@@ -203,11 +209,11 @@ Add item to `<manifest>` section in the `OPF` file.
\Configure{xmlns}{prefix}{uri}
-Add xml name space to `xhtml` files. Useful in `EPUB 3`
+Add `XML` name space to the generated `XHTML` files. Useful in `EPUB 3`.
-## Commands available in config files
+## Commands available in the config file
`\OpfRegisterFile[filename]`
@@ -244,53 +250,44 @@ See the `make4ht` documentation for an example and more information.
# Troubleshooting
+## Fixed layout EPUB
+
+The basic support for the Fixed layout EPUB 3 can be enabled using the following configurations:
+
+ \Configure{OpfMetadata}{\HCode{<meta property="rendition:layout">pre-paginated</meta>}}
+ \Configure{OpfMetadata}{\HCode{<meta property="rendition:orientation">landscape</meta>}}
+ \Configure{OpfMetadata}{\HCode{<meta property="rendition:spread">none</meta>}}
+ \Configure{@HEAD}{\HCode{<meta name="viewport" content="width=1920, height=1080"/>\Hnewline}}
+
+Modify the dimensions in the `<meta name="viewport>` element according to your needs.
+
+## Math issues
+
+Note that while `mobi` is supported by Amazon Kindle, most widespread ebook
+reader, it doesn't support `MathML`. This means that math must be represented
+as images. The same issue is true for the EPUB format as well.
+This is problematic especially for the inline math, as you may experience wrong
+vertical alignment of the math content and surrounding text. If your ebook contains
+math, a better solution is to produce the `epub3` format, as it supports `MathML`.
+The issue with EPUB 3 is that majority of `e-ink` ebook readers don't
+support it. Reader applications exists mainly for Android and Apple
+devices. For books which contains mainly prose, all formats should be suitable,
+but EPUB 3 supports most features from web standards, such as `CSS`.
+
+## Compilation errors
+
When compilation of the document breaks with error during `LaTeX` run, it may
-be caused by some problem in `tex4ht` configuration. Comment out line
+be caused by some problem in `TeX4ht` configuration. Comment out line
`\usepackage{tex4ebook}` in your source file and run command:
htlatex filename
-if same error as in `tex4ebook` run arises, the problem is in some `tex4ht`
+if same error as in `tex4ebook` run arises, the problem is in some `TeX4ht`
configuration. Try to identify the source of problem and if you cannot find the
solution, make minimal example showing the error and ask for help either on
-*tex4ht mailing list*^[http://tug.org/mailman/listinfo/tex4ht] or on
+*TeX4ht mailing list*^[http://tug.org/mailman/listinfo/tex4ht] or on
*TeX.sx*^[http://tex.stackexchange.com/].
-<!--
-## Fontspec
-
-`tex4ht` currently doesn't support `fontspec` and open type fonts. At this
-moment, workaround for this is to modify your source file and conditionally
-include fontspec and any other conflicting packages only when document is not
-processed with `tex4ht`.
-
-Sample:
-
- \documentclass{article}
- \makeatletter
- \@ifpackageloaded{tex4ht}{%
- % Packages for tex4ht unicode support
- \usepackage[utf8]{inputenc}
- \usepackage[T1]{fontenc}
- \usepackage[english,czech]{babel}
- }{%
- % Packages for xelatex
- \usepackage{fontspec}
- \usepackage{polyglossia}
- \setmainfont{Latin Modern Roman}
- }
- \makeatother
-
-The drawback is that not all characters of the Unicode range are supported with
-`inputenc`. For some solutions of this limitation, see a thread on *tex4ht
-mailing list*^[http://tug.org/pipermail/tex4ht/2013q1/000719.html]
-
-Other approach is to use `alternative4ht` package from [helpers4ht](https://github.com/michal-h21/helpers4ht)
-bundle. It works only with Lua backend, but it supports full unicode and you
-don't have to use conditional package inclusion in your document. See
-an [example](http://michal-h21.github.io/samples/helpers4ht/fontspec.html).
--->
-
## Validation
In case of successful compilation, use command line tool `epubcheck`^[you need
diff --git a/support/tex4ebook/changelog.tex b/support/tex4ebook/changelog.tex
index d7743b1204..0d3393cca5 100644
--- a/support/tex4ebook/changelog.tex
+++ b/support/tex4ebook/changelog.tex
@@ -3,6 +3,106 @@
\begin{itemize}
\item
+ 2019/11/01
+
+ \begin{itemize}
+ \tightlist
+ \item
+ released version \texttt{0.3}
+ \end{itemize}
+\item
+ 2019/10/20
+
+ \begin{itemize}
+ \tightlist
+ \item
+ fixed the \texttt{TOC} cleanup in the \texttt{ePub\ 3} mode.
+ \item
+ added support for the \texttt{page-spread-left} and
+ \texttt{page-spreat-right} properties.
+ \end{itemize}
+\item
+ 2019/10/20
+
+ \begin{itemize}
+ \tightlist
+ \item
+ addapted to use the \texttt{make4ht} logging mechanism.
+ \end{itemize}
+\item
+ 2019/10/06
+
+ \begin{itemize}
+ \tightlist
+ \item
+ fixed bug with void elements parsing in the OPF file.
+ \item
+ undo \texttt{\textbackslash{}XeTeXcharclass} for the \texttt{:}
+ character when the OPF file is generated.
+ \end{itemize}
+\item
+ 2019/09/16
+
+ \begin{itemize}
+ \tightlist
+ \item
+ make the default build sequence before loading of the extensions.
+ Some extensions need to modify the build sequence.
+ \end{itemize}
+\item
+ 2019/08/28
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for reading input from \texttt{STDIN}.
+ \end{itemize}
+\item
+ 2019/08/27
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for the \texttt{-\/-jobname} command line option.
+ \end{itemize}
+\item
+ 2019/08/25
+
+ \begin{itemize}
+ \tightlist
+ \item
+ use the \texttt{mkparams.get\_args} function to retrieve the command
+ line options
+ \end{itemize}
+\item
+ 2019/07/24
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for the \texttt{\textbackslash{}author} command with
+ an optional argument
+ \end{itemize}
+\item
+ 2019/05/09
+
+ \begin{itemize}
+ \tightlist
+ \item
+ added support for the \texttt{\textbackslash{}title} command with an
+ optional argument
+ \end{itemize}
+\item
+ 2019/04/04
+
+ \begin{itemize}
+ \tightlist
+ \item
+ register appendix chapters and section in the OPF file list
+ \item
+ fixed handling of appendices in the NCX table of contents
+ \end{itemize}
+\item
2019/03/21
\begin{itemize}
diff --git a/support/tex4ebook/exec_epub.lua b/support/tex4ebook/exec_epub.lua
index d92a8d103c..24cc626aad 100644
--- a/support/tex4ebook/exec_epub.lua
+++ b/support/tex4ebook/exec_epub.lua
@@ -2,6 +2,7 @@ module("exec_epub",package.seeall)
local lfs = require("lfs")
local os = require("os")
local io = require("io")
+local log = logging.new("exec_epub")
--local ebookutils = require("ebookutils")
local ebookutils = require "mkutils"
-- font loading doesn't work, font database format changes often
@@ -29,25 +30,19 @@ local function deletedir(dir)
if file ~= "." and file ~= ".." then
if lfs.attributes(file_path, 'mode') == 'file' then
os.remove(file_path)
- print('remove file',file_path)
+ log:info('remove file',file_path)
elseif lfs.attributes(file_path, 'mode') == 'directory' then
- print('dir', file_path)
+ log:info('dir', file_path)
deletedir(file_path)
end
end
end
lfs.rmdir(dir)
end
- print('remove dir',dir)
+ log:info('remove dir',dir)
end
function prepare(params)
- local randname=tostring(math.random(12000))
- -- if not ebookutils.file_exists("tex4ht.env") then
- -- local env_file = kpse.find_file("epub2.env")
- --print("Local env file: "..env_file)
- -- ebookutils.copy(env_file,"tex4ht.env")
- -- end
local makedir= function(path)
local current = lfs.currentdir()
local dir = ebookutils.prepare_path(path .. "/")
@@ -60,29 +55,45 @@ function prepare(params)
lfs.chdir(current)
end
basedir = params.input.."-".. params.format
- outputdir= basedir.."/"..outputdir_name --"outdir-"..randname --os.tmpdir()
+ outputdir= basedir.."/"..outputdir_name
deletedir(basedir)
makedir(outputdir)
- -- lfs.mkdir(outputdir)
- --ebookutils.mkdirectories(ebookutils.prepare_path(outputdir.."/"))
- metadir = basedir .."/" .. metadir_name --"metadir-"..randname
+ metadir = basedir .."/" .. metadir_name
makedir(metadir)
if params.outdir ~= "" then
destdir = params.outdir .. "/"
makedir(destdir)
end
- --local dd = ebookutils.prepare_path(metadir.."/")
- --for _,d in pairs(dd) do print("metadir path: "..d) end
- -- lfs.mkdir(metadir)
- --local status, msg = ebookutils.mkdirectories(ebookutils.prepare_path(metadir.."/"))
- --if not status then print("make mmetadir error:" ..msg) end
mimetype= basedir .. "/" ..mimetype_name --os.tmpname()
- print(outputdir)
- print(mimetype)
tidy = params.tidy
include_fonts = params.include_fonts
params["t4ht_par"] = params["t4ht_par"] -- + "-d"..string.format(params["t4ht_dir_format"],outputdir)
params.tex4ht_sty_par = params.tex4ht_sty_par .. ",uni-html4"
+ params.config_file.Make.params = params
+ local mode = params.mode
+ if params.config_file.Make:length() < 1 then
+ if mode == "draft" then
+ params.config_file.Make:htlatex()
+ else
+ params.config_file.Make:htlatex()
+ params.config_file.Make:htlatex()
+ params.config_file.Make:htlatex()
+ end
+ end
+ if #params.config_file.Make.image_patterns > 0 then
+ params["t4ht_par"] = params["t4ht_par"] .." -p"
+ end
+ params.config_file.Make:tex4ht()
+ params.config_file.Make:t4ht()
+ -- do some cleanup
+ params.config_file.Make:match("tmp$",function(filename, par)
+ -- detect if a tmp file was created for content from STDIN
+ if par.is_tmp_file then
+ -- and remove it
+ log:info("Removing temporary file", par.tex_file)
+ os.remove(par.tex_file)
+ end
+ end)
return(params)
end
@@ -90,7 +101,7 @@ function run(out,params)
--local currentdir=
outputfilename=out
outputfile = outputfilename..".epub"
- print("Output file: "..outputfile)
+ log:info("Output file: "..outputfile)
--lfs.chdir(metadir)
local m= io.open(metadir.."/container.xml","w")
m:write([[
@@ -107,27 +118,7 @@ media-type="application/oebps-package+xml"/>
m=io.open(mimetype,"w")
m:write("application/epub+zip")
m:close()
- local htlatex_run = "${htlatex} ${input} \"${config}${tex4ht_sty_par}\" \"${tex4ht_par}\" \"${t4ht_par}\" \"${latex_par}\"" % params
- print("Make4ht run")
- print("-------------------")
- params.config_file.Make.params = params
- local mode = params.mode
- if params.config_file.Make:length() < 1 then
- if mode == "draft" then
- params.config_file.Make:htlatex()
- else
- params.config_file.Make:htlatex()
- params.config_file.Make:htlatex()
- params.config_file.Make:htlatex()
- end
- end
- if #params.config_file.Make.image_patterns > 0 then
- params["t4ht_par"] = params["t4ht_par"] .." -p"
- end
- params.config_file.Make:tex4ht()
- params.config_file.Make:t4ht()
params.config_file.Make:run()
- print("-------------------")
--[[for k,v in pairs(params.config_file.Make) do
print(k.. " : "..type(v))
end--]]
@@ -162,7 +153,7 @@ function make_opf()
-- Find mimetype and make item tag for each converted file in the lg file
local fname,ext = item:match("([%a%d%_%-]*)%p([%a%d]*)$")
local mimetype = mimetypes[ext] or ""
- if mimetype == "" then print("Mimetype for "..ext.." is not registered"); return nil end
+ if mimetype == "" then log:info("Mimetype for "..ext.." is not registered"); return nil end
local dir_part = item:split("/")
table.remove(dir_part,#dir_part)
local id=table.concat(dir_part,"-")..fname.."_"..ext
@@ -190,165 +181,164 @@ function make_opf()
--local opf_second_part = outputdir .. "/content-part2.opf"
if
ebookutils.file_exists(opf_first_part) and ebookutils.file_exists(opf_second_part)
- then
- local h_first = io.open(opf_first_part,"r")
- local h_second = io.open(opf_second_part,"r")
- local opf_complete = {}
- table.insert(opf_complete,h_first:read("*all"))
- local used_html = find_all_files(opf_complete[1])
- -- local lg_file = ebookutils.parse_lg(outputfilename..".lg")
- -- The lg_file has been already loaded by make4ht, it doesn't make sense to load it again
- -- Furthermore, it is now possible to add new files from Lua build files
- local lg_file = Make.lgfile or ebookutils.parse_lg(outputfilename..".lg")
- local used_files = {}
- for _,filename in ipairs(lg_file["files"]) do
- -- we need to test the filenames in order to prevent duplicates
- -- filenames are tested without paths, so there may be issues if
- -- the same filename is used in different directories. Is that a problem?
- used_files[filename] = true
- end
- local outside_spine = {}
- local all_used_files = find_all_files(opf_complete[1],"([%a%d%-%_]+%.[%a%d]+)")
- local used_paths = {}
- local used_ids = {}
- for _,k in ipairs(lg_file["files"]) do
- local ext = k:match("%.([%a%d]*)$")
- local parts = k:split "/"
- local fn = parts[#parts]
- local allow_in_spine = {html="",xhtml = "", xml = ""}
- table.remove(parts,#parts)
- --table.insert(parts,1,"OEBPS")
- table.insert(parts,1,outputdir)
- -- print("SSSSS "..fn.." ext .." .. ext)
- --if string.find("jpg gif png", ext) and not all_used_files[k] then
- local item,id = lg_item(k)
- if item then
- local path = table.concat(parts)
- if not used_paths[path] then
- ebookutils.mkdirectories(parts)
- used_paths[path]=true
- end
- if allow_in_spine[ext] and tidy then
- if tidyconf then
- print("Tidy: "..k)
- local run ="tidy -c -w 200 -q -utf8 -m -config " .. tidyconf .." " .. k
- os.execute(run)
- else
- print "Tidy: Cannot load tidyconf.conf"
- end
- end
- if not used_ids[id] then
- ebookutils.copy(k, outputdir .. "/"..k)
- if not all_used_files[fn] then
- table.insert(opf_complete,item)
- if allow_in_spine[ext] then
- table.insert(outside_spine,id)
- end
+ then
+ local h_first = io.open(opf_first_part,"r")
+ local h_second = io.open(opf_second_part,"r")
+ local opf_complete = {}
+ table.insert(opf_complete,h_first:read("*all"))
+ local used_html = find_all_files(opf_complete[1])
+ -- local lg_file = ebookutils.parse_lg(outputfilename..".lg")
+ -- The lg_file has been already loaded by make4ht, it doesn't make sense to load it again
+ -- Furthermore, it is now possible to add new files from Lua build files
+ local lg_file = Make.lgfile or ebookutils.parse_lg(outputfilename..".lg")
+ local used_files = {}
+ for _,filename in ipairs(lg_file["files"]) do
+ -- we need to test the filenames in order to prevent duplicates
+ -- filenames are tested without paths, so there may be issues if
+ -- the same filename is used in different directories. Is that a problem?
+ used_files[filename] = true
+ end
+ local outside_spine = {}
+ local all_used_files = find_all_files(opf_complete[1],"([%a%d%-%_]+%.[%a%d]+)")
+ local used_paths = {}
+ local used_ids = {}
+ for _,k in ipairs(lg_file["files"]) do
+ local ext = k:match("%.([%a%d]*)$")
+ local parts = k:split "/"
+ local fn = parts[#parts]
+ local allow_in_spine = {html="",xhtml = "", xml = ""}
+ table.remove(parts,#parts)
+ --table.insert(parts,1,"OEBPS")
+ table.insert(parts,1,outputdir)
+ -- print("SSSSS "..fn.." ext .." .. ext)
+ --if string.find("jpg gif png", ext) and not all_used_files[k] then
+ local item,id = lg_item(k)
+ if item then
+ local path = table.concat(parts)
+ if not used_paths[path] then
+ ebookutils.mkdirectories(parts)
+ used_paths[path]=true
+ end
+ if allow_in_spine[ext] and tidy then
+ if tidyconf then
+ log:info("Tidy: "..k)
+ local run ="tidy -c -w 200 -q -utf8 -m -config " .. tidyconf .." " .. k
+ os.execute(run)
+ else
+ log:info "Tidy: Cannot load tidyconf.conf"
+ end
+ end
+ if not used_ids[id] then
+ ebookutils.copy(k, outputdir .. "/"..k)
+ if not all_used_files[fn] then
+ table.insert(opf_complete,item)
+ if allow_in_spine[ext] then
+ table.insert(outside_spine,id)
end
- end
- used_ids[id] = true
- end
- end
- for _,f in ipairs(lg_file["images"]) do
- local f = f.output
- local p, id = lg_item(f)
- -- process the images only if they weren't registered in lg_file["files"]
- -- they would be processed twice otherwise
- if not used_files[f] and not used_ids[id] then
- ebookutils.copy(f, outputdir .. "/"..f)
- table.insert(opf_complete,p)
+ end
end
used_ids[id] = true
- end
- local end_opf = h_second:read("*all")
- local spine_items = {}
- for _,i in ipairs(outside_spine) do
- table.insert(spine_items,
- '<itemref idref="${idref}" linear="no" />' % {idref=i})
- end
- table.insert(opf_complete,end_opf % {spine = table.concat(spine_items,"\n")})
- h_first:close()
- h_second:close()
- h_first = io.open(opf_first_part,"w")
- local opf_completed = table.concat(opf_complete,"\n")
- -- poor man's tidy: remove trailing whitespace befora xml tags
- opf_completed = opf_completed:gsub("[ ]*<","<")
- opf_completed = remove_empty_guide(opf_completed)
- h_first:write(opf_completed)
- h_first:close()
- os.remove(opf_second_part)
- --ebookutils.copy(outputfilename ..".css",outputdir.."/")
- ebookutils.copy(opf_first_part,outputdir.."/"..opf_first_part)
- --for c,v in pairs(lg_file["fonts"]) do
- -- print(c, table.concat(v,", "))
- --end
- --print(table.concat(opf_complete,"\n"))
- else
- print("Missing opf file")
- end
- end
- local function find_zip()
- if io.popen("zip -v","r"):close() then
- return "zip"
- elseif io.popen("miktex-zip -v","r"):close() then
- return "miktex-zip"
+ end
+ end
+ for _,f in ipairs(lg_file["images"]) do
+ local f = f.output
+ local p, id = lg_item(f)
+ -- process the images only if they weren't registered in lg_file["files"]
+ -- they would be processed twice otherwise
+ if not used_files[f] and not used_ids[id] then
+ ebookutils.copy(f, outputdir .. "/"..f)
+ table.insert(opf_complete,p)
+ end
+ used_ids[id] = true
+ end
+ local end_opf = h_second:read("*all")
+ local spine_items = {}
+ for _,i in ipairs(outside_spine) do
+ table.insert(spine_items,
+ '<itemref idref="${idref}" linear="no" />' % {idref=i})
end
- print "It appears you don't have zip command installed. I can't pack the ebook"
+ table.insert(opf_complete,end_opf % {spine = table.concat(spine_items,"\n")})
+ h_first:close()
+ h_second:close()
+ h_first = io.open(opf_first_part,"w")
+ local opf_completed = table.concat(opf_complete,"\n")
+ -- poor man's tidy: remove trailing whitespace befora xml tags
+ opf_completed = opf_completed:gsub("[ ]*<","<")
+ opf_completed = remove_empty_guide(opf_completed)
+ h_first:write(opf_completed)
+ h_first:close()
+ os.remove(opf_second_part)
+ --ebookutils.copy(outputfilename ..".css",outputdir.."/")
+ ebookutils.copy(opf_first_part,outputdir.."/"..opf_first_part)
+ --for c,v in pairs(lg_file["fonts"]) do
+ -- print(c, table.concat(v,", "))
+ --end
+ --print(table.concat(opf_complete,"\n"))
+ else
+ log:warning("Missing opf file")
+ end
+end
+local function find_zip()
+ if io.popen("zip -v","r"):close() then
return "zip"
+ elseif io.popen("miktex-zip -v","r"):close() then
+ return "miktex-zip"
end
+ log:warning "It appears you don't have zip command installed. I can't pack the ebook"
+ return "zip"
+end
- function pack_container()
- local ncxfilename = outputdir .. "/" .. outputfilename .. ".ncx"
- if os.execute("tidy -v") > 0 then
- print("Warning:\n tidy command seems missing, you should install it" ..
- " in order\n to make valid epub file")
- print("Using regexp based cleaning")
- local lines = {}
- for line in io.lines(ncxfilename) do
- local content = line:gsub("[ ]*<","<")
- if content:len() > 0 then
- table.insert(lines, content)
- end
+function pack_container()
+ local ncxfilename = outputdir .. "/" .. outputfilename .. ".ncx"
+ if os.execute("tidy -v") > 0 then
+ log:warning("tidy command seems missing, you should install it" ..
+ " in order\n to make valid epub file")
+ log:info("Using regexp based cleaning")
+ local lines = {}
+ for line in io.lines(ncxfilename) do
+ local content = line:gsub("[ ]*<","<")
+ if content:len() > 0 then
+ table.insert(lines, content)
end
- table.insert(lines,"")
- local ncxfile = io.open(ncxfilename,"w")
- ncxfile:write(table.concat(lines,"\n"))
- ncxfile:close()
- else
- print("Tidy ncx "..
- os.execute("tidy -xml -i -q -utf8 -m " .. ncxfilename))
- print("Tidy opf "..
- os.execute("tidy -xml -i -q -utf8 -m " ..
- outputdir .. "/" .. "content.opf"))
- end
- print(mimetype)
- local zip = find_zip()
- -- we need to remove the epub file if it exists already, because it may contain files which aren't used anymore
- if ebookutils.file_exists(outputfile) then os.remove(outputfile) end
- print("Pack mimetype " .. os.execute("cd "..basedir.." && "..zip.." -q0X "..outputfile .." ".. mimetype_name))
- print("Pack metadir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..metadir_name))
- print("Pack outputdir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..outputdir_name))
- print("Copy generated epub ")
- ebookutils.cp(basedir .."/"..outputfile, destdir .. outputfile)
+ end
+ table.insert(lines,"")
+ local ncxfile = io.open(ncxfilename,"w")
+ ncxfile:write(table.concat(lines,"\n"))
+ ncxfile:close()
+ else
+ log:info("Tidy ncx "..
+ os.execute("tidy -xml -i -q -utf8 -m " .. ncxfilename))
+ log:info("Tidy opf "..
+ os.execute("tidy -xml -i -q -utf8 -m " ..
+ outputdir .. "/" .. "content.opf"))
+ end
+ local zip = find_zip()
+ -- we need to remove the epub file if it exists already, because it may contain files which aren't used anymore
+ if ebookutils.file_exists(outputfile) then os.remove(outputfile) end
+ log:info("Pack mimetype " .. os.execute("cd "..basedir.." && "..zip.." -q0X "..outputfile .." ".. mimetype_name))
+ log:info("Pack metadir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..metadir_name))
+ log:info("Pack outputdir " .. os.execute("cd "..basedir.." && "..zip.." -qXr9D " .. outputfile.." "..outputdir_name))
+ log:info("Copy generated epub ")
+ ebookutils.cp(basedir .."/"..outputfile, destdir .. outputfile)
end
- function writeContainer()
- make_opf()
- pack_container()
- end
- local function deldir(path)
- for entry in lfs.dir(path) do
- if entry~="." and entry~=".." then
- os.remove(path.."/"..entry)
- end
- end
- os.remove(path)
- --]]
- end
+function writeContainer()
+ make_opf()
+ pack_container()
+end
+local function deldir(path)
+ for entry in lfs.dir(path) do
+ if entry~="." and entry~=".." then
+ os.remove(path.."/"..entry)
+ end
+ end
+ os.remove(path)
+ --]]
+end
- function clean()
- --deldir(outputdir)
- --deldir(metadir)
- --os.remove(mimetype)
+function clean()
+ --deldir(outputdir)
+ --deldir(metadir)
+ --os.remove(mimetype)
end
diff --git a/support/tex4ebook/exec_epub3.lua b/support/tex4ebook/exec_epub3.lua
index 53173be9e9..edf6df01c2 100644
--- a/support/tex4ebook/exec_epub3.lua
+++ b/support/tex4ebook/exec_epub3.lua
@@ -1,6 +1,7 @@
module(...,package.seeall)
local eb = require("exec_epub")
local dom = require("luaxml-domobject")
+local log = logging.new "exec_epub3"
local ext = "xhtml"
local outputdir = nil
@@ -60,7 +61,10 @@ local function add_media_overlays(content)
end
return os.date("%H:%M:%S",time)
end
- local opfdom = dom.parse(content)
+ -- the second parameter for parse is table with void elements. the OPF format has no
+ -- void elements, so it needs to be empty, otherwise we may get parsing error because of
+ -- <meta> element, which is included in the default void elements
+ local opfdom = dom.parse(content, {})
local items = opfdom:query_selector("manifest item")
local ref = {}
local times = {}
@@ -109,23 +113,136 @@ local function add_media_overlays(content)
end
+local function remove_spurious_TOC_elements(tocdom)
+ local function count_child_elements(el)
+ -- count children elements of the current element
+ local count = 0
+ for _, curr_el in ipairs(el:get_children()) do
+ if curr_el:is_element() then count = count + 1 end
+ end
+ return count
+ end
+ -- modify the TOC to comply to epubcheck tests
+ -- add a blank <li> to empty <ol>
+ for _, el in ipairs(tocdom:query_selector("ol")) do
+ if count_child_elements(el) == 0 then
+ el:remove_node()
+ -- local newli = el:create_element("li")
+ -- local newspan = newli:create_element("span")
+ -- newli:add_child_node(newspan)
+ -- el:add_child_node(newli)
+ end
+ end
+ -- place child elements of the <li> elements to an <a> element, epubcheck reports
+ -- error for text nodes that are direct child of <li>
+ for _, el in ipairs(tocdom:query_selector("li")) do
+ local text = {}
+ local link -- save the <a> element
+ for i, child in ipairs(el._children) do
+ if child:is_text() then
+ -- trim spurious spaces
+ local childtext = child._text:gsub("^%s*",""):gsub("%s*$","")
+ -- save the text for the later use
+ table.insert(text, childtext)
+ child:remove_node()
+ elseif child:is_element() and child:get_element_name() == "a" then
+ link = child
+ table.insert(text, child:get_text())
+ end
+ end
+ if link then
+ local content = table.concat(text, " ")
+ -- remove the original text
+ link._children = {}
+ local text = link:create_text_node(content)
+ link:add_child_node(text)
+ end
+ end
+ return tocdom
+
+end
+local function cleanTOC(content)
+ -- remove spurious empty elements from the TOC, to make epubcheck happy
+ -- find the file with TOC ("properties" attribute set to "nav"
+ local opfdom = dom.parse(content,{})
+ for _,item in ipairs(opfdom:query_selector("item")) do
+ local properties = item:get_attribute("properties") or ""
+ if properties:match("nav") then
+ local filename = item:get_attribute("href")
+ if filename then
+ filename = outputdir .. "/" .. filename
+ local f = io.open(filename, "r")
+ local t = f:read("*all")
+ f:close()
+ local tocdom = dom.parse(t)
+ tocdom = remove_spurious_TOC_elements(tocdom)
+ f = io.open(filename,"w")
+ f:write(tocdom:serialize())
+ f:close()
+ end
+ end
+ end
+
+
+end
+
+local function fix_properties(content)
+ -- some properties should be used only in the <spine> element, so we need to move them
+ -- here from the <manifest> section
+ -- because why it should be easy, when you can just make messy specification
+ -- and of course my old code is extremely messy as well.
+ if content:match("page%-spread%-") or content:match("rendition") then
+ local spread_ids = {}
+ local opfdom = dom.parse(content,{})
+ local update_properties = function(id, s)
+ local current_val = spread_ids[id] or {}
+ current_val[#current_val + 1] = s
+ spread_ids[id] = current_val
+ return ""
+ end
+ for _,item in ipairs(opfdom:query_selector("manifest item")) do
+ local properties = item:get_attribute "properties"
+ if properties then
+ local id = item:get_attribute "id"
+ properties = properties:gsub("(page%-spread%-[^%s]+)", function(s) return update_properties(id,s) end)
+ properties = properties:gsub("(rendition%:[^%s]+)", function(s) return update_properties(id,s) end)
+ -- properties attribute cannot be empty, we must disable it if
+ -- it doesn't contain anything after removing of the page spread
+ if properties:match("^%s*$") then properties = nil
+ end
+ item:set_attribute("properties", properties)
+ end
+ end
+ for _, item in ipairs(opfdom:query_selector("spine itemref")) do
+ local idref = item:get_attribute("idref")
+ local spread = spread_ids[idref]
+ if spread then
+ item:set_attribute("properties", table.concat(spread, " "))
+ end
+ end
+ return opfdom:serialize()
+ end
+ return content
+end
+
local function cleanOPF()
-- in epub3, there must be table of contents
-- if there is no toc in the document, we must add generic one
local opf = "content.opf"
local f = io.open(opf,"r")
if not f then
- print("Cannot open "..opf .. " for toc searching")
+ log:info("Cannot open "..opf .. " for toc searching")
return nil
end
local content = f:read("*all")
f:close()
if content:find "properties[%s]*=[%s]*\"[^\"]*nav" then
- print "TOC nav found"
+ log:info "TOC nav found"
+ cleanTOC(content)
else
- print "no TOC, using generic one"
+ log:info "no TOC, using a generic one"
local inputfile = input .. "." .. ext
- print("Main file name", inputfile)
+ log:info("Main file name: ".. inputfile)
-- write toc file
local toc_name = "generic_toc" .."."..ext
local f = io.open(outputdir .. "/" .. toc_name, "w")
@@ -142,6 +259,7 @@ local function cleanOPF()
content = eb.remove_empty_guide(content)
content = add_media_overlays(content)
+ content = fix_properties(content)
f = io.open(outputdir .. "/" ..opf,"w")
f:write(content)
f:close()
@@ -152,6 +270,7 @@ end
function writeContainer()
--local ret = eb.writeContainer()
+ log:info "write container"
eb.make_opf()
cleanOPF()
local ret = eb.pack_container()
diff --git a/support/tex4ebook/exec_mobi.lua b/support/tex4ebook/exec_mobi.lua
index 11871ade76..ce10b6da76 100644
--- a/support/tex4ebook/exec_mobi.lua
+++ b/support/tex4ebook/exec_mobi.lua
@@ -1,6 +1,7 @@
module(...,package.seeall)
local eb = require("exec_epub")
local ebookutils = require("mkutils")
+local log = logging.new "exec_mobi"
function prepare(params)
return eb.prepare(params)
@@ -14,7 +15,7 @@ function writeContainer()
local ret = eb.writeContainer()
-- convert the epub file to mobi
local epubpath = eb.basedir .. "/" .. eb.outputfile
- print("Pack mobi "..os.execute("kindlegen " .. epubpath))
+ log:info("Pack mobi "..os.execute("kindlegen " .. epubpath))
-- find the mobi filename
local mobifile = epubpath:gsub("epub$", "mobi")
local mobidist = eb.destdir .. eb.outputfile:gsub("epub$", "mobi")
diff --git a/support/tex4ebook/readme.tex b/support/tex4ebook/readme.tex
index 2a6110e03f..13b064bf31 100644
--- a/support/tex4ebook/readme.tex
+++ b/support/tex4ebook/readme.tex
@@ -1,29 +1,23 @@
\hypertarget{introduction}{%
\section{Introduction}\label{introduction}}
-\texttt{TeX4ebook} is bundle of Lua scripts and \texttt{LaTeX} packages
-for conversion of LaTeX files to ebook formats, for example
-\texttt{epub}, \texttt{mobi} and \texttt{epub3}. \texttt{tex4ht} is used
-as conversion engine.
-
-Note that while \texttt{mobi} is supported by Amazon Kindle, most
-widespread ebook reader, it doesn't support \texttt{mathml} and this
-means that math must re represented as images. The same is true for
-\texttt{epub}. This is not a good thing, especially for inline math, as
-you may experience wrong baselines. If your ebook contains math, the
-only correct solution is to produce \texttt{epub3}, as it supports
-\texttt{mathml}. The issue with \texttt{epub3} is, that majority of
-\texttt{e-ink} ebook readers doesn't support this format, reader
-applications exists mainly for Android and Apple devices. For books
-which contains mainly prose, all formats should be suitable, but
-\texttt{epub3} supports most features from web standards, such as
-\texttt{CSS}.
-
-As with \texttt{tex4ht}, the emphasis is on conversion of document's
-logical structure and metadata, basic visual appearance is preserved as
-well, but you should use custom configurations if you want to make the
-document more visually appealing. You can include custom \texttt{CSS} or
-fonts in configuration files.
+\texttt{TeX4ebook} is a tool for conversion from \LaTeX~to ebook
+formats, such as EPUB, MOBI and EPUB 3. It is based on
+\texttt{TeX4ht}\footnote{\url{https://tug.org/tex4ht/}}, which provides
+instructions for the actual \LaTeX~to HTML conversion, and on
+\texttt{make4ht}\footnote{\url{https://ctan.org/pkg/make4ht?lang=en}}.
+
+The conversion is focused on the logical structure of the converted
+document and metadata. Basic visual appearance is preserved as well, but
+you should use custom configurations if you want to make the document
+more visually appealing. You can include custom \texttt{CSS} or fonts in
+a configuration file.
+
+\texttt{TeX4ebook} supports the same features as \texttt{make4ht}, in
+particular build files and extensions. These may be used for
+post-processing of the generated HTML files, or to configure the image
+conversion. See the \texttt{make4ht} documentation to see the supported
+features.
\hypertarget{license}{%
\subsection{License}\label{license}}
@@ -67,8 +61,11 @@ But it is optional. You shouldn't need to modify your \TeX~files
\section{Command line options}\label{command-line-options}}
\begin{description}
+\item[\texttt{-a,-\/-loglevel}]
+Set message log level. Possible values: debug, info, status, warning,
+error, fatal. Default: status.
\item[\texttt{-c,-\/-config}]
-specify custom config file for \texttt{tex4ht}
+specify custom config file for \texttt{TeX4ht}
\end{description}
\textbf{example config file}: File \texttt{sample.cfg}
@@ -95,7 +92,10 @@ Specify make4ht build file\footnote{\url{https://github.com/michal-h21/make4ht\#
Defaulf build file filename is \texttt{filename.mk4}, use this option if
you use different filename.
\item[\texttt{-f,-\/-format\ (default\ epub)}]
-Output format. Epub, Epub3 and Mobi formats are supported.
+Output format. Possible values are \texttt{epub}, \texttt{epub3} and
+\texttt{mobi}.
+\item[\texttt{-j,-\/-jobname}]
+Specify the output file name, without file extension.
\item[\texttt{-l,-\/-lua}]
Use LuaLaTeX as TeX engine.
\item[\texttt{-m,-\/-mode\ (default\ default)}]
@@ -107,8 +107,8 @@ times.
Resolution of generated images, for example math. It should meet
resolution of target devices, which is usually about 167 ppi.
\item[\texttt{-s,-\/-shell-escape}]
-Enable shell escape in htlatex run. This may be needed if you run
-external commands from your source files.
+Enable shell escape in the \texttt{htlatex} run. This is necessary for
+the execution of the external commands from your source files.
\item[\texttt{-t,-\/-tidy}]
process output html files with \texttt{HTML\ tidy} command\footnote{It
needs to be installed separately}.
@@ -121,8 +121,8 @@ Print the version number.
\hypertarget{configuration}{%
\section{Configuration}\label{configuration}}
-\texttt{tex4ebook} uses \texttt{tex4ht}\footnote{\url{http://www.tug.org/tex4ht/}}
-for conversion from LaTeX to html. \texttt{tex4ht} is highly
+\texttt{TeX4ebook} uses \texttt{TeX4ht}\footnote{\url{http://www.tug.org/tex4ht/}}
+for conversion from LaTeX to html. \texttt{TeX4ht} is highly
configurable using config files. Basic config file structure is
\begin{verbatim}
@@ -134,19 +134,19 @@ configurable using config files. Basic config file structure is
\end{verbatim}
Basic info about command configurations can be found in a
-work-in-progres \emph{tex4ht tutorial}\footnote{\url{https://github.com/michal-h21/helpers4ht/wiki/tex4ht-tutorial}},
-\emph{tex4ht documentation}\footnote{\url{http://www.tug.org/applications/tex4ht/mn11.html}},
+work-in-progres \emph{TeX4ht tutorial}\footnote{\url{https://github.com/michal-h21/helpers4ht/wiki/tex4ht-tutorial}},
+\emph{TeX4ht documentation}\footnote{\url{http://www.tug.org/applications/tex4ht/mn11.html}},
and in series of blogposts on CV Radhakrishnan's blog: \emph{Configure
-part 1}\footnote{\url{http://www.cvr.cc/?p=323}}, \emph{Configure part
-2}\footnote{\url{http://www.cvr.cc/?p=362}}, \emph{Low level
-commands}\footnote{\url{http://www.cvr.cc/?p=482}}. Available options
-for \texttt{\textbackslash{}Preamble} command are listed in the article
-\emph{TeX4ht: options}\footnote{\url{http://www.cvr.cc/?p=504}}.
+part 1}\footnote{\url{https://web.archive.org/web/20180908234227/http://www.cvr.cc/?p=323}},
+\emph{Configure part 2}\footnote{\url{https://web.archive.org/web/20180908201057/http://www.cvr.cc/?p=362}},
+\emph{Low level commands}\footnote{\url{https://web.archive.org/web/20180909101325/http://cvr.cc/?p=482}}.
+Available options for \texttt{\textbackslash{}Preamble} command are
+listed in the article \emph{TeX4ht: options}\footnote{\url{https://web.archive.org/web/20180813043722/http://cvr.cc/?p=504}}.
\emph{Comparison of tex4ebook and Pandoc output}\footnote{\url{https://github.com/richelbilderbeek/travis_tex_to_epub_example_1}}
-Great source of tips for \texttt{tex4ht} configuring is \emph{tex4ht tag
-on TeX.sx}\footnote{\url{http://tex.stackexchange.com/questions/tagged/tex4ht}},
-there is also a \emph{tag for tex4ebook}\footnote{\url{http://tex.stackexchange.com/questions/tagged/tex4ebook}}.
+A great source of tips for \texttt{TeX4ht} configuration is \emph{tex4ht
+tag on TeX.sx}\footnote{\url{http://tex.stackexchange.com/questions/tagged/tex4ht}}.
+There is also a \emph{tag for tex4ebook}\footnote{\url{http://tex.stackexchange.com/questions/tagged/tex4ebook}}.
Examples of interesting questions are \emph{including images and fonts
in ebooks}\footnote{\url{http://tex.stackexchange.com/a/213165/2891}} or
@@ -161,7 +161,7 @@ in ebooks}\footnote{\url{http://tex.stackexchange.com/a/213165/2891}} or
\Configure{UniqueIdentifier}{identifier}
\end{verbatim}
-Every epub file should have unique identifier, like ISBN, DOI, URI etc.
+Every EPUB file should have unique identifier, like ISBN, DOI, URI etc.
Default identifier is URI, with value
\texttt{http://example.com/\textbackslash{}jobname}.
@@ -179,8 +179,8 @@ to strip away any information which don't belongs here, such as
\Configure{OpfScheme}{URI}
\end{verbatim}
-Type of unique identifier, default type is URI. It is used only in
-\texttt{epub}, it is deprecated for \texttt{epub3}
+Type of unique identifier, default type is URI. It is used only in the
+EPUB format, it is deprecated for EPUB 3.
\begin{verbatim}
\Configure{resettoclevels}{list of section types in descending order}
@@ -194,7 +194,7 @@ file. Default value is the whole document hierarchy, from
\Configure{DocumentLanguage}{language code}
\end{verbatim}
-Each ePub file must declare the document language. It is inferred from
+Each EPUB file must declare the document language. It is inferred from
\texttt{babel} main language by default, but you can configure it when
it doesn't work correctly. The \texttt{language\ code} should be in
\href{https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes}{ISO 639-1}
@@ -243,11 +243,12 @@ Add item to \texttt{\textless{}manifest\textgreater{}} section in the
\Configure{xmlns}{prefix}{uri}
\end{verbatim}
-Add xml name space to \texttt{xhtml} files. Useful in \texttt{EPUB\ 3}
+Add \texttt{XML} name space to the generated \texttt{XHTML} files.
+Useful in \texttt{EPUB\ 3}.
-\hypertarget{commands-available-in-config-files}{%
-\subsection{Commands available in config
-files}\label{commands-available-in-config-files}}
+\hypertarget{commands-available-in-the-config-file}{%
+\subsection{Commands available in the config
+file}\label{commands-available-in-the-config-file}}
\begin{description}
\item[\texttt{\textbackslash{}OpfRegisterFile{[}filename{]}}]
@@ -293,8 +294,44 @@ information.
\hypertarget{troubleshooting}{%
\section{Troubleshooting}\label{troubleshooting}}
+\hypertarget{fixed-layout-epub}{%
+\subsection{Fixed layout EPUB}\label{fixed-layout-epub}}
+
+The basic support for the Fixed layout EPUB 3 can be enabled using the
+following configurations:
+
+\begin{verbatim}
+\Configure{OpfMetadata}{\HCode{<meta property="rendition:layout">pre-paginated</meta>}}
+\Configure{OpfMetadata}{\HCode{<meta property="rendition:orientation">landscape</meta>}}
+\Configure{OpfMetadata}{\HCode{<meta property="rendition:spread">none</meta>}}
+\Configure{@HEAD}{\HCode{<meta name="viewport" content="width=1920, height=1080"/>\Hnewline}}
+\end{verbatim}
+
+Modify the dimensions in the
+\texttt{\textless{}meta\ name="viewport\textgreater{}} element according
+to your needs.
+
+\hypertarget{math-issues}{%
+\subsection{Math issues}\label{math-issues}}
+
+Note that while \texttt{mobi} is supported by Amazon Kindle, most
+widespread ebook reader, it doesn't support \texttt{MathML}. This means
+that math must be represented as images. The same issue is true for the
+EPUB format as well. This is problematic especially for the inline math,
+as you may experience wrong vertical alignment of the math content and
+surrounding text. If your ebook contains math, a better solution is to
+produce the \texttt{epub3} format, as it supports \texttt{MathML}. The
+issue with EPUB 3 is that majority of \texttt{e-ink} ebook readers don't
+support it. Reader applications exists mainly for Android and Apple
+devices. For books which contains mainly prose, all formats should be
+suitable, but EPUB 3 supports most features from web standards, such as
+\texttt{CSS}.
+
+\hypertarget{compilation-errors}{%
+\subsection{Compilation errors}\label{compilation-errors}}
+
When compilation of the document breaks with error during \texttt{LaTeX}
-run, it may be caused by some problem in \texttt{tex4ht} configuration.
+run, it may be caused by some problem in \texttt{TeX4ht} configuration.
Comment out line \texttt{\textbackslash{}usepackage\{tex4ebook\}} in
your source file and run command:
@@ -303,9 +340,9 @@ htlatex filename
\end{verbatim}
if same error as in \texttt{tex4ebook} run arises, the problem is in
-some \texttt{tex4ht} configuration. Try to identify the source of
+some \texttt{TeX4ht} configuration. Try to identify the source of
problem and if you cannot find the solution, make minimal example
-showing the error and ask for help either on \emph{tex4ht mailing
+showing the error and ask for help either on \emph{TeX4ht mailing
list}\footnote{\url{http://tug.org/mailman/listinfo/tex4ht}} or on
\emph{TeX.sx}\footnote{\url{http://tex.stackexchange.com/}}.
diff --git a/support/tex4ebook/tex4ebook b/support/tex4ebook/tex4ebook
index a95bf44c23..731607fc5b 100755
--- a/support/tex4ebook/tex4ebook
+++ b/support/tex4ebook/tex4ebook
@@ -5,6 +5,9 @@
kpse.set_program_name("luatex")
require("lapp-mk4")
-- require("ebookutils")
+logging = require "make4ht-logging"
+if os.type == "windows" then logging.use_colors = false end
+local log = logging.new("tex4ebook")
local ebookutils = require "mkutils"
local mkparams = require "mkparams"
local mk_config = require "make4ht-config"
@@ -24,39 +27,37 @@ local output_formats={epub=true,mobi=true,epub3=true}
local executor=nil
local tidy = false
local include_fonts = false
+
+-- message used for option parsing by the mkparams lib
local arg_message = [[
tex4ebook - ebook generation support for LaTeX
Usage:
tex4ebook [switches] filename ["tex4ht.sty op."] ["tex4ht op."] ["t4ht op"] ["latex op"]
+ -a,--loglevel (default status) Set log level.
+ possible values: debug, info, status, warning, error, fatal
-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
-f,--format (default epub) Output format. Supported values: epub, epub3, mobi
-h,--help Display help message
+ -j,--jobname (default nil) Set the jobname
-l,--lua Use lualatex for document compilation
-m,--mode (default default) Switch which can be used in the makefile
-r,--resolution (default 167)
-s,--shell-escape Enable shell escape in htlatex run
-t,--tidy Run html tidy on html output. May result in wrong spacing!
- -v,--version Display version number
-x,--xetex Use xelatex for document compilation
+ -v,--version Display version number
+ ]]
- <filename> (string) Input file name
-
-Positional optional argumens:
- ["tex4ht.sty op."] Additional parameters for tex4ht.sty
- ["tex4ht op."] Options for tex4ht command
- ["t4ht op"] Options for t4ht command
- ["latex op"] Additional options for LaTeX
+-- options for the template used by mkparams to generate the help message
+local mkparams_parameters = {
+ progname = "tex4ebook",
+ issue_tracker = "https://github.com/michal-h21/tex4ebook/issues"
+}
-Documentation: https://tug.org/applications/tex4ht/mn.html
-Issue tracker for tex4ht bugs: https://puszcza.gnu.org.ua/bugs/?group=tex4ht
-Issue tracker for tex4ebook bugs: https://github.com/michal-h21/tex4ebook/issues
-]]
-
--- This option is no longer available, all files must be unicode
--- -u,--utf8
-local args=lapp(arg_message)
+-- process the command line arguments
+local args = mkparams.get_args(mkparams_parameters, arg_message)
if args["filename"] == nil and args["version"] == false then
print(arg_message)
@@ -66,7 +67,7 @@ else
end
if args.version then
- print "tex4ebook v0.2c"
+ print "tex4ebook v0.3"
return
end
@@ -85,11 +86,6 @@ if args["include-fonts"] then
include_fonts = true
end
--- local mathml = ","
--- if args["mathml"] then
--- -- mathml = ",mathml,"
--- tex4ht_sty_par = tex4ht_sty_par .. ",mathml"
--- end
local mode = args.mode or "default"
if os.type=="unix" then
@@ -109,25 +105,7 @@ if args.tidy then
else
tidy = false
end
--- Env file copying
-
---[[if not ebookutils.file_exists("tex4ht.env") then
-local env_file = kpse.find_file("epub2.env")
-ebookutils.copy_filter(env_file,"tex4ht.env",function(s) return s % {
-move = move_cmd,
-copy = copy_cmd,
-resolution = args.resolution
-} end)
-end--]]
-
---print ("nazdar ${world}" % {world="svete"})
---print(args.config)
-
-local input = ebookutils.remove_extension(input_file)
-local config=ebookutils.remove_extension(args.config)
--- local tex4ht_sty_par = config ..tex4ht_sty_par..","+args.format
---local sty_args = args[2] and ", " .. args[2] or ""
local sty_args = ""
if args[2] then
sty_args = "," .. args[2]
@@ -138,12 +116,17 @@ local t4ht_par = t4ht_par + args[4]
local latex_par = latex_par + args[5]
-- use default parameter processing from make4ht
--- add some needed args
+-- add some needed args (is it useful anymore?)
args.filename=input_file
+
+-- let make4ht handle the common options
local params = mkparams.process_args(args)
+local input = params.input
+log:status("Conversion started")
+log:status("Input file: ".. params.tex_file)
-local output_format = params.output_format --args.format
+local output_format = params.output_format
-- use epub as default output_format
output_format = output_format or "epub"
local extensions = ebookutils.load_extensions(params.extensions, output_format)
@@ -152,7 +135,7 @@ local oldparams = {
-- htlatex=latex_cmd
-- ,input=input
-- ,tex_file = tex_file
- format= output_format
+ format = output_format
-- ,latex_par=latex_par
-- ,tex4ht_sty_par=tex4ht_sty_par
-- ,tex4ht_par=tex4ht_par
@@ -162,7 +145,6 @@ local oldparams = {
,tidy = tidy
,include_fonts = include_fonts
,resolution=args.resolution
- ,mathml=mathml
,packages="\\RequirePackage{tex4ebook}"
}
@@ -175,25 +157,15 @@ params.tex4ht_sty_par=params.tex4ht_sty_par .. ",charset=utf-8,"..output_format
params.tex4ht_par= " -cmozhtf -utf8" .. params.tex4ht_par
-if output_formats[output_format] then
- executor=require("exec_"..output_format)
- params=executor.prepare(params)
- if #extensions > 0 then
- params = ebookutils.extensions_prepare_parameters(extensions,params)
- end
-else
- print("Unknown output format: "..output_format)
- return
-end
-- find tex4ebook configuration file
local configname = "tex4ebook"
local conffile = mk_config.find_config(configname) or mk_config.find_xdg_config(configname)
if conffile then
- print("Using configuration file: " .. conffile)
+ log:info("Using configuration file: " .. conffile)
ebookutils.load_config(params, conffile)
else
- print "No conffile"
+ log:info "No conffile"
end
local build_file = input.. ".mk4"
@@ -205,8 +177,20 @@ end
local config_file = ebookutils.load_config(params, build_file)
params["config_file"] = config_file
+
+
+if output_formats[output_format] then
+ executor=require("exec_"..output_format)
+ params=executor.prepare(params)
+ if #extensions > 0 then
+ params = ebookutils.extensions_prepare_parameters(extensions,params)
+ end
+else
+ log:error("Unknown output format: "..output_format)
+ return
+end
--config_file.Make:run()
-print("${htlatex} ${input} \"${tex4ht_sty_par}\" \"${tex4ht_par}\" \"${t4ht_par}\" \"${latex_par}\"" % params)
+-- print("${htlatex} ${input} \"${tex4ht_sty_par}\" \"${tex4ht_par}\" \"${t4ht_par}\" \"${latex_par}\"" % params)
if #extensions > 0 then
config_file.Make = ebookutils.extensions_modify_build(extensions, config_file.Make)
end
@@ -214,4 +198,5 @@ end
executor.run(input,params)
executor.writeContainer()
executor.clean()
+log:status("Conversion finished")
--print(args[1])
diff --git a/support/tex4ebook/tex4ebook-doc.pdf b/support/tex4ebook/tex4ebook-doc.pdf
index 6c7fd83af0..8372406fd9 100644
--- a/support/tex4ebook/tex4ebook-doc.pdf
+++ b/support/tex4ebook/tex4ebook-doc.pdf
Binary files differ
diff --git a/support/tex4ebook/tex4ebook.4ht b/support/tex4ebook/tex4ebook.4ht
index e4233fc55a..e623ac8bc2 100644
--- a/support/tex4ebook/tex4ebook.4ht
+++ b/support/tex4ebook/tex4ebook.4ht
@@ -178,6 +178,10 @@ href="#1" media-type="\a:CoverMimeType" />}}
\patch:sec:register{likesection}
\patch:sec:register{likesubsection}
\patch:sec:register{likesubsubsection}
+\patch:sec:register{appendix}
+\patch:sec:register{appendixsec}
+\patch:sec:register{appendixsubsec}
+\patch:sec:register{appendixsubsubsec}
\:CheckOption{epub}
\if:Option
@@ -264,7 +268,7 @@ href="#1" media-type="\a:CoverMimeType" />}}
\def\tmp:processlevel#1{
\bgroup
\csxdef{tmp:resettoclevels#1}{}
- \def\do##1{\csxdef{tmp:resettoclevels#1}{\csname tmp:resettoclevels#1\endcsname ##1,like##1,}}
+ \def\do##1{\csxdef{tmp:resettoclevels#1}{\csname tmp:resettoclevels#1\endcsname ##1,like##1,\appendix:type{##1}}}
\def\tmp:parse##1#1##2\nil{
\docsvlist{#1##2}
}
@@ -273,6 +277,8 @@ href="#1" media-type="\a:CoverMimeType" />}}
\navsection{#1}{\csname tmp:resettoclevels#1\endcsname}
% define hierarchy also for starred sections
\navsection{like#1}{\csname tmp:resettoclevels#1\endcsname}
+ % and for appendices
+ \ifcsdef{appendix:type:#1}{\navsection{\csuse{appendix:type:#1}}{\csname tmp:resettoclevels#1\endcsname}}{}
}
% define children levels for each sectioning level
@@ -292,6 +298,14 @@ href="#1" media-type="\a:CoverMimeType" />}}
\ifx\:temp\z@ro\else#1\fi
}
+% to create correct hiearchical NCX for appendices, we register corresponding appendix types
+% for various section types
+\def\appendix:type#1{\ifcsdef{appendix:type:#1}{\csuse{appendix:type:#1},}{}}
+\def\def:appendix:type#1#2{\csdef{appendix:type:#1}{#2}}
+\def:appendix:type{chapter}{appendix}
+\def:appendix:type{section}{appendixsec}
+\def:appendix:type{subsection}{appendixsubsec}
+\def:appendix:type{subsubsection}{appendixsubsubsec}
%
\def\ncx:head{%
@@ -312,7 +326,7 @@ href="#1" media-type="\a:CoverMimeType" />}}
% define toc levels which should be included in the NCX file
\NewConfigure{resettoclevels}{1}
-\Configure{resettoclevels}{part,appendix,chapter,appendixsec,section,appendixsubsec,subsection,appendixsubsubsec,subsubsection,paragraph}
+\Configure{resettoclevels}{part,chapter,section,subsection,subsubsection,paragraph}
\def\:tempa{%
\EndP
@@ -369,6 +383,8 @@ href="#1" media-type="\a:CoverMimeType" />}}
\def\print:opf:scheme#1{ opf:scheme="#1"}
\def\:tempa{%
+% French language definition makes the : character active, which can cause compilation error
+\ifdefined\XeTeXcharclass\XeTeXcharclass `\: \z@\fi%
\bgroup
\setcounter{tocdepth}{3}
% Basic sctructure of the opf file
diff --git a/support/tex4ebook/tex4ebook.sty b/support/tex4ebook/tex4ebook.sty
index c3726ee167..27a46b756e 100644
--- a/support/tex4ebook/tex4ebook.sty
+++ b/support/tex4ebook/tex4ebook.sty
@@ -1,10 +1,10 @@
-% Package odsfile. Author Michal Hoftich <michal.h21@gmail.com>
+% Package tex4ebook. Author Michal Hoftich <michal.h21@gmail.com>
% This package is subject of LPPL license, version 1.3
\ProvidesPackage{tex4ebook}[2016/03/31 version 0.1d]
\RequirePackage{etoolbox}
\RequirePackage{kvoptions}
\RequirePackage{graphicx}
-% Command for generating NCX file. Hard work is odne in the file
+% Command for generating NCX file. The hard work is done in the file
% tex4ebook.4ht
\def\ncxtable{}
% Command for generating OPF file
@@ -122,18 +122,41 @@
\def\Author{Anonymous}
% We need to save values of title, author etc.
-%\AtBeginDocument{
-\let\origtitle\title
-\renewcommand\title[1]{%
- \origtitle{#1}
- \let\Title\@title
+\let\tf@orig@title\title
+
+% normal \title
+\newcommand\tf@title[1]{%
+ \tf@orig@title{#1}%
+ \let\Title\@title%
+}
+
+% \title with optional argument
+\newcommand\tf@opttitle[2][]{%
+ \tf@orig@title[#1]{#2}%
+ \let\Title\@title%
+}
+
+% some classes (amsart) define \title command with optional argument
+\renewcommand\title{%
+\@ifnextchar[\tf@opttitle\tf@title%
}
-\let\origauthor\author
-\renewcommand\author[1]{%
- \origauthor{#1}%
- \let\Author\@author
+\let\tf@orig@author\author
+\newcommand\tf@author[1]{%
+ \tf@orig@author{#1}%
+ \let\Author\@author%
}
+
+\newcommand\tf@optauthor[2][]{%
+ \tf@orig@author[#1]{#2}%
+ \let\Author\@author%
+}
+
+% support optiona argument for \author as well
+\renewcommand\author{%
+\@ifnextchar[\tf@optauthor\tf@author%
+}
+
%\let\Author\@author
\let\Date\today
\let\origdate\date