Jekyll/Liquid Templating: How to group blog posts by year?

前端 未结 8 1187
無奈伤痛
無奈伤痛 2020-11-28 04:45

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

相关标签:
8条回答
  • 2020-11-28 04:49

    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 %}
    
    0 讨论(0)
  • 2020-11-28 04:52

    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.

    0 讨论(0)
  • 2020-11-28 04:57

    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:

    example

    0 讨论(0)
  • 2020-11-28 04:59

    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)

    0 讨论(0)
  • 2020-11-28 05:01
    <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>
    
    0 讨论(0)
  • 2020-11-28 05:06

    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 %}
    
    0 讨论(0)
提交回复
热议问题