Pandoc lua 过滤器强制使用紧凑列表
2019-9-15 10:20:40
收藏:0
阅读:94
评论:2
我想编写一个 lua 过滤器,强制 Pandoc 在从 markdown 转换为 PDF 时使用紧凑列表。我注意到,包含嵌套表格/文本/ divs 的列表将不使用 \tightlist 选项,因为 Pandoc AST 对于每个列表项使用 Para 而不是 Plain。我尝试修改这里的示例 链接,以强制所有 BulletList 和 OrderedList 项目变成 Plain,但是当一个项目包含嵌套内容时无法使其正常工作。对于第一个列表项,pandoc mwe.txt -f markdown -t native --lua-filter the-filter.lua 返回一个 Para:
[BulletList
[[Plain [Str "list",Space,Str "1"]]
,[Plain [Str "list",Space,Str "1"]]
,[Plain [Str "list",Space,Str "1"]]]
,Para [Str "Some",Space,Str "paragraph"]
,BulletList
[[Para [Str "list",Space,Str "2"]
,Div ("",["class"],[])
[Para [Str "Nested",Space,Str "div"]]]
,[Plain [Str "list",Space,Str "2"]]
,[Plain [Str "list",Space,Str "2"]]]]
我不知道该如何解决这个问题:
- 我应该使用
walk_block并将每个列表项更改为Plain吗? - 对于
#blocks> 1 的情况如何处理?我该如何将Para更改为Plain,然后包含任何嵌套内容(比如说我有两个嵌套的 divs)?
mwe.txt
- list 1
- list 1
- list 1
Some paragraph
- list 2
::: {.class}
Nested div
:::
- list 2
- list 2
the-filter.lua
local List = require 'pandoc.List'
function compactifyItem2 (blocks)
if (#blocks == 1) then
if (blocks[1].t == 'Para') then
return {pandoc.Plain(blocks[1].content)}
else
return blocks
end
elseif (#blocks == 2) then -- I assume I have to change the Para and nest the child content
if (blocks[1].t == 'Para') then
blocks.content = pandoc.Plain(blocks[1].content) .. blocks[2].content
return {blocks.content}
end
else
return blocks
end
end
function compactifyList (l)
l.content = List.map(l.content, compactifyItem2)
return l
end
return {{
BulletList = compactifyList,
OrderedList = compactifyList
}}
点赞
用户7361270
原始答案在使用 Pandoc 2.11 和通过 Google 文档导出的 docx 文件时无法工作。有关详细信息,请参见 此问题。这是原始答案的修改版本。
-- 源代码:https://stackoverflow.com/a/57943159/7361270
-- 由 makeworld 修改
-- 遍历项目中的所有块,将“顶层”的 Para 转换为 Plain 块。
function compactifyItem (blocks)
-- 按步骤遍历块列表,使用变量 `i` 记录元素在列表中的索引,并将当前块赋值给 `blk`。
for i, blk in ipairs(blocks) do
if blk.t == 'Para' then
-- 更新项目中的块列表。
blocks[i] = pandoc.Plain(blk.content)
elseif blk.t == 'BlockQuote' then
-- 这是 Google 文档中的问题,每个项目符号都在块引用中。
-- https://github.com/jgm/pandoc/issues/6824
blocks[i] = pandoc.Plain(blk.content[1].content)
end
end
return blocks
end
function compactifyList (l)
-- l.content 是 pandoc.List 的实例,因此以下代码等同于 pandoc.List.map(l.content, compactifyItem)
l.content = l.content:map(compactifyItem)
return l
end
return {{
BulletList = compactifyList,
OrderedList = compactifyList
}}
2020-11-14 00:50:15
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

你已经非常接近了。我相信以下代码可以适用于一般情况:
--- 遍历所有块的项目,将 'top-level' Para 转换为 Plain block。 function compactifyItem (blocks) -- 逐步遍历块列表, 用变量 `i` 记录块在列表中的索引,用 `blk` 记录当前块。 for i, blk in ipairs(blocks) do if blk.t == 'Para' then -- 更新该项目的块列表。 blocks[i] = pandoc.Plain(blk.content) end end return blocks end function compactifyList (l) -- l.content 是 pandoc.List 的一个实例,因此以下代码与 pandoc.List.map(l.content, compactifyItem) 等价 l.content = l.content:map(compactifyItem) return l end return {{ BulletList = compactifyList, OrderedList = compactifyList }}多块项目是链接帖子中遗漏的情况。然而,人们可能会对何时压缩列表有不同的意见。以上代码应该压缩_所有_列表。
使用
walk_blocks会有意外的副作用,因为它会影响_所有_块,包括 Div 下面嵌套的 Para 块。