You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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">&amp;</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=&quot;menukey&quot;&gt;' .. part .. '&lt;/span&gt;'
    end

    newContent = '&lt;span class=&quot;menukeys&quot;&gt;' .. newContent .. '&lt;/span&gt;'

    return pandoc.RawInline('html', newContent)
  end
end

问题本质

过滤器错误地将菜单选项中的空格或符号单独用menukey元素包裹,原因在于:

  1. 自定义的split函数使用了[^%s]+模式,这里的separator是" > ",[^%s]会把空格、>这些字符都当作分隔符,导致多字符的菜单选项被拆分。
  2. 代码中存在拼写错误: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

关键修改说明

  1. 移除了有问题的自定义split函数,改用string.gmatch配合正则模式%s*(.-)%s*(?= > |$),可以精准匹配" > "分隔的每个完整菜单选项,同时自动去除选项前后的空格。
  2. 修正了拼写错误elen.text为elem.text。
  3. 使用pandoc.utils.stringify处理菜单选项内容,自动转义HTML特殊字符(比如&会转成&),避免HTML语法错误。
  4. 直接使用正确的HTML标签格式(无需转义引号,pandoc会自动处理)。

内容的提问来源于stack exchange,提问作者Oo'-

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:24:52