From 4f5ed85c1914690e1023f1ae308c9583069f4d57 Mon Sep 17 00:00:00 2001
From: Steve Manuel
Date: Sun, 25 Dec 2016 11:59:33 -0800
Subject: adding error handling and less alloc happy buffer writes in editor
code
---
management/editor/dom.go | 236 ++++++++++++++++++++++++++++++++++-------
management/editor/editor.go | 54 ++++++++--
management/editor/repeaters.go | 66 ++++++++++--
3 files changed, 297 insertions(+), 59 deletions(-)
diff --git a/management/editor/dom.go b/management/editor/dom.go
index 7fa2b54..41aafa7 100644
--- a/management/editor/dom.go
+++ b/management/editor/dom.go
@@ -3,6 +3,7 @@ package editor
import (
"bytes"
"html"
+ "log"
"strings"
)
@@ -29,108 +30,265 @@ func newElement(tagName, label, fieldName string, p interface{}, attrs map[strin
// domElementSelfClose is a special DOM element which is parsed as a
// self-closing tag and thus needs to be created differently
func domElementSelfClose(e *element) []byte {
- e.viewBuf.Write([]byte(``))
return e.viewBuf.Bytes()
}
// domElementCheckbox is a special DOM element which is parsed as a
// checkbox input tag and thus needs to be created differently
func domElementCheckbox(e *element) []byte {
- e.viewBuf.Write([]byte(``))
- e.viewBuf.Write([]byte(`<` + e.tagName + ` `))
+ _, err := e.viewBuf.WriteString(`
`)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
+
+ _, err = e.viewBuf.WriteString(`<` + e.tagName + ` `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
for attr, value := range e.attrs {
- e.viewBuf.Write([]byte(attr + `="` + value + `" `))
+ _, err := e.viewBuf.WriteString(attr + `="` + value + `" `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
}
- e.viewBuf.Write([]byte(` name="` + e.name + `"`))
- e.viewBuf.Write([]byte(` /> `))
+ _, err = e.viewBuf.WriteString(` name="` + e.name + `" />`)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
+
if e.label != "" {
- e.viewBuf.Write([]byte(`` + e.label + ` `))
+ _, err = e.viewBuf.WriteString(
+ `` +
+ e.label + ` `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
}
- e.viewBuf.Write([]byte(`
`))
+
+ _, err = e.viewBuf.WriteString(`
`)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementCheckbox")
+ return nil
+ }
+
return e.viewBuf.Bytes()
}
// domElement creates a DOM element
func domElement(e *element) []byte {
- e.viewBuf.Write([]byte(``))
return e.viewBuf.Bytes()
}
func domElementWithChildrenSelect(e *element, children []*element) []byte {
- e.viewBuf.Write([]byte(``))
return e.viewBuf.Bytes()
}
func domElementWithChildrenCheckbox(e *element, children []*element) []byte {
- e.viewBuf.Write([]byte(`<` + e.tagName + ` `))
+ _, err := e.viewBuf.WriteString(`<` + e.tagName + ` `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
for attr, value := range e.attrs {
- e.viewBuf.Write([]byte(attr + `="` + value + `" `))
+ _, err = e.viewBuf.WriteString(attr + `="` + value + `" `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
}
- e.viewBuf.Write([]byte(` >`))
+ _, err = e.viewBuf.WriteString(` >`)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
if e.label != "" {
- e.viewBuf.Write([]byte(`` + e.label + ` `))
+ _, err = e.viewBuf.WriteString(`` + e.label + ` `)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
}
// loop over children and create domElement for each child
for _, child := range children {
- e.viewBuf.Write(domElementCheckbox(child))
+ _, err = e.viewBuf.Write(domElementCheckbox(child))
+ if err != nil {
+ log.Println("Error writing HTML domElementCheckbox to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
}
- e.viewBuf.Write([]byte(`` + e.tagName + `>
`))
+ _, err = e.viewBuf.WriteString(`` + e.tagName + `>
`)
+ if err != nil {
+ log.Println("Error writing HTML string to buffer: domElementWithChildrenCheckbox")
+ return nil
+ }
return e.viewBuf.Bytes()
}
diff --git a/management/editor/editor.go b/management/editor/editor.go
index 7194c27..511edb2 100644
--- a/management/editor/editor.go
+++ b/management/editor/editor.go
@@ -4,6 +4,7 @@ package editor
import (
"bytes"
+ "log"
"net/http"
)
@@ -38,16 +39,28 @@ func Form(post Editable, fields ...Field) ([]byte, error) {
editor := post.Editor()
editor.ViewBuf = &bytes.Buffer{}
- editor.ViewBuf.Write([]byte(``))
+ _, err := editor.ViewBuf.WriteString(``)
+ if err != nil {
+ log.Println("Error writing HTML string to editor Form buffer")
+ return nil, err
+ }
for _, f := range fields {
addFieldToEditorView(editor, f)
}
- editor.ViewBuf.Write([]byte(` `))
+ _, err = editor.ViewBuf.WriteString(``)
+ if err != nil {
+ log.Println("Error writing HTML string to editor Form buffer")
+ return nil, err
+ }
// content items with Item embedded have some default fields we need to render
- editor.ViewBuf.Write([]byte(``))
+ _, err = editor.ViewBuf.WriteString(` `)
+ if err != nil {
+ log.Println("Error writing HTML string to editor Form buffer")
+ return nil, err
+ }
publishTime := `
@@ -98,9 +111,16 @@ func Form(post Editable, fields ...Field) ([]byte, error) {
`
- editor.ViewBuf.Write([]byte(publishTime))
+ _, err = editor.ViewBuf.WriteString(publishTime)
+ if err != nil {
+ log.Println("Error writing HTML string to editor Form buffer")
+ return nil, err
+ }
- addPostDefaultFieldsToEditorView(post, editor)
+ err = addPostDefaultFieldsToEditorView(post, editor)
+ if err != nil {
+ return nil, err
+ }
submit := `
@@ -186,16 +206,26 @@ func Form(post Editable, fields ...Field) ([]byte, error) {
});
`
- editor.ViewBuf.Write([]byte(submit + script + `
`))
+ _, err = editor.ViewBuf.WriteString(submit + script + `
`)
+ if err != nil {
+ log.Println("Error writing HTML string to editor Form buffer")
+ return nil, err
+ }
return editor.ViewBuf.Bytes(), nil
}
-func addFieldToEditorView(e *Editor, f Field) {
- e.ViewBuf.Write(f.View)
+func addFieldToEditorView(e *Editor, f Field) error {
+ _, err := e.ViewBuf.Write(f.View)
+ if err != nil {
+ log.Println("Error writing field view to editor view buffer")
+ return err
+ }
+
+ return nil
}
-func addPostDefaultFieldsToEditorView(p Editable, e *Editor) {
+func addPostDefaultFieldsToEditorView(p Editable, e *Editor) error {
defaults := []Field{
Field{
View: Input("Slug", p, map[string]string{
@@ -220,7 +250,11 @@ func addPostDefaultFieldsToEditorView(p Editable, e *Editor) {
}
for _, f := range defaults {
- addFieldToEditorView(e, f)
+ err := addFieldToEditorView(e, f)
+ if err != nil {
+ return err
+ }
}
+ return nil
}
diff --git a/management/editor/repeaters.go b/management/editor/repeaters.go
index f9a289c..4a597c5 100644
--- a/management/editor/repeaters.go
+++ b/management/editor/repeaters.go
@@ -3,6 +3,7 @@ package editor
import (
"bytes"
"fmt"
+ "log"
"strings"
)
@@ -39,7 +40,12 @@ func InputRepeater(fieldName string, p interface{}, attrs map[string]string) []b
scope := tagNameFromStructField(fieldName, p)
html := bytes.Buffer{}
- html.WriteString(``)
+ _, err := html.WriteString(``)
+ if err != nil {
+ log.Println("Error writing HTML string to InputRepeater buffer")
+ return nil
+ }
+
for i, val := range vals {
el := &element{
tagName: "input",
@@ -54,9 +60,17 @@ func InputRepeater(fieldName string, p interface{}, attrs map[string]string) []b
el.label = attrs["label"]
}
- html.Write(domElementSelfClose(el))
+ _, err := html.Write(domElementSelfClose(el))
+ if err != nil {
+ log.Println("Error writing domElementSelfClose to InputRepeater buffer")
+ return nil
+ }
+ }
+ _, err := html.WriteString(` `)
+ if err != nil {
+ log.Println("Error writing HTML string to InputRepeater buffer")
+ return nil
}
- html.WriteString(` `)
return append(html.Bytes(), RepeatController(fieldName, p, "input", ".input-field")...)
}
@@ -72,7 +86,11 @@ func SelectRepeater(fieldName string, p interface{}, attrs, options map[string]s
// {map value}
scope := tagNameFromStructField(fieldName, p)
html := bytes.Buffer{}
- html.WriteString(``)
+ _, err := html.WriteString(``)
+ if err != nil {
+ log.Println("Error writing HTML string to SelectRepeater buffer")
+ return nil
+ }
// find the field values in p to determine if an option is pre-selected
fieldVals := valueFromStructField(fieldName, p)
@@ -131,11 +149,20 @@ func SelectRepeater(fieldName string, p interface{}, attrs, options map[string]s
opts = append(opts, opt)
}
- html.Write(domElementWithChildrenSelect(sel, opts))
+ _, err := html.Write(domElementWithChildrenSelect(sel, opts))
+ if err != nil {
+ log.Println("Error writing domElementWithChildrenSelect to SelectRepeater buffer")
+ return nil
+ }
}
}
- html.WriteString(` `)
+ _, err = html.WriteString(` `)
+ if err != nil {
+ log.Println("Error writing HTML string to SelectRepeater buffer")
+ return nil
+ }
+
return append(html.Bytes(), RepeatController(fieldName, p, "select", ".input-field")...)
}
@@ -227,14 +254,33 @@ func FileRepeater(fieldName string, p interface{}, attrs map[string]string) []by
name := tagNameFromStructField(fieldName, p)
html := bytes.Buffer{}
- html.WriteString(``)
+ _, err := html.WriteString(``)
+ if err != nil {
+ log.Println("Error writing HTML string to FileRepeater buffer")
+ return nil
+ }
+
for i, val := range vals {
className := fmt.Sprintf("%s-%d", name, i)
nameidx := tagNameFromStructFieldMulti(fieldName, i, p)
- html.WriteString(fmt.Sprintf(tmpl, nameidx, addLabelFirst(i, attrs["label"]), val, className, fieldName))
- html.WriteString(fmt.Sprintf(script, nameidx, className))
+
+ _, err := html.WriteString(fmt.Sprintf(tmpl, nameidx, addLabelFirst(i, attrs["label"]), val, className, fieldName))
+ if err != nil {
+ log.Println("Error writing HTML string to FileRepeater buffer")
+ return nil
+ }
+
+ _, err = html.WriteString(fmt.Sprintf(script, nameidx, className))
+ if err != nil {
+ log.Println("Error writing HTML string to FileRepeater buffer")
+ return nil
+ }
+ }
+ _, err = html.WriteString(` `)
+ if err != nil {
+ log.Println("Error writing HTML string to FileRepeater buffer")
+ return nil
}
- html.WriteString(` `)
return append(html.Bytes(), RepeatController(fieldName, p, "input.upload", "div.file-input."+fieldName)...)
}
--
cgit v1.2.3