Skip to content

Commit

Permalink
feat: add include template function
Browse files Browse the repository at this point in the history
  • Loading branch information
majori committed Nov 27, 2024
1 parent f232f0e commit aea0de0
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 6 deletions.
2 changes: 1 addition & 1 deletion docs/site/docs/usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ The rest of the files are rendered from the templates. You can edit the template

## Templating

Templates are done by using [Go templates](https://pkg.go.dev/text/template). Examples of how to write these templates can be found in [this article](https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go#step-4-writing-a-template) and in the [example recipe](https://github.com/futurice/jalapeno/blob/main/examples/variable-types/templates/README.md?plain=1).
Templates are done by using [Go templates](https://pkg.go.dev/text/template) extended with [sprig functions](https://masterminds.github.io/sprig/). Examples of how to write these templates can be found in [this article](https://www.digitalocean.com/community/tutorials/how-to-use-templates-in-go#step-4-writing-a-template) and in the [example recipe](https://github.com/futurice/jalapeno/blob/main/examples/variable-types/templates/README.md?plain=1).

The following context is available on the templates:

Expand Down
2 changes: 1 addition & 1 deletion pkg/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func New() Engine {

func (e Engine) Render(templates map[string][]byte, values map[string]interface{}) (map[string][]byte, error) {
t := template.New("gotpl")
t.Funcs(funcMap())
t.Funcs(funcMap(t))

rendered := make(map[string][]byte)

Expand Down
5 changes: 3 additions & 2 deletions pkg/engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ func TestRender(t *testing.T) {
{
"macros",
map[string][]byte{
"templates/main": []byte("{{ template \"helper1\" }} {{ template \"helper2\" }} {{ include \"helper3\" . | upper }}"),
"templates/helper1": []byte("{{ define \"helper1\" }}ONE{{ end }}"),
"templates/main": []byte("{{ template \"helper1\" }} {{ template \"helper2\" }}"),
"templates/helper2": []byte("{{ define \"helper2\" }}TWO{{ end }}"),
"templates/helper3": []byte("{{ define \"helper3\" }}three{{ end }}"),
},
map[string]interface{}{},
map[string][]byte{
"templates/main": []byte("ONE TWO"),
"templates/main": []byte("ONE TWO THREE"),
},
},
}
Expand Down
25 changes: 23 additions & 2 deletions pkg/engine/funcs.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package engine

import (
"fmt"
"math/big"
"math/rand"
"strings"
Expand All @@ -11,10 +12,12 @@ import (

var prngs = make(map[string]*rand.Rand)

func funcMap() template.FuncMap {
func funcMap(t *template.Template) template.FuncMap {
f := sprig.TxtFuncMap()
includedNames := make(map[string]int)

// Add additional template functions here
// Custom template functions
f["include"] = includeFun(t, includedNames)
f["stableRandomAlphanumeric"] = stableRandomAlphanumeric

return f
Expand All @@ -23,6 +26,7 @@ func funcMap() template.FuncMap {
const lowerAlpha = "abcdefghijlkmnopqrstuvwxyz"
const number = "0123456789"
const alphanumeric = lowerAlpha + number
const recursionMaxNums = 100

// Generate a pseudo-random alphanumeric string of the given length
// such that the sequence of strings generated by successive calls
Expand Down Expand Up @@ -56,3 +60,20 @@ func prngForStr(str string) *rand.Rand {
func resetRngs() {
prngs = make(map[string]*rand.Rand)
}

func includeFun(t *template.Template, includedNames map[string]int) func(string, interface{}) (string, error) {
return func(name string, data interface{}) (string, error) {
var buf strings.Builder
if v, ok := includedNames[name]; ok {
if v > recursionMaxNums {
return "", fmt.Errorf("unable to execute template: maximum recursion depth reached for template block \"%s\"", name)
}
includedNames[name]++
} else {
includedNames[name] = 1
}
err := t.ExecuteTemplate(&buf, name, data)
includedNames[name]--
return buf.String(), err
}
}

0 comments on commit aea0de0

Please sign in to comment.