--- /dev/null
+package revel
+
+import (
+ "html/template"
+ "io"
+ "log"
+ "strings"
+)
+
+const GO_TEMPLATE = "go"
+
+// Called on startup, initialized when the REVEL_BEFORE_MODULES_LOADED is called
+func init() {
+ AddInitEventHandler(func(typeOf Event, value interface{}) (responseOf EventResponse) {
+ if typeOf == REVEL_BEFORE_MODULES_LOADED {
+ RegisterTemplateLoader(GO_TEMPLATE, func(loader *TemplateLoader) (TemplateEngine, error) {
+ // Set the template delimiters for the project if present, then split into left
+ // and right delimiters around a space character
+
+ TemplateDelims := Config.StringDefault("template.go.delimiters", "")
+ var splitDelims []string
+ if TemplateDelims != "" {
+ splitDelims = strings.Split(TemplateDelims, " ")
+ if len(splitDelims) != 2 {
+ log.Fatalln("app.conf: Incorrect format for template.delimiters")
+ }
+ }
+
+ return &GoEngine{
+ loader: loader,
+ templateSet: template.New("__root__").Funcs(TemplateFuncs),
+ templatesByName: map[string]*GoTemplate{},
+ splitDelims: splitDelims,
+ }, nil
+ })
+ }
+ return
+ })
+}
+
+// Adapter for Go Templates.
+type GoTemplate struct {
+ *template.Template
+ engine *GoEngine
+ *TemplateView
+}
+
+// return a 'revel.Template' from Go's template.
+func (gotmpl GoTemplate) Render(wr io.Writer, arg interface{}) error {
+ return gotmpl.Execute(wr, arg)
+}
+
+// The main template engine for Go
+type GoEngine struct {
+ // The template loader
+ loader *TemplateLoader
+ // THe current template set
+ templateSet *template.Template
+ // A map of templates by name
+ templatesByName map[string]*GoTemplate
+ // The delimiter that is used to indicate template code, defaults to {{
+ splitDelims []string
+ // True if map is case insensitive
+ CaseInsensitive bool
+}
+
+// Convert the path to lower case if needed
+func (i *GoEngine) ConvertPath(path string) string {
+ if i.CaseInsensitive {
+ return strings.ToLower(path)
+ }
+ return path
+}
+
+// Returns true if this engine can handle the response
+func (i *GoEngine) Handles(templateView *TemplateView) bool {
+ return EngineHandles(i, templateView)
+}
+
+// Parses the template vide and adds it to the template set
+func (engine *GoEngine) ParseAndAdd(baseTemplate *TemplateView) error {
+ // If alternate delimiters set for the project, change them for this set
+ if engine.splitDelims != nil && strings.Index(baseTemplate.Location(), ViewsPath) > -1 {
+ engine.templateSet.Delims(engine.splitDelims[0], engine.splitDelims[1])
+ } else {
+ // Reset to default otherwise
+ engine.templateSet.Delims("", "")
+ }
+ templateSource := string(baseTemplate.FileBytes)
+ templateName := engine.ConvertPath(baseTemplate.TemplateName)
+ tpl, err := engine.templateSet.New(baseTemplate.TemplateName).Parse(templateSource)
+ if nil != err {
+ _, line, description := ParseTemplateError(err)
+ return &Error{
+ Title: "Template Compilation Error",
+ Path: baseTemplate.TemplateName,
+ Description: description,
+ Line: line,
+ SourceLines: strings.Split(templateSource, "\n"),
+ }
+ }
+ engine.templatesByName[templateName] = &GoTemplate{Template: tpl, engine: engine, TemplateView: baseTemplate}
+ return nil
+}
+
+// Lookups the template name, to see if it is contained in this engine
+func (engine *GoEngine) Lookup(templateName string) Template {
+ // Case-insensitive matching of template file name
+ if tpl, found := engine.templatesByName[engine.ConvertPath(templateName)]; found {
+ return tpl
+ }
+ return nil
+}
+
+// Return the engine name
+func (engine *GoEngine) Name() string {
+ return GO_TEMPLATE
+}
+
+// An event listener to listen for Revel INIT events
+func (engine *GoEngine) Event(action Event, i interface{}) {
+ if action == TEMPLATE_REFRESH_REQUESTED {
+ // At this point all the templates have been passed into the
+ engine.templatesByName = map[string]*GoTemplate{}
+ engine.templateSet = template.New("__root__").Funcs(TemplateFuncs)
+ // Check to see what should be used for case sensitivity
+ engine.CaseInsensitive = Config.BoolDefault("go.template.caseinsensitive", true)
+ }
+}