Pandoc 的 Org-mode 阅读器完全指南:导出选项、表格、强调规则与扩展兼容性
2026/9/19 20:06:07 网站建设 项目流程

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 特有选项、表格处理、强调规则自定义、smartfancy_lists扩展,以及当前尚不支持的 Org 特性,并结合 src/Text/Pandoc/Readers/Org/ 下的真实解析器源码与测试用例,帮助你准确掌握 Pandoc 处理 Org 文档的行为边界,避免踩坑。

读完本文,你将能够:区分"Pandoc 已支持 / 行为与 Emacs 有差异 / 完全不支持"三类 Org 导出关键字;用#+OPTIONS精确控制解析行为;通过 Lua filter 恢复未知指令为元数据;自定义强调字符边界;正确使用smartfancy_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,除非在命令行选项中指定目标

从源码看,AUTHORDATETITLE等走的是lineOfInlines解析路径(即把值当作带标记的行内内容解析),而EMAILLANGUAGE走的是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_CLASSLaTeX 文档类;与 Org-mode 一致,默认类为article。内容作为纯文本存入documentclass元数据
LATEX_CLASS_OPTIONSLaTeX 文档类的选项;完全支持。内容作为纯文本存入classoption元数据
SUBTITLE文档副标题;完全支持。内容作为行内元素存入subtitle元数据
HTML_HEAD/HTML_HEAD_EXTRA追加到 HTML 文档<head>的任意行;完全支持。内容以"原始 HTML 行列表"存入header-includes元数据

源码佐证:在 Meta.hs 中,html_headhtml_head_extralatex_headerlatex_header_extra均通过metaExportSnippet(生成rawInline)后collectAsList累积为header-includes元数据列表;latex_class映射到documentclasslatex_class_options会过滤掉[]字符后映射到classoptionsubtitle则走lineOfInlines+collectLines

四、Pandoc 特有选项(Pandoc-specific Options)

以下选项是 Emacs Org 不识别、由 Pandoc 额外支持的:

关键字说明
NOCITE将列出的引用加入参考文献,而无需在正文中提及。特殊值@*会把所有可用引用加入参考文献
HEADER-INCLUDES类似HTML_HEADLATEX_HEADER,但把选项值当作带标记的普通文本处理
INSTITUTE作者所属机构;值按带标记文本读取,存入institute元数据字段。该字段默认出现在 beamer 演示文稿的标题页上

从源码看,nocitelineOfInlines+collectLines(对应 Meta.hs),institute也走同样的行内文本路径(Meta.hs)。

五、未列出的选项:保留为 Raw Block,可用 Filter 处理

任何未在上面列出的导出选项或指令,在 Pandoc 解析时不产生直接效果,但信息不会丢失——它们会被保留为格式为orgraw block。这意味着:

  1. 可以通过 doc/filters.md(过滤器)访问它们;
  2. 它们会被原样包含在 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.org

Lua 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),optionsToParserStateExt_smartExt_smart_quotes映射为exportSmartQuotes,把Ext_smartExt_special_strings映射为exportSpecialStrings,并且默认导出设置中exportSmartQuotes = FalseexportSpecialStrings = 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 时额外允许lowerAlphaupperAlpha单字母标记,并将.解析为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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询