forked from kabukky/journey
-
Notifications
You must be signed in to change notification settings - Fork 0
/
templates.go
158 lines (147 loc) · 4.97 KB
/
templates.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package templates
import (
"bytes"
"errors"
"github.com/kabukky/journey/database"
"github.com/kabukky/journey/structure"
"github.com/kabukky/journey/structure/methods"
"net/http"
"sync"
)
type Templates struct {
sync.RWMutex
m map[string]*Helper
}
func newTemplates() *Templates { return &Templates{m: make(map[string]*Helper)} }
// Global compiled templates - thread safe and accessible from all packages
var compiledTemplates = newTemplates()
func ShowPostTemplate(writer http.ResponseWriter, slug string) error {
compiledTemplates.RLock()
defer compiledTemplates.RUnlock()
blog, err := methods.GenerateBlog()
if err != nil {
return err
}
post, err := database.RetrievePostBySlug(slug)
if err != nil {
return err
} else if !post.IsPublished { // Make sure the post is published before rendering it
return errors.New("Post not published.")
}
requestData := structure.RequestData{Posts: make([]structure.Post, 1), Blog: blog, CurrentTemplate: 1} // CurrentTemplate = post
requestData.Posts[0] = *post
// If the post is a page and the page template is available, use the page template
if post.IsPage {
if template, ok := compiledTemplates.m["page"]; ok {
_, err = writer.Write(executeHelper(template, &requestData, 1)) // context = post
return err
}
}
_, err = writer.Write(executeHelper(compiledTemplates.m["post"], &requestData, 1)) // context = post
return err
}
func ShowAuthorTemplate(writer http.ResponseWriter, slug string, page int) error {
compiledTemplates.RLock()
defer compiledTemplates.RUnlock()
postIndex := int64(page - 1)
if postIndex < 0 {
postIndex = 0
}
blog, err := methods.GenerateBlog()
if err != nil {
return err
}
author, err := database.RetrieveUserBySlug(slug)
if err != nil {
return err
}
posts, err := database.RetrievePostsByUser(author.Id, blog.PostsPerPage, (blog.PostsPerPage * postIndex))
if err != nil {
return err
}
requestData := structure.RequestData{Posts: posts, Blog: blog, CurrentIndexPage: page, CurrentTemplate: 3} // CurrentTemplate = author
if template, ok := compiledTemplates.m["author"]; ok {
_, err = writer.Write(executeHelper(template, &requestData, 0)) // context = index
} else {
_, err = writer.Write(executeHelper(compiledTemplates.m["index"], &requestData, 0)) // context = index
}
return err
}
func ShowTagTemplate(writer http.ResponseWriter, slug string, page int) error {
compiledTemplates.RLock()
defer compiledTemplates.RUnlock()
postIndex := int64(page - 1)
if postIndex < 0 {
postIndex = 0
}
blog, err := methods.GenerateBlog()
if err != nil {
return err
}
tag, err := database.RetrieveTagBySlug(slug)
if err != nil {
return err
}
posts, err := database.RetrievePostsByTag(tag.Id, blog.PostsPerPage, (blog.PostsPerPage * postIndex))
if err != nil {
return err
}
requestData := structure.RequestData{Posts: posts, Blog: blog, CurrentIndexPage: page, CurrentTag: tag, CurrentTemplate: 2} // CurrentTemplate = tag
if template, ok := compiledTemplates.m["tag"]; ok {
_, err = writer.Write(executeHelper(template, &requestData, 0)) // context = index
} else {
_, err = writer.Write(executeHelper(compiledTemplates.m["index"], &requestData, 0)) // context = index
}
return err
}
func ShowIndexTemplate(writer http.ResponseWriter, page int) error {
compiledTemplates.RLock()
defer compiledTemplates.RUnlock()
postIndex := int64(page - 1)
if postIndex < 0 {
postIndex = 0
}
blog, err := methods.GenerateBlog()
if err != nil {
return err
}
posts, err := database.RetrievePostsForIndex(blog.PostsPerPage, (blog.PostsPerPage * postIndex))
if err != nil {
return err
}
requestData := structure.RequestData{Posts: posts, Blog: blog, CurrentIndexPage: page, CurrentTemplate: 0} // CurrentTemplate = index
_, err = writer.Write(executeHelper(compiledTemplates.m["index"], &requestData, 0)) // context = index
return err
}
func executeHelper(helper *Helper, values *structure.RequestData, context int) []byte {
// Set context and set it back to the old value once fuction returns
defer setCurrentHelperContext(values, values.CurrentHelperContext)
values.CurrentHelperContext = context
block := helper.Block
indexTracker := 0
extended := false
var extendHelper *Helper
for index, child := range helper.Children {
// Handle extend helper
if index == 0 && child.Name == "!<" {
extended = true
extendHelper = compiledTemplates.m[string(child.Function(&child, values))]
} else {
var buffer bytes.Buffer
toAdd := child.Function(&child, values)
buffer.Write(block[:child.Position+indexTracker])
buffer.Write(toAdd)
buffer.Write(block[child.Position+indexTracker:])
block = buffer.Bytes()
indexTracker += len(toAdd)
}
}
if extended {
extendHelper.BodyHelper.Block = block
return executeHelper(extendHelper, values, values.CurrentHelperContext) // TODO: not sure if context = values.CurrentHelperContext is right.
}
return block
}
func setCurrentHelperContext(values *structure.RequestData, context int) {
values.CurrentHelperContext = context
}