package handlebars
import (
"html"
"path/filepath"
"github.com/aymerick/raymond"
"github.com/mickael-menu/zk/adapter/handlebars/helpers"
"github.com/mickael-menu/zk/core/style"
"github.com/mickael-menu/zk/core/templ"
"github.com/mickael-menu/zk/util"
"github.com/mickael-menu/zk/util/errors"
)
func Init(lang string, supportsUTF8 bool, logger util.Logger, styler style.Styler) {
helpers.RegisterConcat()
helpers.RegisterDate(logger)
helpers.RegisterList(supportsUTF8)
helpers.RegisterPrepend(logger)
helpers.RegisterShell(logger)
helpers.RegisterSlug(lang, logger)
helpers.RegisterStyle(styler, logger)
}
// Template renders a parsed handlebars template.
type Template struct {
template *raymond.Template
}
// Render renders the template with the given context.
func (t *Template) Render(context interface{}) (string, error) {
res, err := t.template.Exec(context)
if err != nil {
return "", errors.Wrap(err, "render template failed")
}
return html.UnescapeString(res), nil
}
// Loader loads and holds parsed handlebars templates.
type Loader struct {
strings map[string]*Template
files map[string]*Template
}
// NewLoader creates a new instance of Loader.
func NewLoader() *Loader {
return &Loader{
strings: make(map[string]*Template),
files: make(map[string]*Template),
}
}
// Load retrieves or parses a handlebars string template.
func (l *Loader) Load(content string) (templ.Renderer, error) {
wrap := errors.Wrapperf("load template failed")
// Already loaded?
template, ok := l.strings[content]
if ok {
return template, nil
}
// Load new template.
vendorTempl, err := raymond.Parse(content)
if err != nil {
return nil, wrap(err)
}
template = &Template{vendorTempl}
l.strings[content] = template
return template, nil
}
// LoadFile retrieves or parses a handlebars file template.
func (l *Loader) LoadFile(path string) (templ.Renderer, error) {
wrap := errors.Wrapper("load template file failed")
path, err := filepath.Abs(path)
if err != nil {
return nil, wrap(err)
}
// Already loaded?
template, ok := l.files[path]
if ok {
return template, nil
}
// Load new template.
vendorTempl, err := raymond.ParseFile(path)
if err != nil {
return nil, wrap(err)
}
template = &Template{vendorTempl}
l.files[path] = template
return template, nil
}