Description
I propose adding an apply
function to text/template which would execute a template and send its output to a pipeline:
{{ apply markdown | highlight "html" }}
Hello, **Gopher**!
{{ end }}
<pre class="code">
Hello, <span class="tag"><strong></span>Gopher<span class="tag"></strong></span>!
</pre>
The motivation for this feature is essentially the same as the motivation for Hugo's shortcodes. When authoring content in Go templates, it is often desirable to run templated content through a template function for post-processing - for example, for syntax highlighting, processing markdown, creating "accordion" sections, etc.
Different flavors of this behavior have been proposed before (see below), and have been rejected with workarounds. Unfortunately, the best workaround available today is to add an eval "template name" .
function and then use named templates, which is too cumbersome in practice:
{{ template "base.html" . }}
{{ define "content 1" }}
Hello, **{{ .Name }}**!
Watch this _sweet_ video to get started:
{{ end }}
{{ define "content 2" }}
Don't forget to [like and subscribe](https://video.com/gopher)!
{{ end }}
{{ define "some block from base.html" }}
{{ eval "content 1" . | markdown }}
<iframe src="https://video.com/gopher/123456/embed"></iframe>
{{ eval "content 2" . | markdown }}
{{ end }}
I propose for apply
to simply be sugar for this workaround, albeit without defining a named template. With the proposed feature, this example would look like:
{{ template "base.html" . }}
{{ define "some block from base.html" }}
{{ apply markdown }}
Hello, **{{ .Name }}**!
Watch this _sweet_ video to get started:
{{ end }}
<iframe src="https://video.com/gopher/123456/embed"></iframe>
{{ apply markdown }}
Don't forget to [like and subscribe](https://video.com/gopher)!
{{ end }}
{{ end }}
I have created a prototype implementation of this feature.
Prior proposals
- proposal: text/template: allow template and block outputs to be chained #33273
This issue proposed modifications to the behavior ofblock
andtemplate
which were deemed unacceptable. A workaround was suggested where the user can supply aneval
function to execute a named template and get its result as a value. Unfortunately this workaround is still too cumbersome for the workflows described in this proposal. - proposal: text/template: Template block function that receives what is inside the block as input #44144
This issue was, in my opinion, erroneously closed as a duplicate of the previous issue. However, it did not redefine any existing syntax, so it was not really proposing the same thing. I hope that my proposal is a more complete and thoughtful version of this idea.
Open questions
Is this API sufficient? It may be wise to additionally expose APIs like the following, but I will leave that for further discussion.
-
eval "template name" .
: evaluates a template by name and returns the output as a string. This behavior is implicitly present inapply
, and is part of the commonly-suggested workaround, so it may be worth exposing explicitly. Example:{{ define "greet" }}Hello, {{ . }}!{{ end }} {{ $greeting := eval "greet" .Name }} {{ urlquery $greeting }} // Output (when executed with Name = "Gopher"): Hello%2C+Gopher!
Metadata
Metadata
Assignees
Type
Projects
Status