I\'m rewriting my blog to use Jekyll. Jekyll uses the Liquid templating language so it makes it a little more difficult to learn how to customize.
I\'d like to group
Did not much like the other answer so here's an alternative for you. Basic logic: Display year/month only if it "new":
{% assign var currentYear = 0 %}
{% assign var currentMonth = 0 %}
{% for post in site.posts %}
{% capture year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% capture month %}{{ post.date | date: "%B" }}{% endcapture %}
{% if currentYear != year %}
<div>
<h2>{{ year }}</h2>
</div>
{% assign var currentYear = year %}
{% endif %}
{% if currentMonth != month %}
<div>
<h3>{{ month }}</h3>
</div>
{% assign var currentMonth = month %}
{% endif %}
<p>{{ post.title }}</p>
{% endfor %}
These previous solutions are fantastic but luckily in late 2016, Jekyll added a group_by_exp filter that can do this much more cleanly.
{% assign postsByYear =
site.posts | group_by_exp:"post", "post.date | date: '%Y'" %}
{% for year in postsByYear %}
<h1>{{ year.name }}</h1>
<ul>
{% for post in year.items %}
<li><a href="{{ post.url }}">{{ post.title }}-{{ post.date }}</a></li>
{% endfor %}
</ul>
{% endfor %}
Documentation can be found on the Jekyll Templates page.
Variation of Ankit R Gadiya's answer. The inner for
loop was displaying the html code. I needed to de-indent it to get it to properly render the markup. I also added the post's excerpt:
{% assign postsByYear = site.posts | group_by_exp:"post", "post.date | date: '%Y'" %}
{% for year in postsByYear %}
<h1>{{ year.name }}</h1>
{% assign postsByMonth = year.items | group_by_exp:"post", "post.date | date: '%B'" %}
{% for month in postsByMonth %}
<h2>{{ month.name }}</h2>
<ul>
{% for post in month.items %}
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
<br>{{ post.excerpt }}
</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
Example:
It can be done with much, much less Liquid code than in the existing answers:
{% for post in site.posts %}
{% assign currentdate = post.date | date: "%Y" %}
{% if currentdate != date %}
<li id="y{{currentdate}}">{{ currentdate }}</li>
{% assign date = currentdate %}
{% endif %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
This will return exactly the HTML specified in your question:
<li id="y2013">2013</li>
<li><a href="/2013/01/01/foo/">foo</a></li>
<li id="y2012">2012</li>
<li><a href="/2012/02/01/bar/">bar</a></li>
<li><a href="/2012/01/01/baz/">baz</a></li>
However, this is not the optimal solution, because the year numbers are "only" list items as well.
It's not much more Liquid code to put the year into a headline and to begin a new <ul>
for each year's posts:
{% for post in site.posts %}
{% assign currentdate = post.date | date: "%Y" %}
{% if currentdate != date %}
{% unless forloop.first %}</ul>{% endunless %}
<h1 id="y{{post.date | date: "%Y"}}">{{ currentdate }}</h1>
<ul>
{% assign date = currentdate %}
{% endif %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% if forloop.last %}</ul>{% endif %}
{% endfor %}
The generated HTML:
<h1 id="y2013">2013</h1>
<ul>
<li><a href="/2013/01/01/foo/">foo</a></li>
</ul>
<h1 id="y2012">2012</h1>
<ul>
<li><a href="/2012/02/01/bar/">bar</a></li>
<li><a href="/2012/01/01/baz/">baz</a></li>
</ul>
You can also group by month and year instead (so that the headlines are February 2012
, January 2012
and so on).
To do this, you just need to replace date: "%Y"
(in the second line of both above examples) by date: "%B %Y"
.
(%B
is the full month name, see the documentation)
<ul>
{% for post in site.posts %}
{% assign year = post.date | date: "%Y" %}
{% if year != prev_year %}
<h3>{{year}}</h3>
{% endif %}
<li>
<span>{{ post.date | date: "%B %e, %Y" }}</span>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% assign prev_year = year %}
{% endfor %}
</ul>
Some solutions above are very complex but then as @Trevor pointed out that we can levarage Jekyll's group_by_exp
filter. Also I liked the solution but what I needed was grouped by Year and then inside that list grouped by Month. So, I tweaked it a little bit.
{% assign postsByYear = site.posts | group_by_exp:"post", "post.date | date: '%Y'" %}
{% for year in postsByYear %}
<h1>{{ year.name }}</h1>
{% assign postsByMonth = year.items | group_by_exp:"post", "post.date | date: '%B'" %}
{% for month in postsByMonth %}
<h2>{{ month.name }}</h2>
<ul>
{% for post in month.items %}
<li><a href="{{ post.url }}">{{ post.title }}-{{ post.date }}</a></li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}