This commit is contained in:
binwiederhier
2025-07-13 12:45:00 +02:00
parent 3ac3e2ec7c
commit 2a468493f9
16 changed files with 174 additions and 216 deletions

View File

@@ -10,19 +10,19 @@ import (
// Date can be a `time.Time` or an `int, int32, int64`. // Date can be a `time.Time` or an `int, int32, int64`.
// In the later case, it is treated as seconds since UNIX // In the later case, it is treated as seconds since UNIX
// epoch. // epoch.
func date(fmt string, date interface{}) string { func date(fmt string, date any) string {
return dateInZone(fmt, date, "Local") return dateInZone(fmt, date, "Local")
} }
func htmlDate(date interface{}) string { func htmlDate(date any) string {
return dateInZone("2006-01-02", date, "Local") return dateInZone("2006-01-02", date, "Local")
} }
func htmlDateInZone(date interface{}, zone string) string { func htmlDateInZone(date any, zone string) string {
return dateInZone("2006-01-02", date, zone) return dateInZone("2006-01-02", date, zone)
} }
func dateInZone(fmt string, date interface{}, zone string) string { func dateInZone(fmt string, date any, zone string) string {
var t time.Time var t time.Time
switch date := date.(type) { switch date := date.(type) {
default: default:
@@ -63,7 +63,7 @@ func mustDateModify(fmt string, date time.Time) (time.Time, error) {
return date.Add(d), nil return date.Add(d), nil
} }
func dateAgo(date interface{}) string { func dateAgo(date any) string {
var t time.Time var t time.Time
switch date := date.(type) { switch date := date.(type) {
@@ -81,7 +81,7 @@ func dateAgo(date interface{}) string {
return duration.String() return duration.String()
} }
func duration(sec interface{}) string { func duration(sec any) string {
var n int64 var n int64
switch value := sec.(type) { switch value := sec.(type) {
default: default:
@@ -94,7 +94,7 @@ func duration(sec interface{}) string {
return (time.Duration(n) * time.Second).String() return (time.Duration(n) * time.Second).String()
} }
func durationRound(duration interface{}) string { func durationRound(duration any) string {
var d time.Duration var d time.Duration
switch duration := duration.(type) { switch duration := duration.(type) {
default: default:

View File

@@ -15,15 +15,15 @@ func TestHtmlDate(t *testing.T) {
func TestAgo(t *testing.T) { func TestAgo(t *testing.T) {
tpl := "{{ ago .Time }}" tpl := "{{ ago .Time }}"
if err := runtv(tpl, "2m5s", map[string]interface{}{"Time": time.Now().Add(-125 * time.Second)}); err != nil { if err := runtv(tpl, "2m5s", map[string]any{"Time": time.Now().Add(-125 * time.Second)}); err != nil {
t.Error(err) t.Error(err)
} }
if err := runtv(tpl, "2h34m17s", map[string]interface{}{"Time": time.Now().Add(-(2*3600 + 34*60 + 17) * time.Second)}); err != nil { if err := runtv(tpl, "2h34m17s", map[string]any{"Time": time.Now().Add(-(2*3600 + 34*60 + 17) * time.Second)}); err != nil {
t.Error(err) t.Error(err)
} }
if err := runtv(tpl, "-5s", map[string]interface{}{"Time": time.Now().Add(5 * time.Second)}); err != nil { if err := runtv(tpl, "-5s", map[string]any{"Time": time.Now().Add(5 * time.Second)}); err != nil {
t.Error(err) t.Error(err)
} }
} }
@@ -42,7 +42,7 @@ func TestUnixEpoch(t *testing.T) {
} }
tpl := `{{unixEpoch .Time}}` tpl := `{{unixEpoch .Time}}`
if err = runtv(tpl, "1560458379", map[string]interface{}{"Time": tm}); err != nil { if err = runtv(tpl, "1560458379", map[string]any{"Time": tm}); err != nil {
t.Error(err) t.Error(err)
} }
} }
@@ -55,66 +55,66 @@ func TestDateInZone(t *testing.T) {
tpl := `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "UTC" }}` tpl := `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "UTC" }}`
// Test time.Time input // Test time.Time input
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": tm}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": tm}); err != nil {
t.Error(err) t.Error(err)
} }
// Test pointer to time.Time input // Test pointer to time.Time input
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": &tm}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": &tm}); err != nil {
t.Error(err) t.Error(err)
} }
// Test no time input. This should be close enough to time.Now() we can test // Test no time input. This should be close enough to time.Now() we can test
loc, _ := time.LoadLocation("UTC") loc, _ := time.LoadLocation("UTC")
if err = runtv(tpl, time.Now().In(loc).Format("02 Jan 06 15:04 -0700"), map[string]interface{}{"Time": ""}); err != nil { if err = runtv(tpl, time.Now().In(loc).Format("02 Jan 06 15:04 -0700"), map[string]any{"Time": ""}); err != nil {
t.Error(err) t.Error(err)
} }
// Test unix timestamp as int64 // Test unix timestamp as int64
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int64(1560458379)}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int64(1560458379)}); err != nil {
t.Error(err) t.Error(err)
} }
// Test unix timestamp as int32 // Test unix timestamp as int32
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int32(1560458379)}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int32(1560458379)}); err != nil {
t.Error(err) t.Error(err)
} }
// Test unix timestamp as int // Test unix timestamp as int
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int(1560458379)}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int(1560458379)}); err != nil {
t.Error(err) t.Error(err)
} }
// Test case of invalid timezone // Test case of invalid timezone
tpl = `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "foobar" }}` tpl = `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "foobar" }}`
if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": tm}); err != nil { if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": tm}); err != nil {
t.Error(err) t.Error(err)
} }
} }
func TestDuration(t *testing.T) { func TestDuration(t *testing.T) {
tpl := "{{ duration .Secs }}" tpl := "{{ duration .Secs }}"
if err := runtv(tpl, "1m1s", map[string]interface{}{"Secs": "61"}); err != nil { if err := runtv(tpl, "1m1s", map[string]any{"Secs": "61"}); err != nil {
t.Error(err) t.Error(err)
} }
if err := runtv(tpl, "1h0m0s", map[string]interface{}{"Secs": "3600"}); err != nil { if err := runtv(tpl, "1h0m0s", map[string]any{"Secs": "3600"}); err != nil {
t.Error(err) t.Error(err)
} }
// 1d2h3m4s but go is opinionated // 1d2h3m4s but go is opinionated
if err := runtv(tpl, "26h3m4s", map[string]interface{}{"Secs": "93784"}); err != nil { if err := runtv(tpl, "26h3m4s", map[string]any{"Secs": "93784"}); err != nil {
t.Error(err) t.Error(err)
} }
} }
func TestDurationRound(t *testing.T) { func TestDurationRound(t *testing.T) {
tpl := "{{ durationRound .Time }}" tpl := "{{ durationRound .Time }}"
if err := runtv(tpl, "2h", map[string]interface{}{"Time": "2h5s"}); err != nil { if err := runtv(tpl, "2h", map[string]any{"Time": "2h5s"}); err != nil {
t.Error(err) t.Error(err)
} }
if err := runtv(tpl, "1d", map[string]interface{}{"Time": "24h5s"}); err != nil { if err := runtv(tpl, "1d", map[string]any{"Time": "24h5s"}); err != nil {
t.Error(err) t.Error(err)
} }
if err := runtv(tpl, "3mo", map[string]interface{}{"Time": "2400h5s"}); err != nil { if err := runtv(tpl, "3mo", map[string]any{"Time": "2400h5s"}); err != nil {
t.Error(err) t.Error(err)
} }
} }

View File

@@ -17,7 +17,7 @@ import (
// Structs are never considered unset. // Structs are never considered unset.
// //
// For everything else, including pointers, a nil value is unset. // For everything else, including pointers, a nil value is unset.
func dfault(d interface{}, given ...interface{}) interface{} { func dfault(d any, given ...any) any {
if empty(given) || empty(given[0]) { if empty(given) || empty(given[0]) {
return d return d
@@ -26,7 +26,7 @@ func dfault(d interface{}, given ...interface{}) interface{} {
} }
// empty returns true if the given value has the zero value for its type. // empty returns true if the given value has the zero value for its type.
func empty(given interface{}) bool { func empty(given any) bool {
g := reflect.ValueOf(given) g := reflect.ValueOf(given)
if !g.IsValid() { if !g.IsValid() {
return true return true
@@ -54,7 +54,7 @@ func empty(given interface{}) bool {
} }
// coalesce returns the first non-empty value. // coalesce returns the first non-empty value.
func coalesce(v ...interface{}) interface{} { func coalesce(v ...any) any {
for _, val := range v { for _, val := range v {
if !empty(val) { if !empty(val) {
return val return val
@@ -65,7 +65,7 @@ func coalesce(v ...interface{}) interface{} {
// all returns true if empty(x) is false for all values x in the list. // all returns true if empty(x) is false for all values x in the list.
// If the list is empty, return true. // If the list is empty, return true.
func all(v ...interface{}) bool { func all(v ...any) bool {
for _, val := range v { for _, val := range v {
if empty(val) { if empty(val) {
return false return false
@@ -74,9 +74,9 @@ func all(v ...interface{}) bool {
return true return true
} }
// any returns true if empty(x) is false for any x in the list. // anyNonEmpty returns true if empty(x) is false for anyNonEmpty x in the list.
// If the list is empty, return false. // If the list is empty, return false.
func any(v ...interface{}) bool { func anyNonEmpty(v ...any) bool {
for _, val := range v { for _, val := range v {
if !empty(val) { if !empty(val) {
return true return true
@@ -86,25 +86,25 @@ func any(v ...interface{}) bool {
} }
// fromJSON decodes JSON into a structured value, ignoring errors. // fromJSON decodes JSON into a structured value, ignoring errors.
func fromJSON(v string) interface{} { func fromJSON(v string) any {
output, _ := mustFromJSON(v) output, _ := mustFromJSON(v)
return output return output
} }
// mustFromJSON decodes JSON into a structured value, returning errors. // mustFromJSON decodes JSON into a structured value, returning errors.
func mustFromJSON(v string) (interface{}, error) { func mustFromJSON(v string) (any, error) {
var output interface{} var output any
err := json.Unmarshal([]byte(v), &output) err := json.Unmarshal([]byte(v), &output)
return output, err return output, err
} }
// toJSON encodes an item into a JSON string // toJSON encodes an item into a JSON string
func toJSON(v interface{}) string { func toJSON(v any) string {
output, _ := json.Marshal(v) output, _ := json.Marshal(v)
return string(output) return string(output)
} }
func mustToJSON(v interface{}) (string, error) { func mustToJSON(v any) (string, error) {
output, err := json.Marshal(v) output, err := json.Marshal(v)
if err != nil { if err != nil {
return "", err return "", err
@@ -113,12 +113,12 @@ func mustToJSON(v interface{}) (string, error) {
} }
// toPrettyJSON encodes an item into a pretty (indented) JSON string // toPrettyJSON encodes an item into a pretty (indented) JSON string
func toPrettyJSON(v interface{}) string { func toPrettyJSON(v any) string {
output, _ := json.MarshalIndent(v, "", " ") output, _ := json.MarshalIndent(v, "", " ")
return string(output) return string(output)
} }
func mustToPrettyJSON(v interface{}) (string, error) { func mustToPrettyJSON(v any) (string, error) {
output, err := json.MarshalIndent(v, "", " ") output, err := json.MarshalIndent(v, "", " ")
if err != nil { if err != nil {
return "", err return "", err
@@ -127,7 +127,7 @@ func mustToPrettyJSON(v interface{}) (string, error) {
} }
// toRawJSON encodes an item into a JSON string with no escaping of HTML characters. // toRawJSON encodes an item into a JSON string with no escaping of HTML characters.
func toRawJSON(v interface{}) string { func toRawJSON(v any) string {
output, err := mustToRawJSON(v) output, err := mustToRawJSON(v)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -136,7 +136,7 @@ func toRawJSON(v interface{}) string {
} }
// mustToRawJSON encodes an item into a JSON string with no escaping of HTML characters. // mustToRawJSON encodes an item into a JSON string with no escaping of HTML characters.
func mustToRawJSON(v interface{}) (string, error) { func mustToRawJSON(v any) (string, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
enc := json.NewEncoder(buf) enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false) enc.SetEscapeHTML(false)
@@ -148,10 +148,9 @@ func mustToRawJSON(v interface{}) (string, error) {
} }
// ternary returns the first value if the last value is true, otherwise returns the second value. // ternary returns the first value if the last value is true, otherwise returns the second value.
func ternary(vt interface{}, vf interface{}, v bool) interface{} { func ternary(vt any, vf any, v bool) any {
if v { if v {
return vt return vt
} }
return vf return vf
} }

View File

@@ -53,7 +53,7 @@ func TestEmpty(t *testing.T) {
t.Error(err) t.Error(err)
} }
dict := map[string]interface{}{"top": map[string]interface{}{}} dict := map[string]any{"top": map[string]any{}}
tpl = `{{if empty .top.NoSuchThing}}1{{else}}0{{end}}` tpl = `{{if empty .top.NoSuchThing}}1{{else}}0{{end}}`
if err := runtv(tpl, "1", dict); err != nil { if err := runtv(tpl, "1", dict); err != nil {
t.Error(err) t.Error(err)
@@ -77,7 +77,7 @@ func TestCoalesce(t *testing.T) {
assert.NoError(t, runt(tpl, expect)) assert.NoError(t, runt(tpl, expect))
} }
dict := map[string]interface{}{"top": map[string]interface{}{}} dict := map[string]any{"top": map[string]any{}}
tpl := `{{ coalesce .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` tpl := `{{ coalesce .top.NoSuchThing .bottom .bottom.dollar "airplane"}}`
if err := runtv(tpl, "airplane", dict); err != nil { if err := runtv(tpl, "airplane", dict); err != nil {
t.Error(err) t.Error(err)
@@ -97,7 +97,7 @@ func TestAll(t *testing.T) {
assert.NoError(t, runt(tpl, expect)) assert.NoError(t, runt(tpl, expect))
} }
dict := map[string]interface{}{"top": map[string]interface{}{}} dict := map[string]any{"top": map[string]any{}}
tpl := `{{ all .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` tpl := `{{ all .top.NoSuchThing .bottom .bottom.dollar "airplane"}}`
if err := runtv(tpl, "false", dict); err != nil { if err := runtv(tpl, "false", dict); err != nil {
t.Error(err) t.Error(err)
@@ -117,7 +117,7 @@ func TestAny(t *testing.T) {
assert.NoError(t, runt(tpl, expect)) assert.NoError(t, runt(tpl, expect))
} }
dict := map[string]interface{}{"top": map[string]interface{}{}} dict := map[string]any{"top": map[string]any{}}
tpl := `{{ any .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` tpl := `{{ any .top.NoSuchThing .bottom .bottom.dollar "airplane"}}`
if err := runtv(tpl, "true", dict); err != nil { if err := runtv(tpl, "true", dict); err != nil {
t.Error(err) t.Error(err)
@@ -125,7 +125,7 @@ func TestAny(t *testing.T) {
} }
func TestFromJSON(t *testing.T) { func TestFromJSON(t *testing.T) {
dict := map[string]interface{}{"Input": `{"foo": 55}`} dict := map[string]any{"Input": `{"foo": 55}`}
tpl := `{{.Input | fromJSON}}` tpl := `{{.Input | fromJSON}}`
expected := `map[foo:55]` expected := `map[foo:55]`
@@ -141,7 +141,7 @@ func TestFromJSON(t *testing.T) {
} }
func TestToJSON(t *testing.T) { func TestToJSON(t *testing.T) {
dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}} dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42}}
tpl := `{{.Top | toJSON}}` tpl := `{{.Top | toJSON}}`
expected := `{"bool":true,"number":42,"string":"test"}` expected := `{"bool":true,"number":42,"string":"test"}`
@@ -151,7 +151,7 @@ func TestToJSON(t *testing.T) {
} }
func TestToPrettyJSON(t *testing.T) { func TestToPrettyJSON(t *testing.T) {
dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}} dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42}}
tpl := `{{.Top | toPrettyJSON}}` tpl := `{{.Top | toPrettyJSON}}`
expected := `{ expected := `{
"bool": true, "bool": true,
@@ -164,7 +164,7 @@ func TestToPrettyJSON(t *testing.T) {
} }
func TestToRawJSON(t *testing.T) { func TestToRawJSON(t *testing.T) {
dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42, "html": "<HEAD>"}} dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42, "html": "<HEAD>"}}
tpl := `{{.Top | toRawJSON}}` tpl := `{{.Top | toRawJSON}}`
expected := `{"bool":true,"html":"<HEAD>","number":42,"string":"test"}` expected := `{"bool":true,"html":"<HEAD>","number":42,"string":"test"}`

View File

@@ -1,29 +1,29 @@
package sprig package sprig
func get(d map[string]interface{}, key string) interface{} { func get(d map[string]any, key string) any {
if val, ok := d[key]; ok { if val, ok := d[key]; ok {
return val return val
} }
return "" return ""
} }
func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} { func set(d map[string]any, key string, value any) map[string]any {
d[key] = value d[key] = value
return d return d
} }
func unset(d map[string]interface{}, key string) map[string]interface{} { func unset(d map[string]any, key string) map[string]any {
delete(d, key) delete(d, key)
return d return d
} }
func hasKey(d map[string]interface{}, key string) bool { func hasKey(d map[string]any, key string) bool {
_, ok := d[key] _, ok := d[key]
return ok return ok
} }
func pluck(key string, d ...map[string]interface{}) []interface{} { func pluck(key string, d ...map[string]any) []any {
res := []interface{}{} var res []any
for _, dict := range d { for _, dict := range d {
if val, ok := dict[key]; ok { if val, ok := dict[key]; ok {
res = append(res, val) res = append(res, val)
@@ -32,7 +32,7 @@ func pluck(key string, d ...map[string]interface{}) []interface{} {
return res return res
} }
func keys(dicts ...map[string]interface{}) []string { func keys(dicts ...map[string]any) []string {
k := []string{} k := []string{}
for _, dict := range dicts { for _, dict := range dicts {
for key := range dict { for key := range dict {
@@ -42,8 +42,8 @@ func keys(dicts ...map[string]interface{}) []string {
return k return k
} }
func pick(dict map[string]interface{}, keys ...string) map[string]interface{} { func pick(dict map[string]any, keys ...string) map[string]any {
res := map[string]interface{}{} res := map[string]any{}
for _, k := range keys { for _, k := range keys {
if v, ok := dict[k]; ok { if v, ok := dict[k]; ok {
res[k] = v res[k] = v
@@ -52,8 +52,8 @@ func pick(dict map[string]interface{}, keys ...string) map[string]interface{} {
return res return res
} }
func omit(dict map[string]interface{}, keys ...string) map[string]interface{} { func omit(dict map[string]any, keys ...string) map[string]any {
res := map[string]interface{}{} res := map[string]any{}
omit := make(map[string]bool, len(keys)) omit := make(map[string]bool, len(keys))
for _, k := range keys { for _, k := range keys {
@@ -68,8 +68,8 @@ func omit(dict map[string]interface{}, keys ...string) map[string]interface{} {
return res return res
} }
func dict(v ...interface{}) map[string]interface{} { func dict(v ...any) map[string]any {
dict := map[string]interface{}{} dict := map[string]any{}
lenv := len(v) lenv := len(v)
for i := 0; i < lenv; i += 2 { for i := 0; i < lenv; i += 2 {
key := strval(v[i]) key := strval(v[i])
@@ -82,20 +82,19 @@ func dict(v ...interface{}) map[string]interface{} {
return dict return dict
} }
func values(dict map[string]interface{}) []interface{} { func values(dict map[string]any) []any {
values := []interface{}{} var values []any
for _, value := range dict { for _, value := range dict {
values = append(values, value) values = append(values, value)
} }
return values return values
} }
func dig(ps ...interface{}) (interface{}, error) { func dig(ps ...any) (any, error) {
if len(ps) < 3 { if len(ps) < 3 {
panic("dig needs at least three arguments") panic("dig needs at least three arguments")
} }
dict := ps[len(ps)-1].(map[string]interface{}) dict := ps[len(ps)-1].(map[string]any)
def := ps[len(ps)-2] def := ps[len(ps)-2]
ks := make([]string, len(ps)-2) ks := make([]string, len(ps)-2)
for i := 0; i < len(ks); i++ { for i := 0; i < len(ks); i++ {
@@ -105,7 +104,7 @@ func dig(ps ...interface{}) (interface{}, error) {
return digFromDict(dict, def, ks) return digFromDict(dict, def, ks)
} }
func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (interface{}, error) { func digFromDict(dict map[string]any, d any, ks []string) (any, error) {
k, ns := ks[0], ks[1:] k, ns := ks[0], ks[1:]
step, has := dict[k] step, has := dict[k]
if !has { if !has {
@@ -114,5 +113,5 @@ func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (inter
if len(ns) == 0 { if len(ns) == 0 {
return step, nil return step, nil
} }
return digFromDict(step.(map[string]interface{}), d, ns) return digFromDict(step.(map[string]any), d, ns)
} }

View File

@@ -8,7 +8,7 @@ import (
func Example() { func Example() {
// Set up variables and template. // Set up variables and template.
vars := map[string]interface{}{"Name": " John Jacob Jingleheimer Schmidt "} vars := map[string]any{"Name": " John Jacob Jingleheimer Schmidt "}
tpl := `Hello {{.Name | trim | lower}}` tpl := `Hello {{.Name | trim | lower}}`
// Get the Sprig function map. // Get the Sprig function map.

View File

@@ -24,68 +24,26 @@ func FuncMap() template.FuncMap {
return HTMLFuncMap() return HTMLFuncMap()
} }
// HermeticTxtFuncMap returns a 'text/template'.FuncMap with only repeatable functions.
func HermeticTxtFuncMap() ttemplate.FuncMap {
r := TxtFuncMap()
for _, name := range nonhermeticFunctions {
delete(r, name)
}
return r
}
// HermeticHTMLFuncMap returns an 'html/template'.Funcmap with only repeatable functions.
func HermeticHTMLFuncMap() template.FuncMap {
r := HTMLFuncMap()
for _, name := range nonhermeticFunctions {
delete(r, name)
}
return r
}
// TxtFuncMap returns a 'text/template'.FuncMap // TxtFuncMap returns a 'text/template'.FuncMap
func TxtFuncMap() ttemplate.FuncMap { func TxtFuncMap() ttemplate.FuncMap {
return ttemplate.FuncMap(GenericFuncMap()) return GenericFuncMap()
} }
// HTMLFuncMap returns an 'html/template'.Funcmap // HTMLFuncMap returns an 'html/template'.Funcmap
func HTMLFuncMap() template.FuncMap { func HTMLFuncMap() template.FuncMap {
return template.FuncMap(GenericFuncMap()) return GenericFuncMap()
} }
// GenericFuncMap returns a copy of the basic function map as a map[string]interface{}. // GenericFuncMap returns a copy of the basic function map as a map[string]any.
func GenericFuncMap() map[string]interface{} { func GenericFuncMap() map[string]any {
gfm := make(map[string]interface{}, len(genericMap)) gfm := make(map[string]any, len(genericMap))
for k, v := range genericMap { for k, v := range genericMap {
gfm[k] = v gfm[k] = v
} }
return gfm return gfm
} }
// These functions are not guaranteed to evaluate to the same result for given input, because they var genericMap = map[string]any{
// refer to the environment or global state.
var nonhermeticFunctions = []string{
// Date functions
"date",
"date_in_zone",
"date_modify",
"now",
"htmlDate",
"htmlDateInZone",
"dateInZone",
"dateModify",
// Strings
"randAlphaNum",
"randAlpha",
"randAscii",
"randNumeric",
"randBytes",
"uuidv4",
}
var genericMap = map[string]interface{}{
"hello": func() string { return "Hello!" },
// Date functions // Date functions
"ago": dateAgo, "ago": dateAgo,
"date": date, "date": date,
@@ -157,18 +115,18 @@ var genericMap = map[string]interface{}{
"untilStep": untilStep, "untilStep": untilStep,
// VERY basic arithmetic. // VERY basic arithmetic.
"add1": func(i interface{}) int64 { return toInt64(i) + 1 }, "add1": func(i any) int64 { return toInt64(i) + 1 },
"add": func(i ...interface{}) int64 { "add": func(i ...any) int64 {
var a int64 = 0 var a int64 = 0
for _, b := range i { for _, b := range i {
a += toInt64(b) a += toInt64(b)
} }
return a return a
}, },
"sub": func(a, b interface{}) int64 { return toInt64(a) - toInt64(b) }, "sub": func(a, b any) int64 { return toInt64(a) - toInt64(b) },
"div": func(a, b interface{}) int64 { return toInt64(a) / toInt64(b) }, "div": func(a, b any) int64 { return toInt64(a) / toInt64(b) },
"mod": func(a, b interface{}) int64 { return toInt64(a) % toInt64(b) }, "mod": func(a, b any) int64 { return toInt64(a) % toInt64(b) },
"mul": func(a interface{}, v ...interface{}) int64 { "mul": func(a any, v ...any) int64 {
val := toInt64(a) val := toInt64(a)
for _, b := range v { for _, b := range v {
val = val * toInt64(b) val = val * toInt64(b)
@@ -195,7 +153,7 @@ var genericMap = map[string]interface{}{
"empty": empty, "empty": empty,
"coalesce": coalesce, "coalesce": coalesce,
"all": all, "all": all,
"any": any, "any": anyNonEmpty,
"compact": compact, "compact": compact,
"mustCompact": mustCompact, "mustCompact": mustCompact,
"fromJSON": fromJSON, "fromJSON": fromJSON,
@@ -250,8 +208,10 @@ var genericMap = map[string]interface{}{
"omit": omit, "omit": omit,
"values": values, "values": values,
"append": push, "push": push, "append": push,
"mustAppend": mustPush, "mustPush": mustPush, "push": push,
"mustAppend": mustPush,
"mustPush": mustPush,
"prepend": prepend, "prepend": prepend,
"mustPrepend": mustPrepend, "mustPrepend": mustPrepend,
"first": first, "first": first,

View File

@@ -43,7 +43,7 @@ func runt(tpl, expect string) error {
// runtv takes a template, and expected return, and values for substitution. // runtv takes a template, and expected return, and values for substitution.
// //
// It runs the template and verifies that the output is an exact match. // It runs the template and verifies that the output is an exact match.
func runtv(tpl, expect string, vars interface{}) error { func runtv(tpl, expect string, vars any) error {
fmap := TxtFuncMap() fmap := TxtFuncMap()
t := template.Must(template.New("test").Funcs(fmap).Parse(tpl)) t := template.Must(template.New("test").Funcs(fmap).Parse(tpl))
var b bytes.Buffer var b bytes.Buffer
@@ -58,7 +58,7 @@ func runtv(tpl, expect string, vars interface{}) error {
} }
// runRaw runs a template with the given variables and returns the result. // runRaw runs a template with the given variables and returns the result.
func runRaw(tpl string, vars interface{}) (string, error) { func runRaw(tpl string, vars any) (string, error) {
fmap := TxtFuncMap() fmap := TxtFuncMap()
t := template.Must(template.New("test").Funcs(fmap).Parse(tpl)) t := template.Must(template.New("test").Funcs(fmap).Parse(tpl))
var b bytes.Buffer var b bytes.Buffer

View File

@@ -8,14 +8,14 @@ import (
) )
// Reflection is used in these functions so that slices and arrays of strings, // Reflection is used in these functions so that slices and arrays of strings,
// ints, and other types not implementing []interface{} can be worked with. // ints, and other types not implementing []any can be worked with.
// For example, this is useful if you need to work on the output of regexs. // For example, this is useful if you need to work on the output of regexs.
func list(v ...interface{}) []interface{} { func list(v ...any) []any {
return v return v
} }
func push(list interface{}, v interface{}) []interface{} { func push(list any, v any) []any {
l, err := mustPush(list, v) l, err := mustPush(list, v)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -24,14 +24,14 @@ func push(list interface{}, v interface{}) []interface{} {
return l return l
} }
func mustPush(list interface{}, v interface{}) ([]interface{}, error) { func mustPush(list any, v any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(list) l2 := reflect.ValueOf(list)
l := l2.Len() l := l2.Len()
nl := make([]interface{}, l) nl := make([]any, l)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
nl[i] = l2.Index(i).Interface() nl[i] = l2.Index(i).Interface()
} }
@@ -43,7 +43,7 @@ func mustPush(list interface{}, v interface{}) ([]interface{}, error) {
} }
} }
func prepend(list interface{}, v interface{}) []interface{} { func prepend(list any, v any) []any {
l, err := mustPrepend(list, v) l, err := mustPrepend(list, v)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -52,8 +52,8 @@ func prepend(list interface{}, v interface{}) []interface{} {
return l return l
} }
func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) { func mustPrepend(list any, v any) ([]any, error) {
//return append([]interface{}{v}, list...) //return append([]any{v}, list...)
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
@@ -61,19 +61,19 @@ func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) {
l2 := reflect.ValueOf(list) l2 := reflect.ValueOf(list)
l := l2.Len() l := l2.Len()
nl := make([]interface{}, l) nl := make([]any, l)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
nl[i] = l2.Index(i).Interface() nl[i] = l2.Index(i).Interface()
} }
return append([]interface{}{v}, nl...), nil return append([]any{v}, nl...), nil
default: default:
return nil, fmt.Errorf("cannot prepend on type %s", tp) return nil, fmt.Errorf("cannot prepend on type %s", tp)
} }
} }
func chunk(size int, list interface{}) [][]interface{} { func chunk(size int, list any) [][]any {
l, err := mustChunk(size, list) l, err := mustChunk(size, list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -82,7 +82,7 @@ func chunk(size int, list interface{}) [][]interface{} {
return l return l
} }
func mustChunk(size int, list interface{}) ([][]interface{}, error) { func mustChunk(size int, list any) ([][]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -91,7 +91,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) {
l := l2.Len() l := l2.Len()
cs := int(math.Floor(float64(l-1)/float64(size)) + 1) cs := int(math.Floor(float64(l-1)/float64(size)) + 1)
nl := make([][]interface{}, cs) nl := make([][]any, cs)
for i := 0; i < cs; i++ { for i := 0; i < cs; i++ {
clen := size clen := size
@@ -102,7 +102,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) {
} }
} }
nl[i] = make([]interface{}, clen) nl[i] = make([]any, clen)
for j := 0; j < clen; j++ { for j := 0; j < clen; j++ {
ix := i*size + j ix := i*size + j
@@ -117,7 +117,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) {
} }
} }
func last(list interface{}) interface{} { func last(list any) any {
l, err := mustLast(list) l, err := mustLast(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -126,7 +126,7 @@ func last(list interface{}) interface{} {
return l return l
} }
func mustLast(list interface{}) (interface{}, error) { func mustLast(list any) (any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -143,7 +143,7 @@ func mustLast(list interface{}) (interface{}, error) {
} }
} }
func first(list interface{}) interface{} { func first(list any) any {
l, err := mustFirst(list) l, err := mustFirst(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -152,7 +152,7 @@ func first(list interface{}) interface{} {
return l return l
} }
func mustFirst(list interface{}) (interface{}, error) { func mustFirst(list any) (any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -169,7 +169,7 @@ func mustFirst(list interface{}) (interface{}, error) {
} }
} }
func rest(list interface{}) []interface{} { func rest(list any) []any {
l, err := mustRest(list) l, err := mustRest(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -178,7 +178,7 @@ func rest(list interface{}) []interface{} {
return l return l
} }
func mustRest(list interface{}) ([]interface{}, error) { func mustRest(list any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -189,7 +189,7 @@ func mustRest(list interface{}) ([]interface{}, error) {
return nil, nil return nil, nil
} }
nl := make([]interface{}, l-1) nl := make([]any, l-1)
for i := 1; i < l; i++ { for i := 1; i < l; i++ {
nl[i-1] = l2.Index(i).Interface() nl[i-1] = l2.Index(i).Interface()
} }
@@ -200,7 +200,7 @@ func mustRest(list interface{}) ([]interface{}, error) {
} }
} }
func initial(list interface{}) []interface{} { func initial(list any) []any {
l, err := mustInitial(list) l, err := mustInitial(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -209,7 +209,7 @@ func initial(list interface{}) []interface{} {
return l return l
} }
func mustInitial(list interface{}) ([]interface{}, error) { func mustInitial(list any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -220,7 +220,7 @@ func mustInitial(list interface{}) ([]interface{}, error) {
return nil, nil return nil, nil
} }
nl := make([]interface{}, l-1) nl := make([]any, l-1)
for i := 0; i < l-1; i++ { for i := 0; i < l-1; i++ {
nl[i] = l2.Index(i).Interface() nl[i] = l2.Index(i).Interface()
} }
@@ -231,7 +231,7 @@ func mustInitial(list interface{}) ([]interface{}, error) {
} }
} }
func sortAlpha(list interface{}) []string { func sortAlpha(list any) []string {
k := reflect.Indirect(reflect.ValueOf(list)).Kind() k := reflect.Indirect(reflect.ValueOf(list)).Kind()
switch k { switch k {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -243,7 +243,7 @@ func sortAlpha(list interface{}) []string {
return []string{strval(list)} return []string{strval(list)}
} }
func reverse(v interface{}) []interface{} { func reverse(v any) []any {
l, err := mustReverse(v) l, err := mustReverse(v)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -252,7 +252,7 @@ func reverse(v interface{}) []interface{} {
return l return l
} }
func mustReverse(v interface{}) ([]interface{}, error) { func mustReverse(v any) ([]any, error) {
tp := reflect.TypeOf(v).Kind() tp := reflect.TypeOf(v).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -260,7 +260,7 @@ func mustReverse(v interface{}) ([]interface{}, error) {
l := l2.Len() l := l2.Len()
// We do not sort in place because the incoming array should not be altered. // We do not sort in place because the incoming array should not be altered.
nl := make([]interface{}, l) nl := make([]any, l)
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
nl[l-i-1] = l2.Index(i).Interface() nl[l-i-1] = l2.Index(i).Interface()
} }
@@ -271,7 +271,7 @@ func mustReverse(v interface{}) ([]interface{}, error) {
} }
} }
func compact(list interface{}) []interface{} { func compact(list any) []any {
l, err := mustCompact(list) l, err := mustCompact(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -280,15 +280,15 @@ func compact(list interface{}) []interface{} {
return l return l
} }
func mustCompact(list interface{}) ([]interface{}, error) { func mustCompact(list any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(list) l2 := reflect.ValueOf(list)
l := l2.Len() l := l2.Len()
nl := []interface{}{} nl := []any{}
var item interface{} var item any
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
item = l2.Index(i).Interface() item = l2.Index(i).Interface()
if !empty(item) { if !empty(item) {
@@ -302,7 +302,7 @@ func mustCompact(list interface{}) ([]interface{}, error) {
} }
} }
func uniq(list interface{}) []interface{} { func uniq(list any) []any {
l, err := mustUniq(list) l, err := mustUniq(list)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -311,15 +311,15 @@ func uniq(list interface{}) []interface{} {
return l return l
} }
func mustUniq(list interface{}) ([]interface{}, error) { func mustUniq(list any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(list) l2 := reflect.ValueOf(list)
l := l2.Len() l := l2.Len()
dest := []interface{}{} dest := []any{}
var item interface{} var item any
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
item = l2.Index(i).Interface() item = l2.Index(i).Interface()
if !inList(dest, item) { if !inList(dest, item) {
@@ -333,7 +333,7 @@ func mustUniq(list interface{}) ([]interface{}, error) {
} }
} }
func inList(haystack []interface{}, needle interface{}) bool { func inList(haystack []any, needle any) bool {
for _, h := range haystack { for _, h := range haystack {
if reflect.DeepEqual(needle, h) { if reflect.DeepEqual(needle, h) {
return true return true
@@ -342,7 +342,7 @@ func inList(haystack []interface{}, needle interface{}) bool {
return false return false
} }
func without(list interface{}, omit ...interface{}) []interface{} { func without(list any, omit ...any) []any {
l, err := mustWithout(list, omit...) l, err := mustWithout(list, omit...)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -351,15 +351,15 @@ func without(list interface{}, omit ...interface{}) []interface{} {
return l return l
} }
func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) { func mustWithout(list any, omit ...any) ([]any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(list) l2 := reflect.ValueOf(list)
l := l2.Len() l := l2.Len()
res := []interface{}{} res := []any{}
var item interface{} var item any
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
item = l2.Index(i).Interface() item = l2.Index(i).Interface()
if !inList(omit, item) { if !inList(omit, item) {
@@ -373,7 +373,7 @@ func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) {
} }
} }
func has(needle interface{}, haystack interface{}) bool { func has(needle any, haystack any) bool {
l, err := mustHas(needle, haystack) l, err := mustHas(needle, haystack)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -382,7 +382,7 @@ func has(needle interface{}, haystack interface{}) bool {
return l return l
} }
func mustHas(needle interface{}, haystack interface{}) (bool, error) { func mustHas(needle any, haystack any) (bool, error) {
if haystack == nil { if haystack == nil {
return false, nil return false, nil
} }
@@ -390,7 +390,7 @@ func mustHas(needle interface{}, haystack interface{}) (bool, error) {
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
l2 := reflect.ValueOf(haystack) l2 := reflect.ValueOf(haystack)
var item interface{} var item any
l := l2.Len() l := l2.Len()
for i := 0; i < l; i++ { for i := 0; i < l; i++ {
item = l2.Index(i).Interface() item = l2.Index(i).Interface()
@@ -410,7 +410,7 @@ func mustHas(needle interface{}, haystack interface{}) (bool, error) {
// slice $list 0 3 -> list[0:3] = list[:3] // slice $list 0 3 -> list[0:3] = list[:3]
// slice $list 3 5 -> list[3:5] // slice $list 3 5 -> list[3:5]
// slice $list 3 -> list[3:5] = list[3:] // slice $list 3 -> list[3:5] = list[3:]
func slice(list interface{}, indices ...interface{}) interface{} { func slice(list any, indices ...any) any {
l, err := mustSlice(list, indices...) l, err := mustSlice(list, indices...)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -419,7 +419,7 @@ func slice(list interface{}, indices ...interface{}) interface{} {
return l return l
} }
func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) { func mustSlice(list any, indices ...any) (any, error) {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
@@ -446,8 +446,8 @@ func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) {
} }
} }
func concat(lists ...interface{}) interface{} { func concat(lists ...any) any {
var res []interface{} var res []any
for _, list := range lists { for _, list := range lists {
tp := reflect.TypeOf(list).Kind() tp := reflect.TypeOf(list).Kind()
switch tp { switch tp {

View File

@@ -9,7 +9,7 @@ import (
) )
// toFloat64 converts 64-bit floats // toFloat64 converts 64-bit floats
func toFloat64(v interface{}) float64 { func toFloat64(v any) float64 {
if str, ok := v.(string); ok { if str, ok := v.(string); ok {
iv, err := strconv.ParseFloat(str, 64) iv, err := strconv.ParseFloat(str, 64)
if err != nil { if err != nil {
@@ -38,13 +38,13 @@ func toFloat64(v interface{}) float64 {
} }
} }
func toInt(v interface{}) int { func toInt(v any) int {
// It's not optimal. But I don't want duplicate toInt64 code. // It's not optimal. But I don't want duplicate toInt64 code.
return int(toInt64(v)) return int(toInt64(v))
} }
// toInt64 converts integer types to 64-bit integers // toInt64 converts integer types to 64-bit integers
func toInt64(v interface{}) int64 { func toInt64(v any) int64 {
if str, ok := v.(string); ok { if str, ok := v.(string); ok {
iv, err := strconv.ParseInt(str, 10, 64) iv, err := strconv.ParseInt(str, 10, 64)
if err != nil { if err != nil {
@@ -78,7 +78,7 @@ func toInt64(v interface{}) int64 {
} }
} }
func max(a interface{}, i ...interface{}) int64 { func max(a any, i ...any) int64 {
aa := toInt64(a) aa := toInt64(a)
for _, b := range i { for _, b := range i {
bb := toInt64(b) bb := toInt64(b)
@@ -89,7 +89,7 @@ func max(a interface{}, i ...interface{}) int64 {
return aa return aa
} }
func maxf(a interface{}, i ...interface{}) float64 { func maxf(a any, i ...any) float64 {
aa := toFloat64(a) aa := toFloat64(a)
for _, b := range i { for _, b := range i {
bb := toFloat64(b) bb := toFloat64(b)
@@ -98,7 +98,7 @@ func maxf(a interface{}, i ...interface{}) float64 {
return aa return aa
} }
func min(a interface{}, i ...interface{}) int64 { func min(a any, i ...any) int64 {
aa := toInt64(a) aa := toInt64(a)
for _, b := range i { for _, b := range i {
bb := toInt64(b) bb := toInt64(b)
@@ -109,7 +109,7 @@ func min(a interface{}, i ...interface{}) int64 {
return aa return aa
} }
func minf(a interface{}, i ...interface{}) float64 { func minf(a any, i ...any) float64 {
aa := toFloat64(a) aa := toFloat64(a)
for _, b := range i { for _, b := range i {
bb := toFloat64(b) bb := toFloat64(b)
@@ -148,17 +148,17 @@ func untilStep(start, stop, step int) []int {
return v return v
} }
func floor(a interface{}) float64 { func floor(a any) float64 {
aa := toFloat64(a) aa := toFloat64(a)
return math.Floor(aa) return math.Floor(aa)
} }
func ceil(a interface{}) float64 { func ceil(a any) float64 {
aa := toFloat64(a) aa := toFloat64(a)
return math.Ceil(aa) return math.Ceil(aa)
} }
func round(a interface{}, p int, rOpt ...float64) float64 { func round(a any, p int, rOpt ...float64) float64 {
roundOn := .5 roundOn := .5
if len(rOpt) > 0 { if len(rOpt) > 0 {
roundOn = rOpt[0] roundOn = rOpt[0]
@@ -179,7 +179,7 @@ func round(a interface{}, p int, rOpt ...float64) float64 {
} }
// converts unix octal to decimal // converts unix octal to decimal
func toDecimal(v interface{}) int64 { func toDecimal(v any) int64 {
result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64) result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64)
if err != nil { if err != nil {
return 0 return 0

View File

@@ -192,7 +192,7 @@ func TestToInt(t *testing.T) {
} }
func TestToDecimal(t *testing.T) { func TestToDecimal(t *testing.T) {
tests := map[interface{}]int64{ tests := map[any]int64{
"777": 511, "777": 511,
777: 511, 777: 511,
770: 504, 770: 504,

View File

@@ -6,23 +6,23 @@ import (
) )
// typeIs returns true if the src is the type named in target. // typeIs returns true if the src is the type named in target.
func typeIs(target string, src interface{}) bool { func typeIs(target string, src any) bool {
return target == typeOf(src) return target == typeOf(src)
} }
func typeIsLike(target string, src interface{}) bool { func typeIsLike(target string, src any) bool {
t := typeOf(src) t := typeOf(src)
return target == t || "*"+target == t return target == t || "*"+target == t
} }
func typeOf(src interface{}) string { func typeOf(src any) string {
return fmt.Sprintf("%T", src) return fmt.Sprintf("%T", src)
} }
func kindIs(target string, src interface{}) bool { func kindIs(target string, src any) bool {
return target == kindOf(src) return target == kindOf(src)
} }
func kindOf(src interface{}) string { func kindOf(src any) string {
return reflect.ValueOf(src).Kind().String() return reflect.ValueOf(src).Kind().String()
} }

View File

@@ -33,7 +33,7 @@ func base32decode(v string) string {
return string(data) return string(data)
} }
func quote(str ...interface{}) string { func quote(str ...any) string {
out := make([]string, 0, len(str)) out := make([]string, 0, len(str))
for _, s := range str { for _, s := range str {
if s != nil { if s != nil {
@@ -43,7 +43,7 @@ func quote(str ...interface{}) string {
return strings.Join(out, " ") return strings.Join(out, " ")
} }
func squote(str ...interface{}) string { func squote(str ...any) string {
out := make([]string, 0, len(str)) out := make([]string, 0, len(str))
for _, s := range str { for _, s := range str {
if s != nil { if s != nil {
@@ -53,7 +53,7 @@ func squote(str ...interface{}) string {
return strings.Join(out, " ") return strings.Join(out, " ")
} }
func cat(v ...interface{}) string { func cat(v ...any) string {
v = removeNilElements(v) v = removeNilElements(v)
r := strings.TrimSpace(strings.Repeat("%v ", len(v))) r := strings.TrimSpace(strings.Repeat("%v ", len(v)))
return fmt.Sprintf(r, v...) return fmt.Sprintf(r, v...)
@@ -79,11 +79,11 @@ func plural(one, many string, count int) string {
return many return many
} }
func strslice(v interface{}) []string { func strslice(v any) []string {
switch v := v.(type) { switch v := v.(type) {
case []string: case []string:
return v return v
case []interface{}: case []any:
b := make([]string, 0, len(v)) b := make([]string, 0, len(v))
for _, s := range v { for _, s := range v {
if s != nil { if s != nil {
@@ -114,8 +114,8 @@ func strslice(v interface{}) []string {
} }
} }
func removeNilElements(v []interface{}) []interface{} { func removeNilElements(v []any) []any {
newSlice := make([]interface{}, 0, len(v)) newSlice := make([]any, 0, len(v))
for _, i := range v { for _, i := range v {
if i != nil { if i != nil {
newSlice = append(newSlice, i) newSlice = append(newSlice, i)
@@ -124,7 +124,7 @@ func removeNilElements(v []interface{}) []interface{} {
return newSlice return newSlice
} }
func strval(v interface{}) string { func strval(v any) string {
switch v := v.(type) { switch v := v.(type) {
case string: case string:
return v return v
@@ -149,7 +149,7 @@ func trunc(c int, s string) string {
return s return s
} }
func join(sep string, v interface{}) string { func join(sep string, v any) string {
return strings.Join(strslice(v), sep) return strings.Join(strslice(v), sep)
} }

View File

@@ -56,7 +56,7 @@ func TestQuote(t *testing.T) {
t.Error(err) t.Error(err)
} }
tpl = `{{ .value | quote }}` tpl = `{{ .value | quote }}`
values := map[string]interface{}{"value": nil} values := map[string]any{"value": nil}
if err := runtv(tpl, ``, values); err != nil { if err := runtv(tpl, ``, values); err != nil {
t.Error(err) t.Error(err)
} }
@@ -71,7 +71,7 @@ func TestSquote(t *testing.T) {
t.Error(err) t.Error(err)
} }
tpl = `{{ .value | squote }}` tpl = `{{ .value | squote }}`
values := map[string]interface{}{"value": nil} values := map[string]any{"value": nil}
if err := runtv(tpl, ``, values); err != nil { if err := runtv(tpl, ``, values); err != nil {
t.Error(err) t.Error(err)
} }
@@ -128,7 +128,7 @@ func TestToStrings(t *testing.T) {
tpl := `{{ $s := list 1 2 3 | toStrings }}{{ index $s 1 | kindOf }}` tpl := `{{ $s := list 1 2 3 | toStrings }}{{ index $s 1 | kindOf }}`
assert.NoError(t, runt(tpl, "string")) assert.NoError(t, runt(tpl, "string"))
tpl = `{{ list 1 .value 2 | toStrings }}` tpl = `{{ list 1 .value 2 | toStrings }}`
values := map[string]interface{}{"value": nil} values := map[string]any{"value": nil}
if err := runtv(tpl, `[1 2]`, values); err != nil { if err := runtv(tpl, `[1 2]`, values); err != nil {
t.Error(err) t.Error(err)
} }
@@ -137,10 +137,10 @@ func TestToStrings(t *testing.T) {
func TestJoin(t *testing.T) { func TestJoin(t *testing.T) {
assert.NoError(t, runt(`{{ tuple "a" "b" "c" | join "-" }}`, "a-b-c")) assert.NoError(t, runt(`{{ tuple "a" "b" "c" | join "-" }}`, "a-b-c"))
assert.NoError(t, runt(`{{ tuple 1 2 3 | join "-" }}`, "1-2-3")) assert.NoError(t, runt(`{{ tuple 1 2 3 | join "-" }}`, "1-2-3"))
assert.NoError(t, runtv(`{{ join "-" .V }}`, "a-b-c", map[string]interface{}{"V": []string{"a", "b", "c"}})) assert.NoError(t, runtv(`{{ join "-" .V }}`, "a-b-c", map[string]any{"V": []string{"a", "b", "c"}}))
assert.NoError(t, runtv(`{{ join "-" .V }}`, "abc", map[string]interface{}{"V": "abc"})) assert.NoError(t, runtv(`{{ join "-" .V }}`, "abc", map[string]any{"V": "abc"}))
assert.NoError(t, runtv(`{{ join "-" .V }}`, "1-2-3", map[string]interface{}{"V": []int{1, 2, 3}})) assert.NoError(t, runtv(`{{ join "-" .V }}`, "1-2-3", map[string]any{"V": []int{1, 2, 3}}))
assert.NoError(t, runtv(`{{ join "-" .value }}`, "1-2", map[string]interface{}{"value": []interface{}{"1", nil, "2"}})) assert.NoError(t, runtv(`{{ join "-" .value }}`, "1-2", map[string]any{"value": []any{"1", nil, "2"}}))
} }
func TestSortAlpha(t *testing.T) { func TestSortAlpha(t *testing.T) {
@@ -194,7 +194,7 @@ func TestCat(t *testing.T) {
t.Error(err) t.Error(err)
} }
tpl = `{{ .value | cat "a" "b"}}` tpl = `{{ .value | cat "a" "b"}}`
values := map[string]interface{}{"value": nil} values := map[string]any{"value": nil}
if err := runtv(tpl, "a b", values); err != nil { if err := runtv(tpl, "a b", values); err != nil {
t.Error(err) t.Error(err)
} }

View File

@@ -6,7 +6,7 @@ import (
"reflect" "reflect"
) )
func dictGetOrEmpty(dict map[string]interface{}, key string) string { func dictGetOrEmpty(dict map[string]any, key string) string {
value, ok := dict[key] value, ok := dict[key]
if !ok { if !ok {
return "" return ""
@@ -19,8 +19,8 @@ func dictGetOrEmpty(dict map[string]interface{}, key string) string {
} }
// parses given URL to return dict object // parses given URL to return dict object
func urlParse(v string) map[string]interface{} { func urlParse(v string) map[string]any {
dict := map[string]interface{}{} dict := map[string]any{}
parsedURL, err := url.Parse(v) parsedURL, err := url.Parse(v)
if err != nil { if err != nil {
panic(fmt.Sprintf("unable to parse url: %s", err)) panic(fmt.Sprintf("unable to parse url: %s", err))
@@ -42,7 +42,7 @@ func urlParse(v string) map[string]interface{} {
} }
// join given dict to URL string // join given dict to URL string
func urlJoin(d map[string]interface{}) string { func urlJoin(d map[string]any) string {
resURL := url.URL{ resURL := url.URL{
Scheme: dictGetOrEmpty(d, "scheme"), Scheme: dictGetOrEmpty(d, "scheme"),
Host: dictGetOrEmpty(d, "host"), Host: dictGetOrEmpty(d, "host"),

View File

@@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
var urlTests = map[string]map[string]interface{}{ var urlTests = map[string]map[string]any{
"proto://auth@host:80/path?query#fragment": { "proto://auth@host:80/path?query#fragment": {
"fragment": "fragment", "fragment": "fragment",
"host": "host:80", "host": "host:80",