Skip to content

Commit

Permalink
Render templates from embed.FS (#89)
Browse files Browse the repository at this point in the history
* Upgrade to go 1.16

* Add EmbedFileSystem to render templates from `embed.FS`

* Require go 1.16 in fs_embed.go and fs_embed_test.go
  • Loading branch information
dominik-lekse authored May 14, 2021
1 parent 8d2b52a commit 987556a
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 2 deletions.
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,27 @@ admin/edit
home
~~~

You can also load templates from memory by providing the Asset and AssetNames options,
Templates can be loaded from an `embed.FS`.

~~~ go
// ...

//go:embed templates/*.html templates/*.tmpl
var embeddedTemplates embed.FS

// ...

r := render.New(render.Options{
Directory: "templates",
FileSystem: &EmbedFileSystem{
FS: embeddedTemplates,
},
Extensions: []string{".html", ".tmpl"},
})
// ...
~~~

You can also load templates from memory by providing the `Asset` and `AssetNames` options,
e.g. when generating an asset file using [go-bindata](https://github.com/jteeuwen/go-bindata).

### Layouts
Expand Down
31 changes: 31 additions & 0 deletions fs_embed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// +build go1.16

package render

import (
"embed"
"io/fs"
"path/filepath"
)

// EmbedFileSystem implements FileSystem on top of an embed.FS
type EmbedFileSystem struct {
embed.FS
}

var _ FileSystem = &EmbedFileSystem{}

func (e *EmbedFileSystem) Walk(root string, walkFn filepath.WalkFunc) error {
return fs.WalkDir(e.FS, root, func(path string, d fs.DirEntry, err error) error {
if d == nil {
return nil
}

info, err := d.Info()
if err != nil {
return err
}

return walkFn(path, info, err)
})
}
57 changes: 57 additions & 0 deletions fs_embed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// +build go1.16

package render

import (
"embed"
"net/http"
"net/http/httptest"
"testing"
)

//go:embed fixtures/*/*.html fixtures/*/*.tmpl fixtures/*/*/*.tmpl fixtures/*/*.amber fixtures/*/*/*.amber
var EmbedFixtures embed.FS

func TestEmbedFileSystemTemplateLookup(t *testing.T) {
baseDir := "fixtures/template-dir-test"
fname0Rel := "0"
fname1Rel := "subdir/1"
fnameShouldParsedRel := "dedicated.tmpl/notbad"
dirShouldNotParsedRel := "dedicated"

r := New(Options{
Directory: baseDir,
Extensions: []string{".tmpl", ".html"},
FileSystem: &EmbedFileSystem{
FS: EmbedFixtures,
},
})

expect(t, r.TemplateLookup(fname1Rel) != nil, true)
expect(t, r.TemplateLookup(fname0Rel) != nil, true)
expect(t, r.TemplateLookup(fnameShouldParsedRel) != nil, true)
expect(t, r.TemplateLookup(dirShouldNotParsedRel) == nil, true)
}

func TestEmbedFileSystemHTMLBasic(t *testing.T) {
render := New(Options{
Directory: "fixtures/basic",
FileSystem: &EmbedFileSystem{
FS: EmbedFixtures,
},
})

var err error
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err = render.HTML(w, http.StatusOK, "hello", "gophers")
})

res := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/foo", nil)
h.ServeHTTP(res, req)

expectNil(t, err)
expect(t, res.Code, 200)
expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
expect(t, res.Body.String(), "<h1>Hello gophers</h1>\n")
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/unrolled/render

go 1.12
go 1.16

require github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385

0 comments on commit 987556a

Please sign in to comment.