Tags? 31 August, 2015

After doing my initial post yesterday I realised it'd be useful to have tags (or categories, whatever your preferred nomenclature) support. It's an easy way for a user to quickly find everything relating to, say, Pretzel without having to read about cats. How do we go about getting such a feature? Remeember that Pretzel is a static blog engine. Everything is generated offline on your computer and then uploaded to your host (in my case, Github Pages) so there's no hitting a database to pull back the relevant files.

If you investigate a little bit you'll find that when you're viewing an individual post the template used to generate the static HTML is _layouts/post.html which seems to have some code relating to tags;


    <li><a href="/tag/pretzel">pretzel</a></li>

    <li><a href="/tag/blog">blog</a></li>

The default set up has some support for it! Excellent! If you look at the mark down source files for your post you'll see there's a block of YAML at the top (actually this is something Jekyll refers to as Front Matter and is how it determines the file is special and needs processing. Pretzel follows this same convention). We need to add some tags to this block. The Front Matter for this post might be;

---
layout: post
title: "Tags?"
tags: [ pretzel, blog ]
---

This tells Pretzel that this post has two tags associated with it; Pretzel and blog. Let's fire up Pretzel and "taste" things...

Tag Rendering

Success! I'll just go click on those tag links and...

404, Tag Not Found

I should have known that'd be too easy. If you have a look about the place you'll find that there's a plugin for Jekyll to support tags. But that's not that helpful to us. So back to the drawing board. I came across a post on using tags on Github Pages - it seems that Github Pages don't support the tags plugin so Jekyll users are in a similar boat to us. Interesting!

Going through the steps in the Minddust post we can straight away skip the first two - the default Pretzel templates already contain markup for tags. Let's start with creating a new layout. Create a new file _layouts/posts_by_tag.html and we'll copy the content from Minddust;

<h1>Articles by tag :</h1>
<div>
    
        <p>There are no posts for this tag.</p>
    
</div>

After a bit of trial and error I found you don't actually need _data/tags.yml either so ignore that. We do, however, have to create a template-per-tag. This is where such a method will kind of fall down. If you use lots and lots of tags this is the sort of thing that you are (well, I am, anyhow) likely to forget. If you do then your readers will get a 404 when they click on a tag that you haven't "populated" yet. In lieu of a better solution we'll live with this. Now we'll create our first tag layout file - for me that's tag/blog.md. (Note: The tag portion is because our URLs will be of the form tag/blog - if you wanted these to be of the form my-awesome-tags/blog your blog.md would instead live in the my-awesome-tags directory. Jekyll / Pretzel will copy directories from the input to the output unless they start with an underscore).

---
layout: posts_by_tag
tag: blog
permalink: /tag/blog
---

Nothing else is needed in our layout file. A couple of notes; the layout value should be the filename of your layout file, without the path or extension, that you created earlier (eg. I have _layouts/posts_by_tag.html so this value is posts_by_tag). The permalink tag here just sets the output URL to be used. I want to serve my tag page as /tag/blog instead of the default /tag/blog.html.) Now that that's done let's test it out!

No articles?!?

... And apparently I have even fewer blog posts than I thought! The good news is we aren't getting a 404 anymore. The bad news is... we're not getting our nice list of posts for the tag. What gives? I did a little digging and it turns out it's the syntax of the layout file. Whilst Pretzel is largely compatible with Jekyll it isn't 100% so. The way it does tags is one of those differences. In Jekyll it seems like it's a dictionary of tag names to posts. However in Pretzel tags are a list of tag items each of which has the name of the tag and all of the posts for that tag. (Side note: I believe Categories work the same way). So our copy-pasta'd layout file just isn't going to cut it.

<h1>Posts by tag </h1>
<div>
    
    
    
        
    
        
    
        
    
        
    
        
    
        
    
    
    
        <p>There's no posts for ""!</p>
    
</div>

First off we're going to set a variable HasTag to false. We'll then loop through all of the tags that have been used on our site and compare the Name to the tag the user is currently looking at. If they match we set HasTag to true and loop through all of the Posts on the tag and output a link to the post using it's title. Finally if HasTag is still false we can print out "No tags found" style message. Now let's try again...

It's ugly, but it works!

... And it works! It's not pretty but it's a list of all my posts. Now why does this look so bland compared to the rest of the posts (not that they're terribly pretty, but still!). If you snoop about your setup you'll see there's _layouts/layout.html which has all the base styling for your site. When you look at the default _layouts/post.html you'll see at the top it has

---
layout: layout
---

It might look a little redundant but it's actually saying "Inherit the layout for this file from the file stored at _layouts/layout.html". So, we just need to add a similar tag to our posts_by_tag.html;

---
layout: layout
---
<h1>Posts by tag </h1>
<div>
    
    
    
        
    
        
    
        
    
        
    
        
    
        
    
    
    
        <p>There's no posts for ""!</p>
    
</div>

Prettier styled posts

And that's about it! Have a look through the list of Liquid Variables for other details you may wish to include on your listing page (such as the post.date). And finally don't forget you'll need to go through and create a corresponding .md file in tag for each tag you use on your site. In the future I'll look at seeing if this is something I can automate as I'm not one for doing something a computer will do much more reliably.

blog comments powered by Disqus