From cdccf6f51607ed11c488ed564af2e53186757b7f Mon Sep 17 00:00:00 2001 From: Xavier Coulon Date: Sun, 19 Jan 2020 23:01:21 +0100 Subject: [PATCH] refactor(renderer): remove context.Context in renderer context type (#480) also, stop using pointer to context during rendering Fixes #479 Signed-off-by: Xavier Coulon --- cmd/libasciidoc/root_cmd.go | 3 +- libasciidoc.go | 9 +++-- pkg/renderer/context.go | 36 +++---------------- pkg/renderer/document_metadata.go | 3 +- pkg/renderer/html5/article_adoc_test.go | 5 ++- pkg/renderer/html5/blank_line.go | 2 +- pkg/renderer/html5/contextual_pipeline.go | 2 +- pkg/renderer/html5/cross_reference.go | 4 +-- pkg/renderer/html5/delimited_block.go | 20 +++++------ pkg/renderer/html5/document.go | 8 ++--- pkg/renderer/html5/document_details.go | 4 +-- pkg/renderer/html5/footnote.go | 6 ++-- pkg/renderer/html5/html5.go | 10 +++--- pkg/renderer/html5/image.go | 4 +-- pkg/renderer/html5/inline_elements.go | 4 +-- pkg/renderer/html5/labeled_list.go | 2 +- pkg/renderer/html5/link.go | 2 +- pkg/renderer/html5/literal_blocks.go | 2 +- pkg/renderer/html5/ordered_list.go | 2 +- pkg/renderer/html5/paragraph.go | 18 +++++----- pkg/renderer/html5/passthrough.go | 4 +-- pkg/renderer/html5/quoted_text.go | 2 +- pkg/renderer/html5/section.go | 6 ++-- pkg/renderer/html5/string.go | 2 +- pkg/renderer/html5/table.go | 2 +- pkg/renderer/html5/table_of_contents.go | 4 +-- pkg/renderer/html5/unordered_list.go | 2 +- pkg/renderer/html5/user_macro.go | 2 +- pkg/renderer/pre_render.go | 8 ++--- pkg/renderer/preamble.go | 7 ++-- pkg/renderer/table_of_contents.go | 3 +- test/supported_fixtures_test.go | 3 +- testsupport/document_metadata_matcher.go | 3 +- testsupport/document_metadata_matcher_test.go | 3 +- testsupport/document_preamble_matcher.go | 5 ++- testsupport/document_preamble_matcher_test.go | 5 ++- testsupport/document_toc_matcher.go | 5 ++- testsupport/html5_rendering_matcher.go | 7 ++-- 38 files changed, 92 insertions(+), 127 deletions(-) diff --git a/cmd/libasciidoc/root_cmd.go b/cmd/libasciidoc/root_cmd.go index 6b5d8752..d221cb29 100644 --- a/cmd/libasciidoc/root_cmd.go +++ b/cmd/libasciidoc/root_cmd.go @@ -1,7 +1,6 @@ package main import ( - "context" "fmt" "io" "os" @@ -49,7 +48,7 @@ func NewRootCmd() *cobra.Command { defer close() path, _ := filepath.Abs(source) log.Debugf("Starting to process file %v", path) - _, err := libasciidoc.ConvertFileToHTML(context.Background(), source, out, renderer.IncludeHeaderFooter(!noHeaderFooter)) + _, err := libasciidoc.ConvertFileToHTML(source, out, renderer.IncludeHeaderFooter(!noHeaderFooter)) if err != nil { return err } diff --git a/libasciidoc.go b/libasciidoc.go index d5181a2c..74614c52 100644 --- a/libasciidoc.go +++ b/libasciidoc.go @@ -3,7 +3,6 @@ package libasciidoc import ( - "context" "io" "os" "time" @@ -28,7 +27,7 @@ var ( // ConvertFileToHTML converts the content of the given filename into an HTML document. // The conversion result is written in the given writer `output`, whereas the document metadata (title, etc.) (or an error if a problem occurred) is returned // as the result of the function call. -func ConvertFileToHTML(ctx context.Context, filename string, output io.Writer, options ...renderer.Option) (map[string]interface{}, error) { +func ConvertFileToHTML(filename string, output io.Writer, options ...renderer.Option) (map[string]interface{}, error) { file, err := os.Open(filename) if err != nil { return nil, errors.Wrapf(err, "error opening %s", filename) @@ -40,12 +39,12 @@ func ConvertFileToHTML(ctx context.Context, filename string, output io.Writer, o return nil, errors.Wrapf(err, "error opening %s", filename) } options = append(options, renderer.LastUpdated(stat.ModTime())) - return ConvertToHTML(ctx, filename, file, output, options...) + return ConvertToHTML(filename, file, output, options...) } // ConvertToHTML converts the content of the given reader `r` into a full HTML document, written in the given writer `output`. // Returns an error if a problem occurred -func ConvertToHTML(ctx context.Context, filename string, r io.Reader, output io.Writer, options ...renderer.Option) (map[string]interface{}, error) { +func ConvertToHTML(filename string, r io.Reader, output io.Writer, options ...renderer.Option) (map[string]interface{}, error) { start := time.Now() defer func() { duration := time.Since(start) @@ -56,7 +55,7 @@ func ConvertToHTML(ctx context.Context, filename string, r io.Reader, output io. if err != nil { return nil, errors.Wrapf(err, "error while parsing the document") } - rendererCtx := renderer.Wrap(ctx, doc, options...) + rendererCtx := renderer.NewContext(doc, options...) // insert tables of contents, preamble and process file inclusions err = renderer.Prerender(rendererCtx) if err != nil { diff --git a/pkg/renderer/context.go b/pkg/renderer/context.go index f4d9817e..e0542363 100644 --- a/pkg/renderer/context.go +++ b/pkg/renderer/context.go @@ -1,10 +1,8 @@ package renderer import ( - "context" "errors" "io" - "time" "github.com/bytesparadise/libasciidoc/pkg/types" log "github.com/sirupsen/logrus" @@ -18,22 +16,20 @@ type MacroTemplate interface { // 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 options map[string]interface{} macros map[string]MacroTemplate } -// 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, options ...Option) *Context { - result := &Context{ - context: ctx, +// NewContext returns a new rendering context for the given document. +func NewContext(document types.Document, options ...Option) Context { + result := Context{ Document: document, options: make(map[string]interface{}), macros: make(map[string]MacroTemplate), } for _, option := range options { - option(result) + option(&result) } return result } @@ -162,27 +158,3 @@ func (ctx *Context) MacroTemplate(name string) (MacroTemplate, error) { } return nil, errors.New("unknown user macro: " + name) } - -// ----------------------- -// context.Context methods -// ----------------------- - -// 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.context.Done() -} - -// Err wrapper implementation of context.Context.Err() -func (ctx *Context) Err() error { - return ctx.context.Err() -} - -// Value wrapper implementation of context.Context.Value(interface{}) -func (ctx *Context) Value(key interface{}) interface{} { - return ctx.context.Value(key) -} diff --git a/pkg/renderer/document_metadata.go b/pkg/renderer/document_metadata.go index 156adb66..a2381a81 100644 --- a/pkg/renderer/document_metadata.go +++ b/pkg/renderer/document_metadata.go @@ -8,7 +8,7 @@ import ( ) // ProcessDocumentHeader includes the authors and revision in the document attributes -func ProcessDocumentHeader(ctx *Context) { +func ProcessDocumentHeader(ctx Context) Context { if authors, ok := ctx.Document.Authors(); ok { for i, author := range authors { var part1, part2, part3, email string @@ -70,6 +70,7 @@ func ProcessDocumentHeader(ctx *Context) { ctx.Document.Attributes.AddNonEmpty("revdate", revision.Revdate) ctx.Document.Attributes.AddNonEmpty("revremark", revision.Revremark) } + return ctx } func key(k string, i int) string { diff --git a/pkg/renderer/html5/article_adoc_test.go b/pkg/renderer/html5/article_adoc_test.go index 1e0f5152..57a74f44 100644 --- a/pkg/renderer/html5/article_adoc_test.go +++ b/pkg/renderer/html5/article_adoc_test.go @@ -3,7 +3,6 @@ package html5_test import ( "bufio" "bytes" - "context" "os" "github.com/bytesparadise/libasciidoc/pkg/parser" @@ -25,8 +24,8 @@ var _ = Describe("article.adoc", func() { Expect(err).ToNot(HaveOccurred()) GinkgoT().Logf("actual document: `%s`", spew.Sdump(doc)) buff := bytes.NewBuffer(nil) - rendererCtx := renderer.Wrap(context.Background(), doc) - _, err = html5.Render(rendererCtx, buff) + ctx := renderer.NewContext(doc) + _, err = html5.Render(ctx, buff) Expect(err).ToNot(HaveOccurred()) }) }) diff --git a/pkg/renderer/html5/blank_line.go b/pkg/renderer/html5/blank_line.go index 31ffe285..c31aadf9 100644 --- a/pkg/renderer/html5/blank_line.go +++ b/pkg/renderer/html5/blank_line.go @@ -7,7 +7,7 @@ import ( log "github.com/sirupsen/logrus" ) -func renderBlankLine(ctx *renderer.Context, l types.BlankLine) ([]byte, error) { //nolint:unparam +func renderBlankLine(ctx renderer.Context, l types.BlankLine) ([]byte, error) { //nolint:unparam if ctx.IncludeBlankLine() { log.Debug("rendering blankline") return []byte("\n\n"), nil diff --git a/pkg/renderer/html5/contextual_pipeline.go b/pkg/renderer/html5/contextual_pipeline.go index 8eff4c93..41c3114c 100644 --- a/pkg/renderer/html5/contextual_pipeline.go +++ b/pkg/renderer/html5/contextual_pipeline.go @@ -7,7 +7,7 @@ import ( // ContextualPipeline as structure that carries the renderer context along with // the pipeline data to process in a template or in a nested template type ContextualPipeline struct { - Context *renderer.Context + Context renderer.Context // The actual pipeline Data interface{} } diff --git a/pkg/renderer/html5/cross_reference.go b/pkg/renderer/html5/cross_reference.go index b87d0127..16b6d65d 100644 --- a/pkg/renderer/html5/cross_reference.go +++ b/pkg/renderer/html5/cross_reference.go @@ -20,7 +20,7 @@ func init() { externalCrossReferenceTmpl = newTextTemplate("external cross reference", `{{ .Label }}`) } -func renderInternalCrossReference(ctx *renderer.Context, xref types.InternalCrossReference) ([]byte, error) { +func renderInternalCrossReference(ctx renderer.Context, xref types.InternalCrossReference) ([]byte, error) { log.Debugf("rendering cross reference with ID: %s", xref.ID) result := bytes.NewBuffer(nil) var label string @@ -52,7 +52,7 @@ func renderInternalCrossReference(ctx *renderer.Context, xref types.InternalCros return result.Bytes(), nil } -func renderExternalCrossReference(ctx *renderer.Context, xref types.ExternalCrossReference) ([]byte, error) { +func renderExternalCrossReference(ctx renderer.Context, xref types.ExternalCrossReference) ([]byte, error) { log.Debugf("rendering cross reference with ID: %s", xref.Location) result := bytes.NewBuffer(nil) label, err := renderInlineElements(ctx, xref.Label) diff --git a/pkg/renderer/html5/delimited_block.go b/pkg/renderer/html5/delimited_block.go index 61eda778..19addf15 100644 --- a/pkg/renderer/html5/delimited_block.go +++ b/pkg/renderer/html5/delimited_block.go @@ -132,7 +132,7 @@ func init() { }) } -func renderDelimitedBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderDelimitedBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { log.Debugf("rendering delimited block of kind '%v'", b.Attributes[types.AttrKind]) var err error kind := b.Kind @@ -156,7 +156,7 @@ func renderDelimitedBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte } } -func renderFencedBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderFencedBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { previouslyWithin := ctx.SetWithinDelimitedBlock(true) previouslyInclude := ctx.SetIncludeBlankLine(true) defer func() { @@ -179,7 +179,7 @@ func renderFencedBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, e return result.Bytes(), err } -func renderListingBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderListingBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { previouslyWithin := ctx.SetWithinDelimitedBlock(true) previouslyInclude := ctx.SetIncludeBlankLine(true) defer func() { @@ -202,7 +202,7 @@ func renderListingBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, return result.Bytes(), err } -func renderSourceBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderSourceBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { previouslyWithin := ctx.SetWithinDelimitedBlock(true) previouslyInclude := ctx.SetIncludeBlankLine(true) defer func() { @@ -228,7 +228,7 @@ func renderSourceBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, e return result.Bytes(), err } -func renderExampleBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderExampleBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { result := bytes.NewBuffer(nil) if k, ok := b.Attributes[types.AttrAdmonitionKind].(types.AdmonitionKind); ok { err := admonitionBlockTmpl.Execute(result, ContextualPipeline{ @@ -271,7 +271,7 @@ func renderExampleBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, return result.Bytes(), err } -func renderQuoteBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderQuoteBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { result := bytes.NewBuffer(nil) err := quoteBlockTmpl.Execute(result, ContextualPipeline{ Context: ctx, @@ -290,7 +290,7 @@ func renderQuoteBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, er return result.Bytes(), err } -func renderVerseBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderVerseBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { result := bytes.NewBuffer(nil) err := verseBlockTmpl.Execute(result, ContextualPipeline{ Context: ctx, @@ -309,7 +309,7 @@ func renderVerseBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, er return result.Bytes(), err } -func renderVerseBlockElement(ctx *renderer.Context, element interface{}) ([]byte, error) { +func renderVerseBlockElement(ctx renderer.Context, element interface{}) ([]byte, error) { before := ctx.SetIncludeBlankLine(true) defer ctx.SetIncludeBlankLine(before) switch e := element.(type) { @@ -322,7 +322,7 @@ func renderVerseBlockElement(ctx *renderer.Context, element interface{}) ([]byte } } -func renderVerseBlockParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderVerseBlockParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debugf("rendering paragraph with %d line(s) within a delimited block or a list", len(p.Lines)) result := bytes.NewBuffer(nil) err := verseBlockParagraphTmpl.Execute(result, ContextualPipeline{ @@ -336,7 +336,7 @@ func renderVerseBlockParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte return result.Bytes(), err } -func renderSidebarBlock(ctx *renderer.Context, b types.DelimitedBlock) ([]byte, error) { +func renderSidebarBlock(ctx renderer.Context, b types.DelimitedBlock) ([]byte, error) { result := bytes.NewBuffer(nil) err := sidebarBlockTmpl.Execute(result, ContextualPipeline{ Context: ctx, diff --git a/pkg/renderer/html5/document.go b/pkg/renderer/html5/document.go index 1731b414..79acf76f 100644 --- a/pkg/renderer/html5/document.go +++ b/pkg/renderer/html5/document.go @@ -49,7 +49,7 @@ Last updated {{ .LastUpdated }} } // renderDocument renders the whole document, including the HEAD and BODY containers if needed -func renderDocument(ctx *renderer.Context, output io.Writer) (map[string]interface{}, error) { +func renderDocument(ctx renderer.Context, output io.Writer) (map[string]interface{}, error) { renderedTitle, err := renderDocumentTitle(ctx) if err != nil { return nil, errors.Wrapf(err, "unable to render full document") @@ -113,7 +113,7 @@ func renderDocument(ctx *renderer.Context, output io.Writer) (map[string]interfa // renderDocumentElements renders all document elements, including the footnotes, // but not the HEAD and BODY containers -func renderDocumentElements(ctx *renderer.Context) ([]byte, error) { +func renderDocumentElements(ctx renderer.Context) ([]byte, error) { elements := []interface{}{} for i, e := range ctx.Document.Elements { switch e := e.(type) { @@ -160,7 +160,7 @@ func renderDocumentElements(ctx *renderer.Context) ([]byte, error) { return buff.Bytes(), nil } -func renderDocumentTitle(ctx *renderer.Context) ([]byte, error) { +func renderDocumentTitle(ctx renderer.Context) ([]byte, error) { if documentTitle, hasTitle := ctx.Document.Title(); hasTitle { title, err := renderPlainText(ctx, documentTitle) if err != nil { @@ -171,7 +171,7 @@ func renderDocumentTitle(ctx *renderer.Context) ([]byte, error) { return nil, nil } -func renderDocumentHeader(ctx *renderer.Context) ([]byte, error) { +func renderDocumentHeader(ctx renderer.Context) ([]byte, error) { if documentTitle, hasTitle := ctx.Document.Title(); hasTitle { title, err := renderInlineElements(ctx, documentTitle) if err != nil { diff --git a/pkg/renderer/html5/document_details.go b/pkg/renderer/html5/document_details.go index b73a3e0c..8865a621 100644 --- a/pkg/renderer/html5/document_details.go +++ b/pkg/renderer/html5/document_details.go @@ -26,7 +26,7 @@ func init() {
{{ end }}`) } -func renderDocumentDetails(ctx *renderer.Context) (*htmltemplate.HTML, error) { +func renderDocumentDetails(ctx renderer.Context) (*htmltemplate.HTML, error) { if ctx.Document.Attributes.HasAuthors() { authors, err := renderDocumentAuthorsDetails(ctx) if err != nil { @@ -56,7 +56,7 @@ func renderDocumentDetails(ctx *renderer.Context) (*htmltemplate.HTML, error) { return nil, nil } -func renderDocumentAuthorsDetails(ctx *renderer.Context) (*htmltemplate.HTML, error) { +func renderDocumentAuthorsDetails(ctx renderer.Context) (*htmltemplate.HTML, error) { authorsDetailsBuff := bytes.NewBuffer(nil) i := 1 for { diff --git a/pkg/renderer/html5/footnote.go b/pkg/renderer/html5/footnote.go index 8b28148f..4328eafa 100644 --- a/pkg/renderer/html5/footnote.go +++ b/pkg/renderer/html5/footnote.go @@ -36,7 +36,7 @@ func init() { {{ end }}{{ end }} `, texttemplate.FuncMap{ - "renderFootnoteContent": func(ctx *renderer.Context, elements []interface{}) (string, error) { + "renderFootnoteContent": func(ctx renderer.Context, elements []interface{}) (string, error) { result, err := renderInlineElements(ctx, elements) if err != nil { return "", errors.Wrapf(err, "unable to render foot note content") @@ -51,7 +51,7 @@ func renderFootnoteIndex(idx int) string { return strconv.Itoa(idx + 1) } -func renderFootnote(ctx *renderer.Context, note types.Footnote) ([]byte, error) { +func renderFootnote(ctx renderer.Context, note types.Footnote) ([]byte, error) { result := bytes.NewBuffer(nil) ref := "" noteRef, hasRef := ctx.Document.FootnoteReferences[note.Ref] @@ -102,7 +102,7 @@ func renderFootnote(ctx *renderer.Context, note types.Footnote) ([]byte, error) return result.Bytes(), nil } -func renderFootnotes(ctx *renderer.Context, notes types.Footnotes) ([]byte, error) { +func renderFootnotes(ctx renderer.Context, notes types.Footnotes) ([]byte, error) { // skip if there's no foot note in the doc if len(notes) == 0 { return []byte{}, nil diff --git a/pkg/renderer/html5/html5.go b/pkg/renderer/html5/html5.go index 813f3465..e8fb2c24 100644 --- a/pkg/renderer/html5/html5.go +++ b/pkg/renderer/html5/html5.go @@ -12,11 +12,11 @@ import ( ) // Render renders the given document in HTML and writes the result in the given `writer` -func Render(ctx *renderer.Context, output io.Writer) (map[string]interface{}, error) { +func Render(ctx renderer.Context, output io.Writer) (map[string]interface{}, error) { return renderDocument(ctx, output) } -func renderElements(ctx *renderer.Context, elements []interface{}) ([]byte, error) { +func renderElements(ctx renderer.Context, elements []interface{}) ([]byte, error) { log.Debugf("rendering %d elements(s)...", len(elements)) buff := bytes.NewBuffer(nil) hasContent := false @@ -51,7 +51,7 @@ func renderElements(ctx *renderer.Context, elements []interface{}) ([]byte, erro // renderListElements is similar to the `renderElements` func above, // but it sets the `withinList` context flag to true for the first element only -func renderListElements(ctx *renderer.Context, elements []interface{}) ([]byte, error) { +func renderListElements(ctx renderer.Context, elements []interface{}) ([]byte, error) { log.Debugf("rendering list with %d element(s)...", len(elements)) buff := bytes.NewBuffer(nil) hasContent := false @@ -80,7 +80,7 @@ func renderListElements(ctx *renderer.Context, elements []interface{}) ([]byte, } // nolint: gocyclo -func renderElement(ctx *renderer.Context, element interface{}) ([]byte, error) { +func renderElement(ctx renderer.Context, element interface{}) ([]byte, error) { // log.Debugf("rendering element of type `%T`", element) switch e := element.(type) { case []interface{}: @@ -135,7 +135,7 @@ func renderElement(ctx *renderer.Context, element interface{}) ([]byte, error) { } // nolint: gocyclo -func renderPlainText(ctx *renderer.Context, element interface{}) ([]byte, error) { +func renderPlainText(ctx renderer.Context, element interface{}) ([]byte, error) { log.Debugf("rendering plain string for element of type %T", element) switch element := element.(type) { case []interface{}: diff --git a/pkg/renderer/html5/image.go b/pkg/renderer/html5/image.go index b1bbeb07..a0a7e4ec 100644 --- a/pkg/renderer/html5/image.go +++ b/pkg/renderer/html5/image.go @@ -31,7 +31,7 @@ func init() { }) } -func renderImageBlock(ctx *renderer.Context, img types.ImageBlock) ([]byte, error) { +func renderImageBlock(ctx renderer.Context, img types.ImageBlock) ([]byte, error) { result := bytes.NewBuffer(nil) title := "" if t := img.Attributes.GetAsString(types.AttrTitle); t != "" { @@ -64,7 +64,7 @@ func renderImageBlock(ctx *renderer.Context, img types.ImageBlock) ([]byte, erro return result.Bytes(), nil } -func renderInlineImage(ctx *renderer.Context, img types.InlineImage) ([]byte, error) { +func renderInlineImage(ctx renderer.Context, img types.InlineImage) ([]byte, error) { result := bytes.NewBuffer(nil) err := inlineImageTmpl.Execute(result, struct { Role string diff --git a/pkg/renderer/html5/inline_elements.go b/pkg/renderer/html5/inline_elements.go index 09f769db..308a7b35 100644 --- a/pkg/renderer/html5/inline_elements.go +++ b/pkg/renderer/html5/inline_elements.go @@ -22,7 +22,7 @@ func verbatim() renderLinesOption { } } -func renderInlineElements(ctx *renderer.Context, elements []interface{}, options ...renderLinesOption) ([]byte, error) { +func renderInlineElements(ctx renderer.Context, elements []interface{}, options ...renderLinesOption) ([]byte, error) { log.Debugf("rendering line with %d element(s)...", len(elements)) config := renderLinesConfig{ render: renderElement, @@ -55,4 +55,4 @@ func renderInlineElements(ctx *renderer.Context, elements []interface{}, options return buf.Bytes(), nil } -type renderFunc func(*renderer.Context, interface{}) ([]byte, error) +type renderFunc func(renderer.Context, interface{}) ([]byte, error) diff --git a/pkg/renderer/html5/labeled_list.go b/pkg/renderer/html5/labeled_list.go index c182039c..b8ed88f6 100644 --- a/pkg/renderer/html5/labeled_list.go +++ b/pkg/renderer/html5/labeled_list.go @@ -73,7 +73,7 @@ func init() { } -func renderLabeledList(ctx *renderer.Context, l types.LabeledList) ([]byte, error) { +func renderLabeledList(ctx renderer.Context, l types.LabeledList) ([]byte, error) { var tmpl texttemplate.Template tmpl, err := getLabeledListTmpl(l) if err != nil { diff --git a/pkg/renderer/html5/link.go b/pkg/renderer/html5/link.go index 48193860..a2fa445f 100644 --- a/pkg/renderer/html5/link.go +++ b/pkg/renderer/html5/link.go @@ -17,7 +17,7 @@ func init() { linkTmpl = newTextTemplate("external link", `{{ .Text }}`) } -func renderLink(ctx *renderer.Context, l types.InlineLink) ([]byte, error) { //nolint: unparam +func renderLink(ctx renderer.Context, l types.InlineLink) ([]byte, error) { //nolint: unparam result := bytes.NewBuffer(nil) location := l.Location.String() var text []byte diff --git a/pkg/renderer/html5/literal_blocks.go b/pkg/renderer/html5/literal_blocks.go index 41ec1562..a01d8965 100644 --- a/pkg/renderer/html5/literal_blocks.go +++ b/pkg/renderer/html5/literal_blocks.go @@ -27,7 +27,7 @@ func init() { }) } -func renderLiteralBlock(ctx *renderer.Context, b types.LiteralBlock) ([]byte, error) { +func renderLiteralBlock(ctx renderer.Context, b types.LiteralBlock) ([]byte, error) { log.Debugf("rendering delimited block with content: %s", b.Lines) var lines []string switch b.Attributes.GetAsString(types.AttrLiteralBlockType) { diff --git a/pkg/renderer/html5/ordered_list.go b/pkg/renderer/html5/ordered_list.go index 3c5375c5..a34bf1ae 100644 --- a/pkg/renderer/html5/ordered_list.go +++ b/pkg/renderer/html5/ordered_list.go @@ -30,7 +30,7 @@ func init() { } -func renderOrderedList(ctx *renderer.Context, l types.OrderedList) ([]byte, error) { +func renderOrderedList(ctx renderer.Context, l types.OrderedList) ([]byte, error) { result := bytes.NewBuffer(nil) err := orderedListTmpl.Execute(result, ContextualPipeline{ Context: ctx, diff --git a/pkg/renderer/html5/paragraph.go b/pkg/renderer/html5/paragraph.go index d45c87f0..b8857dd5 100644 --- a/pkg/renderer/html5/paragraph.go +++ b/pkg/renderer/html5/paragraph.go @@ -97,7 +97,7 @@ func init() { }) } -func renderParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { // if len(p.Lines) == 0 { // return make([]byte, 0), nil // } @@ -140,7 +140,7 @@ func renderParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { return result.Bytes(), nil } -func renderAdmonitionParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderAdmonitionParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debug("rendering admonition paragraph...") result := bytes.NewBuffer(nil) k, ok := p.Attributes[types.AttrAdmonitionKind].(types.AdmonitionKind) @@ -168,7 +168,7 @@ func renderAdmonitionParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte return result.Bytes(), err } -func renderSourceParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderSourceParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debug("rendering source paragraph...") result := bytes.NewBuffer(nil) err := sourceParagraphTmpl.Execute(result, ContextualPipeline{ @@ -188,7 +188,7 @@ func renderSourceParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, er return result.Bytes(), err } -func renderVerseParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderVerseParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debug("rendering verse paragraph...") result := bytes.NewBuffer(nil) err := verseParagraphTmpl.Execute(result, ContextualPipeline{ @@ -208,7 +208,7 @@ func renderVerseParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, err return result.Bytes(), err } -func renderQuoteParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderQuoteParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debug("rendering quote paragraph...") result := bytes.NewBuffer(nil) err := quoteParagraphTmpl.Execute(result, ContextualPipeline{ @@ -228,7 +228,7 @@ func renderQuoteParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, err return result.Bytes(), err } -func renderDelimitedBlockParagraph(ctx *renderer.Context, p types.Paragraph) ([]byte, error) { +func renderDelimitedBlockParagraph(ctx renderer.Context, p types.Paragraph) ([]byte, error) { log.Debugf("rendering paragraph with %d line(s) within a delimited block or a list", len(p.Lines)) result := bytes.NewBuffer(nil) err := delimitedBlockParagraphTmpl.Execute(result, ContextualPipeline{ @@ -259,7 +259,7 @@ func renderCheckStyle(style interface{}) string { } } -func renderIconClass(ctx *renderer.Context, kind types.AdmonitionKind) string { +func renderIconClass(ctx renderer.Context, kind types.AdmonitionKind) string { if icons, _ := ctx.Document.Attributes.GetAsString("icons"); icons == "font" { return renderClass(kind) } @@ -343,7 +343,7 @@ func PlainText() RenderLinesOption { // renderLines renders all lines (i.e, all `InlineElements`` - each `InlineElements` being a slice of elements to generate a line) // and includes an `\n` character in-between, until the last one. // Trailing spaces are removed for each line. -func renderLines(ctx *renderer.Context, lines [][]interface{}, options ...RenderLinesOption) ([]byte, error) { // renderLineFunc renderFunc, hardbreak bool +func renderLines(ctx renderer.Context, lines [][]interface{}, options ...RenderLinesOption) ([]byte, error) { // renderLineFunc renderFunc, hardbreak bool config := RenderLinesConfig{ render: renderLine, hardbreaks: false, @@ -381,7 +381,7 @@ func renderLines(ctx *renderer.Context, lines [][]interface{}, options ...Render return buf.Bytes(), nil } -func renderLine(ctx *renderer.Context, element interface{}) ([]byte, error) { +func renderLine(ctx renderer.Context, element interface{}) ([]byte, error) { if elements, ok := element.([]interface{}); ok { return renderInlineElements(ctx, elements) } diff --git a/pkg/renderer/html5/passthrough.go b/pkg/renderer/html5/passthrough.go index 5da38849..326af044 100644 --- a/pkg/renderer/html5/passthrough.go +++ b/pkg/renderer/html5/passthrough.go @@ -9,7 +9,7 @@ import ( "github.com/pkg/errors" ) -func renderPassthrough(ctx *renderer.Context, p types.Passthrough) ([]byte, error) { +func renderPassthrough(ctx renderer.Context, p types.Passthrough) ([]byte, error) { renderedContent, err := renderPassthroughContent(ctx, p) if err != nil { return nil, errors.Wrap(err, "unable to render passthrough") @@ -26,7 +26,7 @@ func renderPassthrough(ctx *renderer.Context, p types.Passthrough) ([]byte, erro } // renderPassthroughMacro renders the passthrough content in ist raw from -func renderPassthroughContent(ctx *renderer.Context, p types.Passthrough) ([]byte, error) { +func renderPassthroughContent(ctx renderer.Context, p types.Passthrough) ([]byte, error) { buf := bytes.NewBuffer(nil) for _, element := range p.Elements { switch element := element.(type) { diff --git a/pkg/renderer/html5/quoted_text.go b/pkg/renderer/html5/quoted_text.go index 14d46288..c626d475 100644 --- a/pkg/renderer/html5/quoted_text.go +++ b/pkg/renderer/html5/quoted_text.go @@ -25,7 +25,7 @@ func init() { superscriptTextTmpl = newTextTemplate("superscript text", "{{ . }}") } -func renderQuotedText(ctx *renderer.Context, t types.QuotedText) ([]byte, error) { +func renderQuotedText(ctx renderer.Context, t types.QuotedText) ([]byte, error) { elementsBuffer := bytes.NewBuffer(nil) for _, element := range t.Elements { b, err := renderElement(ctx, element) diff --git a/pkg/renderer/html5/section.go b/pkg/renderer/html5/section.go index ea2c36c4..2d1f1916 100644 --- a/pkg/renderer/html5/section.go +++ b/pkg/renderer/html5/section.go @@ -51,7 +51,7 @@ func init() { `{{ .Content }}`) } -func renderPreamble(ctx *renderer.Context, p types.Preamble) ([]byte, error) { +func renderPreamble(ctx renderer.Context, p types.Preamble) ([]byte, error) { log.Debugf("rendering preamble...") result := bytes.NewBuffer(nil) // the
wrapper is only necessary @@ -77,7 +77,7 @@ func renderPreamble(ctx *renderer.Context, p types.Preamble) ([]byte, error) { return result.Bytes(), nil } -func renderSection(ctx *renderer.Context, s types.Section) ([]byte, error) { +func renderSection(ctx renderer.Context, s types.Section) ([]byte, error) { log.Debugf("rendering section level %d", s.Level) renderedSectionTitle, err := renderSectionTitle(ctx, s) if err != nil { @@ -109,7 +109,7 @@ func renderSection(ctx *renderer.Context, s types.Section) ([]byte, error) { return result.Bytes(), nil } -func renderSectionTitle(ctx *renderer.Context, s types.Section) (string, error) { +func renderSectionTitle(ctx renderer.Context, s types.Section) (string, error) { result := bytes.NewBuffer(nil) renderedContent, err := renderInlineElements(ctx, s.Title) if err != nil { diff --git a/pkg/renderer/html5/string.go b/pkg/renderer/html5/string.go index e8dba70c..475aa83c 100644 --- a/pkg/renderer/html5/string.go +++ b/pkg/renderer/html5/string.go @@ -15,7 +15,7 @@ var stringTmpl = newTextTemplate("string element", "{{ escape . }}", "escape": EscapeString, }) -func renderStringElement(ctx *renderer.Context, str types.StringElement) ([]byte, error) { //nolint: unparam +func renderStringElement(ctx renderer.Context, str types.StringElement) ([]byte, error) { //nolint: unparam buf := bytes.NewBuffer(nil) err := stringTmpl.Execute(buf, str.Content) if err != nil { diff --git a/pkg/renderer/html5/table.go b/pkg/renderer/html5/table.go index 40744072..7c16b82b 100644 --- a/pkg/renderer/html5/table.go +++ b/pkg/renderer/html5/table.go @@ -39,7 +39,7 @@ func init() { }) } -func renderTable(ctx *renderer.Context, t types.Table) ([]byte, error) { +func renderTable(ctx renderer.Context, t types.Table) ([]byte, error) { result := bytes.NewBuffer(nil) // inspect first line to obtain cell width ratio widths := []string{} diff --git a/pkg/renderer/html5/table_of_contents.go b/pkg/renderer/html5/table_of_contents.go index 26fe2914..796fe96a 100644 --- a/pkg/renderer/html5/table_of_contents.go +++ b/pkg/renderer/html5/table_of_contents.go @@ -47,7 +47,7 @@ type TableOfContentsSection struct { Elements template.HTML } -func renderTableOfContents(ctx *renderer.Context, m types.TableOfContentsMacro) ([]byte, error) { //nolint:unparam +func renderTableOfContents(ctx renderer.Context, m types.TableOfContentsMacro) ([]byte, error) { //nolint:unparam log.Debug("rendering table of contents...") renderedSections, err := renderTableOfContentsSections(ctx, ctx.Document.Elements, 1) if err != nil { @@ -68,7 +68,7 @@ func renderTableOfContents(ctx *renderer.Context, m types.TableOfContentsMacro) return result.Bytes(), nil } -func renderTableOfContentsSections(ctx *renderer.Context, elements []interface{}, currentLevel int) (template.HTML, error) { +func renderTableOfContentsSections(ctx renderer.Context, elements []interface{}, currentLevel int) (template.HTML, error) { sections := make([]TableOfContentsSection, 0) for _, element := range elements { log.Debugf("traversing document element of type %T", element) diff --git a/pkg/renderer/html5/unordered_list.go b/pkg/renderer/html5/unordered_list.go index 1eacda34..14edc544 100644 --- a/pkg/renderer/html5/unordered_list.go +++ b/pkg/renderer/html5/unordered_list.go @@ -28,7 +28,7 @@ func init() { }) } -func renderUnorderedList(ctx *renderer.Context, l types.UnorderedList) ([]byte, error) { +func renderUnorderedList(ctx renderer.Context, l types.UnorderedList) ([]byte, error) { // make sure nested elements are aware of that their rendering occurs within a list checkList := false if len(l.Items) > 0 { diff --git a/pkg/renderer/html5/user_macro.go b/pkg/renderer/html5/user_macro.go index e13005bb..d0b5916c 100644 --- a/pkg/renderer/html5/user_macro.go +++ b/pkg/renderer/html5/user_macro.go @@ -7,7 +7,7 @@ import ( "github.com/bytesparadise/libasciidoc/pkg/types" ) -func renderUserMacro(ctx *renderer.Context, um types.UserMacro) ([]byte, error) { +func renderUserMacro(ctx renderer.Context, um types.UserMacro) ([]byte, error) { buf := bytes.NewBuffer([]byte{}) macro, err := ctx.MacroTemplate(um.Name) if err != nil { diff --git a/pkg/renderer/pre_render.go b/pkg/renderer/pre_render.go index 585cf477..aa9b8447 100644 --- a/pkg/renderer/pre_render.go +++ b/pkg/renderer/pre_render.go @@ -9,10 +9,10 @@ import ( // - wraps elements in a preamble // - generates the ToC // - processes the document headers (added in the document attributes) -func Prerender(ctx *Context) error { - IncludePreamble(ctx) - IncludeTableOfContents(ctx) - ProcessDocumentHeader(ctx) +func Prerender(ctx Context) error { + ctx = IncludePreamble(ctx) + ctx = IncludeTableOfContents(ctx) + ctx = ProcessDocumentHeader(ctx) if log.IsLevelEnabled(log.DebugLevel) { log.Debug("pre-rendered document:") spew.Dump(ctx.Document) diff --git a/pkg/renderer/preamble.go b/pkg/renderer/preamble.go index 5b096154..ef0623b0 100644 --- a/pkg/renderer/preamble.go +++ b/pkg/renderer/preamble.go @@ -7,13 +7,14 @@ import ( // IncludePreamble wraps all document elements before the first section in a `Preamble`, // unless the document has no section. Returns a new document with the changes. -func IncludePreamble(ctx *Context) { +func IncludePreamble(ctx Context) Context { if header, ok := ctx.Document.Header(); ok { header.Elements = insertPreamble(header.Elements) ctx.Document.Elements[0] = header // need to update the header in the parent doc as we don't use pointers here. - return + } else { + ctx.Document.Elements = insertPreamble(ctx.Document.Elements) } - ctx.Document.Elements = insertPreamble(ctx.Document.Elements) + return ctx } func insertPreamble(blocks []interface{}) []interface{} { diff --git a/pkg/renderer/table_of_contents.go b/pkg/renderer/table_of_contents.go index df40534b..9577aedc 100644 --- a/pkg/renderer/table_of_contents.go +++ b/pkg/renderer/table_of_contents.go @@ -7,10 +7,11 @@ import ( // IncludeTableOfContents includes a Table Of Contents in the document // if the `toc` attribute is present -func IncludeTableOfContents(ctx *Context) { +func IncludeTableOfContents(ctx Context) Context { if t, found := ctx.Document.Attributes.GetAsString(types.AttrTableOfContents); found { ctx.Document = insertTableOfContents(ctx.Document, t) } + return ctx } func insertTableOfContents(doc types.Document, location string) types.Document { diff --git a/test/supported_fixtures_test.go b/test/supported_fixtures_test.go index 7e45886b..626331c6 100644 --- a/test/supported_fixtures_test.go +++ b/test/supported_fixtures_test.go @@ -2,7 +2,6 @@ package test_test import ( "bytes" - "context" "io/ioutil" "os/exec" "path/filepath" @@ -79,7 +78,7 @@ func entries(pattern string) []TableEntry { func convert(sourcePath string) (string, error) { // generate the HTML output buff := bytes.NewBuffer(nil) - _, err := libasciidoc.ConvertFileToHTML(context.Background(), sourcePath, buff) + _, err := libasciidoc.ConvertFileToHTML(sourcePath, buff) if err != nil { return "", err } diff --git a/testsupport/document_metadata_matcher.go b/testsupport/document_metadata_matcher.go index 2b0c9e28..bc2242c2 100644 --- a/testsupport/document_metadata_matcher.go +++ b/testsupport/document_metadata_matcher.go @@ -1,7 +1,6 @@ package testsupport import ( - "context" "fmt" "github.com/bytesparadise/libasciidoc/pkg/renderer" @@ -29,7 +28,7 @@ func (m *metadataMatcher) Match(actual interface{}) (success bool, err error) { if !ok { return false, errors.Errorf("HaveMetadata matcher expects a Document (actual: %T)", actual) } - ctx := renderer.Wrap(context.Background(), source) + ctx := renderer.NewContext(source) renderer.ProcessDocumentHeader(ctx) m.actual = ctx.Document.Attributes m.comparison = compare(m.actual, m.expected) diff --git a/testsupport/document_metadata_matcher_test.go b/testsupport/document_metadata_matcher_test.go index 853929ef..8eb2bf45 100644 --- a/testsupport/document_metadata_matcher_test.go +++ b/testsupport/document_metadata_matcher_test.go @@ -1,7 +1,6 @@ package testsupport_test import ( - "context" "fmt" "github.com/bytesparadise/libasciidoc/pkg/renderer" @@ -54,7 +53,7 @@ var _ = Describe("document metadata assertions", func() { Expect(err).ToNot(HaveOccurred()) Expect(result).To(BeFalse()) // also verify the messages - ctx := renderer.Wrap(context.Background(), actual) + ctx := renderer.NewContext(actual) renderer.ProcessDocumentHeader(ctx) obtained := ctx.Document.Attributes Expect(matcher.FailureMessage(actual)).To(Equal(fmt.Sprintf("expected document metadata to match:\n%s", compare(obtained, expected)))) diff --git a/testsupport/document_preamble_matcher.go b/testsupport/document_preamble_matcher.go index 73b1032b..cfc387a9 100644 --- a/testsupport/document_preamble_matcher.go +++ b/testsupport/document_preamble_matcher.go @@ -1,7 +1,6 @@ package testsupport import ( - "context" "fmt" "github.com/bytesparadise/libasciidoc/pkg/renderer" @@ -29,8 +28,8 @@ func (m *preambleMatcher) Match(actual interface{}) (success bool, err error) { if !ok { return false, errors.Errorf("HavePreamble matcher expects a Document (actual: %T)", actual) } - ctx := renderer.Wrap(context.Background(), doc) - renderer.IncludePreamble(ctx) + ctx := renderer.NewContext(doc) + ctx = renderer.IncludePreamble(ctx) m.actual = ctx.Document m.comparison = compare(m.actual, m.expected) return m.comparison.diffs == "", nil diff --git a/testsupport/document_preamble_matcher_test.go b/testsupport/document_preamble_matcher_test.go index c6721cb2..a34ed38e 100644 --- a/testsupport/document_preamble_matcher_test.go +++ b/testsupport/document_preamble_matcher_test.go @@ -1,7 +1,6 @@ package testsupport_test import ( - "context" "fmt" "github.com/bytesparadise/libasciidoc/pkg/renderer" @@ -105,8 +104,8 @@ var _ = Describe("document preamble assertions", func() { Expect(err).ToNot(HaveOccurred()) Expect(result).To(BeFalse()) // also verify messages - ctx := renderer.Wrap(context.Background(), actual) - renderer.IncludePreamble(ctx) + ctx := renderer.NewContext(actual) + ctx = renderer.IncludePreamble(ctx) obtained := ctx.Document GinkgoT().Logf(matcher.FailureMessage(actual)) GinkgoT().Logf(fmt.Sprintf("expected documents to match:\n%s", compare(obtained, expected))) diff --git a/testsupport/document_toc_matcher.go b/testsupport/document_toc_matcher.go index b44c58f6..6f0cbe71 100644 --- a/testsupport/document_toc_matcher.go +++ b/testsupport/document_toc_matcher.go @@ -1,7 +1,6 @@ package testsupport import ( - "context" "fmt" "github.com/bytesparadise/libasciidoc/pkg/renderer" @@ -29,8 +28,8 @@ func (m *tocMatcher) Match(actual interface{}) (success bool, err error) { if !ok { return false, errors.Errorf("HaveTableOfContents matcher expects a Document (actual: %T)", actual) } - ctx := renderer.Wrap(context.Background(), doc) - renderer.IncludeTableOfContents(ctx) + ctx := renderer.NewContext(doc) + ctx = renderer.IncludeTableOfContents(ctx) m.actual = ctx.Document m.comparison = compare(m.actual, m.expected) return m.comparison.diffs == "", nil diff --git a/testsupport/html5_rendering_matcher.go b/testsupport/html5_rendering_matcher.go index c0d9bcd6..d03c955a 100644 --- a/testsupport/html5_rendering_matcher.go +++ b/testsupport/html5_rendering_matcher.go @@ -2,7 +2,6 @@ package testsupport import ( "bytes" - "context" "fmt" "os" "strings" @@ -55,7 +54,7 @@ func (m *html5BodyMatcher) Match(actual interface{}) (success bool, err error) { } contentReader := strings.NewReader(content) resultWriter := bytes.NewBuffer(nil) - metadata, err := libasciidoc.ConvertToHTML(context.Background(), m.filename, contentReader, resultWriter, m.opts...) + metadata, err := libasciidoc.ConvertToHTML(m.filename, contentReader, resultWriter, m.opts...) if err != nil { return false, err } @@ -112,7 +111,7 @@ func (m *html5TitleMatcher) Match(actual interface{}) (success bool, err error) } contentReader := strings.NewReader(content) resultWriter := bytes.NewBuffer(nil) - metadata, err := libasciidoc.ConvertToHTML(context.Background(), m.filename, contentReader, resultWriter, renderer.IncludeHeaderFooter(false)) + metadata, err := libasciidoc.ConvertToHTML(m.filename, contentReader, resultWriter, renderer.IncludeHeaderFooter(false)) if err != nil { return false, err } @@ -164,7 +163,7 @@ func (m *html5DocumentMatcher) Match(actual interface{}) (success bool, err erro return false, errors.Errorf("RenderHTML5Body matcher expects a string (actual: %T)", actual) } resultWriter := bytes.NewBuffer(nil) - _, err = libasciidoc.ConvertFileToHTML(context.Background(), filename, resultWriter, renderer.IncludeHeaderFooter(true)) + _, err = libasciidoc.ConvertFileToHTML(filename, resultWriter, renderer.IncludeHeaderFooter(true)) if err != nil { return false, err }