iris/adaptors/view/adaptor.go
Gerasimos (Makis) Maropoulos 13e83fc57e SessionsPolicy and sessions adaptor, history and _example written.
Former-commit-id: e8b0dde3cb3b72919f01b9d836d8ccb3d4e20214
2017-02-15 20:06:19 +02:00

139 lines
5.6 KiB
Go

// Package view is the adaptor of the 5 template engines
// as written by me at https://github.com/kataras/go-template
package view
import (
"io"
"strings"
"github.com/kataras/go-template"
"gopkg.in/kataras/iris.v6"
)
// Adaptor contains the common actions
// that all template engines share.
//
// We need to export that as it is without an interface
// because it may be used as a wrapper for a template engine
// that is not exists yet but community can create.
type Adaptor struct {
dir string
extension string
// for a .go template file lives inside the executable
assetFn func(name string) ([]byte, error)
namesFn func() []string
reload bool
engine template.Engine // used only on Adapt, we could make
//it as adaptEngine and pass a second parameter there but this would break the pattern.
}
// NewAdaptor returns a new general template engine policy adaptor.
func NewAdaptor(directory string, extension string, e template.Engine) *Adaptor {
return &Adaptor{
dir: directory,
extension: extension,
engine: e,
}
}
// Binary optionally, use it when template files are distributed
// inside the app executable (.go generated files).
func (h *Adaptor) Binary(assetFn func(name string) ([]byte, error), namesFn func() []string) *Adaptor {
h.assetFn = assetFn
h.namesFn = namesFn
return h
}
// Reload if setted to true the templates are reloading on each call,
// use it when you're in development and you're boring of restarting
// the whole app when you edit a template file
func (h *Adaptor) Reload(developmentMode bool) *Adaptor {
h.reload = developmentMode
return h
}
// Adapt adapts a template engine to the main Iris' policies.
// this specific Adapt is a multi-policies adaptors
// we use that instead of just return New() iris.RenderPolicy
// for two reasons:
// - the user may need to edit the adaptor's fields
// like Directory, Binary
// - we need to adapt an event policy to add the engine to the external mux
// and load it.
func (h *Adaptor) Adapt(frame *iris.Policies) {
mux := template.DefaultMux
// on the build state in order to have the shared funcs also
evt := iris.EventPolicy{
Build: func(s *iris.Framework) {
// mux has default to ./templates and .html ext
// no need for any checks here.
// the RenderPolicy will give a "no templates found on 'directory'"
// if user tries to use the context.Render without having the template files
// no need to panic here because we will use the html as the default template engine
// even if the user doesn't asks for
// or no? we had the defaults before... maybe better to give the user
// the oportunity to learn about the template's configuration
// (now 6.1.4 ) they are defaulted and users may don't know how and if they can change the configuration
// even if the book and examples covers these things, many times they're asking me on chat.............
// so no defaults? ok no defaults. This file then will be saved to /adaptors as with other template engines.
// simple.
mux.AddEngine(h.engine).
Directory(h.dir, h.extension).
Binary(h.assetFn, h.namesFn)
mux.Reload = h.reload
// notes for me: per-template engine funcs are setted by each template engine adaptor itself,
// here we will set the template funcs policy'.
// as I explain on the TemplateFuncsPolicy it exists in order to allow community to create plugins
// even by adding custom template funcs to their behaviors.
// We know that iris.TemplateFuncsPolicy is useless without this specific
// adaptor. We also know that it is not a good idea to have two
// policies with the same function or we can? wait. No we can't.
// We can't because:
// - the RenderPolicy should accept any type of render process, not only tempaltes.
// - I didn't design iris/policy.go to keep logic about implementation, this would make that very limited
// and I don't want to break that just for the templates.
// - We want community to be able to create packages which can adapt template functions but
// not to worry about the rest of the template engine adaptor policy.
// And even don't worry if the user has registered or use a template engine at all.
// So we should keep separate the TemplateFuncsPolicy(just map[string]interface{})
// from the rest of the implementation.
//
// So when the community wants to create a template adaptor has two options:
// - Use the RenderPolicy which is just a func
// - Use the kataras/iris/adaptors/view.Adaptor adaptor wrapper for RenderPolicy with a compination of kataras/go-template/.Engine
//
//
// So here is the only place we adapt the iris.TemplateFuncsPolicy to the tempaltes, if and only if templates are used,
// otherwise they are just ignored without any creepy things.
//
// The TemplateFuncsPolicy will work in compination with the specific template adaptor's functions(see html.go and the rest)
if len(frame.TemplateFuncsPolicy) > 0 {
mux.SetFuncMapToEngine(frame.TemplateFuncsPolicy, h.engine)
}
if err := mux.Load(); err != nil {
s.Log(iris.ProdMode, err.Error())
}
},
}
// adapt the build event to the main policies
evt.Adapt(frame)
r := iris.RenderPolicy(func(out io.Writer, file string, tmplContext interface{}, options ...map[string]interface{}) (error, bool) {
// template mux covers that but maybe we have more than one RenderPolicy
// and each of them carries a different mux on the new design.
if strings.Contains(file, h.extension) {
return mux.ExecuteWriter(out, file, tmplContext, options...), true
}
return nil, false
})
r.Adapt(frame)
}