forked from revel/revel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template_engine.go
117 lines (102 loc) · 3.97 KB
/
template_engine.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
package revel
import (
"bufio"
"bytes"
"errors"
"fmt"
"path/filepath"
"strings"
)
type TemplateEngine interface {
// prase template string and add template to the set.
ParseAndAdd(basePath *TemplateView) error
// returns Template corresponding to the given templateName, or nil
Lookup(templateName string) Template
// Fired by the template loader when events occur
Event(event int, arg interface{})
// returns true if this engine should be used to parse the file specified in baseTemplate
Handles(templateView *TemplateView) bool
// returns the name of the engine
Name() string
}
// The template view information
type TemplateView struct {
TemplateName string // The name of the view
FilePath string // The file path (view relative)
BasePath string // The file system base path
FileBytes []byte // The file loaded
EngineType string // The name of the engine used to render the view
}
var templateLoaderMap = map[string]func(loader *TemplateLoader) (TemplateEngine, error){}
// Allow for templates to be registered during init but not initialized until application has been started
func RegisterTemplateLoader(key string, loader func(loader *TemplateLoader) (TemplateEngine, error)) (err error) {
if _, found := templateLoaderMap[key]; found {
err = fmt.Errorf("Template loader %s already exists", key)
}
templateLoaderMap[key] = loader
return
}
// Sets the template name from Config
// Sets the template API methods for parsing and storing templates before rendering
func (loader *TemplateLoader) CreateTemplateEngine(templateEngineName string) (TemplateEngine, error) {
if "" == templateEngineName {
templateEngineName = GO_TEMPLATE
}
factory := templateLoaderMap[templateEngineName]
if nil == factory {
fmt.Printf("registered factories %#v\n %s \n", templateLoaderMap, templateEngineName)
return nil, errors.New("Unknown template engine name - " + templateEngineName + ".")
}
templateEngine, err := factory(loader)
if nil != err {
return nil, errors.New("Failed to init template engine (" + templateEngineName + "), " + err.Error())
}
INFO.Println("init templates:", templateEngineName)
return templateEngine, nil
}
// Passing in a comma delimited list of engine names to be used with this loader to parse the template files
func (loader *TemplateLoader) initializeEngines(runtimeLoader *templateRuntime, templateEngineNameList string) (err *Error) {
// Walk through the template loader's paths and build up a template set.
if templateEngineNameList == "" {
templateEngineNameList = GO_TEMPLATE
}
runtimeLoader.templatesAndEngineList = []TemplateEngine{}
for _, engine := range strings.Split(templateEngineNameList, ",") {
engine := strings.TrimSpace(strings.ToLower(engine))
if templateLoader, err := loader.CreateTemplateEngine(engine); err != nil {
runtimeLoader.compileError = &Error{
Title: "Panic (Template Loader)",
Description: err.Error(),
}
return runtimeLoader.compileError
} else {
// Always assign a default engine, switch it if it is specified in the config
runtimeLoader.templatesAndEngineList = append(runtimeLoader.templatesAndEngineList, templateLoader)
}
}
return
}
func EngineHandles(engine TemplateEngine, templateView *TemplateView) bool {
if line, _, e := bufio.NewReader(bytes.NewBuffer(templateView.FileBytes)).ReadLine(); e == nil && string(line[:3]) == "#! " {
// Extract the shebang and look at the rest of the line
// #! pong2
// #! go
templateType := strings.TrimSpace(string(line[2:]))
if engine.Name() == templateType {
// Advance the read file bytes so it does not include the shebang
templateView.FileBytes = templateView.FileBytes[len(line)+1:]
templateView.EngineType = templateType
return true
}
}
filename := filepath.Base(templateView.FilePath)
bits := strings.Split(filename, ".")
if len(bits) > 2 {
templateType := strings.TrimSpace(bits[len(bits)-2])
if engine.Name() == templateType {
templateView.EngineType = templateType
return true
}
}
return false
}