From 69e515326f139fda7746c9e3444100a643410ede Mon Sep 17 00:00:00 2001 From: Elara Musayelyan Date: Mon, 30 Oct 2023 21:06:17 -0700 Subject: [PATCH] Make macros per-template-execution --- macro_tag.go | 12 ++++++------ namespace.go | 18 +++++++----------- salix.go | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/macro_tag.go b/macro_tag.go index fbcafd7..ad53027 100644 --- a/macro_tag.go +++ b/macro_tag.go @@ -30,17 +30,17 @@ func (mt macroTag) Run(tc *TagContext, block, args []ast.Node) error { } if len(block) == 0 { - tc.t.ns.mu.Lock() - macro, ok := tc.t.ns.macros[name] + tc.t.macroMtx.Lock() + macro, ok := tc.t.macros[name] if !ok { return ErrNoSuchMacro } - tc.t.ns.mu.Unlock() + tc.t.macroMtx.Unlock() return tc.Execute(macro, nil) } else { - tc.t.ns.mu.Lock() - tc.t.ns.macros[name] = block - tc.t.ns.mu.Unlock() + tc.t.macroMtx.Lock() + tc.t.macros[name] = block + tc.t.macroMtx.Unlock() } return nil diff --git a/namespace.go b/namespace.go index b530980..68e458b 100644 --- a/namespace.go +++ b/namespace.go @@ -21,26 +21,22 @@ package salix import ( "reflect" "sync" - - "go.elara.ws/salix/ast" ) // Namespace represents a collection of templates that can include each other type Namespace struct { - mu sync.Mutex - tmpls map[string]*Template - vars map[string]reflect.Value - tags map[string]Tag - macros map[string][]ast.Node + mu sync.Mutex + tmpls map[string]*Template + vars map[string]reflect.Value + tags map[string]Tag } // New returns a new template namespace func New() *Namespace { return &Namespace{ - tmpls: map[string]*Template{}, - vars: map[string]reflect.Value{}, - tags: map[string]Tag{}, - macros: map[string][]ast.Node{}, + tmpls: map[string]*Template{}, + vars: map[string]reflect.Value{}, + tags: map[string]Tag{}, } } diff --git a/salix.go b/salix.go index 70c023d..8460890 100644 --- a/salix.go +++ b/salix.go @@ -24,6 +24,7 @@ import ( "html" "io" "reflect" + "sync" "go.elara.ws/salix/ast" ) @@ -61,6 +62,9 @@ type Template struct { tags map[string]Tag vars map[string]reflect.Value + + macroMtx sync.Mutex + macros map[string][]ast.Node } // WithVarMap returns a copy of the template with its variable map set to m. @@ -124,7 +128,21 @@ func (t *Template) WithEscapeHTML(b bool) *Template { // Execute executes a parsed template and writes // the result to w. func (t *Template) Execute(w io.Writer) error { - return t.execute(w, t.ast, nil) + // Create a new template to give each execution + // its own macros + tmpl := &Template{ + ns: t.ns, + name: t.name, + ast: t.ast, + + escapeHTML: t.escapeHTML, + + tags: t.tags, + vars: t.vars, + macros: map[string][]ast.Node{}, + } + + return tmpl.execute(w, t.ast, nil) } func (t *Template) execute(w io.Writer, nodes []ast.Node, local map[string]any) error {