Repository: gohugoio/hugo (language: go)

Issue:
content adapter: Handle <!--more--> separator in content.value
This may not be possible, in which case we should add a note to the [content adapter documentation](https://gohugo.io/content-management/content-adapters/).

```go
func TestFoo(t *testing.T) {
	t.Parallel()

	files := `
-- hugo.toml --
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
[markup.goldmark.renderer]
unsafe = true
-- content/s1/_content.gotmpl --
{{ $page := dict
	"content" (dict "mediaType" "text/markdown" "value" "aaa <!--more--> bbb")
	"title" "p1"
	"path" "p1"
  }}
  {{ .AddPage $page }}
-- layouts/_default/single.html --
summary: {{ .Summary }}|content: {{ .Content}}
`

	b := hugolib.Test(t, files)

	b.AssertFileContent("public/s1/p1/index.html",
		"summary: aaa|content: <p>aaa bbb</p>",
	)
}
```

The file content assertion fails. Actual content is:

```text
summary: aaa bbb|content: <p>aaa <!--more--> bbb</p>
```

Note that (a) the summary isn't correct and (b) the `<--more-->` separator is passed through to content.

Reference: <https://discourse.gohugo.io/t/content-adapters-content-summary-not-works/50096/>


Discussion / hints:

Fix patch:
diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go
index 5b039b91b04..6dffd18a579 100644
--- a/hugolib/page__per_output.go
+++ b/hugolib/page__per_output.go
@@ -307,7 +307,10 @@ func (pco *pageContentOutput) RenderString(ctx context.Context, args ...any) (te
 	if pageparser.HasShortcode(contentToRender) {
 		contentToRenderb := []byte(contentToRender)
 		// String contains a shortcode.
-		parseInfo.itemsStep1, err = pageparser.ParseBytesMain(contentToRenderb, pageparser.Config{})
+		parseInfo.itemsStep1, err = pageparser.ParseBytes(contentToRenderb, pageparser.Config{
+			NoFrontMatter:    true,
+			NoSummaryDivider: true,
+		})
 		if err != nil {
 			return "", err
 		}
diff --git a/parser/pageparser/pagelexer.go b/parser/pageparser/pagelexer.go
index e3b0f1e5468..a5f64b0371b 100644
--- a/parser/pageparser/pagelexer.go
+++ b/parser/pageparser/pagelexer.go
@@ -63,16 +63,18 @@ func (l *pageLexer) Input() []byte {
 }
 
 type Config struct {
-	NoFrontMatter bool
+	NoFrontMatter    bool
+	NoSummaryDivider bool
 }
 
 // note: the input position here is normally 0 (start), but
 // can be set if position of first shortcode is known
 func newPageLexer(input []byte, stateStart stateFunc, cfg Config) *pageLexer {
 	lexer := &pageLexer{
-		input:      input,
-		stateStart: stateStart,
-		cfg:        cfg,
+		input:          input,
+		stateStart:     stateStart,
+		summaryDivider: summaryDivider,
+		cfg:            cfg,
 		lexerShortcodeState: lexerShortcodeState{
 			currLeftDelimItem:  tLeftDelimScNoMarkup,
 			currRightDelimItem: tRightDelimScNoMarkup,
@@ -297,6 +299,8 @@ func (s *sectionHandlers) skip() int {
 }
 
 func createSectionHandlers(l *pageLexer) *sectionHandlers {
+	handlers := make([]*sectionHandler, 0, 2)
+
 	shortCodeHandler := &sectionHandler{
 		l: l,
 		skipFunc: func(l *pageLexer) int {
@@ -332,30 +336,35 @@ func createSectionHandlers(l *pageLexer) *sectionHandlers {
 		},
 	}
 
-	summaryDividerHandler := &sectionHandler{
-		l: l,
-		skipFunc: func(l *pageLexer) int {
-			if l.summaryDividerChecked || l.summaryDivider == nil {
-				return -1
-			}
-			return l.index(l.summaryDivider)
-		},
-		lexFunc: func(origin stateFunc, l *pageLexer) (stateFunc, bool) {
-			if !l.hasPrefix(l.summaryDivider) {
-				return origin, false
-			}
+	handlers = append(handlers, shortCodeHandler)
 
-			l.summaryDividerChecked = true
-			l.pos += len(l.summaryDivider)
-			// This makes it a little easier to reason about later.
-			l.consumeSpace()
-			l.emit(TypeLeadSummaryDivider)
+	if !l.cfg.NoSummaryDivider {
+		summaryDividerHandler := &sectionHandler{
+			l: l,
+			skipFunc: func(l *pageLexer) int {
+				if l.summaryDividerChecked {
+					return -1
+				}
+				return l.index(l.summaryDivider)
+			},
+			lexFunc: func(origin stateFunc, l *pageLexer) (stateFunc, bool) {
+				if !l.hasPrefix(l.summaryDivider) {
+					return origin, false
+				}
 
-			return origin, true
-		},
-	}
+				l.summaryDividerChecked = true
+				l.pos += len(l.summaryDivider)
+				// This makes it a little easier to reason about later.
+				l.consumeSpace()
+				l.emit(TypeLeadSummaryDivider)
 
-	handlers := []*sectionHandler{shortCodeHandler, summaryDividerHandler}
+				return origin, true
+			},
+		}
+
+		handlers = append(handlers, summaryDividerHandler)
+
+	}
 
 	return &sectionHandlers{
 		l:           l,
diff --git a/parser/pageparser/pagelexer_intro.go b/parser/pageparser/pagelexer_intro.go
index 0ff0958fee5..925c61c9e58 100644
--- a/parser/pageparser/pagelexer_intro.go
+++ b/parser/pageparser/pagelexer_intro.go
@@ -14,8 +14,6 @@
 package pageparser
 
 func lexIntroSection(l *pageLexer) stateFunc {
-	l.summaryDivider = summaryDivider
-
 LOOP:
 	for {
 		r := l.next()
diff --git a/parser/pageparser/pageparser.go b/parser/pageparser/pageparser.go
index 988a80c83cf..1cf87bb70c8 100644
--- a/parser/pageparser/pageparser.go
+++ b/parser/pageparser/pageparser.go
@@ -47,15 +47,6 @@ func ParseBytes(b []byte, cfg Config) (Items, error) {
 	return l.items, l.err
 }
 
-// ParseBytesMain parses b starting with the main section.
-func ParseBytesMain(b []byte, cfg Config) (Items, error) {
-	l, err := parseBytes(b, cfg, lexMainSection)
-	if err != nil {
-		return nil, err
-	}
-	return l.items, l.err
-}
-
 type ContentFrontMatter struct {
 	Content           []byte
 	FrontMatter       map[string]any


Test patch:
diff --git a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
index cbb2da75c86..f351cbb9871 100644
--- a/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
+++ b/hugolib/pagesfromdata/pagesfromgotmpl_integration_test.go
@@ -643,3 +643,29 @@ Footer: {{ range index site.Menus.footer }}{{ .Name }}|{{ end }}|
 		"Footer: Footer|p2||",
 	)
 }
+
+func TestPagesFromGoTmplMore(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- hugo.toml --
+disableKinds = ['home','rss','section','sitemap','taxonomy','term']
+[markup.goldmark.renderer]
+unsafe = true
+-- content/s1/_content.gotmpl --
+{{ $page := dict
+	"content" (dict "mediaType" "text/markdown" "value" "aaa <!--more--> bbb")
+	"title" "p1"
+	"path" "p1"
+  }}
+  {{ .AddPage $page }}
+-- layouts/_default/single.html --
+summary: {{ .Summary }}|content: {{ .Content}}
+`
+
+	b := hugolib.Test(t, files)
+
+	b.AssertFileContent("public/s1/p1/index.html",
+		"<p>aaa</p>|content: <p>aaa</p>\n<p>bbb</p>",
+	)
+}
diff --git a/parser/pageparser/pageparser_test.go b/parser/pageparser/pageparser_test.go
index a50ab46e9d7..c6bedbd6fd3 100644
--- a/parser/pageparser/pageparser_test.go
+++ b/parser/pageparser/pageparser_test.go
@@ -101,3 +101,14 @@ func BenchmarkHasShortcode(b *testing.B) {
 		}
 	})
 }
+
+func TestSummaryDividerStartingFromMain(t *testing.T) {
+	c := qt.New(t)
+
+	input := `aaa <!--more--> bbb`
+	items, err := collectStringMain(input)
+	c.Assert(err, qt.IsNil)
+
+	c.Assert(items, qt.HasLen, 4)
+	c.Assert(items[1].Type, qt.Equals, TypeLeadSummaryDivider)
+}