Pandoc Lua过滤器菜单键转换Bug:符号与空格被错误拆分包裹
Pandoc Lua过滤器菜单键转换错误修复
我参考LaTeX包menukeys开发了一款Pandoc Lua过滤器,用于将菜单键的Markdown语法转换为HTML,但遇到了含空格与特殊符号的菜单选项被错误拆分的问题。
Markdown语法示例
Path: `> C > Users > {usuario} > AppData > Roaming > nvm` Path: `> Network & Internet > Wi-Fi > Hardware Properties`
预期转换后的HTML
<p> Path: <span class="menukeys"> <span class="menukey">C</span> <span class="menukey">Users</span> <span class="menukey">{usuario}</span> <span class="menukey">AppData</span> <span class="menukey">Roaming</span> <span class="menukey">nvm</span> </span> </p> <p> Path: <span class="menukeys"> <span class="menukey">Network & Internet</span> <span class="menukey">Wi-Fi</span> <span class="menukey">Hardware Properties</span> </span> </p>
实际错误转换结果
<p> Path: <span class="menukeys"> <span class="menukey">Network</span> <span class="menukey">&</span> <span class="menukey">Internet</span> <span class="menukey">Wi-Fi</span> <span class="menukey">Hardware</span> <span class="menukey">Properties</span> </span> </p>
效果对比
- 错误效果:菜单选项被拆分成多个独立的
menukey元素,比如"Network & Internet"被拆成"Network"、"&"、"Internet"三个部分,"Hardware Properties"被拆成"Hardware"和"Properties"。 - 预期效果:每个完整的菜单选项作为一个单独的
menukey元素,保留空格与特殊符号。
当前使用的Pandoc Lua过滤器代码
function string:split(separator) local fields = {} local pattern = string.format("([^%s]+)", separator) self:gsub(pattern, function(c) fields[#fields + 1] = c end) return fields end function Code(elem) if elem.text:sub(1, 1) == ">" then local parts = elen.text:sub(2):split(" > ") local newContent = "" for i, part in ipairs(parts) do newContent = newContent .. 'span class="menukey">' .. part .. '</span>' end newContent = '<span class="menukeys">' .. newContent .. '</span>' return pandoc.RawInline('html', newContent) end end
问题本质
过滤器错误地将菜单选项中的空格或符号单独用menukey元素包裹,原因在于:
- 自定义的
split函数使用了[^%s]+模式,这里的separator是" > ",[^%s]会把空格、>这些字符都当作分隔符,导致多字符的菜单选项被拆分。 - 代码中存在拼写错误:
elen.text应为elem.text。
修复后的过滤器代码
function Code(elem) if elem.text:sub(1, 1) == ">" then -- 跳过开头的>,匹配" > "分隔的内容 local parts = {} -- 使用gmatch匹配分隔符之间的内容,保留空格和特殊符号 for part in elem.text:sub(2):gmatch("%s*(.-)%s*(?= > |$)") do table.insert(parts, part) end local newContent = '<span class="menukeys">' for _, part in ipairs(parts) do -- 转义HTML特殊字符 local escaped_part = pandoc.utils.stringify(pandoc.Str(part)) newContent = newContent .. '<span class="menukey">' .. escaped_part .. '</span>' end newContent = newContent .. '</span>' return pandoc.RawInline('html', newContent) end end
关键修改说明
- 移除了有问题的自定义
split函数,改用string.gmatch配合正则模式%s*(.-)%s*(?= > |$),可以精准匹配" > "分隔的每个完整菜单选项,同时自动去除选项前后的空格。 - 修正了拼写错误
elen.text为elem.text。 - 使用
pandoc.utils.stringify处理菜单选项内容,自动转义HTML特殊字符(比如&会转成&),避免HTML语法错误。 - 直接使用正确的HTML标签格式(无需转义引号,pandoc会自动处理)。
内容的提问来源于stack exchange,提问作者Oo'-
相关产品推荐
相关产品推荐

