diff options
Diffstat (limited to 'support/tex4ebook')
-rw-r--r-- | support/tex4ebook/README | 139 | ||||
-rw-r--r-- | support/tex4ebook/changelog.tex | 100 | ||||
-rw-r--r-- | support/tex4ebook/exec_epub.lua | 372 | ||||
-rw-r--r-- | support/tex4ebook/exec_epub3.lua | 129 | ||||
-rw-r--r-- | support/tex4ebook/exec_mobi.lua | 3 | ||||
-rw-r--r-- | support/tex4ebook/readme.tex | 137 | ||||
-rwxr-xr-x | support/tex4ebook/tex4ebook | 99 | ||||
-rw-r--r-- | support/tex4ebook/tex4ebook-doc.pdf | bin | 73368 -> 78095 bytes | |||
-rw-r--r-- | support/tex4ebook/tex4ebook.4ht | 20 | ||||
-rw-r--r-- | support/tex4ebook/tex4ebook.sty | 45 |
10 files changed, 656 insertions, 388 deletions
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 Binary files differindex 6c7fd83af0..8372406fd9 100644 --- a/support/tex4ebook/tex4ebook-doc.pdf +++ b/support/tex4ebook/tex4ebook-doc.pdf 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 |