Pandoc lua过滤器:如何保留脚注的格式?

RLe*_*sur 4 markdown html5 lua filter pandoc

我尝试实现“页面媒体模块的CSS生成的内容”中定义的脚注。
使用此定义,脚注必须为inline span。我写了一个pandoc lua过滤器的初稿。
这是我的第一个pandoc过滤器(也是我第一次在中进行编码lua)。

这是过滤器:

Note = function (elem)
  local textContent = {}
  local content = elem.content
  for i = 1, #content do
    textContent[2*i-1] = pandoc.Str(pandoc.utils.stringify(content[i]))
    if i < #content
    then
      textContent[2*i] = pandoc.LineBreak()
    end
  end
  return pandoc.Span(textContent, pandoc.Attr("", {"footnote"}, {}))
end
Run Code Online (Sandbox Code Playgroud)

它适用于带有未格式化文本的脚注(由于使用了该stringify()功能而导致格式丢失):简单的脚注和多个块的脚注都可以很好地呈现。

为了保留格式,我尝试在元素walk_block()上使用函数,但是无法获得任何结果。contentNote

我有第二个问题:stringify()函数返回CodeBlock元素的空字符串。

因此,当我在以下markdown文本上使用此过滤器时:

Here is a footnote reference,[^1] and another.[^longnote]

[^1]: Here is the footnote.

[^longnote]: Here's one with multiple blocks.

    Subsequent paragraphs are indented to show that they
belong to the previous footnote.

        { some.code }

    The whole paragraph can be indented, or just the first
    line.  In this way, multi-paragraph footnotes work like
    multi-paragraph list items.

This paragraph won't be part of the note, because it
isn't indented.
Run Code Online (Sandbox Code Playgroud)

我获得以下HTML片段:

<p>
  Here is a footnote reference,
  <span class="footnote">Here is the footnote.</span>
  and another.
  <span class="footnote">Here’s one with multiple blocks.
    <br />
    Subsequent paragraphs are indented to show that they belong to the previous footnote.
    <br />
    <br />
    The whole paragraph can be indented, or just the first line. In this way, multi-paragraph footnotes work like multi-paragraph list items.
  </span>
</p>
<p>This paragraph won’t be part of the note, because it isn’t indented.</p>
Run Code Online (Sandbox Code Playgroud)

代码块丢失。有什么办法可以同时保留脚注的格式和代码块?

RLe*_*sur 5

我发现了如何处理Note元素。

首先,Note元素是一个内联元素,因此我们可以使用walk_inline。奇怪的是,一个Note元素可以嵌入诸如Para或的块元素CodeBlock

以下过滤器仅处理ParaCodeBlock元素。保留格式。

由于Para元素是内联元素的列表,因此很明显在元素中重用这些元素Span
CodeBlock文本也可在一个内联处理Code元件。

local List = require 'pandoc.List'

Note = function (elem)
  local inlineElems = List:new{} -- where we store all Inline elements of the footnote
  -- Note is an inline element, so we have to use walk_inline
  pandoc.walk_inline(elem, {
    -- Para is a list of Inline elements, so we can concatenate to inlineElems
    Para = function(el)
      inlineElems:extend(el.content)
      inlineElems:extend(List:new{pandoc.LineBreak()})
    end,
    -- CodeBlock is a block element. We have to store its text content in an inline Code element
    CodeBlock = function(el)
      inlineElems:extend(List:new{pandoc.Code(el.text, el.attr), pandoc.LineBreak()})
    end
  })
  table.remove(inlineElems) -- remove the extra LineBreak
  return pandoc.Span(inlineElems, pandoc.Attr("", {"footnote"}, {}))
end
Run Code Online (Sandbox Code Playgroud)

如果Note元素嵌入其他类型的块元素(如a BulletList或a Table),则必须为该walk_inline功能开发特定的过滤器。

  • Pandoc具有将块转换为内联的功能,但未作为Lua函数公开。据我了解,这种功能将使您的生活大大简化。我可以建议在[pandoc问题追踪器](https://github.com/jgm/pandoc/issues)上提出一个问题吗? (2认同)