Go 1.6 master template support in Hugo; help needed!


This implements support for the new block keyword in Go 1.6 (is going to be released in a few days).

To see it in action, have a look at this line/commit (notice the block with the placeholder; I have only one block, but you can have as many as you want, sidebar etc., with default content filled in):

That branch on my blog is now a mix of Ace base templates and Go base templates. The logic for choosing the templates is the same:

// Look for base template in the follwing order:
//   1. <current-path>/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>.
//   2. <current-path>/baseof.<suffix>
//   3. _default/<template-name>-baseof.<suffix>, e.g. list-baseof.<suffix>.
//   4. _default/baseof.<suffix>
//   5. <themedir>/layouts/_default/<template-name>-baseof.<suffix>
//   6. <themedir>/layouts/_default/baseof.<suffix>

The baseof filename pattern looks better with Ace files (Ace Of Base), but I guess it sticks.

I have one problem though, and I need your input:

  • Not all templates needs a base template (views etc.), so we need a way to identify them.
  • I currently look inside them and look for a {{define keyword.

This works, but the problem is that define is a general-purpose keyword that can be used in other settings (define and block or template in the same file).

So we need something else … or something in addition to the above.


So, if I understand this correctly, you are looking for a way to distinguish between a template that needs a block default, and a template which doesn’t?

How about using a comment? {{/BLOCK: FALSE/}} or something like that…? That would, ofc, mean that we would have to tag the templates which require this comment.

Yes, that is solution, but I had hoped that I didn’t have to invent something just for this …

Yeah, I realise that it probably would be a lot of extra work, however, the alternative isn’t good enough. Until there is something better, an explicit distinguish is the way to move forward. Anything else would leave a bug in the system that’s waiting to bite in our asses.

The work is all in supporting/documenting a new magic keyword. It will create lots of issues and discussions about “the master template doesn’t work …”

Yepp. However, again, the alternative is some very convoluted logic to TRY and determine which template needs a block or not, no?

There are several options:

  1. Introduce a new keyword inside the file
  2. Mark these templates with a special file name
  3. Mark the defines: {{define “ext-T1” … meaning: look for the block that defines this in an external file.
  4. Look for a define that is not used
  5. Say that define can only be used in external base templates

Simplicity is hard.

Personally, I would prefer an explicit solution.

Either filename indication, or the extra keyword. It’s explicit. There is no way to misinterpret it. What do you think?

I think I have to think about it.

Naive question @bep: is the idea of “blocks” similar to “blocks” in Swig or “blocks” in Twig? For example, base.html > post.html with {{block extends "base.html"}} in the post and the “base.html” being, for lack of a better example, your <head>, <header>,<footer>, etc?

I looked at the above line/commit, but I’m a little unclear as to what the block does. Thanks!

I have no clue what Twig and Swig and Wig … is but blocks in this setting is a way to

  1. Keep all the page frame stuff in one (or a few) place (header with CSS, footer)
  2. Have placeholders with default content for sections that can be overridden in the individual templates: main content, sidebar …

@bep From that terse but insightful description, I’m thinking that “block” in Go templates is at least semi-equivalent to the aforementioned templating languages’ use of the same word.

If so, this would be an awesome improvement. Setting defaults, extending layouts, etc in something like Swig/Twig is much easier for management. Liquid (Jekyll) extends templates based on the layout: in front matter as well.

As always, I appreciate the feedback, brother. Cheers.

Another challenge here is whatever approach we take now should be compatible with the better approach the Go template library will take in the future.

I think the filename approach is probably the safest one.

It think we should just say that for Hugo (for now) define as used by blocks are only permitted in base templates.

Does that seem right. I admit to not really understanding the block implementation yet.

I don’t think “the better choice” will get in the way of Hugo’s API. It will, hopefully, make the implementation simpler.

I didn’t know about the define keyword until I started messing with this. People can use it today as well, I guess, as a macro kind of thing in the top of a template. But would be surprised of someone did. Partial works better for that.

So yes, I think we can go down that road for starters.

Would it be possible to develop a keyword and have it default to the current state? This means everything that already exists is covered and the new stuff can use the shiny.

This could be announced with a flip in the future to default to using the new process.

Eventually, it would be possible to deprecate the old method altogether.

Not sure what you ask for here. What is the current state a keyword that doesn’t exist yet? As to implementing keywords, that would have to be done in Go’s stdlib, so ask them.

I was offering a suggestion.

Consider it a bad idea and just ignore it.