Merge pull request #962 from gin-gonic/feat/func-maps
Made funMaps for the templates configurable and hot-reloadable
This commit is contained in:
		
							
								
								
									
										1
									
								
								fixtures/basic/raw.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								fixtures/basic/raw.tmpl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| Date: {[{.now | formatAsDate}]} | ||||
							
								
								
									
										18
									
								
								gin.go
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								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. | ||||
|  | ||||
							
								
								
									
										54
									
								
								gin_test.go
									
									
									
									
									
								
							
							
						
						
									
										54
									
								
								gin_test.go
									
									
									
									
									
								
							| @ -6,6 +6,7 @@ package gin | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"html/template" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| @ -15,14 +16,28 @@ 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() { | ||||
| 		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") | ||||
| @ -32,12 +47,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 +83,20 @@ func TestLoadHTMLGlob(t *testing.T) { | ||||
| 	td() | ||||
| } | ||||
|  | ||||
| func TestLoadHTMLGlobFromFuncMap(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 { | ||||
|  | ||||
| @ -100,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) { | ||||
|  | ||||
| } | ||||
|  | ||||
| @ -28,6 +28,7 @@ type ( | ||||
| 		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") | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user