Something went wrong. Try again.
😻 Your teal.fm scrobbles as a one-liner on your site. musicat.cuducos.me
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758// Package render substitutes entities into a {nameN}/{imageN} template.package render
import ( "fmt" "regexp" "strconv" "strings"
"tangled.org/cuducos.me/musicat/selection")
var placeholder = regexp.MustCompile(`\{(name|image)([1-9]|10)\}`)
// maxSlots is what a caller offering no template is assumed to want: it may// reference any slot up to this one.const maxSlots = 10
// Slots reports how many entity slots a template needs: its highest referenced// slot, or maxSlots when no template is offered.func Slots(t string) int { if t == "" { return maxSlots } n := 0 for _, m := range placeholder.FindAllStringSubmatch(t, -1) { if i, err := strconv.Atoi(m[2]); err == nil && i > n { n = i } } return n}
// Template replaces {nameN} and {imageN} with the matching entity. A placeholder// with no entry is an error rather than a silent empty string, so a caller knows// its template and the data disagree. Substitution is raw: the caller owns// escaping for its output format.func Template(t string, es []selection.Entity) (string, error) { var b strings.Builder end := 0 for _, m := range placeholder.FindAllStringSubmatchIndex(t, -1) { n, err := strconv.Atoi(t[m[4]:m[5]]) if err != nil || n < 1 || n > len(es) { return "", fmt.Errorf("template uses %s, but there are %d entries", t[m[0]:m[1]], len(es)) } b.WriteString(t[end:m[0]]) e := es[n-1] if t[m[2]:m[3]] == "image" { b.WriteString(e.Image) } else { b.WriteString(e.Name) } end = m[1] } b.WriteString(t[end:]) return b.String(), nil}