)
Pandoc AsciiDoc 写入器词内强调检测原理与 Golden Test 剖析issue #7803【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc本文以 Pandoc 仓库中的回归测试用例 test/command/7803.md 为切入点深入剖析 AsciiDoc 写入器writer在 HTML → AsciiDoc 转换中如何判断词内强调intraword emphasis并据此决定使用单下划线_还是双下划线__作为强调定界符。读完本文你将掌握 AsciiDoc 输出中强调标记的选型规则、inlineListToAsciiDoc中基于isSpacy的相邻内联元素扫描算法以及 Pandoc 命令测试golden test的编写与运行机制能够自行分析、验证乃至扩展这一类格式转换边界行为。测试用例概览一段 HTML 列表的转换test/command/7803.md 是 Pandoc 命令测试套件中的一个回归测试regression test文件整体是一个 fenced code block其内容格式由 test/Tests/Command.hs 的模块注释明确定义% pandoc -f html -t asciidoc ul lia hrefx.htmiXx/i/ai,/i ... /ul ^D * link:x.htm[_Xx_]_,_ ...解析规则为第一行%之后是待执行的 shell 命令中间若干行作为该命令的 stdin 输入以单独一行^D标记 stdin 结束之后的每一行是期望的 stdout 输出若期望出现 stderr 输出需在每行前加2前缀若期望非零退出码则末尾追加 exitcode。运行时test/Tests/Command.hs 中的execTest会通过shell调用test-pandoc --emulate见pandocToEmulate将输入喂给 pandoc 进程再把实际输出与期望输出做 golden 比对。因此7803.md本身就是一个输入 期望输出的完整规范记录了该场景下 HTML 读取器与 AsciiDoc 写入器协作后的既定行为。该测试对应的代码修复记录在 changelog.mdAsciiDoc writer: Improve detection of intraword emphasis (#7803).提交ea7458228AsciiDoc writer: improve detection of intraword emphasisCloses #7803只改动了两处一行实现代码加一个测试文件——正是本用例。待解决问题的本质单下划线与双下划线的取舍在 AsciiDocAsciidoctor 方言中_text_表示斜体强调而__text__表示词内强调intraword emphasis即当被强调的文本紧贴在普通单词字符之间、不与其他单词分隔时使用的形式。例如A__b__C中b是词内强调若写成A_b_C则不会被解析为强调而是原样输出。Pandoc 内部文档模型并不区分词内与词间强调——HTML 中i就是i。因此 AsciiDoc 写入器必须根据被强调内容在相邻内联元素序列中的位置自行推断只有当强调内容紧邻着非分隔字符比如紧跟在Xx之后时才需要升级为__...__否则使用普通的_..._。源码实现inlineListToAsciiDoc与isSpacy判定核心逻辑位于 src/Text/Pandoc/Writers/AsciiDoc.hs。写入器用WriterState中的一个intraword :: Bool字段src/Text/Pandoc/Writers/AsciiDoc.hs#L65-L77在递归过程中传递当前内联元素是否处于词内位置这一状态。inlineListToAsciiDoc对相邻内联元素y : x : xs分三种情况处理若y结尾不是分隔符isSpacy End y为 False则说明x紧跟在一个词内处理x时需要开启intraword即withIntraword $ inlineToAsciiDoc opts x否则若x开头不是分隔符isSpacy Start x为 False说明y处于词内位置处理y时开启intraword其余情况两者都不处于词内。withIntrawordsrc/Text/Pandoc/Writers/AsciiDoc.hs#L604-L605在求值前后分别setIntraword True与setIntraword False实现局部状态切换。isSpacy的判定规则src/Text/Pandoc/Writers/AsciiDoc.hs#L586-L599如下Space、LineBreak、SoftBreak一律视为分隔符Str的末尾/开头字符若是标点isPunctuation或空白isSpace则该侧视为分隔符Link、Image的结尾视为分隔符isSpacy End (Link{}) True其余情况——关键所在——在修复后一律视为非分隔符isSpacy _ _ True。修复的实质把默认值从分隔改为不分隔提交ea7458228对实现的改动只有一行src/Text/Pandoc/Writers/AsciiDoc.hs中inlineListToAsciiDoc的isSpacy函数isSpacy Start (Str xs) | Just (c, _) - T.uncons xs isPunctuation c || isSpace c - isSpacy _ _ False isSpacy _ _ True改动前未知类型的内联元素默认被当作分隔符False导致Link、Emph等复杂元素开头/结尾相邻的强调被误判为词间输出普通_..._改动后默认按非分隔符处理True只有明确命中空白、标点或链接结尾时才按分隔符处理。这使链接、图片等内联对象与强调文本相邻时能更准确地识别词内强调。逐行验证期望输出现在把测试输入与输出逐项对应验证isSpacy的推断逻辑#HTML 输入片段AsciiDoc 输出判定依据1aiXx/i/ai,/ilink:x.htm[_Xx_]_,_Link结尾为分隔Xx非词内用_Xx_,后接/li换行独立成_,_2i,,/i_,,_连续两个标点各自独立强调3i1/i_1_数字前无紧邻词字符41i1/i1__1__前置1为词字符1处于词内 →__1__5ibcd/i_bcd_独立强调6aibcd/ia__bcd__紧邻a词内 →__bcd__7aibcd/iea__bcd__e前后均紧邻词字符词内强调8aXx/a i,/ilink:x.htm[_Xx_] _,_Link结尾分隔 Space分隔i,/i前有空格9,i,/ilink:x.htm[_Xx_],_,_前一个,为标点分隔10aXx/ai,/ilink:x.htm[Xx]_,_链接文本无强调,独立强调从源码看可推断出判定机制如下Link的结尾isSpacy End (Link{}) True与Str中的标点字符、空白字符一样被视为分隔符反之字母、数字等普通字符isPunctuation与isSpace均为 False视为词字符紧邻它们的强调内容便进入intraword分支输出__...__。这正是第 4、6、7 行与第 1、5 行产生差异的原因。关联机制Emph与Strong的定界符选择isSpacy推断出的intraword状态最终由 inlineToAsciiDoc 消费inlineToAsciiDoc opts (Emph lst) do contents - inlineListToAsciiDoc opts lst isIntraword - gets intraword let marker if isIntraword then __ else _ return $ delimited marker marker contentsEmph斜体词内用__词间用_Strong加粗词内用****词间用**Underline、Strikeout、Superscript、Subscript、SmallCaps则固定使用[...]#/^...^/~...~/[smallcaps]#...#等定界符不随词内状态变化。delimited marker marker contents会确保定界符与内容之间保持正确的空白关系最终形成测试中形如1__1__、a__bcd__e的输出。延伸同系列的相邻修复#7803并非孤例changelog 显示 AsciiDoc 写入器的强调/转义处理经历过一系列迭代#8070修复链接文本中的逗号逗号会触发 AsciiDoc 属性解析需替换为#44;数字实体相关逻辑见 inlineToAsciiDoc 中的fixCommas#8525/ 后续调整链接尾迹link trail的字符范围从仅 ASCII 字母扩展为除 CJK 统一表意文字区间外的所有字母以兼容西班牙语等语言#8936asciidoc格式转向以 Asciidoctor 解析的现代方言为目标asciidoctor成为废弃同义词writeAsciiDoctor。这些修复共同塑造了当前 src/Text/Pandoc/Writers/AsciiDoc.hs 中escapeString、isSpacy等函数的复杂行为而test/command/目录下的编号测试文件则构成了保障这些行为不回归的防线。如何运行与扩展该测试命令测试统一由 test/test-pandoc.hs 中的Tests.Command.tests驱动测试分组见pandoc tests。常规执行方式# 构建并运行全部测试含 command 测试 cabal test pandoc # 或使用 Makefile 目标 make test若要单独验证本用例可用等价命令手工复现pandoc -f html -t asciidoc test/command/7803.md 的输入部分新增类似回归测试时只需在 test/command/ 下新建NNNN.md文件按% 命令 / stdin / ^D / 期望输出的格式书写即可无需改动测试框架代码——这正是 test/Tests/Command.hs 设计的可扩展性所在。小结test/command/7803.md以最小化的 HTML 列表输入完整锁定了 AsciiDoc 写入器词内强调检测的 10 种边界情形是理解isSpacy判定算法与intraword状态机的最佳样例。其背后的修复默认值由分隔改为不分隔提醒我们在格式转换器中未显式匹配即视为默认的策略选择往往正是决定输出是否符合目标格式方言语义的关键。【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考