Pandoc lua 过滤器强制使用紧凑列表

我想编写一个 lua 过滤器,强制 Pandoc 在从 markdown 转换为 PDF 时使用紧凑列表。我注意到,包含嵌套表格/文本/ divs 的列表将不使用 \tightlist 选项,因为 Pandoc AST 对于每个列表项使用 Para 而不是 Plain。我尝试修改这里的示例 链接,以强制所有 BulletListOrderedList 项目变成 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
}}
点赞
用户2425163
用户2425163

你已经非常接近了。我相信以下代码可以适用于一般情况:

--- 遍历所有块的项目,将 '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 块。

2019-09-15 10:18:53
用户7361270
用户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