Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(renderer): lazy loading of templates #1062

Merged
merged 1 commit into from
Jun 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions code-gen/renderer-templates/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"log"
"text/template"
"unicode"
)

const (
sgmlRenderer = `package sgml

import (
"sync"
text "text/template"
)

type sgmlRenderer struct {
templates Templates
functions text.FuncMap
{{ range $i, $tmpl := . }}
{{ once $tmpl}} sync.Once
{{ tmpl $tmpl}} *text.Template
{{ end }}
}

{{ range $i, $tmpl := . }}
func (r *sgmlRenderer) {{ func $tmpl }} (*text.Template, error) {
var err error
r.{{ once $tmpl }}.Do(func() {
r.{{ tmpl $tmpl }}, err = r.newTemplate("{{ $tmpl }}", r.templates.{{ $tmpl }}, err)
})
return r.{{ tmpl $tmpl }}, err
}

{{ end }}
`
)

func main() {
// read the content of pkg/renderer/sgml/templates.go
fs := token.NewFileSet()
f, err := parser.ParseFile(fs, "pkg/renderer/sgml/templates.go", nil, parser.AllErrors)
if err != nil {
log.Fatal(err)
}
v := &visitor{
fields: []string{},
}
ast.Walk(v, f)
tmpl, err := template.New("templates").Funcs(template.FuncMap{
"once": func(s string) string {
return string(unicode.ToLower(rune(s[0]))) + s[1:] + "Once"
},
"func": func(s string) string {
return string(unicode.ToLower(rune(s[0]))) + s[1:] + "()"
},
"tmpl": func(s string) string {
return string(unicode.ToLower(rune(s[0]))) + s[1:] + "Tmpl"
},
}).Parse(sgmlRenderer)
if err != nil {
log.Fatal(err)
}
// fmt.Printf("templates: %v\n", v.fields)
result := &bytes.Buffer{}
if err := tmpl.Execute(result, v.fields); err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", result.String())
}

type visitor struct {
fields []string
}

func (v *visitor) Visit(n ast.Node) ast.Visitor {
if n == nil {
return nil
}
if f, ok := n.(*ast.Field); ok {
v.fields = append(v.fields, f.Names[0].Name)
}
return v
}
12 changes: 10 additions & 2 deletions pkg/renderer/sgml/blank_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ import (

func (r *sgmlRenderer) renderLineBreak() (string, error) {
buf := &strings.Builder{}
if err := r.lineBreak.Execute(buf, nil); err != nil {
tmpl, err := r.lineBreak()
if err != nil {
return "", err
}
if err := tmpl.Execute(buf, nil); err != nil {
return "", err
}
return buf.String(), nil
}

func (r *sgmlRenderer) renderThematicBreak() (string, error) {
buf := &strings.Builder{}
if err := r.thematicBreak.Execute(buf, nil); err != nil {
tmpl, err := r.thematicBreak()
if err != nil {
return "", err
}
if err := tmpl.Execute(buf, nil); err != nil {
return "", err
}
return buf.String(), nil
Expand Down
16 changes: 3 additions & 13 deletions pkg/renderer/sgml/cross_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ func (r *sgmlRenderer) renderInternalCrossReference(ctx *renderer.Context, xref
if log.IsLevelEnabled(log.DebugLevel) {
log.Debugf("rendering cross reference with ID: %s", spew.Sdump(xref.ID))
}
result := &strings.Builder{}
var label string
xrefID, ok := xref.ID.(string)
if !ok {
Expand Down Expand Up @@ -54,45 +53,36 @@ func (r *sgmlRenderer) renderInternalCrossReference(ctx *renderer.Context, xref
} else {
label = "[" + xrefID + "]"
}
err := r.internalCrossReference.Execute(result, struct {
return r.execute(r.internalCrossReference, struct {
Href string
Label string
}{
Href: xrefID,
Label: label,
})
if err != nil {
return "", errors.Wrapf(err, "unable to render internal cross reference")
}
return result.String(), nil
}

func (r *sgmlRenderer) renderExternalCrossReference(ctx *renderer.Context, xref *types.ExternalCrossReference) (string, error) {
// log.Debugf("rendering cross reference with ID: %s", xref.Location)
result := &strings.Builder{}
var label string
var err error
switch l := xref.Attributes[types.AttrXRefLabel].(type) {
case string:
label = l
case []interface{}:
if label, err = r.renderInlineElements(ctx, l); err != nil {
return "", errors.Wrap(err, "unable to render external cross reference")
return "", err
}
default:
label = defaultXrefLabel(xref)
}
err = r.externalCrossReference.Execute(result, struct {
return r.execute(r.externalCrossReference, struct {
Href string
Label string
}{
Href: getCrossReferenceLocation(xref),
Label: label,
})
if err != nil {
return "", errors.Wrap(err, "unable to render external cross reference")
}
return result.String(), nil
}

func defaultXrefLabel(xref *types.ExternalCrossReference) string {
Expand Down
17 changes: 5 additions & 12 deletions pkg/renderer/sgml/delimited_block_admonition.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ func (r *sgmlRenderer) renderAdmonitionBlock(ctx *renderer.Context, b *types.Del
if err != nil {
return "", err
}
result := &strings.Builder{}
blocks := discardBlankLines(b.Elements)
content, err := r.renderElements(ctx, blocks)
if err != nil {
Expand All @@ -33,8 +32,7 @@ func (r *sgmlRenderer) renderAdmonitionBlock(ctx *renderer.Context, b *types.Del
if err != nil {
return "", errors.Wrap(err, "unable to render admonition block title")
}

err = r.admonitionBlock.Execute(result, struct {
return r.execute(r.admonitionBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -51,18 +49,16 @@ func (r *sgmlRenderer) renderAdmonitionBlock(ctx *renderer.Context, b *types.Del
Icon: icon,
Content: content,
})
return result.String(), err
}

func (r *sgmlRenderer) renderAdmonitionParagraph(ctx *renderer.Context, p *types.Paragraph) (string, error) {
log.Debug("rendering admonition paragraph...")
result := &strings.Builder{}
kind, ok, err := p.Attributes.GetAsString(types.AttrStyle)
if err != nil {
return "", err
}
if !ok {
return "", errors.Errorf("failed to render admonition with unknown kind: %T", p.Attributes[types.AttrStyle])
return "", errors.Errorf("failed to render admonition paragraph with unknown kind: %T", p.Attributes[types.AttrStyle])
}
kind = strings.ToLower(kind)
icon, err := r.renderIcon(ctx, types.Icon{Class: kind, Attributes: p.Attributes}, true)
Expand All @@ -75,14 +71,13 @@ func (r *sgmlRenderer) renderAdmonitionParagraph(ctx *renderer.Context, p *types
}
roles, err := r.renderElementRoles(ctx, p.Attributes)
if err != nil {
return "", errors.Wrap(err, "unable to render fenced block roles")
return "", err
}
title, err := r.renderElementTitle(ctx, p.Attributes)
if err != nil {
return "", errors.Wrap(err, "unable to render fenced block title")
return "", err
}

err = r.admonitionParagraph.Execute(result, struct {
return r.execute(r.admonitionParagraph, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -99,6 +94,4 @@ func (r *sgmlRenderer) renderAdmonitionParagraph(ctx *renderer.Context, p *types
Icon: icon,
Content: content,
})

return result.String(), err
}
18 changes: 5 additions & 13 deletions pkg/renderer/sgml/delimited_block_example.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import (
)

func (r *sgmlRenderer) renderExampleBlock(ctx *renderer.Context, b *types.DelimitedBlock) (string, error) {
result := &strings.Builder{}
caption := &strings.Builder{}

// default, example block
number := 0
content, err := r.renderElements(ctx, b.Elements)
Expand Down Expand Up @@ -47,8 +44,9 @@ func (r *sgmlRenderer) renderExampleBlock(ctx *renderer.Context, b *types.Delimi
if err != nil {
return "", errors.Wrap(err, "unable to render example block title")
}
caption := &strings.Builder{}
caption.WriteString(c)
err = r.exampleBlock.Execute(result, struct {
return r.execute(r.exampleBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -65,12 +63,10 @@ func (r *sgmlRenderer) renderExampleBlock(ctx *renderer.Context, b *types.Delimi
ExampleNumber: number,
Content: content,
})
return result.String(), err
}

func (r *sgmlRenderer) renderExampleParagraph(ctx *renderer.Context, p *types.Paragraph) (string, error) {
log.Debug("rendering example paragraph...")
result := &strings.Builder{}
content, err := r.renderElements(ctx, p.Elements)
if err != nil {
return "", errors.Wrap(err, "unable to render example paragraph content")
Expand All @@ -83,7 +79,7 @@ func (r *sgmlRenderer) renderExampleParagraph(ctx *renderer.Context, p *types.Pa
if err != nil {
return "", errors.Wrap(err, "unable to render example paragraph title")
}
err = r.exampleBlock.Execute(result, struct {
return r.execute(r.exampleBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -98,8 +94,6 @@ func (r *sgmlRenderer) renderExampleParagraph(ctx *renderer.Context, p *types.Pa
Title: title,
Content: string(content) + "\n",
})

return result.String(), err
}

func (r *sgmlRenderer) renderLiteralParagraph(ctx *renderer.Context, p *types.Paragraph) (string, error) {
Expand All @@ -118,10 +112,9 @@ func (r *sgmlRenderer) renderLiteralParagraph(ctx *renderer.Context, p *types.Pa
}
title, err := r.renderElementTitle(ctx, p.Attributes)
if err != nil {
return "", errors.Wrap(err, "unable to render callout list roles")
return "", errors.Wrap(err, "unable to render literal block roles")
}
result := &strings.Builder{}
err = r.literalBlock.Execute(result, struct {
return r.execute(r.literalBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -134,7 +127,6 @@ func (r *sgmlRenderer) renderLiteralParagraph(ctx *renderer.Context, p *types.Pa
Roles: roles,
Content: content,
})
return result.String(), err
}

// adjustHeadingSpaces removes the same number of heading spaces on each line, based on the
Expand Down
8 changes: 2 additions & 6 deletions pkg/renderer/sgml/delimited_block_fenced.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ func (r *sgmlRenderer) renderFencedBlock(ctx *renderer.Context, b *types.Delimit
ctx.WithinDelimitedBlock = previousWithinDelimitedBlock
}()
ctx.WithinDelimitedBlock = true
result := &strings.Builder{}
// lines := discardEmptyLines(b.Elements)
content, err := r.renderElements(ctx, b.Elements)
if err != nil {
return "", errors.Wrap(err, "unable to render fenced block content")
Expand All @@ -26,10 +24,9 @@ func (r *sgmlRenderer) renderFencedBlock(ctx *renderer.Context, b *types.Delimit
}
title, err := r.renderElementTitle(ctx, b.Attributes)
if err != nil {
return "", errors.Wrap(err, "unable to render callout list roles")
return "", errors.Wrap(err, "unable to render fenced block roles")
}

err = r.fencedBlock.Execute(result, struct {
return r.execute(r.fencedBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -42,5 +39,4 @@ func (r *sgmlRenderer) renderFencedBlock(ctx *renderer.Context, b *types.Delimit
Roles: roles,
Content: strings.Trim(content, "\n"),
})
return result.String(), err
}
12 changes: 3 additions & 9 deletions pkg/renderer/sgml/delimited_block_listing.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ func (r *sgmlRenderer) renderListingBlock(ctx *renderer.Context, b *types.Delimi
ctx.WithinDelimitedBlock = previousWithinDelimitedBlock
}()
ctx.WithinDelimitedBlock = true
result := &strings.Builder{}
content, err := r.renderElements(ctx, b.Elements)
if err != nil {
return "", errors.Wrap(err, "unable to render listing block content")
Expand All @@ -30,8 +29,7 @@ func (r *sgmlRenderer) renderListingBlock(ctx *renderer.Context, b *types.Delimi
if err != nil {
return "", errors.Wrap(err, "unable to render listing block title")
}

err = r.listingBlock.Execute(result, struct {
return r.execute(r.listingBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -44,11 +42,9 @@ func (r *sgmlRenderer) renderListingBlock(ctx *renderer.Context, b *types.Delimi
Roles: roles,
Content: strings.Trim(content, "\n"),
})
return result.String(), err
}

func (r *sgmlRenderer) renderListingParagraph(ctx *renderer.Context, p *types.Paragraph) (string, error) {
result := &strings.Builder{}
content, err := r.renderElements(ctx, p.Elements)
if err != nil {
return "", errors.Wrap(err, "unable to render listing block content")
Expand All @@ -59,10 +55,9 @@ func (r *sgmlRenderer) renderListingParagraph(ctx *renderer.Context, p *types.Pa
}
title, err := r.renderElementTitle(ctx, p.Attributes)
if err != nil {
return "", errors.Wrap(err, "unable to render callout list roles")
return "", errors.Wrap(err, "unable to render listing paragraph roles")
}

err = r.listingBlock.Execute(result, struct {
return r.execute(r.listingBlock, struct {
Context *renderer.Context
ID string
Title string
Expand All @@ -75,5 +70,4 @@ func (r *sgmlRenderer) renderListingParagraph(ctx *renderer.Context, p *types.Pa
Roles: roles,
Content: content,
})
return result.String(), err
}
Loading