一篇没有目录的文章,就像一场事先没有公布菜单的筵席,吃到后来云里雾里,完全不知道后面还有什么内容。而一旦握有目录,不仅能够掌握阅读节奏,而且在看到目录的那一刻,说不定还能判断一篇文章究竟值不值得读。
然而,传统书籍必备的目录,却没有成为网页文章的标准,读者根本不知道自己将读到什么,往往在惹了一身的臊味之后才知道文章在讲什么,这时候时间已经浪费了。李敖所谓臭鸡蛋闻闻就行,不用下嘴,苟无目录,则往往在下口甚至吞下肚子之后才知文章好坏。小到个人博客,大到大型网站,概莫能外。1
Chrome 浏览器上有个 Simple Outliner 插件,就旨在为网页生成目录;显然,这又到了 Safari——以及其他不支持 Chrome 插件的浏览器——眼红的时候。羡慕归羡慕,比起等待好心人开发 Safari 版本,不如自己动手制作一个;我不熟悉该插件所用的编程语言,但凭着可怜的网页开发知识,还是设计出了一套方案,并且打包到 Keyboard Maestro 中2,以便为本无目录的网页导航。
示例文章主要为 Eric Steven Raymond 的 Basics of the Unix Philosophy。
使用指津
有必要澄清,没有哪个方案该称自己支持所有网页,包括前文提及的 Simple Outliner 也力有未逮——当然,开发者懂得扬长避短,支持了 Inoreader 和 Feedly 两个重量级阅读服务。我将在下一节说明本文方案的原理,并指出其限制。所有 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,则会发现,虽然目录是生成了,但里面除了各层级的标题,还夹杂关联文章和作者、版权等信息。我们先不去争论版权部分该不该体现在目录中(这不是一个技术问题),显然关联文章是不该出现的,而它们之所以现身,就是因为我采取了最鲁棒的方法:检查网页上的所有标题,并将其纳入目录。万幸的是我们本身就有目录,大概不需要对本网站动手术。3
究其原理,我们在网页上看到的文字,都是由 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 专用组件,移植到其他浏览器——甚至手机浏览器——都有可能。吾辈生而有涯,暂时就走到抛出砖头的这一步吧,不求引玉,但求激起些许水花。