File: template_engine.go

package info (click to toggle)
golang-github-revel-revel 1.0.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,240 kB
  • sloc: xml: 7; makefile: 7; javascript: 1
file content (118 lines) | stat: -rw-r--r-- 4,167 bytes parent folder | download | duplicates (2)
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
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 Event, 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)
	}
	templateLog.Debug("Registered template engine loaded", "name", 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())
	}

	templateLog.Debug("CreateTemplateEngine: init templates", "name", 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
}