在博客中使用 BibTeX

8 月 19 日更新:一些关于 a11y 和排版方式的 内容 已经变化。20 日更新:加入了 新样式。2020 年 2 月 13 日更新:为过窄的页面设计了一个新的布局。

在博客中使用 BibTeX 的需求起源于一些需要引用文献的博文。例如之前的 NC¹ 属性加密 KW19,那时候我是手工格式化参考文献的。当然,能自动化就不要手工去做,于是几个月前开始了 BibTeX-TS——TypeScript 写的 BibTeX 解析器。现在设施已经足够完备,我可以把 alpha.bst 的实现近似翻译到 JavaScript 里,成为博客构建系统的一部分。位图版的题图(BibTeX 徽标)衍生自 Wikimedia Commons。

BibTeX-TS 和博客工具链

BibTeX-TS 的需求脱胎于我对 blogging 工具链的要求,不过它是一个一般向的项目。主要功能是把 .bib 文件解析为结构化的对象并加以操作。

整个过程花了几个月,从西雅图到北京,我在研究的空余时间(或者说研究累了需要换换脑筋)慢慢完成。中间有两次推倒重来的过程:第一次没有记录在 git 的历史里,第二次可以在 git 的历史中找到。

在西雅图的时候主要写了基本对象模型、解析器和 BST 语言的基本函数(例如 purify$ 用于清理字符串、format.name$ 用于格式化名字),几个比较有意思的:

  • 由于面向对象的引入,一些 BST 函数被分成了几步,譬如 format.name$ 本来是接受两个字符串和一个整数(一堆名字、一个名字格式和第几个名字)输出一个字符串(格式化好的那个名字),在 BibTeX-TS 里分成把字符串解析成名字、把字符串解析成名字格式、用名字格式格式化名字三部分。
  • 我发现了一个新的写 parser 的模式——用下一个状态转移的委托(函数指针)表示状态,例如 .bib 解析器 就是这样写出来的。
  • 我看了很多遍 Déc07Mar09,这两篇文档详尽地解释了 BibTeX 的细节(比 bibtex.org 清楚多了)。很多细节都是值得注意的,还有一部分细节是过时的(例如 purify$ 也会删除所有非 ASCII 字符,这对汉语文献非常不友好,虽然可能并不需要引用很多汉语文献),我希望和原版尽量接近,但也有选择性。

在北京做的部分是实现简易 TeX 渲染框架并实例化框架、着手翻译 alpha.bst 的实现(我翻译的方法就是盯着它并把它的每个类型的渲染函数翻译一遍;实际上很容易写一个 BST 解析器和解释器,毕竟基础设施已经有了,而且 BST 是一个非常容易模拟的语言),见于 此(当然这个实现和 alpha.bst 是有出入的,例如我没有对文章标题做 title case 转换,因为很多人根本不会写 BibTeX 文件,按照 alpha.bst 的程序渲染出来的结果乱七八糟)。还有就是(我已经轻车熟路的)实现 BibTeX-TS 和博客工具链之间的胶水,以及稍微更新一下实现用 Markdown 行内代码 `cite:key1,key2` 语法做文内引用、用代码块 ```blog-bib 语法做 BibTeX 渲染,以及把锚记跳转 hook 起来。

整个过程的结果就是我的博客以后可以用 BibTeX 自动格式化参考文献,以及手有点抽筋儿。

自定义样式

可以用 @string { property = {value} } 自定义样式:

设置 属性 取值(第一个为默认)
BibTeX 样式 bst alpha、plain、abbrv
引用周围的括号 brackets []、()
多个引用的分隔符 comma ,、;
分隔符后空白大小 space thin、normal、none
昵称列格式 nickname cite、[]、.
昵称列对齐 align right、left
语言 lang 任意

其中,若 nickname 值为 cite,则根据 brackets 推断:如果 brackets 是 [],则 nickname 取 [];如果 brackets 是 (),则 nickname 取 .。align 仅对足够宽的页面生效。lang 属性用于设置参考文献 div 的 lang 属性,如果没有则不设置。修改上述属性的例子见 Blogging my blog。

例子

本文本身就是一个例子,文中的 BibTeX 都可以直接从官网复制而不加修改(当然我实际上修改了一些让渲染结果更适合 Web)。几个有意思的特性:

  • 所有的功能都是静态的,客户端不需要 JavaScript。
  • 支持 crossref 交叉引用(这是标准样式的一部分),作为引用文章描述文字的 TeX 代码中包含的 \cite 也会被处理,例如 KW19 的描述文字里有一个对 IR19 的引用。
  • 多次引用同一篇文章,每次的引用都有自己的身份,因此点击引用的链接后可以通过“返回”链接重新回到正确的位置。例如 Dam92 和 Dam92。
  • 可以一次引用多篇文章,例如 GSW13QWW18CDG⁺17。
  • 为了支持汉语文章的渲染,我添加了两个新的 TeX 控制序列 \nickname 和 \zhCN。前者只有在渲染文章昵称(首字母)时才渲染当前分组内的后续内容,否则不渲染;后者把该分组内后续内容渲染为带有汉语语言标记的 HTML。如果作者名字写 {\nickname L}{\nickname i}{\nickname}{\nickname\bgroup}{ }{\egroup\egroup\bgroup\zhCN 李雷},则渲染结果是 Li19。前面三个 \nickname 控制序列是为了确保提取文章昵称的时候得到 Li,后面通过巧妙的组合使得 purify$ 整个字符串的时候得到的是 Li 李雷(最长的拼音音节可以有 6 个字符,对齐是为了排序),并且通过 \nickname 控制序列确保 Li 不会被渲染。
  • 如果你在 LaTeX 里 \cite{key1,key2} 且选择逗点后不加空格,则 LaTeX 似乎不允许在一个 \cite 控制序列产生的中括号内换行(至少 LLNCS 是这样的),我觉得必要时逗点后换行比较合理。这个问题和逗点后没有空格是联动的,大概是 LaTeX 认为没有后面空格的逗点是小数(逗)点,所以禁止换行——然而这在一些情况下的排版结果简直惨不忍睹。
    • LaTeX 里的解决方法是在 , 后面加上 \hspace{0pt}。
    • 在我的 blog 里,为了解决上面这个问题,同时为了更好的 accessibility,我把 [,] 包裹在 span 里,并且设置 aria-hidden="true",且在逗点的 span 里放置一个内部是空格的 span,它的字体大小由需要的空格的大小控制。这篇文章选择的空格样式是“无空格”,实际的实现里是有一个字号为 0 的空格。举个例子:“Gro11DLO⁺18。”按照简体中文排版规则外加“允许引用内逗点后断行”,前面这句话可以断行的地方是:“举”“个”“例”周围、冒号后、逗点后、右引号后。
    • 有趣的实际评测:Edge 44.17763.1.0、Safari for iOS 12.4、Safari for macOS 10.14.6、Chrome 73.0.3683.103 for Windows (x64) 似乎都认为冒号后、右引号后不可以断行;Chrome 76.0.3809.100 for Windows (x64) 允许冒号后、右引号后断行。
  • 一个美中不足的地方是每个 `cite:key` 产生的 a 标签的 ID 是依据“这是第几次 cite 这个 key”产生的,这导致文章修改后链接的 ID 可能变化,对书签不友好。这是技术难度、书写难度和效果之间的权衡——要么我需要人工智能来指定一个比较稳定的 ID,要么我需要每次手工指定 ID(这太麻烦了),要么我选择放弃书签稳定性。我选择了放弃书签稳定性。
  • 除了 Li19,这篇文章用到的例子文献都是我读过的😄。

References

Here’s the list of references (this sentence is rendered using @preamble{ ... }).
CDG⁺17 ↩ Chongwon Cho, Nico Döttling, Sanjam Garg, Divya Gupta, Peihan Miao, and Antigoni Polychroniadou. Laconic Oblivious Transfer and its Applications. Cryptology ePrint Archive, Report 2017/491, 2017. https://eprint.iacr.org/2017/491.
Dam92 ↩↩ Ivan Damgård. Towards Practical Public Key Systems Secure Against Chosen Ciphertext attacks. In Joan Feigenbaum, editor, Advances in Cryptology — CRYPTO ’91, pages 445–456, Berlin, Heidelberg, 1992. Springer Berlin Heidelberg.
Déc07 ↩ Xavier Décoret. A summary of . Online, 2007.
DLO⁺18 ↩ Ivan Damgård, Ji Luo, Sabine Oechsner, Peter Scholl, and Mark Simkin. Compact Zero-Knowledge Proofs of Small Hamming Weight. In Michel Abdalla and Ricardo Dahab, editors, Public-Key Cryptography – PKC 2018, pages 530–560, Cham, 2018. Springer International Publishing.
Gro11 ↩ D. Gross. Recovering Low-Rank Matrices From Few Coefficients in Any Basis. IEEE Transactions on Information Theory, 57(3):1548–1566, March 2011.
GSW13 ↩ Craig Gentry, Amit Sahai, and Brent Waters. Homomorphic Encryption from Learning with Errors: Conceptually-Simpler, Asymptotically-Faster, Attribute-Based. Cryptology ePrint Archive, Report 2013/340, 2013. https://eprint.iacr.org/2013/340.
IR19 ↩↩ Yuval Ishai and Vincent Rijmen, editors. Advances in Cryptology - EUROCRYPT 2019 - 38th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Darmstadt, Germany, May 19-23, 2019, Proceedings, Part I, volume 11476 of Lecture Notes in Computer Science, Springer, 2019.
KW19 ↩↩ Lucas Kowalczyk and Hoeteck Wee. Compact Adaptively Secure ABE for from -Lin. In Advances in Cryptology - EUROCRYPT 2019 - 38th Annual International Conference on the Theory and Applications of Cryptographic Techniques, Darmstadt, Germany, May 19-23, 2019, Proceedings, Part I IR19, pages 3–33.
Li19 ↩↩ 李雷. 一个例子. August 2019. 这是一个虚构的参考文献.
Mar09 ↩ Nicolas Markey. Tame the BeaST, 2009. See CTAN package and PDF.
QWW18 ↩ Willy Quach, Hoeteck Wee, and Daniel Wichs. Laconic Function Evaluation and Applications. Cryptology ePrint Archive, Report 2018/409, 2018. https://eprint.iacr.org/2018/409.

请启用 JavaScript 来查看由 Disqus 驱动的评论。