Using a List as the Root Node of a Yaml Data Template

Hey everyone,

I’m trying to figure out if I’m doing something wrong or if I hit a bug. Let’s play out the following scenario:

I want to create a data template with a list of books and then display them in a template file. My data template would be:

# ./data/books.yml
- title: "Harry Potter and the Order of the Phoenix"
  author: "J.K. Rowlings"
  pages: 870
- title: "A Wrinkle in Time"
  author: "Madeleine L'Engle"
  pages: 240
- title: "My Side of the Mountain"
  author: "Jean Craighead George"
  pages: 175

I’d try to display them in a layout file with:

{{ range .Site.Data.books }}
<p>an item in the loop</p>
{{ end }}

The loop will have zero iterations. I started thinking that maybe the root node of a Yaml file can’t be a list but a few Stack Overflow posts say it can. I then ran my Yaml through http://www.yamllint.com/ and it comes up as valid.

Am I missing something? Is this a parsing bug on Hugo’s part?

If so, it is in go-yaml.

What I suggest you do is a printf .Site.Data.books "%T to see what type it actually is.

Running:     {{ printf "%T" .Site.Data.books }}

prints out:     <nil>.

I had to update my post above. With using a map key, which is how you’d often see a Yaml file start, I get map[string]interface {} but when using the Yaml from my example, the type is just nil.

Try to run with hugo -v … I suspect there are some warnings that you don’t see.

OK, I see it now: Hugo expects the data file to be a map, so you need some kind of root.

So we still think this is a go-yaml issue? I’ll work around this for now but I’ll open an Issue in their repo if that’s the case.

No we now think that this is an issue with your data file. If there’s not warnings in the log, then there is a Hugo issue.

To add some context to the above.

We have to unmarshal the YAML (and TOML and JSON) into something, and we need to know about that before we do it, so we picked the map, which a fair amount of more flexible than, say, restrict it to single integers only.

You can wrap you list in a map. You can not wrap your list in an int.

I did run hugo -v and found the warning: line 1: cannot unmarshal !!seq into map[string]interface {}.

I do consider this an issue because what I’m trying to use is standard, up to spec, Yaml. The best solution is that this should work as is since it’s standard Yaml.

If you refuse to add this to Hugo (or if I need to open a go-yaml issue), then at the very least the second, lessor optimal solution is to add it to the Data Template doc so this can be a known thing. Hopefully we don’t go that route but if we do, I can make a Docs PR.

EDIT: Actually, the docs do say it’ll be “accessible as a map”.

OK, I take it back. This is a Hugo issue. Can you create a GitHub issue and I will fix it.

https://github.com/gohugoio/hugo/issues/3890