// Filename: internal/pongo/renderer.go package pongo import ( "fmt" "net/http" "github.com/flosch/pongo2/v6" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/render" ) type Renderer struct { Context pongo2.Context tplSet *pongo2.TemplateSet } func New(directory string, isDebug bool) *Renderer { loader := pongo2.MustNewLocalFileSystemLoader(directory) tplSet := pongo2.NewSet("gin-pongo-templates", loader) tplSet.Debug = isDebug return &Renderer{Context: make(pongo2.Context), tplSet: tplSet} } // Instance returns a new render.HTML instance for a single request. func (p *Renderer) Instance(name string, data interface{}) render.Render { var glob pongo2.Context if p.Context != nil { glob = p.Context } var context pongo2.Context if data != nil { if ginContext, ok := data.(gin.H); ok { context = pongo2.Context(ginContext) } else if pongoContext, ok := data.(pongo2.Context); ok { context = pongoContext } else if m, ok := data.(map[string]interface{}); ok { context = m } else { context = make(pongo2.Context) } } else { context = make(pongo2.Context) } for k, v := range glob { if _, ok := context[k]; !ok { context[k] = v } } tpl, err := p.tplSet.FromCache(name) if err != nil { panic(fmt.Sprintf("Failed to load template '%s': %v", name, err)) } return &HTML{ p: p, Template: tpl, Name: name, Data: context, } } type HTML struct { p *Renderer Template *pongo2.Template Name string Data pongo2.Context } func (h *HTML) Render(w http.ResponseWriter) error { h.WriteContentType(w) bytes, err := h.Template.ExecuteBytes(h.Data) if err != nil { return err } _, err = w.Write(bytes) return err } func (h *HTML) WriteContentType(w http.ResponseWriter) { header := w.Header() if val := header["Content-Type"]; len(val) == 0 { header["Content-Type"] = []string{"text/html; charset=utf-8"} } } func C(ctx *gin.Context) pongo2.Context { p, exists := ctx.Get("pongo2") if exists { if pCtx, ok := p.(pongo2.Context); ok { return pCtx } } pCtx := make(pongo2.Context) ctx.Set("pongo2", pCtx) return pCtx }