diff --git a/context/context.go b/context/context.go
new file mode 100644
index 00000000..0fd637cd
--- /dev/null
+++ b/context/context.go
@@ -0,0 +1,43 @@
+package context
+
+import (
+ "context"
+ "time"
+
+ "github.com/bytesparadise/libasciidoc/types"
+)
+
+// Context is a custom implementation of the standard golang context.Context interface,
+// which carries the types.Document which is being processed
+type Context struct {
+ context context.Context
+ Document types.Document
+}
+
+// Wrap wraps the given `ctx` context into a new context which will contain the given `document` document.
+func Wrap(ctx context.Context, document types.Document) Context {
+ return Context{
+ context: ctx,
+ Document: document,
+ }
+}
+
+// Deadline wrapper implementation of context.Context.Deadline()
+func (ctx *Context) Deadline() (deadline time.Time, ok bool) {
+ return ctx.context.Deadline()
+}
+
+// Done wrapper implementation of context.Context.Done()
+func (ctx *Context) Done() <-chan struct{} {
+ return ctx.Done()
+}
+
+// Err wrapper implementation of context.Context.Err()
+func (ctx *Context) Err() error {
+ return ctx.Err()
+}
+
+// Value wrapper implementation of context.Context.Value(interface{})
+func (ctx *Context) Value(key interface{}) interface{} {
+ return ctx.Value(key)
+}
diff --git a/libasciidoc.go b/libasciidoc.go
index 6e9deb2b..7adfc74e 100644
--- a/libasciidoc.go
+++ b/libasciidoc.go
@@ -4,6 +4,7 @@ import (
"context"
"io"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/parser"
"github.com/bytesparadise/libasciidoc/renderer"
htmlrenderer "github.com/bytesparadise/libasciidoc/renderer/html5"
@@ -15,7 +16,7 @@ import (
// ConvertToHTMLBody converts the content of the given reader `r` into an set of
elements for an HTML/BODY document.
// The conversion result is written in the given writer `w`, whereas the document metadata (title, etc.) (or an error if a problem occurred) is returned
// as the result of the function call.
-func ConvertToHTMLBody(r io.Reader, w io.Writer) (*types.DocumentAttributes, error) {
+func ConvertToHTMLBody(ctx context.Context, r io.Reader, w io.Writer) (*types.DocumentAttributes, error) {
doc, err := parser.ParseReader("", r)
if err != nil {
return nil, errors.Wrapf(err, "error while parsing the document")
@@ -23,7 +24,7 @@ func ConvertToHTMLBody(r io.Reader, w io.Writer) (*types.DocumentAttributes, err
document := doc.(*types.Document)
options := renderer.Options{}
options[renderer.IncludeHeaderFooter] = false // force value
- err = htmlrenderer.Render(context.Background(), *document, w, options)
+ err = htmlrenderer.Render(asciidoc.Wrap(ctx, *document), w, options)
if err != nil {
return nil, errors.Wrapf(err, "error while rendering the document")
}
@@ -33,15 +34,14 @@ func ConvertToHTMLBody(r io.Reader, w io.Writer) (*types.DocumentAttributes, err
// ConvertToHTML converts the content of the given reader `r` into a full HTML document, written in the given writer `w`.
// Returns an error if a problem occurred
-func ConvertToHTML(r io.Reader, w io.Writer, options renderer.Options) error {
-
+func ConvertToHTML(ctx context.Context, r io.Reader, w io.Writer, options renderer.Options) error {
doc, err := parser.ParseReader("", r)
if err != nil {
return errors.Wrapf(err, "error while parsing the document")
}
document := doc.(*types.Document)
options[renderer.IncludeHeaderFooter] = true // force value
- err = htmlrenderer.Render(context.Background(), *document, w, options)
+ err = htmlrenderer.Render(asciidoc.Wrap(ctx, *document), w, options)
if err != nil {
return errors.Wrapf(err, "error while rendering the document")
}
diff --git a/libasciidoc_test.go b/libasciidoc_test.go
index fcf73bce..2b95c7ec 100644
--- a/libasciidoc_test.go
+++ b/libasciidoc_test.go
@@ -2,6 +2,7 @@ package libasciidoc_test
import (
"bytes"
+ "context"
"strings"
"time"
@@ -179,8 +180,8 @@ Last updated {{.LastUpdated}}
func verifyDocumentBody(t GinkgoTInterface, expectedTitle *string, expectedContent, source string) {
t.Logf("processing '%s'", source)
sourceReader := strings.NewReader(source)
- resultWriter := bytes.NewBuffer(make([]byte, 0))
- metadata, err := ConvertToHTMLBody(sourceReader, resultWriter)
+ resultWriter := bytes.NewBuffer(nil)
+ metadata, err := ConvertToHTMLBody(context.Background(), sourceReader, resultWriter)
require.Nil(t, err, "Error found while parsing the document")
require.NotNil(t, metadata)
t.Log("Done processing document")
@@ -199,10 +200,10 @@ func verifyDocumentBody(t GinkgoTInterface, expectedTitle *string, expectedConte
func verifyCompleteDocument(t GinkgoTInterface, expectedContent, source string) {
t.Logf("processing '%s'", source)
sourceReader := strings.NewReader(source)
- resultWriter := bytes.NewBuffer(make([]byte, 0))
+ resultWriter := bytes.NewBuffer(nil)
options := renderer.Options{}
options[renderer.LastUpdated] = time.Now()
- err := ConvertToHTML(sourceReader, resultWriter, options)
+ err := ConvertToHTML(context.Background(), sourceReader, resultWriter, options)
require.Nil(t, err, "Error found while parsing the document")
t.Log("Done processing document")
result := string(resultWriter.Bytes())
diff --git a/parser/asciidoc-grammar.peg b/parser/asciidoc-grammar.peg
index 5338c134..02f3e60c 100644
--- a/parser/asciidoc-grammar.peg
+++ b/parser/asciidoc-grammar.peg
@@ -17,7 +17,7 @@ DocumentBlock <- !EOF content:(Section / StandaloneBlock) {
return content.(types.DocElement), nil
}
-StandaloneBlock <- DocumentAttribute / List / BlockImage / DelimitedBlock / Paragraph / ElementAttribute / BlankLine //TODO: should Paragraph be the last type ?
+StandaloneBlock <- DocumentAttributeDeclaration / DocumentAttributeReset / List / BlockImage / DelimitedBlock / Paragraph / ElementAttribute / BlankLine //TODO: should Paragraph be the last type ?
Section <- Section1 / Section2 / Section3 / Section4 / Section5 / Section6
@@ -101,18 +101,38 @@ Heading6 <- attributes:(ElementAttribute)* level:("======") WS+ content:InlineCo
// ------------------------------------------
-// Document Attribute
+// Document Attributes
// ------------------------------------------
-DocumentAttribute <- DocumentAttributeWithNameOnly / DocumentAttributeWithNameAndValue
+DocumentAttributeDeclaration <- DocumentAttributeDeclarationWithNameOnly / DocumentAttributeDeclarationWithNameAndValue
-DocumentAttributeWithNameOnly <- ":" name:((!NEWLINE !":" !WS .)+) ":" WS* EOL {
- return types.NewDocumentAttribute(name.([]interface{}), nil)
+DocumentAttributeDeclarationWithNameOnly <- ":" name:(AttributeName) ":" WS* EOL {
+ return types.NewDocumentAttributeDeclaration(name.([]interface{}), nil)
}
-DocumentAttributeWithNameAndValue <- ":" name:((!NEWLINE !":" !WS .)+) ":" WS+ value:(!NEWLINE .)* EOL {
- return types.NewDocumentAttribute(name.([]interface{}), value.([]interface{}))
+DocumentAttributeDeclarationWithNameAndValue <- ":" name:(AttributeName) ":" WS+ value:(!NEWLINE .)* EOL {
+ return types.NewDocumentAttributeDeclaration(name.([]interface{}), value.([]interface{}))
}
+DocumentAttributeReset <- DocumentAttributeResetWithHeadingBangSymbol / DocumentAttributeResetWithTrailingBangSymbol
+
+DocumentAttributeResetWithHeadingBangSymbol <- ":!" name:(AttributeName) ":" WS* EOL {
+ return types.NewDocumentAttributeReset(name.([]interface{}))
+}
+
+DocumentAttributeResetWithTrailingBangSymbol <- ":" name:(AttributeName) "!:" WS* EOL {
+ return types.NewDocumentAttributeReset(name.([]interface{}))
+}
+
+
+DocumentAttributeSubstitution <- "{" name:(AttributeName) "}" {
+ return types.NewDocumentAttributeSubstitution(name.([]interface{}))
+}
+
+// AttributeName must be at least one character long,
+// must begin with a word character (A-Z, a-z, 0-9 or _) and
+// must only contain word characters and hyphens ('-').
+AttributeName <- ([A-Z] / [a-z] / [0-9] / "_") ([A-Z] / [a-z] / [0-9] / "-")*
+
// ------------------------------------------
// List Items
// ------------------------------------------
@@ -137,14 +157,16 @@ Paragraph <- attributes:(ElementAttribute)* lines:(InlineContent)+ {
return types.NewParagraph(c.text, lines.([]interface{}), attributes.([]interface{}))
}
-// an inline content element may begin and end with spaces,
-// but it must contain at least an image, a quoted text, an external link or a word
-InlineContent <- elements:(WS* (InlineImage / QuotedText / ExternalLink / Word) WS*)+ EOL {
+// an inline content element may start with and end with spaces,
+// but it must contain at least an inline element (image, quoted text, external link, document attribute substitution, word, etc.)
+InlineContent <- elements:(WS* InlineElement WS*)+ EOL {
return types.NewInlineContent(c.text, elements.([]interface{}))
}
+InlineElement <- InlineImage / QuotedText / ExternalLink / DocumentAttributeSubstitution / Word
+
// ------------------------------------------
-// Quote Texts (bold, italic and monospace)
+// Quoted Texts (bold, italic and monospace)
// ------------------------------------------
QuotedText <- BoldText / ItalicText / MonospaceText
diff --git a/parser/document_attributes_test.go b/parser/document_attributes_test.go
index d471c315..d25ecc57 100644
--- a/parser/document_attributes_test.go
+++ b/parser/document_attributes_test.go
@@ -9,6 +9,28 @@ var _ = Describe("Parsing Document Attributes", func() {
Context("Valid document attributes", func() {
+ It("valid attribute names", func() {
+
+ actualContent := `:a:
+:author: Xavier
+:_author: Xavier
+:Author: Xavier
+:0Author: Xavier
+:Auth0r: Xavier`
+ expectedDocument := &types.Document{
+ Attributes: &types.DocumentAttributes{},
+ Elements: []types.DocElement{
+ &types.DocumentAttributeDeclaration{Name: "a"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "_author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "Author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "0Author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "Auth0r", Value: "Xavier"},
+ },
+ }
+ verify(GinkgoT(), expectedDocument, actualContent)
+ })
+
It("heading section with attributes", func() {
actualContent := `= a heading
@@ -35,9 +57,9 @@ a paragraph`
},
},
Elements: []types.DocElement{
- &types.DocumentAttribute{Name: "toc"},
- &types.DocumentAttribute{Name: "date", Value: "2017-01-01"},
- &types.DocumentAttribute{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "toc"},
+ &types.DocumentAttributeDeclaration{Name: "date", Value: "2017-01-01"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
&types.Paragraph{
Lines: []*types.InlineContent{
&types.InlineContent{
@@ -63,9 +85,9 @@ a paragraph`
expectedDocument := &types.Document{
Attributes: &types.DocumentAttributes{},
Elements: []types.DocElement{
- &types.DocumentAttribute{Name: "toc"},
- &types.DocumentAttribute{Name: "date", Value: "2017-01-01"},
- &types.DocumentAttribute{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "toc"},
+ &types.DocumentAttributeDeclaration{Name: "date", Value: "2017-01-01"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
&types.Paragraph{
Lines: []*types.InlineContent{
&types.InlineContent{
@@ -90,9 +112,9 @@ a paragraph`
expectedDocument := &types.Document{
Attributes: &types.DocumentAttributes{},
Elements: []types.DocElement{
- &types.DocumentAttribute{Name: "toc"},
- &types.DocumentAttribute{Name: "date", Value: "2017-01-01"},
- &types.DocumentAttribute{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "toc"},
+ &types.DocumentAttributeDeclaration{Name: "date", Value: "2017-01-01"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
&types.Paragraph{
Lines: []*types.InlineContent{
&types.InlineContent{
@@ -118,9 +140,9 @@ a paragraph`
expectedDocument := &types.Document{
Attributes: &types.DocumentAttributes{},
Elements: []types.DocElement{
- &types.DocumentAttribute{Name: "toc"},
- &types.DocumentAttribute{Name: "date", Value: "2017-01-01"},
- &types.DocumentAttribute{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "toc"},
+ &types.DocumentAttributeDeclaration{Name: "date", Value: "2017-01-01"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
&types.Paragraph{
Lines: []*types.InlineContent{
&types.InlineContent{
@@ -154,16 +176,70 @@ a paragraph`
},
},
},
- &types.DocumentAttribute{Name: "toc"},
- &types.DocumentAttribute{Name: "date", Value: "2017-01-01"},
- &types.DocumentAttribute{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeDeclaration{Name: "toc"},
+ &types.DocumentAttributeDeclaration{Name: "date", Value: "2017-01-01"},
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
+ },
+ }
+ verify(GinkgoT(), expectedDocument, actualContent)
+ })
+
+ It("paragraph with attribute substitution", func() {
+
+ actualContent := `:author: Xavier
+
+a paragraph written by {author}.`
+ expectedDocument := &types.Document{
+ Attributes: &types.DocumentAttributes{},
+ Elements: []types.DocElement{
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
+ &types.Paragraph{
+ Lines: []*types.InlineContent{
+ &types.InlineContent{
+ Elements: []types.InlineElement{
+ &types.StringElement{Content: "a paragraph written by "},
+ &types.DocumentAttributeSubstitution{Name: "author"},
+ &types.StringElement{Content: "."},
+ },
+ },
+ },
+ },
+ },
+ }
+ verify(GinkgoT(), expectedDocument, actualContent)
+ })
+
+ It("paragraph with attribute resets", func() {
+
+ actualContent := `:author: Xavier
+
+:!author1:
+:author2!:
+a paragraph written by {author}.`
+ expectedDocument := &types.Document{
+ Attributes: &types.DocumentAttributes{},
+ Elements: []types.DocElement{
+ &types.DocumentAttributeDeclaration{Name: "author", Value: "Xavier"},
+ &types.DocumentAttributeReset{Name: "author1"},
+ &types.DocumentAttributeReset{Name: "author2"},
+ &types.Paragraph{
+ Lines: []*types.InlineContent{
+ &types.InlineContent{
+ Elements: []types.InlineElement{
+ &types.StringElement{Content: "a paragraph written by "},
+ &types.DocumentAttributeSubstitution{Name: "author"},
+ &types.StringElement{Content: "."},
+ },
+ },
+ },
+ },
},
}
verify(GinkgoT(), expectedDocument, actualContent)
})
})
- Context("Valid document attributes", func() {
+ Context("Invalid document attributes", func() {
It("paragraph and without blank line in between", func() {
actualContent := `a paragraph
@@ -201,5 +277,31 @@ a paragraph`
}
verify(GinkgoT(), expectedDocument, actualContent)
})
+
+ It("invalid attribute names", func() {
+
+ actualContent := `:@date: 2017-01-01
+:{author}: Xavier`
+ expectedDocument := &types.Document{
+ Attributes: &types.DocumentAttributes{},
+ Elements: []types.DocElement{
+ &types.Paragraph{
+ Lines: []*types.InlineContent{
+ &types.InlineContent{
+ Elements: []types.InlineElement{
+ &types.StringElement{Content: ":@date: 2017-01-01"},
+ },
+ },
+ &types.InlineContent{
+ Elements: []types.InlineElement{
+ &types.StringElement{Content: ":{author}: Xavier"},
+ },
+ },
+ },
+ },
+ },
+ }
+ verify(GinkgoT(), expectedDocument, actualContent)
+ })
})
})
diff --git a/renderer/html5/delimited_block.go b/renderer/html5/delimited_block.go
index 4b703511..6023d3ed 100644
--- a/renderer/html5/delimited_block.go
+++ b/renderer/html5/delimited_block.go
@@ -2,9 +2,9 @@ package html5
import (
"bytes"
- "context"
"html/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -21,9 +21,9 @@ func init() {
`)
}
-func renderDelimitedBlock(ctx context.Context, block types.DelimitedBlock) ([]byte, error) {
+func renderDelimitedBlock(ctx asciidoc.Context, block types.DelimitedBlock) ([]byte, error) {
log.Debugf("rendering delimited block with content: %s", block.Content)
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
err := sourceBlockTmpl.Execute(result, block)
if err != nil {
return nil, errors.Wrapf(err, "unable to render delimited block")
diff --git a/renderer/html5/document_attribute.go b/renderer/html5/document_attribute.go
new file mode 100644
index 00000000..0c1457c2
--- /dev/null
+++ b/renderer/html5/document_attribute.go
@@ -0,0 +1,30 @@
+package html5
+
+import (
+ "bytes"
+ "fmt"
+
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
+ "github.com/bytesparadise/libasciidoc/types"
+)
+
+func processAttributeDeclaration(ctx asciidoc.Context, attribute types.DocumentAttributeDeclaration) error {
+ ctx.Document.Attributes.Add(attribute)
+ return nil
+}
+
+func processAttributeReset(ctx asciidoc.Context, attribute types.DocumentAttributeReset) error {
+ ctx.Document.Attributes.Reset(attribute)
+ return nil
+}
+
+func renderAttributeSubstitution(ctx asciidoc.Context, attribute types.DocumentAttributeSubstitution) ([]byte, error) {
+ result := bytes.NewBuffer(nil)
+ value := ctx.Document.Attributes.Get(attribute)
+ if value == nil {
+ result.WriteString(fmt.Sprintf("{%s}", attribute.Name))
+ } else {
+ result.WriteString(*value)
+ }
+ return result.Bytes(), nil
+}
diff --git a/renderer/html5/document_attribute_test.go b/renderer/html5/document_attribute_test.go
index 4c4d7ddb..2671d412 100644
--- a/renderer/html5/document_attribute_test.go
+++ b/renderer/html5/document_attribute_test.go
@@ -29,4 +29,43 @@ var _ = Describe("Rendering With Attributes", func() {
`
verify(GinkgoT(), expected, content)
})
+
+ It("a paragraph with substitution", func() {
+ content := `:author: Xavier
+
+a paragraph written by {author}`
+
+ expected := `
+
a paragraph written by Xavier
+
`
+ verify(GinkgoT(), expected, content)
+ })
+
+ It("paragraphs with definitions, substitutions and resets", func() {
+ content := `author is {author}.
+
+:author: me
+author is now {author}.
+
+:author: you
+author is now {author}.
+
+:author!:
+author is now {author}.`
+
+ expected := `
+
+
+
+
author is now {author}.
+
`
+ verify(GinkgoT(), expected, content)
+ })
+
})
diff --git a/renderer/html5/image.go b/renderer/html5/image.go
index 88b4becb..35756413 100644
--- a/renderer/html5/image.go
+++ b/renderer/html5/image.go
@@ -2,9 +2,9 @@ package html5
import (
"bytes"
- "context"
"html/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -25,8 +25,8 @@ func init() {
inlineImageTmpl = newHTMLTemplate("inline image", ``)
}
-func renderBlockImage(ctx context.Context, img types.BlockImage) ([]byte, error) {
- result := bytes.NewBuffer(make([]byte, 0))
+func renderBlockImage(ctx asciidoc.Context, img types.BlockImage) ([]byte, error) {
+ result := bytes.NewBuffer(nil)
err := blockImageTmpl.Execute(result, img)
if err != nil {
return nil, errors.Wrapf(err, "unable to render block image")
@@ -35,8 +35,8 @@ func renderBlockImage(ctx context.Context, img types.BlockImage) ([]byte, error)
return result.Bytes(), nil
}
-func renderInlineImage(ctx context.Context, img types.InlineImage) ([]byte, error) {
- result := bytes.NewBuffer(make([]byte, 0))
+func renderInlineImage(ctx asciidoc.Context, img types.InlineImage) ([]byte, error) {
+ result := bytes.NewBuffer(nil)
err := inlineImageTmpl.Execute(result, img)
if err != nil {
return nil, errors.Wrapf(err, "unable to render inline image")
diff --git a/renderer/html5/inline_content.go b/renderer/html5/inline_content.go
index 17cf2b4b..7a1a6942 100644
--- a/renderer/html5/inline_content.go
+++ b/renderer/html5/inline_content.go
@@ -3,16 +3,15 @@ package html5
import (
"bytes"
- "context"
-
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
)
-func renderInlineContent(ctx context.Context, content types.InlineContent) ([]byte, error) {
- renderedElementsBuff := bytes.NewBuffer(make([]byte, 0))
+func renderInlineContent(ctx asciidoc.Context, content types.InlineContent) ([]byte, error) {
+ renderedElementsBuff := bytes.NewBuffer(nil)
for _, element := range content.Elements {
- renderedElement, err := renderElement(ctx, element)
+ renderedElement, err := processElement(ctx, element)
if err != nil {
return nil, errors.Wrapf(err, "unable to render paragraph element")
}
diff --git a/renderer/html5/list_item.go b/renderer/html5/list_item.go
index 329c2f03..10f1a4b9 100644
--- a/renderer/html5/list_item.go
+++ b/renderer/html5/list_item.go
@@ -2,9 +2,9 @@ package html5
import (
"bytes"
- "context"
"html/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -30,8 +30,8 @@ func init() {
listItemContentTmpl = newHTMLTemplate("list item content", `{{.}}
`)
}
-func renderList(ctx context.Context, list types.List) ([]byte, error) {
- renderedElementsBuff := bytes.NewBuffer(make([]byte, 0))
+func renderList(ctx asciidoc.Context, list types.List) ([]byte, error) {
+ renderedElementsBuff := bytes.NewBuffer(nil)
for i, item := range list.Items {
renderedListItem, err := renderListItem(ctx, *item)
if err != nil {
@@ -43,7 +43,7 @@ func renderList(ctx context.Context, list types.List) ([]byte, error) {
}
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
// here we must preserve the HTML tags
err := unorderedListTmpl.Execute(result, struct {
ID *types.ElementID
@@ -59,12 +59,12 @@ func renderList(ctx context.Context, list types.List) ([]byte, error) {
return result.Bytes(), nil
}
-func renderListItem(ctx context.Context, item types.ListItem) ([]byte, error) {
+func renderListItem(ctx asciidoc.Context, item types.ListItem) ([]byte, error) {
renderedItemContent, err := renderListItemContent(ctx, *item.Content)
if err != nil {
return nil, errors.Wrapf(err, "unable to render list item")
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
var renderedChildrenOutput *template.HTML
if item.Children != nil {
childrenOutput, err := renderList(ctx, *item.Children)
@@ -88,8 +88,8 @@ func renderListItem(ctx context.Context, item types.ListItem) ([]byte, error) {
return result.Bytes(), nil
}
-func renderListItemContent(ctx context.Context, content types.ListItemContent) ([]byte, error) {
- renderedLinesBuff := bytes.NewBuffer(make([]byte, 0))
+func renderListItemContent(ctx asciidoc.Context, content types.ListItemContent) ([]byte, error) {
+ renderedLinesBuff := bytes.NewBuffer(nil)
for _, line := range content.Lines {
renderedLine, err := renderInlineContent(ctx, *line)
if err != nil {
@@ -97,7 +97,7 @@ func renderListItemContent(ctx context.Context, content types.ListItemContent) (
}
renderedLinesBuff.Write(renderedLine)
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
err := listItemContentTmpl.Execute(result, renderedLinesBuff.String())
if err != nil {
return nil, errors.Wrapf(err, "unable to render list item")
diff --git a/renderer/html5/paragraph.go b/renderer/html5/paragraph.go
index 86f68f23..32049be9 100644
--- a/renderer/html5/paragraph.go
+++ b/renderer/html5/paragraph.go
@@ -1,12 +1,10 @@
package html5
import (
- "html/template"
-
"bytes"
+ "html/template"
- "context"
-
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
)
@@ -22,8 +20,8 @@ func init() {
`)
}
-func renderParagraph(ctx context.Context, paragraph types.Paragraph) ([]byte, error) {
- renderedLinesBuff := bytes.NewBuffer(make([]byte, 0))
+func renderParagraph(ctx asciidoc.Context, paragraph types.Paragraph) ([]byte, error) {
+ renderedLinesBuff := bytes.NewBuffer(nil)
for i, line := range paragraph.Lines {
renderedLine, err := renderInlineContent(ctx, *line)
if err != nil {
@@ -35,7 +33,7 @@ func renderParagraph(ctx context.Context, paragraph types.Paragraph) ([]byte, er
}
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
err := paragraphTmpl.Execute(result, struct {
ID *types.ElementID
Title *types.ElementTitle
diff --git a/renderer/html5/quoted_text.go b/renderer/html5/quoted_text.go
index 19fdcec2..d07b1eb8 100644
--- a/renderer/html5/quoted_text.go
+++ b/renderer/html5/quoted_text.go
@@ -1,11 +1,10 @@
package html5
import (
- "context"
- "html/template"
-
"bytes"
+ "html/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -22,10 +21,10 @@ func init() {
monospaceTextTmpl = newHTMLTemplate("monospace text", "{{.}}
")
}
-func renderQuotedText(ctx context.Context, t types.QuotedText) ([]byte, error) {
- elementsBuffer := bytes.NewBuffer(make([]byte, 0))
+func renderQuotedText(ctx asciidoc.Context, t types.QuotedText) ([]byte, error) {
+ elementsBuffer := bytes.NewBuffer(nil)
for _, element := range t.Elements {
- b, err := renderElement(ctx, element)
+ b, err := processElement(ctx, element)
if err != nil {
return nil, errors.Wrapf(err, "unable to render text quote")
}
@@ -34,7 +33,7 @@ func renderQuotedText(ctx context.Context, t types.QuotedText) ([]byte, error) {
return nil, errors.Wrapf(err, "unable to render text quote")
}
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
var tmpl *template.Template
switch t.Kind {
case types.Bold:
diff --git a/renderer/html5/renderer.go b/renderer/html5/renderer.go
index 7ad46339..9bb6fb94 100644
--- a/renderer/html5/renderer.go
+++ b/renderer/html5/renderer.go
@@ -2,15 +2,14 @@ package html5
import (
"bytes"
- "context"
"html/template"
"io"
texttemplate "text/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/renderer"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
- log "github.com/sirupsen/logrus"
)
var documentTmpl *texttemplate.Template
@@ -42,7 +41,7 @@ Last updated {{.LastUpdated}}
}
// Render renders the given document in HTML and writes the result in the given `writer`
-func Render(ctx context.Context, document types.Document, output io.Writer, options renderer.Options) error {
+func Render(ctx asciidoc.Context, output io.Writer, options renderer.Options) error {
includeHeaderFooter, err := options.IncludeHeaderFooter()
if err != nil {
return errors.Wrap(err, "error while rendering the HTML document")
@@ -55,13 +54,12 @@ func Render(ctx context.Context, document types.Document, output io.Writer, opti
if *includeHeaderFooter {
// use a temporary writer for the document's content
- renderedElementsBuff := bytes.NewBuffer(make([]byte, 0))
- renderElements(ctx, document.Elements, renderedElementsBuff)
+ renderedElementsBuff := bytes.NewBuffer(nil)
+ processElements(ctx, renderedElementsBuff)
renderedHTMLElements := template.HTML(renderedElementsBuff.String())
-
title := "undefined"
- if document.Attributes.GetTitle() != nil {
- title = *document.Attributes.GetTitle()
+ if ctx.Document.Attributes.GetTitle() != nil {
+ title = *ctx.Document.Attributes.GetTitle()
}
err := documentTmpl.Execute(output, struct {
Generator string
@@ -79,21 +77,20 @@ func Render(ctx context.Context, document types.Document, output io.Writer, opti
}
return nil
}
- return renderElements(ctx, document.Elements, output)
+ return processElements(ctx, output)
}
-func renderElements(ctx context.Context, elements []types.DocElement, output io.Writer) error {
+func processElements(ctx asciidoc.Context, output io.Writer) error {
hasContent := false
- for _, element := range elements {
- content, err := renderElement(ctx, element)
+ for _, element := range ctx.Document.Elements {
+ content, err := processElement(ctx, element)
if err != nil {
return errors.Wrapf(err, "failed to render the document")
}
// if there's already some content, we need to insert a `\n` before writing
// the rendering output of the current element (if application, ie, not empty)
if hasContent && len(content) > 0 {
- log.Debugf("Appending '\\n' after element of type '%T'", element)
output.Write([]byte("\n"))
}
// if the element was rendering into 'something' (ie, not enpty result)
@@ -105,7 +102,7 @@ func renderElements(ctx context.Context, elements []types.DocElement, output io.
return nil
}
-func renderElement(ctx context.Context, element types.DocElement) ([]byte, error) {
+func processElement(ctx asciidoc.Context, element types.DocElement) ([]byte, error) {
switch element.(type) {
case *types.Section:
return renderSection(ctx, *element.(*types.Section))
@@ -125,9 +122,14 @@ func renderElement(ctx context.Context, element types.DocElement) ([]byte, error
return renderInlineContent(ctx, *element.(*types.InlineContent))
case *types.StringElement:
return renderStringElement(ctx, *element.(*types.StringElement))
- case *types.DocumentAttribute:
- // for now, silently ignored in the output
- return make([]byte, 0), nil
+ case *types.DocumentAttributeDeclaration:
+ // 'process' function do not return any rendered content, but may return an error
+ return nil, processAttributeDeclaration(ctx, *element.(*types.DocumentAttributeDeclaration))
+ case *types.DocumentAttributeReset:
+ // 'process' function do not return any rendered content, but may return an error
+ return nil, processAttributeReset(ctx, *element.(*types.DocumentAttributeReset))
+ case *types.DocumentAttributeSubstitution:
+ return renderAttributeSubstitution(ctx, *element.(*types.DocumentAttributeSubstitution))
default:
return nil, errors.Errorf("unsupported type of element: %T", element)
}
diff --git a/renderer/html5/renderer_test.go b/renderer/html5/renderer_test.go
index 58342412..6b45bcb8 100644
--- a/renderer/html5/renderer_test.go
+++ b/renderer/html5/renderer_test.go
@@ -5,6 +5,7 @@ import (
"context"
"strings"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/parser"
. "github.com/bytesparadise/libasciidoc/renderer/html5"
"github.com/bytesparadise/libasciidoc/types"
@@ -21,8 +22,9 @@ func verify(t GinkgoTInterface, expected, content string) {
require.Nil(t, err, "Error found while parsing the document")
actualDocument := doc.(*types.Document)
t.Logf("Actual document:\n%s", actualDocument.String(1))
- buff := bytes.NewBuffer(make([]byte, 0))
- err = Render(context.Background(), *actualDocument, buff, nil)
+ buff := bytes.NewBuffer(nil)
+ ctx := asciidoc.Wrap(context.Background(), *actualDocument)
+ err = Render(ctx, buff, nil)
t.Log("Done processing document")
require.Nil(t, err)
require.Empty(t, err)
diff --git a/renderer/html5/section.go b/renderer/html5/section.go
index 8c77799f..a01684a1 100644
--- a/renderer/html5/section.go
+++ b/renderer/html5/section.go
@@ -2,10 +2,11 @@ package html5
import (
"bytes"
- "context"
"html/template"
"strconv"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
+
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -46,7 +47,7 @@ func init() {
`{{.Content}}`)
}
-func renderSection(ctx context.Context, section types.Section) ([]byte, error) {
+func renderSection(ctx asciidoc.Context, section types.Section) ([]byte, error) {
switch section.Heading.Level {
case 1:
return renderSectionLevel1(ctx, section)
@@ -55,7 +56,7 @@ func renderSection(ctx context.Context, section types.Section) ([]byte, error) {
}
}
-func renderSectionLevel1(ctx context.Context, section types.Section) ([]byte, error) {
+func renderSectionLevel1(ctx asciidoc.Context, section types.Section) ([]byte, error) {
// only applies if the first element (if exists) is not a nested section
var preambleElements []types.DocElement
var otherElements []types.DocElement
@@ -74,9 +75,9 @@ func renderSectionLevel1(ctx context.Context, section types.Section) ([]byte, er
}
}
// log.Debugf("Preamble elements: %d", len(preambleElements))
- renderedPreambleElementsBuff := bytes.NewBuffer(make([]byte, 0))
+ renderedPreambleElementsBuff := bytes.NewBuffer(nil)
for i, element := range preambleElements {
- renderedElement, err := renderElement(ctx, element)
+ renderedElement, err := processElement(ctx, element)
if err != nil {
return nil, errors.Wrapf(err, "unable to render preamble element")
}
@@ -86,9 +87,9 @@ func renderSectionLevel1(ctx context.Context, section types.Section) ([]byte, er
}
}
renderedHTMLPreamble := template.HTML(renderedPreambleElementsBuff.String())
- renderedElementsBuff := bytes.NewBuffer(make([]byte, 0))
+ renderedElementsBuff := bytes.NewBuffer(nil)
for i, element := range otherElements {
- renderedElement, err := renderElement(ctx, element)
+ renderedElement, err := processElement(ctx, element)
if err != nil {
return nil, errors.Wrapf(err, "unable to render section element")
}
@@ -98,7 +99,7 @@ func renderSectionLevel1(ctx context.Context, section types.Section) ([]byte, er
}
}
renderedHTMLElements := template.HTML(renderedElementsBuff.String())
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
err := section1ContentTmpl.Execute(result, struct {
Class string
Preamble template.HTML
@@ -115,14 +116,14 @@ func renderSectionLevel1(ctx context.Context, section types.Section) ([]byte, er
return result.Bytes(), nil
}
-func renderOtherSection(ctx context.Context, section types.Section) ([]byte, error) {
+func renderOtherSection(ctx asciidoc.Context, section types.Section) ([]byte, error) {
renderedHeading, err := renderHeading(ctx, section.Heading)
if err != nil {
return nil, errors.Wrapf(err, "error while rendering section heading")
}
- renderedElementsBuff := bytes.NewBuffer(make([]byte, 0))
+ renderedElementsBuff := bytes.NewBuffer(nil)
for i, element := range section.Elements {
- renderedElement, err := renderElement(ctx, element)
+ renderedElement, err := processElement(ctx, element)
if err != nil {
return nil, errors.Wrapf(err, "unable to render section element")
}
@@ -131,7 +132,7 @@ func renderOtherSection(ctx context.Context, section types.Section) ([]byte, err
renderedElementsBuff.WriteString("\n")
}
}
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
// select the appropriate template for the section
var tmpl *template.Template
if section.Heading.Level == 1 {
@@ -159,9 +160,9 @@ func renderOtherSection(ctx context.Context, section types.Section) ([]byte, err
return result.Bytes(), nil
}
-func renderHeading(ctx context.Context, heading types.Heading) ([]byte, error) {
- result := bytes.NewBuffer(make([]byte, 0))
- renderedContent, err := renderElement(ctx, heading.Content)
+func renderHeading(ctx asciidoc.Context, heading types.Heading) ([]byte, error) {
+ result := bytes.NewBuffer(nil)
+ renderedContent, err := processElement(ctx, heading.Content)
if err != nil {
return nil, errors.Wrapf(err, "error while rendering heading content")
}
diff --git a/renderer/html5/string.go b/renderer/html5/string.go
index 37649401..ee562e2f 100644
--- a/renderer/html5/string.go
+++ b/renderer/html5/string.go
@@ -2,9 +2,9 @@ package html5
import (
"bytes"
- "context"
"html/template"
+ asciidoc "github.com/bytesparadise/libasciidoc/context"
"github.com/bytesparadise/libasciidoc/types"
"github.com/pkg/errors"
)
@@ -16,8 +16,8 @@ func init() {
stringElementTmpl = newHTMLTemplate("string element", "{{.}}")
}
-func renderStringElement(ctx context.Context, str types.StringElement) ([]byte, error) {
- result := bytes.NewBuffer(make([]byte, 0))
+func renderStringElement(ctx asciidoc.Context, str types.StringElement) ([]byte, error) {
+ result := bytes.NewBuffer(nil)
err := stringElementTmpl.Execute(result, str.Content)
if err != nil {
return nil, errors.Wrapf(err, "unable to render string element")
diff --git a/types/document_metadata.go b/types/document_metadata.go
index bc703ec3..19ae9fc0 100644
--- a/types/document_metadata.go
+++ b/types/document_metadata.go
@@ -1,7 +1,7 @@
package types
// DocumentAttributes the document metadata
-type DocumentAttributes map[string]interface{}
+type DocumentAttributes map[string]string
const (
title string = "title"
@@ -10,9 +10,7 @@ const (
// GetTitle retrieves the document title in its metadata, or returns nil if the title was not specified
func (m DocumentAttributes) GetTitle() *string {
if t, ok := m[title]; ok {
- if t, ok := t.(string); ok {
- return &t
- }
+ return &t
}
return nil
}
@@ -23,7 +21,21 @@ func (m DocumentAttributes) SetTitle(t string) {
}
// Add adds the given attribute
-func (m DocumentAttributes) Add(a *DocumentAttribute) {
+func (m DocumentAttributes) Add(a DocumentAttributeDeclaration) {
// TODO: raise a warning if there was already a name/value
m[a.Name] = a.Value
}
+
+// Reset resets the given attribute
+func (m DocumentAttributes) Reset(a DocumentAttributeReset) {
+ delete(m, a.Name)
+}
+
+// Get gets the given value for the given attribute, or nil if none was found
+func (m DocumentAttributes) Get(a DocumentAttributeSubstitution) *string {
+ // TODO: raise a warning if there was no entry found
+ if value, ok := m[a.Name]; ok {
+ return &value
+ }
+ return nil
+}
diff --git a/types/grammar_types.go b/types/grammar_types.go
index 9b33d63e..6592dd41 100644
--- a/types/grammar_types.go
+++ b/types/grammar_types.go
@@ -83,11 +83,11 @@ func (d *Document) initAttributes() {
// String implements the DocElement#String() method
func (d *Document) String(indentLevel int) string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
for i := range d.Elements {
result.WriteString(fmt.Sprintf("\n%s", d.Elements[i].String(0)))
}
- log.Debug(fmt.Sprintf("Printing document:\n%s", result.String()))
+ // log.Debug(fmt.Sprintf("Printing document:\n%s", result.String()))
return result.String()
}
@@ -95,38 +95,96 @@ func (d *Document) String(indentLevel int) string {
// Document Attributes
// ------------------------------------------
-// DocumentAttribute the type for Document Attributes
-type DocumentAttribute struct {
+// DocumentAttributeDeclaration the type for Document Attribute Declarations
+type DocumentAttributeDeclaration struct {
Name string
Value string
}
-// NewDocumentAttribute initializes a new Document Attribute
-func NewDocumentAttribute(name []interface{}, value []interface{}) (*DocumentAttribute, error) {
+// NewDocumentAttributeDeclaration initializes a new DocumentAttributeDeclaration
+func NewDocumentAttributeDeclaration(name []interface{}, value []interface{}) (*DocumentAttributeDeclaration, error) {
attrName, err := stringify(name)
if err != nil {
- return nil, errors.Wrapf(err, "error while initializing a DocumentAttribute")
+ return nil, errors.Wrapf(err, "error while initializing a DocumentAttributeDeclaration")
}
attrValue, err := stringify(value)
if err != nil {
- return nil, errors.Wrapf(err, "error while initializing a DocumentAttribute")
+ return nil, errors.Wrapf(err, "error while initializing a DocumentAttributeDeclaration")
}
- log.Debugf("Initialized a new DocumentAttribute: '%s' -> '%s'", *attrName, *attrValue)
- return &DocumentAttribute{
+ log.Debugf("Initialized a new DocumentAttributeDeclaration: '%s' -> '%s'", *attrName, *attrValue)
+ return &DocumentAttributeDeclaration{
Name: *attrName,
Value: *attrValue,
}, nil
}
// String implements the DocElement#String() method
-func (a *DocumentAttribute) String(indentLevel int) string {
- result := bytes.NewBuffer(make([]byte, 0))
- result.WriteString(fmt.Sprintf("%s '%s' -> '%s'\n", indent(indentLevel), a.Name, a.Value))
- return result.String()
+func (a *DocumentAttributeDeclaration) String(indentLevel int) string {
+ return fmt.Sprintf("%s '%s' -> '%s'\n", indent(indentLevel), a.Name, a.Value)
+}
+
+// Accept implements DocElement#Accept(Visitor)
+func (a *DocumentAttributeDeclaration) Accept(v Visitor) error {
+ return nil
+}
+
+// DocumentAttributeReset the type for DocumentAttributeReset
+type DocumentAttributeReset struct {
+ Name string
+}
+
+// NewDocumentAttributeReset initializes a new Document Attribute Resets.
+func NewDocumentAttributeReset(name []interface{}) (*DocumentAttributeReset, error) {
+ attrName, err := stringify(name)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error while initializing a DocumentAttributeReset")
+ }
+ log.Debugf("Initialized a new DocumentAttributeReset: '%s'", *attrName)
+ return &DocumentAttributeReset{Name: *attrName}, nil
+}
+
+// String implements the DocElement#String() method
+func (a *DocumentAttributeReset) String(indentLevel int) string {
+ return fmt.Sprintf("%s '%s'\n", indent(indentLevel), a.Name)
+}
+
+// PlainString implements the InlineElement#PlainString() method
+func (a *DocumentAttributeReset) PlainString() string {
+ return fmt.Sprintf("{%s}'\n", a.Name)
+}
+
+// Accept implements DocElement#Accept(Visitor)
+func (a *DocumentAttributeReset) Accept(v Visitor) error {
+ return nil
+}
+
+// DocumentAttributeSubstitution the type for DocumentAttributeSubstitution
+type DocumentAttributeSubstitution struct {
+ Name string
+}
+
+// NewDocumentAttributeSubstitution initializes a new Document Attribute Substitutions
+func NewDocumentAttributeSubstitution(name []interface{}) (*DocumentAttributeSubstitution, error) {
+ attrName, err := stringify(name)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error while initializing a DocumentAttributeSubstitution")
+ }
+ log.Debugf("Initialized a new DocumentAttributeSubstitution: '%s'", *attrName)
+ return &DocumentAttributeSubstitution{Name: *attrName}, nil
+}
+
+// String implements the DocElement#String() method
+func (a *DocumentAttributeSubstitution) String(indentLevel int) string {
+ return fmt.Sprintf("%s '%s'\n", indent(indentLevel), a.Name)
+}
+
+// PlainString implements the InlineElement#PlainString() method
+func (a *DocumentAttributeSubstitution) PlainString() string {
+ return fmt.Sprintf("{%s}'\n", a.Name)
}
// Accept implements DocElement#Accept(Visitor)
-func (a *DocumentAttribute) Accept(v Visitor) error {
+func (a *DocumentAttributeSubstitution) Accept(v Visitor) error {
return nil
}
@@ -153,7 +211,7 @@ func NewSection(heading *Heading, blocks []interface{}) (*Section, error) {
// String implements the DocElement#String() method
func (s *Section) String(indentLevel int) string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
result.WriteString(fmt.Sprintf("%s '%s'\n", indent(indentLevel), s.Heading.Level, s.Heading.Content.String(0)))
for _, element := range s.Elements {
result.WriteString(fmt.Sprintf("%s", element.String(indentLevel+1)))
@@ -225,7 +283,7 @@ func (h *Heading) String(indentLevel int) string {
// PlainString returns a plain string version of all elements in this Heading's Content, without any rendering
func (h *Heading) PlainString() string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
for i, element := range h.Content.Elements {
result.WriteString(element.PlainString())
if i < len(h.Content.Elements)-1 {
@@ -489,7 +547,7 @@ func NewParagraph(text []byte, lines []interface{}, attributes []interface{}) (*
// String implements the DocElement#String() method
func (p *Paragraph) String(indentLevel int) string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
result.WriteString(fmt.Sprintf("%s", indent(indentLevel)))
for _, line := range p.Lines {
result.WriteString(fmt.Sprintf("%s\n", line.String(0)))
@@ -533,18 +591,19 @@ type InlineContent struct {
// NewInlineContent initializes a new `InlineContent` from the given values
func NewInlineContent(text []byte, elements []interface{}) (*InlineContent, error) {
- mergedElements := make([]InlineElement, 0)
- for _, e := range merge(elements) {
- mergedElements = append(mergedElements, e.(InlineElement))
+ mergedElements := merge(elements)
+ mergedInlineElements := make([]InlineElement, len(mergedElements))
+ for i, element := range mergedElements {
+ mergedInlineElements[i] = element.(InlineElement)
}
- result := &InlineContent{Elements: mergedElements}
+ result := &InlineContent{Elements: mergedInlineElements}
log.Debugf("Initialized new InlineContent with %d elements: '%s'", len(result.Elements), result.String(0))
- return &InlineContent{Elements: mergedElements}, nil
+ return result, nil
}
// String implements the DocElement#String() method
func (c *InlineContent) String(indentLevel int) string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
result.WriteString(indent(indentLevel))
for i, element := range c.Elements {
result.WriteString(fmt.Sprintf("%s", element.String(0)))
@@ -1017,7 +1076,7 @@ func (t *QuotedText) String(indentLevel int) string {
// PlainString implements the InlineElement#PlainString() method
func (t *QuotedText) PlainString() string {
- result := bytes.NewBuffer(make([]byte, 0))
+ result := bytes.NewBuffer(nil)
for i, element := range t.Elements {
result.WriteString(element.PlainString())
if i < len(t.Elements)-1 {
diff --git a/types/type_utils.go b/types/type_utils.go
index 948a41cd..f31c3b02 100644
--- a/types/type_utils.go
+++ b/types/type_utils.go
@@ -6,7 +6,6 @@ import (
"unicode"
"github.com/pkg/errors"
- log "github.com/sirupsen/logrus"
)
func indent(indentLevel int) string {
@@ -44,7 +43,7 @@ func merge(elements []interface{}, extraElements ...interface{}) []interface{} {
result := make([]interface{}, 0)
allElements := append(elements, extraElements...)
// log.Debugf("Merging %d element(s):", len(allElements))
- buff := bytes.NewBuffer(make([]byte, 0))
+ buff := bytes.NewBuffer(nil)
for _, v := range allElements {
if v == nil {
continue
@@ -89,7 +88,7 @@ func merge(elements []interface{}, extraElements ...interface{}) []interface{} {
// the given arguments if the buffer was empty
func appendBuffer(elements []interface{}, buff *bytes.Buffer) ([]interface{}, *bytes.Buffer) {
if buff.Len() > 0 {
- return append(elements, NewStringElement(buff.String())), bytes.NewBuffer(make([]byte, 0))
+ return append(elements, NewStringElement(buff.String())), bytes.NewBuffer(nil)
}
return elements, buff
}
@@ -102,7 +101,7 @@ func stringify(elements []interface{}) (*string, error) {
if element == nil {
continue
}
- log.Debugf("%[1]v (%[1]T) ", element)
+ // log.Debugf("%[1]v (%[1]T) ", element)
switch element := element.(type) {
case string:
buff.WriteString(element)
@@ -127,7 +126,7 @@ func stringify(elements []interface{}) (*string, error) {
}
result := buff.String()
- log.Debugf("stringified %v -> '%s' (%v characters)", elements, result, len(result))
+ // log.Debugf("stringified %v -> '%s' (%v characters)", elements, result, len(result))
return &result, nil
}
@@ -142,7 +141,7 @@ func isMn(r rune) bool {
// in the given 'source' with the given 'replacement'.
func NewReplaceNonAlphanumericsFunc(replacement string) NormalizationFunc {
return func(source string) ([]byte, error) {
- buf := bytes.NewBuffer(make([]byte, 0))
+ buf := bytes.NewBuffer(nil)
lastCharIsSpace := false
for _, r := range strings.TrimLeft(source, " ") { // ignore heading spaces
if unicode.Is(unicode.Letter, r) || unicode.Is(unicode.Number, r) {
@@ -183,7 +182,7 @@ type ReplaceNonAlphanumericsVisitor struct {
}
func NewReplaceNonAlphanumericsVisitor() *ReplaceNonAlphanumericsVisitor {
- buf := bytes.NewBuffer(make([]byte, 0))
+ buf := bytes.NewBuffer(nil)
return &ReplaceNonAlphanumericsVisitor{
buf: *buf,
normalize: NewReplaceNonAlphanumericsFunc("_"),