diff options
Diffstat (limited to 'hugolib')
-rw-r--r-- | hugolib/content_render_hooks_test.go | 49 | ||||
-rw-r--r-- | hugolib/integrationtest_builder.go | 2 | ||||
-rw-r--r-- | hugolib/page__per_output.go | 108 | ||||
-rw-r--r-- | hugolib/shortcode.go | 2 |
4 files changed, 148 insertions, 13 deletions
diff --git a/hugolib/content_render_hooks_test.go b/hugolib/content_render_hooks_test.go index dbfd46459..5b2121ef8 100644 --- a/hugolib/content_render_hooks_test.go +++ b/hugolib/content_render_hooks_test.go @@ -427,3 +427,52 @@ Image: <p>html-image: image.jpg|Text: Hello<br> Goodbye|Plain: Hello GoodbyeEND</p> `) } + +func TestRenderHookContentFragmentsOnSelf(t *testing.T) { + files := ` +-- hugo.toml -- +baseURL = "https://example.org" +disableKinds = ["taxonomy", "term", "RSS", "sitemap", "robotsTXT"] +-- content/p1.md -- +--- +title: "p1" +--- + +## A {#z} +## B +## C + +-- content/p2.md -- +--- +title: "p2" +--- + +## D +## E +## F + +-- layouts/_default/_markup/render-heading.html -- +Heading: {{ .Text }}| +Self Fragments: {{ .Page.Fragments.Identifiers }}| +P1 Fragments: {{ (site.GetPage "p1.md").Fragments.Identifiers }}| +-- layouts/_default/single.html -- +{{ .Content}} +` + + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).Build() + + b.AssertFileContent("public/p1/index.html", ` +Self Fragments: [b c z] +P1 Fragments: [b c z] + `) + b.AssertFileContent("public/p2/index.html", ` +Self Fragments: [d e f] +P1 Fragments: [b c z] + `) + +} diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go index 5b457893d..f0e3c504d 100644 --- a/hugolib/integrationtest_builder.go +++ b/hugolib/integrationtest_builder.go @@ -32,6 +32,8 @@ import ( func NewIntegrationTestBuilder(conf IntegrationTestConfig) *IntegrationTestBuilder { // Code fences. conf.TxtarString = strings.ReplaceAll(conf.TxtarString, "§§§", "```") + // Multiline strings. + conf.TxtarString = strings.ReplaceAll(conf.TxtarString, "§§", "`") data := txtar.Parse([]byte(conf.TxtarString)) 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, diff --git a/hugolib/shortcode.go b/hugolib/shortcode.go index 13fe913a6..0a10d47eb 100644 --- a/hugolib/shortcode.go +++ b/hugolib/shortcode.go @@ -422,7 +422,7 @@ func doRenderShortcode( // shortcode. if sc.doMarkup && (level > 0 || sc.configVersion() == 1) { var err error - b, err := p.pageOutput.contentRenderer.RenderContent(ctx, []byte(inner), false) + b, err := p.pageOutput.contentRenderer.ParseAndRenderContent(ctx, []byte(inner), false) if err != nil { return zeroShortcode, err } |