# 为 Safari 网页生成可点击的导航目录（Keyboard Maestro 为例）

> 本文公开全文。

原文：https://utgd.net/article/9829

一篇没有目录的文章，就像一场事先没有公布菜单的筵席，吃到后来云里雾里，完全不知道后面还有什么内容。而一旦握有目录，不仅能够掌握阅读节奏，而且在看到目录的那一刻，说不定还能判断一篇文章究竟值不值得读。

然而，传统书籍必备的目录，却没有成为网页文章的标准，读者根本不知道自己将读到什么，往往在惹了一身的臊味之后才知道文章在讲什么，这时候时间已经浪费了。李敖所谓臭鸡蛋闻闻就行，不用下嘴，苟无目录，则往往在下口甚至吞下肚子之后才知文章好坏。小到个人博客，大到大型网站，概莫能外。

Chrome 浏览器上有个 Simple Outliner 插件，就旨在为网页生成目录；显然，这又到了 Safari——以及其他不支持 Chrome 插件的浏览器——眼红的时候。羡慕归羡慕，比起等待好心人开发 Safari 版本，不如自己动手制作一个；我不熟悉该插件所用的编程语言，但凭着可怜的网页开发知识，还是设计出了一套方案，并且打包到 Keyboard Maestro 中，以便为本无目录的网页导航。

Keyboard Maestro Macro 下载

示例文章主要为 Eric Steven Raymond 的 Basics of the Unix Philosophy。

## 使用指津

所有 Keyboard Maestro Macro 在使用前都需要注意设置和权限，尽管写过的文章已经不少，但还是需要唠叨一圈：下载 Macro 后，需记得启用该动作和在所在的 Macro Group，盖为安全起见，网上下载的 Keyboard Maestro Macro 默认都是禁用的。本文的 Macro 需要调用 Javascript，因此还需要 Safari 那边做好配合：

- 打开 Safari 浏览器，进入设置页面，在“Advanced”菜单中启用开发者菜单——“Show Develop menu in menu bar”（不同版本的 Safari，该选项位置也有差异，找不到的话可转道“General”一试）；

- 在开发者菜单中勾选“Allow JavaScript from Apple Events”；

- 选择同意“Allow”，可能需要输入密码或验证指纹。

做好以上准备——Keyboard Maestro 老手估计早就备妥——就可以开始使用 Macro。在网页文章中按下 ⌘Command\-K，不出意外（有意外请看下一节）就能看到一个目录列表，其中已经摘有当前文章各个层级的标题，并略带缩进排布，以示标题级别；点击其中任何一项，即可滚动到该标题所处的位置。

前述 Keyboard Maestro 列表本质上是个带搜索结果的输入框，可以在第一行输入关键词，进一步过滤目录。遇上那种篇幅上万字、目录排成串的长文，可能就得过滤一下。又或者，我可能本来就无事不登三宝殿，一开始就有大致的阅读方向，此时也可以输入关键词，缩小需要浏览的范围。

另外，除了直接在网页上使用，本方案也适用于本地的 HTML 文件。我分享过用 DEVONthink 做 RSS 阅读器的方法，DEVONthink 抓取到的文章默认就是 HTML 格式，并且都是精简过的页面，一般都可以用本文方案生成目录。

整个动作的功能就这么简单，生成目录，点击跳转，以及进一步的搜索过滤。如果你还对原理也感兴趣，或者单纯很像吐槽为什么上图中有一大串形如 id="641141" 的玩意儿，那么，就让我们移驾原理分析部分。

## 原理分析

生成目录的浏览器插件，通常是把目录直接嵌入网页，不得不解决很多兼容性问题。而使用自动化工具，则绝大多数工作都在网页外部完成，对网页、浏览器乃至操作系统的依赖都可以降到最低——我甚至实现了一个 Shortcuts 版本。

如果你在本文上运行 Macro，则会发现，虽然目录是生成了，但里面除了各层级的标题，还夹杂关联文章和作者、版权等信息。我们先不去争论版权部分该不该体现在目录中（这不是一个技术问题），显然关联文章是不该出现的，而它们之所以现身，就是因为我采取了最鲁棒的方法：检查网页上的所有标题，并将其纳入目录。万幸的是我们本身就有目录，大概不需要对本网站动手术。

究其原理，我们在网页上看到的文字，都是由 HTML（HyperText Markup Language，超文本标记语言）渲染而来的。读者们更熟悉的 Markdown 其实就是简化的后的 HTML，两者的共通点就是常常用左右一组代码把文本包起来，从而实现特殊样式，例如想用 HTML 实现粗体，就可以用如下代码：\<strong\>粗体\</strong\>。\<strong\> 和 \</strong\> 就是一组 HTML 标签，被它们包裹的文本就会变粗。与之类似，一段网页上的文字之所以称得上标题，就是因为它们前后有 \<h标题层级数字\> 标签包裹。直接检查 HTML 源码并从中找出 \<h\> 标签，大概就能用最少的工夫确保最大的兼容性。

至此，制作目录就简单了，不过是将标题从 HTML 源码中挑出来。麻烦的是跳转，有的网页做得规范，本身就会给标题一个 ID，相当于挂了一个门牌号，据此可以直接定位到网页的对应位置（这里隐去了 Javascript 的技术细节）。但很多网页并不那么细致，于是我萌发了手动添加 ID 的念头，前文图片中反复出现的 id="xxxxxx" 就是 Macro 自动插入的 ID 参数。有了这些 ID，方能直达标题所在之处。如果不需要搜索框，尤其是实时反馈结果的搜索框，则其他自动化工具也可以拿来给网页做目录，只不过交互不一定像 Keyboard Maestro 那么可靠；下面展示的就是 Shortcuts 版本，点击跳转的过程就很不顺利，并不实用。

此外，为了区分标题层级，我还在标题前面增加了一些缩进，层级越深，缩进越多。如此一来，大小标题，一目了然。当然，如果在美学上有更多追求，则可以设法隐藏目录列表中的文章 ID 和标题层级，但这部分内容属于锦上添花，对我而言收益基本为零，便止步于此。精益求精的机会，就留给诸位。

总之，能不能生成目录，只和网页结构有关，而与文章内容无涉。以知乎和微信公众号为例，能不能生成目录，就要看作者有没有专门设置标题，如果像某些公众号那样滥用样式，我也力有未逮。

有点深度的文章，当然配得上为它制作目录；而更俗气的文章，同样可以一用。我也会浏览一些购物推荐或盘点榜单，比如 Outdoor 杂志上的导购文章；此时我很清楚，这些网站遵循着超市的货架摆放法则，越是吸引眼球的东西摆得越靠前，要是按照文章顺序逐个浏览，很可能会给自己“种草”，往购物车里丢一堆不需要的商品。更好的办法是做一个目录，扫一眼这周又有哪些新品推荐——公平竞争，不带图片！——只有感兴趣的产品，我才会点击目录进一步查看。现在漂亮的传单和能够轰掉脑袋的广告铺天盖地，但是产品目录则在消费市场上销声匿迹，大概是因为目录会暴露太多信息、给客户太多主动权，从而引起商家不快吧。

## 小结

古谚有云，网有纲，裘有领，目录者，纲领也。尽管网页文章通常篇幅不大，近年来还流行在标题下标榜几分钟就能读完，但毕竟不如直接把目录示人，让读者自己判断要不要读或读哪些部分，所谓丰俭由人。对于好文章，目录是导航手册，指示游览的方向；遇到坏文章，目录就是透视镜，一把扯掉标题党的皇帝新衣——尤其是“你不知道的xx个xx技巧”“我们最近买的xx个好物”这种文章，一旦挂上目录，就能避免通篇阅读、吃到臭鸡蛋。

这篇文章受 Simple Outliner 的功能启发，但受限于个人水平，只能拼拼凑凑造出一个哈尔移动城堡一样的工具，估计远不如人家优雅。但好在本文方案很容易改造，并不需要任何 Safari 专用组件，移植到其他浏览器——甚至手机浏览器——都有可能。吾辈生而有涯，暂时就走到抛出砖头的这一步吧，不求引玉，但求激起些许水花。

---

[前往标准阅读页](https://utgd.net/article/9829?audience=web)
