如何半自动地给 PDF 添加目录

什么东西比一个 PDF 文档更惹人烦?一个没有目录的 PDF 文档。

没有目录的原因很多。可能是在文档传播的过程中被导出丢失了,也可能就是那个作者,明明知晓那么多 LaTeX 的技巧,但就是懒得多动一下手指方便读者。

我们只能自己给文档加目录了。

要做到这件事,我们需要一个免费的小工具:PdgCntEditor。然后,为了省事,我们还需要一小段脚本来快速修整格式。我把这两样东西打包准备好了,你可以点击下载。| 备用地址

这个工具只有 Windows 下有,macOS下我暂时还没找到替代品。因此,你还需要一个虚拟机/双系统。

首先,打开你要添加目录的 PDF,找到它正文里的目录。如果连这个也没有,或者你看的 PDF 是扫描版,那还是放弃吧。把正文里的目录复制下来,粘贴到 Drafts 里。

PdgCntEditor 对于批量添加目录的格式要求是:

  1. 目录的标题和对应的页码之间用制表符(Tab)隔开。
  2. 多个标题之间换行隔开。
  3. 有多层级的标题时,在标题前面加额外的制表符表示层级的缩进。

粘贴到 Drafts

可以看到,从 PDF 里复制出来的内容可以说惨不忍睹,完全不符合 PdgCntEditor 的格式要求。我手动修改了其中的前几行。我们需要把整个目录八百多行全改成这个样子,才能批量添加成功。

这时候,我们需要一小段脚本来帮助我们完成这项工作。安装压缩包里附的 Drafts 动作,然后对这个草稿运行。我们会得到:

运行结果

可以看到,现在的格式都正确了。图中有些页码看起来被换行了,但实际上那是一个制表符。确认这一点的方法是把光标移到有问题的地方,按方向键向前移动一次光标。如果光标回到了上一行最后一个字母的右边,那就表明这里是一个换行。但如果光标移动到了上一行最后一个字母的左边,则说明这里没有换行,只是显示问题。

当然,你得到的很可能和我的结果不一样——因为这个动作只是我针对我面前的这份文档复制出来的目录所写的。它使用 JavaScript 运行正则表达式来匹配并替换文本,大致做了以下几件事:

  1. 把页码和标题之间的「……………」和「. . . . . . . . . . . . 」等内容删除,替换成单个制表符。
  2. 对于所有「1.1」、「10.2」之类的小节号,换行并缩进一次。
  3. 对于所有「1.1.2」、「10.2.5」之类的小节号,换行并缩进两次。
  4. 给大部分单词之间加上空格。

大部分 PDF 拷出来的文本都是类似的格式,所以这个动作应该能帮到你。如果情况不一样,你也可以根据实际情况改写一下我的正则表达式。否则……也许我以后会写一个更通用的动作也说不定。

运行完动作之后,你还是需要手工修整一下。有些地方是复制出来时就有的错误,光靠正则表达式不能去除。

错误

完成以后,让我们在 PdgCntEditor 中打开待添加目录的文档。首先把修整好的目录文本粘贴进主界面,然后点击右上角的 PDF 文档图标:

使用PdgCntEditor

在这里,我们需要为这个目录设定基准页。基准页很好确定:用预览(或者其它 PDF 阅读器)打开该文档,找到待生成的目录中第一章的第一页,它所在的页码就是基准页。

寻找基准页

填入基准页,确认,然后按保存即可。

Done

这时再打开文档,就可以看到目录了。

你可以在这里下载到我用的示例文档。最后提醒一句:在目录文本的标题里不要用制表符,否则生成出来的目录会出错。