-
Notifications
You must be signed in to change notification settings - Fork 3
/
template.go
108 lines (95 loc) · 2.34 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
package template
import (
"io"
"io/ioutil"
"os"
"path/filepath"
"github.com/gobwas/glob"
"github.com/sirupsen/logrus"
)
// Template represents a template that can be rendered using provided values.
type Template interface {
Render(out io.Writer, values Scope) error
RenderString(values Scope) (string, error)
}
// Load loads template from the path.
func Load(path string) (Template, error) {
source, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
return Parse(string(source))
}
// Parse parses template in the source string.
func Parse(source string) (Template, error) {
return parsePlush(source)
}
// RenderAll renders all templates in the path (directory or a single file) to an output path (directory or file) using the provided value scope.
func RenderAll(templatePath string, excludedPaths []string, outputPath string, values Scope) error {
return filepath.Walk(templatePath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
relPath, err := filepath.Rel(templatePath, path)
if err != nil {
return err
}
if relPath == "." {
// templatePath is a path to a file.
relPath = filepath.Base(templatePath)
}
if ok, err := pathMatches(excludedPaths, relPath); ok || err != nil {
return err // err is nil if ok
}
logrus.Println("Rendering", relPath)
filePath, err := renderString(filepath.Join(outputPath, relPath), values)
if err != nil {
return err
}
return renderFile(path, filePath, values)
})
}
func renderFile(templatePath, outputPath string, values Scope) error {
t, err := Load(templatePath)
if err != nil {
return err
}
err = os.MkdirAll(filepath.Dir(outputPath), 0700)
if err != nil {
return err
}
out, err := os.Create(outputPath)
if err != nil {
return err
}
defer func() {
_ = out.Close()
}()
return t.Render(out, values)
}
func renderString(templateSource string, values Scope) (string, error) {
t, err := Parse(templateSource)
if err != nil {
return "", err
}
str, err := t.RenderString(values)
if err != nil {
return "", err
}
return str, nil
}
func pathMatches(patterns []string, path string) (bool, error) {
for _, pattern := range patterns {
p, err := glob.Compile(pattern)
if err != nil {
return false, err
}
if p.Match(path) {
return true, nil
}
}
return false, nil
}