Chronological Taxonomy Listings in Hugo

Added by to Tools on and tagged · site · hugo ·

About 2 minutes to read (352 words)

Pretty Print Terminal Files With Bat Turning Taskwarrior Posts Into a Series

The archive pages now list tags and categories such that the ones with most recent posts come first!

That may not sound impressive or even necessary. Hugo's normal taxonomy ordering .Data.Terms.ByCount and .Data.Terms.Alphabetical are sufficient for normal cases, and taxonomy detail pages already present their posts in a reverse chronology.

This site isn't quite a normal case. The Random Geekery Blog is almost six years old, and includes archived content from other sites dating back to 2000. My many obsessions have waxed and waned over the years. Presenting tags by name or by number of posts means we must dig to find out what's relevant to me lately. I find that frustrating because of the way my brain holds information: fresh topics are near the top, and older stuff is somewhere down below when I need it.

After the traditional grumbling about how this would be a two minute task with Perl, I set to the task of figuring it out. Let's skip the bits where I messed around with $.Scratch and get straight to what worked in layout/_default/terms.html.

First, I built a list of relevant information by stepping through the terms of that particular taxononomy. For each tag, category, or whatever, convert the publishing date of the most recent post with that tag (or category, or whatever) to a .Unix timestamp. Create a dict with the term and its associated timestamp, then append it to a slice.

{{- $stamped_terms := slice -}}
{{- range $term, $value := .Data.Terms -}}
  {{- $last_stamp := (index $value.Pages.ByDate.Reverse 0).Date.Unix -}}
  {{- $term_stamp := dict "term" $term "stamp" $last_stamp -}}
  {{- $stamped_terms = $stamped_terms | append $term_stamp -}}
{{- end -}}

Momentarily setting aside concerns for falsehoods programmers believe about UNIX time, I have a list of terms and their freshest post's timestamp. Leap seconds probably won't be an issue here.

map[stamp:1143504000 term:43-things]
...
map[stamp:1526515200 term:zentangle]

I sort that list based on the timestamp, in descending order. Grab the term from the dict and then it's pretty much the same taxonomy summary I had before.

<dl>
  {{ range $stamp := sort $stamped_terms "stamp" "desc" -}}
    {{- $key := index $stamp "term" -}}
    {{- $value := index $.Data.Terms $key -}}
    <dt>
      <a href="/{{ $.Data.Plural | urlize }}/{{ $key | urlize }}/">{{ $key }}</a>
    </dt>
    <dd>
      {{- $first_post := index $value.Pages.ByDate 0 -}}
      {{ if eq $value.Count 1 }}
        Includes 1 post from {{ $first_post.Date.Format $.Site.Params.DateForm }}
      {{ else }}
        {{- $last_post := index $value.Pages.ByDate.Reverse 0 -}}
        Includes {{ $value.Count }} posts from
        {{ $first_post.Date.Format $.Site.Params.DateForm }}
        to
        {{ $last_post.Date.Format $.Site.Params.DateForm }}
      {{ end }}
    </dd>
  {{ end }}
</dl>

And that's pretty much it! Had to post in case I needed this information later.