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

如何调整Pandoc Lua过滤器执行顺序,实现Block到Inline信息传递

解决Pandoc Lua过滤器执行顺序问题:先收集脚注再处理链接

核心思路

Pandoc默认按AST节点类型的固定顺序执行过滤器,Link节点会早于BulletList被处理。要打破这个顺序,最可靠的方式是在全局文档处理阶段先主动收集脚注信息,再处理正文里的链接节点,具体有两种落地方式:

  • 利用Pandoc全局入口函数,先遍历所有Block提取脚注数据
  • 调用pandoc.walk函数分两次遍历AST:第一次收集脚注,第二次替换链接

具体实现代码

基于你的需求调整后的完整Lua过滤器:

-- 全局存储脚注ID与内容的映射表
local footnotes = {}

function Pandoc(doc)
  -- 第一步:遍历所有Block,提取脚注信息并移除原脚注列表
  local cleaned_blocks = {}
  for _, block in ipairs(doc.blocks) do
    if block.t == 'BulletList' then
      -- 假设BulletList的每个item对应一个脚注,根据你的AST结构调整解析逻辑
      for _, item in ipairs(block.content) do
        local note_id = nil
        local note_content = {}
        -- 遍历脚注项内的行内元素,分离ID和内容
        for _, inline in ipairs(item[1].content) do
          if inline.t == 'Link' and inline.target:match('^#fn:') then
            note_id = inline.target:sub(4) -- 提取"fn:"后的ID部分
          else
            table.insert(note_content, inline)
          end
        end
        if note_id then
          footnotes[note_id] = note_content
        end
      end
      -- 脚注列表处理后从文档中移除(若需保留可跳过此逻辑)
    else
      table.insert(cleaned_blocks, block)
    end
  end

  -- 第二步:遍历所有Link节点,替换为LaTeX脚注命令
  local final_blocks = pandoc.walk_block(pandoc.Div(cleaned_blocks), {
    Link = function(link)
      local target = link.target
      -- 匹配正文中的脚注引用链接(格式为#fnref:xxx)
      if target:match('^#fnref:') then
        local note_id = target:sub(7) -- 提取"fnref:"后的ID
        if footnotes[note_id] then
          -- 将脚注内容转为字符串后包裹成LaTeX命令
          return pandoc.RawInline('latex', string.format('\\footnote{%s}', pandoc.utils.stringify(footnotes[note_id])))
        end
      end
      -- 非脚注链接原样返回
      return link
    end
  })

  -- 返回修改后的文档
  return pandoc.Pandoc(final_blocks, doc.meta)
end

关键细节说明

  • 全局入口优先执行:Pandoc函数是Pandoc过滤器的最高优先级入口,会在所有节点级过滤器(如单独的Link、BulletList函数)之前运行,确保脚注信息先被收集完毕。
  • AST遍历逻辑适配:代码中的脚注解析逻辑需根据你的实际AST结构调整,比如脚注ID的提取规则、内容的组成元素等。
  • LaTeX命令生成:用RawInline包裹LaTeX脚注命令,确保Pandoc输出时直接保留该格式。

对应AST结构参考

你的XHTML转换后AST结构大致如下:

正文中的脚注引用Link节点:

Link {
  attr = {"", [], [("href", "#fnref:1")]},
  content = [Str "1"],
  target = "#fnref:1",
  title = ""
}

正文末尾的脚注BulletList节点:

BulletList {
  content = {
    Plain {
      content = {
        Link {
          attr = {"fn:1", [], [("href", "#fnref:1")]},
          content = [Str "1"],
          target = "#fnref:1",
          title = ""
        },
        Space,
        Str "这是脚注的具体内容。"
      }
    }
  }
}

内容的提问来源于stack exchange,提问作者Carl Sorensen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:54:25