使用 Lua 和 walk_block 进行 Pandoc 过滤器

我想要应用一个仅在文档正文中更改文本的 LUA 过滤器,而不改变元数据。这比我想象的要难得多。

过滤器应该在内联和块元素前后添加文本。如果它对内联元素(如Code)有效,则对块元素CodeBlock无效。

function Pandoc(doc)
  blocks = {}
  for k,block in pairs(doc.blocks) do
    table.insert(blocks, pandoc.walk_block(block, {
      -- 无效!?
      CodeBlock = function(el)
        return {
          pandoc.Para({pandoc.Str("Before")}),
          el,
          pandoc.Para({pandoc.Str("After")})}
      end,
      -- 有效!
      Code = function(el)
        return {pandoc.Str("Before"), el, pandoc.Str("After")}
      end,
    }))
  end

  return pandoc.Pandoc(blocks, doc.meta)
end

我错过了什么?干杯,

点赞
用户2425163
用户2425163

问题在于 walk_blockwalk_inline 处理的是元素的 _内容_,而不是元素本身。

如果 wrapper 是你的筛选表格,这将能做到你想要的效果:

function Pandoc (doc)
  local div = pandoc.Div(doc.blocks)
  local blocks = pandoc.walk_block(div, wrapper).content
  return pandoc.Pandoc(blocks, doc.meta)
end

另一种解决方案是保存和恢复元数据,可像这样:

local meta = {}
return {
  { Meta = function(m) meta = m; return {} end },
  wrapper,
  { Meta = function(_) return meta; end },
}

这可能更高效,因为仅对元数据和代码/代码块元素进行序列化/反序列化可能比对整个文档进行序列化/反序列化更快。

2017-11-17 17:31:30