HUGO

Order data files by secondary parameter

Sorry, I probably just missed something: How is it possible to sort data file output by a “secondary” parameter?

This is what I need for a huge bibliography:

{{ range .Site.Data.bibliography }}
{{ range sort . "author.family" }}
{{ .title }} …
{{ end }}
{{ end }}

Thank you very much in advance!

You can try something like this.

{{ range sort .Site.Data.bibliography ".author.family" "desc" }}
{{ .title }}
{{ end }}
1 Like

Thanks a lot, @gsienkoPL

Nesting ranges seems to be necessary.

Otherwise Hugo prompts an error message:

error calling sort: author is neither a struct field, a method nor a map element of type interface {}

even if you do not use sort:

can't evaluate field title in type interface {}

Can you point to your code? I have big json data which I treat with range and sort from field inside data in the manner I write in the first post without problems.

{{ $json := getJSON "data/uchwaly.json" }}
{{ range sort $json ".data" "desc" }}
do staff....
{{ end }}

From the error, you don’t have author field in your data.Can you show example of your data?

Thanks for your effort.

I exported a .bib file using

pandoc-citeproc -y bibliography.bib > bibliography.yaml

and then exported it to TOML.

Here is an example:

[[references]]
id = "byron1905complete"
type = "book"
title = "The complete poetical works"
publisher = "Houghton Mifflin"

  [[references.author]]
  family = "Byron"
  given = "George Gordon Byron Baron"

  [[references.issued]]
  year = "1905"

The file is called bibliography.toml located in the data folder, so that references seems to be obsolete in the template file.

A quick update:

Unfortunately no success with getJSON. Again, a secondary field caused an error.

The following sorting method apparently only works with inline frontmatter, not with data files

{{ range (.Date.Pages.ByParam "author.last_name") }}
  <!-- … -->
{{ end }}

I am a bit clueless now.

The problem here is that you have map, not array. Try to save bibliograffy as array

[id1]
id = "byron1905complete"
type = "book"
title = "The complete poetical works"
publisher = "Houghton Mifflin"
family = "Byron"
given = "George Gordon Byron Baron"
year = "1905"
[id2]
...

I think that even with map it should be possible using Scratch. But simple I’m not so good in Hugo to help you with that :confused:

Thanks a lot, @gsienkoPL!

The bib file is really huge so that it is hardly possible to change each entry manually.

Yes, I will have a look Scratch for this use case.

As a last resort javascript could sort the output …

Ok… I think is a little ugly, but it works. It will return sorted map.

Biblio data (\data\bibliography.toml)

[[references]]
id = "1"
type = "book"
title = "Book 1"
publisher = "Publisher 1"

  [[references.author]]
  family = "Author 3"
  given = "a1"

  [[references.issued]]
  year = "1905"
  
[[references]]
id = "2"
type = "book"
title = "Book 2"
publisher = "Publisher 2"

  [[references.author]]
  family = "Author 1"
  given = "a2"

  [[references.issued]]
  year = "5091"
  
[[references]]
id = "3"
type = "book"
title = "Book 3"
publisher = "Publisher 3"

  [[references.author]]
  family = "Author 2"
  given = "a3"

  [[references.issued]]
  year = "1905"

and the code

{{$k := .Site.Data.bibliography.references}}
{{ range $i, $v := $k }}

  {{- if $i -}}{{- end -}}
  {{$a := slice .id .title .type .publisher}}
  {{$b := .author}}
  
  {{ range $o, $p := $b }}
    {{- if $o -}}{{- end -}}
    {{$c := slice .family .given}}
    
    {{$d := union $a $c}}
    {{$d0 := index $d 0}}
    {{$d1 := index $d 1}}
    {{$d2 := index $d 2}}
    {{$d3 := index $d 3}}
    {{$d4 := index $d 4}}
    {{$d5 := index $d 5}}
        
    {{$.Scratch.SetInMap "biblio" $d4 (dict "id" $d0 "type" $d1 "family" $d4) }}     

  {{end}}

{{end}}

{{$.Scratch.GetSortedMapValues "biblio"}}

The clue is to range twice, build a two slice, marge it, and used $.Scratch.SetInMap and $.Scratch.GetSortedMapValues to get the map sorted. All later taken randomly, sort are made with value of $d4.

Wow! That is gorgeous. I could not have solved it that way.

Thank you very, very much for your effort!

Inline Frontmatter can be sorted directly by a secondary field, Frontmatter from the data folder can’t. Maybe, it makes sense to add a pull request to GitHub for this.