49

我正在重写我的博客以使用 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 %}
4

8 回答 8

60

它可以用比现有答案少得多的 Liquid 代码来完成:

{% 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>

但是,这不是最佳解决方案,因为年份数字也是“唯一”列表项。将年份放在标题中并为每年的帖子
开始新的并不是更多的 Liquid 代码:<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 2012January 2012依此类推)。

为此,您只需将date: "%Y" (在上述两个示例的第二行中)替换为date: "%B %Y".
%B是完整的月份名称,请参阅文档

于 2013-12-25T23:01:19.033 回答
37

如果您想按年份细分,代码如下:

{% 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 %}

这只是你在哪里进行循环切割的问题。

于 2013-09-30T21:56:31.920 回答
32

这些之前的解决方案非常棒,但幸运的是,在 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 模板页面上找到。

于 2017-04-03T17:39:51.280 回答
9

上面的一些解决方案非常复杂,但正如@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 %}
于 2017-05-22T14:22:47.373 回答
2

尝试:

{% 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 }} &raquo;</span>
      <a href="{{ post.url }}">{{ post.title }}</a>
    </li>

  {% if forloop.last %}
    </ul>
  {% endif %}

  {% capture last_year %}{{ this_year }}{% endcapture %}
{% endfor %}
于 2013-10-05T21:36:09.000 回答
2

不太喜欢其他答案,所以这里有一个替代方案。基本逻辑:仅当“新”时才显示年/月:

{% 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 %}
于 2019-05-15T16:45:25.840 回答
2
<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>
于 2017-08-23T18:32:18.527 回答
2

Ankit R Gadiya答案的变体。内部for循环显示 html 代码。我需要取消缩进以使其正确呈现标记。我还添加了帖子的摘录:

{% 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 %}

例子:

例子

于 2020-04-21T14:39:49.113 回答