Published 2022-03-26.
Time to read: 1 minutes.
jekyll collection.
I wanted to put up a page that showed articles, ordered by most recently modified.
After working on the problem for a bit, I realized that if every page had a last_modified_at entry in front matter the problem would be much easier.
So I wrote a Ruby program, not a Jekyll plugin, and processed each post in less than two shakes of a lamb’s tail.
#!/usr/bin/env ruby
# Add date: and last_modified_at: fields to front matter for posts that do not have them.
# @return number of lines between the --- lines, which demark front matter
def front_matter_length(contents)
return nil unless contents[0].start_with? "---"
contents[1..].find_index { |line| line.start_with? "---" }
end
# @return date from front matter, or the filename if front matter entry is not present
def read_date(front_matter)
date_line = front_matter
.find { |line| line.start_with? "date:" }
return nil unless date_line
date_line.delete_prefix("date:")
.strip
end
def process(directory)
Dir[directory].each do |file_name|
contents = File.readlines(file_name, chomp: true)
last_front = front_matter_length contents
next unless last_front
front_matter = contents[1..last_front]
date = read_date front_matter
unless date
date = File.basename(file_name)[0..9]
contents.insert(last_front + 1, "date: #{date}") # insert before 2nd ---
last_front += 1
must_save = true
end
modified_at = front_matter.find { |line| line.start_with? "last_modified_at:" }
unless modified_at
contents.insert(last_front + 1, "last_modified_at: #{date}") # insert before 2nd ---
must_save = true
end
File.write(file_name, contents.join("\n")) if must_save
end
end
[
"collections/_posts/**/*.html",
"collections/_drafts/**/*.html",
].each { |dir| process dir }
If you need to do something similar, you could modify the last bit of the program, and type in the paths to your Jekyll website posts.
[
"collections/_posts/**/*.html",
"collections/_drafts/**/*.html",
].each { |dir| process dir }
BTW, I did not convert front matter to YAML because I did not want to change it in any way. Transforming it from text to YAML, and then transforming it back to text again almost certainly would alter the text. I did not want to disturb what was there before, so I just considered front matter as text, and it all went very nicely.