Pandoc 处理 Markdown 文件的格式转化

Markdown 写起来很舒服,纯文本管理起来也很顺手,但是涉及交流的时候,在有些场合也显得不太“正式”,这时候就需要转换成其它格式。

常用的无非是 HTML 格式、MS Word 格式(是的,大微软我们难以绕开)和 pdf 格式。这时就可以祭出神器 Pandoc 了。我说它“神”是因为有两点:第一,它是一个哲学教授写的工具,第二,它是用 Haskell 写的……

安装

下面的命令都是 macOS 上的,其实除了安装不一样之外,都大同小异。需要安装的软件主要有两个:

1
2
brew install pandoc
brew cask wkhtmltopdf

markdown -> docx

这一步非常简单:

1
pandoc -o test.docx test.md

如果需要修改默认的格式,可以先用pandoc --print-default-data-file reference.docx > custom-reference.docx命令输出默认的格式,再把 custom-reference.docx 文件修改成你想要的格式,最后引用它就可以了:

1
pandoc --reference-doc=custom-reference.docx -o test.docx test.md

markdown -> html

也一样非常直接:

1
pandoc -s -o test.html test.md

markdown -> pdf

用 wkhtmltopdf 引擎输出 pdf

这一步曾经很纠结,一开始走的是"markdown->latex/xelatex->pdf"这条路,是成功了。不过上学时被 $\TeX$ 的中文支持给折磨怕了,现在年纪大了不愿意无故折腾,不想多深入研究 $\LaTeX$ ,所以要有点个性化(如修改多种字体、调整格式等)就显得比较麻烦了。

$\TeX$ 这东西,确实是在学术领域更适合,以几年的血泪史奉劝一句:不建议需要使用中文的凡人折腾

然后就走了一条"markdown->html->pdf"的路,生活就幸福多了,在 Pandoc 1.16 之前,是先通过上面的方法转成 html 文档,再使用wkhtmltopdf命令将 html 文件转成 pdf,分了两步,但也非常干脆,没什么拖泥带水的。

从 1.16 开始 Pandoc 就直接支持使用 wkhtmltopdf 作为生成 pdf 的引擎了,于是比较完美的解决方案出现:

1
pandoc --pdf-engine=wkhtmltopdf -o test.pdf test.md

也可以只使用-t html选项,默认就是--pdf-engine=wkhtmltopdf。使用这种方式时,margin-left, margin-right, margin-top, margin-bottom, footer-html, header-htmlpapersize 这几个可以直接在参数中设定,其它的格式可以(也只能)通过 --css 选项指定 CSS 文件来设置。这对我来说够了,不过wkhtmltopdf的参数非常之多,所以如果想更精细的调整,还是可以使用两步的方法分别调用pandocwkhtmltopdf来实现。

输出带页眉页脚的 pdf

这个依靠 wkhtmltopdf 实现,分别准备一个html文件即可,以页脚为例,准备一个footer.html文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<div>
	<div style="float:left"> 
		<font size=2 color=gray><span>&copy </span> Copyright by </font>
		<font size=2><strong> XXXX科技股份有限公司</strong> </font> 
	</div>
	<div style="float:right"> 
		<img src="./images/logo.png"  alt="NOBO AUTOMOTIVE" width="77.5" height="21.45" />
	</div>
</div>

注意两点:

  1. <!DOCTYPE html>是必须的。
  2. 如果有中文,需要加上第二行:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

使用这个文件有三种方式,第一就是在markdown文件的 Front Matter 里里直接加入源数据:

1
2
3
4
---
header-html: ./header.html
footer-html: ./footer.html
---

这种方式最方便,但是对 markdown 文档有一点的侵入性。

第二种方式是在命令行中使用--variable参数:pandoc --pdf-engine wkhtmltopdf --variable=footer-html:footer.html ...。 这种方法不用改动markdown源文件,命令行参数比较简洁,但是需要pandoc支持才行,目前支持的是:footer-htmlheader-htmlmargin-leftmargin-rightmargin-topmargin-bottompapersize

第三种方法中通过--pdf-engine-opt直接把参数传给wkhtmltopdf:pandoc --pdf-engine wkhtmltopdf --pdf-engine-opt=--footer-html --pdf-engine-opt=footer.html ...,这种写要比第二种啰嗦一些,但是通用性最好,我喜欢用这种,只进行一次记忆就行了,而且命令不是每次都重新输入,所以也不麻烦。

一个较完整的示例(footer.html在当前目录下):

1
pandoc  --self-contained --standalone --number-sections --table-of-contents --pdf-engine wkhtmltopdf --pdf-engine-opt=--footer-line --pdf-engine-opt=--footer-spacing --pdf-engine-opt=5 --pdf-engine-opt=--footer-html --pdf-engine-opt=footer.html --pdf-engine-opt=toc --pdf-engine-opt=--xsl-style-sheet --pdf-engine-opt=toc.xsl example.md -o example.pdf

如果页眉页脚只是文字,并不需要一个html文件,这时候直接使用footer-left这一类参数即可实现。

wkhtmltopdf 中目录的处理

如果是生成pdf,就不要使用pandoc自己的目录参数了“–table-of-contents”,使用 wkhtmltopdf 的目录生成功能:--pdf-engine-opt=toc,这样生成的目录单独占一页,且带页码。

可以使用wkhtmltopdf --dump-default-toc-xsl导出目录样式进行修改,然后再引用,没有仔细研究,只是把“Table of Contents”改成了中文,增大了h1字体和ul行高,把每一层的 80%改成了90%看起来舒服一些。

取后在命令行中使用这个文件:--pdf-engine-opt=toc --pdf-engine-opt=--xsl-style-sheet --pdf-engine-opt=toc.xsl

几个常用的参数

除了上面最基本的-t-f-o等参数,还有几个我个人比较常用的参数:

  • -c URL/--css=URL 指定 CSS 文件,这在生成 HTML 和 PDF 时都很有用
  • --toc/--table-of-content 自动生成目录,可以使用–toc-depth=NUMBER来指定深度
  • -s/--standalone 生成的文件会带头注和脚注,对 html 文件还能解决未指定编码的问题
  • --self-contained 会将CSS、图片等嵌入到目标 html 文件中
  • -N/--number-sections 自动生成章节编号,带 class unnumbered 的除外(即# Header {.unnumbered}# Header {-}

其它问题

  1. pandoc 输入输出都是 utf-8,处理其它编码时可以使用 iconv 来转一下编码。
  2. 有时候输出的 pdf 文件还需要一个漂亮的封面,这时候就不要吊死在 markdown 上了,可以使用其它工具做一个 pdf 格式的,最后拼到生成的 pdf 文件之前就可以了,拼接我使用的工具是 ghostscript,在 macOS 上可以通过 Homebrew 安装即可。(wkhtmltopdf也支持封面,应该也很方便,但是我没有研究了)
  3. 对于自己常用的参数,可以写一些脚本封装一下来简化每次的输入,更进一步可以使用 makefile 来管理构建输出,个人使用的是 cmake,也是神器,有时间另行介绍。
  4. 用 git 或 github 管理 markdown 文件是一个非常不错的选择。
  5. 图片如何居中,使用Typora等工具时,图片是自动居中的,但是pandoc处理后就没有了,可以使用html标签:
    1
    2
    3
    
     <p align="center">   
       <img src=".\llvm.png"> 
     </p>
    

写在最后 – 对工具使用的反思

之前有不少文档需要批量操作,修改、输出、交流也比较频繁,这套工作流的形成用了不少时间,带来了不少方便。

但现在其实也很少使用了(其实从2022年下半年以后用得就很少了),所以也没有看看最近有没有更好的处理方法。现在多数的 markdown 编辑都自带了输出 pdf 文件的功能,而且也能自定义 CSS,所以如果不是需要批量操作,或有特别的格式调整,这也完全够用了。而且现在随着 markdown 越来越普及,往往直接分享源文件就可以了!

工具是死的,人是活的,在工具方便我的原则是“可以折腾,但不要纠结”,先用熟练一种,有新方法时也不要排斥,不断更新自己的,这个过程中一直保持一种可以“信手拈来”的状态(所用的方法和工具不一定是最新最好的,熟练更重要)。