Skip to content

Commit 89b4650

Browse files
committed
Address feedback
- Use a string builder instead of string to minimize allocations - Use proper doc-comment format With the use of stringBuilder, errors have been introduced into the package. I added the dependency `github.com/pkg/errors` to help handle them, but if we'd prefer to stick with the standard library I think that'd be fair. My thinking was the circumstances that caused strings.Builder.WriteString() to error would warrent a stack trace and metadata, something which is more pragmatically done using `github.com/pkg/errors`.
1 parent cab2b98 commit 89b4650

File tree

1 file changed

+135
-48
lines changed

1 file changed

+135
-48
lines changed

document.go

+135-48
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,169 @@
11
package gemini
22

3-
// DocumentBuilder allows programatic document creation using the builder pattern.
3+
import (
4+
"bytes"
5+
"strings"
6+
7+
"github.com/pkg/errors"
8+
)
9+
10+
// DocumentBuilder allows programmatic document creation using the builder pattern.
411
// DocumentBuilder supports the use of headers and footers, which combined with the body at build time.
512
type DocumentBuilder struct {
6-
header string
7-
body string
13+
header string
14+
body *strings.Builder
815
footer string
916
}
1017

11-
// Instantiate a new DocumentBuilder.
18+
// NewDocumentBuilder creates a DocumentBuilder.
1219
func NewDocumentBuilder() DocumentBuilder {
13-
return DocumentBuilder{}
20+
builder := new(strings.Builder)
21+
return DocumentBuilder{"", builder, ""}
1422
}
1523

16-
// Ensures any string passed through this function will be terminated with a newline
17-
func ensureNewlineTerminated(text string) string {
18-
if len(text) == 0 || text[len(text)-1] != '\n' {
19-
text += "\n"
20-
}
21-
return text
24+
// SetHeader sets a document header. The header is written before the document body during `Build()`.
25+
func (doc *DocumentBuilder) SetHeader(header string) {
26+
doc.header = header
2227
}
2328

24-
// Set the document header
25-
func (self *DocumentBuilder) SetHeader(header string) {
26-
self.header = ensureNewlineTerminated(header)
29+
// SetFooter sets a document footer. The footer is written after the document body during `Build()`.
30+
func (doc *DocumentBuilder) SetFooter(footer string) {
31+
doc.footer = footer
2732
}
2833

29-
// Set the document footer
30-
func (self *DocumentBuilder) SetFooter(footer string) {
31-
self.footer = ensureNewlineTerminated(footer)
32-
}
34+
// AddLine appends a new line to the document. Adds a newline to the end of the line if none is present.
35+
func (doc *DocumentBuilder) AddLine(line string) error {
36+
_, err := doc.body.WriteString(line)
37+
if err != nil {
38+
return errors.Wrap(err, "Error writing to document")
39+
}
40+
41+
if !strings.HasSuffix(line, "\n") {
42+
_, err = doc.body.WriteString("\n")
43+
if err != nil {
44+
return errors.Wrap(err, "Error writing to document")
45+
}
46+
}
3347

34-
// Add a new line to the document. Adds a newline to the end of the line if none is present.
35-
func (self *DocumentBuilder) AddLine(line string) {
36-
self.body += ensureNewlineTerminated(line)
48+
return nil
3749
}
3850

39-
// Add an H1 (#) header line to the document.
40-
func (self *DocumentBuilder) AddH1Header(header string) {
41-
self.AddLine("# " + header)
51+
// AddH1Header appends an H1 (#) header line to the document.
52+
func (doc *DocumentBuilder) AddH1Header(header string) error {
53+
_, err := doc.body.WriteString("# ")
54+
if err != nil {
55+
return errors.Wrap(err, "Error writing to document")
56+
}
57+
58+
doc.AddLine(header)
59+
return err
4260
}
4361

44-
// Add an H2 (##) header line to the document.
45-
func (self *DocumentBuilder) AddH2Header(header string) {
46-
self.AddLine("## " + header)
62+
// AddH2Header appends an H2 (##) header line to the document.
63+
func (doc *DocumentBuilder) AddH2Header(header string) error {
64+
_, err := doc.body.WriteString("## ")
65+
if err != nil {
66+
return errors.Wrap(err, "Error writing to document")
67+
}
68+
69+
err = doc.AddLine(header)
70+
return err
4771
}
4872

49-
// Add an H3 (###) header line to the document.
50-
func (self *DocumentBuilder) AddH3Header(header string) {
51-
self.AddLine("### " + header)
73+
// AddH3Header appends an H3 (###) header line to the document.
74+
func (doc *DocumentBuilder) AddH3Header(header string) error {
75+
_, err := doc.body.WriteString("### ")
76+
if err != nil {
77+
return errors.Wrap(err, "Error writing header line to document")
78+
}
79+
80+
err = doc.AddLine(header)
81+
return err
5282
}
5383

54-
// Add a quote line to the document.
55-
func (self *DocumentBuilder) AddQuote(header string) {
56-
self.AddLine("> " + header)
84+
// AddQuote appends a quote line to the document.
85+
func (doc *DocumentBuilder) AddQuote(header string) error {
86+
_, err := doc.body.WriteString("> ")
87+
if err != nil {
88+
return errors.Wrap(err, "Error writing quote to document")
89+
}
90+
91+
err = doc.AddLine(header)
92+
return err
5793
}
5894

59-
// Add an unordered list item to the document.
60-
func (self *DocumentBuilder) AddBullet(header string) {
61-
self.AddLine("* " + header)
95+
// AddBullet appends an unordered list item to the document.
96+
func (doc *DocumentBuilder) AddBullet(header string) error {
97+
_, err := doc.body.WriteString("* ")
98+
if err != nil {
99+
return errors.Wrap(err, "Error writing bullet to document")
100+
}
101+
102+
err = doc.AddLine(header)
103+
return err
62104
}
63105

64-
// Add a toggle formatting line to the document.
65-
func (self *DocumentBuilder) ToggleFormatting() {
66-
self.AddLine("```")
106+
// ToggleFormatting appends a toggle formatting line to the document.
107+
func (doc *DocumentBuilder) ToggleFormatting() error {
108+
return doc.AddLine("```")
67109
}
68110

69-
// Add an aliased link line to the document.
70-
func (self *DocumentBuilder) AddLink(url string, title string) {
71-
self.AddLine("=> " + url + "\t" + title)
111+
// AddLink appends an aliased link line to the document.
112+
func (doc *DocumentBuilder) AddLink(url string, title string) error {
113+
_, err := doc.body.WriteString("=> ")
114+
if err != nil {
115+
return errors.Wrap(err, "Error writing link to document")
116+
}
117+
_, err = doc.body.WriteString(url)
118+
if err != nil {
119+
return errors.Wrap(err, "Error writing link to document")
120+
}
121+
_, err = doc.body.WriteString("\t")
122+
if err != nil {
123+
return errors.Wrap(err, "Error writing link to document")
124+
}
125+
// AddLine to ensure there is a newline
126+
err = doc.AddLine(title)
127+
return err
72128
}
73129

74-
// Add a link line to the document.
75-
func (self *DocumentBuilder) AddRawLink(url string) {
76-
self.AddLine("=> " + url)
130+
// AddRawLink appends a link line to the document.
131+
func (doc *DocumentBuilder) AddRawLink(url string) error {
132+
_, err := doc.body.WriteString("=> ")
133+
if err != nil {
134+
return errors.Wrap(err, "Error writing raw link to document")
135+
}
136+
err = doc.AddLine(url)
137+
return err
77138
}
78139

79-
// Build the document into a serialized byte slice.
80-
func (self *DocumentBuilder) Build() []byte {
81-
return []byte(self.header + self.body + self.footer)
140+
// Build builds the document into a serialized byte slice.
141+
func (doc *DocumentBuilder) Build() ([]byte, error) {
142+
buf := bytes.Buffer{}
143+
144+
// Write header
145+
_, err := buf.WriteString(doc.header)
146+
if err != nil {
147+
return nil, errors.Wrap(err, "Error building document header")
148+
}
149+
if !strings.HasSuffix(doc.header, "\n") {
150+
_, err = buf.WriteString("\n")
151+
if err != nil {
152+
return nil, errors.Wrap(err, "Error building document header")
153+
}
154+
}
155+
156+
// Write body
157+
_, err = buf.WriteString(doc.body.String())
158+
if err != nil {
159+
return nil, errors.Wrap(err, "Error building document body")
160+
}
161+
162+
// Write footer
163+
_, err = buf.WriteString(doc.footer)
164+
if err != nil {
165+
return nil, errors.Wrap(err, "Error building document footer")
166+
}
167+
168+
return buf.Bytes(), nil
82169
}

0 commit comments

Comments
 (0)