1

Recently, I have been having some issues with TikZ in LaTeX. I want to convert my PhD dissertation, written in LaTeX, to .docx using pandoc. I am able to use lua filters to have pandoc convert TikZ images, thanks to help here.

However, a small problems remains. In the .docx file, the TikZ images are not centered. Nor are my captions included: it seems like pandoc simply ignores \begin{figure} whereafter I have included these commands.

Question

How to give a caption to and how to center TikZ figures in a .docx file converted with pandoc?

I am probably looking right over the solution, but as I am inexperienced with programming I do not know how to fix this.

Here is my .tex file:

\documentclass[a4paper,12pt]{book}
\usepackage{graphicx}
\usepackage[english]{babel}

\usepackage{tikz}

\begin{document}

\begin{figure}

\centering

\begin{tikzpicture}

         \draw circle(5cm);

\end{tikzpicture}

\caption{Admire my circle!}

\end{figure}

\end{document}

Here is my .lua file, taken from here, which functions as a filter:

local function file_exists(name)
  local f = io.open(name, 'r')
  if f ~= nil then io.close(f); return true
  else return false end
end

--- Create a standalone LaTeX document which contains only the TikZ picture. --- Convert to png via Imagemagick. local function tikz2image(src, outfile) local tmp = os.tmpname() local tmpdir = string.match(tmp, "^(.*[\/])") or "." -- local tmpdir = "." local f = io.open(tmp .. ".tex", 'w') f:write("\documentclass{standalone}\n") -- include all packages needed to compile your images f:write("\usepackage{tikz}\n\usepackage{stanli}\n\usetikzlibrary{arrows.meta,positioning}\n") f:write("\begin{document}\n") f:write(src) f:write("\n\end{document}\n") f:close() os.execute("pdflatex -output-directory " .. tmpdir .. " " .. tmp) -- os.execute("convert " .. tmp .. ".pdf " .. "-colorspace RGB " .. outfile) os.execute("pdftoppm -png " .. tmp .. ".pdf " .. "> " .. outfile) os.remove(tmp .. ".tex") os.remove(tmp .. ".pdf") os.remove(tmp .. ".log") os.remove(tmp .. ".aux") end

function RawBlock(el) -- Don't alter element if it's not a tikzpicture environment if not el.text:match'^\begin{tikzpicture}' then return nil -- Alternatively, parse the contained LaTeX now: -- return pandoc.read(el.text, 'latex').blocks end
local fname = pandoc.sha1(el.text) .. ".png" if not file_exists(fname) then tikz2image(el.text, fname) end return pandoc.Para({pandoc.Image({}, fname)}) end

Here is the command I enter in the terminal:

pandoc -s --from latex+raw_tex --lua-filter=tikz.lua test.tex -o test.docx
Boreq
  • 103
  • 1
    If you are trying to convert a large project, that includes many elements that are not represented in pandoc's AST, you will run into many problems. Maybe it's easier to use another tool, I'd suggest tex4ht: http://www.tug.org/tex4ht/ – DG' Oct 27 '20 at 09:47

2 Answers2

2

I have done something similar, starting from the example at pandoc.org/lua-filters.html#building-images-with-tikz.

The main thing is that the filter looks for a raw LaTeX block that starts with '\begin{tikzpicture}', and your blocks start with '\begin{figure}'. You can replace the former with the latter.

I then modified the 'tikz_doc_template' for my use.

Here is the filter that I use: gitlab.com/twsh/pandoc-lua-filters/-/blob/master/tikz-qtree.lua

--[[ Turn figure environments into SVG images
Links are relative
Only one tikzpicture per block
If there is a \caption{...}, set the title text to ...;
pandoc will turn this into a <figcaption> for HTML.
It is assumed that the caption finishes at a line break ]]

local system = require 'pandoc.system'

local tikz_doc_template = [[ \documentclass{standalone} \usepackage{lmodern} \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage{tikz-qtree} \usepackage{amsmath} \begin{document} %s \end{document} ]]

local function tikz2image(src, outfile) system.with_temporary_directory( 'tikz2image', function(tmpdir) system.with_working_directory( tmpdir, function() local f = io.open('tikz.tex', 'w') f:write(tikz_doc_template:format(src)) f:close() os.execute('pdflatex tikz.tex') os.execute('pdf2svg tikz.pdf ' .. outfile) end ) end ) end

local function file_exists(name) local f = io.open(name, 'r') if f ~= nil then io.close(f) return true else return false end end

function RawBlock(el) tikz = el.text:match('\begin{tikzpicture}(.+)\end{tikzpicture}') if tikz then local fname = pandoc.sha1(tikz) .. '.' .. 'svg' local fpath = system.get_working_directory() .. '/' .. fname if not file_exists(fpath) then tikz2image(tikz, fpath) end local caption = el.text:match('\caption{(.+)}\n') if caption then local caption_text = pandoc.utils.stringify(pandoc.read(caption, 'latex').blocks) return pandoc.Para({pandoc.Image({pandoc.Str(caption_text)}, fname, 'fig:')}) else return pandoc.Para({pandoc.Image({}, fname, 'fig:')}) end else return el end end

twsh
  • 2,718
0

As a serial lurker, I don't have the reputation to comment. Sorry about that.

Image Magick seems to have updated their command from "Convert" to just "Magick" in version 7 and above (https://imagemagick.org/script/command-line-tools.php). Making that edit caused this too work for me with the Image Magick route.

MarcG
  • 1