Skip to content

Commit

Permalink
Evaluate post-summary divider HTML shortcodes
Browse files Browse the repository at this point in the history
In HTML content pages with summary dividers, shortcodes after
the summary divider are not evaluated but are simply printed
as-is within the .Content of the page.

The issue takes place in hugolib.newPageContentOutput. In this
function, we apply various transformations to cp.workContent,
and at the end of the function, make this assignment:

cp.content = helpers.BytesToHTML(cp.workContent)

If a page has a manual summary divider and is HTML, we perform
this transformation on cp.workContent:

cp.workContent = src[cp.p.source.posBodyStart:]

While this sets the workContent to all content after the
summary divider, it does so *after* newPageContentOutput
calls replaceShortcodeTokens and evaluates shortcodes. This
means that evaluated shortcodes are replaced with
unevaluated ones after the summary divider.

The fix is to reuse logic from the function we use to
evaluate the summary divider for non-HTML pages,
hugolib.splitUserDefinedSummaryAndContent. While the current
code branches on whether the page is HTML before calling
this function, this change branches within the function,
since the function already includes a "markup" parameter we
can use to perform the branching.

And since this function already splits the summary/content
while preserving evaluated shortcodes, we can reuse its splitting
logic to fix the issue.

Fixes #6513
  • Loading branch information
ptgott committed May 14, 2022
1 parent c2fa0a3 commit b2b362b
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 20 deletions.
38 changes: 18 additions & 20 deletions hugolib/page__per_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,12 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
}

if cp.p.source.hasSummaryDivider {
if isHTML {
src := p.source.parsed.Input()

// Use the summary sections as they are provided by the user.
if p.source.posSummaryEnd != -1 {
cp.summary = helpers.BytesToHTML(src[p.source.posMainContent:p.source.posSummaryEnd])
}

if cp.p.source.posBodyStart != -1 {
cp.workContent = src[cp.p.source.posBodyStart:]
}

summary, content, err := splitUserDefinedSummaryAndContent(cp.p.m.markup, cp.workContent)
if err != nil {
cp.p.s.Log.Errorf("Failed to set user defined summary for page %q: %s", cp.p.pathOrTitle(), err)
} else {
summary, content, err := splitUserDefinedSummaryAndContent(cp.p.m.markup, cp.workContent)
if err != nil {
cp.p.s.Log.Errorf("Failed to set user defined summary for page %q: %s", cp.p.pathOrTitle(), err)
} else {
cp.workContent = content
cp.summary = helpers.BytesToHTML(summary)
}
cp.workContent = content
cp.summary = helpers.BytesToHTML(summary)
}
} else if cp.p.m.summary != "" {
b, err := cp.renderContent([]byte(cp.p.m.summary), false)
Expand Down Expand Up @@ -683,6 +669,12 @@ func splitUserDefinedSummaryAndContent(markup string, c []byte) (summary []byte,
start := bytes.LastIndex(c[:startDivider], []byte("<"+startTag))
end := bytes.Index(c[startDivider:], []byte("</"+startTag))

// We don't add tags to the divider in HTML, so set the indexes to the
// "not found" value
if markup == "html" {
start, end = -1, -1
}

if start == -1 {
start = startDivider
} else {
Expand Down Expand Up @@ -717,7 +709,13 @@ func splitUserDefinedSummaryAndContent(markup string, c []byte) (summary []byte,
return
}

content = bytes.TrimSpace(withoutDivider)
// For HTML, do not include the pre-divider summary in the content. Do so
// for other markups.
if markup == "html" {
content = bytes.TrimSpace(withoutDivider[start:])
} else {
content = bytes.TrimSpace(withoutDivider)
}

return
}
72 changes: 72 additions & 0 deletions hugolib/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2098,3 +2098,75 @@ Page1: {{ $p1.Path }}

b.AssertFileContent("public/index.html", "Lang: no", filepath.FromSlash("Page1: a/B/C/Page1.md"))
}

// Issue #6513
func TestHTMLManualSummaryShortcodes(t *testing.T) {
b := newTestSitesBuilder(t).WithSimpleConfigFile()
c := qt.New(t)

b.WithTemplatesAdded(
`_default/single.html`,
`{{ .Content }}`,
`shortcodes/ten.html`,
`10`,
)

b.WithContent(
`posts/htmlwithmore.html`,
`
---
title: HTML with a manual summary
---
summary
<!--more-->
{{< ten >}}
`,
`posts/htmlwithnomore.html`,
`
---
title: HTML with a frontmatter summary
summary: summary
---
{{< ten >}}
`,
`posts/mdwithmore.md`,
`
---
title: MD with a manual summary
---
summary
<!--more-->
{{< ten >}}
`,
`posts/mdwithnomore.md`,
`
---
title: MD with a frontmatter summary
summary: summary
---
{{< ten >}}
`,
)

err := b.BuildE(BuildCfg{})

c.Assert(err, qt.Equals, nil)
// Not including the summary in the content for HTML pages
b.AssertFileContent(
"public/posts/htmlwithmore/index.html",
`10`,
)
b.AssertFileContent(
"public/posts/htmlwithnomore/index.html",
`10`,
)
b.AssertFileContent(
"public/posts/mdwithmore/index.html",
`<p>summary</p>
10`,
)
b.AssertFileContent(
"public/posts/mdwithnomore/index.html",
`10`,
)
}

0 comments on commit b2b362b

Please sign in to comment.