package renderer import ( "errors" "fmt" "html/template" "net/url" "reflect" "strings" "time" "github.com/jinzhu/inflection" yml "gopkg.in/yaml.v2" ) var ( funcMap = template.FuncMap{ "query": query, "convertDate": convertDate, "modelPath": modelPath, "dict": dict, "yaml": yaml, "create": create, "update": update, "delete": delete, "show": show, "all": all, "execute": execute, "isSlice": isSlice, "toSlice": toSlice, "string": callString, "incr": incr, "mod2": mod2, "toLower": toLower, "anchor": anchor, "html": html, "field": field, } ) func field(name string, value interface{}) interface{} { if value != nil { s := reflect.ValueOf(value).Elem() return s.FieldByName(name).Interface() } else { return nil } } func html(content string) template.HTML { return template.HTML(content) } func anchor(text, url string) template.HTML { return template.HTML(fmt.Sprintf("%s", url, text)) } func toLower(text string) string { return strings.ToLower(text) } func mod2(value int) bool { return value%2 == 0 } func incr(value int) int { return value + 1 } func callString(value interface{}) string { if value != nil { return reflect.ValueOf(value).MethodByName("String").Interface().(func() string)() } else { return "" } } func isSlice(value interface{}) bool { return reflect.TypeOf(value).Kind() == reflect.Slice } func yaml(content string) (interface{}, error) { var result interface{} err := yml.Unmarshal([]byte(content), &result) if err != nil { return nil, err } return result, nil } func dict(values ...interface{}) (map[string]interface{}, error) { if len(values)%2 != 0 { return nil, errors.New("invalid dict call") } dict := make(map[string]interface{}, len(values)/2) for i := 0; i < len(values); i += 2 { key, ok := values[i].(string) if !ok { return nil, errors.New("dict keys must be strings") } dict[key] = values[i+1] } return dict, nil } func toSlice(values ...string) interface{} { var result []string result = append(result, values...) return result } func getType(myvar interface{}) (res string) { t := reflect.TypeOf(myvar) for t.Kind() == reflect.Ptr { t = t.Elem() res += "*" } return res + t.Name() } func query(values ...string) template.URL { var ( urlValues url.Values format bool ) urlValues = make(url.Values) for i := 0; i < len(values); i += 2 { if values[i] == "format" { format = true } urlValues.Add(values[i], values[i+1]) } if !format { urlValues.Set("format", "html") } return template.URL(urlValues.Encode()) } func convertDate(value interface{}) string { t, ok := value.(time.Time) if !ok { return "" } return fmt.Sprintf("%d-%02d-%02d", t.Year(), t.Month(), t.Day()) } func modelPath(model string, action string, id uint) string { var q template.URL action = strings.ToLower(action) plural := inflection.Plural(strings.ToLower(model)) if action != "" { switch action { case "show": q = query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)) return fmt.Sprintf("/%s/%d?%s", plural, id, q) case "update": q = query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_add_update", plural), "update", "true") return fmt.Sprintf("/%s/%d/%s?%s", plural, id, action, q) case "create": q = query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_add_update", plural)) return fmt.Sprintf("/%s/%s/?%s", plural, action, q) case "delete": q = query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)) return fmt.Sprintf("/%s/%d/%s?%s", plural, id, action, q) } } q = query("tpl_layout", "base", "tpl_content", plural) return fmt.Sprintf("/%s?%s", plural, q) } func all(model string) string { plural := inflection.Plural(strings.ToLower(model)) q := query("tpl_layout", "base", "tpl_content", plural) return fmt.Sprintf("/%s?%s", plural, q) } func create(model string) string { action := "create" plural := inflection.Plural(strings.ToLower(model)) q := query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_add_update", plural)) return fmt.Sprintf("/%s/%s/?%s", plural, action, q) } func show(model string, id uint, format ...string) string { action := "show" plural := inflection.Plural(strings.ToLower(model)) args := []string{"tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)} if len(format) > 0 { args = append(args, []string{"format", format[0]}...) } // q := query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)) q := query(args...) return fmt.Sprintf("/%s/%d?%s", plural, id, q) } func execute(model string, id uint) string { action := "execute" plural := inflection.Plural(strings.ToLower(model)) q := query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)) return fmt.Sprintf("/%s/%d/%s?%s", plural, id, action, q) } func update(model string, id uint) string { action := "update" plural := inflection.Plural(strings.ToLower(model)) q := query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_add_update", plural), "update", "true") return fmt.Sprintf("/%s/%d/%s?%s", plural, id, action, q) } func delete(model string, id uint) string { action := "delete" plural := inflection.Plural(strings.ToLower(model)) q := query("tpl_layout", "base", "tpl_content", fmt.Sprintf("%s_%s", plural, action)) return fmt.Sprintf("/%s/%d/%s?%s", plural, id, action, q) }