This makes the header ids match the newly added dt ids.
Also make sure newlines are preserved in hooks' `.PlainText`.
Fixes #13405
Fixes #13410
})
}
}
+
+// Issue 13410.
+func TestRenderHooksMultilineTitlePlainText(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+-- content/p1.md --
+---
+title: "p1"
+---
+
+First line.
+Second line.
+----------------
+-- layouts/_default/_markup/render-heading.html --
+Plain text: {{ .PlainText }}|Text: {{ .Text }}|
+-- layouts/_default/single.html --
+Content: {{ .Content}}|
+}
+`
+ b := Test(t, files)
+
+ b.AssertFileContent("public/p1/index.html",
+ "Content: Plain text: First line.\nSecond line.|",
+ "|Text: First line.\nSecond line.||\n",
+ )
+}
b := hugolib.Test(t, files)
b.AssertFileContent("public/p1/index.html",
- "<h2 id=\"hello-testhttpsexamplecom\">\n Hello <a href=\"https://example.com\">Test</a>\n\n <a class=\"anchor\" href=\"#hello-testhttpsexamplecom\">#</a>\n</h2>",
+ "<h2 id=\"hello-test\">\n Hello <a href=\"https://example.com\">Test</a>\n\n <a class=\"anchor\" href=\"#hello-test\">#</a>\n</h2>",
)
}
package attributes
import (
+ "strings"
+
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
"github.com/gohugoio/hugo/markup/goldmark/internal/render"
"github.com/yuin/goldmark"
}
// Markdown settext headers can have multiple lines, use the last line for the ID.
-func textHeadingID(node *ast.Heading, reader text.Reader) []byte {
- var line []byte
- lastIndex := node.Lines().Len() - 1
- if lastIndex > -1 {
- lastLine := node.Lines().At(lastIndex)
- line = lastLine.Value(reader.Source())
+func textHeadingID(n *ast.Heading, reader text.Reader) []byte {
+ text := render.TextPlain(n, reader.Source())
+ if n.Lines().Len() > 1 {
+
+ // For multiline headings, Goldmark's extension for headings returns the last line.
+ // We have a slightly different approach, but in most cases the end result should be the same.
+ // Instead of looking at the text segments in Lines (see #13405 for issues with that),
+ // we split the text above and use the last line.
+ parts := strings.Split(text, "\n")
+ text = parts[len(parts)-1]
}
- return line
+
+ return []byte(text)
}
Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď
: Testing accents.
-Mutiline set text header
+Multiline set text header
Second line
---------------
+## Example [hyperlink](https://example.com/) in a header
+
-- layouts/_default/single.html --
{{ .Content }}|Identifiers: {{ .Fragments.Identifiers }}|
`
`<dt id="my-title-1">My Title</dt>`,
`<dt id="term">良善天父</dt>`,
`<dt id="a-a-a-a-a-a-c-c-c-c-c-c-c-c-d">Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď</dt>`,
- `<h2 id="second-line">Mutiline set text header`,
- "|Identifiers: [a-a-a-a-a-a-c-c-c-c-c-c-c-c-d base-name base-name-1 foo-something-bar foobar my-title my-title-1 second-line term title-with-id title-with-id]|",
+ `<h2 id="second-line">`,
+ `<h2 id="example-hyperlink-in-a-header">`,
+ "|Identifiers: [a-a-a-a-a-a-c-c-c-c-c-c-c-c-d base-name base-name-1 example-hyperlink-in-a-header foo-something-bar foobar my-title my-title-1 second-line term title-with-id title-with-id]|",
)
}
-// Copyright 2024 The Hugo Authors. All rights reserved.
+// Copyright 2025 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
"sync"
bp "github.com/gohugoio/hugo/bufferpool"
+ east "github.com/yuin/goldmark-emoji/ast"
htext "github.com/gohugoio/hugo/common/text"
"github.com/gohugoio/hugo/tpl"
if c == nil {
return
}
+
switch c := c.(type) {
case *ast.RawHTML:
s := strings.TrimSpace(tpl.StripHTML(string(c.Segments.Value(source))))
buf.Write(c.Value)
case *ast.Text:
buf.Write(c.Segment.Value(source))
+ if c.HardLineBreak() || c.SoftLineBreak() {
+ buf.WriteByte('\n')
+ }
+ case *east.Emoji:
+ buf.WriteString(string(c.ShortName))
default:
textPlainTo(c.FirstChild(), source, buf)
}
// image
b.AssertFileContent("public/p3/index.html", `
-<li><a href="#an-image-kittenajpg">An image <img src="a.jpg" alt="kitten" /></a></li>
+<li><a href="#an-image-kitten">An image <img src="a.jpg" alt="kitten" /></a></li>
`)
// raw html
b.AssertFileContent("public/p4/index.html", `
-<li><a href="#some-spanrawspan-html">Some <span>raw</span> HTML</a></li>
+<li><a href="#some-raw-html">Some <span>raw</span> HTML</a></li>
`)
// typographer