HUGO

How to (reverse) sort frontmatter list

I have a list of items in my frontmatter:

---
title: Gallery
images:
  - image:
      description: An apple
      imagefile: apple.jpg
  - image:
      description: Citrus fruit
      imagefile: orange.jpg
  - image:
      description: Yellow and bent
      imagefile: banana.jpg
---

I can iterate over this via {{ range .Params.images }}, which works fine.

Is there a way to reverse the order of the range as is possible for builtin ranges like .Pages?

Things like {{ range (.Params.images).Reverse }} do not work, presumably because these frontmatter-derived ranges aren’t the correct type for that method.

You could save your front matter list to a variable, sort that variable in descending order by some key, then range that variable.

Introducing an extra key really feels like over-engineering in this case. The CMS cannot natively write indices, the order in the frontmatter is the order chosen by the user. Alas, I cannot easily reverse the order at the CMS level either.

Any other ideas welcome.

For now I may fall back on a hack like CSS flex-wrap: flex-reverse; :neutral_face:

No need to add a new key. I meant use the existing description or imagefile.
I’m on my phone so cannot give you a code example at the moment.
But see the hugo docs on the sort function for examples.

Maybe I wasn’t clear on that, but I want to reverse the existing order, not sort it differently. I can see how the title I chose is misleading.

If I could turn the frontmatter-list (I don’t know the type) into a slice somehow, then it would be no problem to revert it.

We may be talking past each other. Once I get back to my laptop I’ll show what I had in mind.

Try this:

{{ range sort .Params.images ".image.imagefile" "desc" }}
{{ .image.imagefile }}
{{ end }}

It will output:

orange.jpg

banana.jpg

apple.jpg

Yeah, this was a misunderstanding, sorry! My intent is an order-preserving reverse:

E D A C B  →  B C A D E

not

E D A C B  →  A B C D E
E D A C B  →  E D C B A

Thanks for the suggestion anyway, still useful to see how that works.

Sorry I’m still not clear on the question. Perhaps someone on here more familiar can help you. Good luck!

You can do something like a reverse range seq:

{{ $slice := your list }}
{{ $len := len $slice }} <!-- get length of list -->
{{ range (seq $len) }} <!-- see docs -->
  {{ $i := sub $len . }} <!-- $i at first iteration will be (len - 1), then (len - 2) etc -->
  {{ index $slice $i }} <!-- get list element at $i -->
{{ end }}
2 Likes

That’s a neat workaround, works well. Thank you!