繁体   English   中英

如何更改 Pandoc 元素的 HTML 呈现?

[英]How to change the HTML rendering of a Pandoc element?

我正在尝试从 .odt 文件自定义脚注的默认 HTML 输出。

例如带有如下脚注的文件:

一些带脚注的文字1

将呈现以下 HTML 输出:

<ol class="footnotes">
    <li id="fn1" role="doc-endnote">
        <p>Content of footnote number 1. <a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p>
    </li>
</ol>

相反,我希望输出一个扁平的段落,并硬编码一个如下所示的数字:

<p>1. Content of footnote number 1. <a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p>

我使用了 Pandoc repo 中的sample.lua的一部分,但没有工作,该过程被此错误阻止:

$ pandoc --lua-filter=my-filter.lua file.odt -o file.html

Error running filter my-filter.lua:
my-filter.lua:7: bad argument #1 to 'gsub' (string expected, got table)
stack traceback:
        [C]: in function 'string.gsub'
        my-filter.lua:7: in function 'Note'

下面是我尝试的脚本,我想我天真地忽略了一些明显的东西,或者我不太了解过滤器的工作原理。

-- Table to store footnotes, so they can be included at the end.
local notes = {}

function Note(s)
    local num = #notes + 1
    -- insert the back reference right before the final closing tag.
    s = string.gsub(s,
          '(.*)</', '%1 <a href="#fnref' .. num ..  '">&#8617;</a></')
    -- add a list item with the note to the note table.
    table.insert(notes, '<p id="fn' .. num .. '">' .. num .. '. ' .. s .. '</p>')
    -- return the footnote reference, linked to the note.
    return '<a id="fnref' .. num .. '" href="#fn' .. num ..
            '"><sup>' .. num .. '</sup></a>'
end

function Pandoc (doc)
    local buffer = {}
    local function add(s)
    table.insert(buffer, s)
    end
    add(doc)
    if #notes > 0 then
    for _,note in pairs(notes) do
      add(note)
    end
    end
    return table.concat(buffer,'\n') .. '\n'
end

更新

调整@tarleb 回答的部分内容我现在设法修改了内联注释参考链接,但显然第二个函数没有在文档末尾呈现脚注列表。 少了什么东西?

local notes = pandoc.List{}

function Note(note)

    local num = #notes + 1

    -- add a list item with the note to the note table.
    notes:insert(pandoc.utils.blocks_to_inlines(note.content))

    -- return the footnote reference, linked to the note.
    return pandoc.RawInline('html', '<a id="fnref' .. num .. '" href="#fn' .. num ..
            '"><sup>' .. num .. '</sup></a>')
end

function Pandoc (doc)
  doc.meta['include-after'] = notes:map(
    function (content, i)
      -- return a paragraph for each note.
        return pandoc.Para({tostring(i) .. '. '} .. content)
    end
  )
  return doc
end

sample.lua是自定义 Lua 编写器的示例,而不是 Lua 过滤器。 它们可能看起来相似,但完全不同。 例如,过滤器函数修改抽象文档元素,而自定义编写器中的函数通常需要字符串,至少在第一个参数中是这样。

在过滤器中解决此问题的一个好方法是将自定义渲染放在include-after元数据中:

local notes = pandoc.List{}

function Pandoc (doc)
  doc.blocks:walk {
    Note = function (note)
      notes:insert(pandoc.utils.blocks_to_inlines(note.content))
      -- Raw HTML goes into an RawInline element
      return pandoc.RawInline('html', 'footnote link HTML goes here')
    end
  }

  doc.meta['include-after'] = notes:map(
    function (content, i)
      -- return a paragraph for each note.
      return pandoc.Para({tostring(i) .. ' '} .. content)
    end
  )
  return doc
end

经过一些试验和错误后,我设法得到了一个按预期工作的结果,但“风格上”并不是绝对完美的。

请阅读我下面的评论,主要是作为练习,我试图更好地理解如何以想要的方式使用这个伟大的工具,而不是任何合理的人应该以富有成效的方式(或任何方式)。 ;)

我想改进的:

  • 我必须将p元素包装在div中,因为从 Pandoc 2.18开始,无法为 Paragraph 提供直接属性 这是一个小的代码膨胀,但可以接受。

  • 我想使用section元素而不是div将所有注释放在文档末尾(在Pandoc函数中使用),但我还没有找到一种方法来创建RawBlock元素,然后将注释块添加到它。

我完全不精通 Lua,几乎没有掌握 Pandoc 如何工作的一些概念,所以我非常有信心我在下面所做的并不是最佳的。 欢迎提出建议!

local notes = pandoc.List{}

function Note(note)

    local num = #notes + 1

    -- create a paragraph for the note content
    local footNote = pandoc.Para(
        -- Prefix content with number, ex. '1. '
        {tostring(num) .. '. '} ..
        -- paragraph accept Inline objects as content, Note content are Block objects
        -- and must be converted to inlines
        pandoc.utils.blocks_to_inlines(note.content) ..
        -- append backlink
        { pandoc.RawInline('html', '<a class="footnote-back" href="#fnref' .. num ..  '" role="doc-backlink"> ↩︎</a>')}
        )

    -- it's not possible to render paragraphs with attribute elements as of Pandoc 2.18
    -- so wrap the footnote in a <div> with attributes and append the element to the list
    notes:insert(pandoc.Div(footNote, {id = 'fn' .. num, role = 'doc-endnote'}))

    -- return the inline body footnote reference, linked to the note.
    return pandoc.RawInline('html', '<a id="fnref' .. num .. '" href="#fn' .. num ..
            '"><sup>' .. num .. '</sup></a>')
end

function Pandoc (doc)

  if #notes > 0 then
  -- append collected notes to block list, the end of the document
  doc.blocks:insert(
    pandoc.Div(notes:map(
        function (note)
            return note
        end
      )),
      -- attributes
      {class = 'footnotes', role = 'doc-endnotes'}
  )
  end

  return doc
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM