Pandoc 的 Haskell 库家族:解析支撑通用文档转换器的 20+ 个核心依赖
【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc
本文基于 doc/libraries.md(pandoc 作者 John MacFarlane 撰写的官方库清单),逐层剖析支撑 pandoc 这一通用标记语言转换器的全部 Haskell 库:从引文处理、Markdown 解析、数学转换,到模板渲染、语法高亮与 Lua 脚本引擎。读完本文,你将理解 pandoc 的模块化架构如何工作、每个库在转换链路中的职责,以及在 pandoc.cabal 中对应的版本约束与源码落点,为二次开发或独立复用这些库提供全景地图。
为什么 pandoc 是"库的家族"而非一个单体程序
pandoc 的定位不仅是命令行工具,更是一个 Haskell 库——pandoc.cabal 的包描述将其定义为 "a Haskell library for converting from one markup format to another"。为了支持从轻量标记(Markdown 各变体、reStructuredText、AsciiDoc、Org、djot)到 XML 格式(DocBook、JATS、TEI)、办公文档(Docx、ODT、RTF)乃至幻灯片与笔记本(ipynb)等数十种格式的双向转换,作者将可复用的底层能力拆分为一系列独立的 Hackage 库,pandoc 主包则通过build-depends将它们组装起来。
从 pandoc.cabal 的依赖声明可以看到,pandoc 3.11 直接依赖上述家族中的绝大部分库,并给出精确版本区间,例如:
citeproc >= 0.13.0.1 && < 0.14, commonmark >= 0.3 && < 0.4, commonmark-extensions >= 0.2.7.1 && < 0.3, commonmark-pandoc >= 0.3 && < 0.4, doclayout >= 0.5.0.3 && < 0.6, doctemplates >= 0.11 && < 0.12, emojis >= 0.1.5 && < 0.2, gridtables >= 0.1 && < 0.2, ipynb >= 0.2 && < 0.3, jira-wiki-markup >= 1.5.1 && < 1.6, skylighting >= 0.15 && < 0.16, skylighting-core >= 0.15 && < 0.16, texmath >= 0.13.2.2 && < 0.14, unicode-collation >= 0.1.1 && < 0.2, zip-archive >= 0.4.3.1 && < 0.5, typst >= 0.11.0.1 && < 0.12, djot >= 0.1.4.2 && < 0.2下面按功能域逐一展开每个库的职责与在仓库中的实现证据。
引文与参考文献:citeproc、rfc5051、unicode-collation
citeproc是 pandoc 引文系统的核心,负责使用 CSL(Citation Style Language)样式表处理引文与参考文献。文档中的定位是 "Citation processing using CSL stylesheets"。在 pandoc 源码中,src/Text/Pandoc/Citeproc.hs 导出的processCitations :: PandocMonad m => Pandoc -> m Pandoc是整条引文管线的入口函数,将元数据中的参考文献、引文键与 CSL 样式合并处理。仓库自带的 data/default.csl 与 citeproc/biblatex-localization 目录下的各语言.lbx.strings本地化文件(如 english、german、chinese 等),正是 citeproc 处理 BibTeX/BibLaTeX 本地化文案时加载的数据资源。
rfc5051与unicode-collation都用于排序。按官方描述,rfc5051 提供 "Simple unicode collation",明确标注 "used for citation sorting"——即引文列表的粗略排序;unicode-collation 则提供 "Proper Unicode collation (sorting)",即符合 Unicode 规范的完整排序算法。二者在 pandoc.cabal 中可见unicode-collation的直接依赖约束,而 rfc5051 更可能是经由 citeproc 传递引入的间接依赖。它们共同保证参考文献列表在不同语言字符集下按正确次序排列。
Markdown 与轻量标记解析:commonmark 三件套、djot、gridtables、jira-wiki-markup
文档将commonmark、commonmark-extensions、commonmark-pandoc三个库并列介绍,定位为 "Efficient, standards-compliant parser for commonmark and extensions",即高效且符合 CommonMark 规范、并支持其扩展语法的解析器:
commonmark:CommonMark 规范本身的高性能解析核心;commonmark-extensions:表格、脚注、任务列表、数学等 CommonMark 官方扩展;commonmark-pandoc:将 CommonMark AST 桥接为 pandoc 内部 AST 的适配层。
在仓库中,src/Text/Pandoc/Readers/CommonMark.hs 正是基于这套三件套实现commonmark输入格式读取器的文件,三者版本约束在 pandoc.cabal 中分别为0.3、0.2.7.1、0.3下限。
djot是 pandoc 作者主导的另一种轻量标记语法,该库提供 "Parser and renderer for djot light markup syntax"。仓库中的 src/Text/Pandoc/Readers/Djot.hs 与 src/Text/Pandoc/Writers/Djot.hs 分别承载 djot 的读取与输出能力。
gridtables提供 "Support for parsing grid style textual tables",即 Markdown/文本中的网格型表格解析。这类表格在 pandoc 的表格测试套件 test/tables 下有大量 golden 用例(如tables.markdown、tables.rst),而网格表格正是 reStructuredText 与某些 Markdown 方言的常见表式。
jira-wiki-markup提供 "Support for parsing Jira wiki syntax"。对应仓库中的 src/Text/Pandoc/Readers/Jira.hs 读取器,使 pandoc 能把 Jira 的 wiki 语法文档转换为标准格式。
数学与排版:texmath、typst、typst-symbol
texmath是 pandoc 数学能力的核心,负责 "Conversion of math between tex, Word equation, MathML, and GNU eqn"。也就是说,它把 TeX 数学公式转换为 Word OMML 公式、MathML、roff eqn 等表示,反之亦然。pandoc 的数学输入输出(如tex_math_dollars扩展、LaTeX/HTML 输出中的公式渲染)最终都汇聚于此,版本约束为>= 0.13.2.2 && < 0.14(pandoc.cabal)。
typst库负责 "Parsing and evaluating typst syntax",即解析并求值 Typst 排版语言的语法;typst-symbol则提供 "Symbol and emoji lookup for typst language",即 Typst 符号名与 emoji 的查表转换。二者支撑 pandoc 的 Typst 输入(src/Text/Pandoc/Readers/Typst.hs、src/Text/Pandoc/Readers/Typst/Math.hs)与输出(src/Text/Pandoc/Writers/Typst.hs),以及 data/templates/default.typst 与 data/templates/template.typst 等模板资源。
模板与文档布局:doctemplates、doclayout
doctemplates直接 "Supports pandoc's templates"。pandoc 的全部输出格式都依赖模板机制:仓库 data/templates 目录下存放着default.latex、default.html5、default.epub3、default.docx(openxml)等数十份默认模板,源码侧的 src/Text/Pandoc/Templates.hs 以及 CLI 中 src/Text/Pandoc/App/CommandLineOptions.hs 对Text.DocTemplates的Context/Val类型操作,都是该库的消费方。版本约束为>= 0.11 && < 0.12(pandoc.cabal)。
doclayout提供 "Combinators for laying out a textual document, with support for line wrapping, tabular layout, and more"——即面向纯文本排版的组合子,支持自动换行、表格对齐等。它被 LaTeX、roff、ConTeXt 等基于文本的 writer 大量使用;例如 src/Text/Pandoc/Citeproc/BibTeX.hs 就导入了Text.DocLayout的literal、hsep、nest、hang、Doc等构造器来排版 BibTeX 输出。
语法高亮:skylighting-core 与 skylighting
文档将skylighting-core与skylighting并列介绍:前者是底层的高亮引擎与语法定义核心,后者在其上构建面向用户的完整接口,共同构成 "Syntax highlighting engine supporting over 140 languages"(支持超过 140 种语言的语法高亮引擎)。pandoc 的代码块高亮(--highlight-style选项、highlighting相关扩展)正是由其驱动:
- src/Text/Pandoc/Highlighting.hs 直接
import Skylighting; - src/Text/Pandoc/App/OutputSettings.hs 使用
Skylighting.defaultSyntaxMap与Skylighting.Parser.parseSyntaxDefinition解析用户自定义语法定义; - src/Text/Pandoc/Options.hs 在选项类型中引用
SyntaxMap与defaultSyntaxMap。
两个库的版本约束均为>= 0.15 && < 0.16(pandoc.cabal)。
Lua 脚本引擎生态:hslua 系列
pandoc 的过滤器(filter)、自定义 reader/writer 都依赖 Lua 运行时。官方文档列出的 hslua 家族各司其职:
- hslua-aeson:将 aeson 数据类型转换为 Lua 对象,让 JSON 数据在 Lua 脚本中可操作;
- hslua-cli:提供模仿默认
lua可执行文件的命令行接口,用于交互式调试与独立脚本执行; - hslua-module-doclayout:把上文 doclayout 库以 Lua 模块形式暴露,使 Lua 过滤器也能做文本排版(pandoc-lua-engine/pandoc-lua-engine.cabal 约束为
>= 1.2 && < 1.3); - hslua-module-path / -system / -text / -version:分别将 Haskell 的路径处理、系统交互、文本处理与版本信息等基础库能力暴露给 Lua;
- hslua-objectorientation 与 hslua-packaging:提供"面向对象"接口的绑定、包装与辅助函数,让 Lua 能以 OO 风格访问 Haskell 数据类型。
这些库的依赖关系集中在 pandoc-lua-engine/pandoc-lua-engine.cabal(hslua >= 2.5 && < 2.6、hslua-module-path、hslua-module-system、hslua-module-text、hslua-module-version、hslua-module-zip等),仓库中的 pandoc-lua-engine/src/Text/Pandoc/Lua 模块树即为该引擎的实现主体。pandoc 的 Lua 使用文档可参考 doc/lua-filters.md 与 doc/custom-readers.md。
文档容器与杂项:ipynb、zip-archive、emojis
ipynb提供 "Representation of Jupyter notebooks and conversion to and from JSON",即 Jupyter 笔记本的数据模型及其与 JSON 的双向转换。pandoc 对.ipynb的读写(src/Text/Pandoc/Readers/Ipynb.hs、src/Text/Pandoc/Writers/Ipynb.hs)均建立在该库之上,版本约束>= 0.2 && < 0.3(pandoc.cabal)。
zip-archive是 "A pure zip file creator and extractor, used by pandoc for docx, ODT, and EPUB"。docx、ODT、EPUB 本质上是 zip 容器,pandoc 通过该库完成这些格式的打包与解包;src/Text/Pandoc/Readers/Docx/Parse.hs、src/Text/Pandoc/Readers/ODT/ContentReader.hs、src/Text/Pandoc/Writers/EPUB.hs 等模块均会触及 zip 读写逻辑,而参考文档容器模板则存放在 data/docx、data/odt、data/pptx 目录。
emojis提供 "Conversion between emoji characters and aliases",即 emoji 字符与别名(如:smile:)之间的相互转换,用于 Markdown 的emoji扩展在源码文本与 Unicode 字符间的映射,版本约束>= 0.1.5 && < 0.2(pandoc.cabal)。
在 pandoc 源码中的调用链示例
把文档中的库清单落到仓库源码,可以勾勒出几条典型调用链:
- Markdown → HTML 高亮:
commonmark系列解析出 AST → pandoc 内部Pandoc文档 → writer 渲染代码块时调用 Skylighting 完成语法高亮 → 输出 HTML。 - 引用 → 参考文献表:阅读器收集
[@key]引文 → processCitations(citeproc 库)依据 CSL 样式与 data/default.csl 生成参考文献 →doclayout组合子排版(见 src/Text/Pandoc/Citeproc/BibTeX.hs)。 - Lua 过滤器:pandoc 加载用户 Lua 脚本 → hslua 引擎将 Pandoc AST 映射为 Lua 对象(hslua-aeson、hslua-packaging)→ 脚本执行后回写结果。
- docx 输出:内容按 OOXML 结构序列化 →
zip-archive打包为 zip 容器 → 生成最终.docx。
如何独立使用这些库
由于每个库都是独立的 Hackage 包,开发者可以在 pandoc 之外单独复用它们,例如:
- 只做引文处理:直接调用 citeproc,不必引入完整 pandoc;
- 只做语法高亮:基于 skylighting 定制自己的渲染管线;
- 只做CommonMark 解析:用 commonmark + commonmark-extensions 构建符合规范的解析器;
- 只做数学格式转换:texmath 提供 TeX ↔ MathML ↔ Word 公式 ↔ eqn 的纯函数式 API;
- 只做zip 打包:zip-archive 提供纯 Haskell 的 zip 读写能力。
在构建时,若通过 cabal 或 stack 引用 pandoc,上述版本区间(如pandoc.cabal中>=下限)即是对这些库的最低兼容要求;使用 GHC 9.6.7 及以上版本(见 pandoc.cabal 的tested-with列表)可获得完整支持。
小结
pandoc 的"库家族"架构体现了清晰的关注点分离:解析(commonmark、djot、gridtables、jira-wiki-markup)、语义转换(texmath、typst、ipynb、emojis)、呈现(doctemplates、doclayout、skylighting)、扩展(hslua 系列)与容器(zip-archive)各成一体,再经 pandoc.cabal 精确的版本约束组装为统一的转换平台。理解这张依赖地图,无论是深入 pandoc 源码、编写自定义过滤器,还是复用其中某个库构建独立工具,都能事半功倍。完整的库清单与官方描述请参阅 doc/libraries.md。
【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考