Jekyll 自定义 collection 钩子
Jekyll custom collection hook
这个问题困扰我一段时间了。
生成的 Jekyll 站点会在所需页面上显示正确的 collection 及其所有信息。但是除了(默认)posts
collection 之外的所有 collection 都不能在 ruby 插件中使用。
案例:
我们有一个使用 Jekyll 的博客站点。
为了使用作者信息和 vice-versa 丰富博客 posts,有一些使用 Jekyll::Hooks.register
的自定义插件
博客 post 是用 markdown 语言编写的,并且都包含一些 YAML 格式的信息:
---
layout: post
authors: [author]
title: 'title'
intro: a short intro text
image: /path/to/image.png
tags: [jekyll, collections]
category: Programming
comments: true
---
这是使用作者信息丰富 post 的代码:
Jekyll::Hooks.register :site, :post_read do |site|
puts 'Enriching posts with link to authors'
site.posts.docs.each { |post|
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
end
下一步:
我用两个 collection 更新了站点,因为我们还想展示将要提供的培训课程和讲座。
两个 collection 都包含一些降价格式的文件,文件顶部有相同类型的 YAML 信息。
--- ---
layout: talk layout: training
speakers: [author] trainers: [author]
title: Title title: Title
subtitle: Subtitle subtitle: Subtitle
duration: 120 minutes duration: 180 minutes
level: beginner level: intermediate
image: /path/to/image.png image: /path/to/image.png
tags: [] tags: []
category: Talks category: Training
comments: false comments: false
--- ---
然后我将 collection 添加到 _config.yml
collections:
training:
output: true
permalink: /training/:path/
talks:
output: true
permalink: /talks/:path/
defaults:
- scope:
path: "training"
type: training
values:
layout: training
- scope:
path: "talks"
type: talks
values:
layout: talk
所需实施:
现在我也想和作者一起丰富讲座和培训课程。
因为 posts,讲座和培训文件都在 collection 中,我假设将 posts
object 更改为 talks
或training
应获得所需的 object 并循环遍历它们。
所以我把自定义插件改成了这个:
Jekyll::Hooks.register :site, :post_read do |site|
puts 'Enriching posts with link to authors'
site.posts.docs.each { |post|
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
site.talks.docs.each { |talk|
talk.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
end
但是我得到这个错误:
jekyll 3.7.3 | Error: undefined method `talks' for #<Jekyll::Site:0x00007f9325268e90>
困扰我的是,当我记录 collection 内容时,我得到以下结果:(格式化为 json 结构以提高可读性)
{
"posts"=>
#<Jekyll::Collection @label=posts docs=[
#<Jekyll::Document _posts/2017-02-01-page1.md collection=posts>,
#<Jekyll::Document _posts/2017-02-02-page2.md collection=posts>,
#<Jekyll::Document _posts/2018-04-04-page3.md collection=posts>
]>,
"training"=>
#<Jekyll::Collection @label=training docs=[
#<Jekyll::Document _training/page1.md collection=training>,
#<Jekyll::Document _training/page2.md collection=training>,
#<Jekyll::Document _training/page3.md collection=training>
]>,
"talks"=>
#<Jekyll::Collection @label=talks docs=[
#<Jekyll::Document _talks/page1.md collection=talks>,
#<Jekyll::Document _talks/page2.md collection=talks>,
#<Jekyll::Document _talks/page3.md collection=talks>
]>
}
据我所知,talks
和 training
collection 与 posts
collection 处于同一级别和数据结构].
问题:
我怎样才能在我的自定义插件中获得 talks/training collection 以便我可以用作者信息丰富数据。
为了便于阅读,我减少了文件和输出。完整的代码库可在 GitHub
你必须调查 site.collections
。
这可以解决问题:
Jekyll::Hooks.register :site, :post_read do |site|
['posts', 'talks'].each do collection{
site.collections[collections].docs.each { |talk|
talk.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
}
end
David 给我指出了正确的方向。
我不得不遍历集合
site.collections.each do |collection|
collection.each do |item|
if item.respond_to?("each")
item.docs.each do |post|
if post.data['authors']
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
end
end
end
end
end
我仍然觉得很奇怪 site
对象上没有其他集合。
但这对我有用。
这个问题困扰我一段时间了。
生成的 Jekyll 站点会在所需页面上显示正确的 collection 及其所有信息。但是除了(默认)posts
collection 之外的所有 collection 都不能在 ruby 插件中使用。
案例:
我们有一个使用 Jekyll 的博客站点。
为了使用作者信息和 vice-versa 丰富博客 posts,有一些使用 Jekyll::Hooks.register
博客 post 是用 markdown 语言编写的,并且都包含一些 YAML 格式的信息:
---
layout: post
authors: [author]
title: 'title'
intro: a short intro text
image: /path/to/image.png
tags: [jekyll, collections]
category: Programming
comments: true
---
这是使用作者信息丰富 post 的代码:
Jekyll::Hooks.register :site, :post_read do |site|
puts 'Enriching posts with link to authors'
site.posts.docs.each { |post|
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
end
下一步:
我用两个 collection 更新了站点,因为我们还想展示将要提供的培训课程和讲座。
两个 collection 都包含一些降价格式的文件,文件顶部有相同类型的 YAML 信息。
--- ---
layout: talk layout: training
speakers: [author] trainers: [author]
title: Title title: Title
subtitle: Subtitle subtitle: Subtitle
duration: 120 minutes duration: 180 minutes
level: beginner level: intermediate
image: /path/to/image.png image: /path/to/image.png
tags: [] tags: []
category: Talks category: Training
comments: false comments: false
--- ---
然后我将 collection 添加到 _config.yml
collections:
training:
output: true
permalink: /training/:path/
talks:
output: true
permalink: /talks/:path/
defaults:
- scope:
path: "training"
type: training
values:
layout: training
- scope:
path: "talks"
type: talks
values:
layout: talk
所需实施:
现在我也想和作者一起丰富讲座和培训课程。
因为 posts,讲座和培训文件都在 collection 中,我假设将 posts
object 更改为 talks
或training
应获得所需的 object 并循环遍历它们。
所以我把自定义插件改成了这个:
Jekyll::Hooks.register :site, :post_read do |site|
puts 'Enriching posts with link to authors'
site.posts.docs.each { |post|
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
site.talks.docs.each { |talk|
talk.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
end
但是我得到这个错误:
jekyll 3.7.3 | Error: undefined method `talks' for #<Jekyll::Site:0x00007f9325268e90>
困扰我的是,当我记录 collection 内容时,我得到以下结果:(格式化为 json 结构以提高可读性)
{
"posts"=>
#<Jekyll::Collection @label=posts docs=[
#<Jekyll::Document _posts/2017-02-01-page1.md collection=posts>,
#<Jekyll::Document _posts/2017-02-02-page2.md collection=posts>,
#<Jekyll::Document _posts/2018-04-04-page3.md collection=posts>
]>,
"training"=>
#<Jekyll::Collection @label=training docs=[
#<Jekyll::Document _training/page1.md collection=training>,
#<Jekyll::Document _training/page2.md collection=training>,
#<Jekyll::Document _training/page3.md collection=training>
]>,
"talks"=>
#<Jekyll::Collection @label=talks docs=[
#<Jekyll::Document _talks/page1.md collection=talks>,
#<Jekyll::Document _talks/page2.md collection=talks>,
#<Jekyll::Document _talks/page3.md collection=talks>
]>
}
据我所知,talks
和 training
collection 与 posts
collection 处于同一级别和数据结构].
问题:
我怎样才能在我的自定义插件中获得 talks/training collection 以便我可以用作者信息丰富数据。
为了便于阅读,我减少了文件和输出。完整的代码库可在 GitHub
你必须调查 site.collections
。
这可以解决问题:
Jekyll::Hooks.register :site, :post_read do |site|
['posts', 'talks'].each do collection{
site.collections[collections].docs.each { |talk|
talk.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
}
}
end
David 给我指出了正确的方向。
我不得不遍历集合
site.collections.each do |collection|
collection.each do |item|
if item.respond_to?("each")
item.docs.each do |post|
if post.data['authors']
post.data['authors'].collect! { |author_username|
site.data['authors'][author_username]
}.compact!
end
end
end
end
end
我仍然觉得很奇怪 site
对象上没有其他集合。
但这对我有用。