Skip to content

Instantly share code, notes, and snippets.

@rakd
Created December 6, 2017 05:20
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rakd/5073f57e5053ce443cd8de070e623d63 to your computer and use it in GitHub Desktop.
Save rakd/5073f57e5053ce443cd8de070e623d63 to your computer and use it in GitHub Desktop.
template inheritance for echo/golang
package main
import (
"fmt"
"html/template"
"io"
"log"
"os"
"path/filepath"
"strings"
"github.com/labstack/echo"
)
/*
view files should be below
- app/views/layouts/base.html
- app/views/layouts/amp.html
- app/views/layouts/admin.html
- app/views/partials/XXXX.html
- app/views/XXX/YYY.html
*/
// Template ...
type Template struct {
templates map[string]*template.Template
}
// Add ...
func (t Template) Add(name string, tmpl *template.Template) {
if tmpl == nil {
panic("template can not be nil")
}
if len(name) == 0 {
panic("template name cannot be empty")
}
t.templates[name] = tmpl
}
// Render ...
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
if _, ok := t.templates[name]; ok == false {
// not such view
return fmt.Errorf("no such view. (%s)", name)
}
return t.templates[name].Execute(w, data)
}
// NewTemplate creates a new template
func NewTemplate(templatesDir string) *Template {
ext := ".html"
ins := Template{
templates: map[string]*template.Template{},
}
layout := templatesDir + "layouts/base" + ext
adminLayout := templatesDir + "layouts/admin" + ext
ampLayout := templatesDir + "layouts/amp" + ext
_, err := os.Stat(layout)
if err != nil {
log.Panicf("cannot find %s", layout)
os.Exit(1)
}
_, err = os.Stat(adminLayout)
if err != nil {
log.Printf("cannot find %s", adminLayout)
os.Exit(1)
}
_, err = os.Stat(ampLayout)
if err != nil {
log.Printf("cannot find %s", ampLayout)
os.Exit(1)
}
partials, err := filepath.Glob(templatesDir + "partials/" + "*" + ext)
if err != nil {
log.Print("cannot find " + templatesDir + "partials/" + "*" + ext)
os.Exit(1)
}
funcMap := template.FuncMap{
"safehtml": func(text string) template.HTML { return template.HTML(text) },
}
views, _ := filepath.Glob(templatesDir + "**/*" + ext)
for _, view := range views {
dir, file := filepath.Split(view)
dir = strings.Replace(dir, templatesDir, "", 1)
file = strings.TrimSuffix(file, ext)
renderName := dir + file
if strings.Contains(renderName, "_amp") {
tmplfiles := append([]string{ampLayout, view}, partials...)
tmpl := template.Must(template.New(filepath.Base(ampLayout)).Funcs(funcMap).ParseFiles(tmplfiles...))
ins.Add(renderName, tmpl)
log.Printf("renderName: %s, layout: %s", renderName, ampLayout)
} else if strings.Contains(renderName, "admin") {
tmplfiles := append([]string{adminLayout, view}, partials...)
tmpl := template.Must(template.New(filepath.Base(adminLayout)).Funcs(funcMap).ParseFiles(tmplfiles...))
ins.Add(renderName, tmpl)
log.Printf("renderName: %s, layout: %s", renderName, adminLayout)
} else {
tmplfiles := append([]string{layout, view}, partials...)
tmpl := template.Must(template.New(filepath.Base(layout)).Funcs(funcMap).ParseFiles(tmplfiles...))
ins.Add(renderName, tmpl)
log.Printf("renderName: %s, layout: %s", renderName, layout)
}
}
return &ins
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment