HomeBlog
Jekyll Related Posts without Plugin - 羡辙杂俎
2014.07.15 22:57:38
Jekyll Related Posts without Plugin

What will you learn in this post?

This post introduces how to implement related posts function with Jekyll. Since GitHub disables plugin for security reasons, plugins like LawrenceWoodman / related_posts-jekyll_plugin cannot be used. Default site.related_posts may return recent posts when there aren’t enough posts sharing the same tags with current post.

Jekyll’s Native Support

Jekyll has native support for related posts function, which can be used with Liquid as site.related_posts.

However, as we can see from its source code, it lists posts with mutual tags without ordering by how many mutual tags they share. In this way, if A post is tagged with a, b and c, B post is tagged with a and C post is tagged with a and c, A’s related posts may contain only B but not C if you set the limit to be 1. Apparently, this doesn’t make sense.

Using Plugin

LawrenceWoodman / related_posts-jekyll_plugin is an easy-to-use Jekyll plugin to implement related posts feature.

It solves the above problem by calculating how many mutual tags they share and sort by it, as we can see from the source code below.

def related_posts(posts)
    return [] unless posts.size > 1
    highest_freq = Jekyll::Post.tag_freq(posts).values.max
    related_scores = Hash.new(0)
    posts.each do |post|
        post.tags.each do |tag|
            if self.tags.include?(tag) && post != self
                cat_freq = Jekyll::Post.tag_freq(posts)[tag]
                related_scores[post] += (1+highest_freq-cat_freq)
            end
        end
    end

    Jekyll::Post.sort_related_posts(related_scores)
end

But just as the default Jekyll behaves, it returns recent posts if there aren’t enough posts sharing the same tags. I think this doesn’t make sense. After all, why should a post called How to become a good programmer be related to I was bitten by a bug yesterday just because there are no other related posts?

So, I improved it with the following code and pulled a request.

related_scores.each do |post, score|
    if score < 0
        related_scores.delete(post)
    end
end

I have almost no experience with Ruby, but this isn’t too hard for me.

Without Plugin

After I’ve done with the previous improvement and pushed my blog code to GitHub with joy, I found it didn’t word! :scream:

I thought it was the cache, but it still doesn’t change when I tried to clear the cache and even visit it using a different browser and a different device.

Finally, I realized that this is caused by GitHub’s disabling plugins for security concerns. I knew this before, but didn’t know that this is the reason I was looking for.

Then, I improved the default one and return only those with mutual tags. It still cost me much time, since the syntax of Liquid is so strange! :weary:

You can’t use !abc to check if abc is false. Instead, you should use abc == false.

You can’t use abc++ or even abc = abc + 1 to increment a variable. Instead, you should use something as strange as appending a character * at a time, and then check abc.size to get its length as a string and this is how you increment a variable! :joy: But, believe me, this is not the strangest syntax when you use Liquid.

Who can tell me why this syntax is so strange!

博文对你有帮助吗?如果有的话,要不要送我一本书呢?:heart_eyes:

微信公众号“羡辙部落格”(xianzheblog)提供本站优质非技术类博文推送。

Creative Commons License
Every blog post in this site by Wenli Zhang is licensed under a CC 3.0 License, based on a work at Github. You can see the source code of this blog site at github.com/Ovilia/blog.

Comments

comments powered by Disqus