ssg  
Where to Discuss?

Local Group

Preface

Goal: Miscellanous range loop to achieved wordpress like side panel widget.

Source Code

This article use tutor-07 theme. We will create it step by step.


5: Recent Posts

This require a new filter in main configuration.

Filter: Limit

Since nunjucks does not have a builty in function for limit. We need to add limit filter in .eleventy.js:

  // Limit Filter: Copy paste from Jérôme Coupé
  eleventyConfig.addNunjucksFilter("limit", function(array, limit) {
    return array.slice(0, limit);
  });

Later you can use this filter as code below:

  {% set posts = collections.posts | limit(5) %}

You can see how flexible nunjucks is.

Layout: Nunjucks Page or Post

Consider examine only recent posts:

  <aside class="column is-one-thirds">
    {% include "widget/recent-posts.njk" %}
  </aside>

Partial Widget: Nunjucks Recent Post

{% extends "layouts/widget.njk" %}

{% set color = 'lime' %}

{% block widget_header %}
  <strong>Recent Posts</strong>
  <span class="fa fa-newspaper is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  {% set posts = collections.posts | limit(5) %}
  <ul class="widget-list">
    {%- for post in posts -%}
    <li><a href="{{ post.url | url }}">{{ post.data.title }}</a></li>
    {%- endfor -%}
  </ul>
{% endblock %}

The Loop

After sorting the posts array by date, I limit the result for only first five result.

  {% set posts = collections.posts | limit(5) %}
  <ul class="widget-list">
    {%- for post in posts -%}
    <li><a href="{{ post.url | url }}">{{ post.data.title }}</a></li>
    {%- endfor -%}
  </ul>

Render: Browser

You can open page kind, or post kind, to test this widget.

11ty: Widget: Recent Posts


6: Tags

Just a simple loop example.

Layout: Nunjucks Page or Post

Consider examine only tags:

  <aside class="column is-one-thirds">
    {% include "widget/tags.njk" %}
  </aside>

Partial Widget: Nunjucks Recent Post

{% extends "layouts/widget.njk" %}

{% set color = 'light-blue' %}

{% block widget_header %}
  <strong>Tags</strong>
  <span class="fa fa-tag is-pulled-right"></span>
{% endblock %}

{% block widget_body %}
  {%- for tag in collections.tagList -%}
    {%- set tagUrl %}/tags/{{ tag | slug }}/{% endset -%}
    <a class="tag is-small is-light
              {{ color }} z-depth-1 hoverable p-b-5"
       href="{{ tagUrl | url }}">
      <span class="fa fa-tag"></span>&nbsp;{{ tag }}
    </a>&nbsp;
  {%- endfor -%}
  
  <div class="clearfix"></div>
{% endblock %}

The Loop

This is actually, only a simple loop example, but with complex html formatting.

  {%- for tag in collections.tagList -%}
    {%- set tagUrl %}/tags/{{ tag | slug }}/{% endset -%}
    <a class="tag is-small is-light
              {{ color }} z-depth-1 hoverable p-b-5"
       href="{{ tagUrl | url }}">
      <span class="fa fa-tag"></span>&nbsp;{{ tag }}
    </a>&nbsp;
  {%- endfor -%}

Render: Browser

You can open page kind, or post kind, to test this widget.

11ty: Widget: Tags


7: Grouped Archives

Making a grouping archive by month and year is not hard, it just need carefully carved with patient. Consider this step by step procedure to make this happened:

  • Grouping by Year

  • Grouping by Year, then Month

  • Give a Nice Formatting.

Filter: mapdate

We need previously discussed mapdate filter, to sort year and month.

  // Custom: Grouping by date
  eleventyConfig.addNunjucksFilter("mapdate", function(posts) {
    return posts.map(post => ({ 
      ...post,
      year:      moment(post.date).format("Y"),
      month:     moment(post.date).format("MM"),
      monthtext: moment(post.date).format("MMMM")
    }));
  });

You might want to read the article again.

Grouping by Year

This require two loops.

  1. Year Loop, using mapdate Filter

  2. Posts Loop.

{% block widget_body %}

  {% set posts = collections.posts %}
  {% set page_year = page.date | date('Y')  %}

  {%- set posts = posts | mapdate  -%}
  {%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}

  {%- for year, postsInYear in groupByYear -%}
      {%- if year == page_year -%}
        <ul class="widget-list">
          {%- for post in postsInYear | sort(false, true, 'month') -%}
            <li>
              <a href="{{ post.url | url }}">
                {{ post.data.title }}
              </a>
            </li>
            {%- endfor -%}
        </ul>
      {%- endif -%}
  {%- endfor -%}

{% endblock %}

11ty: Widget: Archive This Year

Grouping by Year, then Month

This require three loops.

  1. Year Loop, using mapdate Filter

  2. Month in Year Loop, using mapdate Filter

  3. Posts Loop.

{% extends "layouts/widget.njk" %}

{% set color = 'green' %}

{% block widget_header %}
  <strong>Archive This Month</strong>
  <span class="fa fa-archive is-pulled-right"></span>
{% endblock %}

{% block widget_body %}

  {% set posts = collections.posts %}
  {% set page_year = page.date | date('Y')  %}
  {% set page_month = page.date | date('MM')  %}

  {%- set posts = posts | mapdate  -%}
  {%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}

  {%- for year, postsInYear in groupByYear -%}
      {%- if year == page_year -%}
        {%- set groupByMonth = postsInYear | groupBy('month') -%}
        {%- set groupByMonth = groupByMonth | dictsort | reverse -%}

        {%- for month, postsInMonth in groupByMonth -%}
          {%- if month == page_month -%}
            <ul class="widget-list">
            {%- for post in postsInMonth | sort(false, true, 'month') -%}

            <li>
              <a href="{{ post.url | url }}">
                {{ post.data.title }}
              </a>
            </li>
            {%- endfor -%}
            </ul>
          {%- endif -%}
        {%- endfor -%}
      {%- endif -%}
  {%- endfor -%}

{% endblock %}

11ty: Widget: Archive This Month

Give a Nice Formatting.

Each stuff should have their own header.

{% extends "layouts/widget.njk" %}

{% set color = 'green' %}

{% block widget_header %}
  <strong>Archive</strong>
  <span class="fa fa-archive is-pulled-right"></span>
{% endblock %}

{% block widget_body %}

  {% set posts = collections.posts %}
  {% set page_year = page.date | date('Y')  %}
  {% set page_month = page.date | date('MM')  %}

  {%- set posts = posts | mapdate  -%}
  {%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}

  {%- for year, postsInYear in groupByYear -%}
      <div class ="archive-year p-t-5" id="{{ year }}">
        <a href="{{ "/pages/archives-by-month" | url }}#{{ year }}">
        {{ year }}</a>
      </div>

      {%- if year == page_year -%}
        {%- set groupByMonth = postsInYear | groupBy('month') -%}
        {%- set groupByMonth = groupByMonth | dictsort | reverse -%}

        <ul class="widget-archive m-t-0">
        {%- for month, postsInMonth in groupByMonth -%}
          <li class="list-month">
            <span id="{{ year }}-{{ month }}">
                  <a href="{{ "/pages/archives-by-month" | url }}#{{ year }}-{{ month }}">
                  {{ month }}</a> - {{ year }}</span>
          </li>

          {%- if month == page_month -%}
          <li>
            <ul class="widget-list">
            {%- for post in postsInMonth | sort(false, true, 'month') -%}

            <li>
              <a href="{{ post.url | url }}">
                {{ post.data.title }}
              </a>
            </li>
            {%- endfor -%}
            </ul>
          </li>
          {%- endif -%}
        {%- endfor -%}
        </ul>
      {%- endif -%}
  {%- endfor -%}

{% endblock %}

11ty: Widget: Archive Tree Grouped

This widget is specifically made for post kind, because we have already set date for each post kind.


What is Next ?

Consider continue reading [ Eleventy - Widget - Data ]. We are going to explore eleventy static data feature with widget.

Thank you for reading.