在同一个文档中分离 YAML 和纯文本
Separate YAML and plain text on the same document
在使用 django 构建博客时,我意识到将文章的文本和所有相关信息(标题、作者等)一起存储在一个 human-readable 文件中非常实用格式,然后使用简单的脚本将这些文件记入数据库。
话虽如此,YAML 的可读性和易用性引起了我的注意,YAML 语法的唯一缺点是缩进:
---
title: Title of the article
author: Somebody
# Other stuffs here ...
text:|
This is the text of the article. I can write whatever I want
but I need to be careful with the indentation...and this is a
bit boring.
---
我认为这不是最佳解决方案(尤其是当文件将由临时用户编写时)。像这样的格式可能会好得多
---
title: Title of the article
author: Somebody
# Other stuffs here ...
---
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
有什么解决办法吗?最好使用 python。
也欢迎其他文件格式的建议!
我发现 Front Matter 做的正是我想做的。
还有a python package.
不幸的是,这是不可能的,人们认为可行的方法是在单独的文档中对单个标量使用 |
:
import ruamel.yaml
yaml_str = """\
title: Title of the article
author: Somebody
---
|
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
"""
for d in ruamel.yaml.load_all(yaml_str):
print(d)
print('-----')
但这不是因为 |
是 block indentation indicator。尽管在顶层缩进 0(零)很容易工作,但 ruamel.yaml(和 PyYAML)不允许这样做。
然而,您自己解析它很容易,这比使用前端包的优势在于您可以使用 YAML 1.2,并且不限于使用 YAML 1.1,因为 frontmaker 使用 PyYAML。另请注意,我使用了更合适的文档结尾标记 ...
来将 YAML 与 markdown 分开:
import ruamel.yaml
combined_str = """\
title: Title of the article
author: Somebody
...
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
"""
with open('test.yaml', 'w') as fp:
fp.write(combined_str)
data = None
lines = []
yaml_str = ""
with open('test.yaml') as fp:
for line in fp:
if data is not None:
lines.append(line)
continue
if line == '...\n':
data = ruamel.yaml.round_trip_load(yaml_str)
continue
yaml_str += line
print(data['author'])
print(lines[2])
给出:
Somebody
I want...
(round_trip_load
允许转储并保留注释、锚名称等)。
在使用 django 构建博客时,我意识到将文章的文本和所有相关信息(标题、作者等)一起存储在一个 human-readable 文件中非常实用格式,然后使用简单的脚本将这些文件记入数据库。
话虽如此,YAML 的可读性和易用性引起了我的注意,YAML 语法的唯一缺点是缩进:
---
title: Title of the article
author: Somebody
# Other stuffs here ...
text:|
This is the text of the article. I can write whatever I want
but I need to be careful with the indentation...and this is a
bit boring.
---
我认为这不是最佳解决方案(尤其是当文件将由临时用户编写时)。像这样的格式可能会好得多
---
title: Title of the article
author: Somebody
# Other stuffs here ...
---
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
有什么解决办法吗?最好使用 python。 也欢迎其他文件格式的建议!
我发现 Front Matter 做的正是我想做的。 还有a python package.
不幸的是,这是不可能的,人们认为可行的方法是在单独的文档中对单个标量使用 |
:
import ruamel.yaml
yaml_str = """\
title: Title of the article
author: Somebody
---
|
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
"""
for d in ruamel.yaml.load_all(yaml_str):
print(d)
print('-----')
但这不是因为 |
是 block indentation indicator。尽管在顶层缩进 0(零)很容易工作,但 ruamel.yaml(和 PyYAML)不允许这样做。
然而,您自己解析它很容易,这比使用前端包的优势在于您可以使用 YAML 1.2,并且不限于使用 YAML 1.1,因为 frontmaker 使用 PyYAML。另请注意,我使用了更合适的文档结尾标记 ...
来将 YAML 与 markdown 分开:
import ruamel.yaml
combined_str = """\
title: Title of the article
author: Somebody
...
Here there is the text of the article, it is not valid YAML but
just plain text. Here I could put **Markdown** or <html>...or whatever
I want...
"""
with open('test.yaml', 'w') as fp:
fp.write(combined_str)
data = None
lines = []
yaml_str = ""
with open('test.yaml') as fp:
for line in fp:
if data is not None:
lines.append(line)
continue
if line == '...\n':
data = ruamel.yaml.round_trip_load(yaml_str)
continue
yaml_str += line
print(data['author'])
print(lines[2])
给出:
Somebody
I want...
(round_trip_load
允许转储并保留注释、锚名称等)。