如何在Pandoc的 Lua过滤器中把信息从块级元素传递到行内元素
我正在使用pandoc处理一个xhtml文件。该文件包含脚注,脚注在正文中以指向未在正文中的元素的链接来标记。
在AST中,脚注包含在紧随正文文本之后的BulletList中。
我正在转换为LaTeX,且希望正文中的链接被替换为LaTeX的脚注命令。
为了获取脚注的文本,我创建了一个函数,扫描BulletList,并创建一个Lua表,其中包含目标字符串和脚注文本字符串。BulletList函数执行时,这个Lua表已被创建。但不幸的是,由于过滤器函数的默认执行顺序,Link函数在BulletList函数之前执行,导致Lua表为空。
我读到可以在Pandoc Lua Filters中修改过滤器的执行顺序,但我还没搞清楚具体怎么实现。希望得到一些帮助。
这是我的lua过滤器:
footnotes = {}
function BulletList (elem)
local note_count = 0
local bList = elem.content
local label
print ("In BulletList")
for k, v in ipairs(bList) do
label = v[1].content[1].identifier
local note_text
for kk, vv in ipairs(v[3].content) do
local this_text
for kkk, vvv in ipairs(vv.content) do
if vvv.tag == "Link" then
this_text = vvv.content
else
this_text = vvv
end
if note_text == nil then
note_text = pandoc.Inlines(this_text)
else
if pandoc.utils.type(this_text) == "Inlines" then
note_text = note_text .. this_text
else
note_text:insert(this_text)
end
end
end
end
note_count = note_count + 1
footnotes[note_count] = {label, note_text}
print (note_count, footnotes[note_count][1], footnotes[note_count][2])
end
return {} -- Swallow the BulletList
end
function Link (elem)
if FORMAT:match 'latex' then
if elem.classes[1] == "study-note-ref" then
local backRef = elem.identifier
local word = elem.content[2]
local targ = string.sub(elem.target,2)
local note_content
print ("in Link", #footnotes)
for k, v in ipairs(footnotes) do
if v[1] == targ then
note_content = v[2]
end
end
if not note_content then
note_content = "footnote text not found"
end
local new_el = pandoc.Inlines({
word ,
pandoc.RawInline('latex', "\\footnote{\n") ,
note_content ,
pandoc.RawInline('latex', "\n}")
})
return new_el
else
return elem
end
end
end
function Pandoc(doc)
doc = doc:walk {BulletList = BulletList}
print (#footnotes)
return doc:walk {}
end
这是我的AST:
[ Div
( "" , [ "body-block" ] , [] )
[ Div
( "" , [ "verse" ] , [] )
[ Para
[ Str "Text"
, Space
, Str "with"
, Space
, Link
( "BACK_note3a" , [ "study-note-ref" ] , [] )
[ Superscript [ Str "a" ] , Str "footnote" ]
( "#note3a" , "" )
, Str "."
]
]
]
, BulletList
[ [ Para
[ Span
( "note3a" , [] , [] )
[ Link
( "" , [ "BACK" ] , [] )
[ Str "\9664" ]
( "#BACK_note3a" , "" )
]
]
, Div
( "" , [ "label-group" ] , [] )
[ Para
[ Span ( "" , [ "label-verse" ] , [] ) [ Str "3" ]
, Span ( "" , [ "label-marker" ] , [] ) [ Str "a" ]
]
]
, Para
[ Span
( "" , [] , [ ( "note-category" , "cross-ref" ) ] )
[ Link
( "" , [ "scripture-ref" ] , [] )
[ Str "Footnote" , Space , Str "text" ]
( "ref-file.xhtml#p30" , "" )
, Str "."
]
]
]
]
]
解决方案
有多种方法可以修改过滤器的执行顺序。
通过 walking文档::walk 方法允许执行一个过滤器,因此在对 Pandoc 进行过滤时,提供了一种非常灵活的修改文档的方法:
function Pandoc (doc)
doc = doc:walk{
BulletList = function (bl)
-- collect the notes here
end
}
doc = doc:walk{
Link = function (l)
-- replace the footnote links
-- (Could also use `pandoc.Note` instead of `pandoc.RawInline`)
end,
}
return doc
end
另一种方法让过滤器返回多个“子过滤器”,它们按给定的顺序执行。我把这种方法视为已被弃用:
return {
{
BulletList = function (...)
return nil
end
},
{
Link = function (link)
return nil
end
},
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。