diff options
Diffstat (limited to 'paper/lua-filters/diagram-generator/diagram-generator.lua')
-rw-r--r-- | paper/lua-filters/diagram-generator/diagram-generator.lua | 295 |
1 files changed, 0 insertions, 295 deletions
diff --git a/paper/lua-filters/diagram-generator/diagram-generator.lua b/paper/lua-filters/diagram-generator/diagram-generator.lua deleted file mode 100644 index aef2ea4..0000000 --- a/paper/lua-filters/diagram-generator/diagram-generator.lua +++ /dev/null @@ -1,295 +0,0 @@ ---[[ - This Lua filter is used to create images with or without captions from - code blocks. Currently PlantUML, GraphViz, Tikz, and Python can be - processed. For further details, see README.md. - - Thanks to @floriandd2ba and @jgm for the initial implementation of - the PlantUML filter, which I used as a template. Thanks also @muxueqz - for the code to generate a GraphViz image. -]] - --- The PlantUML path. If set, uses the environment variable PLANTUML or the --- value "plantuml.jar" (local PlantUML version). In order to define a --- PlantUML version per pandoc document, use the meta data to define the key --- "plantumlPath". -local plantumlPath = os.getenv("PLANTUML") or "plantuml.jar" - --- The Inkscape path. In order to define an Inkscape version per pandoc --- document, use the meta data to define the key "inkscapePath". -local inkscapePath = os.getenv("INKSCAPE") or "inkscape" - --- The Python path. In order to define a Python version per pandoc document, --- use the meta data to define the key "pythonPath". -local pythonPath = os.getenv("PYTHON") - --- The Python environment's activate script. Can be set on a per document --- basis by using the meta data key "activatePythonPath". -local pythonActivatePath = os.getenv("PYTHON_ACTIVATE") - --- The Java path. In order to define a Java version per pandoc document, --- use the meta data to define the key "javaPath". -local javaPath = os.getenv("JAVA_HOME") -if javaPath then - javaPath = javaPath .. package.config:sub(1,1) .. "bin" - .. package.config:sub(1,1) .. "java" -else - javaPath = "java" -end - --- The dot (Graphviz) path. In order to define a dot version per pandoc --- document, use the meta data to define the key "dotPath". -local dotPath = os.getenv("DOT") or "dot" - --- The pdflatex path. In order to define a pdflatex version per pandoc --- document, use the meta data to define the key "pdflatexPath". -local pdflatexPath = os.getenv("PDFLATEX") or "pdflatex" - --- The default format is SVG i.e. vector graphics: -local filetype = "svg" -local mimetype = "image/svg+xml" - --- Check for output formats that potentially cannot use SVG --- vector graphics. In these cases, we use a different format --- such as PNG: -if FORMAT == "docx" then - filetype = "png" - mimetype = "image/png" -elseif FORMAT == "pptx" then - filetype = "png" - mimetype = "image/png" -elseif FORMAT == "rtf" then - filetype = "png" - mimetype = "image/png" -end - --- Execute the meta data table to determine the paths. This function --- must be called first to get the desired path. If one of these --- meta options was set, it gets used instead of the corresponding --- environment variable: -function Meta(meta) - plantumlPath = meta.plantumlPath or plantumlPath - inkscapePath = meta.inkscapePath or inkscapePath - pythonPath = meta.pythonPath or pythonPath - pythonActivatePath = meta.activatePythonPath or pythonActivatePath - javaPath = meta.javaPath or javaPath - dotPath = meta.dotPath or dotPath - pdflatexPath = meta.pdflatexPath or pdflatexPath -end - --- Call plantuml.jar with some parameters (cf. PlantUML help): -local function plantuml(puml, filetype) - local final = pandoc.pipe(javaPath, {"-jar", plantumlPath, "-t" .. filetype, "-pipe", "-charset", "UTF8"}, puml) - return final -end - --- Call dot (GraphViz) in order to generate the image --- (thanks @muxueqz for this code): -local function graphviz(code, filetype) - local final = pandoc.pipe(dotPath, {"-T" .. filetype}, code) - return final -end - --- Compile LaTeX with Tikz code to an image: -local function tikz2image(src, filetype, additionalPackages) - - -- Define file names: - local outfile = string.format("./tmp-latex/file.%s", filetype) - local tmp = "./tmp-latex/file" - local tmpDir = "./tmp-latex/" - - -- Ensure, that the tmp directory exists: - os.execute("mkdir -p tmp-latex") - - -- Build and write the LaTeX document: - local f = io.open(tmp .. ".tex", 'w') - f:write("\\documentclass{standalone}\n\\usepackage{tikz}\n") - - -- Any additional package(s) are desired? - if additionalPackages then - f:write(additionalPackages) - end - - f:write("\\begin{document}\n") - f:write(src) - f:write("\n\\end{document}\n") - f:close() - - -- Execute the LaTeX compiler: - pandoc.pipe(pdflatexPath, {'-output-directory', tmpDir, tmp}, '') - - -- Build the basic Inkscape command for the conversion: - local baseCommand = " --without-gui --file=" .. tmp .. ".pdf" - local knownFormat = false - - if filetype == "png" then - - -- Append the subcommands to convert into a PNG file: - baseCommand = baseCommand .. " --export-png=" - .. tmp .. ".png --export-dpi=300" - knownFormat = true - - elseif filetype == "svg" then - - -- Append the subcommands to convert into a SVG file: - baseCommand = baseCommand .. " --export-plain-svg=" .. tmp .. ".svg" - knownFormat = true - - end - - -- Unfortunately, continuation is only possible, if we know the actual - -- format: - local imgData = nil - if knownFormat then - - -- We know the desired format. Thus, execute Inkscape: - os.execute("\"" .. inkscapePath .. "\"" .. baseCommand) - - -- Try to open the image: - local r = io.open(tmp .. "." .. filetype, 'rb') - - -- Read the image, if available: - if r then - imgData = r:read("*all") - r:close() - end - - -- Delete the image tmp file: - os.remove(outfile) - end - - -- Remove the temporary files: - os.remove(tmp .. ".tex") - os.remove(tmp .. ".pdf") - os.remove(tmp .. ".log") - os.remove(tmp .. ".aux") - - return imgData -end - --- Run Python to generate an image: -local function py2image(code, filetype) - - -- Define the temp files: - local outfile = string.format('%s.%s', os.tmpname(), filetype) - local pyfile = os.tmpname() - - -- Replace the desired destination's file type in the Python code: - local extendedCode = string.gsub(code, "%$FORMAT%$", filetype) - - -- Replace the desired destination's path in the Python code: - extendedCode = string.gsub(extendedCode, "%$DESTINATION%$", outfile) - - -- Write the Python code: - local f = io.open(pyfile, 'w') - f:write(extendedCode) - f:close() - - -- Execute Python in the desired environment: - local pycmd = pythonPath .. ' ' .. pyfile - local command = pythonActivatePath - and pythonActivatePath .. ' && ' .. pycmd - or pycmd - os.execute(command) - - -- Try to open the written image: - local r = io.open(outfile, 'rb') - local imgData = nil - - -- When the image exist, read it: - if r then - imgData = r:read("*all") - r:close() - else - io.stderr:write(string.format("File '%s' could not be opened", outfile)) - end - - -- Delete the tmp files: - os.remove(pyfile) - os.remove(outfile) - - return imgData -end - --- Executes each document's code block to find matching code blocks: -function CodeBlock(block) - - -- Predefine a potential image: - local fname = nil - - -- Using a table with all known generators i.e. converters: - local converters = { - plantuml = plantuml, - graphviz = graphviz, - tikz = tikz2image, - py2image = py2image, - } - - -- Check if a converter exists for this block. If not, return the block - -- unchanged. - local img_converter = converters[block.classes[1]] - if not img_converter then - return nil - end - - -- Call the correct converter which belongs to the used class: - local success, img = pcall(img_converter, block.text, - filetype, block.attributes["additionalPackages"] or nil) - - -- Was ok? - if success and img then - -- Hash the figure name and content: - fname = pandoc.sha1(img) .. "." .. filetype - - -- Store the data in the media bag: - pandoc.mediabag.insert(fname, mimetype, img) - - else - - -- an error occured; img contains the error message - io.stderr:write(tostring(img)) - io.stderr:write('\n') - - end - - -- Case: This code block was an image e.g. PlantUML or dot/Graphviz, etc.: - if fname then - - -- Define the default caption: - local caption = {} - local enableCaption = nil - - -- If the user defines a caption, use it: - if block.attributes["caption"] then - caption = pandoc.read(block.attributes.caption).blocks[1].content - - -- This is pandoc's current hack to enforce a caption: - enableCaption = "fig:" - end - - -- Create a new image for the document's structure. Attach the user's - -- caption. Also use a hack (fig:) to enforce pandoc to create a - -- figure i.e. attach a caption to the image. - local imgObj = pandoc.Image(caption, fname, enableCaption) - - -- Now, transfer the attribute "name" from the code block to the new - -- image block. It might gets used by the figure numbering lua filter. - -- If the figure numbering gets not used, this additional attribute - -- gets ignored as well. - if block.attributes["name"] then - imgObj.attributes["name"] = block.attributes["name"] - end - - -- Finally, put the image inside an empty paragraph. By returning the - -- resulting paragraph object, the source code block gets replaced by - -- the image: - return pandoc.Para{ imgObj } - end -end - --- Normally, pandoc will run the function in the built-in order Inlines -> --- Blocks -> Meta -> Pandoc. We instead want Meta -> Blocks. Thus, we must --- define our custom order: -return { - {Meta = Meta}, - {CodeBlock = CodeBlock}, -} |