Reputation: 2150
I'm using jekyll-bootstrap to maintain a blog on GitHub.
I'd like to have a sorted tags_list. The tag with the most posts comes first. Then I can have a display that shows the first tags with bigger font-size and last tags with smaller font-size. And I also want a splice function.
If in python/Jinja2, I'd like some code like this:
{% for tag in sorted_tags[:10] %}
<li style="font-size:{{ tag.count }}px;">{{ tag.name }}</li>
{% endfor %}
What's the equivalent implementation in ruby/jekyll?
Upvotes: 7
Views: 2087
Reputation: 182000
This is how I'm sorting by the number of posts in a tag (descending), without any plugins (i.e. GitHub Pages compatible).
It also works when your tag names contain spaces; only ,
and :
are forbidden characters (but you can easily change those).
{% capture counts_with_tags_string %}{% for tag in site.tags %}{{ tag[1] | size | prepend:"000000" | slice:-6,6 }}:{{ tag[0] }}{% unless forloop.last %},{% endunless %}{% endfor %}{% endcapture %}
{% assign counts_with_tags = counts_with_tags_string | split:"," | sort | reverse %}
<ol>
{% for count_with_tag in counts_with_tags %}
{% assign tag = count_with_tag | split:":" | last %}
{% assign count = site.tags[tag] | size %}
<li><a href="/blog/tags/{{ tag | slugify }}">{{ tag }} ({{ count }})</a></li>
{% endfor %}
</ol>
It's super gross. What it does:
counts_with_tags_string
is set to a string like 000005:first_tag,000010:second_tag,000002:third_tag
. The zero-padded numbers are generated using the filter chain | prepend:"000000" | slice:-6,6
.counts_with_tags
.:
to find the original tag name. We could find the count in the same way, but because it's zero padded, it's easier to look it up using site.tags[tag] | size
instead.Upvotes: 3
Reputation: 833
I'm hosting my blog on github and wanted a solution to sorting a tag list that did not involve any jekyll plugins since Github doesn't allow for custom plugins (jekyll bootstrap attempts this as well). My post here doesn't really answer the question since I sort by tag name, and NOT by size. You can adapt this method to output the tag size as well in the string and then do some fancier spliting to get a different sort order (but it will be messy)
I was able to do this with the following code:
{% capture tagString %}{% for tag in site.tags %}{{ tag[0] }}{% unless forloop.last %}|{% endunless %}{% endfor %}{% endcapture %}
{% assign tags = tagString | split: '|' | sort: 'downcase' %}
<div id="cloud">
{% for tag in tags %}
{% assign number = site.tags[tag].size %}
{% assign slug = tag | downcase | replace: ' ', '_' %}
<span class="{% if number == 1 %}small{% elsif number <= 5 %}medium{% elsif number <= 10 %}large{% else %}huge{% endif %}">
<a href="#tag-{{ slug }}">{{ tag | downcase }}</a>
</span>
{% endfor %}
</div>
It's kind of odd since I capture a string of tags (using |
as separator) and then use that to create an array. After that point (in the loop) I can refer to the tag as tag
and the list of sites that use that tag as site.tags[tag]
.
I use this on my blog: https://github.com/kelsin/kelsin.github.io/blob/master/tags/index.html
The rest of the code is just how I've chosen to make a tag cloud on my tag page. Hope this helps someone else looking for a solution (without plugins)!
Upvotes: 0
Reputation: 7242
I only needed to do this in one place, on the page where my list of Tags was listed, so I wrote it as a Jekyll filter:
tag_index.html
<h2>Posts by Tag</h2>
<ul class="tags-list">
{{ site.tags | render_tags_list }}
</ul>
_plugins/filters.rb
module Jekyll
module Filters
def render_tags_list(tags)
sorted_tags = tags.keys.sort_by! { |tag| tag.downcase }
str = ''
sorted_tags.each { |tag|
str << '<li>' + tags[tag].size.to_s + ' - <a href="/tag/' + tag + '">' + tag + '</a></li>'
}
str
end
end
end
You could certainly just allow the filter to return sorted_tags
above if you wanted to keep a better separation between "view" logic and programming logic, but my case was very simple. Trying to re-access a hash value by a specific key using Liquid templating wasn't a very concise process, or maybe I was just doing it wrong, but was much easier in Ruby.
Upvotes: 0
Reputation: 1001
I thought that the tags array is sorted. Assuming so, you can do this:
{% for tag in site.tags %}
<li style="font-size: {{ tag[1].size }}px">{{ tag[0] }}</li>
{% endfor %}
That feels a little hacky, but it should work. Unfortunately, Liquid doesn't currently allow you to sort arrays within your templates. If you want to do any sorting on the array, you'd probably have to write a plugin to do so - it shouldn't be too complex. In fact, there's an existing plugin for sorting accessors that may do it: https://github.com/krazykylep/Jekyll-Sort
Upvotes: 0