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  }