diff --git a/dynamic.go b/dynamic.go index 766ec89..0642d50 100644 --- a/dynamic.go +++ b/dynamic.go @@ -3,6 +3,7 @@ package multitemplate import ( "fmt" "html/template" + "io/fs" "path/filepath" "github.com/gin-gonic/gin" @@ -39,6 +40,7 @@ const ( templateType builderType = iota filesTemplateType globTemplateType + fsTemplateType stringTemplateType stringFuncTemplateType filesFuncTemplateType @@ -51,6 +53,7 @@ type templateBuilder struct { templateName string files []string glob string + fsys fs.FS templateString string funcMap template.FuncMap templateStrings []string @@ -64,6 +67,8 @@ func (tb templateBuilder) buildTemplate() *template.Template { return template.Must(template.ParseFiles(tb.files...)) case globTemplateType: return template.Must(template.ParseGlob(tb.glob)) + case fsTemplateType: + return template.Must(template.ParseFS(tb.fsys, tb.files...)) case stringTemplateType: return template.Must(template.New(tb.templateName).Parse(tb.templateString)) case stringFuncTemplateType: @@ -108,6 +113,13 @@ func (r DynamicRender) AddFromGlob(name, glob string) *template.Template { return builder.buildTemplate() } +func (r DynamicRender) AddFromFS(name string, fsys fs.FS, files ...string) *template.Template { + builder := &templateBuilder{templateName: name, fsys: fsys, files: files} + builder.buildType = fsTemplateType + r[name] = builder + return builder.buildTemplate() +} + // AddFromString supply add template from strings func (r DynamicRender) AddFromString(name, templateString string) *template.Template { builder := &templateBuilder{templateName: name, templateString: templateString} diff --git a/dynamic_test.go b/dynamic_test.go index a66077f..0a2cefa 100644 --- a/dynamic_test.go +++ b/dynamic_test.go @@ -2,6 +2,7 @@ package multitemplate import ( "html/template" + "os" "testing" "github.com/gin-gonic/gin" @@ -22,6 +23,13 @@ func createFromGlobDynamic() Renderer { return r } +func createFromFSDynamic() Render { + r := New() + r.AddFromFS("index", os.DirFS("."), "tests/base.html", "tests/article.html") + + return r +} + func createFromStringDynamic() Renderer { r := NewRenderer() r.AddFromString("index", "Welcome to {{ .name }} template") @@ -90,6 +98,20 @@ func TestAddFromGlobDynamic(t *testing.T) { assert.Equal(t, "

Test Multiple Template

\nHi, this is login template\n", w.Body.String()) } +func TestAddFromFSDynamic(t *testing.T) { + router := gin.New() + router.HTMLRender = createFromFSDynamic() + router.GET("/", func(c *gin.Context) { + c.HTML(200, "index", gin.H{ + "title": "Test Multiple Template", + }) + }) + + w := performRequest(router, "GET", "/") + assert.Equal(t, 200, w.Code) + assert.Equal(t, "

Test Multiple Template

\nHi, this is article template\n", w.Body.String()) +} + func TestAddFromStringDynamic(t *testing.T) { router := gin.New() router.HTMLRender = createFromStringDynamic() diff --git a/multitemplate.go b/multitemplate.go index 0940aa8..09c2978 100644 --- a/multitemplate.go +++ b/multitemplate.go @@ -3,6 +3,7 @@ package multitemplate import ( "fmt" "html/template" + "io/fs" "path/filepath" "github.com/gin-gonic/gin/render" @@ -49,6 +50,13 @@ func (r Render) AddFromGlob(name, glob string) *template.Template { return tmpl } +// AddFromFS supply add template from fs.FS (e.g. embed.FS) +func (r Render) AddFromFS(name string, fsys fs.FS, files ...string) *template.Template { + tmpl := template.Must(template.ParseFS(fsys, files...)) + r.Add(name, tmpl) + return tmpl +} + // AddFromString supply add template from strings func (r Render) AddFromString(name, templateString string) *template.Template { tmpl := template.Must(template.New(name).Parse(templateString)) diff --git a/multitemplate_test.go b/multitemplate_test.go index debf16f..6b631de 100644 --- a/multitemplate_test.go +++ b/multitemplate_test.go @@ -5,6 +5,7 @@ import ( "html/template" "net/http" "net/http/httptest" + "os" "testing" "github.com/gin-gonic/gin" @@ -32,6 +33,13 @@ func createFromGlob() Render { return r } +func createFromFS() Render { + r := New() + r.AddFromFS("index", os.DirFS("."), "tests/base.html", "tests/article.html") + + return r +} + func createFromString() Render { r := New() r.AddFromString("index", "Welcome to {{ .name }} template") @@ -93,6 +101,20 @@ func TestAddFromGlob(t *testing.T) { assert.Equal(t, "

Test Multiple Template

\nHi, this is login template\n", w.Body.String()) } +func TestAddFromFS(t *testing.T) { + router := gin.New() + router.HTMLRender = createFromFS() + router.GET("/", func(c *gin.Context) { + c.HTML(200, "index", gin.H{ + "title": "Test Multiple Template", + }) + }) + + w := performRequest(router, "GET", "/") + assert.Equal(t, 200, w.Code) + assert.Equal(t, "

Test Multiple Template

\nHi, this is article template\n", w.Body.String()) +} + func TestAddFromString(t *testing.T) { router := gin.New() router.HTMLRender = createFromString() diff --git a/renderer.go b/renderer.go index 8420133..2e48737 100644 --- a/renderer.go +++ b/renderer.go @@ -2,6 +2,7 @@ package multitemplate import ( "html/template" + "io/fs" "github.com/gin-gonic/gin/render" ) @@ -15,6 +16,7 @@ type Renderer interface { Add(name string, tmpl *template.Template) AddFromFiles(name string, files ...string) *template.Template AddFromGlob(name, glob string) *template.Template + AddFromFS(name string, fsys fs.FS, files ...string) *template.Template AddFromString(name, templateString string) *template.Template AddFromStringsFuncs(name string, funcMap template.FuncMap, templateStrings ...string) *template.Template AddFromFilesFuncs(name string, funcMap template.FuncMap, files ...string) *template.Template