Using ConTeXt to convert markdown to PDF

I am using markdown to write the course notes for a lecture that I am teaching this semester. The notes have no math—just text and images—and markdown is the ideal input format. At the same time, I am easily convert a markdown file to a nicely typeset pdf using pandoc—with the ConTeXt filter module providing the plumbing.

However, it took me a while to come up with a work flow that I like. Normally, to use the filter module I have to create a tex file that that converts and inputs the appropriate markdown file; something like:

% file: 01-intro.tex
% Boilerplate code to typeset a markdown file

\environment ECSE321
% ECSE321.tex is the environment file that
% sets up the layout, fonts, and style. It
% also loads the filter module and sets up
% a |markdown| external filter environment.

\starttext
\processmarkdownfile{01-intro.txt}
% This command converts 01-intro.txt into a
% tex file and inputs the result
\stoptext

However, such a setup gets frustrating very quickly. For each lecture, I need to create two files: a markdown file (like 01-intro.txt) and a tex file with boilerplate code (like 01-intro.tex above). I might be able to get rid of the boilerplate tex file by writing a script that creates the file—adding needless complexity to a simple task. Wouldn’t it be nice if I could just say

context <magic options> 01-intro.txt

That is, compile the markdown file directly. After thinking about it for a while, I realized that this task was simple. I just needed to load the environment file and ask it to run \processmarkdownfile on the current input file. ConTeXt provides a switch --enironment=filename to specify an environment file; the macro \inputfilename contains the name of the input file (\jobname contains the name without extension. \inputfilename contains the name with extension). So, I just needed to add

\processmarkdownfile{\inputfilename}

at the appropriate place in the environment file. So, I modified the environment file as follows:

% file ECSE321.tex
\startenvironment ECSE321

% Setups for fonts, layout, and styles

\usemodule[filter]

\defineexternalfilter
[markdown]
[filtercommand={pandoc -f \externalfilterparameter{format} -t context
-i \externalfilterinputfile\space
-o \externalfilteroutputfile},
format=markdown,
directory=output]

\stopenvironment

\doifnotmode{standalone}{\endinput}
\starttext
\processmarkdownfile{\inputfilename}
\stoptext

If the standalone mode is not set, ConTeXt stops reading the environment file after \stopenvironment. If the mode is set, it processes the input file as a markdown file. So, I can invoke ConTeXt using

context --environment=ECSE321 --mode=standalone 01-intro.txt

to directly compile a markdown file to pdf. To simplify this process, I added

alias lec='context --environment=ECSE321 --mode=standalone'

in my .zshrc file and now I am happily compiling my lecture notes using

lec 01-intro.txt

5 thoughts on “Using ConTeXt to convert markdown to PDF”

1. Great. Does pandoc provide a syntax for literal ConTeXt snippets for, e.g. lua or TikZ?

• Pandoc passes everything inside a context environment \start<whatever>\stop<whatever> unchanged. So, the contents of \startluacode ... \stopluacode and \starttikzcode .. \stoptikzcode are not touched. If you want more control, you can write stuff inside \startCONTEXT ... \stopCONTEXT environment, and add \let\startCONTEXT\donothing and \let\stopCONTEXT\donothing in your style file.

2. While this looks extremely cool, I cannot get it to work with the latest context. Context seems to insist on processing the markdown file.

I *can* get it to work in the original, “quickly frustrating” way, but as you point out, you end up with a lot of files that do very little.

(My application is monthly progress reports for a project, and I’m using markdown so that I have both the PDF sent in to the client, and an easy way to render a web page or even a .doc file down the road)

• Now ConTeXt stops reading the current file when it encounters a \stopenvironment. So, you need to use

\doifnotmode{standalone}{\stopenvironment}