mirror of
https://github.com/GlueOps/autoglue.git
synced 2026-02-13 12:50:05 +01:00
initial rebuild
This commit is contained in:
209
internal/funcs/funcs.go
Normal file
209
internal/funcs/funcs.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package funcs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"math"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/text/language"
|
||||
"golang.org/x/text/message"
|
||||
)
|
||||
|
||||
var printer = message.NewPrinter(language.English)
|
||||
|
||||
var TemplateFuncs = template.FuncMap{
|
||||
// Time functions
|
||||
"now": time.Now,
|
||||
"timeSince": time.Since,
|
||||
"timeUntil": time.Until,
|
||||
"formatTime": formatTime,
|
||||
"approxDuration": approxDuration,
|
||||
|
||||
// String functions
|
||||
"uppercase": strings.ToUpper,
|
||||
"lowercase": strings.ToLower,
|
||||
"pluralize": pluralize,
|
||||
"slugify": slugify,
|
||||
"safeHTML": safeHTML,
|
||||
|
||||
// Slice functions
|
||||
"join": strings.Join,
|
||||
|
||||
// Number functions
|
||||
"incr": incr,
|
||||
"decr": decr,
|
||||
"formatInt": formatInt,
|
||||
"formatFloat": formatFloat,
|
||||
|
||||
// Boolean functions
|
||||
"yesno": yesno,
|
||||
|
||||
// URL functions
|
||||
"urlSetParam": urlSetParam,
|
||||
"urlDelParam": urlDelParam,
|
||||
}
|
||||
|
||||
func formatTime(format string, t time.Time) string {
|
||||
return t.Format(format)
|
||||
}
|
||||
|
||||
func approxDuration(d time.Duration) string {
|
||||
const (
|
||||
day = 24 * time.Hour
|
||||
year = 365 * day
|
||||
)
|
||||
|
||||
formatUnit := func(count int, singular, plural string) string {
|
||||
if count == 1 {
|
||||
return fmt.Sprintf("1 %s", singular)
|
||||
}
|
||||
return fmt.Sprintf("%d %s", count, plural)
|
||||
}
|
||||
|
||||
switch {
|
||||
case d >= year:
|
||||
return formatUnit(int(math.Round(float64(d)/float64(year))), "year", "years")
|
||||
case d >= day:
|
||||
return formatUnit(int(math.Round(float64(d)/float64(day))), "day", "days")
|
||||
case d >= time.Hour:
|
||||
return formatUnit(int(math.Round(d.Hours())), "hour", "hours")
|
||||
case d >= time.Minute:
|
||||
return formatUnit(int(math.Round(d.Minutes())), "minute", "minutes")
|
||||
case d >= time.Second:
|
||||
return formatUnit(int(math.Round(d.Seconds())), "second", "seconds")
|
||||
default:
|
||||
return "less than 1 second"
|
||||
}
|
||||
}
|
||||
|
||||
func pluralize(count any, singular string, plural string) (string, error) {
|
||||
n, err := toInt64(count)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if n == 1 {
|
||||
return singular, nil
|
||||
}
|
||||
|
||||
return plural, nil
|
||||
}
|
||||
|
||||
func slugify(s string) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
for _, r := range s {
|
||||
switch {
|
||||
case r > unicode.MaxASCII:
|
||||
continue
|
||||
case unicode.IsLetter(r):
|
||||
buf.WriteRune(unicode.ToLower(r))
|
||||
case unicode.IsDigit(r), r == '_', r == '-':
|
||||
buf.WriteRune(r)
|
||||
case unicode.IsSpace(r):
|
||||
buf.WriteRune('-')
|
||||
}
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func safeHTML(s string) template.HTML {
|
||||
return template.HTML(s)
|
||||
}
|
||||
|
||||
func incr(i any) (int64, error) {
|
||||
n, err := toInt64(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n++
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func decr(i any) (int64, error) {
|
||||
n, err := toInt64(i)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
n--
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func formatInt(i any) (string, error) {
|
||||
n, err := toInt64(i)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return printer.Sprintf("%d", n), nil
|
||||
}
|
||||
|
||||
func formatFloat(f float64, dp int) string {
|
||||
format := "%." + strconv.Itoa(dp) + "f"
|
||||
return printer.Sprintf(format, f)
|
||||
}
|
||||
|
||||
func yesno(b bool) string {
|
||||
if b {
|
||||
return "Yes"
|
||||
}
|
||||
|
||||
return "No"
|
||||
}
|
||||
|
||||
func urlSetParam(u *url.URL, key string, value any) *url.URL {
|
||||
nu := *u
|
||||
values := nu.Query()
|
||||
|
||||
values.Set(key, fmt.Sprintf("%v", value))
|
||||
|
||||
nu.RawQuery = values.Encode()
|
||||
return &nu
|
||||
}
|
||||
|
||||
func urlDelParam(u *url.URL, key string) *url.URL {
|
||||
nu := *u
|
||||
values := nu.Query()
|
||||
|
||||
values.Del(key)
|
||||
|
||||
nu.RawQuery = values.Encode()
|
||||
return &nu
|
||||
}
|
||||
|
||||
func toInt64(i any) (int64, error) {
|
||||
switch v := i.(type) {
|
||||
case int:
|
||||
return int64(v), nil
|
||||
case int8:
|
||||
return int64(v), nil
|
||||
case int16:
|
||||
return int64(v), nil
|
||||
case int32:
|
||||
return int64(v), nil
|
||||
case int64:
|
||||
return v, nil
|
||||
case uint:
|
||||
return int64(v), nil
|
||||
case uint8:
|
||||
return int64(v), nil
|
||||
case uint16:
|
||||
return int64(v), nil
|
||||
case uint32:
|
||||
return int64(v), nil
|
||||
// Note: uint64 not supported due to risk of truncation.
|
||||
case string:
|
||||
return strconv.ParseInt(v, 10, 64)
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("unable to convert type %T to int", i)
|
||||
}
|
||||
Reference in New Issue
Block a user