113 lines
2.5 KiB
Go
113 lines
2.5 KiB
Go
package funcmap
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
)
|
|
|
|
var ErrEarlyTermination = fmt.Errorf("template was early terminated by calling {{ stop }}")
|
|
|
|
func Stop() (string, error) {
|
|
return "", ErrEarlyTermination
|
|
}
|
|
|
|
func Lookup(name string, args ...reflect.Value) (interface{}, error) {
|
|
if len(args) == 0 {
|
|
return nil, fmt.Errorf("lookup expects at least 1 argument, got 0")
|
|
}
|
|
zero := reflect.ValueOf("")
|
|
|
|
target := args[0]
|
|
if len(args) > 1 {
|
|
zero = args[1]
|
|
}
|
|
switch target.Kind() {
|
|
case reflect.Map:
|
|
if target.IsNil() || target.Type().Elem().Kind() != zero.Kind() {
|
|
target = reflect.MakeMap(reflect.MapOf(target.Type().Key(), zero.Type()))
|
|
target.SetMapIndex(reflect.ValueOf(name), zero)
|
|
}
|
|
|
|
return target.MapIndex(reflect.ValueOf(name)).Interface(), nil
|
|
case reflect.Pointer:
|
|
field := target.MethodByName(name)
|
|
if field.IsValid() {
|
|
return field.Interface(), nil
|
|
}
|
|
case reflect.Struct:
|
|
field := target.FieldByName(name)
|
|
if field.IsValid() {
|
|
return field.Interface(), nil
|
|
}
|
|
case reflect.Interface:
|
|
method := target.MethodByName(name)
|
|
if method.IsValid() {
|
|
return method.Interface(), nil
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("cannot lookup %s from type %v", name, target.Type())
|
|
}
|
|
return nil, fmt.Errorf("no such method or field %s", name)
|
|
}
|
|
|
|
func Invoke(name string, target reflect.Value, args ...reflect.Value) (any, error) {
|
|
if name != "" {
|
|
t, err := Lookup(name, target)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
target = reflect.ValueOf(t)
|
|
}
|
|
ret := target.Call(args)
|
|
if len(ret) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
if err, ok := ret[len(ret)-1].Interface().(error); ok && err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch len(ret) {
|
|
case 0:
|
|
return nil, nil
|
|
case 1:
|
|
return ret[0].Interface(), nil
|
|
default:
|
|
var rets []any
|
|
for _, r := range ret {
|
|
rets = append(rets, r.Interface())
|
|
}
|
|
return rets, nil
|
|
}
|
|
|
|
}
|
|
|
|
func Void(args ...reflect.Value) string {
|
|
return ""
|
|
}
|
|
|
|
func GetFuncMap() map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"lookup": Lookup,
|
|
"invoke": Invoke,
|
|
"void": Void,
|
|
"get": FuncGet,
|
|
"set": FuncSet,
|
|
"math": Math,
|
|
"xml": EscapeXML,
|
|
"stop": Stop,
|
|
"trima_img": TrimaImg,
|
|
"parse_json": ParseJSON,
|
|
"json": MarshalJSON,
|
|
"get_auth": AuthGet,
|
|
"sprintf": func(format string, input ...interface{}) interface{} {
|
|
return fmt.Sprintf(format, input...)
|
|
},
|
|
"http": HttpRequest,
|
|
"version": Version,
|
|
"find_word": FindWord,
|
|
"contain": Contain,
|
|
"query": EscapeQuery,
|
|
"theme_color": ThemeColor,
|
|
}
|
|
}
|