Reputation: 1415
I am using the standard jekyll installation to maintain a blog, everything is going fine. Except I would really like to tag my posts.
I can tag a post using the YAML front matter, but how do I generate pages for each tag that can will list all posts for a tag?
Upvotes: 50
Views: 16177
Reputation: 10324
I've written a pre-push
hook to detect missing tag pages. It will offer to create the missing tag pages with a bash script, gentag
. The hook will also warn if pushing a draft.
For simplicity, it assumes tags are entered as a yaml array in front matter which are collected with yq
.
There's also a pre-receive
hook to deploy the site on a personal webserver.
Upvotes: 0
Reputation: 53
I do these with CSS. First lists an element and use the tag name as its id.
<span id="{{ site.posts | map: 'tags' | uniq | join: '"></span><span id="' }}"></span>
And then lists all the post and use its tags as a value for the "tags" custom attribute.
{% for post in site.posts %}
<article class="post" tags="{% for tag in post.tags %}{{tag}}{% if forloop.last == false %}{{" "}}{% endif %}{% endfor %}">
<h3><a href="{{post.url}}">{{post.title}}</a></h3>
</article>
{% endfor %}
And then in CSS, hide all the posts by default, and only show posts with tags matches the url id/ hash
.post {
display: none;
}
{% for tag in site.tags %}#{{tag[0]}}:target ~ [tags~={{tag[0]}}]{% if forloop.last == false %}, {% endif %}{% endfor %} {
display: block;
}
/*
The compiled version will look like this
#tagname:target ~ [tags~="tagname"], #tagname2:target ~ [tags~="tagname2"] {
display: block;
}
*/
I made an article about this here.
Upvotes: 0
Reputation: 36451
Here is a solution with alphabetically sorted tags on a single page.
It uses Liquid only, which means that it works on GitHub Pages:
{% capture tags %}
{% for tag in site.tags %}
{{ tag[0] }}
{% endfor %}
{% endcapture %}
{% assign sortedtags = tags | split:' ' | sort %}
{% for tag in sortedtags %}
<h3 id="{{ tag }}">{{ tag }}</h3>
<ul>
{% for post in site.tags[tag] %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
{% endfor %}
You can see it in action here.
EDIT:
There's also a way to generate a separate page for each tag without plugins (which will work on GitHub Pages).
I have a more detailed explanation on my blog:
Separate pages per tag/category with Jekyll (without plugins)
First, you need a new layout file:
/_layouts/tagpage.html
:---
layout: default
---
<h1>{{ page.tag }}</h1>
<ul>
{% for post in site.tags[page.tag] %}
<li>
{{ post.date | date: "%B %d, %Y" }}: <a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
With this layout file, you can add a new tag page by adding a new file with just two lines of YAML front-matter.
Here's an example for the jekyll
tag:
/tags/jekyll/index.html
:---
layout: tagpage
tag: jekyll
---
The only disadvantage of this approach: each time you use a new tag for the first time, you have to remember to create a new two-line file for it.
To generate the root index file (i.e. the list of tags that links to /tags/jekyll/index.html
etc.), you can use a similar solution like the one on top of this answer where I generate a single page with alphebetically sorted tags:
{% capture tags %}
{% for tag in site.tags %}
{{ tag[0] }}
{% endfor %}
{% endcapture %}
{% assign sortedtags = tags | split:' ' | sort %}
{% for tag in sortedtags %}
<a href="/tags/{{ tag }}/">{{ tag }}</a><br>
{% endfor %}
This will generate a list of links like this:
<ul>
<li><a href="/tags/.net/">.net</a></li>
<li><a href="/tags/authentication/">authentication</a></li>
<li><a href="/tags/backup/">backup</a></li>
</ul>
Note that this solution uses a blank to split tags, so it doesn't work when your tags contain blanks and Yevgeniy Brikman's comment applies here as well.
Upvotes: 81
Reputation: 878
Based on Christian's answer above I made a bash script that does what he described.
https://github.com/ObjectiveTruth/objectivetruth.github.io/blob/master/rebuild_tags.sh
Be sure to have the accompanying 14 line vim script in the /non_website_resources/
directory
AND
Make the /_layouts/tagpage.html
shown in Christian's answer above but rename it to /_layouts/tag_pages.html
File structure should be like this:
.jekyll_website_root
├── _posts
├── _layout
│ ├── tag_pages.html
├── rebuild_tags.sh
Run from the root directory ./rebuild_tags.sh
If you get permission denied error be sure to run chmod 777 rebuild_tags.sh
If you look at scripts comments its fairly simple:
Uses sed
to find all the tags in every .md
file in _post
directory
Uses sed
to massage the data to proper format
Takes all the unique tags and makes a directory and a index.html
for each
This way, if you have any new tags, just run the script to rebuild the pages before pushing to github
A nice simple non-plugin way to do tags
EDIT
Removed dependency on other files. Just need the one script!
Upvotes: 1
Reputation: 2031
I use the great Jekyll Tagging plugin that automatically generates a tags cloud and tag pages. Easy to install and use.
Here is a page for the "photo" tag on my blog (in french), and you can see the tags cloud in the bottom.
Upvotes: 1
Reputation: 26230
This gist will generate a page per category for you: https://gist.github.com/524748
It uses a Jekyll Generator plugin, plus a Page subclass.
Upvotes: 14
Reputation: 5652
I had the same question, and stumbled upon this: http://gist.github.com/143571.
It's a rake task which generates a tag list. I modified it slightly, and my version is at: http://github.com/mattfoster/mattfoster.github.com/blob/master/Rakefile.
Whilst this doesn't give you a page per tag, you can use anchors, which is half way there!
Upvotes: 5
Reputation: 2792
Have a look at sites using jekyll. There are a few custom forks which have implemented tagging functionality, hopefully also in the way you want :-)
Upvotes: 8