When I first started this blog, I wasn’t really sure how it would end up or where it would go. I didn’t have any fixed ideas of what content I wanted to add or how it would look. Along the way I cribbed a few things from colleagues at work and the internet in general, and one of those things was the reading time on the post, the estimated number of minutes it will take to read a blog post.

At the time, I didn’t really understand the plugin system in Jekyll (I still don’t to be honest!), so I borrowed this implementation of reading time. The added benefit was I could learn more about Liquid and how it works.

So this is what the reading time in the post now looks like:

Reading Time in Post

This was all great, but when I started to posting my blog links to the company Slack, I learnt about Rich Text Preview and the concept of “unfurling” your links in Slack. I added the basic metadata tags, along with the Facebook and Twitter tags, and the previews now looked a lot better!

Slack Preview

Today I discovered that you can use the additional Twitter tags to include some other custom data that Slack will render nice and bold. I wanted to include the reading time in a similar fashion to how Medium does it, as part of the unfurled data.

Now unfortunately the problem lies in where the reading time calculation is performed and how the Jekyll templating engine works. Lower down pages cannot pass data up to higher templates, and the reading time is calculated at the post level, using the post content variable. However the required metadata tags are set in the head of the HTML document, on the topmost level of the Jekyll layout.

In order to solve this I needed a way to find the raw post object in the site.posts variable and then extract the post content from that. Then I could calculate the reading time off that chunk of html. After using my Google Fu and learning about filters as well as tearing my hair out a bit, I came up with the following:

{% assign currentPost = site.posts | where: "id", page.id | first %}

This gets the current post in the context of the default.html layout page. We can then calculate the reading time based only on the posts content, not the page content, which includes any headings and ancillary content.

The below code snippet can now be included with your other metadata tag generation and it looks like this:

{% if page.date %}
{% assign currentPost = site.posts | where: "id", page.id | first %}

{% assign words = currentPost.content | number_of_words %}
{% capture readingtime = 1 min read %}
{% if words < 360 %}
1 min read
{% else %}
{{ words | divided_by:180 }} min read
{% endif %}
{% endcapture %}

<meta name="twitter:label1" value="Reading Time" />
<meta name="twitter:data1" value="{{ readingtime | strip | strip_newlines }}" />    
{% endif %}

The end result in Slack now looks like this:

Slack Preview with Time

So purdy! Happy Blogging!