ARTICLE DETAIL

资讯详情

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

Pandoc 缩写词与 smart 扩展:从 issue 4635 回归测试看 softbreak 场景下的不间断空格处理

Pandoc 缩写词与 smart 扩展:从 issue 4635 回归测试看 softbreak 场景下的不间断空格处理 Pandoc 缩写词与 smart 扩展从 issue #4635 回归测试看 softbreak 场景下的不间断空格处理【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc导读本文围绕 pandoc 仓库中的回归测试 test/command/4635.md 展开深入剖析 Pandoc 的 Markdown 阅读器在启用smart扩展时如何处理缩写词如 cf.、Mr.普通空格后自动插入不间断空格non-breaking space而换行softbreak之后则保持换行原样。读完本文你将理解--abbreviations选项、默认缩写表data/abbreviations的加载机制、str解析器中\160的插入逻辑以及 issue #4635 背后缩写词 softbreak这一边界场景的完整修复链路。测试用例 4635.md 是什么test/command/4635.md 是 Pandoc 的命令式黄金测试golden test用例之一位于 test/command 目录下编号对应 GitHub issue #4635。该目录中的每个.md文件都遵循同一约定% pandoc ...开头书写命令行随后给出输入^D表示输入结束再给出期望的标准输出。这类测试由 test/Command.hs 驱动Pandoc 会以文档中指定的参数与输入实际运行一遍并将结果与文档中记录的期望输出逐字比对。因此 4635.md 不仅是一个 bug 修复的见证更是一个可执行的规格说明——任何回归例如缩写词后误吞换行、或错误地把 softbreak 替换成空格都会让测试直接失败。缩写词的来源默认数据文件与 --abbreviations 选项测试中的 cf. 之所以被特殊对待是因为它出现在 Pandoc 内置的缩写词表中。默认缩写表位于 data/abbreviations共 80 个词条除 cf. 外还包括 e.g.、i.e.、Mr.、Mrs.、Dr.、St.、vs. 等常见英文缩写用户可通过命令行选项--abbreviationsFILE指定自定义缩写文件其参数解析位于 src/Text/Pandoc/App/CommandLineOptions.hs加载逻辑位于 src/Text/Pandoc/App.hs 的readAbbreviations函数未指定文件时读取数据文件abbreviations指定时读取用户文件然后按行切分、过滤空行、组装成Set Text。可以用pandoc --print-default-data-fileabbreviations随时查看默认表内容。从源码注释可以确认These currently only affect the Markdown reader.这些缩写词目前仅影响 Markdown 阅读器而 MANUAL.txt 也说明smart扩展会在 Mr. 这类缩写词之后插入不间断空格MANUAL.txt。smart 扩展与缩写词源码中的插入逻辑真正执行缩写词后插 nbsp的是 Markdown 阅读器的str解析器位于 src/Text/Pandoc/Readers/Markdown.hs。其核心逻辑为解析出一段由字母数字与单个点号组成的词如cf.仅当smart扩展开启guardEnabled Ext_smart时才取出readerAbbreviations选项中的缩写词集合进行成员判断若当前词命中缩写表则解析其后的空白并分情况处理若空白解析结果是单个Space则用B.str \160不间断空格替换产出Str cf. 不间断空格若结果是其他结构如SoftBreak即换行则原样保留不替换。源码中紧邻的注释直接点明了本测试的意图src/Text/Pandoc/Readers/Markdown.hs-- replace space after with nonbreaking space -- if softbreak, move before abbrev if possible (#4635)也就是说缩写词后若跟普通空格需要插入\160防止排版换行断开缩写但若缩写词后面本身是一个换行softbreak则应当尊重这个换行而不是把它吞掉并换成不间断空格。四个测试场景逐条解读4635.md 用 4 个输入/输出对覆盖了缩写词后是 softbreak这一问题的全部形态。以下按原文档顺序完整给出并逐条分析。场景 1括号包裹的缩写词后换行% pandoc -f markdown -t native (cf. foo) ^D [ Para [ Str (cf. , SoftBreak , Str foo) ] ]输入(cf.换行foo)(cf.被解析为单个Str (cf.换行保留为SoftBreakfoo)成为下一个Str。要点即使cf.是已知缩写其后是换行而非空格因此不插入 nbspsoftbreak 完整保留。场景 2行首有正文、括号包裹的缩写词后换行% pandoc -f markdown -t native a (cf. foo) ^D [ Para [ Str a , Space , Str (cf. , SoftBreak , Str foo) ] ]在场景 1 基础上增加前置单词a。结果中a与(cf.之间是普通Space而(cf.与foo)之间依然是SoftBreak。这确认了括号包裹并不影响缩写词的识别也不影响换行保留的行为。场景 3缩写词直接后换行% pandoc -f markdown -t native cf. foo ^D [ Para [ Str cf. , SoftBreak , Str foo ] ]最纯粹的情形cf.独占一行首。尽管cf.命中缩写表其后是换行因此产出Str cf. SoftBreak Str foo无任何 nbsp 插入。场景 4行首有正文、缩写词直接后换行% pandoc -f markdown -t native a cf. foo ^D [ Para [ Str a , Space , Str cf. , SoftBreak , Str foo ] ]a与cf.之间是普通Spacecf.与foo之间是SoftBreak。四个场景共同验证了同一条不变式缩写词后的 softbreak 始终原样保留只有空格才被替换为 nbsp。与普通空格行为的对比为什么需要 #4635 修复为了理解上述行为的价值可以对照smart扩展在缩写词 空格下的表现输入cf. foo输出应为[Para [Str cf., Str \160, Str foo]]缩写词与下一词之间是不间断空格\160。这正是排版上的预期——避免 cf. 出现在行尾而 foo 被挤到下一行造成视觉断裂。issue #4635 暴露的问题则在于 softbreak 路径在没有修复前缩写词后的换行若被当作普通空白处理要么会被替换成 nbsp 从而吞掉换行改变段落换行语义要么换行被错误地折叠进缩写词处理流程导致与str合并逻辑冲突。修复后的str解析器通过case B.toList ils对空白结果做模式匹配src/Text/Pandoc/Readers/Markdown.hscase B.toList ils of [Space] - return $! (B.str result B.str \160) _ - return $! (B.str result ils)只有结果恰好是单个Space时才替换为\160出现SoftBreak等任何其他结构时都原样拼接。这样既保留了 nbsp 的排版价值又不会破坏 Markdown 源文本中的显式换行。如何复现与验证无需搭建复杂环境只需本仓库源码构建出的 pandoc 可执行文件或系统安装的 pandoc即可复现全部四个场景# 场景 3缩写词后换行 printf cf.\nfoo\n | pandoc -f markdown -t native # 场景 4正文 缩写词后换行 printf a cf.\nfoo\n | pandoc -f markdown -t native # 对照缩写词后普通空格 → 输出中会出现 \160 printf cf. foo\n | pandoc -f markdown -t native前两条命令的输出应与 4635.md 中记录的期望输出逐字一致。注意该行为依赖smart扩展开启pandoc 的markdown格式默认启用smart可用-f markdown-smart关闭验证差异且与--abbreviations自定义文件配合时会按新表判定命中。小结test/command/4635.md以 4 组最小化的输入输出对精确锁定了 Pandoc 在缩写词 softbreak这一边界场景下的行为契约缩写词只对紧随其后的普通空格触发 nbsp 替换对换行SoftBreak一律放行。配合 data/abbreviations 默认缩写表、src/Text/Pandoc/App.hs 的加载逻辑、以及 src/Text/Pandoc/Readers/Markdown.hs 的str解析器读者既能从命令行层面复现现象也能从源码层面理解机制是一份兼具测试规格与实现原理双重价值的参考资料。【免费下载链接】pandocUniversal markup converter项目地址: https://gitcode.com/gh_mirrors/pa/pandoc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表