If you've read some of my previous posts on SitePoint or elsewhere, you may know that I'm working on a board game. In the game, called Chip Shop, you get to run a computer company in 1980s America.

如果您已经阅读过我以前在SitePoint或其他地方发布的一些文章 ,则可能会知道我正在棋盘游戏。 在名为Chip Shop的游戏中,您可以在1980年代美国经营一家计算机公司。

As part of the project, I'm attempting to open source the entire game as much as possible. After several false starts, I've decided on a basic framework of Markdown for most of the game components—especially cards and the manual.

作为项目的一部分,我正在尝试尽可能开源整个游戏。 经过几次错误的尝试之后,我决定为大多数游戏组件(尤其是纸牌和手册)选择Markdown的基本框架。

As the game's website uses Jekyll, the website for the game is generated from the Markdown files. I intend to have premium pre-boxed and print-yourself versions of the game, and to achieve this I need to generate PDFs from the Markdown files.

由于游戏的网站使用Jekyll ,因此游戏的网站是从Markdown文件生成的。 我打算使用该游戏的高级预装盒和自行打印版本,为实现这一目标,我需要从Markdown文件生成PDF。

我要完成的工作 (What I'm Trying to Accomplish)

My ideal workflow is to generate the PDF files at the same time as generating the website, rather than generate the files as visitors request them. This rules out my usual option for PDF generation, wkhtmltopdf, as it generates PDFs from already generated HTML. Another reason it's not an option is that I want the PDF card versions to look different from the HTML pages, and Jekyll lacks any kind of view mode feature to accomplish this without resorting to complex CSS rules.

我理想的工作流程是在生成网站的同时生成PDF文件,而不是根据访问者的要求生成文件。 这排除了我通常用于生成PDF的选项wkhtmltopdf ,因为它从已经生成HTML生成PDF。 不能选择的另一个原因是,我希望PDF卡版本看起来与HTML页面不同,而Jekyll缺乏任何视图模式功能来完成此任务,而无需诉诸复杂CSS规则。

The Markdown template file for cards in the Chip Shop game contains a lot of Markdown front matter fields for game mechanics. Not all are used on every card. For convenience during printing, I need to fit as many cards on an A4 page as possible—in this case, a 3×3 grid. Eventually the pages will need to be double-sided, but I haven't implemented that yet.

Chip Shop游戏中卡片的Markdown模板文件包含许多Markdown面向游戏机制的物质领域 。 并非每张卡都使用全部。 为了方便打印,我需要在A4页面上尽可能多地放入卡片,在这种情况下为3×3网格。 最终,页面需要是双面的,但是我还没有实现。

输入Pandoc和LaTeX (Enter Pandoc and LaTeX)

Any internet search looking for solutions to generating PDFs from Markdown will lead you down the Pandoc path. Pandoc is an open-source, Swiss Army knife markup conversion tool that supports a wide and growing variety of input and output markup formats.

任何在互联网上寻找从Markdown生成PDF的解决方案的搜索都将带您进入Pandoc的道路。 Pandoc是一种开源的瑞士军刀标记转换工具,它支持越来越多的输入和输出标记格式。

To generate PDFs with Pandoc, LaTeX is needed. LaTeX has its roots in the scientific research community, and is a document declaration and layout system. Combining Pandoc and LaTeX allows us to use variables, and thus to generate PDFs from a series of Markdown files and support Markdown front matter.

要使用Pandoc生成PDF,需要LaTeX 。 LaTeX起源于科学研究界,是一个文档声明和布局系统。 Pandoc和LaTeX的结合使我们可以使用变量,从而从一系列Markdown文件生成PDF并支持Markdown前端。

Despite the power of Pandoc and LaTeX, I couldn't find any way of combining multiple PDFs (cards) onto one page, especially when using variables from Markdown files. After much research, I settled on PDFJam, a simple command line tool for this requirement.

尽管有Pandoc和LaTeX的强大功能,但我找不到将多个PDF(卡片)组合到一页上的任何方法,尤其是在使用Markdown文件中的变量时。 经过大量研究,我选择了PDFJam ,它是满足此要求的简单命令行工具。

安装依赖项 (Installing Dependencies)

降价促销 (Markdown)

You need no extra software for Markdown, except maybe an editor and there are so many of those, I suggest you read a few SitePoint posts to make your choice.

Markdown不需要额外的软件,除了编辑器外,而且其中有很多,我建议您阅读一些SitePoint 帖子以做出选择。

杰基尔 (Jekyll)

I'll continue to use Jekyll in my examples taken from my game to illustrate the build process, but it isn't an essential part of PDF generation if you don't need a website.


潘多克 (Pandoc)

On my Mac, I installed Pandoc with Homebrew, but there are options for all operating systems.


胶乳 (LaTeX)

There are lots of opinions on the best way to install LaTeX, depending on what you need or intend to do with it. A full installation of its common tools and libraries can near 2GB, but for most purposes a minimal installation will be enough. Read the project's download page to find the best option for you.

关于安装LaTeX的最佳方法有很多意见,这取决于您需要或打算使用它。 完整安装其常用工具和库可能需要将近2GB,但对于大多数用途而言,只需最少安装即可。 阅读项目的下载页面,以找到最适合您的选择。

For this tutorial, we'll be using the xelatex engine, as I use custom fonts. But you can select any engine that supplies specific features you require.

在本教程中,我们将使用xelatex引擎,因为我使用自定义字体。 但是您可以选择任何提供所需特定功能的引擎。

杰姆 (PDFJam)

Depending on how you installed LaTeX, you may have PDFJam installed already. (Check by typing which pdfjam in the terminal.) If you haven't, then find details on installation here.

根据您安装LaTeX的方式,您可能已经安装了PDFJam。 (通过在终端中键入which pdfjam进行检查。)如果尚未安装请在此处找到有关安装的详细信息

构建过程 (The Build Process)

After some consideration, a bash script that I run locally seemed the best option for now. There are better methods, but it works, and I can improve the process later, transferring it to a Continuous Integration system or Git Hooks.

经过考虑,我目前在本地运行的bash脚本似乎是最好的选择。 有更好的方法,但是它可以工作,我以后可以改进该过程,将其转移到Continuous Integration系统或Git Hooks。

View the bash script on GitHub.


Let's now step through this script.


建立 (Setup)

bundle install
bundle update

rm -dfr _site
rm -dfr pod

These commands ensure that the Ruby dependencies Jekyll needs to build the website are up-to-date, and that we remove any existing website and print folders.


建立网站 (Build the Website)

jekyll build
mkdir -p pod/pdf/cards

Next we build the website and create a folder for the print versions of the cards.


从Markdown生成PDF (Generating PDFs from Markdown)

Let's create a folder containing a PDF version of each Markdown file:


for filename in _cards/*.md; do
  echo $filename
  pandoc --from=markdown+yaml_metadata_block --template _layouts/cards.latex -o pod/pdf/cards/"$(basename "$filename" .md)".pdf --latex-engine=xelatex $filename

The script processes every Markdown file in the _cards directory, ensuring that the Markdown front matter fields are observed. Using the cards.latex template (we'll look at that next), the correct LaTeX engine outputs a PDF with an appropriate name.

该脚本处理_cards目录中的每个Markdown文件,确保遵守Markdown前_cards字段。 使用正确的LaTeX引擎使用cards.latex模板(我们接下来将介绍),输出具有适当名称的PDF。

LaTeX文件 (The LaTeX File)

A lot of the magic for generating the card files from Pandoc takes place in a LaTeX template.


View the LaTeX template on GitHub.


LaTeX is new to me, but it isn't too complex. I'll explain what I changed from the default LaTeX file (found in Pandoc_install_dir/data/templates/default.latex) to make the cards work. I recommend sharelatex.com for previewing LaTeX files as you edit them.

LaTeX对我来说是新手,但并不太复杂。 我将说明如何更改默认LaTeX文件(可在Pandoc_install_dir/data/templates/default.latex )以使卡正常工作。 我建议您使用sharelatex.com在编辑LaTeX文件时预览它们。

% Set page size
% We need column layouts
% We want images in our layout
% Where are images located
% We want to use a custom font installed on our local system, so add that package and select the font

We need a specific page size, and we'll use columns later for the costs and scores of the cards. We're using graphics and custom fonts, so we need those packages.

我们需要特定的页面尺寸,稍后我们将使用各列来计算卡的成本和得分。 我们正在使用图形和自定义字体,因此我们需要那些

We're attempting to create a simple layout that's clear and uncluttered. Here's how we accomplished it:

我们正在尝试创建一个清晰整洁的简单布局。 这是我们如何完成它:

  \begin{tabular}{ l l }
    Costs & Scores \\
    $if(staffcost)$ Staff: {$staffcost$} $endif$ & $if(loyaltyscore)$ Loyalty: {$loyaltyscore$} $endif$ \\
    $if(rdcost)$ RandD: {$rdcost$} $endif$ & $if(profitscore)$ Profit: {$profitscore$} for {$profitlength$} turns $endif$ \\
    $if(marketingcost)$ Marketing: {$marketingcost$} $endif$ & $if(longevityscore)$ Longevity: {$longevityscore$} $endif$ \\
    $if(longevitycost)$ Longevity: {$longevitycost$} $endif$ &  \\
    $if(moneycost)$ Money: {$moneycost$} $endif$ &
    Special: {$specialscore$}

I feel a lot of the above is reasonably self explanatory for anyone used to code or markup. We're creating the elements of the card, aligning them, setting font sizes and checking if there are values before outputting them, so that the card doesn't end up with empty fields.

我觉得以上内容对于习惯于编码或标记的任何人来说都是可以自我解释的。 我们正在创建卡的元素,将它们对齐,设置字体大小,并在输出它们之前检查是否有值,以便卡不会以空字段结尾。

We resize the image to a particular size and centre it. The costs and score values are in a two-column layout, set with the begin{tabular} command and the column quantity with the number of ls.

我们将图像调整为特定大小并将其居中。 成本和得分值采用两列布局,使用begin{tabular}命令设置,列数量设置为l s。

Single Card

将卡合并到一页上 (Combining Cards Onto One Page)

We use PDFJam to create a large PDF file combining each of the individual PDF cards:


pdfjam pod/pdf/cards/*.pdf --no-landscape --frame true --nup 3x3 --suffix complete --outfile ./cards.pdf
mv cards pod/cards_complete.pdf

With this command, we specificy the following:


  • that the page orientation should always be portrait

  • that each individual PDF should be framed

  • the grid size

  • a file name suffix

  • a file name.


PDFJam can give an error if you don't output into its working directory, so I move the file to where I actually want it (hopefully that's solvable in the future). Here we could also delete the individual PDF files if we don't want them.

如果您不输出到PDFJam,PDFJam可能会给出错误,因此我将文件移动到我真正想要的位置(希望将来可以解决)。 在这里,如果我们不想删除单个PDF文件,也​​可以删除它们。

And that's it—we have a website and printable PDF of the game cards.


Cards 9up

运行脚本 (Running the Script)

I run the build script with ./build.sh. As there's a lot of image and PDF processing, it takes about five to ten minutes. I then have a separate script that deploys these folders to a web server.

我使用./build.sh运行构建脚本。 由于图像和PDF处理很多,大约需要五到十分钟。 然后,我有一个单独的脚本将这些文件夹部署到Web服务器。

下一步是什么 (What's Next)

This process has taken me a while to get right, but it's now good enough to move forwards and finesse the process and layouts after play testing.


I hope you find my research and experiments useful for your projects. Please let me know if you have any comments or suggestions.

希望您发现我的研究和实验对您的项目有用。 如果您有任何意见或建议,请告诉我。

翻译自: https://www.sitepoint.com/creating-pdfs-from-markdown-with-pandoc-and-latex/

  • 0
  • 0
  • 0
  • 一键三连
  • 扫一扫,分享海报

评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
钱包余额 0