2022-11-05 07:44:37 +00:00
|
|
|
// Package templates helps sites to manage their templates
|
2021-10-24 16:39:48 +00:00
|
|
|
package templates
|
|
|
|
|
2021-11-10 18:05:52 +00:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"errors"
|
|
|
|
"io"
|
|
|
|
"io/fs"
|
|
|
|
"net/http"
|
|
|
|
"path/filepath"
|
|
|
|
|
2022-11-05 07:45:48 +00:00
|
|
|
"github.com/flosch/pongo2/v6"
|
2021-11-10 18:05:52 +00:00
|
|
|
"github.com/gin-gonic/gin/render"
|
2022-11-05 07:29:17 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
2021-11-10 18:05:52 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
_ pongo2.TemplateLoader = &FSLoader{}
|
|
|
|
_ render.Render = &renderer{}
|
|
|
|
_ pongo2.TemplateLoader = &EmptyLoader{}
|
|
|
|
)
|
2021-10-24 16:39:48 +00:00
|
|
|
|
2022-11-05 07:44:37 +00:00
|
|
|
// TemplateSite is an interface that is for storing templates.
|
2021-10-24 16:39:48 +00:00
|
|
|
type TemplateSite interface {
|
2021-11-10 18:05:52 +00:00
|
|
|
Templates() pongo2.TemplateLoader
|
|
|
|
}
|
|
|
|
|
|
|
|
// FSLoader is an interim until pongo merges the pullrequest for fs.FS
|
|
|
|
type FSLoader struct {
|
|
|
|
fs.FS
|
|
|
|
}
|
|
|
|
|
|
|
|
// Abs return the join of base and name
|
|
|
|
func (e *FSLoader) Abs(base, name string) string {
|
|
|
|
return filepath.Join(filepath.Dir(base), name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns an io.Reader where the template's content can be read from.
|
|
|
|
func (e *FSLoader) Get(path string) (reader io.Reader, err error) {
|
|
|
|
f, err := e.FS.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
|
|
|
|
bt, err := io.ReadAll(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return bytes.NewBuffer(bt), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pongo2Renderer is an simple wrapper for gin to use pongo2 templates
|
|
|
|
type Pongo2Renderer struct {
|
|
|
|
ts *pongo2.TemplateSet
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewPongo2Renderer creates an wrapper for gin
|
|
|
|
func NewPongo2Renderer(ts *pongo2.TemplateSet) render.HTMLRender {
|
|
|
|
return &Pongo2Renderer{ts: ts}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instance create an new instance of an REnder object
|
2022-11-06 09:52:24 +00:00
|
|
|
func (p2r *Pongo2Renderer) Instance(name string, data any) render.Render {
|
2021-11-10 18:05:52 +00:00
|
|
|
tmpl, err := p2r.ts.FromFile(name)
|
|
|
|
r := &renderer{
|
|
|
|
tmpl: tmpl,
|
|
|
|
err: err,
|
|
|
|
}
|
|
|
|
if data != nil {
|
|
|
|
switch data.(type) {
|
|
|
|
case pongo2.Context:
|
|
|
|
r.data = data.(pongo2.Context)
|
2022-11-06 09:52:24 +00:00
|
|
|
case map[string]any:
|
|
|
|
r.data = data.(map[string]any)
|
2021-11-10 18:05:52 +00:00
|
|
|
default:
|
2022-11-06 09:52:24 +00:00
|
|
|
r.err = errors.New("Failed to detect possible format for pongo2. It needs to be map[string]any or pongo2.Context")
|
2021-11-10 18:05:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Debug().Msg("Returning an instance")
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
type renderer struct {
|
|
|
|
tmpl *pongo2.Template
|
|
|
|
err error
|
|
|
|
data pongo2.Context
|
|
|
|
}
|
|
|
|
|
|
|
|
// Render renders the template
|
|
|
|
func (r *renderer) Render(rw http.ResponseWriter) error {
|
|
|
|
if r.err != nil {
|
|
|
|
log.Debug().Msg("rendering failed")
|
|
|
|
return r.err
|
|
|
|
}
|
|
|
|
log.Debug().Msg("wirting template")
|
|
|
|
return r.tmpl.ExecuteWriter(r.data, rw)
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteContentType is an static function that always writes text/html as the Contenttype into the response
|
|
|
|
func (*renderer) WriteContentType(rw http.ResponseWriter) {
|
|
|
|
rw.Header().Set("Content-Type", "text/html")
|
|
|
|
}
|
|
|
|
|
|
|
|
// EmptyLoader is an Empty Loader
|
|
|
|
type EmptyLoader struct{}
|
|
|
|
|
|
|
|
// Abs return the join of base and name
|
|
|
|
func (*EmptyLoader) Abs(base, name string) string {
|
|
|
|
return filepath.Join(filepath.Dir(base), name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get returns always errors
|
|
|
|
func (*EmptyLoader) Get(string) (io.Reader, error) {
|
|
|
|
return nil, errors.New("This Loader has no templates")
|
2021-10-24 16:39:48 +00:00
|
|
|
}
|