From ae8cbc8f456299ebf8f6437e90faef1d40fe508b Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Mon, 24 Jul 2023 12:33:16 +0300 Subject: [PATCH] added template.Registry.LoadFS method --- tools/template/registry.go | 32 ++++++++++++-- tools/template/registry_test.go | 76 +++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 4 deletions(-) diff --git a/tools/template/registry.go b/tools/template/registry.go index 86ddcb82..0a4c0039 100644 --- a/tools/template/registry.go +++ b/tools/template/registry.go @@ -21,7 +21,9 @@ package template import ( + "fmt" "html/template" + "io/fs" "strings" "github.com/pocketbase/pocketbase/tools/store" @@ -43,16 +45,18 @@ type Registry struct { cache *store.Store[*Renderer] } -// LoadFiles caches (if not already) the specified files set as a +// LoadFiles caches (if not already) the specified filenames set as a // single template and returns a ready to use Renderer instance. -func (r *Registry) LoadFiles(files ...string) *Renderer { - key := strings.Join(files, ",") +// +// There must be at least 1 filename specified. +func (r *Registry) LoadFiles(filenames ...string) *Renderer { + key := strings.Join(filenames, ",") found := r.cache.Get(key) if found == nil { // parse and cache - tpl, err := template.ParseFiles(files...) + tpl, err := template.ParseFiles(filenames...) found = &Renderer{template: tpl, parseError: err} r.cache.Set(key, found) } @@ -74,3 +78,23 @@ func (r *Registry) LoadString(text string) *Renderer { return found } + +// LoadString caches (if not already) the specified fs and globPatterns +// pair as single template and returns a ready to use Renderer instance. +// +// There must be at least 1 file matching the provided globPattern(s) +// (note that most file names serves as glob patterns matching themselves). +func (r *Registry) LoadFS(fs fs.FS, globPatterns ...string) *Renderer { + key := fmt.Sprintf("%v%v", fs, globPatterns) + + found := r.cache.Get(key) + + if found == nil { + // parse and cache + tpl, err := template.ParseFS(fs, globPatterns...) + found = &Renderer{template: tpl, parseError: err} + r.cache.Set(key, found) + } + + return found +} diff --git a/tools/template/registry_test.go b/tools/template/registry_test.go index b1b5a124..4a2147a9 100644 --- a/tools/template/registry_test.go +++ b/tools/template/registry_test.go @@ -1,6 +1,7 @@ package template import ( + "fmt" "os" "path/filepath" "strings" @@ -138,3 +139,78 @@ func TestRegistryLoadString(t *testing.T) { } }) } + +func TestRegistryLoadFS(t *testing.T) { + r := NewRegistry() + + t.Run("invalid fs", func(t *testing.T) { + fs := os.DirFS("__missing__") + + files := []string{"missing1", "missing2"} + + key := fmt.Sprintf("%v%v", fs, files) + + r.LoadFS(fs, files...) + + renderer := r.cache.Get(key) + + if renderer == nil { + t.Fatal("Expected renderer to be initialized even if invalid, got nil") + } + + if renderer.template != nil { + t.Fatalf("Expected renderer template to be nil, got %v", renderer.template) + } + + if renderer.parseError == nil { + t.Fatalf("Expected renderer parseError to be set, got nil") + } + }) + + t.Run("valid fs", func(t *testing.T) { + // create test templates + dir, err := os.MkdirTemp(os.TempDir(), "template_test2") + if err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, "base.html"), []byte(`Base:{{template "content"}}`), 0644); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(dir, "content.html"), []byte(`{{define "content"}}Content:123{{end}}`), 0644); err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + + fs := os.DirFS(dir) + + files := []string{"base.html", "content.html"} + + key := fmt.Sprintf("%v%v", fs, files) + + r.LoadFS(fs, files...) + + renderer := r.cache.Get(key) + + if renderer == nil { + t.Fatal("Expected renderer to be initialized even if invalid, got nil") + } + + if renderer.template == nil { + t.Fatal("Expected renderer template to be set, got nil") + } + + if renderer.parseError != nil { + t.Fatalf("Expected renderer parseError to be nil, got %v", renderer.parseError) + } + + result, err := renderer.Render(nil) + if err != nil { + t.Fatalf("Unexpected Render() error, got %v", err) + } + + expected := "Base:Content:123" + if result != expected { + t.Fatalf("Expected Render() result %q, got %q", expected, result) + } + }) +}