Pandoc Lua 过滤器结构
Lua 过滤器是表格结构,元素名称作为键,值则是对这些元素进行操作的函数。
过滤器应放在单独的文件中,并通过 --lua-filter
命令行参数传递。例如,如果一个过滤器定义在名为 current-date.lua
的文件中,则应用该过滤器的方式如下:
pandoc --lua-filter=current-date.lua -f markdown MANUAL.txt
--lua-filter
选项可以多次提供。Pandoc 会按照命令行中出现的顺序应用所有过滤器(包括通过 --filter
指定的 JSON 过滤器和通过 --lua-filter
指定的 Lua 过滤器)。
Pandoc 期望每个 Lua 文件返回一系列过滤器列表。该列表中的过滤器按顺序被调用,每个过滤器处理前一个过滤器的结果。如果没有值由过滤脚本返回,那么 Pandoc 将尝试生成一个单一的过滤器,通过收集所有顶层函数来实现,这些函数的名称与 Pandoc 元素( 如 Str
、Para
、Meta
或 Pandoc
)的名称相对应。(这就是为什么上面两个例子等价的原因。)
对于每个过滤器,文档会被遍历,每个元素都会被过滤器处理。对于过滤器包含条目的元素(即具有同名函数的元素),它们会被传递给 Lua 元素过滤器函数。换句话说,对于文档中的每个相应元素,过滤器条目都会被调用,并将相应的元素作为输入。
过滤器函数的返回值必须是以下之一:
nil
:这意味着对象应该保持不变。- 一个 Pandoc 对象:这必须与输入类型相同,并且将替换原始对象。
- Pandoc 对象的列表:这些将替换原始对象;列表将与原始对象的邻居合并(插入到原始对象所属的列表中);返回空列表将删除对象。
过滤器函数的输出必须产生与输入相同类型的元素。这意味着作用于内联元素的过滤器函数必须返回 nil
、一个内联元素或内联元素列表,而过滤块元素的函数必须返回 nil
、一个块元素或块元素列表。如果违反此条件,Pandoc 将抛出错误。
如果没有匹配元素节点类型的函数,则过滤系统将查找更通用的回退函数。支持两种回退函数,Inline
和 Block
。每个都匹配相应类型的元素。
没有匹配函数的元素保持不变。
请参阅 模块文档 以获取 Pandoc 元素列表。
元素序列的过滤器
对于某些过滤任务,需要知道元素在文档中出现的顺序。仅检查单个元素是不够的。
有两种特殊函数名可用于定义内联列表或块列表上的过滤器。
- Inlines (inlines):如果出现在过滤器中,此函数将被调用在所有内联元素列表上,例如 Para(段落)块的内容或 Image 的描述。传递给函数的
inlines
参数将是每次调用的 内联元素 列表。 - Blocks (blocks):如果出现在过滤器中,此函数将被调用在所有块元素列表上,例如 MetaBlocks 元元素块的内容、列表中的每一项以及 Pandoc 文档的主要内容。传递给函数的
blocks
参数将是每次调用的 块元素 列表 。
这些过滤器函数是特殊的,因为结果必须是 nil
,在这种情况下列表保持不变,或者必须是正确类型的列表,即与输入参数相同的类型。不允许单个元素作为返回值,因为在这种上下文中通常意味着有 bug。
请参阅 “删除正常引用前的空格” 以获取示例。
此功能已在 Pandoc 2.9.2 中添加。
遍历顺序
可以通过设置键 traverse
为 'topdown'
或 'typewise'
来选择过滤器的遍历顺序;默认值为 'typewise'
。
示例:
local filter = {
traverse = 'topdown',
-- ... 过滤器函数 ...
}
return {filter}
此支持在 Pandoc 2.17 中添加;先前版本忽略 traverse
设置 。
按类型遍历
过滤器集内的元素过滤器函数以固定顺序被调用,跳过任何不存在的函数:
仍然可以通过显式返回多个过滤器集来强制不同的顺序。例如,如果希望Meta的过滤器在Str之前运行,可以编写:
-- ... 过滤器定义 ...
return {
{ Meta = Meta }, -- (1)
{ Str = Str } -- (2)
}
过滤器集按返回的顺序应用。因此,(1) 中的所有函数都在 (2) 之前运行,导致Meta的过滤器函数在开始过滤Str元素之前运行。
从上至下的遍历
有时,从根到叶的深度优先遍历文档树,并且在单次运行中完成会更加自然。
例如,一个块列表 [Plain [Str "a"], Para [Str "b"]]
将尝试按以下顺序应用过滤器函数:Blocks
、Plain
、Inlines
、Str
、Para
、Inlines
、Str
。
顶向下的遍历可以通过在过滤器函数中返回 false
作为第二个值来提前终止。在这种情况下,返回元素的任何子元素都不会被处理。
例如,要排除脚注的内容不被处理,可以编写如下内容:
traverse = 'topdown'
function Note(n)
return n, false
end
全局变量
Pandoc 通过设置全局变量向 Lua 过滤器传递额外的数据。
FORMAT
全局变量
FORMAT
设置为使用的 Pandoc 写入器格式(如html5
、latex
等),因此过滤器的行为可以根据最终输出格式进行条件判断。PANDOC_READER_OPTIONS
提供给解析器的选项表。( 类型为 ReaderOptions )
PANDOC_WRITER_OPTIONS
将传递给写入器的选项表。虽然对象可以修改,但这些更改不会被 Pandoc 捕获。( 类型为 WriterOptions )
在 自定义写入器 中访问此变量已 废弃。从 Pandoc 3.0 开始,在自定义写入器中它被设置为占位符值(默认选项)。实际写入器选项是通过
Writer
或ByteStringWriter
函数提供的,这些函数将选项作为第二个函数参数传递。自 Pandoc 2.17 版本起
PANDOC_VERSION
包含 Pandoc 的版本号作为一个 Version 对象,该对象像数值索引表一样工作,最显著的数字排在前面。例如,对于 Pandoc 2.7.3,变量的值等同于表
{2, 7, 3}
。使用tostring(PANDOC_VERSION)
来生成版本字符串。此变量也在自定义写入器中设置。PANDOC_API_VERSION
包含 Pandoc 编译时所针对的 pandoc-types API 的版本。它是一个数值索引表,最显著的数字排在前面。例如,如果 Pandoc 是基于 pandoc-types 1.17.3 编译的,则变量的值将等同于表
{1, 17, 3}
。使用tostring(PANDOC_API_VERSION)
来生成版本字符串。此变量也在自定义写入器中设置。PANDOC_SCRIPT_FILE
调用过滤器所用的文件名。此值可用于相对于脚本文件查找其他文件。此变量也在自定义写入器中设置。
PANDOC_STATE
所有读取器和写入器共享的状态。Pandoc 使用它来收集和传递信息。此变量的值类型为 CommonState 并且只读。
pandoc
通过全局变量
pandoc
可获得pandoc
模块,该模块在下一节中描述。本文档中描述的其他模块则作为各自名称下的子字段加载。lpeg
此变量持有
lpeg
模块,这是一个基于解析表达式文法 (PEG) 的包。它提供了优秀的解析工具,并在官方 LPeg 主页 上进行了文档说明。Pandoc 使用内置的库版本,除非包维护者配置了依赖系统范围内的安装。注意
require 'lpeg'
的结果不一定等于这个值;require
机制更倾向于使用系统的lpeg
库而不是内置版本。re
包含基于 LPeg 的 LPeg.re 模块,提供了一个 正则表达式引擎 的实现。Pandoc 使用内置的库版本,除非包维护者配置了依赖系统范围内的安装。
注意
require 're'
的结果不一定等于这个值;require
机制更倾向于使用系统的lpeg
库而不是内置版本。