0

In my template, I use a sub-template that generates a piece of output. The template output must be shifted though (because the output is in YAML format). Is there any possibility to post-process template output?

{{ template "subtemplate" | indent 10 }}

This indent 10 is fictional, just to explain what I need.

It is possible (as @icza suggested) to save the output into a variable and then work with it, but maybe there is a better, more elegant approach?

{{$var := execTempl "subtemplate"}}
{{$var}}
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
  • 1
    Capture the output of the template in a variable, which you can pass to other functions. See [Capture or assign golang template output to variable](https://stackoverflow.com/questions/40164896/capture-or-assign-golang-template-output-to-variable/40170999#40170999) – icza Oct 21 '21 at 13:10
  • @icz: Yes, I know about it, but maybe there is any more elegant solution? – Igor Chubin Oct 21 '21 at 13:12
  • You could make the indentation depth a parameter to `execTempl` – flyx Oct 21 '21 at 13:32

1 Answers1

1

The closest you can get to {{ template "subtemplate" | indent 10 }} is to define a function that parses and executes the subtemplate and outputs the result as string.

var externalTemplates = map[string]*template.Template{
    "subtemplate": template.Must(template.New("subtemplate").Parse(sub_template)),
}

// Executes external template, must be registered with FuncMap in the main template.
func xtemplate(name string) (string, error) {
    var b bytes.Buffer
    if err := externalTemplates[name].ExecuteTemplate(&b, name, nil); err != nil {
        return "", err
    }
    return b.String(), nil
}
t := template.Must(template.New("t").Funcs(template.FuncMap{
    "xtemplate": xtemplate, // register func
}).Parse(main_template))

In the main template you can then use the function like this:

{{ xtemplate "subtemplate" | indent 10 }}

https://play.golang.org/p/brolOLFT4xL

mkopriva
  • 35,176
  • 4
  • 57
  • 71
  • Basically it is the same what @icza suggested: `xtemplate` is `execTempl`, right? – Igor Chubin Oct 21 '21 at 14:30
  • Yes minus the variable part. That's what you didn't like about that approach isn't it? – mkopriva Oct 21 '21 at 14:31
  • Yes, I just wanted to be sure that I don't miss anything. It is a good approach, anyway better then other ugly alternatives I had before – Igor Chubin Oct 21 '21 at 14:33
  • 1
    @IgorChubin one difference between icza's linked answer and the above is that icza is using a single instance of `*template.Template` while the above answer is using one for main template and a set of "external templates". Because the above registers `xtemplate` only with the main template you cannot use it inside the external templates. So you may actually prefer the single-instance version if you want to be able to call `xtemplate` also from the "external templates". Although nothing stops you from registering `xtemplate` with the externals as well. – mkopriva Oct 21 '21 at 14:41