Skip to content

Commit a5dfc85

Browse files
committed
diagram-generator: refactor tikz2image
Closes: #73
1 parent c4c0839 commit a5dfc85

File tree

1 file changed

+86
-73
lines changed

1 file changed

+86
-73
lines changed

diagram-generator/diagram-generator.lua

+86-73
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ Copyright: © 2018-2020 John MacFarlane <[email protected]>,
1111
2019-2020 Albert Krewinkel <[email protected]>
1212
License: MIT – see LICENSE file for details
1313
]]
14+
-- Module pandoc.system is required and was added in version 2.7.3
15+
PANDOC_VERSION:must_be_at_least '2.7.3'
16+
17+
local system = require 'pandoc.system'
18+
local with_temporary_directory = system.with_temporary_directory
19+
local with_working_directory = system.with_working_directory
1420

1521
-- The PlantUML path. If set, uses the environment variable PLANTUML or the
1622
-- value "plantuml.jar" (local PlantUML version). In order to define a
@@ -93,83 +99,90 @@ local function graphviz(code, filetype)
9399
return final
94100
end
95101

96-
-- Compile LaTeX with Tikz code to an image:
97-
local function tikz2image(src, filetype, additionalPackages)
98-
99-
-- Define file names:
100-
local outfile = string.format("./tmp-latex/file.%s", filetype)
101-
local tmp = "./tmp-latex/file"
102-
local tmpDir = "./tmp-latex/"
103-
104-
-- Ensure, that the tmp directory exists:
105-
os.execute("mkdir -p tmp-latex")
106-
107-
-- Build and write the LaTeX document:
108-
local f = io.open(tmp .. ".tex", 'w')
109-
f:write("\\documentclass{standalone}\n\\usepackage{tikz}\n")
110-
111-
-- Any additional package(s) are desired?
112-
if additionalPackages then
113-
f:write(additionalPackages)
114-
end
115-
116-
f:write("\\begin{document}\n")
117-
f:write(src)
118-
f:write("\n\\end{document}\n")
119-
f:close()
120-
121-
-- Execute the LaTeX compiler:
122-
pandoc.pipe(pdflatexPath, {'-output-directory', tmpDir, tmp}, '')
123-
124-
-- Build the basic Inkscape command for the conversion:
125-
local baseCommand = " --without-gui --file=" .. tmp .. ".pdf"
126-
local knownFormat = false
127-
128-
if filetype == "png" then
129-
130-
-- Append the subcommands to convert into a PNG file:
131-
baseCommand = baseCommand .. " --export-png="
132-
.. tmp .. ".png --export-dpi=300"
133-
knownFormat = true
134-
135-
elseif filetype == "svg" then
136-
137-
-- Append the subcommands to convert into a SVG file:
138-
baseCommand = baseCommand .. " --export-plain-svg=" .. tmp .. ".svg"
139-
knownFormat = true
140-
141-
end
142-
143-
-- Unfortunately, continuation is only possible, if we know the actual
144-
-- format:
145-
if not knownFormat then
146-
error(string.format("Don't know how to convert pdf to %s.", filetype))
147-
end
148-
149-
local imgData = nil
150-
151-
-- We know the desired format. Thus, execute Inkscape:
152-
os.execute("\"" .. inkscapePath .. "\"" .. baseCommand)
102+
--
103+
-- TikZ
104+
--
105+
106+
--- LaTeX template used to compile TikZ images. Takes additional
107+
--- packages as the first, and the actual TikZ code as the second
108+
--- argument.
109+
local tikz_template = [[
110+
\documentclass{standalone}
111+
\usepackage{tikz}
112+
%% begin: additional packages
113+
%s
114+
%% end: additional packages
115+
\begin{document}
116+
%s
117+
\end{document}
118+
]]
153119

154-
-- Try to open the image:
155-
local r = io.open(tmp .. "." .. filetype, 'rb')
120+
--- Returns a function which takes the filename of a PDF and a
121+
-- target filename, and writes the input as the given format.
122+
-- Returns `nil` if conversion into the target format is not
123+
-- possible.
124+
local function convert_from_pdf(filetype)
125+
-- Build the basic Inkscape command for the conversion
126+
local inkscape_output_args
127+
if filetype == 'png' then
128+
inkscape_output_args = '--export-png="%s" --export-dpi=300'
129+
elseif filetype == 'svg' then
130+
inkscape_output_args = '--export-plain-svg="%s"'
131+
else
132+
return nil
133+
end
134+
return function (pdf_file, outfile)
135+
local inkscape_command = string.format(
136+
'"%s" --without-gui --file="%s" ' .. inkscape_output_args,
137+
inkscapePath,
138+
pdf_file,
139+
outfile
140+
)
141+
io.stderr:write(inkscape_command .. '\n')
142+
local command_output = io.popen(inkscape_command)
143+
-- TODO: print output when debugging.
144+
command_output:close()
145+
end
146+
end
156147

157-
-- Read the image, if available:
158-
if r then
159-
imgData = r:read("*all")
148+
--- Compile LaTeX with Tikz code to an image
149+
local function tikz2image(src, filetype, additional_packages)
150+
local convert = convert_from_pdf(filetype)
151+
-- Bail if there is now known way from PDF to the target format.
152+
if not convert then
153+
error(string.format("Don't know how to convert pdf to %s.", filetype))
154+
end
155+
return with_temporary_directory("tikz2image", function (tmpdir)
156+
return with_working_directory(tmpdir, function ()
157+
-- Define file names:
158+
local file_template = "%s/tikz-image.%s"
159+
local tikz_file = file_template:format(tmpdir, "tex")
160+
local pdf_file = file_template:format(tmpdir, "pdf")
161+
local outfile = file_template:format(tmpdir, filetype)
162+
163+
-- Build and write the LaTeX document:
164+
local f = io.open(tikz_file, 'w')
165+
f:write(tikz_template:format(additional_packages or '', src))
166+
f:close()
167+
168+
-- Execute the LaTeX compiler:
169+
pandoc.pipe(pdflatexPath, {'-output-directory', tmpdir, tikz_file}, '')
170+
171+
convert(pdf_file, outfile)
172+
173+
-- Try to open and read the image:
174+
local img_data
175+
local r = io.open(outfile, 'rb')
176+
if r then
177+
img_data = r:read("*all")
160178
r:close()
161-
end
179+
else
180+
-- TODO: print warning
181+
end
162182

163-
-- Delete the image tmp file:
164-
os.remove(outfile)
165-
166-
-- Remove the temporary files:
167-
os.remove(tmp .. ".tex")
168-
os.remove(tmp .. ".pdf")
169-
os.remove(tmp .. ".log")
170-
os.remove(tmp .. ".aux")
171-
172-
return imgData
183+
return img_data
184+
end)
185+
end)
173186
end
174187

175188
-- Run Python to generate an image:

0 commit comments

Comments
 (0)