![](/assets/images/image-default.png)
A Tag To Prevent Manual Updates
In a previous post, I added some Ruby code to be able to update the categories of the posts by simply moving the post from one subfolder to another. This works well if there are no links between the posts, but it causes issues otherwise.
For example, before moving the editing minima post(_posts/2022-12-26-editing-minima.md
) to the category subdirectory, I would refer to it from other posts using post_url
liquid tag like this:
{% post_url_short 2022-12-26-editing-minima %}
Once I move the post to the subdirectory _posts/site-updates
, the link reference will break (and prevent me from serving the site). This issue can be solved by updating the path in the reference - see the updated reference below.
<!-- non-convenient approach (default tag)-->
{% post_url_short site-updates/2022-12-26-editing-minima %}
The solution above is not a great solution. Even if I go through every link and update it, there is still a big issue remaining: if in the future I want to move one post from one category to another (from one subdir to another) it will be necessary to update every other post that links to the one I am moving.
What caught my attention is that Jekyll matching method “path-date-slug”, while it is very accurate, it is too much for the way my site works. I will never have two posts on the same date with the same slug, therefore if I had a tag that identified the post by matching “date-slug”, it would be good enough for me. The code below creates such a tag:
# _plugins/post_url_short_tag.rb
module Jekyll
class PostUrlShortTag < Liquid::Tag
def initialize(tag_name, input, tokens)
super
@input = input.strip
end
def render(context)
puts "Executing tag 'post_url_short', input: '#{@input}'"
# Splitting the text inputted when the tag was called (argument)
date = @input[0...10] # Extract the first 10 characters as date
puts "\tDate extracted from input: '#{date}'"
slug = @input[11..-1] # Extract from the 12th character to the end as slug
puts "\tSlug extracted from input: '#{slug}'"
# We are considering slug as the text after the date in the filename of the post file.
# If we were specifically checking the slug we would go `p.data['slug']`, but it's
# not the case - we consider the slug the last part of the file name (in `YYYY-MM-DD-example.md`
# it would be `example`, ignoring the front matter). This assumes that filenames are unique.
site = context.registers[:site]
post = site.posts.docs.find { |p| p.date.strftime('%Y-%m-%d') == date && p.basename.split('.').first[11..-1] == slug }
if post
puts "\tPost found with title '#{post.data['title']}', of date '#{post.data['date']}'"
else
puts "\tPOST NOT FOUND"
end
post.url if post
end
end
end
Liquid::Template.register_tag('post_url_short', Jekyll::PostUrlShortTag)
Using the new tag post_url_short
, I will not need to change the path of the references to a post every time I change it from one subdir to the other. See below for an example of how the new tag is used.
<!-- convenient approach (new tag) -->
{% post_url_short 2022-12-26-editing-minima %}