github.com/henvic/wedeploycli@v1.7.6-0.20200319005353-3630f582f284/templates/templates.go (about) 1 // Licensed under Apache license 2.0 2 // SPDX-License-Identifier: Apache-2.0 3 // Copyright 2013-2016 Docker, Inc. 4 5 // NOTICE: export from moby/utils/templates/templates.go (modified) 6 // https://github.com/moby/moby/blob/da0ccf8e61e4d5d4005e19fcf0115372f09840bf/utils/templates/templates.go 7 // https://github.com/moby/moby/blob/da0ccf8e61e4d5d4005e19fcf0115372f09840bf/LICENSE 8 9 package templates 10 11 import ( 12 "bytes" 13 "encoding/json" 14 "io" 15 "strings" 16 "text/template" 17 18 "github.com/hashicorp/errwrap" 19 ) 20 21 var funcs = template.FuncMap{ 22 "json": func(v interface{}) string { 23 a, _ := json.Marshal(v) 24 return string(a) 25 }, 26 "split": strings.Split, 27 "join": strings.Join, 28 "title": strings.Title, 29 "lower": strings.ToLower, 30 "upper": strings.ToUpper, 31 "pad": padWithSpace, 32 } 33 34 // Funcs adds the elements of the argument map to the template's function map. 35 func Funcs(funcMap template.FuncMap) { 36 for k, v := range funcMap { 37 funcs[k] = v 38 } 39 } 40 41 type compiledTemplate struct { 42 template *template.Template 43 err error 44 } 45 46 var cachedTmpl = map[string]compiledTemplate{} 47 48 // ExecuteOrList executes the Execute function if format is not empty, 49 // otherwise, it returns all as a JSON 50 func ExecuteOrList(format string, data interface{}) (string, error) { 51 if format != "" { 52 return Execute(format, data) 53 } 54 55 bin, err := json.MarshalIndent(&data, "", " ") 56 57 if err != nil { 58 return "", err 59 } 60 61 return string(bin), nil 62 } 63 64 // Execute template with format and data values 65 func Execute(format string, data interface{}) (string, error) { 66 if _, ok := cachedTmpl[format]; !ok { 67 tmpl, tmplErr := parse(format) 68 cachedTmpl[format] = compiledTemplate{tmpl, tmplErr} 69 } 70 71 return execute(format, data) 72 } 73 74 func execute(format string, data interface{}) (string, error) { 75 var ( 76 buf bytes.Buffer 77 wr io.Writer = &buf 78 79 cached = cachedTmpl[format] 80 tmpl = cached.template 81 err = cached.err 82 ) 83 84 if err != nil { 85 return "", errwrap.Wrapf("template parsing error: {{err}}", err) 86 } 87 88 if err := tmpl.Execute(wr, data); err != nil { 89 return "", errwrap.Wrapf("can't execute template: {{err}}", err) 90 } 91 92 return buf.String(), nil 93 } 94 95 // Parse creates a new annonymous template with the basic functions 96 // and parses the given format. 97 func parse(format string) (*template.Template, error) { 98 return newParse("", format) 99 } 100 101 // NewParse creates a new tagged template with the basic functions 102 // and parses the given format. 103 func newParse(tag, format string) (*template.Template, error) { 104 return template.New(tag).Funcs(funcs).Parse(format) 105 } 106 107 // padWithSpace adds whitespace to the input if the input is non-empty 108 func padWithSpace(source string, prefix, suffix int) string { 109 if source == "" { 110 return source 111 } 112 return strings.Repeat(" ", prefix) + source + strings.Repeat(" ", suffix) 113 }