Jekyll/Liquid Templating: Как группировать сообщения в блогах по годам?
Я переписываю свой блог, чтобы использовать Jekyll. Jekyll использует язык шаблонов Liquid, поэтому он немного усложняет процесс настройки.
Я хотел бы сгруппировать свой список сообщений в блогах по годам. Как я могу написать код Liquid, чтобы это сделать?
{% for post in site.posts %}
<li><!-- display post year here (but only once, per year) --></li>
<li>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% endfor %}
Ответы
Ответ 1
Если вы хотите разбить его на год, вот код:
{% for post in site.posts %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
{% if forloop.first %}
<h2 id="{{ this_year }}-ref">{{this_year}}</h2>
<ul>
{% endif %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% if forloop.last %}
</ul>
{% else %}
{% if this_year != next_year %}
</ul>
<h2 id="{{ next_year }}-ref">{{next_year}}</h2>
<ul>
{% endif %}
{% endif %}
{% endfor %}
Если вы хотите разбить его на год и месяцы, это может быть достигнуто следующим образом:
{% for post in site.posts %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% capture this_month %}{{ post.date | date: "%B" }}{% endcapture %}
{% capture next_year %}{{ post.previous.date | date: "%Y" }}{% endcapture %}
{% capture next_month %}{{ post.previous.date | date: "%B" }}{% endcapture %}
{% if forloop.first %}
<h2 id="{{ this_year }}-ref">{{this_year}}</h2>
<h3 id="{{ this_year }}-{{ this_month }}-ref">{{ this_month }}</h3>
<ul>
{% endif %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% if forloop.last %}
</ul>
{% else %}
{% if this_year != next_year %}
</ul>
<h2 id="{{ next_year }}-ref">{{next_year}}</h2>
<h3 id="{{ next_year }}-{{ next_month }}-ref">{{ next_month }}</h3>
<ul>
{% else %}
{% if this_month != next_month %}
</ul>
<h3 id="{{ this_year }}-{{ next_month }}-ref">{{ next_month }}</h3>
<ul>
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
Это только вопрос, где вы делаете срез в цикле.
Ответ 2
Это можно сделать с гораздо меньшим количеством жидкого кода, чем в существующих ответах:
{% 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 %}
Это вернет точно HTML, указанный в вашем вопросе:
<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>
Однако это не оптимальное решение, так как номера года являются "только" элементами списка.
Это не намного больше Жидкий код, чтобы помещать год в заголовок и начинать новый <ul>
за каждый год:
{% 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 %}
Сгенерированный 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>
Вы можете также группировать по месяцам и годам вместо (чтобы заголовки были February 2012
, January 2012
и т.д.).
Для этого вам просто нужно заменить date: "%Y"
(во второй строке обоих приведенных выше примеров) на date: "%B %Y"
.
(%B
- полное имя месяца, см. documentation)
Ответ 3
Эти предыдущие решения фантастичны, но, к счастью, в конце 2016 года Jekyll добавил фильтр group_by_exp
, который может сделать это гораздо более чисто.
{% 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 %}
Документацию можно найти на странице Jekyll Templates.
Ответ 4
Некоторые вышеприведенные решения очень сложны, но затем @Trevor указал, что мы можем использовать фильтр Jekyll group_by_exp
. Также мне понравилось решение, но то, что мне было нужно, было сгруппировано по году, а затем внутри этого списка, сгруппированного по месяцам. Итак, я немного изменил его.
{% 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 %}
Ответ 5
Try:
{% for post in site.posts %}
{% capture this_year %}{{ post.date | date: "%Y" }}{% endcapture %}
{% if forloop.first %}
<h2 id="{{ this_year }}-ref">{{this_year}}</h2>
<ul class="posts">
{% else %}
{% if this_year != last_year %}
</ul>
<h2 id="{{ this_year }}-ref">{{this_year}}</h2>
<ul class="posts">
{% endif %}
{% endif %}
<li>
<span class="post-date">{{ post.date | date_to_string }} »</span>
<a href="{{ post.url }}">{{ post.title }}</a>
</li>
{% if forloop.last %}
</ul>
{% endif %}
{% capture last_year %}{{ this_year }}{% endcapture %}
{% endfor %}
Ответ 6
<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>
Ответ 7
Не очень понравился другой ответ, так что здесь альтернатива для вас. Основная логика: отображать год/месяц, только если он "новый":
{% 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 %}