5

ruby 中是否有某种方法可以编辑降价文件顶部的 YAML Frontmatter,就像 Jekyll 和 Middleman 中使用的那样?

就像是:

def update_yaml
  #magic that changes A: 1 to A: 2 in Frontmatter block
end

然后我的降价文件将从

---
A: 1
---
# Title
Words. More words. This is the words part of the file.

---
A: 2
---
# Title
Words. More words. This is the words part of the file.

似乎唯一的选择是解析整个文件,然后重写整个文件,只更改所需的部分,但我希望有更好的东西。

4

4 回答 4

4

最近我遇到了同样的问题,作为替代方案,您可以使用python-frontmatter. 它很容易使用。以下是更改 yaml 变量值的代码:

    import frontmatter
    import io
    with io.open('File.md', 'r') as f:
        post = frontmatter.load(f)
        post['A'] = 2

        # Save the file.
        newfile = io.open(fname, 'w', encoding='utf8')
        frontmatter.dump(post, newfile)
        newfile.close()

有关更多示例,您可以访问此页面

于 2017-02-04T06:49:18.783 回答
2

是的,您可以做得更好,您只需从源读取 YAML 文档并在其末尾停止读取(---)然后处理您的 YAML,将其写入新文件(数据的实际长度可能会改变,所以它是您不太可能将其重写到位),然后读取输入文件的其余部分,并将其写出。

我看到的最大问题是,您的 ruby​​ YAML 解析器将在往返过程中丢弃所有使 YAML 人类可读的注释、标签名称和可能的其他内容。

于 2016-04-30T07:10:32.063 回答
2

我不知道有什么更好的,但是实现起来很简单:

require "yaml"

YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m

def update_data(data)
  data.merge("A" => 2)
end

if $stdin.read =~ YAML_FRONT_MATTER_REGEXP
  data, content = YAML.load($1), Regexp.last_match.post_match
  data = update_data(data)
  YAML.dump(data, $stdout)
  $stdout.puts("---", content)
end

上面读取$stdin和写入(在 Ideone 上$stdout查看它的实际操作),但实际上您可能希望从文件中读取并写入Tempfile,并在成功后用 Tempfile 替换原始文件(例如,使用)。FileUtils

如果您想知道,我YAML_FRONT_MATTER_REGEXP 直接从 Jekyll中窃取并修改了它的前端处理代码

于 2016-04-30T04:55:56.240 回答
0

Middleman 的一位开发人员实际上在 Twitter 上联系了 Middleman,并提供了一个具体的 Middleman,但仍然非常慷慨和有益的回应。它在实践中与其他答案相似(截至撰写本文时),但它使用了一些中间人功能。他们的回应(经过编辑以在这种情况下有意义)如下。


如果您制作脚本或扩展,您可以要求middleman-core/util/data提供::Middleman::Util::Data.parse

这将获取一个文件名和一个中间人“源文件”以及一个分隔符列表(---用于前面的内容)并返回 2 个值:前面的数据对象和文件其余部分的字符串内容。

然后,您可以修改此 ruby​​ 对象并写入文件。

所以,阅读看起来像:

require "middleman-core/util/data”

resource = app.sitemap.resources.find_resource_by_destination_path(“whatever.html”)

frontmatter, content = ::Middleman::Util::Data.parse(resource.file_descriptor, app.config[:frontmatter_delims])

并写:

# change frontmatter

::File.write(resource.source_file, %Q{
---
#{frontmatter.to_yaml}
---

#{content}
})

抱歉,数据解析的东西有点奇怪(需要特殊的文件描述符和配置值),这些东西通常不在核心之外使用。

于 2016-05-02T14:07:01.963 回答