github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/internal/fs/templates.go (about) 1 // Copyright (c) 2021-2022, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package fs 6 7 import ( 8 "bytes" 9 "fmt" 10 "strconv" 11 "strings" 12 "text/template" 13 14 "github.com/fatih/color" 15 "golang.org/x/text/cases" 16 "golang.org/x/text/language" 17 ) 18 19 type consoleRender interface { 20 RenderConsole() ([]byte, error) 21 } 22 23 type mdRender interface { 24 RenderMarkdown() ([]byte, error) 25 } 26 27 func ExecuteTemplate(file string, i any, funcMap template.FuncMap) ([]byte, error) { 28 buf := bytes.NewBuffer([]byte{}) 29 t := template.New(file) 30 funcs := map[string]any{ 31 "StringsJoin": stringsJoin, 32 "RenderConsole": renderConsolePadded, 33 "RenderMarkdown": renderMarkdown, 34 "MarkdownEscape": markdownEscape, 35 "Bold": boldString, 36 "Title": cases.Title(language.AmericanEnglish).String, 37 } 38 39 for k, v := range funcMap { 40 funcs[k] = v 41 } 42 43 t.Funcs(funcs) 44 45 body, err := FS.ReadFile(file) 46 if err != nil { 47 return nil, err 48 } 49 50 p, err := t.Parse(string(body)) 51 if err != nil { 52 return nil, err 53 } 54 55 err = p.Execute(buf, i) 56 if err != nil { 57 return nil, err 58 } 59 60 return buf.Bytes(), nil 61 } 62 63 func stringsJoin(s []string) string { 64 return strings.Join(s, ", ") 65 } 66 67 func boldString(s string) string { 68 return color.New(color.Bold).Sprintf(s) 69 } 70 71 func renderMarkdown(i mdRender) string { 72 out, err := i.RenderMarkdown() 73 if err != nil { 74 panic(err) 75 } 76 77 return string(out) 78 } 79 80 func renderConsolePadded(i consoleRender, padding int) string { 81 out, err := i.RenderConsole() 82 if err != nil { 83 panic(err) 84 } 85 86 return paragraphPadding(string(out), padding) 87 } 88 89 func paragraphPadding(paragraph string, padding int) string { 90 parts := strings.Split(paragraph, "\n") 91 ps := fmt.Sprintf("%"+strconv.Itoa(padding)+"s", " ") 92 93 for i := range parts { 94 parts[i] = ps + parts[i] 95 } 96 97 return strings.Join(parts, "\n") 98 } 99 100 // use to escape within backticks, not for general full md escape, we mainly want to avoid escaping backticks and tables 101 func markdownEscape(s string) string { 102 escaped := s 103 for _, c := range strings.Fields("` |") { 104 escaped = strings.Replace(escaped, c, "\\"+c, -1) 105 } 106 107 return escaped 108 }