12 type TemplateEngine interface {
13 // prase template string and add template to the set.
14 ParseAndAdd(basePath *TemplateView) error
16 // returns Template corresponding to the given templateName, or nil
17 Lookup(templateName string) Template
19 // Fired by the template loader when events occur
20 Event(event Event, arg interface{})
22 // returns true if this engine should be used to parse the file specified in baseTemplate
23 Handles(templateView *TemplateView) bool
25 // returns the name of the engine
29 // The template view information
30 type TemplateView struct {
31 TemplateName string // The name of the view
32 FilePath string // The file path (view relative)
33 BasePath string // The file system base path
34 FileBytes []byte // The file loaded
35 EngineType string // The name of the engine used to render the view
38 var templateLoaderMap = map[string]func(loader *TemplateLoader) (TemplateEngine, error){}
40 // Allow for templates to be registered during init but not initialized until application has been started
41 func RegisterTemplateLoader(key string, loader func(loader *TemplateLoader) (TemplateEngine, error)) (err error) {
42 if _, found := templateLoaderMap[key]; found {
43 err = fmt.Errorf("Template loader %s already exists", key)
45 templateLog.Debug("Registered template engine loaded", "name", key)
46 templateLoaderMap[key] = loader
50 // Sets the template name from Config
51 // Sets the template API methods for parsing and storing templates before rendering
52 func (loader *TemplateLoader) CreateTemplateEngine(templateEngineName string) (TemplateEngine, error) {
53 if "" == templateEngineName {
54 templateEngineName = GO_TEMPLATE
56 factory := templateLoaderMap[templateEngineName]
58 fmt.Printf("registered factories %#v\n %s \n", templateLoaderMap, templateEngineName)
59 return nil, errors.New("Unknown template engine name - " + templateEngineName + ".")
61 templateEngine, err := factory(loader)
63 return nil, errors.New("Failed to init template engine (" + templateEngineName + "), " + err.Error())
66 templateLog.Debug("CreateTemplateEngine: init templates", "name", templateEngineName)
67 return templateEngine, nil
70 // Passing in a comma delimited list of engine names to be used with this loader to parse the template files
71 func (loader *TemplateLoader) initializeEngines(runtimeLoader *templateRuntime, templateEngineNameList string) (err *Error) {
72 // Walk through the template loader's paths and build up a template set.
73 if templateEngineNameList == "" {
74 templateEngineNameList = GO_TEMPLATE
77 runtimeLoader.templatesAndEngineList = []TemplateEngine{}
78 for _, engine := range strings.Split(templateEngineNameList, ",") {
79 engine := strings.TrimSpace(strings.ToLower(engine))
81 if templateLoader, err := loader.CreateTemplateEngine(engine); err != nil {
82 runtimeLoader.compileError = &Error{
83 Title: "Panic (Template Loader)",
84 Description: err.Error(),
86 return runtimeLoader.compileError
88 // Always assign a default engine, switch it if it is specified in the config
89 runtimeLoader.templatesAndEngineList = append(runtimeLoader.templatesAndEngineList, templateLoader)
95 func EngineHandles(engine TemplateEngine, templateView *TemplateView) bool {
96 if line, _, e := bufio.NewReader(bytes.NewBuffer(templateView.FileBytes)).ReadLine(); e == nil && string(line[:3]) == "#! " {
97 // Extract the shebang and look at the rest of the line
100 templateType := strings.TrimSpace(string(line[2:]))
101 if engine.Name() == templateType {
102 // Advance the read file bytes so it does not include the shebang
103 templateView.FileBytes = templateView.FileBytes[len(line)+1:]
104 templateView.EngineType = templateType
108 filename := filepath.Base(templateView.FilePath)
109 bits := strings.Split(filename, ".")
111 templateType := strings.TrimSpace(bits[len(bits)-2])
112 if engine.Name() == templateType {
113 templateView.EngineType = templateType