package render import ( "bytes" "errors" "fmt" "go-udemy-web-1/internal/config" "go-udemy-web-1/internal/helpers" "go-udemy-web-1/internal/models" "html/template" "net/http" "path/filepath" "time" "github.com/justinas/nosurf" ) var functions = template.FuncMap{ "humanDate": HumanDate, "formatDate": FormatDate, "iterate": Iterate, "add": Add, } var ( app *config.AppConfig pathToTemplates = "./templates" ) // NewRenderer sets the config for the template package func NewRenderer(a *config.AppConfig) { app = a } // HumanDate returns formatted time func HumanDate(t time.Time) string { return t.Format("2006-01-02") } func FormatDate(t time.Time, f string) string { return t.Format(f) } // Iterate returns a slice of ints, starting at 1, going to count func Iterate(count int) []int { var i int var items []int for i = 0; i < count; i++ { items = append(items, i) } return items } func Add(a, b int) int { return a + b } // AddDefaultData adds default template data func AddDefaultData(td *models.TemplateData, r *http.Request) *models.TemplateData { td.Flash = app.Session.PopString(r.Context(), "flash") td.Warning = app.Session.PopString(r.Context(), "warning") td.Error = app.Session.PopString(r.Context(), "error") td.CSRFToken = nosurf.Token(r) if app.Session.Exists(r.Context(), "user_id") { td.IsAuthenticated = 1 } return td } // Template renders a HTML template file func Template(w http.ResponseWriter, r *http.Request, tmpl string, td *models.TemplateData) error { var tc map[string]*template.Template if app.UseCache { // get the template cache from the app config tc = app.TemplateCahce } else { tc, _ = CreateTemplateCache() } // get requested template from cache t, ok := tc[tmpl] if !ok { return errors.New("could not get template from template cache") } // Write to a buffer to make sure that the template can be read and // written successfully buf := new(bytes.Buffer) td = AddDefaultData(td, r) err := t.Execute(buf, td) if err != nil { helpers.ServerError(w, err) return err } // render the template _, err = buf.WriteTo(w) if err != nil { helpers.ServerError(w, err) return err } return nil } func CreateTemplateCache() (map[string]*template.Template, error) { myCache := map[string]*template.Template{} // get all of the files named *.page.tmpl from templates pages, err := filepath.Glob(fmt.Sprintf("%s/*.page.tmpl", pathToTemplates)) if err != nil { return myCache, err } // range through all files ending with *page.tmpl for _, page := range pages { name := filepath.Base(page) ts, err := template.New(name).Funcs(functions).ParseFiles(page) if err != nil { return myCache, err } matches, err := filepath.Glob(fmt.Sprintf("%s/*.layout.tmpl", pathToTemplates)) if err != nil { return myCache, err } if len(matches) > 0 { ts, err = ts.ParseGlob(fmt.Sprintf("%s/*.layout.tmpl", pathToTemplates)) if err != nil { return myCache, err } } myCache[name] = ts } return myCache, nil }