in.pdf
|
|
+----------------------+--------------------+
| | |
V V V
+----------+ +-----------+ +----------+
| | recipe | | ToC | |
| pdfxmeta +--------->| pdftocgen +-------->| pdftocio +---> out.pdf
| | | | | |
+----------+ +-----------+ +----------+
pdf.tocgen 是一套能够自动为 PDF 文件生成目录( ToC )的开源命令行工具。它能够利用 PDF 文件中标题的字体与位置信息来生成一个基本的大纲。它的源码可以在 GitHub 上找到,但是对它的介绍请阅读项目的主页。
我写这套工具的主要目的是为了让阅读讲义、公开 PDF 教材以及 arXiv 上的论文更加方便。它应该对使用 pdftex (以及 pdflatex, pdfxetex 等)从 TeX 生成的 PDF 支持最好,但是任何软件生成的 PDF都应该是支持的(即,它并不支持扫描的 PDF ),比如 troff/groff 、Adobe InDesign 、Microsoft Word 之类软件中导出的 PDF 。
pdf.tocgen 是使用 Python 3 写成的,我自己是在 Linux 下用 Python 3.8 运行的,但是测试显示最低版本应该是 3.7 。你可以直接使用
$ pip install -U pdf.tocgen
在系统上安装 pdf.tocgen 的最新版本。你也可以用 pipx 或者
$ pip install -U --user pdf.tocgen
来为当前用户安装,防止污染系统的 Python 环境。
pdf.tocgen 的设计受到 Unix 哲学 的影响。我刻意将它拆分成三个程序。它们能够互相协作,但是你也可以将它们分开来使用。它们代表了生成目录所需要的三个步骤:
pdfxmeta
: 从 PDF 中提取标题的元数据(字体和位置),用来制作一个 recipepdftocgen
: 使用 recipe 从 PDF 中提取目录pdftocio
: 将目录导入 PDF 文件如果你想要一个正式的介绍,请阅读主页中的例子。这里我只做一个简单的概览。
这里我使用的例子是 Paul Graham 在他网站上提供的 On Lisp 的 PDF 版本,PDF 本身是没有内嵌目录的。
首先,使用 pdfxmeta
搜索标题的元数据:
$ pdfxmeta -p 14 onlisp.pdf "The Extensible"
The Extensible Language:
font.name = "Times-Bold"
font.size = 19.92530059814453
font.color = 0x000000
font.superscript = false
font.italic = false
font.serif = true
font.monospace = false
font.bold = true
bbox.left = 138.60000610351562
bbox.top = 306.947998046875
bbox.right = 354.4866638183594
bbox.bottom = 334.5445251464844
这就是这个 PDF 中这个标题所对应的元数据,我们可以利用它来制作一个 recipe 。它是一个 TOML 格式的文件,用来告诉 pdftocgen
标题应该所具有的属性:
[[heading]]
# 第一级标题
level = 1
# 所应该具有的元数据
font.name = "Times-Bold"
font.size = 19.92530059814453
你可以把 pdfxmeta
的输出都导出到一个文件里,方便之后修改
$ pdfxmeta -p 14 onlisp.pdf "The Extensible" >> recipe.toml
$ pdfxmeta -p 14 -i onlisp.pdf "^design" >> recipe.toml
$ vim recipe.toml # edit
修改过后的 recipe.toml
可以是这样子的:
[[heading]]
level = 1
font.name = "Times-Bold"
font.size = 19.92530059814453
[[heading]]
level = 2
font.name = "Times-Bold"
font.size = 11.9552001953125
具体的属性需要你自己来测试,recipes
文件夹里有一些已经制作好的 recipe,你也可以发 pull request 或者 patch 贡献更多的 recipe 。
有了这个 recipe 我们就能直接用 pdftocgen
来输出一个目录了。
$ pdftocgen in.pdf < recipe.toml
"Preface" 5
"Bottom-up Design" 5
"Plan of the Book" 7
"Examples" 9
"Acknowledgements" 9
"Contents" 11
"The Extensible Language" 14
"1.1 Design by Evolution" 14
"1.2 Programming Bottom-Up" 16
"1.3 Extensible Software" 18
"1.4 Extending Lisp" 19
"1.5 Why Lisp (or When)" 21
"Functions" 22
"2.1 Functions as Data" 22
"2.2 Defining Functions" 23
"2.3 Functional Arguments" 26
"2.4 Functions as Properties" 28
"2.5 Scope" 29
"2.6 Closures" 30
"2.7 Local Functions" 34
"2.8 Tail-Recursion" 35
"2.9 Compilation" 37
"2.10 Functions from Lists" 40
"Functional Programming" 41
"3.1 Functional Design" 41
"3.2 Imperative Outside-In" 46
"3.3 Functional Interfaces" 48
"3.4 Interactive Programming" 50
[--snip--]
它的输出可以直接用 pipe 导入到 pdftocio
,将目录导入到 PDF 中
$ pdftocgen onlisp.pdf < recipe.toml | pdftocio onlisp.pdf
你也可以将它导入到一个文件中,修改生成中出现的错误:
$ pdftocgen onlisp.pdf < recipe.toml > toc
$ vim toc # edit
$ pdftocio onlisp.pdf < toc
toc
文件的具体格式请见主页中的 例子,它的设计是为了 Vim 里的易编辑性,因为你有很大可能会想微调 pdftocgen
所输出的目录。
每个程序都有一些附加的功能,请使用 -h
flag 显示所有的选项。
pdf.tocgen 是一个自由软件,它采用的是 GPLv3 License,所有的衍生软件必须保证用户的自由。recipes
目录中的所有 recipe 都采用 CC BY-NC-SA 4.0 License 以避免任何商业用途,它们没有附带在安装包里。
你可以免费使用 pdf.tocgen 以及自由地修改它的源码,但如果你觉得这个工具有帮助到你,并且想支持我或者这个工程,我也接受一些匿名的捐款,但是我不会保证我会优先考虑你的请求。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.