In general, I like to write my pandoc documents as close to the canonical format as possible and let LaTeX deal with positioning figures. It works pretty well, and it’s infinitely more straightforward than doing it in Word. However, LaTeX doesn’t natively wrap text around figures, and sometimes you really need to maximize the use of space. In pure LaTeX, this can be done with the wrapfig package. In pandoc, this package can be used through a template, but it’s a little tricky if you don’t want every figure treated the same way.
I recently wanted to start using pandoc in writing proposals, some of which have hard page limits. I didn’t come across a solution online, and so I worked out a simple little filter, pandoc-wrapfig, that integrates pandoc and the wrapfig package together:
#! /usr/bin/env python3 # -*- coding: utf-8 -*- """Pandoc filter to allow variable wrapping of LaTeX/pdf documents through the wrapfig package. Simply add a " {?}" tag to the end of the caption for the figure, where ? is an integer specifying the width of the wrap in inches. 0 will cause the width of the figure to be used. """ from pandocfilters import toJSONFilter, Image, RawInline, stringify import re FLAG_PAT = re.compile('.*\{(\d+\.?\d?)\}') def wrapfig(key, val, fmt, meta): if key == 'Image': attrs, caption, target = val if FLAG_PAT.match(stringify(caption)): # Strip tag size = FLAG_PAT.match(caption[-1]['c']).group(1) stripped_caption = caption[:-2] if fmt == 'latex': latex_begin = r'\begin{wrapfigure}{r}{' + size + 'in}' if len(stripped_caption) > 0: latex_fig = r'\centering\includegraphics{' + target[0] \ + '}\caption{' latex_end = r'}\end{wrapfigure}' return [RawInline(fmt, latex_begin + latex_fig)] \ + stripped_caption + [RawInline(fmt, latex_end)] else: latex_fig = r'\centering\includegraphics{' + target[0] \ + '}' latex_end = r'\end{wrapfigure}' return [RawInline(fmt, latex_begin + latex_fig)] \ + [RawInline(fmt, latex_end)] else: return Image(attrs, stripped_caption, target) if __name__ == '__main__': toJSONFilter(wrapfig)
The usage of this filter is quite simple: It’s triggered by ending the caption with “{x}”, where x is a number that specifies the width in inches; if x = 0, the text is wrapped to the width of the figure. I’ve set it to align all figures to the right margin; that could easily be changed in the filter (or it could be further modified to enable additional control). Of course, the pdf template must load the wrapfig package. If pandoc is used to generate something other than a pdf, the filter just removes the tag (handy for using Marked).
Here’s a quick example:
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ![Figure Caption. {0}](testfig) Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ![Figure Caption.](testfig) Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
The first figure is wrapped to its width, as you’d expect. The second, which lacks the “{x}” tag, is ignored by the filter and inserted without wrapping (useful if the figure is too wide to make enough room for text). Here’s the output using the little modified template I included in the Github package:
Honestly, it’s not seamless. There’s a certain amount of tweaking that one must do to get all the figures into the right positions: they can’t be too close together, nor can they be too close to the end of a page. However, in the end it works well for the right project.