Pandoc Lua 过滤器

引言

Pandoc 长期以来都支持过滤器,这些过滤器可以在解析和写入阶段之间操纵 Pandoc 抽象语法树 (AST)。传统的 Pandoc 过滤器 接受 Pandoc AST 的 JSON 表示,并生成修改后的 AST 的 JSON 表示。这些过滤器可以用任何编程语言编写,并通过 --filter 选项从 Pandoc 中调用。

尽管传统的过滤器非常灵活,但它们也有一些缺点。首先,在标准输出上写入 JSON 和从标准输入读取 JSON 有一些开销(两次,过滤器的每一侧一次)。其次,过滤器能否工作取决于用户的环境细节。过滤器可能需要特定编程语言的解释器可用,以及用于操纵 JSON 形式的 Pandoc AST 的库。你不能简单地提供一个可以被拥有某个版本 Pandoc 可执行文件的任何人使用的过滤器。

从版本 2.0 开始,Pandoc 允许无需任何外部依赖就能用 Lua 编写过滤器。Lua 解释器(版本 5.4)和用于创建 Pandoc 过滤器的 Lua 库被内置到 Pandoc 可执行文件中。Pandoc 数据类型直接映射到 Lua,避免了通过管道写入 JSON 和从管道读取 JSON 的开销。

下面是一个 Lua 过滤器的例子,它将强烈强调转换为小写斜体:

return {
  {
    Strong = function (elem)
      return pandoc.SmallCaps(elem.content)
    end,
  }
}

或者等价地,

function Strong(elem)
  return pandoc.SmallCaps(elem.content)
end

这表示:遍历 AST,当你找到一个 Strong 元素时,用相同内容的小写斜体元素替换它。

要运行它,将其保存在一个文件中,比如 smallcaps.lua,然后使用 --lua-filter=smallcaps.lua 调用 Pandoc。

这里有一个快速的性能比较,将 Pandoc 手册(MANUAL.txt)转换为 HTML,使用了用编译过的 Haskell (smallcaps) 和解释型 Python (smallcaps.py) 编写的同一 JSON 过滤器的不同版本:

命令 时间
pandoc 1.01s
pandoc --filter ./smallcaps 1.36s
pandoc --filter ./smallcaps.py 1.40s
pandoc --lua-filter ./smallcaps.lua 1.03s

如你所见,Lua 过滤器避免了通过管道进行 JSON 序列化和反序列化的大量开销。

在本文档中