There are different ways out there to create slides for talks. One used a lot in academia is LaTeX Beamer. For the unknowing, in short, Beamer allows to generate PDF slides by relying on the comprehensive typesetting greatness of LaTeX.

Compared to WYSIWYG tools like Powerpoint and Keynote, LaTeX Beamer has a high getting-started threshold of learning the keywords and peculiarities, which is inherent to all things LaTeX. This makes it unappealing for beginners, but also somewhat reduces productivity for experienced users.
But fear not! There’s a well-working converter from the great markup language Markdown to LaTeX Beamer slides. And this is how it works.

TL;DR: Pandoc can convert Markdown to PDF slides using LaTeX Beamer. It works out of the box, but can easily be extended. Apart from LaTeX Beamer, also HTML slideshows using reveal.js (and others) are possible from the same source file.

Pandoc

Pandoc allows for conversion between different markup languages. It can convert between docx, HTML, LaTeX, and Markdown. Especially the latter two are quite interesting; using Pandoc, you can write texts in the highly productive language of Markdown but have it set to PDF using the capabilities of LaTeX.1 Try out the capabilities of Pandoc yourself on pandoc.org/try/.

From

# Headline 1
**This** is a *text*.

Pandoc generates

\section{Headline 1}\label{headline-1}
\textbf{This} is a \emph{text}.

and will add the corresponding headers if you add the standalone option (--standalone) to the pandoc command line call.

The really cool thing? Pandoc also supports LaTeX Beamer. The above snippet would be set to one Beamer slide:

\begin{frame}{Headline 1}
\textbf{This} is a \emph{text}.
\end{frame}

Easy! Pandoc also supports converting the Markdown-written slides to other targets, like HTML presentations using reveal.js and others. Since I was not able to convert the presentation template of my institute to a reveal.js template I have not really dug too much into this.2

Options and Features

A very concise example of the conversion abilities can be found at the Pandoc demo page. From input to output.

Basic LaTeX Beamer Support

The full support for LaTeX and LaTeX Beamer from Pandoc is outlined in its documentation. Here are some basics.

Pandoc can use each first-level headline to create a new slide with the headline as the slide’s title. This is a harsh over-simplification, see the footnote.3 Also, horizontal rules (-----) start new slides.

Lists, ordered and unordered, are taken from their Markdown format (* Something and 1. Anything) to their respective LaTeX commands (itemize and enumerate).

Also pictures can be included (Markdown syntax: ![A nice picture](img/nice.pdf)).4

List items can appear by prepending the list item with a > (i.e. > * Something), pauses can be added on a slide by three one-space-interleaved dots (. . .).

To put a Beamer slide into one of the special modes, different attributes can be used. For instance, using # Title {.fragile} will lead to \begin{frame}[fragile]{Title}, the mode needed for code highlighting e.g. with minted.

YAML

Through commented keywords at the beginning of the Markdown file, global parameters of the presentation can be set. The keywords are written in a YAML metadata manner.

For example, variables like author, title (and subtitle), and date of the presentation can be set:

---
author: Ch. Darwin
title: On the Origin of Species
date: 24.11.1859
---

At the same place, Beamer themes can be chosen (using theme, et al.). Also, further LaTeX options can be specified (fontfamily, toc, …) and features of the (Beamer) document enabled, like using BibLaTeX (biblatex: true)5 or proper tables with booktabs (tables: true).
Behind the curtains, the YAML variables are passed through to the template used for conversion where they can be used as triggers or options.

A very handy keyword in the YAML metadata is header-includes, which allows injecting LaTeX code into the header. Useful for including certain packages or even whole .tex files with display configurations:6

header-includes: 
    - \input{_header}
    - \usepackage{siunitx}
    - \DeclareSIUnit[number-unit-product = {}]{\flops}{FLOPS}

Additionally to the header-includes YAML, there are also include-before and include-after. They inject something right at the beginning and just before the end of the content body of the document, respectively.

Easy & Out of the Box: Markdown → PDF with Pandoc

The easiest way to get your Markdown slides set in LaTeX Beamer PDF is with the following line

pandoc --to=beamer --output=slides.pdf slides.md

Some Options

Say, you like to change the font of your presentation? Easy! Just add the following to the YAML

header-includes:
    - \setsansfont{Roboto}

and tell Pandoc to use the XeLaTeX engine with pandoc --to=beamer -o slides.pdf slides.md --latex-engine=xelatex.7

You have a package which uses shell commands via the --shell-escape mechanism? Just append --latex-engine-opt=-shell-escape to the command.

There’s a lot more trickery which can be done. Just have a look at man pandoc.

Comprehensive & Flexible: Markdown → LaTeX → PDF with Pandoc and pdflatex / latexmk

Although super sleek, I encountered one problem with the immediate conversion from Markdown to PDF: I couldn’t use a certain package (minted). So I split up the process: Use Pandoc to generate a .tex file from the Markdown input and use a usual means of typesetting8 to finalize the processing to a PDF.

With a small wrapper script you don’t even feel a difference but have the added flexibility of configuring the pdflatex call directly.

Temp Files Problem

So, minted. minted is, in my mind, the best code highlighting package for LaTeX out there. As a backend, it uses the Python program Pygments to generate colored code snippets.

To do so, it needs to escape to the shell. No problem, you say, haven’t I just introduced latex-engine-opts=-shell-escape? True! But minted creates temporary files in the document’s root directory. And because Pandoc happily copies the automatically generated .tex file to some randomly chosen temporary location and changes the -output-directory value of pdflatex, the document’s root directory can not be found. minted offers the outputdir=<directory> package option, but there is no way to predict where Pandoc will copy the the temporary files to. At least to my knowledge.

After a short discussion with the minted people, I split up the process of PDF slide generation.

Two-Step Process

Essentially, the two needed commands are

pandoc --to=beamer --standalone --output=slides.tex slides.md
latexmk -pdf slides.tex

Or pdflatex slides.tex if you rather use that program. But, remember, you can configure a lot in latexmk with the .latexmkrc file. Here’s mine.

If you combine the two calls into one script, you don’t even feel the difference. As an example: My run.py file which has also a few additional options.

Custom Template

One more thing before we are done: I modified the default beamer template9 of Pandoc to include an institute, since that’s one of Beamer’s default macros. Just add

$if(institute)$
\institute{$institute$}
$endif$

somewhere after the if clause of $if(author)$. Use it with a instute: My University in the YAML part of your presentation. An alternative to changing the template would be to put it into the header-includes command.

Recap

LaTeX Beamer enables programmatically writing slides with LaTeX, creating a PDF file as output. Pandoc can convert the easy Markdown markup language to Beamer slides with one simple command. If you make two commands out of the one, you are more flexible in typesetting. Pandoc’s conversion engine can be configured by some statements in the top of the file. Pack all your LaTeX customization in one .tex file and include it via header-includes.

  1. In fact, this blog is also written entirely in Markdown. 

  2. The problem with a FZJ reveal.js template is somewhat reveal.js-conceptual: Our design has very distinctly designed borders, for example a colorful bar at the very left of each slide. I was not able to implement this to a reveal.js, looking both correct (and well) in the usual presentation mode, but also in the PDF print mode at the same time. The latter is important since most scientific conferences expect talks in a static PDF format, not a fancy HTML file. I would gladly appreciate a port of the FZJ presentation template to any form of JavaScript-based presentation engines! 

  3. Pandoc uses that headline level as a slide separator which is, throughout the whole document, only followed directly by text and no other (lower level) headline.

    Like this, the document can be structured a bit more into sections aside from slides: Headers, above the slide-seperator headline level are used to create title slides. In general, --slide-level can be used to manually override the behavior. See the documentation

  4. Up to now, I fell back on using \includgraphics{} directly in the Markdown code since the ability to specify image dimensions in Markdown was only a very recent addition to the Pandoc parser.

    Now, one can specify for example the width of an image like this: ![A nice picture](img/nice.pdf){ width=90% }, which will be converted to \includegraphics[width=0.9\textwidth]{img/nice.pdf}. Before, it was using the full width of the slide, which was not working properly for the template I’m using. 

  5. If you can use BibLaTeX, you should use BibLaTeX. Always. It’s far superior than BibTeX, more modern, and has a much greater feature set. It’s also quite backwards compatible, you can transition smoothly on your own time. 

  6. In my example here, you can use the file _header.tex to include further LaTeX code you don’t want to clutter the Markdown file with. Like your favorite font package, some \hypersetup{} commands, or your default set of packages. See remarks on how I use it a bit later in this posting. 

  7. Finally! You can set those beautiful Beamer slides with your favorite font, Comic Sans MS! 

  8. Just advertising it here quickly: Please use latexmk as your Makefile-esk interface to pdflatex (or XeLaTeX, or LuaLaTeX, or …)! It will help you out a lot! It will automatically detect how many runs are necessary until your document is stable; it can be steered using a .latexmkrc file; and it has a great continuous preview mode, which compiles your document automatically once it’s changed and opens a previewer afterwards: latexmk -pdf -pvc document.tex

  9. Also, I needed to exchange \frame{\titlepage} with \maketitle, because my template wants it this way.