From e38c36ee0d6d2131b263b571a8a7e2e8e2a708dc Mon Sep 17 00:00:00 2001 From: Thomas Boerger Date: Fri, 30 Jun 2017 21:22:40 +0200 Subject: [PATCH 1/3] Made funMaps for the templates configurable and hot-reloadable --- gin.go | 18 ++++++++++++------ render/html.go | 14 +++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/gin.go b/gin.go index 992d2f1..c4118a4 100644 --- a/gin.go +++ b/gin.go @@ -47,6 +47,7 @@ type ( RouterGroup delims render.Delims HTMLRender render.HTMLRender + FuncMap template.FuncMap allNoRoute HandlersChain allNoMethod HandlersChain noRoute HandlersChain @@ -112,6 +113,7 @@ func New() *Engine { basePath: "/", root: true, }, + FuncMap: template.FuncMap{}, RedirectTrailingSlash: true, RedirectFixedPath: false, HandleMethodNotAllowed: false, @@ -147,19 +149,19 @@ func (engine *Engine) Delims(left, right string) *Engine { func (engine *Engine) LoadHTMLGlob(pattern string) { if IsDebugging() { - debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern))) - engine.HTMLRender = render.HTMLDebug{Glob: pattern, Delims: engine.delims} + debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern))) + engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims} } else { - templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseGlob(pattern)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern)) engine.SetHTMLTemplate(templ) } } func (engine *Engine) LoadHTMLFiles(files ...string) { if IsDebugging() { - engine.HTMLRender = render.HTMLDebug{Files: files, Delims: engine.delims} + engine.HTMLRender = render.HTMLDebug{Files: files, FuncMap: engine.FuncMap, Delims: engine.delims} } else { - templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).ParseFiles(files...)) + templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseFiles(files...)) engine.SetHTMLTemplate(templ) } } @@ -169,7 +171,11 @@ func (engine *Engine) SetHTMLTemplate(templ *template.Template) { debugPrintWARNINGSetHTMLTemplate() } - engine.HTMLRender = render.HTMLProduction{Template: templ} + engine.HTMLRender = render.HTMLProduction{Template: templ.Funcs(engine.FuncMap)} +} + +func (engine *Engine) SetFuncMap(funcMap template.FuncMap) { + engine.FuncMap = funcMap } // NoRoute adds handlers for NoRoute. It return a 404 code by default. diff --git a/render/html.go b/render/html.go index 3ea5e08..cf91219 100644 --- a/render/html.go +++ b/render/html.go @@ -25,9 +25,10 @@ type ( } HTMLDebug struct { - Files []string - Glob string - Delims Delims + Files []string + Glob string + Delims Delims + FuncMap template.FuncMap } HTML struct { @@ -55,11 +56,14 @@ func (r HTMLDebug) Instance(name string, data interface{}) Render { } } func (r HTMLDebug) loadTemplate() *template.Template { + if r.FuncMap == nil { + r.FuncMap = template.FuncMap{} + } if len(r.Files) > 0 { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseFiles(r.Files...)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseFiles(r.Files...)) } if len(r.Glob) > 0 { - return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).ParseGlob(r.Glob)) + return template.Must(template.New("").Delims(r.Delims.Left, r.Delims.Right).Funcs(r.FuncMap).ParseGlob(r.Glob)) } panic("the HTML debug render was created without files or glob pattern") } From a40699e07f71b33c3c4a064af3468c09d333688c Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sun, 2 Jul 2017 12:38:05 +0800 Subject: [PATCH 2/3] add FuncMap testing Signed-off-by: Bo-Yi Wu --- fixtures/basic/raw.tmpl | 1 + gin_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 fixtures/basic/raw.tmpl diff --git a/fixtures/basic/raw.tmpl b/fixtures/basic/raw.tmpl new file mode 100644 index 0000000..8bc7570 --- /dev/null +++ b/fixtures/basic/raw.tmpl @@ -0,0 +1 @@ +Date: {[{.now | formatAsDate}]} diff --git a/gin_test.go b/gin_test.go index 3ab4697..3cd134c 100644 --- a/gin_test.go +++ b/gin_test.go @@ -6,6 +6,7 @@ package gin import ( "fmt" + "html/template" "io/ioutil" "net/http" "reflect" @@ -15,6 +16,11 @@ import ( "github.com/stretchr/testify/assert" ) +func formatAsDate(t time.Time) string { + year, month, day := t.Date() + return fmt.Sprintf("%d/%02d/%02d", year, month, day) +} + func setupHTMLFiles(t *testing.T) func() { go func() { router := New() @@ -32,12 +38,21 @@ func setupHTMLFiles(t *testing.T) func() { func setupHTMLGlob(t *testing.T) func() { go func() { + SetMode(DebugMode) router := New() router.Delims("{[{", "}]}") + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) router.LoadHTMLGlob("./fixtures/basic/*") router.GET("/test", func(c *Context) { c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) }) + router.GET("/raw", func(c *Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) router.Run(":8888") }() t.Log("waiting 1 second for server startup") @@ -59,6 +74,20 @@ func TestLoadHTMLGlob(t *testing.T) { td() } +func TestLoadHTMLFromFuncMap(t *testing.T) { + time.Now() + td := setupHTMLGlob(t) + res, err := http.Get("http://127.0.0.1:8888/raw") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "Date: 2017/07/01\n", string(resp[:])) + + td() +} + // func (engine *Engine) LoadHTMLFiles(files ...string) { // func (engine *Engine) RunTLS(addr string, cert string, key string) error { From 6d071c1d360141168de629c4b686175df2efa61f Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Sun, 2 Jul 2017 13:06:43 +0800 Subject: [PATCH 3/3] Add load html file and func map. Signed-off-by: Bo-Yi Wu --- gin_test.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/gin_test.go b/gin_test.go index 3cd134c..bdf5a9a 100644 --- a/gin_test.go +++ b/gin_test.go @@ -23,12 +23,21 @@ func formatAsDate(t time.Time) string { func setupHTMLFiles(t *testing.T) func() { go func() { + SetMode(TestMode) router := New() router.Delims("{[{", "}]}") - router.LoadHTMLFiles("./fixtures/basic/hello.tmpl") + router.SetFuncMap(template.FuncMap{ + "formatAsDate": formatAsDate, + }) + router.LoadHTMLFiles("./fixtures/basic/hello.tmpl", "./fixtures/basic/raw.tmpl") router.GET("/test", func(c *Context) { c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"}) }) + router.GET("/raw", func(c *Context) { + c.HTML(http.StatusOK, "raw.tmpl", map[string]interface{}{ + "now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC), + }) + }) router.Run(":8888") }() t.Log("waiting 1 second for server startup") @@ -74,7 +83,7 @@ func TestLoadHTMLGlob(t *testing.T) { td() } -func TestLoadHTMLFromFuncMap(t *testing.T) { +func TestLoadHTMLGlobFromFuncMap(t *testing.T) { time.Now() td := setupHTMLGlob(t) res, err := http.Get("http://127.0.0.1:8888/raw") @@ -129,6 +138,20 @@ func TestLoadHTMLFiles(t *testing.T) { td() } +func TestLoadHTMLFilesFuncMap(t *testing.T) { + time.Now() + td := setupHTMLFiles(t) + res, err := http.Get("http://127.0.0.1:8888/raw") + if err != nil { + fmt.Println(err) + } + + resp, _ := ioutil.ReadAll(res.Body) + assert.Equal(t, "Date: 2017/07/01\n", string(resp[:])) + + td() +} + func TestLoadHTMLReleaseMode(t *testing.T) { }