<!--
On line 11 you’ll notice an unless forloop.last. This is because it’s a quick an easy way to keep the array index in bounds. The following lines show how you can use a tag’s name to pull the tag from site.tags. I checked for post.title != null because I don’t want to display pages without titles.
-->
<div id="tags">
<h1>Tags</h1>
<ul class="tag-box inline">
{% for item in (0..site.tags.size) %}
{% unless forloop.last %}
{% capture this_word %}{{ tag_words[item] | strip_newlines }}{% endcapture %}
<li><a href="#{{ this_word | cgi_escape }}">{{ this_word }} <span>{{ site.tags[this_word].size }}</span></a></li>
{% endunless %}
{% endfor %}
</ul>
{% for item in (0..site.tags.size) %}
{% unless forloop.last %}
{% capture this_word %}{{ tag_words[item] | strip_newlines }}{% endcapture %}
<h2 id="{{ this_word | cgi_escape }}">{{ this_word }}</h2>
<ul class="posts">
{% for post in site.tags[this_word] %}
{% if post.title != null %}
<li itemscope><span class="entry-date"><time datetime="{{ post.date | date_to_xmlschema }}" itemprop="datePublished">{{ post.date | date: "%B %d, %Y" }}</time></span> » <a href="{{ post.url }}">{{ post.title }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endunless %}
{% endfor %}
</div>
<!--
Line 1 above will get the tag name for every tag on the site and set them to the site_tags variable. Each tag object contains both the tag name and a list of the associated posts. This capture statement is all on one line so that the commas can reliably be used as delimiters. Line 2 creates the tag_words variable that is a sorted array of the tag names.
-->
{% capture site_tags %}
{% for tag in site.tags %}
{{ tag | first }}
{% unless forloop.last %},{% endunless %}
{% endfor %}
{% endcapture %}
{% assign tag_words = site_tags | split:',' | sort %}