Preface
Goal: Get organized with your theme.
Source Code
This article use tutor-04 theme. We will create it step by step.
4: Content: Category and Tag
My motivation to move code is to refactor, and then reuse.
Like previous code, consider move liquid code,
from content in pages/
folder to partial in _includes/index/
.
Partial Liquid: Terms Array
Consider isolate our liquid code in its own partial file artefact.
{% capture spaceless %}
{% assign term_array = "" | split: "|" %}
{% for tag in terms %}
{% assign term_first = tag | first %}
{% assign term_array = term_array | push: term_first %}
{% endfor %}
{% assign term_array = term_array | sort %}
{% endcapture %}
Partial Liquid: Terms List
And move the view to its own partial file artefact.
<p>Tag List:
<ul>
{% for item in (0..terms.size) %}{% unless forloop.last %}
{% assign this_word = term_array[item] | strip_newlines %}
<li id="{{ this_word | slugify }}" class ="anchor-target">
{{ this_word }}
</li>
{% endunless %}{% endfor %}
</ul>
</p>
This is exactly the same code as previous theme.
Content: Simple Tags List
---
layout : index
title : All Tags
permalink : /tags/
---
{% assign terms = site.tags %}
{% include index/terms-array.html %}
{% include index/terms-list.html %}
Now see how this custom page looks like.
Partial Liquid: Terms Badge
With the same logic, we can make a list of terms badge.
<p>Tag Badges:
{% for item in (0..terms.size) %}{% unless forloop.last %}
{% assign this_word = term_array[item] | strip_newlines %}
<span>[
<a href="#{{ this_word | slugify }}">
{{ this_word }}
</a>
<small>({{ terms[this_word].size }})</small>
]</span>
{% endunless %}{% endfor %}
</p>
This is not a hard thing to do, just need extra imagination.
Partial Liquid: Terms Tree
Why not go further, create tags tree. With each tags as key, and each post as branch list.
<p>Tag Tree:
<ul>
{% for item in (0..terms.size) %}{% unless forloop.last %}
{% assign this_word = term_array[item] | strip_newlines %}
<li id="{{ this_word | slugify }}" class ="anchor-target">
{{ this_word }}
<ul>
{% for post in terms[this_word] %}
{% if post.title != null %}
<li>
<a href="{{ post.url | prepend: site.baseurl }}">
{{ post.title }}
</a>
</li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endunless %}{% endfor %}
</ul>
</p>
Content: Tags Tree
Now is a good time to put the whole thing together.
---
layout : index
title : All Tags
permalink : /tags/
---
{% assign terms = site.tags %}
{% include index/terms-array.html %}
{% include index/terms-badge.html %}
{% include index/terms-tree.html %}
Now see how this custom page looks like.
Content: Categories Tree
Apply the refactored code above for categories page is easy.
---
layout : index
title : All Categories
permalink : /categories/
---
{% assign terms = site.categories %}
{% include index/terms-array.html %}
{% include index/terms-badge.html %}
{% include index/terms-tree.html %}
Now see how this custom page looks like.
5: Content: Archive by Year, then by Month
My motivation to move code is to have complex code by-month
,
while at the same time keeping the simple code by-year
.
This way, I can track, anytime I forget how it works.
Partial Liquid: By Year
Like above code, consider move liquid code,
from content in pages/
folder to partial in _includes/index/
.
{% assign postsByYear = posts
| group_by_exp: "post", "post.date | date: '%Y'" %}
<div id="archive">
{% for year in postsByYear %}
{% capture spaceless %}
{% assign current_year = 'now' | date: '%Y' %}
{% assign year_text = nil %}
{% if year.name == current_year %}
{% assign year_text = year.name
| prepend: "This year's posts (" | append: ')' %}
{% else %}
{% assign year_text = year.name %}
{% endif %}
{% endcapture %}
<section>
<p class ="anchor-target"
id="{{ year.name }}"
>{{ year_text }}</p>
<ul>
{% for post in year.items %}
<li><a href="{{ site.baseurl }}{{ post.url }}">
{{ post.title }}
</a></li>
{% endfor %}
</ul>
</section>
{% endfor %}
</div>
Content: Archive by Year
The code in pages
should be simpler by now.
---
layout : index
title : Archive by Year
permalink : /by-year/
---
{% assign posts = site.posts %}
{% include index/by-year.html %}
Now see how this custom page looks like.
Partial Liquid: By Month
Like above code, we can have better view. With a little effort, we can make a tree view. By year, then by month for each year. Things going to get more complex by now.
{% assign postsByYear = posts
| group_by_exp: "post", "post.date | date: '%Y'" %}
<div id="archive">
{% for year in postsByYear %}
{% capture spaceless %}
{% assign current_year = 'now' | date: '%Y' %}
{% assign year_text = nil %}
{% if year.name == current_year %}
{% assign year_text = year.name
| prepend: "This year's posts (" | append: ')' %}
{% else %}
{% assign year_text = year.name %}
{% endif %}
{% endcapture %}
<section>
<p class ="anchor-target"
id="{{ year.name }}"><b>{{ year_text }}</b></p>
{% assign postsByMonth = year.items
| group_by_exp:"post", "post.date | date: '%m'"
| sort: 'name'
| reverse %}
<ul>
{% for month in postsByMonth %}
<li>
{% for post in month.items limit:1 %}
<div id="{{ year.name }}-{{ month.name }}">
{{ post.date | date: '%b - %Y' }}</div>
{% endfor %}
<ul>
{% for post in month.items %}
<li><a href="{{ site.baseurl }}{{ post.url }}">
{{ post.title }}
</a></li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
</section>
{% endfor %}
</div>
Content: Archive by Year
The code in pages
is also simple.
---
layout : index
title : Archive by Month
permalink : /by-month/
---
{% assign posts = site.posts %}
{% include index/by-month.html %}
Now see how this custom page looks like.
Liquid Loop: How Does It Works?
We have outer loop by year, and inner loop by month.
{% assign postsByYear = posts
| group_by_exp: "post", "post.date | date: '%Y'" %}
{% for year in postsByYear %}
...
{% assign postsByMonth = year.items
| group_by_exp:"post", "post.date | date: '%m'"
| sort: 'name'
| reverse %}
{% for month in postsByMonth %}
{% for post in month.items %}
...
{% endfor %}
{% endfor %}
{% endfor %}
What’s Next?
Consider continue reading [ Jekyll - Plain - Managing Code - Part Three ].
Thank you for reading.