Pandoc 的 Org-mode 阅读器完全指南:导出选项、表格、强调规则与扩展兼容性
Pandoc 的 Org-mode 阅读器完全指南导出选项、表格、强调规则与扩展兼容性【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandocPandoc 作为通用标记语言转换器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:等才会进入 HTMLtitle与meta区域不带-s时只输出正文片段。三、格式特定选项Format-specific OptionsEmacs 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_head、html_head_extra、latex_header、latex_header_extra均通过metaExportSnippet生成rawInline后collectAsList累积为header-includes元数据列表latex_class映射到documentclasslatex_class_options会过滤掉[]字符后映射到classoptionsubtitle则走lineOfInlinescollectLines。四、Pandoc 特有选项Pandoc-specific Options以下选项是 Emacs Org 不识别、由 Pandoc 额外支持的关键字说明NOCITE将列出的引用加入参考文献而无需在正文中提及。特殊值*会把所有可用引用加入参考文献HEADER-INCLUDES类似HTML_HEAD和LATEX_HEADER但把选项值当作带标记的普通文本处理INSTITUTE作者所属机构值按带标记文本读取存入institute元数据字段。该字段默认出现在 beamer 演示文稿的标题页上从源码看nocite走lineOfInlinescollectLines对应 Meta.hsinstitute也走同样的行内文本路径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 keyvalue。自 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) -- Dont 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 documents metadata. function Meta (meta) for name, value in pairs(variables) do meta[name] value end return meta end使用方式filter 保存为如directives-to-meta.luapandoc -f org -t html -s --lua-filterdirectives-to-meta.lua input.orgLua filter 的完整编写规范可参考 doc/lua-filters.md。六、表格TablesPandoc 支持普通 Org 表格有时称为 pipe tables即用|分隔单元格的表格grid tables由 table.el 创建的表格即用---边框线绘制的表格。在 BlockStarts.hs 中可以看到对应的起始解析器tableStart匹配|gridTableStart匹配后跟-。6.1 列宽Column widthsOrg-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 RulesOrg-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 零宽空格强调允许的换行数为 1emphasisAllowedNewlines 1解析结束字符时会检查后置字符集合orgStateEmphasisPostChars与当前强调字符栈Inlines.hs。八、smart扩展与特殊字符串Org-mode 允许通过特殊字符序列插入某些字符。例如省略号键入...代替 Unicode 省略号…破折号--表示 en dash–---表示 em dash—引号与撇号可以按 smart 方式处理替换为语言特定的 Unicode 引号字符。8.1 与 Markdown 的差异与 Markdown 一样可以通过启用smart扩展一次性打开所有这些行为。然而禁用smart默认状态并不会必然禁用 smart 引号和特殊字符串——它只是退回到 Org-mode 的默认行为。从源码看ParserState.hsoptionsToParserState把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归档树处理ddrawers 列表支持(not ...)补集写法e实体f脚注p规划信息tags标签todoTODO 关键字|表格texLaTeX 片段t/nil/verbatim。布尔值遵循 elisp 语义只有nil、{}、()视为假其余非空值视为真ExportSettings.hs。未识别的设置项会触发UnknownOrgExportOption日志警告。九、fancy_lists扩展与字母序号列表Org-mode 有变量org-list-allow-alphabetical设为t时允许使用单字符字母作为有序列表标记。由于该变量默认为nilPandoc 中可以通过启用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/DefaultDelimfancy 时额外允许lowerAlpha与upperAlpha单字母标记并将.解析为Period、)解析为OneParen风格起始序号可由[n]计数器 cookie 指定listCounterCookie见 BlockStarts.hs默认从 1 开始。启用方式pandoc -f orgfancy_lists -t latex input.org十、当前不支持的特性Library of BabelLibrary of babel巴别图书馆用于在多种编程语言之间翻译执行代码块这超出了 Pandoc 的职责范围原文 out-of-scope for pandoc。官方建议的工作流是使用 Emacs 运行代码然后把得到的 org 文件喂给 Pandoc。十一、关于标题层级Headline Levels的常见困惑原文档专门提示了一个常见误解对应历史 issueOrg-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),仅供参考