ARTICLE DETAIL

资讯详情

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

Pandoc OPML 读取器 `_note` 属性 HTML 处理深度解析:raw_html 与 native_divs 扩展如何决定转换结果

Pandoc OPML 读取器 `_note` 属性 HTML 处理深度解析:raw_html 与 native_divs 扩展如何决定转换结果 Pandoc OPML 读取器_note属性 HTML 处理深度解析raw_html 与 native_divs 扩展如何决定转换结果【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc导读本文以 Pandoc 仓库中的命令测试用例 test/command/4164.md 为切入点深入剖析 OPML 读取器对outline节点_note属性中内嵌 HTML 的处理逻辑并揭示raw_html、native_divs这两个扩展在转换链路中的决定性作用。读完本文你将理解为什么同一份 OPML 输入在默认与禁用扩展两种模式下会产出围栏 Div 原始 HTML与转义纯文本两种截然不同的 Markdown 结果并能基于源码机制自行控制_note中的 HTML 行为。测试用例全景4164.md 在验证什么Pandoc 的命令测试采用命令 标准输入 期望输出的固定格式由 test/Tests/Command.hs 驱动。其规则见 test/Tests/Command.hs为代码块第一行以%开头给出待执行的命令随后是作为 stdin 传入的输入以^D行终止之后的行是对 stdout 的期望输出。test/command/4164.md 正是这样一个包含两个对照测试的文件它用同一份 OPML 输入分别验证默认扩展与禁用raw_html/native_divs两种模式下_note属性中 HTML 的解析差异测试一默认扩展-f opml% pandoc -f opml -t markdown ?xml version1.0? opml version1.0 head title test /title /head body outline texttest outline texttry _noteHere is inline html:#xA;#xA;lt;divgt; #xA;lt;balisegt;#xA;bla bla#xA;lt;/divgt;/ /outline /body /opml ^D # test ## try Here is inline html: ::: {} balise{html} bla bla :::测试二禁用扩展-f opml-raw_html-native_divs% pandoc -f opml-raw_html-native_divs -t markdown ?xml version1.0? opml version1.0 head title test /title /head body outline texttest outline texttry _noteHere is inline html:#xA;#xA;lt;divgt; #xA;lt;balisegt;#xA;bla bla#xA;lt;/divgt;/ /outline /body /opml ^D # test ## try Here is inline html: \div\ \balise\ bla bla \/div\注意 OPML 输入中_note属性值为经过 XML 实体转义的文本#xA;是换行lt;divgt;等是div标签。解码后_note的实际内容为Here is inline html: div balise bla bla /div两份输出中文档标题titletest/title均成为 H1# test第一层outline texttest成为 H2## try之下的内容来源——实际上outline texttest生成了 H1 下的 H2 标题## test仔细对照可见headtitletest/title/head产生# test第一层 outlinetexttest对应## try下的## try观察输出# test ← 来自 headtitletest/title/head ## try ← 来自 outline texttest等等输入中第一个 outline 的texttest应生成标题第二个 outline嵌套texttry生成下一级标题。但输出只有## try而没有## test。这是因为每个 outline 会递增 section level 并生成对应级别标题第一个 outline 是 level 1其text属性恰好也是 test与文档标题# test同名——实际上输出的# test是文档标题## try是第一层 outlinetexttest生成的 level-2 标题这里需要对照源码仔细推敲。OPML 读取器源码outline、text 与 _note 的映射规则OPML 读取器的核心实现位于 src/Text/Pandoc/Readers/OPML.hs入口函数readOPML通过parseXMLContents解析 XML并对顶层元素逐个调用parseBlock处理见 src/Text/Pandoc/Readers/OPML.hs。该读取器已在 src/Text/Pandoc/Readers.hs 中以(opml, TextReader readOPML)注册为文本读取器。parseBlock见 src/Text/Pandoc/Readers/OPML.hs对 OPML 元素的分派规则如下元素 / 属性处理方式源码位置title作为文档标题opmlDocTitleOPML.hsownerName作为文档作者opmlDocAuthorsOPML.hsdateModified作为文档日期opmlDocDateOPML.hsoutline生成标题 _note块并递归处理子 outlineOPML.hs?xml忽略OPML.hs其他元素递归处理其子内容OPML.hs在sect辅助函数中OPML.hs可以看清 outline 的完整映射逻辑标题来源text属性通过asHtml解析为行内元素headerText正文来源_note属性通过asMarkdown解析为块级元素noteBlocks层级来源嵌套深度opmlSectionLevel累加决定标题级别header n这也是为何 outline 逐层嵌套会产生#、##、###等递进标题链接支持若type属性大写化为LINK则标题会被包装为指向url属性的链接。由此回看测试输出# test正是headtitletest/title/head映射的文档标题第一层outline texttest生成 level-1 标题而第二层嵌套outline texttry生成 level-2 标题。原文输出中## try之前没有## test说明当文档标题与顶层 outline 文本重合时测试期望的输出以文档标题与 outline 标题并存的方式呈现——顶层 outlinelevel 1生成 H1但为避免与文档标题重复实际测试期望文件展示的即是上述# test文档标题## try第一层 outline 若为 level 2 则可能因测试缩进的形态。从源码结构可以推断sect n中n opmlSectionLevel 1顶层 outline 对应 level 1 即 H1嵌套 outline 递增因此输出中的## try表明该测试输入的第一层 outline 被处理为 level-2 标题opmlSectionLevel初始为 0首次调用为 1但在测试输入中head与body均为 OPML 结构的外层元素其实际层级由parseBlock递归路径决定。关键机制asHtml与asMarkdown都通过readerExtensions opts继承 OPML 读取器当前的扩展集合OPML.hs。这意味着在命令行通过-f opml-raw_html-native_divs调整扩展会直接传导到_note与text属性的内部解析器——这正是 4164.md 两个测试输出迥异的根源。默认扩展行为围栏 Div 与原始 HTML 内联在默认-f opml模式下OPML 读取器启用的是pandocExtensions全集见下节源码证据其中包含Ext_raw_html与Ext_native_divs。于是_note中的 HTML 按以下路径解析div标签被Ext_native_divs识别为 Div 块无属性在 Markdown 输出中以围栏 Div语法::: {}呈现balise不是标准 HTML 标签但在Ext_raw_html启用时会被当作原始 HTML 内联保留Markdown 输出中表现为balise{html}行内原始属性语法普通文本bla bla原样保留。因此默认输出是结构化保留 HTML 语义的结果HTML 块与行内原始 HTML 都得到还原方便后续继续转换为 HTML、LaTeX 等格式。禁用扩展后的行为HTML 退化为转义纯文本第二个测试命令-f opml-raw_html-native_divs同时禁用raw_html与native_divs命令行-扩展名语法表示关闭对应扩展扩展名来自showExtension即去掉Ext_前缀的小写形式见 Extensions.hs。此时_note内容经asMarkdown解析时Markdown 解析器中的处理逻辑ltSign见 Markdown.hs在Ext_raw_html被禁用后不再把...当作 HTML 标签而是作为普通字符htmlBlock见 Markdown.hs要求guardEnabled Ext_raw_html才解析 HTML 块禁用后该分支失效于是div、balise、/div全部沦为纯文本Markdown 写出时为避免歧义将转义为\最终得到\div\ \balise\ bla bla \/div\。这一对照清晰说明_note中 HTML 是结构化保留还是原样文本完全由 OPML 读取器的扩展集合决定而不是由_note属性本身决定。底层机制为什么-f opml默认启用 raw_html 与 native_divs要理解默认行为需回到扩展定义源头 src/Text/Pandoc/Extensions.hspandocExtensions是 Pandoc 风格 Markdown 的默认扩展集Extensions.hs其中明确包含Ext_raw_htmlL228与Ext_native_divsL237getDefaultExtensions opml直接返回pandocExtensions并附注释-- affects notesExtensions.hs——这是源码对OPML 默认扩展影响_note解析的直接证据。raw_html与native_divs的语义分别为扩展名源码构造子作用raw_htmlExt_raw_html允许在源文档中保留原始 HTML 片段块级与行内native_divsExt_native_divs将div标签的内容解析为 Pandoc 的 Div 块配合_note内部使用的 Markdown/HTML 解析器这两个扩展共同决定了 4164.md 中Div 化与原始 HTML 化的输出路径。复现与验证如何亲手运行该测试4164.md 属于 Pandoc 的命令测试套件Golden Test其运行依赖 test/test-pandoc.hs 与 test/Tests/Command.hs。在已构建的 Pandoc 开发环境中可通过测试套件直接运行# 方式一运行全部命令测试需先构建 make test # 方式二仅运行 4164 相关用例test-pandoc 接受 tasty 模式过滤 cabal run test-pandoc -- -p 4164也可以不借助测试框架直接用 pandoc 二进制手动复现两份输出输入文件需为解除了 XML 实体转义的等价 OPML# 默认扩展HTML 被结构化为 Div 原始 HTML pandoc -f opml -t markdown input.opml # 禁用 raw_html 与 native_divsHTML 被转义为纯文本 pandoc -f opml-raw_html-native_divs -t markdown input.opml实战要点与延伸建议_note属性是 OPML outline 的富文本正文载体Pandoc 会将其按 Markdown 语法解析因此_note中不仅可以放 HTML也可以放普通 Markdown列表、链接、代码块等调整_note中 HTML 的保留策略应修改读取器扩展而非正文-f opmlraw_html强制启用、-f opml-raw_html-native_divs整体关闭 HTML 语义是两种常用组合转换目标决定扩展选择若后续目标为 HTML/EPUB 等富格式默认的raw_html native_divs能最大化保留 HTML 语义若目标是纯文本或需严格转义可参考 4164.md 的第二个测试禁用相关扩展outline 的text、typelink、url等属性分别控制标题文本与链接化行为是 OPML 导入时最常用的定制点相关实现均可回溯至 src/Text/Pandoc/Readers/OPML.hs。通过 4164.md 这一对精巧的对照用例可以直观看到 Pandoc 中格式解析器 扩展开关的分层设计OPML 只负责大纲结构而 HTML 语义的保留与否完全交由扩展系统裁决。理解这一机制是灵活驾驭 Pandoc OPML 输入的关键。【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表