summaryrefslogtreecommitdiffstats
path: root/hugolib/page__per_output.go
diff options
context:
space:
mode:
Diffstat (limited to 'hugolib/page__per_output.go')
-rw-r--r--hugolib/page__per_output.go108
1 files changed, 96 insertions, 12 deletions
diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go
index 827a6b792..ce3498e0e 100644
--- a/hugolib/page__per_output.go
+++ b/hugolib/page__per_output.go
@@ -115,14 +115,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
isHTML := cp.p.m.markup == "html"
if !isHTML {
- r, err := po.contentRenderer.RenderContent(ctx, cp.workContent, true)
- if err != nil {
- return err
- }
-
- cp.workContent = r.Bytes()
-
- if tocProvider, ok := r.(converter.TableOfContentsProvider); ok {
+ createAndSetToC := func(tocProvider converter.TableOfContentsProvider) {
cfg := p.s.ContentSpec.Converters.GetMarkupConfig()
cp.tableOfContents = tocProvider.TableOfContents()
cp.tableOfContentsHTML = template.HTML(
@@ -132,6 +125,31 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
cfg.TableOfContents.Ordered,
),
)
+ }
+ // If the converter supports doing the parsing separately, we do that.
+ parseResult, ok, err := po.contentRenderer.ParseContent(ctx, cp.workContent)
+ if err != nil {
+ return err
+ }
+ if ok {
+ // This is Goldmark.
+ // Store away the parse result for later use.
+ createAndSetToC(parseResult)
+ cp.astDoc = parseResult.Doc()
+
+ return nil
+ }
+
+ // This is Asciidoctor etc.
+ r, err := po.contentRenderer.ParseAndRenderContent(ctx, cp.workContent, true)
+ if err != nil {
+ return err
+ }
+
+ cp.workContent = r.Bytes()
+
+ if tocProvider, ok := r.(converter.TableOfContentsProvider); ok {
+ createAndSetToC(tocProvider)
} else {
tmpContent, tmpTableOfContents := helpers.ExtractTOC(cp.workContent)
cp.tableOfContentsHTML = helpers.BytesToHTML(tmpTableOfContents)
@@ -153,6 +171,19 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
return nil
}
+ if cp.astDoc != nil {
+ // The content is parsed, but not rendered.
+ r, ok, err := po.contentRenderer.RenderContent(ctx, cp.workContent, cp.astDoc)
+ if err != nil {
+ return err
+ }
+ if !ok {
+ return errors.New("invalid state: astDoc is set but RenderContent returned false")
+ }
+
+ cp.workContent = r.Bytes()
+ }
+
if p.cmap.hasNonMarkdownShortcode || cp.placeholdersEnabled {
// There are one or more replacement tokens to be replaced.
var hasShortcodeVariants bool
@@ -210,7 +241,7 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
}
}
} else if cp.p.m.summary != "" {
- b, err := po.contentRenderer.RenderContent(ctx, []byte(cp.p.m.summary), false)
+ b, err := po.contentRenderer.ParseAndRenderContent(ctx, []byte(cp.p.m.summary), false)
if err != nil {
return err
}
@@ -282,6 +313,8 @@ type pageContentOutput struct {
summary template.HTML
tableOfContents *tableofcontents.Fragments
tableOfContentsHTML template.HTML
+ // For Goldmark we split Parse and Render.
+ astDoc any
truncated bool
@@ -682,15 +715,66 @@ func (p *pageContentOutput) setAutoSummary() error {
return nil
}
-func (cp *pageContentOutput) RenderContent(ctx context.Context, content []byte, renderTOC bool) (converter.Result, error) {
+func (cp *pageContentOutput) getContentConverter() (converter.Converter, error) {
if err := cp.initRenderHooks(); err != nil {
return nil, err
}
- c := cp.p.getContentConverter()
+ return cp.p.getContentConverter(), nil
+}
+
+func (cp *pageContentOutput) ParseAndRenderContent(ctx context.Context, content []byte, renderTOC bool) (converter.ResultRender, error) {
+ c, err := cp.getContentConverter()
+ if err != nil {
+ return nil, err
+ }
return cp.renderContentWithConverter(ctx, c, content, renderTOC)
}
-func (cp *pageContentOutput) renderContentWithConverter(ctx context.Context, c converter.Converter, content []byte, renderTOC bool) (converter.Result, error) {
+func (cp *pageContentOutput) ParseContent(ctx context.Context, content []byte) (converter.ResultParse, bool, error) {
+ c, err := cp.getContentConverter()
+ if err != nil {
+ return nil, false, err
+ }
+ p, ok := c.(converter.ParseRenderer)
+ if !ok {
+ return nil, ok, nil
+ }
+ rctx := converter.RenderContext{
+ Src: content,
+ RenderTOC: true,
+ GetRenderer: cp.renderHooks.getRenderer,
+ }
+ r, err := p.Parse(rctx)
+ return r, ok, err
+
+}
+func (cp *pageContentOutput) RenderContent(ctx context.Context, content []byte, doc any) (converter.ResultRender, bool, error) {
+ c, err := cp.getContentConverter()
+ if err != nil {
+ return nil, false, err
+ }
+ p, ok := c.(converter.ParseRenderer)
+ if !ok {
+ return nil, ok, nil
+ }
+ rctx := converter.RenderContext{
+ Src: content,
+ RenderTOC: true,
+ GetRenderer: cp.renderHooks.getRenderer,
+ }
+ r, err := p.Render(rctx, doc)
+ if err == nil {
+ if ids, ok := r.(identity.IdentitiesProvider); ok {
+ for _, v := range ids.GetIdentities() {
+ cp.trackDependency(v)
+ }
+ }
+ }
+
+ return r, ok, err
+}
+
+func (cp *pageContentOutput) renderContentWithConverter(ctx context.Context, c converter.Converter, content []byte, renderTOC bool) (converter.ResultRender, error) {
r, err := c.Convert(
converter.RenderContext{
Src: content,