mirror of
https://github.com/schollz/cowyo.git
synced 2023-08-10 21:13:00 +03:00
148 lines
4.1 KiB
Go
148 lines
4.1 KiB
Go
|
package multitemplate
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"html/template"
|
||
|
"path/filepath"
|
||
|
|
||
|
"github.com/gin-gonic/gin"
|
||
|
"github.com/gin-gonic/gin/render"
|
||
|
)
|
||
|
|
||
|
// DynamicRender type
|
||
|
type DynamicRender map[string]*templateBuilder
|
||
|
|
||
|
var (
|
||
|
_ render.HTMLRender = DynamicRender{}
|
||
|
_ Renderer = DynamicRender{}
|
||
|
)
|
||
|
|
||
|
// NewDynamic is the constructor for Dynamic templates
|
||
|
func NewDynamic() DynamicRender {
|
||
|
return make(DynamicRender)
|
||
|
}
|
||
|
|
||
|
// NewRenderer allows create an agnostic multitemplate renderer
|
||
|
// depending on enabled gin mode
|
||
|
func NewRenderer() Renderer {
|
||
|
if gin.IsDebugging() {
|
||
|
return NewDynamic()
|
||
|
}
|
||
|
return New()
|
||
|
}
|
||
|
|
||
|
// Type of dynamic builder
|
||
|
type builderType int
|
||
|
|
||
|
// Types of dynamic builders
|
||
|
const (
|
||
|
templateType builderType = iota
|
||
|
filesTemplateType
|
||
|
globTemplateType
|
||
|
stringTemplateType
|
||
|
stringFuncTemplateType
|
||
|
filesFuncTemplateType
|
||
|
)
|
||
|
|
||
|
// Builder for dynamic templates
|
||
|
type templateBuilder struct {
|
||
|
buildType builderType
|
||
|
tmpl *template.Template
|
||
|
templateName string
|
||
|
files []string
|
||
|
glob string
|
||
|
templateString string
|
||
|
funcMap template.FuncMap
|
||
|
templateStrings []string
|
||
|
}
|
||
|
|
||
|
func (tb templateBuilder) buildTemplate() *template.Template {
|
||
|
switch tb.buildType {
|
||
|
case templateType:
|
||
|
return tb.tmpl
|
||
|
case filesTemplateType:
|
||
|
return template.Must(template.ParseFiles(tb.files...))
|
||
|
case globTemplateType:
|
||
|
return template.Must(template.ParseGlob(tb.glob))
|
||
|
case stringTemplateType:
|
||
|
return template.Must(template.New(tb.templateName).Parse(tb.templateString))
|
||
|
case stringFuncTemplateType:
|
||
|
tmpl := template.New(tb.templateName).Funcs(tb.funcMap)
|
||
|
for _, ts := range tb.templateStrings {
|
||
|
tmpl = template.Must(tmpl.Parse(ts))
|
||
|
}
|
||
|
return tmpl
|
||
|
case filesFuncTemplateType:
|
||
|
return template.Must(template.New(tb.templateName).Funcs(tb.funcMap).ParseFiles(tb.files...))
|
||
|
default:
|
||
|
panic("Invalid builder type for dynamic template")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add new template
|
||
|
func (r DynamicRender) Add(name string, tmpl *template.Template) {
|
||
|
if tmpl == nil {
|
||
|
panic("template cannot be nil")
|
||
|
}
|
||
|
if len(name) == 0 {
|
||
|
panic("template name cannot be empty")
|
||
|
}
|
||
|
builder := &templateBuilder{templateName: name, tmpl: tmpl}
|
||
|
builder.buildType = templateType
|
||
|
r[name] = builder
|
||
|
}
|
||
|
|
||
|
// AddFromFiles supply add template from files
|
||
|
func (r DynamicRender) AddFromFiles(name string, files ...string) *template.Template {
|
||
|
builder := &templateBuilder{templateName: name, files: files}
|
||
|
builder.buildType = filesTemplateType
|
||
|
r[name] = builder
|
||
|
return builder.buildTemplate()
|
||
|
}
|
||
|
|
||
|
// AddFromGlob supply add template from global path
|
||
|
func (r DynamicRender) AddFromGlob(name, glob string) *template.Template {
|
||
|
builder := &templateBuilder{templateName: name, glob: glob}
|
||
|
builder.buildType = globTemplateType
|
||
|
r[name] = builder
|
||
|
return builder.buildTemplate()
|
||
|
}
|
||
|
|
||
|
// AddFromString supply add template from strings
|
||
|
func (r DynamicRender) AddFromString(name, templateString string) *template.Template {
|
||
|
builder := &templateBuilder{templateName: name, templateString: templateString}
|
||
|
builder.buildType = stringTemplateType
|
||
|
r[name] = builder
|
||
|
return builder.buildTemplate()
|
||
|
}
|
||
|
|
||
|
// AddFromStringsFuncs supply add template from strings
|
||
|
func (r DynamicRender) AddFromStringsFuncs(name string, funcMap template.FuncMap, templateStrings ...string) *template.Template {
|
||
|
builder := &templateBuilder{templateName: name, funcMap: funcMap,
|
||
|
templateStrings: templateStrings}
|
||
|
builder.buildType = stringFuncTemplateType
|
||
|
r[name] = builder
|
||
|
return builder.buildTemplate()
|
||
|
}
|
||
|
|
||
|
// AddFromFilesFuncs supply add template from file callback func
|
||
|
func (r DynamicRender) AddFromFilesFuncs(name string, funcMap template.FuncMap, files ...string) *template.Template {
|
||
|
tname := filepath.Base(files[0])
|
||
|
builder := &templateBuilder{templateName: tname, funcMap: funcMap, files: files}
|
||
|
builder.buildType = filesFuncTemplateType
|
||
|
r[name] = builder
|
||
|
return builder.buildTemplate()
|
||
|
}
|
||
|
|
||
|
// Instance supply render string
|
||
|
func (r DynamicRender) Instance(name string, data interface{}) render.Render {
|
||
|
builder, ok := r[name]
|
||
|
if !ok {
|
||
|
panic(fmt.Sprintf("Dynamic template with name %s not found", name))
|
||
|
}
|
||
|
return render.HTML{
|
||
|
Template: builder.buildTemplate(),
|
||
|
Data: data,
|
||
|
}
|
||
|
}
|