Hugo: Allow cascading Front Matter

Created on 16 Jun 2019  Β·  12Comments  Β·  Source: gohugoio/hugo

This issue adresses batch assignment of Front Matter values to descendants of any given content file and is inspired to some extend by the data assignment logic of https://github.com/11ty/eleventy.

Batch assign is already addressed here https://github.com/gohugoio/hugo/issues/5455 but from a single entry point.
I think the following could complement the above for many use cases and provide a simpler approach to batch assign.

Here, we would simply create a new reserved key in Front Matter underneath which any number of key/value pair could be cascaded through the page’s descendants.

Consider the following structure and content files' Front Matter:

β”œβ”€β”€ _index.md
β”œβ”€β”€ blog
β”‚   β”œβ”€β”€ _index.md
β”‚   β”œβ”€β”€ san-fransisco-series
β”‚   β”‚   β”œβ”€β”€ _index.md
β”‚   β”‚   β”œβ”€β”€ castro.md
β”‚   β”‚   β”œβ”€β”€ lombard.md
β”‚   β”‚   └── presidio.md
β”‚   └── moving-again.md
└── contact.md
# content/_index.md
title: Home
cascade:
  banner: images/windows-bliss.jpg
# content/blog/_index.md
title: Blog
cascade:
  banner: images/typewriter.jpg
# content/blog/san-fransisco-series/_index.md
title: San Fransisco
cascade:
  banner: images/golden-gate-sunset.jpg
# content/blog/san-fransisco-series/lombard.md
title: San Fransisco
banner: images/herbie-lombard.jpg

Looking at the different content files above, and from within the template files, .Params.banner would output the following:

| Content file | .Params.banner | cascading from
|-----------------------------------|----------------------| ------ |
| /contact.md | windows-bliss.jpg | Homepage
| /blog/moving-again.md | typewriter.jpg | Blog
| /blog/san-fransisco-series/presidio.md | golden-gate-sunset | SF Series
| /blog/san-fransisco-series/castro.md | golden-gate-sunset | SF series
| /blog/san-fransisco-series/lombard.md | herbie-lombard.jpg | self

Repercusions

They're safe as those "special" key/value pair would be stored in a reserved map.

On the other hand this could take care of https://github.com/gohugoio/hugo/issues/5652 and potentially other issues not yet identified.

How to overwrite with an empty value?

What if a page does not want a banner?

# /blog/rip-dear-celebrity
title: Rest In Peace dear celebrity
banner: false

It becomes the user responsibility to allow an empty or boolean overwrite to editors. I think it's a fair trade-off.

Data source

This for now does not solve the problem of batch assigning Front Matter to remote content, but it could if the user can create a content file matching the remote’s content section and store the section’s Front Matter (cascading or not) in there.

Enhancement

Most helpful comment

you need to somehow set a zero value

Yes as mentioned in this issue's desc, for me it is a good trade of.

And I gladly welcome both your conclusions, route B and merge.

All 12 comments

Sounds like a good idea. About the naming, how about default parameter name instead of cascade?

The name implies that all the parameters under default will have the default values specified there, unless the page itself modifies that default-set parameter value.

I like this very much, and as long as we restrict the cascade keyword to the _index.md types it should not be _too hard_ to implement.

I think this should be able to solve some other long-standing issues:

  • layout/type for nested sections.
  • outputs
  • Possibly others.

It does not solve (my) primary motivation behind # #5455 -- which I vaguely remember as a way to batch-reorder pages (by setting weight), but I guess we cannot have it all ...

I’m glad you guys are on board.

@kaushalmodi, I’ll never get bored of discussing parameter names with you :)

I think such a feature should be called Cascading Front Matter because I believe everyone will instantly understand what this does just by reading those 3 words.

Hence using cascade as parameter.

But it’s also safer than defaults as a reserved front matter key.

I would suspect someone somewhere is already using defaults in their front matter.

Also defaults are temporary values to be overwritten. Here they will rarely be (I suspect).

cascaded through the page’s descendants

@regisphilibert a quick yes and no question to verify that we're in line here: The values defined in cascade will only be applied to the nodes below, not to the node itself. As such, the home page must define all of its front matter values, as the home page has no ancestors.

Yes I saw cascade not targeting self, only descendants.

My turn:

as the home page has no ancestors

Does this mean we cannot use the homepage to define "global" cascade for all pages? If not, maybe global cascade could be added through site's config file?

Does this mean we cannot use the homepage to define "global" cascade for all pages?

You can, but it will not apply to the home page itself (we could of course decide to make an exception for the home page, which I guess would make sense).

I have a related question that, while testing this, surprised me a little. But I guess it is how it is going to be.

If you say for home page:

    cascade:
        outputs: [HTML]

It means that you want all the ancestors to output HTML only (unless overridden by front matter or another cascade).

But then you somewhere in the tree do something like this for /some/section:

    cascade:
        icon: "flag.png"

So, by adding the cascade with that icon you effectively fall back to the default values for outputs for that section.

I don't think we can ... cascade (or merge) the cascades, so to speak. Or, not as the default behaviour. We can maybe add a persistent flag or something to mark that.

I thought they would merge.

I really see this as a parallel to CSS (and other) cascading mechanism. Everything from the ancestors' tree is kept unless overwritten.

If ultimately this is not possible, this will still be a very useful feature but maybe with a different name though.

I thought they would merge.

OK, let's do that. There are maybe some potential issues with that, too, but probably less confusing than the other variant.

Yes I saw cascade not targeting self, only descendants.

You would then maybe typically end up with something like this for a section:

title: "My Section
icon: "flag.png"
outputs: ["HTML"]
type: "blog"
cascade:
   icon: "flag.png"
   outputs: ["HTML"]
   type: "blog"

Which I guess is fine?

Which I guess is fine?

But not great I suppose.

If we go back to the CSS comparison, cascade should apply to self and avoid copy/paste in the section. So this sounds like the proper route (let's call it route B) and I cannot recall why I had reservations about it and sided with route A.

It seems okay in this context that a regular FM would overwrite the section's cascade FM on self.

To use your example:

title: "My Section"
icon: "world.png"
cascade:
   icon: "flag.png"
   outputs: ["HTML"]
   type: "blog"

The section would send down the cascade the flag.png icon but use for itself the world.png. On the other hand, the rest of cascade would apply to self.

Again, route A is fine as well, but will lead to more copy/paste than B I think.

I'm not sure I'm totally getting the CSS allegory, but both B and my initial question about "to merge the cascades" or not have the same problem in that it's not possible to delete elements set in the cascade, you need to somehow set a zero value, e.g.:

title: "My Section"
icon: "" # I don't want an icon
cascade:
   icon: "flag.png"
   outputs: ["HTML"]
   type: "blog"

And similar:

title: "My Section"
icon: "flag.png" 
cascade:
   icon: "" # I don't want my ancestors to have an icon.
   outputs: ["HTML"]
   type: "blog"

But the above avoids the most copy/paste and I suspect is the least surprising. So I suggest:

  • Route B
  • Merge of cascade elements

you need to somehow set a zero value

Yes as mentioned in this issue's desc, for me it is a good trade of.

And I gladly welcome both your conclusions, route B and merge.

This is a really helpful feature, thank you so @regisphilibert!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MunifTanjim picture MunifTanjim  Β·  3Comments

nikolas picture nikolas  Β·  3Comments

vielmetti picture vielmetti  Β·  3Comments

geddski picture geddski  Β·  3Comments

kaushalmodi picture kaushalmodi  Β·  3Comments