Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a39fdb3

Browse files
committed
Added template read and population
Added controller.TemplateOut, revel.TemplateOutArgs
1 parent b1df5bf commit a39fdb3

File tree

3 files changed

+108
-54
lines changed

3 files changed

+108
-54
lines changed

controller.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ func (c *Controller) RenderTemplate(templatePath string) Result {
198198
}
199199
}
200200

201+
// TemplateOutput returns the result of the template rendered using the controllers ViewArgs.
202+
func (c *Controller) TemplateOutput(templatePath string) (data []byte,err error) {
203+
return TemplateOutputArgs(templatePath,c.ViewArgs)
204+
}
205+
201206
// RenderJSON uses encoding/json.Marshal to return JSON to the client.
202207
func (c *Controller) RenderJSON(o interface{}) Result {
203208
c.setStatusIfNil(http.StatusOK)

results.go

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -156,63 +156,20 @@ func (r *RenderTemplateResult) Apply(req *Request, resp *Response) {
156156
// error pages distorted by HTML already written)
157157
if chunked && !DevMode {
158158
resp.WriteHeader(http.StatusOK, "text/html; charset=utf-8")
159-
r.render(req, resp, out)
159+
if err := r.renderOutput(out); err !=nil {
160+
r.renderError(err,req,resp)
161+
}
160162
return
161163
}
162164

163165
// Render the template into a temporary buffer, to see if there was an error
164166
// rendering the template. If not, then copy it into the response buffer.
165167
// Otherwise, template render errors may result in unpredictable HTML (and
166168
// would carry a 200 status code)
167-
var b bytes.Buffer
168-
r.render(req, resp, &b)
169-
170-
// Trimming the HTML will do the following:
171-
// * Remove all leading & trailing whitespace on every line
172-
// * Remove all empty lines
173-
// * Attempt to keep formatting inside <pre></pre> tags
174-
//
175-
// This is safe unless white-space: pre; is used in css for formatting.
176-
// Since there is no way to detect that, you will have to keep trimming off in these cases.
177-
if Config.BoolDefault("results.trim.html", false) {
178-
var b2 bytes.Buffer
179-
// Allocate length of original buffer, so we can write everything without allocating again
180-
b2.Grow(b.Len())
181-
insidePre := false
182-
for {
183-
text, err := b.ReadString('\n')
184-
// Convert to lower case for finding <pre> tags.
185-
tl := strings.ToLower(text)
186-
if strings.Contains(tl, "<pre>") {
187-
insidePre = true
188-
}
189-
// Trim if not inside a <pre> statement
190-
if !insidePre {
191-
// Cut trailing/leading whitespace
192-
text = strings.Trim(text, " \t\r\n")
193-
if len(text) > 0 {
194-
if _, err = b2.WriteString(text); err != nil {
195-
resultsLog.Error("Apply: ", "error", err)
196-
}
197-
if _, err = b2.WriteString("\n"); err != nil {
198-
resultsLog.Error("Apply: ", "error", err)
199-
}
200-
}
201-
} else {
202-
if _, err = b2.WriteString(text); err != nil {
203-
resultsLog.Error("Apply: ", "error", err)
204-
}
205-
}
206-
if strings.Contains(tl, "</pre>") {
207-
insidePre = false
208-
}
209-
// We are finished
210-
if err != nil {
211-
break
212-
}
213-
}
214-
// Replace the buffer
215-
b = b2
169+
b, err := r.ToBytes()
170+
if err!=nil {
171+
r.renderError(err,req,resp)
172+
return
216173
}
217174

218175
if !chunked {
@@ -224,12 +181,85 @@ func (r *RenderTemplateResult) Apply(req *Request, resp *Response) {
224181
}
225182
}
226183

227-
func (r *RenderTemplateResult) render(req *Request, resp *Response, wr io.Writer) {
228-
err := r.Template.Render(wr, r.ViewArgs)
229-
if err == nil {
230-
return
184+
// Return a byte array and or an error object if the template failed to render
185+
func (r *RenderTemplateResult) ToBytes() (b *bytes.Buffer,err error) {
186+
defer func() {
187+
if rerr := recover(); rerr != nil {
188+
resultsLog.Error("ApplyBytes: panic recovery", "recover-error", rerr)
189+
err = fmt.Errorf("Template Execution Panic in %s:\n%s", r.Template.Name(), rerr)
190+
}
191+
}()
192+
b = &bytes.Buffer{}
193+
if err = r.renderOutput(b); err==nil {
194+
if Config.BoolDefault("results.trim.html", false) {
195+
b = r.compressHtml(b)
196+
}
197+
}
198+
return
199+
}
200+
201+
// Output the template to the writer, catch any panics and return as an error
202+
func (r *RenderTemplateResult) renderOutput(wr io.Writer) (err error) {
203+
defer func() {
204+
if rerr := recover(); rerr != nil {
205+
resultsLog.Error("ApplyBytes: panic recovery", "recover-error", rerr)
206+
err = fmt.Errorf("Template Execution Panic in %s:\n%s", r.Template.Name(), rerr)
207+
}
208+
}()
209+
err = r.Template.Render(wr, r.ViewArgs)
210+
return
211+
}
212+
213+
// Trimming the HTML will do the following:
214+
// * Remove all leading & trailing whitespace on every line
215+
// * Remove all empty lines
216+
// * Attempt to keep formatting inside <pre></pre> tags
217+
//
218+
// This is safe unless white-space: pre; is used in css for formatting.
219+
// Since there is no way to detect that, you will have to keep trimming off in these cases.
220+
func (r *RenderTemplateResult) compressHtml(b *bytes.Buffer) (b2 *bytes.Buffer) {
221+
222+
// Allocate length of original buffer, so we can write everything without allocating again
223+
b2.Grow(b.Len())
224+
insidePre := false
225+
for {
226+
text, err := b.ReadString('\n')
227+
// Convert to lower case for finding <pre> tags.
228+
tl := strings.ToLower(text)
229+
if strings.Contains(tl, "<pre>") {
230+
insidePre = true
231+
}
232+
// Trim if not inside a <pre> statement
233+
if !insidePre {
234+
// Cut trailing/leading whitespace
235+
text = strings.Trim(text, " \t\r\n")
236+
if len(text) > 0 {
237+
if _, err = b2.WriteString(text); err != nil {
238+
resultsLog.Error("Apply: ", "error", err)
239+
}
240+
if _, err = b2.WriteString("\n"); err != nil {
241+
resultsLog.Error("Apply: ", "error", err)
242+
}
243+
}
244+
} else {
245+
if _, err = b2.WriteString(text); err != nil {
246+
resultsLog.Error("Apply: ", "error", err)
247+
}
248+
}
249+
if strings.Contains(tl, "</pre>") {
250+
insidePre = false
251+
}
252+
// We are finished
253+
if err != nil {
254+
break
255+
}
231256
}
232257

258+
return
259+
}
260+
261+
// Render the error in the response
262+
func (r *RenderTemplateResult) renderError(err error,req *Request, resp *Response) {
233263
var templateContent []string
234264
templateName, line, description := ParseTemplateError(err)
235265
if templateName == "" {

template.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ var invalidSlugPattern = regexp.MustCompile(`[^a-z0-9 _-]`)
5050
var whiteSpacePattern = regexp.MustCompile(`\s+`)
5151
var templateLog = RevelLog.New("section", "template")
5252

53+
// TemplateOutputArgs returns the result of the template rendered using the passed in arguments.
54+
func TemplateOutputArgs(templatePath string, args map[string]interface{}) (data []byte,err error) {
55+
// Get the Template.
56+
lang, _ := args[CurrentLocaleViewArg].(string)
57+
template, err := MainTemplateLoader.TemplateLang(templatePath, lang)
58+
if err != nil {
59+
return nil, err
60+
}
61+
tr := &RenderTemplateResult{
62+
Template: template,
63+
ViewArgs: args,
64+
}
65+
b,err := tr.ToBytes()
66+
if err!=nil {
67+
return nil,err
68+
}
69+
return b.Bytes(), nil
70+
}
71+
5372
func NewTemplateLoader(paths []string) *TemplateLoader {
5473
loader := &TemplateLoader{
5574
paths: paths,

0 commit comments

Comments
 (0)