-
Notifications
You must be signed in to change notification settings - Fork 1
/
views.go
125 lines (110 loc) · 3.18 KB
/
views.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
118
119
120
121
122
123
124
125
// Copyright (C) 2014-2017 Miquel Sabaté Solà <mikisabate@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package lib
import (
"bytes"
"fmt"
"html/template"
"io/ioutil"
"log"
"net/http"
"path"
"strings"
"time"
)
var (
// ViewsDir is the directory where all the views are being stored.
ViewsDir = "views"
)
const (
// The path to the layout file.
layout = "application/layout"
// The extension of views.
viewsExt = "tpl"
)
// ViewData holds all the data that can be passed to a view.
type ViewData struct {
// The name of the javascript file to be used.
JS string
// The error message.
Error string
// Whether we are on print mode or not.
Print bool
}
// DefaultViewData returns a ViewData object with the assets prefix set as
// expected.
func DefaultViewData() *ViewData {
return &ViewData{}
}
// Returns the path to be used to open the view with the given name.
func view(name string) string {
return path.Join(ViewsDir, name+"."+viewsExt)
}
// Render the view with the given name after evaluating the passed data. The
// rendered view will be written to the given writer.
func Render(res http.ResponseWriter, name string, data interface{}) {
b, e := ioutil.ReadFile(view(layout))
if e != nil {
log.Print("Could not read layout file")
return
}
t, e := template.New("l").Funcs(layoutHelpers(name, data)).Parse(string(b))
if e != nil {
panic("Could not parse layout file")
}
if err := t.Execute(res, data); err != nil {
log.Printf("Could not render template %v: %v", name, err)
}
}
// Returns all the helpers used by the layout template. Right now only the
// "yield" helpers has been implemented.
func layoutHelpers(name string, data interface{}) template.FuncMap {
return template.FuncMap{
"yield": func() template.HTML {
var buffer bytes.Buffer
b, e := ioutil.ReadFile(view(name))
if e != nil {
log.Printf("Could not read: %v => %v", name, e)
return template.HTML("")
}
t := template.New(name).Funcs(viewHelpers())
t, e = t.Parse(string(b))
if e != nil {
log.Printf("Could not parse: %v => %v", name, e)
return template.HTML("")
}
if err := t.Execute(&buffer, data); err != nil {
log.Printf("Could not yield template %v: %v", name, err)
}
return template.HTML(buffer.String())
},
"view": func() template.HTML {
s := strings.SplitN(name, "/", 2)
if len(s) == 2 {
return template.HTML(s[0] + "_" + s[1])
}
return template.HTML("")
},
}
}
// Returns all the helpers available to any view. We have the following
// helpers: fmtDate and inc. The inc helper just increases the given integer
// value by one. The fmtDate helper executes the fmtDate function.
func viewHelpers() template.FuncMap {
return template.FuncMap{
"fmtDate": fmtDate,
"inc": func(n int) int {
return n + 1
},
"noescape": func(str string) template.HTML {
return template.HTML(str)
},
}
}
// Returns a string with the given time formatted as expected by the view.
func fmtDate(t time.Time) string {
return fmt.Sprintf("%02d/%02d/%04d", t.Day(), t.Month(), t.Year())
}