Panbuild is a make-like builder for
pandoc. It is a command-line tool that aims to simplify the construction of multiple output documents (in different formats, such as PDF, DOCX, EPUB, etc.) from a given source document (e.g. one or several Markdown files).
Panbuild relies on YAML code -typically included in a separate build file- to specify the various options that must be passed to
pandoc for the different output formats. This removes the need for repeatedly typing possibly long and complex pandoc commands for each and every target output format. At the same time, this tool greatly simplifies the integration of Pandoc with extensible text editors, by preventing the user from typing commands in a terminal window to fully access all Pandoc features. Panbuild's plugin for the Sublime Text editor constitutes a good example of such a seamless interaction with Pandoc through
To use Panbuild, you must install Pandoc on your system. It is also highly recommended to update your PATH to include the directory where pandoc's binaries were installed (Pandoc's installer typically takes care of that).
Binary installation (Windows and Mac OS X only)
In the Panbuild's download page you can find a ZIP file containing executable files for Windows and Mac OS X. For the installation, just extract the
panbuild executable file from the ZIP archive and place it in any directory included in the PATH (e.g. the directory where
pandoc.exe or the
pandoc executable was installed on your system).
Installation from source
panbuild from source requires Python, a programming language whose interpreter comes pre-installed on Linux and Mac OS X, and which can be easily installed on Windows. Panbuild works with both Python v2.7 and v3.x.
The installation also requires
pip, a program that downloads and installs modules from the Python Package Index (PyPI) or from a specified URL. On Mac OS X, it typically comes installed with your Python distribution. On Windows, make sure you choose to install
pip during the installation of Python (latest Python installers provide such an option). On a Debian-based system (including Ubuntu), you can install
pip (as root) as follows:
apt-get install python-pip
There are basically two ways to install Panbuild from source: with and without
This approach is straightforward and perhaps more suitable for Linux and Mac OS X, where the
git command can be easily installed. In following this approach you can install
panbuild by using the following command as root:
pip install git+https://github.com/jcsaezal/panbuild
To upgrade to the most recent release, proceed as follows:
pip install --upgrade git+https://github.com/jcsaezal/panbuild
If the one-command installation shown above does not work (i.e.
git is not installed on your system) you can follow this two-step process:
Download a copy of the repository in ZIP format and extract it in a temporary folder on your computer.
panbuildon your system by running
pip install <full_path_of_your_temporary_folder>
panbuild command must be executed from the directory that contains the source code of your document (e.g. collection of Markdown files). When running
panbuild without arguments it will try to open a build.yaml file located on the current working directory. If the build file was not found, an error message will be displayed:
$ panbuild [Errno 2] No such file or directory: 'build.yaml'
Otherwise, Panbuild will retrieve the targets found in the build file (one for each target document we want to generate) as well as the pandoc commands required to build those targets. Once this is done, it will invoke these commands sequentially, as in the following example, where three targets were found in the build file:
$ panbuild Building target PDF ...Success Building target HTML ...Success Building target EPUB ...Success
Information is provided below on how to create a build.yaml file. To tell Panbuild to use another build file different from the default one (build.yaml), the
-f option must be specified, which accepts an argument with the name of the actual build file to use.
We can also ask Panbuild to build specific targets of the build file, rather than all of them. We can do that by passing the name of each target in the command line as program arguments separated by a space. For example, to build the "PDF" target only, we should invoke the program as follows:
$ panbuild PDF Building target PDF ...Success
Note also that Panbuild recognizes an implicit
clean target (not defined in the build file) which will delete the files associated with each target:
$ panbuild clean Removing file out.pdf Removing file out.html Removing file out.epub
Another interesting option of the Panbuild program is
-L, which allows us to obtain a list of the targets found in the build file:
$ panbuild -L PDF HTML EPUB
To obtain more information about the various command-line options supported by
panbuild, just use the
$ panbuild -h usage: panbuild [-h] [-f BUILD_FILE] [-L] [-o] [-v] [-d PANDOC_DIR] [-S PANDOC_OPTIONS] [-y] [TARGETS [TARGETS ...]] Panbuild, a YAML-based builder for Pandoc positional arguments: TARGETS a target name (must be defined in the build file) optional arguments: -h, --help show this help message and exit -f BUILD_FILE, --build-file BUILD_FILE Indicates which file contains the build rules. If omitted, panbuild searches for rules in "build.yaml" -L, --list-targets List targets found in build file -o, --list-output List the name of the output file for each target -v, --verbose Enable verbose mode -d PANDOC_DIR, --pandoc-dir PANDOC_DIR Used to point to pandoc executable's directory, in the event it is not in the PATH -S PANDOC_OPTIONS, --sample-build-file PANDOC_OPTIONS Print a sample build file for the pandoc options passed as a parameter. Format PANDOC_OPTIONS ::= '[list-input-files] REST_OF_OPTIONS' -y, --use-yaml-options Show options in YAML format when generating sample build file
To understand the motivation behind Panbuild, let us consider an illustrative example. Suppose that we want to create a report consisting of three chapters that we will distribute through a website in various formats. To write that report, we use the Markdown language, which makes it possible to maintain a simple source code for our document, and which can be easily transformed into multiple document formats -such as PDF or HTML- thanks to Pandoc. Suppose further that the Markdown source code our report has the following features:
- The content of each chapter in the report is written in a separate Markdown file, thus making maintenance more manageable. Therefore, in building the final document (e.g., PDF) with Pandoc, we must indicate the name of each input file in the command line, in the same order in which the corresponding chapter appears in the report.
- We expect chapters, sections and subsections to be given a number automatically (e.g., Chapter 1, Section 1.2, etc.). To make this happen we will invoke Pandoc with the
- Our report contains figures and tables that we want to refer to from the document text. So we want both figures and tables to be automatically numbered and to have a certain ID so that we can to refer to them in the text. Because Pandoc's Markdown does not yet feature specific support for figure/table referencing, we will turn to the
pandoc-crossrefPandoc filter. As such, in invoking Pandoc we will pass the following option
- Finally, we want to distribute the document in three different formats: PDF -optimized for printing-, HTML -served directly by our site as a standalone page- and EPUB -for a better reading experience on mobile devices-. Moreover, we will tell Pandoc to use a specific CSS stylesheet for the HTML version, as well as to include a cover image in the EPUB version.
Provided that the Markdown source for the various chapters is found in the
chapter3.md files, the Pandoc commands below will generate the PDF, HTML and EPUB versions of the report (we assume pandoc v1.19 here):
# For PDF $ pandoc chapter1.md chapter2.md chapter3.md -o report.pdf -N --filter=pandoc-crossref -M documentclass:report -t latex -s --chapters # For HTML $ pandoc chapter1.md chapter2.md chapter3.md -o report.html -N --filter=pandoc-crossref -t html -s --css=cool.css # For EPUB $ pandoc chapter1.md chapter2.md chapter3.md -o report.epub -N --filter=pandoc-crossref -t epub --epub-cover-image=cover.png
To avoid typing these somewhat long commands over and over again to see what a particular final document looks like, we could turn to the GNU Make tool. A very nice feature of GNU Make is that it enables the user to define various targets, which, in the context of Pandoc, could be used to represent the various final documents we may want to generate from our source document (e.g., Markdown). Unfortunately, getting familiar with the syntax of build files in this tool (called Makefiles) takes some time, especially for users that are not used to working with command-line tools.
To overcome this issue, while still offering the target abstraction to the user, Panbuild relies on the YAML language to define build files. Notably, most Pandoc users are already familiar with this language, since it allows them to define Pandoc variables in our document sources via YAML metadata blocks. This fact, coupled with the simplicity of the language syntax, makes YAML a suitable choice for the definition of build files for Panbuild.
Syntax of build files
Now, let us go back to our example to describe the syntax of Panbuild's build files. The following sample YAML code contains the necessary information for Panbuild to build the various final documents from our Markdown code with Pandoc:
pandoc_common: filters: - pandoc-crossref input_files: - chapter1.md - chapter2.md - chapter3.md pandoc_targets: PDF: options: -N -o report.pdf -t latex -s -M documentclass:report --chapters HTML: options: -N -o report.html -t html -s --css=cool.css EPUB: options: -N -o report.epub -t epub --epub-cover-image=cover.png
Clearly, the file consists of various nested sections, (e.g. the
filters section is included within
pandoc_common in the example). The name of a nested section (which ends with ':') is preceded by a number of spaces that depends on its nesting level. Specifically, provided that top-level sections (such as
pandoc_targets) are said to be at level 0, the name of a level-N section has 2N preceding spaces. The right indentation is required in the YAML file in order for Panbuild to be able to process the build rules. Due to the flexibility of the syntax of the YAML language, several other alternative ways exist to encode the same information of this example (as long as the various properties are defined in the same level and within the right section). Users are strongly encouraged to check out this article on the YAML syntax.
In creating a build file two mandatory (top-level) sections are provided:
pandoc_targets. The first section defines those features that target commands have in common; in this case it enumerates the list of Pandoc filters (just one in the example) and the various input (source) files that our document is made up of. Panbuild uses this information when generating the actual Pandoc commands for each target. The second section (
pandoc_targets) defines the set of targets in the build file; each target has an ID associated with it. In the example, three targets are defined, with IDs
EPUB, respectively. The ID of each target in the example matches the uppercase version of the extension of the output file specified in
options. Because each target is typically meant to build a file in a different format, assigning IDs in this way is a good practice. Nevertheless, assigning IDs to the various targets it is totally up to the user; IDs are just arbitrary case-sensitive strings made up of alphanumeric characters, and may include hyphens and underscores too.
options section associated with each target specifies the options that will be passed to the pandoc command when building the target. As is evident, the filters and the input files were omitted in
options for any target, as these aspects were included in the
pandoc_common section (shared among targets).
To use the YAML code shown above with Panbuild, we may store it in a build.yaml file located in the same directory as our document's sources (Markdown files in this case). In doing so, invoking
panbuild without any arguments when in that directory will execute the commands associated with all the targets defined in the file:
$ ls build.yaml chapter2.md cool.css chapter1.md chapter3.md cover.png ... $ panbuild Building target PDF ...Success Building target HTML ...Success Building target EPUB ...Success
The output files generated by Panbuild as a result of running the various pandoc commands will be available in the current working directory.
$ ls build.yaml chapter2.md cool.css report.epub report.pdf chapter1.md chapter3.md cover.png report.html ...
Note that we can easily retrieve the complete Pandoc command for each target by using the
$ panbuild -Lv PDF: pandoc -s --chapters -t latex -M documentclass:report -N -F pandoc-crossref -o report.pdf chapter1.md chapter2.md chapter3.md HTML: pandoc -s -N -t html --css=cool.css -F pandoc-crossref -o report.html chapter1.md chapter2.md chapter3.md EPUB: pandoc --epub-cover-image=cover.png -t epub -N -F pandoc-crossref -o report.epub chapter1.md chapter2.md chapter3.md
The value of the
options property for the various targets shown earlier could be shortened by leveraging two observations:
-Noption of Pandoc is used in all targets, and so it appears multiple times in the file
- The name of the output files for each target follows the same pattern:
basenameis "report" for all targets, and
<extension>can be automatically determined by Pandoc, based on the
-soptions (if present).
According to these observations, we could rewrite the build file as follows:
pandoc_common: filters: - pandoc-crossref input_files: - chapter1.md - chapter2.md - chapter3.md output_basename: report options: -N pandoc_targets: PDF: options: -t latex -s -M documentclass:report --chapters HTML: options: -t html -s --css=cool.css EPUB: options: -t epub --epub-cover-image=cover.png
-N or the
-o switches are no longer specified as target-specific options. Instead, two new properties are specified inside
output_basenameindicates the base name of the output file (the extension will be added automatically).
optionsspecifies the set of options that will be applied for all targets.
The sample build file analyzed in this section exemplifies what would be used in a somewhat complex build scenario, thus allowing us to describe many aspects of the syntax of Panbuild's build files. However, other build properties may be also present inside a target's section, such as these:
preamble: list of input files that will appear first in the command line, right before those listed in the
input_filesproperty. Essentially, this allows the user to add specific preambles (e.g. a cover) just for a certain target output formats.
metadata: dictionary (set of key-value pairs) with variables and values that will be passed to pandoc's command line via the
pandoc_common: ... pandoc_targets: PDF: options: -t latex -s --chapters metadata: documentclass: report lang: en-US ...
variables: dictionary with variables and values that will be passed to pandoc's command line via the
Finally, we should highlight that the contents of the build file, which we have stored so far in a separate
build.yaml file, could be also embedded as a Pandoc's YAML metadata block inside one of the source files pased as input to Pandoc. More generally, such a block may define both the
pandoc_targets properties required for Panbuild, as well as any other Pandoc variables to control the style or any other features of the final document, as explained in Pandoc's User Manual. In case that Panbuild-related information is included in one of the source files rather than in build.yaml, the name of the source file should be passed to
panbuild as an argument of the
-f option (e.g.
panbuild -f source.md). This choice is specially suitable for documents consisting of a single source file. Thus, that single file would be self contained, in the sense that would define both the document's contents as well as the build rules for Panbuild.
Integration with extensible text editors
Panbuild has been designed from the ground up as a tool for creating Pandoc frontends using extensible text editors (i.e. those that support plugins/addons). Today, several Pandoc frontends exist, such as the Typora Markdown Editor or the Pandoc plugin for Sublime Text. Unfortunately, at the time of this writing none of these solutions allow the user to access the full Pandoc's functionality from the GUI. In particular, in these environments the user cannot control what options are passed to Pandoc; instead a set of predefined output profiles are available to the user, which cannot be fully customized with specific pandoc options. In addition, documents divided into multiple source files (such as the example discussed earlier) are simply not supported: Pandoc can be only invoked with one input file from these editors. Under these circumstances, users often have to turn to the command line to invoke Pandoc commands directly.
Despite the fact that Panbuild is a command-line tool, it features several options to allow the creation of Pandoc plugins for extensible text editors. As a proof of concept, we created a Panbuild's plugin for Sublime Text, which illustrates the role of
panbuild in the creation of a graphical frontend for Pandoc, enabling full access to its entire functionality without using the command line.
The plugin relies on the following key options of
-L: displays the list of targets (IDs only) found in the build file
-o: displays the set of output files (argument of Pandoc's
-oswitch) for each target.This option allows a plugin to figure out what specific file is generated after the execution of a Panbuild target. For example, this information could be used by a plugin to open the file automatically with the default application for it, right after the file was built by Pandoc.
$ panbuild -o PDF: report.pdf HTML: report.html EPUB: report.epub
If you experience any difficulties while using Panbuild, please do not hesitate to open an issue on github so that we can help.