yoake/internal/servetpl/funcmap/funcmap.go

114 lines
2.5 KiB
Go
Raw Normal View History

2022-11-07 04:45:02 -06:00
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{}{
2022-11-20 12:05:14 -06:00
"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,
2022-11-11 16:15:22 -06:00
"sprintf": func(format string, input ...interface{}) interface{} {
return fmt.Sprintf(format, input...)
},
2022-11-20 12:05:14 -06:00
"http": HttpRequest,
"version": Version,
"find_word": FindWord,
"contain": Contain,
"query": EscapeQuery,
"theme_color": ThemeColor,
2022-11-07 04:45:02 -06:00
}
}