aboutsummaryrefslogtreecommitdiff
path: root/echo/template_renderer.go
blob: 8515249bfce577a37d5b6b1b7246861bc1be9dc8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package echo

import (
	"html/template"
	"io"
	"io/fs"
	"net/http"
	"path/filepath"

	"github.com/labstack/echo/v4"
)

type TemplateChecker interface {
	HaveTemplate(string) bool
}

type TemplateRenderer struct {
	templates fs.FS
	glob      string
	funcs     template.FuncMap
	cache     *template.Template
	debug     bool
}

func NewTemplateRenderer(templates fs.FS, glob string, funcs template.FuncMap, debug bool) (*TemplateRenderer, error) {
	var err error

	r := &TemplateRenderer{
		templates: templates,
		glob:      glob,
		funcs:     funcs,
		debug:     debug,
	}

	r.cache, err = r.loadTemplates()
	if err != nil {
		return nil, err
	}

	return r, nil
}

func (r *TemplateRenderer) loadTemplates() (*template.Template, error) {
	t := template.New("").Funcs(r.funcs)

	err := fs.WalkDir(r.templates, ".", func(path string, info fs.DirEntry, err error) error {
		if err != nil {
			return err
		}

		if !info.IsDir() {
			_, fn := filepath.Split(path)
			if ok, _ := filepath.Match(r.glob, fn); ok {
				fc, err := fs.ReadFile(r.templates, path)
				if err != nil {
					return err
				}

				_, err = t.New(path).Parse(string(fc))
				if err != nil {
					return err
				}
			}
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return t, nil
}

func (r *TemplateRenderer) getTemplateCache() (*template.Template, error) {
	if !r.debug {
		return r.cache, nil
	}

	tc, err := r.loadTemplates()
	if err != nil {
		return nil, err
	}

	return tc, nil
}

func (r *TemplateRenderer) Render(w io.Writer, name string, data interface{}, ctx echo.Context) error {
	tc, err := r.getTemplateCache()
	if err != nil {
		return err
	}

	if tc.Lookup(name) == nil {
		return echo.NewHTTPError(http.StatusNotFound, "Page not found")
	}

	if err := tc.ExecuteTemplate(w, name, data); err != nil {
		return err
	}

	return nil
}

func (r *TemplateRenderer) HaveTemplate(name string) bool {
	tc, err := r.getTemplateCache()
	if err != nil {
		return false
	}

	return tc.Lookup(name) != nil
}

var _ echo.Renderer = (*TemplateRenderer)(nil)
var _ TemplateChecker = (*TemplateRenderer)(nil)