I try to implement footnotes as defined in CSS Generated Content for Paged Media Module.
With this definition, footnotes have to be inline span
s.
I wrote a first draft of a pandoc
lua
filter.
It is my first pandoc filter (and also the first time I code in lua
).
Here's the filter:
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
It works well for footnotes with unformatted text (formatting is lost due to the use of the stringify()
function): simple footnotes and multiple blocks footnotes are well rendered.
In order to preserve formatting, I tried to use the walk_block()
function on the content
of the Note
element, but I cannot obtain any result.
I got a second problem: the stringify()
function returns a void character string for CodeBlock
elements.
So, when I use this filter on the following markdown
text:
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.
I obtain the following HTML fragment:
<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>
The code block is lost. Is there any way to keep both footnotes' formatting and code blocks?
I found how to process the Note
element.
First, the Note
element is an inline element, so we can use walk_inline
. The weird thing is that a Note
element can embed block elements like Para
or CodeBlock
.
The following filter deal only with Para
and CodeBlock
elements. Formatting is kept.
Since a Para
element is a list of inline elements, it is obvious to reuse those elements in a Span
element.
The CodeBlock
text can also be processed in an inline Code
element.
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
If the Note
element embeds other types of block elements (like a BulletList
or a Table
), one has to develop a specific filter for the walk_inline
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With