[英]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 .. '">↩</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.