Cross-referencing in Pandoc and Markdown with xnos

We have been learning about Markdown and how it can be used for various academic and scientific writing tasks. In this post, we will learn how to cross-reference in our documents.

What is cross-referencing?

If you are not familiar with cross-referencing, it is a way to refer to various things in your document, such as figures, tables, sections and equations. This is very useful in papers, when we want to refer to our figures, tables and equations. It is also useful in books, study notes, class notes, and theses, when we want to refer to sections in our document.

While you could do this yourself by typing in the number of the figure, for example. But what would happen if we changed the order of the figures in our document at the last minute? By using cross-referencing, we let our computer keep track of all these details.

pandoc-crossref vs pandoc-xnos

In the Extra section of the official Pandoc documentation, there are two options for cross-referencing.

Most blog-posts and books talk about pandoc-crossref, a Pandoc filter written in Haskell, the same programming language that Pandoc is written in. Personally, I have had trouble installing pandoc-crossref, and when I finally got it installed, Pandoc would not recognise it (despite being very careful about ensuring they were both the lastest version).

The other option is pandoc-xnos. It is a Pandoc filter written in Python. More accurately, it is a series of filters for tables, figures, equations, and sections. I was a bit skeptical, but pandoc-xnos was easy to install and worked as advertised. Therefore, we will be focusing on pandoc-xnos in the present post.

Installing pandoc-xnos

We need to have Python installed on our computer in order to use the pandoc-xnos filter. Then, we can use pip to install it:

$ pip install pandoc-fignos pandoc-eqnos pandoc-tablenos pandoc-secnos --user --upgrade

Cross-references with pandoc-xnos

In this post we will focus on the basics of cross-referencing and pandoc-xnos. pandoc-xnos has some nice tweaks that are nice to be aware of, so make sure you visit the GitHub repo of each of the four filters (follow the links on this page).

Each type of cross-reference creates a label with a specific prefix, which can be followed by additional text to mark the item that is being labelled. Then, you can make a cross-reference to these items with a slightly different syntax.

First, let’s show some examples of how to create labels for sections, tables, figures and equations:

## Results {#sec:results}

Here are my results. I computed them with this formula:

$$ y = mx + b $$ {#eq:line}

I have plotted them in this figure:

![Amazing results of a line.](img/line.png){#fig:line}

I have also listed some of the points on this line in the following table:

| X | Y |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |

Table: Results related to my line. {#tbl:line}

As we can see, the prefix to the four label types are #sec:, #eq:, #fig:, and #tbl:. Then, immediately after the semi-colon, we can provide an informative name or identifier to the label.

We can then refer to these labels in our document to add a cross-reference.

For example:

That was truly amazing.
In Section @sec:result, we saw all there was to see about lines.
First, in Equation @eq:line, we saw the deep Maths behind a line.
Second, we saw the most beautiful depiction of a line (Figure @fig:line).
Third, Table @tbl:line presented us, in all their glory, 
points to a line.

One of the things that you can specify in pandoc-xnos is the text that preceeds the cross-reference. So, rather than typing ‘Figure’ before each cross-reference, you could have it appear automatically, and in your preferred format (e.g. ‘Figure’ or ‘Fig.’).

Calling the pandoc-xnos filter

Great, we now have a document with labels and cross-references. The next thing we need to do is generate our document. Pandoc allows various filters to be used. Filters are little programs that run as Pandoc is processing our document. Behind the scenes, pandoc-xnos is converting our labels and cross-references to LaTeX labels and references.

Thus, with pandoc-xnos already installed on our computer (and Python as well), we can add --filter pandoc-xnos to our command line call to Pandoc.

For the example document above, I used the following command:

$ pandoc --number-sections --filter pandoc-xnos --variable urlcolor=red -o line.pdf

The following document was generated:

An important thing to note is that, given the syntax used to make cross-references (i.e. using the @ symbol), it is essential that the pandoc-xnos filter be called before the citeproc filter. Citeproc uses the @ symbol to insert citations; thus, it woulc get confused if it came across things like @eq:line and @fig:line.


In this post we learned how to expand Markdown and Pandoc to allow cross-references. This was done using the pandoc-xnos filter, a series of Python programs that manipulate our file as our file is being processed by Pandoc.

One comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s