Pandoc 的 Org-mode 阅读器完全指南:导出选项、表格、强调规则与扩展兼容性
【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc
Pandoc 作为通用标记语言转换器(Universal markup converter),其 Org-mode 阅读器在行为上力求与 Emacs org-mode 保持一致。本文基于仓库中的官方说明文档 doc/org.md,系统梳理 Pandoc 解析 Org 文件时的导出选项(Export Keywords)、格式特定选项、Pandoc 特有选项、表格处理、强调规则自定义、smart与fancy_lists扩展,以及当前尚不支持的 Org 特性,并结合 src/Text/Pandoc/Readers/Org/ 下的真实解析器源码与测试用例,帮助你准确掌握 Pandoc 处理 Org 文档的行为边界,避免踩坑。
读完本文,你将能够:区分"Pandoc 已支持 / 行为与 Emacs 有差异 / 完全不支持"三类 Org 导出关键字;用#+OPTIONS精确控制解析行为;通过 Lua filter 恢复未知指令为元数据;自定义强调字符边界;正确使用smart与fancy_lists扩展。
一、总体定位:尽量兼容,但存在差异
Pandoc 对 Org 文件的处理与 Emacs org-mode 相似(原文表述为 "similar to that of Emacs org-mode"),本文档的目标就是指出那些"无法做到、或尚未做到"的地方。核心结论如下:
- 所有导出行关键字(Export keywords)会填充 Pandoc 的元数据(metadata)字段,因此通常需要使用
-s/--standalone选项生成带元数据的独立文档,这些关键字才会影响输出; - 部分关键字完全支持,部分仅被解析为元数据却未被默认模板使用,还有个别关键字(如
EXPORT_FILE_NAME)明确不支持; - 解析器对未知的
#+指令会保留为格式为org的 raw block,可以通过 filter 继续加工。
二、导出选项(Export Keywords)完整清单
以下关键字在 src/Text/Pandoc/Readers/Org/Meta.hs 的keywordHandlers表中逐一注册并分发处理。
| 关键字 | 支持状态 | 说明 |
|---|---|---|
AUTHOR | 完全支持 | 逗号分隔的作者列表 |
CREATOR | 部分支持 | 输出生成器;作为纯文本元数据creator传入,但默认模板不使用 |
DATE | 完全支持 | 创建或发表日期,Pandoc 支持良好 |
EMAIL | 部分支持 | 作者邮箱;作为纯文本元数据email传入,默认模板不使用 |
LANGUAGE | 部分支持 | 文档语言;作为纯文本元数据lang传入,值应为 BCP47 语言标签 |
SELECT_TAGS | 支持 | 用于选择导出子树的标签 |
EXCLUDE_TAGS | 完全支持 | 阻止子树被导出的标签 |
TITLE | 完全支持 | 文档标题 |
EXPORT_FILE_NAME | 不支持 | 目标文件名;输出默认到 stdout,除非在命令行选项中指定目标 |
从源码看,AUTHOR、DATE、TITLE等走的是lineOfInlines解析路径(即把值当作带标记的行内内容解析),而EMAIL、LANGUAGE走的是anyLine纯文本路径;SELECT_TAGS/EXCLUDE_TAGS则调用tagList解析器,并把结果写入解析器状态中的标签集合,供后续导出子树筛选使用。
关于-s/--standalone的补充
由于这些关键字"填充元数据字段",独立输出时才会体现在文档头。例如:
pandoc -f org -t html -s input.org这样#+TITLE:、#+AUTHOR:、#+DATE:等才会进入 HTML<title>与<meta>区域;不带-s时只输出正文片段。
三、格式特定选项(Format-specific Options)
Emacs Org-mode 支持仅对特定导出格式生效的选项。Pandoc 在解析时是**格式无关(format-agnostic)**的,即无论目标格式是什么,解析行为一致;与 Org-mode 的差异会在下表中注明。
| 关键字 | 行为与差异 |
|---|---|
DESCRIPTION | 文档描述;Pandoc 会把该值作为带标记的文本解析进description元数据字段(跟随 LaTeX 导出器的行为)。而 Org-mode 的 HTML 导出器把描述当纯文本处理。该字段默认模板不使用 |
LATEX_HEADER/LATEX_HEADER_EXTRA | 追加到文档 preamble 的任意行;与 Org-mode 不同,这些行不会插入到 hyperref 设置之前,而是接近 preamble 末尾。内容以"原始 LaTeX 行列表"形式存入header-includes元数据 |
LATEX_CLASS | LaTeX 文档类;与 Org-mode 一致,默认类为article。内容作为纯文本存入documentclass元数据 |
LATEX_CLASS_OPTIONS | LaTeX 文档类的选项;完全支持。内容作为纯文本存入classoption元数据 |
SUBTITLE | 文档副标题;完全支持。内容作为行内元素存入subtitle元数据 |
HTML_HEAD/HTML_HEAD_EXTRA | 追加到 HTML 文档<head>的任意行;完全支持。内容以"原始 HTML 行列表"存入header-includes元数据 |
源码佐证:在 Meta.hs 中,html_head、html_head_extra、latex_header、latex_header_extra均通过metaExportSnippet(生成rawInline)后collectAsList累积为header-includes元数据列表;latex_class映射到documentclass,latex_class_options会过滤掉[]字符后映射到classoption,subtitle则走lineOfInlines+collectLines。
四、Pandoc 特有选项(Pandoc-specific Options)
以下选项是 Emacs Org 不识别、由 Pandoc 额外支持的:
| 关键字 | 说明 |
|---|---|
NOCITE | 将列出的引用加入参考文献,而无需在正文中提及。特殊值@*会把所有可用引用加入参考文献 |
HEADER-INCLUDES | 类似HTML_HEAD和LATEX_HEADER,但把选项值当作带标记的普通文本处理 |
INSTITUTE | 作者所属机构;值按带标记文本读取,存入institute元数据字段。该字段默认出现在 beamer 演示文稿的标题页上 |
从源码看,nocite走lineOfInlines+collectLines(对应 Meta.hs),institute也走同样的行内文本路径(Meta.hs)。
五、未列出的选项:保留为 Raw Block,可用 Filter 处理
任何未在上面列出的导出选项或指令,在 Pandoc 解析时不产生直接效果,但信息不会丢失——它们会被保留为格式为org的raw block。这意味着:
- 可以通过 doc/filters.md(过滤器)访问它们;
- 它们会被原样包含在 Org 格式的输出中。
5.1 把指令恢复为元数据(Directives as Metadata)
以恢复 Pandoc 2.10 之前的旧行为为例:在 2.10 之前,未知关键字被当作变量定义,并加入文档元数据——在 org 文件中写#+key: value,等价于运行 pandoc 时加--metadata key=value。
自 Pandoc 2.10 起,每一行未被处理的#+开头的行,都会在内部被保留为格式为org的 raw block。该 block 可以被过滤器检查和加工。下面这段Lua filter可以把这些未被处理的行重新转换成元数据键值对:
-- intermediate store for variables and their values local variables = {} --- Function called for each raw block element. function RawBlock (raw) -- Don't do anything unless the block contains *org* markup. if raw.format ~= 'org' then return nil end -- extract variable name and value local name, value = raw.text:match '#%+(%w+):%s*(.+)$' if name and value then variables[name] = value end end -- Add the extracted variables to the document's metadata. function Meta (meta) for name, value in pairs(variables) do meta[name] = value end return meta end使用方式(filter 保存为如directives-to-meta.lua):
pandoc -f org -t html -s --lua-filter=directives-to-meta.lua input.orgLua filter 的完整编写规范可参考 doc/lua-filters.md。
六、表格(Tables)
Pandoc 支持:
- 普通 Org 表格(有时称为 "pipe tables",即用
|分隔单元格的表格); - grid tables(由 table.el 创建的表格,即用
+---边框线绘制的表格)。
在 BlockStarts.hs 中可以看到对应的起始解析器:tableStart匹配|,gridTableStart匹配+后跟-。
6.1 列宽(Column widths)
Org-mode 表格不允许单元格内换行,导致文本行可能非常长,导出(尤其是经 LaTeX 转 PDF)时表格容易超出页面宽度。源文本中的过长行通常靠设置列宽来隐藏,但默认的 Emacs 导出器会忽略该设置。
Pandoc 的行为与 Emacs 不同:它会利用列宽信息,在导出时调整表格列的大小,从而缓解超宽问题。
6.2 已知限制
尚不支持跨多列或多行的单元格(colspan / rowspan)。虽然 table.el 的 grid tables 支持行跨列与列跨行,Pandoc 内部结构自 2.10 起也支持,但Org 解析器尚未更新到支持的程度。对应的表格解析与测试位于 test/Tests/Readers/Org/Block/Table.hs。
七、强调规则(Emphasis Rules)
Org-mode 使用复杂的规则判断一个字符串是否代表强调文本。在 Emacs 中,这可以通过变量org-emphasis-regexp-components定制。这种变量模型与 Pandoc 的架构不太契合,因此 Pandoc 提供了特殊的行来修改这些值:
#+pandoc-emphasis-pre: "-\t ('\"{\x200B" #+pandoc-emphasis-post: "-\t\n .,:!?;'\")}[\x200B"上面两行描述的就是这两个变量的默认值。参数必须是合法的(Haskell)字符串;如果参数解析为字符串失败,则恢复默认值。
从源码看,默认值定义在 ParserState.hs 的defaultOrgParserState中,与文档所述一致;pandoc-emphasis-pre/pandoc-emphasis-post两个关键字的处理在 Meta.hs,通过emphChars解析器读取字符串,再用setEmphasisPreChar/setEmphasisPostChar更新解析器状态。
7.1 修改强调规则的作用范围
- 修改强调规则只影响特殊行之后的文档部分;
- 要让整个文档的解析行为都改变,这些特殊行必须是最早出现的行之一;
- 也可以只对选中的片段临时修改,再恢复默认值。下面这段示例中,
test会被当作强调文本,而文档其余部分仍按默认强调规则解析:
#+pandoc-emphasis-pre: "[" #+pandoc-emphasis-post: "]" [/test/] #+pandoc-emphasis-pre: #+pandoc-emphasis-post:注意:重置时使用空值(即恢复默认)。
7.2 强调标记的源码实现细节
在 Inlines.hs 中:
/→ 斜体emph(第 581 行附近);*→ 粗体strong;+→ 删除线strikeout;_→ 下划线underline;- 强调内部禁止出现在边界处的字符(
emphasisForbiddenBorderChars)为\t\n\r 零宽空格; - 强调允许的换行数为 1(
emphasisAllowedNewlines = 1); - 解析结束字符时,会检查后置字符集合
orgStateEmphasisPostChars与当前强调字符栈(Inlines.hs)。
八、smart扩展与特殊字符串
Org-mode 允许通过特殊字符序列插入某些字符。例如:
- 省略号:键入
...代替 Unicode 省略号…; - 破折号:
--表示 en dash(–),---表示 em dash(—); - 引号:
"与撇号'可以按 "smart" 方式处理,替换为语言特定的 Unicode 引号字符。
8.1 与 Markdown 的差异
与 Markdown 一样,可以通过启用smart扩展一次性打开所有这些行为。然而,禁用smart(默认状态)并不会必然禁用 smart 引号和特殊字符串——它只是退回到 Org-mode 的默认行为。
从源码看(ParserState.hs),optionsToParserState把Ext_smart或Ext_smart_quotes映射为exportSmartQuotes,把Ext_smart或Ext_special_strings映射为exportSpecialStrings,并且默认导出设置中exportSmartQuotes = False、exportSpecialStrings = True——这正解释了"禁用 smart 并不等于禁用特殊字符串"。
8.2 关闭特殊字符串的方法
特殊字符串特性可以通过#+OPTIONS: -:nil导出设置关闭。目前没有命令行标志直接控制这些特性。作为变通方案,可以使用大多数 shell 支持的过程替换(process substitution),在命令行上提供该选项行:
pandoc -f org <(printf "#+OPTIONS: -:nil\n") …8.3#+OPTIONS底层解析
#+OPTIONS的解析器实现在 ExportSettings.hs 中,支持一大批 Org 导出设置,例如:
^:上下标(t/nil/{});':smart 引号;*:强调文本;-:特殊字符串;\n:保留换行;H:标题最大层数(整数,默认 3,见下文);arch:归档树处理;d:drawers 列表(支持(not ...)补集写法);e:实体;f:脚注;p:规划信息;tags:标签;todo:TODO 关键字;|:表格;tex:LaTeX 片段(t/nil/verbatim)。
布尔值遵循 elisp 语义:只有nil、{}、()视为假,其余非空值视为真(ExportSettings.hs)。未识别的设置项会触发UnknownOrgExportOption日志警告。
九、fancy_lists扩展与字母序号列表
Org-mode 有变量org-list-allow-alphabetical,设为t时允许使用单字符字母作为有序列表标记。由于该变量默认为nil,Pandoc 中可以通过启用fancy_lists扩展来可选地打开字母标记。
9.1 字母标记与分隔符区分
启用fancy_lists后,Pandoc 还会解析以小写或大写字母开头的列表标记,例如a.和D)。与 markdown 中使用该扩展不同:
- 罗马数字或
#占位符不能用作标记,因为它们在 Org-mode 中不允许。
启用fancy_lists的另一个行为是:Pandoc 会区分.和)两种分隔符。这意味着,当把 Org 转换为 LaTeX 等格式时,Pandoc 会尊重你在 Org 文件中使用的分隔符类型,而不是总是使用导出格式的默认分隔符。
9.2 源码实现
在 BlockStarts.hs 的orderedListStart中:
fancy标志来自guardEnabled Ext_fancy_lists;- 非 fancy 时只允许十进制数字标记,且风格/分隔符为
DefaultStyle/DefaultDelim; - fancy 时额外允许
lowerAlpha与upperAlpha单字母标记,并将.解析为Period、)解析为OneParen风格; - 起始序号可由
[@n]计数器 cookie 指定(listCounterCookie,见 BlockStarts.hs),默认从 1 开始。
启用方式:
pandoc -f org+fancy_lists -t latex input.org十、当前不支持的特性:Library of Babel
Library of babel(巴别图书馆)用于在多种编程语言之间翻译执行代码块,这超出了 Pandoc 的职责范围(原文 "out-of-scope for pandoc")。官方建议的工作流是:使用 Emacs 运行代码,然后把得到的 org 文件喂给 Pandoc。
十一、关于标题层级(Headline Levels)的常见困惑
原文档专门提示了一个常见误解(对应历史 issue):Org-mode 将org-export-headline-levels默认设为 3(可通过#+OPTIONS: H:3配置),因此层级大于 3 的标题处理方式不同(例如第 4 级及更深标题不会被当作普通标题,可能被转换成编号列表等)。
Pandoc 的默认导出设置同样把exportHeadlineLevels设为 3(见 ParserState.hs 的defaultExportSettings),源码注释明确写着"更深标题会被转换为列表"。如果你希望 Pandoc 识别更深层级的标题,可以在 Org 文件中写入:
#+OPTIONS: H:5十二、测试与验证
Org 阅读器的测试覆盖了本文提到的绝大部分特性,便于你深入验证与学习:
- 测试入口:test/Tests/Readers/Org.hs(按 Inlines、Basic Blocks、Meta Information、Directives 分组);
- 元数据与指令:test/Tests/Readers/Org/Meta.hs、test/Tests/Readers/Org/Directive.hs;
- 行内与 smart 行为:test/Tests/Readers/Org/Inline.hs、test/Tests/Readers/Org/Inline/Smart.hs;
- 块级元素:test/Tests/Readers/Org/Block.hs,其中表格见 Block/Table.hs,标题见 Block/Header.hs。
结语
Pandoc 的 Org-mode 支持在"与 Emacs 兼容"与"自身解析模型"之间做了务实取舍:导出关键字大多映射到元数据,格式特定内容以 raw 形式进入header-includes,未处理指令保留为 raw block 并开放给 filter 二次加工;表格、强调规则、smart 与 fancy_lists 扩展则各有明确的行为边界。掌握本文梳理的对照清单,你在将 Org 文档接入 Pandoc 工作流时就能精准预判输出行为,并用#+OPTIONS、特殊行或 Lua filter 按需调整解析结果。
【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考