Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: a mechanism for {text,html}/template allowing template inheritance #23774

Closed
jimmyfrasche opened this issue Feb 11, 2018 · 5 comments
Closed

Comments

@jimmyfrasche
Copy link
Member

Many template languages offer a directive at the top of a template files to say which template to use as a "base". This does not fit the model of templates that Go uses.

Currently, template inheritance in Go requires the program executing the templates to clone or reparse the template files in order to allow a "base" template to provide alternate definitions of the required associated templates. This can be inflexible in practice and requires that the program executing the templates be aware of the template hierarchy.

I propose the template action "extend".

{{extend "name"}}Ds{{end}}
{{extend "name" pipeline}}Ds{{end}}

The Ds are zero or more template definitions (anything other than define actions is an error, whitespace is ignored). These template definitions only exist within the extend block, not in the global namespace.

With zero Ds, extend is exactly the same as the equivalent template action.

When one or more Ds are provided, extend executes the named template overriding any global template definitions with those in Ds.

Essentially it let's you pass both the data and the templates to use to another template, most likely to override blocks.

For a web page, this might look something like:

"welcome.html"

{{extend "layout.html" .}}
  {{define "title"}}Welcome{{end}}

  {{define "body"}}
     <p>Hello, world</p>
  {{end}}
{{end}}

"about.html"

{{extend "layout.html" .}}
  {{define "title"}}About us{{end}}

  {{define "body"}}
     <p>We make great template examples.</p>
  {{end}}
{{end}}

The contents of "layout.html" are largely irrelevant, other than that it may invoke templates named "title" and "body".

The program using these templates does not need to do anything special to allow "welcome.html" and "about.html" to both redefine the same templates in "layout.html": it only has to ParseGlob("templates/*.html") and ExecuteTemplate either "welcome.html" or "about.html", as appropriate.

It does not even need to be aware of the shared "layout.html".

If, later, a certain subset of pages need to extend a different base template, no changes are required of the program—only to the templates that need to be updated.

While a bit more verbose than other template languages, this fits well with how other template languages handle similar problems, lessening the learning curve of Go templates.

It's also a more powerful and general mechanism since it is just an ordinary template action and not a special directive, allowing for finer-grained reuse.

@gopherbot gopherbot added this to the Proposal milestone Feb 11, 2018
@gopherbot
Copy link

Change https://golang.org/cl/93535 mentions this issue: {text,html}/template: add extend template action

@jimmyfrasche
Copy link
Member Author

I know I should wait for feedback before proceeding, but I added a CL with the change added to text/template just to see if it would work (and I could make a change to the main repo). I realize making it work with html/template is the larger issue. I haven't looked at that yet but will do so next.

@rsc
Copy link
Contributor

rsc commented Feb 26, 2018

We already added block to try for extensibility. Let's not add a second way.

@rsc rsc closed this as completed Feb 26, 2018
@jimmyfrasche
Copy link
Member Author

@rsc this works with blocks quite well and provides a very different kind of extensibility than can be achieved today.

To use blocks for extensibility now, for each variant you need to clone the template containing the blocks and then add the template that redefines the blocks. This makes it the responsibility of the author of the program to define how and when templates are extended.

This proposal lets the author of the templates extend templates how and when they see fit. The author of the program doesn't have to do anything special.

(Admittedly I haven't quite figured out how to get it to work with html escaping yet, but that's mostly because I haven't fully digested how the escaping works quite yet)

@jimmyfrasche
Copy link
Member Author

@rsc here's an example of how blocks have to be used today https://play.golang.org/p/d66ga6U0rB- and the same program with the proposed extends action https://play.golang.org/p/HHOpm3-XIq7

They would have the same output, modulo some whitespace. It's a toy example, but I hope it conveys the benefit and demonstrates the complimentary nature of the mechanisms.

@golang golang locked and limited conversation to collaborators Feb 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants