编写Lua版Pandoc过滤器实现缩略语悬浮glossary功能的问题求助
解决方案
你可以通过「拆分含标点的Str节点 + Lua边界模式匹配缩略语 + 返回多元素替换原Str」的方式实现需求,完整代码如下:
-- 词汇表配置 local glossary = {CO = "Cardiac Output", DBP = "Diastolic Blood Pressure", SBP = "Systolic Blood Pressure"} -- 预处理:按缩略语长度降序排序,避免短缩略语先匹配长缩略语的前缀 local sorted_keys = {} for key in pairs(glossary) do table.insert(sorted_keys, key) end table.sort(sorted_keys, function(a, b) return #a > #b end) function Str(elem) local text = elem.text local result = {} local pos = 1 -- 当前扫描位置 local text_len = #text while pos <= text_len do local matched = false -- 尝试匹配所有缩略语 for _, key in ipairs(sorted_keys) do -- %f 为Lua frontier模式,确保缩略语前后都不是字母,避免匹配单词内部字符 local pattern = '%f[%a]' .. key .. '%f[%A]' local start_idx, end_idx = string.find(text, pattern, pos) -- 匹配到且匹配起始位置等于当前扫描位置 if start_idx and start_idx == pos then -- 先添加匹配前的剩余文本(如果有) if start_idx > pos then table.insert(result, pandoc.Str(string.sub(text, pos, start_idx - 1))) end -- 添加悬浮提示Span table.insert(result, pandoc.Span(key, { title = glossary[key], class = "glossary" })) -- 更新扫描位置到匹配结束的下一位 pos = end_idx + 1 matched = true break end end -- 没有匹配到任何缩略语,添加当前字符后继续扫描 if not matched then table.insert(result, pandoc.Str(string.sub(text, pos, pos))) pos = pos + 1 end end -- 如果有生成多元素就返回,否则返回原节点 if #result > 1 then return result elseif #result == 1 then return result[1] else return elem end end
核心逻辑说明
- 边界匹配:使用Lua的
%ffrontier模式保证只有独立出现的缩略语会被匹配,不会识别cobalt这类单词内部的CO片段,不管缩略语周围是逗号、斜杠、分号还是其他标点都能正确识别。 - 多元素返回:Pandoc的过滤器支持返回一个元素列表替换原单个Str节点,因此可以把原来包含标点和多个缩略语的Str拆分为「普通文本Str + 悬浮Span + 普通文本Str」的组合,完全保留原排版格式。
- 排序匹配:提前对缩略语按长度降序排序,避免后续如果新增短缩略语匹配长缩略语前缀的问题。
该方案可以完美覆盖你提供的测试用例中的所有场景:单独出现的缩略语、带标点后缀的缩略语、斜杠分隔的多个缩略语、列表中的缩略语都能正确添加悬浮提示。
内容的提问来源于stack exchange,提问作者cjdbarlow
相关产品推荐
相关产品推荐

