从Markdown文件中解析YAML

4

我正在处理一些遗留代码,这些设计决策并非由我做出。

该代码需要处理一个有许多子目录的目录,其中包含Markdown文件,并将它们编译成一个大的Markdown文件(使用Markdown-PP:https://github.com/jreese/markdown-pp)。然后它将此文件转换为HTML(使用pandoc: https://pandoc.org/),最终再将其转换为PDF(使用wkhtmltopdf:https://wkhtmltopdf.org/)。

问题在于原始Markdown文件中有很多YAML元数据头部分。当Markdown-PP将它们连结在一起时,生成的大型Markdown文件中就会有许多YAML元数据块。由于pandoc处理YAML的方式(许多头使用相同的键名,pandoc会合并这些单独的YAML头部,只保留对应键的第一个值),因此在将其转换为HTML时,大部分元数据都会丢失。

起初我从未在HTML中看到过任何YAML,但通过正确修改pandoc的HTML模板,我成功改变了这一点。但是每个对应键仅获取第一个值。我不确定pandoc是否有解决这个问题的方法,因此我尝试在pandoc之前尝试将YAML处理成HTML。我尝试使用PyYAML(yaml.load_all())在合并后的Markdown中解析YAML,但只能看到第一个YAML块。

以下是一个YAML块的示例:

---
author: foo
size_minimum: 100
time_req_minutes: 120
# and so on
---

问题在于最终文档中的20多个模块都有这些关联元数据。
为了尝试解析YAML,我使用了从这篇文章中借鉴的代码:Is it possible to use PyYAML to read a text file written with a "YAML front matter" block inside?,并进行了一些修改。
import yaml
import sys

def get_yaml(f):
  pointer = f.tell()
  if f.readline() != '---\n':
    f.seek(pointer)
    return ''
  readline = iter(f.readline, '')
  readline = iter(readline.__next__, '---\n') #underscores needed for Python3?
  return ''.join(readline)

# Remove sys.argv, not sure what it was doing
with open(filepath, encoding='UTF-8') as f:
    config = list(yaml.load_all(get_yaml(f), Loader=yaml.SafeLoader)) # Load all to get all the YAML documents, Loader option required for most recent PyYAML, and list because it was originally returning a generator object
    text = f.read()
    print("TEXT from", f)
    #print(text)
    print("CONFIG from", f)
    print(config)

但即使如此,这只会导致第一个YAML块被读取和输出。

我想要能够解析大型Markdown文件中的YAML,并在正确位置用相应的HTML替换它。 我只是不确定这些(或任何)软件包是否具有此功能。 可能我只需要在原始Markdown文件中手动将YAML更改为HTML(耗时,但如果我一开始就这样做,我可能已经完成了)。


为什么不将每个Markdown文件单独解析为HTML,然后将多个HTML片段组合成一个大的HTML文档呢? - Waylan
把这些片段组合起来有多容易?现在,存在一个索引Markdown文件,告诉Markdown-pp在将它们组合在一起时包含哪些其他Markdown文件(请参见https://github.com/jreese/markdown-pp Readme获取更多详细信息)。这些文件按所需顺序排列,以用于最终的网页(HTML)和文档(PDF)。只要文件名保持不变,就可以更改!INCLUDE语法和文件扩展名从.md到.html?但是,如果出现任何问题,可能需要为HTML创建一个新的“索引”文件,对吗? - pls_help_code_pls
我不熟悉Markdown-pp,但如果您想要每个文件应用YAML frontmatter,则需要单独解析每个Markdown文件(在合并之前)。然后,您可以使用任何解决方案来组合HTML。但是,每个Markdown文档都应生成一个有效的HTML片段,可以轻松地附加到其他片段中。不必担心创建无效的HTML。我猜您唯一需要考虑的是定义顺序并从组合的HTML创建全局目录。针对最后一个问题有许多解决方案。 - Waylan
定义顺序并创建目录是主要关注点。然而,这似乎是解决问题最直接的方法。我能想到的唯一其他方法是解析所有Markdown文件中的YAML,并将其转换为HTML。我认为Markdown-pp和pandoc会忽略HTML,并希望pandoc会将其保留在正确的位置。除此之外,我不确定是否有简单的解决方案。不过,感谢您的所有帮助! - pls_help_code_pls
1个回答

8
这个库怎么样:https://github.com/eyeseast/python-frontmatter
它解析文件中的正文和Markdown,并将Markdown部分放置在生成对象的content属性中。
适用于有前置元数据和没有前置元数据(是否有这样一个词?)的文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接