Skip to content

Commit 987556a

Browse files
Render templates from embed.FS (#89)
* 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
1 parent 8d2b52a commit 987556a

File tree

4 files changed

+110
-2
lines changed

4 files changed

+110
-2
lines changed

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,27 @@ admin/edit
171171
home
172172
~~~
173173

174-
You can also load templates from memory by providing the Asset and AssetNames options,
174+
Templates can be loaded from an `embed.FS`.
175+
176+
~~~ go
177+
// ...
178+
179+
//go:embed templates/*.html templates/*.tmpl
180+
var embeddedTemplates embed.FS
181+
182+
// ...
183+
184+
r := render.New(render.Options{
185+
Directory: "templates",
186+
FileSystem: &EmbedFileSystem{
187+
FS: embeddedTemplates,
188+
},
189+
Extensions: []string{".html", ".tmpl"},
190+
})
191+
// ...
192+
~~~
193+
194+
You can also load templates from memory by providing the `Asset` and `AssetNames` options,
175195
e.g. when generating an asset file using [go-bindata](https://github.com/jteeuwen/go-bindata).
176196

177197
### Layouts

fs_embed.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// +build go1.16
2+
3+
package render
4+
5+
import (
6+
"embed"
7+
"io/fs"
8+
"path/filepath"
9+
)
10+
11+
// EmbedFileSystem implements FileSystem on top of an embed.FS
12+
type EmbedFileSystem struct {
13+
embed.FS
14+
}
15+
16+
var _ FileSystem = &EmbedFileSystem{}
17+
18+
func (e *EmbedFileSystem) Walk(root string, walkFn filepath.WalkFunc) error {
19+
return fs.WalkDir(e.FS, root, func(path string, d fs.DirEntry, err error) error {
20+
if d == nil {
21+
return nil
22+
}
23+
24+
info, err := d.Info()
25+
if err != nil {
26+
return err
27+
}
28+
29+
return walkFn(path, info, err)
30+
})
31+
}

fs_embed_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// +build go1.16
2+
3+
package render
4+
5+
import (
6+
"embed"
7+
"net/http"
8+
"net/http/httptest"
9+
"testing"
10+
)
11+
12+
//go:embed fixtures/*/*.html fixtures/*/*.tmpl fixtures/*/*/*.tmpl fixtures/*/*.amber fixtures/*/*/*.amber
13+
var EmbedFixtures embed.FS
14+
15+
func TestEmbedFileSystemTemplateLookup(t *testing.T) {
16+
baseDir := "fixtures/template-dir-test"
17+
fname0Rel := "0"
18+
fname1Rel := "subdir/1"
19+
fnameShouldParsedRel := "dedicated.tmpl/notbad"
20+
dirShouldNotParsedRel := "dedicated"
21+
22+
r := New(Options{
23+
Directory: baseDir,
24+
Extensions: []string{".tmpl", ".html"},
25+
FileSystem: &EmbedFileSystem{
26+
FS: EmbedFixtures,
27+
},
28+
})
29+
30+
expect(t, r.TemplateLookup(fname1Rel) != nil, true)
31+
expect(t, r.TemplateLookup(fname0Rel) != nil, true)
32+
expect(t, r.TemplateLookup(fnameShouldParsedRel) != nil, true)
33+
expect(t, r.TemplateLookup(dirShouldNotParsedRel) == nil, true)
34+
}
35+
36+
func TestEmbedFileSystemHTMLBasic(t *testing.T) {
37+
render := New(Options{
38+
Directory: "fixtures/basic",
39+
FileSystem: &EmbedFileSystem{
40+
FS: EmbedFixtures,
41+
},
42+
})
43+
44+
var err error
45+
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
46+
err = render.HTML(w, http.StatusOK, "hello", "gophers")
47+
})
48+
49+
res := httptest.NewRecorder()
50+
req, _ := http.NewRequest("GET", "/foo", nil)
51+
h.ServeHTTP(res, req)
52+
53+
expectNil(t, err)
54+
expect(t, res.Code, 200)
55+
expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8")
56+
expect(t, res.Body.String(), "<h1>Hello gophers</h1>\n")
57+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module github.com/unrolled/render
22

3-
go 1.12
3+
go 1.16
44

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

0 commit comments

Comments
 (0)