1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
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
m.progname = "make4ht"
-- set the version number before call to process_args()
m.version_number = "v0.1"
m.optiontext = [[
${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
-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 the tex4ht command
-s,--shell-escape Enables running external programs from LaTeX
-u,--utf8 [obsolete] The document is generated in UTF8 encoding by default
-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
local function is_escapedargument(arg)
-- we need to ignore make4ht options which can be used without filename, ie --version and --help
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("^%-.+")
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 ""
optiontext = optiontext .. parameters.postparams ..[[ <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
Documentation: https://tug.org/applications/tex4ht/mn.html
Issue tracker for tex4ht bugs: https://puszcza.gnu.org.ua/bugs/?group=tex4ht
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
-- as fix, add a space before options at the end (we need to stop to add spaces as soon as we find
-- nonempty string which doesn't start with - it will be filename or tex4ht.sty options
if #arg > 1 then -- do this only if more than one argument is used
for i=#arg,1,-1 do
local current = arg[i]
if is_escapedargument(arg[i]) then
arg[i] = " ".. arg[i]
-- empty parameter
elseif current == "" then
else
break
end
end
end
--print("--------------\n" .. optiontext .."--------------\n")
return lapp(optiontext % parameters)
end
--- get outptut file format and list of extensions from --format option string
local function get_format_extensions(format_string)
local format, rest = format_string:match("^([a-zA-Z0-9]+)(.*)")
local extensions = {}
-- it is possible to pass only the extensions
rest = rest or format_string
rest:gsub("([%+%-])([^%+^%-]+)",function(typ, name)
table.insert(extensions, {type = typ, name = name})
end)
return format, extensions
end
-- try to make safe filename
local function escape_filename(input)
-- quoting don't work on Windows, so we will just
if os.type == "windows" then
return '"' .. input .. '"'
else
-- single quotes are safe in Unix
return "'" .. input .. "'"
end
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=".. escape_filename(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
local function tex_file_not_exits(tex_file)
-- try to find the input file, return false if we cannot find it
return not (kpse.find_file(tex_file, "tex") or kpse.find_file(tex_file .. ".tex", "tex"))
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)
--local v = args[key] and value or ""
local v = ""
if args[key] then v = value end
table.insert(tb,v)
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()
end
local outdir = ""
local packages = ""
if args["output-dir"] ~= "nil" then
outdir = args["output-dir"] or ""
outdir = outdir:gsub('\\','/')
outdir = outdir:gsub('/$','')
end
-- make4ht now requires UTF-8 output, because of DOM filters
-- numeric entites are expanded to Unicode characters. These
-- characters would be displayed incorrectly in 8 bit encodings.
args.utf8 = true
if args.backend == "lua4ht" then
args.lua = true
args.xetex = nil
args.utf8 = true
args["no-tex4ht"] = true
packages = packages .."\\RequirePackage{lua4ht}"
end
local compiler = args.lua and "dvilualatex" or args.xetex and "xelatex --no-pdf" or "latex"
local tex_file, is_tmp_file = handle_input_file(args.filename)
-- test if the file exists
if not is_tmp_file and tex_file_not_exits(tex_file) then
log:warning("Cannot find input file: " .. tex_file)
end
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")
--table.insert(latex_params,args["shell-escape"] and "-shell-escape")
local t4sty = args[1] or ""
-- test if first option is custom config file
local cfg_tmp = t4sty:match("([^,^ ]+)")
if cfg_tmp and cfg_tmp ~= args.config then
local fn = cfg_tmp..".cfg"
local f = io.open(fn,"r")
if f then
args.config = cfg_tmp
f:close()
end
end
--[[if args[1] and args[1] ~= "" then
t4sty = args[1]
else
--]]
-- Different behaviour from htlatex
local utf = args.utf8 and ",charset=utf-8" or ""
t4sty = args.config .. "," .. t4sty .. utf
--end
local tex4ht = ""
local dvi= args.xetex and "xdv" or "dvi"
if args[2] and args[2] ~="" then
tex4ht = args[2]
else
tex4ht = args.utf8 and " -cmozhtf -utf8" or ""
end
-- set the correct extension for tex4ht if xetex is used
if args.xetex then tex4ht = tex4ht .. " -.xdv" end
local t4ht = args[3] or ""
local mode = args.mode or "default"
local build_file = input.. ".mk4"
if args["build-file"] and args["build-file"] ~= "nil" then
build_file = args["build-file"]
end
local outformat, extensions
if args["format"] and arg["format"] ~= "nil" then
outformat, extensions = get_format_extensions(args["format"])
end
local parameters = {
htlatex = compiler
,input=input
,tex_file=tex_file
,packages=packages
,latex_par=table.concat(latex_params," ")
--,config=ebookutils.remove_extension(args.config)
,tex4ht_sty_par=t4sty
,tex4ht_par=tex4ht
,t4ht_par=t4ht
,mode = mode
,dvi = dvi
,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
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
log:info("Output format: ".. outformat)
for _, ex in ipairs(extensions) do
log:info("Extension: ".. ex.type .. ex.name)
end
end
return parameters
end
m.get_args = get_args
m.get_format_extensions = get_format_extensions
m.process_args = process_args
return m
|