The XProgramming home page shows three “identified” articles at the top: the most recent Kate article, the most recent “Beyond Agile” article and a randomly-selected “Classic”. On a static site, we think we’ll have to do the random one with some JavaScript. Set that aside.

The other two items are defined at site-generation time and therefore we can set them up when we run Jekyll. So my plan was to enhance the current ronjeffries.com home page to have the most recent “Beyond Agile” article. Simple enough, you’d think.

You’d be wrong. Or, possibly, there is a Liquid trick that I do not as yet know that makes it simple.

The home page layout looks like this:

<!DOCTYPE html>
<html>
  {% include head.html %}
  <body>
    {% include header.html %}
    <div class="page-content">
      <div class="wrapper">
        {{ content }}
        {% include kate.html %}
        {% include beyond.html %}
        {% include posts.html %}
      </div>
    </div>
    {% include footer.html %}
  </body>
</html>

The includes, right now, the list of Kate articles (there’s only one), the single Beyond article, and the list of all posts. (I’m not sure what “content” is doing and will look into that. I’m glad I started writing this article.)

The code we care about today is in beyond.html, of course. It looks like this:

<!-- find and display most recent Beyond Agile article -->
 <h3>Beyond Agile</h3>
 <ul class="post-list">
    {% strip %}
        {% assign date_sorted = (site.pages | sort: 'date' ) %}
        {% assign found = false %}
        {% for page in date_sorted reversed %}
            {% unless found %}
                {% if page.categories contains "Beyond Agile" %}
                    {% assign recent = page %}
                    {% assign found = true %}
                {% endif %}
            {% endunless %}
        {% endfor %}
            <li>
                <p class="page-title"><a class="page-link" href="{{ recent.url | prepend: site.baseurl }}">{{ recent.title }}</a></p>
                <p class="page-blurb">{{recent.blurb}}</p>
            </li>
    {% endstrip %}
</ul>

Let’s talk about this. Our mission is to find the most recent article with category “Beyond Agile” and display it in the <li> tags above. The words there are more or less what you’d expect, referring to recent and its various components, title and so on.

The hard part is how we have to get it.

What I’d rather like to do is consider site.pages, select all the Beyond articles, sort by date, select the last. As far as I can determine, there is no way to build a subset of the site.pages collection. So instead, the code above does this:

  • create date_sorted, all pages sorted by date
  • assert we have not found what we want
  • loop over all pages, reversed (newest first)
  • unless we have already found an article
    • if this is a Beyond article
      • assign it to recent
      • set the found flag

Right. Get all the pages. Sort by date. Loop over all of them in reverse order. Keep a record of the first one with desired category. Keep looping, as far as I know there’s no way to exit. When done looping over 400 articles, you’ve got the one you want. Display it.

This is not what I’d call lovely. I’m proud to have found any way to do it, and I’d welcome being told a better way to do it. The issue is exacerbated by the fact that Liquid is documented almost entirely without examples, and with very cryptic explanations. But mostly, the language has been intentionally crippled, so that you can’t do anything bad with it. I support the idea of not doing anything bad, but it also limits what we can do that’s good.

Anyway, now that I’ve figured it out, after only a couple of hours, I can copy the idea in the two or three other places I need it and be good to go.

But it makes me sad. Worse yet, take a look at the home page. Notice that the article displayed at the top is displayed again in the full list below. On XProgramming, we display the interesting three at the top and then the next most interesting five down below. How am I going to eliminate the favorites picked at the top from the list below? I don’t know yet but I’m pretty sure it involves a headache.