forked from ungerik/go-start
/
template.go
123 lines (105 loc) · 3.13 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package view
import (
"github.com/ungerik/go-start/errs"
"github.com/ungerik/go-start/templatesystem"
"path"
)
type GetTemplateContextFunc func(ctx *Context) (context interface{}, err error)
func NewTemplate(filename string, getContext GetTemplateContextFunc) *Template {
return &Template{Filename: filename, GetContext: getContext}
}
func NewHTML5BoilerplateCSSTemplate(getContext GetTemplateContextFunc, filenames ...string) Views {
views := make(Views, len(filenames)+2)
views[0] = &StaticFile{Filename: "css/html5boilerplate/normalize.css"}
for i := range filenames {
views[i+1] = NewTemplate(filenames[i], getContext)
}
views[len(views)-1] = &StaticFile{Filename: "css/html5boilerplate/poststyle.css"}
return views
}
func TemplateContext(context interface{}) GetTemplateContextFunc {
return func(ctx *Context) (interface{}, error) {
return context, nil
}
}
///////////////////////////////////////////////////////////////////////////////
// Template
type Template struct {
ViewBase
Filename string // Will set file extension at ContentType
Text string
ContentTypeExt string
GetContext GetTemplateContextFunc
TemplateSystem templatesystem.Implementation // If nil, self.App.Config.TemplateSystem is used
template templatesystem.Template
modifiedTime int64
}
func (self *Template) parseTemplate() (templ templatesystem.Template, err error) {
templateSystem := self.TemplateSystem
if templateSystem == nil {
templateSystem = Config.TemplateSystem
}
if self.Filename == "" {
self.modifiedTime = 0
return templateSystem.ParseString(self.Text, "")
}
filePath, found, modified := FindTemplateFile(self.Filename)
if !found {
return nil, errs.Format("Template file not found: %s", self.Filename)
}
self.modifiedTime = modified
if self.ContentTypeExt == "" {
self.ContentTypeExt = path.Ext(filePath)
}
return templateSystem.ParseFile(filePath)
}
func (self *Template) Render(ctx *Context) (err error) {
if self.template != nil && self.Filename != "" {
_, found, modified := FindTemplateFile(self.Filename)
if !found {
return errs.Format("Template file not found: %s", self.Filename)
}
if modified > self.modifiedTime {
self.template = nil
self.ContentTypeExt = ""
}
}
if self.template == nil {
self.template, err = self.parseTemplate()
if err != nil {
return err
}
}
if self.ContentTypeExt != "" {
ctx.Response.ContentTypeByExt(self.ContentTypeExt)
}
var context interface{}
if self.GetContext != nil {
context, err = self.GetContext(ctx)
if err != nil {
return err
}
}
// todo: how to add config data to context if it's not a slice?
// map[string][]string{"args": ctx.Request.URLArgs}
// Config, context.Web
return self.template.Render(ctx.Response, context)
}
//func (self *Template) SetFilename(filename string) {
// self.Filename = filename
// self.Text = ""
// self.template = nil
// ViewChanged(self)
//}
//
//func (self *Template) SetText(text string) {
// self.Filename = ""
// self.Text = text
// self.template = nil
// ViewChanged(self)
//}
//
//func (self *Template) SetContext(context interface{}) {
// self.Context = context
// ViewChanged(self)
//}