Skip to content

Commit d850d03

Browse files
authored
feat: add yaml templating functions (#2219)
* feat: add yaml templating functions * docs: add yaml functions to templating reference * refactor: remove some unnecessary function wrappers
1 parent 0058f18 commit d850d03

File tree

2 files changed

+97
-52
lines changed

2 files changed

+97
-52
lines changed

internal/templater/funcs.go

Lines changed: 95 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
"github.com/davecgh/go-spew/spew"
10+
"gopkg.in/yaml.v3"
1011
"mvdan.cc/sh/v3/shell"
1112
"mvdan.cc/sh/v3/syntax"
1213

@@ -18,58 +19,25 @@ var templateFuncs template.FuncMap
1819

1920
func init() {
2021
taskFuncs := template.FuncMap{
21-
"OS": func() string { return runtime.GOOS },
22-
"ARCH": func() string { return runtime.GOARCH },
23-
"numCPU": func() int { return runtime.NumCPU() },
24-
"catLines": func(s string) string {
25-
s = strings.ReplaceAll(s, "\r\n", " ")
26-
return strings.ReplaceAll(s, "\n", " ")
27-
},
28-
"splitLines": func(s string) []string {
29-
s = strings.ReplaceAll(s, "\r\n", "\n")
30-
return strings.Split(s, "\n")
31-
},
32-
"fromSlash": func(path string) string {
33-
return filepath.FromSlash(path)
34-
},
35-
"toSlash": func(path string) string {
36-
return filepath.ToSlash(path)
37-
},
38-
"exeExt": func() string {
39-
if runtime.GOOS == "windows" {
40-
return ".exe"
41-
}
42-
return ""
43-
},
44-
"shellQuote": func(str string) (string, error) {
45-
return syntax.Quote(str, syntax.LangBash)
46-
},
47-
"splitArgs": func(s string) ([]string, error) {
48-
return shell.Fields(s, nil)
49-
},
50-
// IsSH is deprecated.
51-
"IsSH": func() bool { return true },
52-
"joinPath": func(elem ...string) string {
53-
return filepath.Join(elem...)
54-
},
55-
"relPath": func(basePath, targetPath string) (string, error) {
56-
return filepath.Rel(basePath, targetPath)
57-
},
58-
"merge": func(base map[string]any, v ...map[string]any) map[string]any {
59-
cap := len(v)
60-
for _, m := range v {
61-
cap += len(m)
62-
}
63-
result := make(map[string]any, cap)
64-
maps.Copy(result, base)
65-
for _, m := range v {
66-
maps.Copy(result, m)
67-
}
68-
return result
69-
},
70-
"spew": func(v any) string {
71-
return spew.Sdump(v)
72-
},
22+
"OS": os,
23+
"ARCH": arch,
24+
"numCPU": runtime.NumCPU,
25+
"catLines": catLines,
26+
"splitLines": splitLines,
27+
"fromSlash": filepath.FromSlash,
28+
"toSlash": filepath.ToSlash,
29+
"exeExt": exeExt,
30+
"shellQuote": shellQuote,
31+
"splitArgs": splitArgs,
32+
"IsSH": IsSH, // Deprecated
33+
"joinPath": filepath.Join,
34+
"relPath": filepath.Rel,
35+
"merge": merge,
36+
"spew": spew.Sdump,
37+
"fromYaml": fromYaml,
38+
"mustFromYaml": mustFromYaml,
39+
"toYaml": toYaml,
40+
"mustToYaml": mustToYaml,
7341
}
7442

7543
// aliases
@@ -83,3 +51,78 @@ func init() {
8351
templateFuncs = template.FuncMap(sprig.TxtFuncMap())
8452
maps.Copy(templateFuncs, taskFuncs)
8553
}
54+
55+
func os() string {
56+
return runtime.GOOS
57+
}
58+
59+
func arch() string {
60+
return runtime.GOARCH
61+
}
62+
63+
func catLines(s string) string {
64+
s = strings.ReplaceAll(s, "\r\n", " ")
65+
return strings.ReplaceAll(s, "\n", " ")
66+
}
67+
68+
func splitLines(s string) []string {
69+
s = strings.ReplaceAll(s, "\r\n", "\n")
70+
return strings.Split(s, "\n")
71+
}
72+
73+
func exeExt() string {
74+
if runtime.GOOS == "windows" {
75+
return ".exe"
76+
}
77+
return ""
78+
}
79+
80+
func shellQuote(str string) (string, error) {
81+
return syntax.Quote(str, syntax.LangBash)
82+
}
83+
84+
func splitArgs(s string) ([]string, error) {
85+
return shell.Fields(s, nil)
86+
}
87+
88+
// Deprecated: now always returns true
89+
func IsSH() bool {
90+
return true
91+
}
92+
93+
func merge(base map[string]any, v ...map[string]any) map[string]any {
94+
cap := len(v)
95+
for _, m := range v {
96+
cap += len(m)
97+
}
98+
result := make(map[string]any, cap)
99+
maps.Copy(result, base)
100+
for _, m := range v {
101+
maps.Copy(result, m)
102+
}
103+
return result
104+
}
105+
106+
func fromYaml(v string) any {
107+
output, _ := mustFromYaml(v)
108+
return output
109+
}
110+
111+
func mustFromYaml(v string) (any, error) {
112+
var output any
113+
err := yaml.Unmarshal([]byte(v), &output)
114+
return output, err
115+
}
116+
117+
func toYaml(v any) string {
118+
output, _ := yaml.Marshal(v)
119+
return string(output)
120+
}
121+
122+
func mustToYaml(v any) (string, error) {
123+
output, err := yaml.Marshal(v)
124+
if err != nil {
125+
return "", err
126+
}
127+
return string(output), nil
128+
}

website/docs/reference/templating.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ description here for completeness. For detailed usage, please refer to the
264264
| `toJson`\* | Encodes an object as a JSON string. |
265265
| `toPrettyJson`\* | Encodes an object as a JSON string with new lines and indentation. |
266266
| `toRawJson`\* | Encodes an object as a JSON string with HTML characters unescaped. |
267+
| `fromYaml`\* | Decodes a YAML string into an object. |
268+
| `toYaml`\* | Encodes an object as a YAML string. |
267269
| `b64enc` | Encodes a string into base 64. |
268270
| `b64dec` | Decodes a string from base 64. |
269271
| `b32enc` | Encodes a string into base 32. |

0 commit comments

Comments
 (0)