@@ -18,7 +18,7 @@ type Plugin interface { | |||
SetRoutes(group *echo.Group) | |||
// Inject is called prior to rendering a template. It can extend the | |||
// template data by setting new items in the Extra map. | |||
Inject(name string, data interface{}) error | |||
Inject(name string, data RenderData) error | |||
// Close is called when the plugin is unloaded. | |||
Close() error | |||
} | |||
@@ -40,7 +40,7 @@ func (p *goPlugin) SetRoutes(group *echo.Group) { | |||
group.Static("/plugins/"+p.p.Name+"/assets", pluginDir+"/"+p.p.Name+"/public/assets") | |||
} | |||
func (p *goPlugin) Inject(name string, data interface{}) error { | |||
func (p *goPlugin) Inject(name string, data RenderData) error { | |||
if f, ok := p.p.injectFuncs["*"]; ok { | |||
if err := f(data); err != nil { | |||
return err | |||
@@ -114,7 +114,7 @@ func (p *GoPlugin) TemplateFuncs(funcs template.FuncMap) { | |||
} | |||
// InjectFunc is a function that injects data prior to rendering a template. | |||
type InjectFunc func(data interface{}) error | |||
type InjectFunc func(data RenderData) error | |||
// Inject registers a function to execute prior to rendering a template. The | |||
// special name "*" matches any template. | |||
@@ -68,7 +68,7 @@ func (p *luaPlugin) setRoute(l *lua.LState) int { | |||
return 0 | |||
} | |||
func (p *luaPlugin) inject(name string, data interface{}) error { | |||
func (p *luaPlugin) inject(name string, data RenderData) error { | |||
f, ok := p.renderCallbacks[name] | |||
if !ok { | |||
return nil | |||
@@ -86,7 +86,7 @@ func (p *luaPlugin) inject(name string, data interface{}) error { | |||
return nil | |||
} | |||
func (p *luaPlugin) Inject(name string, data interface{}) error { | |||
func (p *luaPlugin) Inject(name string, data RenderData) error { | |||
if err := p.inject("*", data); err != nil { | |||
return err | |||
} | |||
@@ -116,12 +116,12 @@ func handleGetMailbox(ectx echo.Context) error { | |||
return ctx.Render(http.StatusOK, "mailbox.html", &MailboxRenderData{ | |||
BaseRenderData: *koushin.NewBaseRenderData(ctx), | |||
Mailbox: mbox, | |||
Mailboxes: mailboxes, | |||
Messages: msgs, | |||
PrevPage: prevPage, | |||
NextPage: nextPage, | |||
Query: query, | |||
Mailbox: mbox, | |||
Mailboxes: mailboxes, | |||
Messages: msgs, | |||
PrevPage: prevPage, | |||
NextPage: nextPage, | |||
Query: query, | |||
}) | |||
} | |||
@@ -239,14 +239,14 @@ func handleGetPart(ctx *koushin.Context, raw bool) error { | |||
} | |||
return ctx.Render(http.StatusOK, "message.html", &MessageRenderData{ | |||
BaseRenderData: *koushin.NewBaseRenderData(ctx), | |||
Mailboxes: mailboxes, | |||
Mailbox: mbox, | |||
Message: msg, | |||
Body: body, | |||
PartPath: partPathString, | |||
MailboxPage: int(mbox.Messages-msg.SeqNum) / messagesPerPage, | |||
Flags: flags, | |||
BaseRenderData: *koushin.NewBaseRenderData(ctx), | |||
Mailboxes: mailboxes, | |||
Mailbox: mbox, | |||
Message: msg, | |||
Body: body, | |||
PartPath: partPathString, | |||
MailboxPage: int(mbox.Messages-msg.SeqNum) / messagesPerPage, | |||
Flags: flags, | |||
}) | |||
} | |||
@@ -354,7 +354,7 @@ func handleCompose(ectx echo.Context) error { | |||
return ctx.Render(http.StatusOK, "compose.html", &ComposeRenderData{ | |||
BaseRenderData: *koushin.NewBaseRenderData(ctx), | |||
Message: &msg, | |||
Message: &msg, | |||
}) | |||
} | |||
@@ -20,18 +20,48 @@ type GlobalRenderData struct { | |||
Username string | |||
// TODO: list of mailboxes | |||
// Additional plugin-specific data | |||
// additional plugin-specific data | |||
Extra map[string]interface{} | |||
} | |||
// BaseRenderData is the base type for templates. It should be extended with | |||
// new template-specific fields. | |||
// additional template-specific fields: | |||
// | |||
// type MyRenderData struct { | |||
// BaseRenderData | |||
// // add additional fields here | |||
// } | |||
type BaseRenderData struct { | |||
Global GlobalRenderData | |||
// Additional plugin-specific data | |||
GlobalData GlobalRenderData | |||
// additional plugin-specific data | |||
Extra map[string]interface{} | |||
} | |||
// Global implements RenderData. | |||
func (brd *BaseRenderData) Global() *GlobalRenderData { | |||
return &brd.GlobalData | |||
} | |||
// RenderData is implemented by template data structs. It can be used to inject | |||
// additional data to all templates. | |||
type RenderData interface { | |||
// GlobalData returns a pointer to the global render data. | |||
Global() *GlobalRenderData | |||
} | |||
// NewBaseRenderData initializes a new BaseRenderData. | |||
// | |||
// It can be used by routes to pre-fill the base data: | |||
// | |||
// type MyRenderData struct { | |||
// BaseRenderData | |||
// // add additional fields here | |||
// } | |||
// | |||
// data := &MyRenderData{ | |||
// BaseRenderData: *koushin.NewBaseRenderData(ctx), | |||
// // other fields... | |||
// } | |||
func NewBaseRenderData(ctx *Context) *BaseRenderData { | |||
global := GlobalRenderData{Extra: make(map[string]interface{})} | |||
@@ -41,8 +71,8 @@ func NewBaseRenderData(ctx *Context) *BaseRenderData { | |||
} | |||
return &BaseRenderData{ | |||
Global: global, | |||
Extra: make(map[string]interface{}), | |||
GlobalData: global, | |||
Extra: make(map[string]interface{}), | |||
} | |||
} | |||
@@ -57,7 +87,7 @@ func (r *renderer) Render(w io.Writer, name string, data interface{}, ectx echo. | |||
ctx := ectx.Get("context").(*Context) | |||
for _, plugin := range ctx.Server.Plugins { | |||
if err := plugin.Inject(name, data); err != nil { | |||
if err := plugin.Inject(name, data.(RenderData)); err != nil { | |||
return fmt.Errorf("failed to run plugin '%v': %v", plugin.Name(), err) | |||
} | |||
} | |||