【问题标题】:How pandoc lua filters can be used to add the title as the level-1 header?如何使用 pandoc lua 过滤器将标题添加为 1 级标题?
【发布时间】:2019-08-19 17:40:41
【问题描述】:

当我将多个markdown文件从markdown转换为pdf时,我想使用pandoc lua过滤器。我希望将单个降价文件的标题用作章节(一级标题)。

我学习了现有的例子,我认为这个接近我需要的——基本上我需要将 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

与此降价等效的预期输出(但我的最终格式是 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

【问题讨论】:

  • 不是您问题的完整解决方案,但这有帮助吗? stackoverflow.com/questions/56004886
  • tarleb 感谢您的及时回复。我看过这个例子,确实听起来很接近。但是我不知道如何从 meta.title 写入标题级别 1。
  • 我认为问题源于假设整个文档始终可用于过滤器功能。这通常不是真的。这就是为什么在链接的示例中,首先从元数据中提取标题并将其存储到变量中。只有这样才能修改标题。链接过滤器在您运行时对您有用吗?
  • 你是对的,元信息丢失了。我可以解决的最大问题是让标题从标题添加:``` function Pandoc(doc) local hblocks = {} table.insert(hblocks, pandoc.Header(1, title)) for i,el in对(doc.blocks)做table.insert(hblocks,el)结束返回pandoc.Pandoc(hblocks,doc.meta)结束```

标签: lua pandoc


【解决方案1】:

我认为关键问题是 lua 过滤器仅在将完整的文档集解析为单个 AST 后才运行。因此,在解析之前将各个文件有效地连接起来,以创建具有一组元数据的单个文档。 yaml 元数据块中的单个 title 设置在过滤器有机会运行之前被覆盖。假设您需要从每个单独的元数据块中获取标题(并且不能直接将标题放入),这意味着您不能让 pandoc 加入文件。您将需要分别读取和解析每个文件。幸运的是,使用过滤器很容易做到这一点。

第一步是制作一个包含指向所有其他文件的链接的单个参考文件。

---
title: Combined title
---

![First file](1.md){.markdown}

![Second file](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: Combined 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 对象中获取任何其他内容并将其放入全局对象中。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
  • 2015-12-26
  • 1970-01-01
  • 1970-01-01
  • 2013-10-24
相关资源
最近更新 更多