如何用Pandoc和Docker创建一个出版链(附代码)

1,069 阅读6分钟

用Pandoc和Docker创建一个发布链

今天,我们将仔细研究专业人士如何在Pandoc的帮助下创建一个强大且易于实施的发布链。Pandoc是一个极其简单而强大的工具,它允许用户根据他们的要求将文件转换成各种格式。

它可以大大简化文件和出版,甚至开辟一些新的自动化可能性。最重要的是,Pandoc依赖于对Git友好的Markdown,这意味着你也可以为你的文档实施一个版本控制系统,而没有任何额外的麻烦。

说到麻烦,我们将依靠一个Docker镜像,通过简单的拉动来安装Pandoc和LaTeX。安装软件是很耗时的,而且在开始一个新项目时,从头开始建立一个工作的软件环境也很难有成效。Docker有助于缓解这些问题,因为它允许用户在几分钟内设置好一切,而不管是什么平台。

此外,雇主要求你提供自己的计算机硬件的情况并不少见。这通常被称为自带设备(BYOD),而且我们不要忘记,COVID-19的大流行使得在家工作变得更加普遍。如果没有像Docker这样的解决方案,就很难支持在Windows、macOS和Linux等不同硬件和操作系统上运行的应用程序。

让我们先仔细看看Docker容器和图像,然后再继续讨论Pandoc。

Docker的拯救

使用Docker容器可以消除在一台新机器上安装多个软件应用程序的需要。在Docker Hub上有大量的应用程序的预构建Docker镜像。领先的云供应商,如AWS、Azure和Google都提供了容器注册表。还有许多其他的第三方注册机构,包括GitLab红帽OpenShift

大多数(如果不是全部)应用程序都可能有一个镜像。这意味着没有必要安装大多数应用程序和它们的依赖关系。应用程序可以简单地在Docker容器中运行。这方便地消除了与团队成员在不同硬件和不同操作系统上运行应用程序有关的问题。同样的镜像可以用于在任何可以运行容器的系统上运行,Docker专家可以使这个过程变得非常快速和高效。

Pandoc用例文档

文档可能需要几种不同的格式。同样的文件可能需要以不同的格式提供,如HTML用于演示,PDF用于讲义。文件格式之间的转换可能很繁琐,需要大量的时间。一个好的解决方案是建立一个具有单一真理来源的出版链。所有的文件都应该用相同的语言编写。它应该是一种基于文本的语言,因为它更容易在Git存储库中进行版本和存储。

Markdown是创建单一真理源的一个好选择。可以将Markdown文档转换为其他各种格式的软件是现成的,而且往往是可靠的。

Markdown can be easily converted into a range of different formats for various uses

Markdown可以很容易地转换为一系列不同的格式,用于各种用途。

Pandoc

Pandoc是一个可以将文件转换为不同格式的软件包。特别是,它可以将Markdown转换成HTML、PDF和其他广泛使用的格式。转换过程可以使用Markdown源中的模板和元数据进行定制。

Pandoc需要安装LaTeX来创建PDF文件。安装Pandoc和LaTeX是相当耗时的。幸运的是,有一个叫做pandoc/latex的Docker镜像,它不需要安装Docker以外的东西。

Docker命令

需要找到或创建一个合适的Docker镜像,其中包含必要的软件。建议将镜像拉到本地注册中心,因为下载可能需要一些时间。

docker pull pandoc/latex

要在Docker容器中运行一个命令,需要一个包装器来运行Docker容器并在容器中执行命令。一个好的解决方案是在macOS或UNIX/Linux系统上编写一个shell函数。该函数可以放在任何登录脚本中,或放在一个单独的文件中,如$HOME/.functions 。也可以写一个具有相同功能的脚本或别名。

function pandoc {
   echo pandoc $@
   docker run -it --rm -v $PWD:/work -w /work pandoc/latex pandoc "$@"
}

这个函数做了以下工作:

  • 它将命令打印到屏幕上。
  • 它从pandoc/latex 镜像中运行一个Docker容器。
  • -it 选项创建一个交互式终端会话,并使命令的输出可见。
  • 一旦命令结束,--rm 选项将删除该容器。
  • -v $PWD:/work 选项将主机上的当前目录挂载到容器中的目录/work
  • -w /work 使容器中的/work 目录成为工作目录。
  • 最后,pandoc "$@" 在容器中运行pandoc 命令,并传递给该函数的所有命令行选项。

shell或脚本需要将该函数加载到内存中:

. $HOME/.functions

该函数现在是一个有自己权利的命令,其行为方式与pandoc 二进制文件在本地安装时的行为方式相同。这种方法可以用于Docker镜像中的任何命令。

将Markdown转为HTML

要将Markdown转换为HTML,最好在Markdown中使用一个模板和元数据:

Markdown to HTML

Markdown元数据

Markdown源可以有一个标题部分,可以有任意的元数据。元数据采取键值对的形式。这些值可以在HTML模板中被替换:

---
title: Document title
links:
  prev: index
  next: page002
...

页眉以一行只包含三个破折号的行开始--- 。它的结尾是一行只包含三个点的文字... 。键是单字,后面是冒号和它的值。键值可以被嵌套。这个例子显示了名为title, links.prevlinks.next 的键的定义。

这种方法为每个页面使用一个单独的文件。在这个例子中,上一页是ìndex.md ,当前页是page001.md ,下一页是page002.md 。在实践中,应该使用更有意义的文件名,这样更容易重新排序和插入页面。

HTML模板

一个HTML模板就是一个简单的HTML文件。元数据替换和简单的控制结构可以在美元符号之间添加。下面是一个关于Pandoc的HTML模板的简单例子:

<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>$title$</title>
        <link href="../css/style.css" type="text/css" rel="stylesheet" />
    </head>
    <header>
        <h1>$title$</h1>
    </header>
    <body>
        $body$
    </body>
    <footer>
        $if(links.prev)$
        <a href="$links.prev$.html" class="previous">&laquo; Previous</a>
        $endif$
        $if(links.next)$
        <a href="$links.next$.html" class="next">Next &raquo;</a>
        $endif$
    </footer>
</html>

这个例子显示了一个模板$body$ ,被替换为转换为HTML的Markdown文本。条件语句只在Markdown标题中定义了元数据的情况下生成HTML链接。

从Markdown生成HTML

Pandoc只需要被告知输入和输出文件的名称以及任何模板文件。默认的输入文件格式是Markdown。它可以从指定的输出文件扩展名推断出输出文件格式。

产生输出的命令可以是一个脚本或一个makefile文件:

dir=Project
for input_file in ${dir}/*.md
do
    output_file=HTML/${input_file%.md}.html
    if [[ ${input_file} -nt ${output_file} ]]
    then
        pandoc --data-dir . --template presentations.html -t html \
                -o ${output_file} ${input_file}
    fi
done

对于Project 目录中的每一个.md 文件,如果输出文件比输入文件老或不存在,它就在HTML/Project 目录中创建一个相应的.html 文件。

从Markdown生成Beamer PDF

Beamer是一个用于制作演示文稿的LaTeX包。其输出是一个PDF幻灯片:

Generating Beamer PDF from Markdown

同样的Markdown源文件也可以用来生成Beamer PDF:

pandoc -t beamer -o PDF/Project.pdf -V theme:Boadilla -V colortheme:whale Project/index.md Project/page000.md

命令的细节是:

  • -t beamer 选项表示使用LaTeX和beamer来生成PDF。
  • -o 选项指定了输出文件。
  • -V 选项选择beamer主题和颜色主题。
  • 该命令以一个Markdown文件的列表结束,这些文件将按照给定的顺序串联起来。

所有的处理都是在一个Docker容器内进行的。

马克顿到PDF

将一个Markdown文件转换为PDF文件也很简单。PDF总是通过首先将Markdown转换为LaTeX来生成。元数据可以被添加到Markdown标题中以定制输出,如设置纸张大小和边距大小:

---
title: Title of document
papersize: a4
geometry:
- margin=20mm
...

从Markdown生成PDF

将Markdown转换为PDF的命令很简单:

pandoc -s Project/outline.md -o PDF/ProjectOutline.pdf

-s选项创建一个独立的文档。

结论

不再需要花很多天来安装软件。只要在Docker容器中运行一个命令,就不需要安装。许多应用程序在Docker Hub上有合适的Docker镜像。如果软件需要更新,只需拉出最新的Docker镜像。

设置一台新的计算机只需安装Docker,拉取必要的镜像,并创建一些脚本。

不再需要用不同的格式创建文档。一个单一的格式,如Markdown,可以用于所有文件。然后像Pandoc这样的工具可以从Markdown生成大量不同格式的文档。

由于Markdown是一个文本文件,当检查到一个Git仓库时,可以获得完整的版本历史。Git 仓库也会自动呈现 Markdown,并允许人们对修改进行评论,而不需要使用文档文件中混乱的修改历史记录。