diff --git a/core/template.go b/core/template.go index 3732fbe..986ed39 100644 --- a/core/template.go +++ b/core/template.go @@ -11,23 +11,29 @@ import ( type Renderer struct { multitemplate.Renderer TemplatesBox *packr.Box - FuncMap template.FuncMap + FuncMap template.FuncMap + alreadyAdded map[string]*template.Template } // NewRenderer is a Renderer constructor func NewRenderer(funcMap template.FuncMap) Renderer { return Renderer{ - Renderer: multitemplate.NewRenderer(), - FuncMap: funcMap, + Renderer: multitemplate.NewRenderer(), + FuncMap: funcMap, + alreadyAdded: map[string]*template.Template{}, } } // Push is an AddFromFilesFuncs wrapper func (r *Renderer) Push(name string, files ...string) *template.Template { + if tpl := r.getTemplate(name); tpl != nil { + return tpl + } + if r.TemplatesBox == nil { - return r.AddFromFilesFuncs(name, r.FuncMap, files...) + return r.storeTemplate(name, r.AddFromFilesFuncs(name, r.FuncMap, files...)) } else { - return r.addFromBox(name, r.FuncMap, files...) + return r.storeTemplate(name, r.addFromBox(name, r.FuncMap, files...)) } } @@ -42,4 +48,32 @@ func (r *Renderer) addFromBox(name string, funcMap template.FuncMap, files ...st } return r.AddFromStringsFuncs(name, funcMap, filesData...) -} \ No newline at end of file +} + +// storeTemplate stores built template if multitemplate.DynamicRender is used. +// Dynamic render doesn't store templates - it stores builders, that's why we can't just extract them. +// It possibly can cause data inconsistency in developer enviroments where return value from Renderer.Push is used. +func (r *Renderer) storeTemplate(name string, tpl *template.Template) *template.Template { + if _, ok := r.Renderer.(multitemplate.DynamicRender); ok { + r.alreadyAdded[name] = tpl + } + + return tpl +} + +// getTemplate returns template from render or from storage +func (r *Renderer) getTemplate(name string) *template.Template { + if renderer, ok := r.Renderer.(multitemplate.Render); ok { + if i, ok := renderer[name]; ok { + return i + } + } + + if _, ok := r.Renderer.(multitemplate.DynamicRender); ok { + if i, ok := r.alreadyAdded[name]; ok { + return i + } + } + + return nil +} diff --git a/core/template_test.go b/core/template_test.go index c32dec7..c89fd7c 100644 --- a/core/template_test.go +++ b/core/template_test.go @@ -24,6 +24,11 @@ type TemplateTest struct { } func (t *TemplateTest) SetupSuite() { + t.initTestData() + t.renderer = t.initRenderer() +} + +func (t *TemplateTest) initTestData() { if _, err := os.Stat(testTemplatesDir); err != nil && os.IsNotExist(err) { err := os.Mkdir(testTemplatesDir, os.ModePerm) require.Nil(t.T(), err) @@ -34,8 +39,10 @@ func (t *TemplateTest) SetupSuite() { require.Nil(t.T(), err1) require.Nil(t.T(), err2) } +} - t.renderer = NewRenderer(template.FuncMap{ +func (t *TemplateTest) initRenderer() Renderer { + return NewRenderer(template.FuncMap{ "trans": func(data string) string { if data == "test" { return "ok" @@ -51,6 +58,25 @@ func (t *TemplateTest) Test_Push() { assert.Equal(t.T(), 3, len(tpl.Templates())) } +func (t *TemplateTest) Test_PushAlreadyExists() { + defer func() { + assert.Nil(t.T(), recover()) + }() + + tpl := t.renderer.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2)) + assert.Equal(t.T(), 3, len(tpl.Templates())) +} + +func (t *TemplateTest) Test_PushNewInstance() { + defer func() { + assert.Nil(t.T(), recover()) + }() + + newInstance := t.initRenderer() + tpl := newInstance.Push("index", fmt.Sprintf(testTemplatesFile, 1), fmt.Sprintf(testTemplatesFile, 2)) + assert.Equal(t.T(), 3, len(tpl.Templates())) +} + func TestTemplate_Suite(t *testing.T) { suite.Run(t, new(TemplateTest)) }