mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-29 22:29:56 +02:00
Split parse and render for Goldmark
This also speeds up situations where you only need the fragments/toc and not the rendered content, e.g. Related with fragments type indexing: ```bash name old time/op new time/op delta RelatedSite-10 12.3ms ± 2% 10.7ms ± 1% -12.95% (p=0.029 n=4+4) name old alloc/op new alloc/op delta RelatedSite-10 38.6MB ± 0% 38.2MB ± 0% -1.08% (p=0.029 n=4+4) name old allocs/op new allocs/op delta RelatedSite-10 117k ± 0% 115k ± 0% -1.36% (p=0.029 n=4+4) ``` Fixes #10750
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"bytes"
|
||||
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
|
||||
"github.com/gohugoio/hugo/markup/goldmark/codeblocks"
|
||||
"github.com/gohugoio/hugo/markup/goldmark/images"
|
||||
"github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
|
||||
@@ -26,6 +27,7 @@ import (
|
||||
"github.com/gohugoio/hugo/markup/converter"
|
||||
"github.com/gohugoio/hugo/markup/tableofcontents"
|
||||
"github.com/yuin/goldmark"
|
||||
"github.com/yuin/goldmark/ast"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
@@ -158,26 +160,41 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown {
|
||||
|
||||
var _ identity.IdentitiesProvider = (*converterResult)(nil)
|
||||
|
||||
type converterResult struct {
|
||||
converter.Result
|
||||
type parserResult struct {
|
||||
doc any
|
||||
toc *tableofcontents.Fragments
|
||||
}
|
||||
|
||||
func (p parserResult) Doc() any {
|
||||
return p.doc
|
||||
}
|
||||
|
||||
func (p parserResult) TableOfContents() *tableofcontents.Fragments {
|
||||
return p.toc
|
||||
}
|
||||
|
||||
type renderResult struct {
|
||||
converter.ResultRender
|
||||
ids identity.Identities
|
||||
}
|
||||
|
||||
func (c converterResult) TableOfContents() *tableofcontents.Fragments {
|
||||
return c.toc
|
||||
func (r renderResult) GetIdentities() identity.Identities {
|
||||
return r.ids
|
||||
}
|
||||
|
||||
func (c converterResult) GetIdentities() identity.Identities {
|
||||
return c.ids
|
||||
type converterResult struct {
|
||||
converter.ResultRender
|
||||
tableOfContentsProvider
|
||||
identity.IdentitiesProvider
|
||||
}
|
||||
|
||||
type tableOfContentsProvider interface {
|
||||
TableOfContents() *tableofcontents.Fragments
|
||||
}
|
||||
|
||||
var converterIdentity = identity.KeyValueIdentity{Key: "goldmark", Value: "converter"}
|
||||
|
||||
func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result converter.Result, err error) {
|
||||
|
||||
buf := &render.BufWriter{Buffer: &bytes.Buffer{}}
|
||||
result = buf
|
||||
func (c *goldmarkConverter) Parse(ctx converter.RenderContext) (converter.ResultParse, error) {
|
||||
pctx := c.newParserContext(ctx)
|
||||
reader := text.NewReader(ctx.Src)
|
||||
|
||||
@@ -186,6 +203,16 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
|
||||
parser.WithContext(pctx),
|
||||
)
|
||||
|
||||
return parserResult{
|
||||
doc: doc,
|
||||
toc: pctx.TableOfContents(),
|
||||
}, nil
|
||||
|
||||
}
|
||||
func (c *goldmarkConverter) Render(ctx converter.RenderContext, doc any) (converter.ResultRender, error) {
|
||||
n := doc.(ast.Node)
|
||||
buf := &render.BufWriter{Buffer: &bytes.Buffer{}}
|
||||
|
||||
rcx := &render.RenderContextDataHolder{
|
||||
Rctx: ctx,
|
||||
Dctx: c.ctx,
|
||||
@@ -197,15 +224,32 @@ func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (result convert
|
||||
ContextData: rcx,
|
||||
}
|
||||
|
||||
if err := c.md.Renderer().Render(w, ctx.Src, doc); err != nil {
|
||||
if err := c.md.Renderer().Render(w, ctx.Src, n); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return converterResult{
|
||||
Result: buf,
|
||||
ids: rcx.IDs.GetIdentities(),
|
||||
toc: pctx.TableOfContents(),
|
||||
return renderResult{
|
||||
ResultRender: buf,
|
||||
ids: rcx.IDs.GetIdentities(),
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (c *goldmarkConverter) Convert(ctx converter.RenderContext) (converter.ResultRender, error) {
|
||||
parseResult, err := c.Parse(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
renderResult, err := c.Render(ctx, parseResult.Doc())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return converterResult{
|
||||
ResultRender: renderResult,
|
||||
tableOfContentsProvider: parseResult,
|
||||
IdentitiesProvider: renderResult.(identity.IdentitiesProvider),
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
var featureSet = map[identity.Identity]bool{
|
||||
|
@@ -34,7 +34,7 @@ import (
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func convert(c *qt.C, mconf markup_config.Config, content string) converter.Result {
|
||||
func convert(c *qt.C, mconf markup_config.Config, content string) converter.ResultRender {
|
||||
p, err := Provider.New(
|
||||
converter.ProviderConfig{
|
||||
MarkupConfig: mconf,
|
||||
|
Reference in New Issue
Block a user