[英]Jekyll/Liquid Templating: How to group blog posts by year?
I'm rewriting my blog to use Jekyll.我正在重写我的博客以使用 Jekyll。 Jekyll uses the Liquid templating language so it makes it a little more difficult to learn how to customize.
Jekyll 使用 Liquid 模板语言,因此学习如何自定义变得更加困难。
I'd like to group my list of blog posts by year.我想按年份对我的博客文章列表进行分组。 How would I write the Liquid code to be able to do this?
我将如何编写 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 %}
It can be done with much, much less Liquid code than in the existing answers:它可以用比现有答案少得多的 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 %}
This will return exactly the HTML specified in your question:这将准确返回您的问题中指定的 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>
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:将年份放入标题并为每年的帖子开始一个新的
<ul>
并不是更多的 Liquid 代码:
{% 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:生成的 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).您也可以按月和年分组(这样标题是
February 2012
、 January 2012
February 2012
January 2012
等)。
To do this, you just need to replace date: "%Y"
(in the second line of both above examples) by date: "%B %Y"
.为此,您只需将
date: "%Y"
(在上述两个示例的第二行中)替换为date: "%B %Y"
。
( %B
is the full month name, see the documentation ) (
%B
是完整的月份名称,请参阅文档)
If you want to break it down by year, here's the code:如果你想按年份分解,这里是代码:
{% 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 %}
If you want to break it down to year and months it can be achieved like this:如果你想把它分解成年和月,可以这样实现:
{% 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 %}
It is only a matter of where do you make the cut on the loop.这只是你在循环上的哪里进行切割的问题。
These previous solutions are fantastic but luckily in late 2016, Jekyll added a group_by_exp
filter that can do this much more cleanly.这些以前的解决方案非常棒,但幸运的是,在 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 %}
Documentation can be found on the Jekyll Templates page .文档可以在Jekyll 模板页面找到。
Some solutions above are very complex but then as @Trevor pointed out that we can levarage Jekyll's group_by_exp
filter.上面的一些解决方案非常复杂,但正如@Trevor指出的那样,我们可以利用 Jekyll 的
group_by_exp
过滤器。 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 %}
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 %}
<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>
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 %}
Variation of Ankit R Gadiya 's answer . Ankit R Gadiya答案的变化。 The inner
for
loop was displaying the html code.内部
for
循环显示 html 代码。 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:示例:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.