@@ 457,6 457,19 @@ func (s *Server) AddStaticFunc(fs ...validate.StaticFunc) {
}
}
+// TemplateAllowOverride adds template map keys values that can be overridden by
+// handlers. For instance, if a static func sets a template Map value of "seoData",
+// your handlers can override that value if set to be allowed.
+func (s *Server) TemplateAllowOverride(keys ...string) {
+ s.e.Renderer.(*validate.Template).AddOverride(keys...)
+}
+
+// TemplateProtectVariables will set whether or not to protect variable name collisions
+// from handler Map data.
+func (s *Server) TemplateProtectVariables(protect bool) {
+ s.e.Renderer.(*validate.Template).ProtectVariables(protect)
+}
+
// addDefaultTemplateData will set the default functions and static vars in
// the template renderer
func (s *Server) addDefaultTemplateData() {
@@ 8,6 8,7 @@ import (
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
+ "golang.org/x/exp/slices"
"netlandish.com/x/gobwebs"
)
@@ 26,7 27,10 @@ type (
staticMap Map
staticFuncs []func(c echo.Context) Map
- cloned bool
+
+ cloned bool
+ protect bool
+ allowed []string
}
)
@@ 36,6 40,8 @@ func NewTemplate() *Template {
templateBase: template.New(""),
templates: template.New(""),
staticMap: make(Map),
+ protect: true,
+ allowed: []string{},
}
}
@@ 93,8 99,11 @@ func (t *Template) tmplPayload(c echo.Context, data Map) (Map, error) {
}
if data != nil {
for k, v := range data {
- if _, ok := input[k]; ok {
- return nil, fmt.Errorf("Template context conflict (handler data). Reserved key: %v", k)
+ if t.protect && !slices.Contains(t.allowed, k) {
+ if _, ok := input[k]; ok {
+ return nil, fmt.Errorf(
+ "Template context conflict (handler data). Reserved key: %v", k)
+ }
}
input[k] = v
}
@@ 127,6 136,18 @@ func (t *Template) RenderTemplate(
return t.render(tmpl, w, name, data, c)
}
+// AddOverride will add an override value to the allowed slice
+func (t *Template) AddOverride(keys ...string) {
+ t.allowed = append(t.allowed, keys...)
+}
+
+// ProtectVariables will set the `protect` value. If false, when adding
+// to the template values Map we will not check for name collisions from
+// handler provided maps.
+func (t *Template) ProtectVariables(protect bool) {
+ t.protect = protect
+}
+
// LoadTemplates parses templates given the glob pattern path
func (t *Template) LoadTemplates(path string, tfs fs.FS) error {
var (