Search code examples
jekyllgithub-pagesliquid

Is it possible to sort a Jekyll array based on two variables?


On the frontpage of my site, I display the newest few posts:

{% for post in posts limit: 6 %}
  ...
{% endfor %}

This works fine.

Recently I've been going back and editing some old posts, and I want them to show in this list on the frontpage.

I don't want to change their date. Instead, I've been adding a new lastUpdated variable to each post as I edit it, with the date I edited it.

layout: example
lastUpdated: 2020-09-07
---

So now I want to modify the code on my frontpage so that it sorts by lastUpdated if a post has it, and otherwise it should sort by date.

I tried this:

{% assign posts = site.posts
    | reverse
    | sort: "lastUpdated"
    | reverse %}
{% for post in posts limit: 6 %}
  ...
{% endfor %}

I thought that worked, but it turns out that it's sorting all of the edited posts (the posts that contain lastEdited variables) to the front, followed by newly created posts. I want the edited posts and the newly created posts to both show up in this list, based on their "modified" date.

I tried this:

{% assign posts = site.posts
    | sort: "lastUpdated or date" %}
{% for post in posts limit: 6 %}
  ...
{% endfor %}

But that gives me the posts in the default order, presumably because "lastUpdated or date" is not a valid property.

I also tried this:

{% assign posts = site.posts
    | sort: "lastUpdated" or "date" %}
{% for post in posts limit: 6 %}
  ...
{% endfor %}

But not surprisingly, this is a syntax error.

Is there a simple way to do this that I'm missing?


Solution

  • As soon as I wrote this, I nerd-sniped myself into cobbling together a solution that creates two arrays, and then merges them together based on the lastUpdated and date variables.

    {% assign createdPosts = site.posts %}
    {% assign updatedPosts = site.posts | sort: "lastUpdated" | reverse %}
    
    {% assign createdIndex = 0 %}
    {% assign updatedIndex = 0 %}
    
    {% for i in (1..10) %}
      {% assign createdDate = createdPosts[createdIndex].date | date: "%Y-%m-%d" %}
      {% assign updatedDate = updatedPosts[updatedIndex].lastUpdated | date: "%Y-%m-%d" %}
    
      {% if createdDate > updatedDate or updatedDate == nil %}
        // HTML for createdPosts[createdIndex]
        {% assign createdIndex = createdIndex | plus:1 %}
      {% else %}
        // HTML for updatedPosts[updatedIndex]
        {% assign updatedIndex = updatedIndex | plus:1 %}
      {% endif %}
    
    {% endfor %}
    

    One thing to note is that I couldn't compare date and lastUpdated directly, because I got this error: comparison of Date with Time failed, so I had to convert them both to strings.

    This feels pretty complicated, so I might end up going back and populating every post with lastUpdated to keep it simple.