diff --git a/gin.go b/gin.go index 2d24092f..4d99fdcc 100644 --- a/gin.go +++ b/gin.go @@ -180,7 +180,7 @@ func (engine *Engine) LoadHTMLGlob(pattern string) { if IsDebugging() { debugPrintLoadTemplate(templ) - engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims} + engine.HTMLRender = &render.HTMLDebug{Globs: []string{pattern}, FuncMap: engine.FuncMap, Delims: engine.delims} return } @@ -191,7 +191,7 @@ func (engine *Engine) LoadHTMLGlob(pattern string) { // and associates the result with HTML renderer. func (engine *Engine) LoadHTMLFiles(files ...string) { if IsDebugging() { - engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} + engine.HTMLRender = &render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} return } @@ -199,13 +199,59 @@ func (engine *Engine) LoadHTMLFiles(files ...string) { engine.SetHTMLTemplate(templ) } +// loadHTMLGlobAppend loads HTML files identified by a glob pattern +// and append the result to HTML renderer. +// loadHTMLGlobAppend will merge new files with previous template files. +// LoadHTMLGlob will forget old templates and create a new template object. +func (engine *Engine) loadHTMLGlobAppend(pattern string) { + if engine.HTMLRender == nil { + engine.LoadHTMLGlob(pattern) + return + } + + if IsDebugging() { + left := engine.delims.Left + right := engine.delims.Right + templ := template.Must(template.New("").Delims(left, right).Funcs(engine.FuncMap).ParseGlob(pattern)) + debugPrintLoadTemplate(templ) + } + + engine.HTMLRender.ParseGlob(pattern) +} + +// LoadHTMLGlobAppend loads HTML files identified by glob patterns +// and append each result to HTML renderer. +// LoadHTMLGlobAppend will merge new files with previous template files. +// LoadHTMLGlob will forget old templates and create a new template object. +func (engine *Engine) LoadHTMLGlobAppend(patterns ...string) { + if len(patterns) <= 0 { + panic("LoadHTMLGlobAppend must have at least 1 arguments") + } + for _, pattern := range patterns { + engine.loadHTMLGlobAppend(pattern) + } +} + +// LoadHTMLFiles loads a slice of HTML files +// and append the result to HTML renderer. +// LoadHTMLFilesAppend will merge new files with previous template files. +// LoadHTMLFiles will forget old templates and create a new template object. +func (engine *Engine) LoadHTMLFilesAppend(files ...string) { + if engine.HTMLRender == nil { + engine.LoadHTMLFiles(files...) + return + } + + engine.HTMLRender.ParseFiles(files...) +} + // SetHTMLTemplate associate a template with HTML renderer. func (engine *Engine) SetHTMLTemplate(templ *template.Template) { if len(engine.trees) > 0 { debugPrintWARNINGSetHTMLTemplate() } - engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} + engine.HTMLRender = &render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} } // SetFuncMap sets the FuncMap used for template.FuncMap. diff --git a/gin_test.go b/gin_test.go index 11bdd79c..0010c145 100644 --- a/gin_test.go +++ b/gin_test.go @@ -118,6 +118,48 @@ func TestLoadHTMLGlobReleaseMode(t *testing.T) { assert.Equal(t, "

Hello world

", string(resp)) } +func TestLoadHTMLGlobAppendDebugMode(t *testing.T) { + ts := setupHTMLFiles( + t, + DebugMode, + false, + func(router *Engine) { + router.LoadHTMLGlobAppend("./testdata/template/hello*") + router.LoadHTMLGlobAppend("./testdata/template/raw*") + }, + ) + defer ts.Close() + + res, err := http.Get(fmt.Sprintf("%s/test", ts.URL)) + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp)) +} + +func TestLoadHTMLGlobAppendReleaseMode(t *testing.T) { + ts := setupHTMLFiles( + t, + ReleaseMode, + false, + func(router *Engine) { + router.LoadHTMLGlobAppend("./testdata/template/hello*") + router.LoadHTMLGlobAppend("./testdata/template/raw*") + }, + ) + defer ts.Close() + + res, err := http.Get(fmt.Sprintf("%s/test", ts.URL)) + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp)) +} + func TestLoadHTMLGlobUsingTLS(t *testing.T) { ts := setupHTMLFiles( t, @@ -236,6 +278,48 @@ func TestLoadHTMLFilesReleaseMode(t *testing.T) { assert.Equal(t, "

Hello world

", string(resp)) } +func TestLoadHTMLFilesAppendDebugMode(t *testing.T) { + ts := setupHTMLFiles( + t, + DebugMode, + false, + func(router *Engine) { + router.LoadHTMLFilesAppend("./testdata/template/raw.tmpl") + router.LoadHTMLFilesAppend("./testdata/template/hello.tmpl") + }, + ) + defer ts.Close() + + res, err := http.Get(fmt.Sprintf("%s/test", ts.URL)) + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp)) +} + +func TestLoadHTMLFilesAppendReleaseMode(t *testing.T) { + ts := setupHTMLFiles( + t, + ReleaseMode, + false, + func(router *Engine) { + router.LoadHTMLFilesAppend("./testdata/template/raw.tmpl") + router.LoadHTMLFilesAppend("./testdata/template/hello.tmpl") + }, + ) + defer ts.Close() + + res, err := http.Get(fmt.Sprintf("%s/test", ts.URL)) + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "

Hello world

", string(resp)) +} + func TestLoadHTMLFilesUsingTLS(t *testing.T) { ts := setupHTMLFiles( t, diff --git a/render/html.go b/render/html.go index 6696ece9..db1a8c52 100644 --- a/render/html.go +++ b/render/html.go @@ -21,6 +21,10 @@ type Delims struct { type HTMLRender interface { // Instance returns an HTML instance. Instance(string, interface{}) Render + // Add new template files to this instance with glob + ParseGlob(pattern string) + // Add new template files to this instance + ParseFiles(files ...string) } // HTMLProduction contains template reference and its delims. @@ -32,7 +36,7 @@ type HTMLProduction struct { // HTMLDebug contains template delims and pattern and function with file list. type HTMLDebug struct { Files []string - Glob string + Globs []string Delims Delims FuncMap template.FuncMap } @@ -55,6 +59,16 @@ func (r HTMLProduction) Instance(name string, data interface{}) Render { } } +// Add new template files to this instance (HTMLProduction) with glob +func (r *HTMLProduction) ParseGlob(pattern string) { + template.Must(r.Template.ParseGlob(pattern)) +} + +// Add new template files to this instance (HTMLProduction) with glob +func (r *HTMLProduction) ParseFiles(files ...string) { + template.Must(r.Template.ParseFiles(files...)) +} + // Instance (HTMLDebug) returns an HTML instance which it realizes Render interface. func (r HTMLDebug) Instance(name string, data interface{}) Render { return HTML{ @@ -63,17 +77,32 @@ func (r HTMLDebug) Instance(name string, data interface{}) Render { Data: data, } } + +// Add new template files to this instance (HTMLProduction) with glob +func (r *HTMLDebug) ParseGlob(pattern string) { + r.Globs = append(r.Globs, pattern) +} + +// Add new template files to this instance (HTMLDebug) with glob +func (r *HTMLDebug) ParseFiles(files ...string) { + r.Files = append(r.Files, files...) +} + func (r HTMLDebug) loadTemplate() *template.Template { if r.FuncMap == nil { r.FuncMap = template.FuncMap{} } + if len(r.Files) == 0 && len(r.Globs) == 0 { + panic("the HTML debug render was created without files or glob pattern") + } + t := template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap) if len(r.Files) > 0 { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...)) + template.Must(t.ParseFiles(r.Files...)) } - if r.Glob != "" { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob)) + for _, glob := range r.Globs { + template.Must(t.ParseGlob(glob)) } - panic("the HTML debug render was created without files or glob pattern") + return t } // Render (HTML) executes template and writes its result with custom ContentType for response. diff --git a/render/render.go b/render/render.go index abfc79fc..713556a8 100644 --- a/render/render.go +++ b/render/render.go @@ -24,8 +24,8 @@ var ( _ Render = Redirect{} _ Render = Data{} _ Render = HTML{} - _ HTMLRender = HTMLDebug{} - _ HTMLRender = HTMLProduction{} + _ HTMLRender = &HTMLDebug{} + _ HTMLRender = &HTMLProduction{} _ Render = YAML{} _ Render = MsgPack{} _ Render = Reader{} diff --git a/render/render_test.go b/render/render_test.go index 76e29eeb..1ee20390 100644 --- a/render/render_test.go +++ b/render/render_test.go @@ -422,7 +422,7 @@ func TestRenderHTMLTemplateEmptyName(t *testing.T) { func TestRenderHTMLDebugFiles(t *testing.T) { w := httptest.NewRecorder() htmlRender := HTMLDebug{Files: []string{"../testdata/template/hello.tmpl"}, - Glob: "", + Globs: []string{}, Delims: Delims{Left: "{[{", Right: "}]}"}, FuncMap: nil, } @@ -440,7 +440,7 @@ func TestRenderHTMLDebugFiles(t *testing.T) { func TestRenderHTMLDebugGlob(t *testing.T) { w := httptest.NewRecorder() htmlRender := HTMLDebug{Files: nil, - Glob: "../testdata/template/hello*", + Globs: []string{"../testdata/template/hello*"}, Delims: Delims{Left: "{[{", Right: "}]}"}, FuncMap: nil, } @@ -457,7 +457,7 @@ func TestRenderHTMLDebugGlob(t *testing.T) { func TestRenderHTMLDebugPanics(t *testing.T) { htmlRender := HTMLDebug{Files: nil, - Glob: "", + Globs: []string{}, Delims: Delims{"{{", "}}"}, FuncMap: nil, }