ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

pandoc YAML 元数据块标量类型解析:数字与布尔值如何映射到 Meta 类型

pandoc YAML 元数据块标量类型解析:数字与布尔值如何映射到 Meta 类型 pandoc YAML 元数据块标量类型解析数字与布尔值如何映射到 Meta 类型【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc导读本篇文章围绕 pandoc 仓库中的命令测试用例 test/command/4819.md深入讲解 Markdown 文档顶部 YAML 元数据块YAML metadata block中标量值scalar的类型解析规则数字42为什么最终变成MetaInlines [Str 42]而true、True、FALSE、no又为什么被统一映射为MetaBool。读完本文你将掌握 pandoc 将 YAML 元数据转换为内部Meta数据结构的完整类型分发逻辑并能在实际写作与模板开发中准确预判foo: 42、foo: true、foo: true等写法的最终类型避免在 Lua 过滤器或模板条件判断中踩坑。一、测试用例速览一条命令看懂类型映射test/command/4819.md 是 pandoc 仓库中典型的**命令测试command test**文件它通过% pandoc ...加^DEOF 标记的形式把实际命令行输入与期望输出固化在同一份文档里由 test/Tests/Command.hs 驱动的测试框架逐条执行比对。该文件包含 5 个测试用例全部围绕同一个问题YAML 元数据块中的标量值会被解析成什么类型的MetaValue。用例统一使用-f markdown -t native -s从 Markdown 读取、输出 nativePandoc 内部 AST 的 Haskell 展示形式、并带上-sstandalone输出完整文档骨架使元数据块得以呈现。5 个用例的输入与输出可归纳如下输入YAML 标量期望输出native 形式最终 Meta 类型foo: 42MetaInlines [ Str 42 ]MetaInlinesfoo: trueMetaBool TrueMetaBoolfoo: TrueMetaBool TrueMetaBoolfoo: FALSEMetaBool FalseMetaBoolfoo: noMetaBool FalseMetaBool一个核心规律已经浮出水面YAML 布尔字面量的各种大小写变体true/True/FALSE/no都被识别为真正的布尔值映射为MetaBool而数字42却并未映射为专门的数字类型而是先被转成文本再按 Markdown 内联内容解析最终成为MetaInlines。二、逐例拆解从 YAML 标量到 native 输出1. 数字标量foo: 42→MetaInlines [ Str 42 ]% pandoc -f markdown -t native -s --- foo: 42 ... ^D Pandoc Meta { unMeta fromList [ ( foo , MetaInlines [ Str 42 ] ) ] } []数字42没有被转换为数字类型的元数据值——Pandoc 的Meta类型体系中没有专门的数字构造函数。实际处理是YAML 解析层先把数字转换为十进制文本42再走字符串标量路径把它作为 Markdown 内容解析结果得到单个Str 42。这意味着如果数字附近带有 Markdown 标记也会被一并解析见下文源码解析部分。2. 布尔字面量true/True→MetaBool True% pandoc -f markdown -t native -s --- foo: true ... ^D Pandoc Meta { unMeta fromList [ ( foo , MetaBool True ) ] } []% pandoc -f markdown -t native -s --- foo: True ... ^D Pandoc Meta { unMeta fromList [ ( foo , MetaBool True ) ] } []true与True大小写不同但都被 YAML 解析器识别为布尔真值直接映射为MetaBool True。注意与数字不同布尔值不会被当作 Markdown 文本解析——它保持原生布尔语义这为模板与 Lua 过滤器中的条件判断保留了干净的Bool类型。3. 布尔字面量FALSE→MetaBool False% pandoc -f markdown -t native -s --- foo: FALSE ... ^D Pandoc Meta { unMeta fromList [ ( foo , MetaBool False ) ] } []全大写的FALSE同样被识别为布尔假值。4. 布尔字面量no→MetaBool False% pandoc -f markdown -t native -s --- foo: no ... ^D Pandoc Meta { unMeta fromList [ ( foo , MetaBool False ) ] } []最后一个用例最有陷阱意味YAML 1.1 规范把no以及yes、on、off等也视为布尔字面量因此foo: no被解析为MetaBool False。如果你在元数据中想表达字符串no必须显式加引号写成foo: no否则 pandoc 会把它当成布尔假值——这正是本测试文件想提醒使用者注意的关键行为。三、源码级原理yamlToMetaValue的类型分发上述全部行为都可以在 pandoc 的 Markdown 读取器元数据解析模块 src/Text/Pandoc/Readers/Metadata.hs 中找到直接实现证据。核心函数是yamlToMetaValuesrc/Text/Pandoc/Readers/Metadata.hs#L132-L150它对 YAML 解析出的Value按类型做分发yamlToMetaValue pMetaValue v case v of String t - normalizeMetaValue pMetaValue t Bool b - return $ return $ MetaBool b Number d - normalizeMetaValue pMetaValue $ case fromJSON v of Success (x :: Int) - tshow x _ - tshow d Null - return $ return $ MetaString Array{} - ... -- MetaList Object o - ... -- MetaMap逐一对应Bool b - MetaBool bYAML 布尔值含true/True/FALSE/no等变体直接构造MetaBool不经任何文本解析。这正是测试文件中 4 个布尔用例的出处。Number d - normalizeMetaValue ...数字先尝试按Int用tshow转为文本非整型则回退为tshow d随后走与字符串相同的normalizeMetaValue路径。这解释了42为何变成Str 42。String t - normalizeMetaValue pMetaValue t普通字符串标量会被当作 Markdown 解析。normalizeMetaValuesrc/Text/Pandoc/Readers/Metadata.hs#L108-L128先尝试把内容作为块级 Markdown 解析若只解析出单个段落则把块转换为内联b2i从而得到MetaInlines。字符串最终能否保留为纯文本取决于内容是否包含 Markdown 标记。Null - MetaString 显式的 YAMLnull值映射为空字符串MetaString。Array/Object分别构造MetaList与MetaMap可递归嵌套任意MetaValue。该函数的上游入口是 src/Text/Pandoc/Readers/Markdown.hs#L78-L99 的yamlToMeta其文档注释明确写着 String scalars in the YAML are parsed as MarkdownYAML 中的字符串标量按 Markdown 解析——这与测试文件展示的数字/字符串行为完全一致。YAML 本身的语法解析则由 pandoc.cabal#L572-L573 声明的yaml 0.11 0.12与libyaml依赖提供即 pandoc 复用了 Haskellyaml库对 YAML 1.1 布尔字面量的识别规则。四、命令行-M选项另一条进入MetaBool的路径除 YAML 元数据块外命令行选项-M/--metadata keyvalue也能注入元数据且其布尔解析规则与 YAML 路径相呼应。在 src/Text/Pandoc/App/CommandLineOptions.hs#L1422-L1427 中可以找到如下映射| s true MetaBool True | s True MetaBool True | s TRUE MetaBool True | s false MetaBool False | s False MetaBool False | s FALSE MetaBool False命令行侧同样接受三种大小写变体并映射为MetaBool但不包含YAML 1.1 的no/yes/on/off等写法。也就是说在 YAML 元数据块中foo: no是布尔False在命令行-M foono中no不会被识别为布尔值而是按普通字符串处理。两条路径的布尔字面量集合并不完全一致编写跨环境复用的文档时需要注意这一差异。五、实用要点与验证方法引号是保留字符串语义的关键基于上述规则可以总结出如下决策表写法最终 Meta 类型说明foo: 42MetaInlines [Str 42]数字先转文本再按 Markdown 解析foo: 3.14MetaInlines [Str 3.14]非整型数字同样转为文本foo: true/True/TRUEMetaBool TrueYAML 1.1 布尔真值foo: false/False/FALSEMetaBool FalseYAML 1.1 布尔假值foo: no/yes/on/offMetaBoolYAML 1.1 传统布尔变体易被误用foo: trueMetaInlines [Str true]加引号后是字符串按 Markdown 解析foo: nullMetaString 空值映射为空字符串foo: [a, b]MetaList数组映射为列表foo: {k: v}MetaMap映射递归映射为键值表在编写 pandoc 模板或 Lua 过滤器时若想对元数据做布尔判断务必确认该字段在生产文档中确实以无引号的布尔字面量书写若作者写了foo: false得到的将是字符串而非MetaBool条件判断行为会完全不同。手动复现测试本仓库任意 checkout 后可直接在终端复现测试文件中的全部用例。例如printf -- ---\nfoo: 42\n...\n | pandoc -f markdown -t native -s printf -- ---\nfoo: no\n...\n | pandoc -f markdown -t native -s printf -- ---\nfoo: no\n...\n | pandoc -f markdown -t native -s最后一条命令的输出将是MetaInlines [Str no]与foo: no的MetaBool False形成鲜明对照直观展示引号对类型解析的影响。也可以直接运行仓库的命令测试框架由 test/Tests/Command.hs 驱动来批量验证 test/command/4819.md 及其余所有命令测试用例。六、小结test/command/4819.md 用 5 个精炼的命令用例固化了 pandoc 对 YAML 元数据标量的两条核心规则数字被转写为文本并按 Markdown 内联解析MetaInlines布尔字面量被原样保留MetaBool且大小写不敏感、包含 YAML 1.1 传统写法。其实现证据集中在 src/Text/Pandoc/Readers/Metadata.hs 的yamlToMetaValue类型分发逻辑中。理解这套映射是准确使用 pandoc 元数据驱动模板渲染、Lua 过滤逻辑判断的前提也能帮助你在审阅他人文档时一眼识破foo: no这类看上去是字符串、实际是布尔值的隐性行为。【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表