Tutorial: Link .Site.Data to Content Types by Filename (call for review)

Have a read and let me know by commenting here or opening an issue on the separate repo there if you have any suggested changes or problems. After some review time I will submit this as a PR to the tutorials section if it seems useful to enough people. I confess I was super excited to have found out this is possible—especially after reading others challenges with this same thing in the forums.

Thanks in advance for your feedback.

Trade Offs:This is where the
where function would
come in really handy, if it worked. Unfortunately it, along with
all the grouping functions don’t work with .Site.Data

I don’t see why where shouldn’t work fine for site.Data. If it doesn’t, create a bug on GitHub.

Well I think I have this is worded in a way that implies it is a bug when it really isn’t. The following just isn’t possible because, as far as I can tell, where only works with lists and not maps:

{{ range where .Site.Data.person "admin" "in" "roles" }}
    {{ partial "person/li" . }}
{{ end }}

I image there is a way to break out a sub range or pipeline but at that point it is just easier to put in the if on its own:

{{ range .Site.Data.person }}
    {{ if in .roles "admin" }}{{ partial "person/li" . }}{{ end }}
{{ end }}

I misunderstood the following initially to work on maps, which I am reading in the forums is a common error:

Functions | Hugo description of where when used with the in operator specifically:

It can also be used with an operator like !=, >=, in etc. Without an operator (like above), where compares a given field with a matching value in a way like = is specified.

Thanks for looking into it. I will just remove that part.

In your tutorial you have at least one broken link. For example, you link to “https://gohugo.io/extras/data-files” in the text “Make sure you understand the data file concept fully to get the most out of it. It is really amazing.”. But the link should really be “http://gohugo.io/extras/datafiles/” (note the trailing slash).

You write

mkdir `layouts/partials/person`

Backticks here won’t do what you mean in most (if not all) unix shells: it would try to run the command “layouts/partials/person” and use it’s standard output as the argument to mkdir.

Thanks for the review Holger.

I can see the case for trailing slashes and do understand that links without them are essentially redirects. I also only previewed this using hugo server which corrects those. I also host on GitHub and Surge where links without trailing slashes are handled without a problem. But I will change them all. On GitHub they will all be // instead of http or https, but in the final addition to gohugo.io/templates I’ll make them all relative, as all of the other tutorials do.

I understand the meaning of back ticks, thanks for catching that. It was a dubious markdown typo essentially because I had been using back ticks for markdown every other place that path appears.

@bep how do you feel about the following explanation about where?

Beware: Where will not work here because, and let’s emphasize this, “where only works on lists, taxonomies, terms, and groups”. .Data.Pages is a list so it works. The way we have organized our data/person files means .Site.Data.person is a map, not a list.

Two issues here:

  1. Added tpl: Extend “where” to iterate over maps to Github.

  2. The way where works is that the second parameter is a property of the first’s elements. So, in your example, I would expect to see the reverse of what you posted:

     where .Site.Data.person "roles" "in" "admin"
    

However, that construct reverses the parameters on in. ["admin","user"] is not in "admin". What you need here is to be able to use intersect as an operator, which is not currently supported. That’s another Github feature request. :slightly_smiling:

Two options if intersect becomes a where operator:

  1. intersect only supports arrays/slices at the moment, and you can’t create arrays/slices on the fly in templates (IIRC). So you would need to create a site parameter (or something) to define the roles you want to match against: admin_role = ["admin"]. Then you could do this:

     where .Site.Data.person "roles" "intersect" .Site.Params.admin_role
    
  2. We could extend the intersect func to allow taking a single-element parameter (like a string) and treating it as a single-item array/slice (depending on the type of the other parameter):

     range where .Site.Data.person "roles" "intersect" "admin"
    

Yet another feature request. :wink: Not clear to me yet how much that would complicate the intersect func though.

Also added:

For an example of where with data: