-
-
Save robvdl/04dba3945e7949727085a37f53190124 to your computer and use it in GitHub Desktop.
package web | |
import ( | |
"io" | |
"github.com/flosch/pongo2/v6" | |
"github.com/labstack/echo/v4" | |
"github.com/spf13/viper" | |
) | |
// RenderOptions is used to configure the renderer. | |
type RenderOptions struct { | |
TemplateDir string | |
TemplateSet *pongo2.TemplateSet | |
ContentType string | |
} | |
// Pongo2Render is a custom Echo template renderer using Pongo2. | |
type Pongo2Render struct { | |
Options *RenderOptions | |
} | |
// NewRender creates a new Pongo2Render instance with custom Options. | |
func NewRender(options RenderOptions) (*Pongo2Render, error) { | |
// If TemplateSet is nil construct a new TemplateSet for TemplateDir. | |
if options.TemplateSet == nil { | |
loader, err := pongo2.NewLocalFileSystemLoader(options.TemplateDir) | |
if err != nil { | |
return nil, err | |
} | |
options.TemplateSet = pongo2.NewSet(options.TemplateDir, loader) | |
options.TemplateSet.Debug = viper.GetBool("debug") | |
} | |
render := &Pongo2Render{Options: &options} | |
return render, nil | |
} | |
// DefaultRender creates a Pongo2Render instance with default options. | |
func DefaultRender() (*Pongo2Render, error) { | |
return NewRender(RenderOptions{ | |
TemplateDir: viper.GetString("template_dir"), | |
TemplateSet: nil, | |
ContentType: echo.MIMETextHTMLCharsetUTF8, | |
}) | |
} | |
// Render is an interface function that renders a Pongo2 template as an HTML response. | |
func (p *Pongo2Render) Render(w io.Writer, name string, data interface{}, c echo.Context) error { | |
template, err := p.Options.TemplateSet.FromCache(name) | |
if err != nil { | |
return err | |
} | |
c.Response().Header().Set(echo.HeaderContentType, p.Options.ContentType) | |
return template.ExecuteWriter(data.(pongo2.Context), w) | |
} |
If e.Debug is true (were e is the Echo app), then it will not use a template cache. This is great for development as you can make changes to templates and not have to restart the app.
In production however, when e.Debug is false, it will use a template cache. In this mode, the first time a template is loaded from disk and compiled, it caches the compiled template. So any changes to the template on disk thereafter, requires restarting of the application as the app won't reload it. This is suitable for production but not development.
Also this probably should come with a "how to use", here goes:
e := echo.New()
e.Debug = viper.GetBool("debug")
// Setup the Pongo2 renderer
render, err := DefaultRender()
if err != nil {
// handle or return error (e.g. template dir does not exist could return an error)
}
e.Renderer = render
// Start Echo
e.Logger.Fatal(e.Start(":8080"))
The reason I am using TemplateSet actually originated in my pongo2gin repo on Gitlab (gitlab.com/go-box/pongo2gin), a contributor needed this and added support for template sets. I since cleaned it up, refactored it, and translated the code to use Echo instead of Gin.
You may notice it automatically creates a TemplateSet based on the template dir if TemplateSet was nil. Otherwise it will use the TemplateSet you pass in.
This is a code snippet for setting up Pongo2 as the template renderer in Echo. It is also using viper for config.