如何使用pandoc lua过滤器将标题作为一级标题添加?

我想在将多个Markdown文件从Markdown转换为PDF时使用pandoc lua过滤器。我希望将各个Markdown文件的标题用作章节(一级标题)。

我学习了现有的示例,并且我认为这个示例接近我所需的内容--基本上我需要在所有Markdown文件中添加pandoc.Header(1,doc.meta.title),但我很难编写lua过滤器并使其正常工作。

我认为这个问题正在执行类似的操作pandoc filter in lua and walk_block

pandoc命令:

pandoc -N --lua-filter add-title.lua blog/*.md --pdf-engine=xelatex --toc -s -o my_book.pdf

add-title.lua(这是错误的,没有例外,但输出不会发生任何事情):

function add_header (header)
return {
  {Header = pandoc.Header(1, meta.title)}}
end

输入文件:

1.md

---
title: Topic1
---

## Sample Header from file 1.md

text text text

2.md

---
title: Topic2
---

## Sample Header from file 2.md

text text text

预期输出等同于此markdown(但我的最终格式是pdf)

---
title: Title from pandoc latex variable
---
# Topic1

## Sample Header from file 1.md

text text text

# Topic2

## Sample Header from file 2.md

text text text
点赞
用户4536527
用户4536527

我认为关键问题在于 Lua 过滤器只有在解析出完整文档的 AST 后才能运行。因此,在解析之前,所有单独的文件都会被有效地合并为一个带有单个元数据集的单个文档。在过滤器有机会运行之前,yaml 元数据块中的单独“title”设置已被覆盖。假设您需要从每个单独的元数据块中获取标题(而不能直接将标题放入),则这意味着您不能让 pandoc 合并文件。你需要逐个文件读取并解析它们。幸运的是,使用过滤器很容易做到这一点。

第一步是创建一个包含所有其他文件链接的单个引用文件。

---
title: 合并的标题
---

![第一个文件](1.md){.markdown}

![第二个文件](2.md){.markdown}

请注意,链接是使用一个特殊类.markdown的图像指定的。您可以使用其他方法,但是图像很方便,因为它们支持属性并且很容易识别。

现在,我们只需要一个过滤器,它将用链接的 markdown 文件中解析的元素替换这些图像。我们可以通过从 lua 打开文件并使用pandoc.read(参见 https://www.pandoc.org/lua-filters.html#module-pandoc)将它们解析为完整文档来完成此操作。一旦我们有了文档,我们可以从元数据中读取标题并插入新的标题。请注意,我们将过滤器应用于 Para 元素而不是 Image 本身。这是因为 pandoc 将 Block 元素与 Inline 元素分开,并且过滤器的返回值必须是相同类型。Image 过滤器无法返回从文件解析的块列表,但是 Para 可以。

因此,这是最终的代码。

function Para(elem)
    if #elem.content == 1 and elem.content[1].t == "Image" then
      local img = elem.content[1]
      if img.classes:find('markdown',1) then
        local f = io.open(img.src, 'r')
        local doc = pandoc.read(f:read('*a'))
        f:close()

        -- now we need to create a header from the metadata
        local title=pandoc.utils.stringify(doc.meta.title) or "Title has not been set"
         local newHeader=pandoc.Header(1, {pandoc.Str(title)})
        table.insert(doc.blocks, 1, newHeader)
        return doc.blocks
      end
    end
end

如果您在带有以下命令的组合文件上运行它

pandoc -f markdown -t markdown -i combined.md  -s --lua-filter addtitle.lua

您将获得所需的结果。

---
title: 合并的标题
---

Topic 1
=======

Sample Header from file 1.md
----------------------------

text text text

Topic 2
=======

Sample Header from file 2.md
----------------------------

text text text

请注意,包含文件中的任何其他 yaml 元数据都将丢失。您可以通过从单独的 meta 对象中获取任何其他东西并将其放入全局对象中来捕获任何其他内容。

2019-10-24 15:35:55