]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
markup/goldmark: Fix blockquote render hook text parsing
authorJoe Mooring <joe.mooring@veriphor.com>
Mon, 9 Dec 2024 18:58:52 +0000 (10:58 -0800)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 10 Dec 2024 08:43:33 +0000 (09:43 +0100)
Fixes #12913
Fixes #13119

markup/goldmark/blockquotes/blockquotes.go
markup/goldmark/blockquotes/blockquotes_integration_test.go

index f9d518850afe1a86c3d41e3d8c8d2e989e0de8e9..064200d5e9f914892e9498ccc509a15eed9b2515 100644 (file)
@@ -74,7 +74,7 @@ func (r *htmlRenderer) renderBlockquote(w util.BufWriter, src []byte, node ast.N
        ordinal := ctx.GetAndIncrementOrdinal(ast.KindBlockquote)
 
        typ := typeRegular
-       alert := resolveBlockQuoteAlert(string(text))
+       alert := resolveBlockQuoteAlert(text)
        if alert.typ != "" {
                typ = typeAlert
        }
@@ -85,10 +85,21 @@ func (r *htmlRenderer) renderBlockquote(w util.BufWriter, src []byte, node ast.N
        }
 
        if typ == typeAlert {
-               // Trim preamble: <p>[!NOTE]<br>\n but preserve leading paragraph.
-               // We could possibly complicate this by moving this to the parser, but
-               // keep it simple for now.
-               text = "<p>" + text[strings.Index(text, "\n")+1:]
+               // Parse the blockquote content to determine the alert text. The alert
+               // text begins after the first newline, but we need to add an opening p
+               // tag if the first line of the blockquote content does not have a
+               // closing p tag. At some point we might want to move this to the
+               // parser.
+               before, after, found := strings.Cut(strings.TrimSpace(text), "\n")
+               if found {
+                       if strings.HasSuffix(before, "</p>") {
+                               text = after
+                       } else {
+                               text = "<p>" + after
+                       }
+               } else {
+                       text = ""
+               }
        }
 
        bqctx := &blockquoteContext{
@@ -165,7 +176,7 @@ func resolveBlockQuoteAlert(s string) blockQuoteAlert {
        m := blockQuoteAlertRe.FindStringSubmatch(s)
        if len(m) == 4 {
                title := strings.TrimSpace(m[3])
-               title = strings.TrimRight(title, "</p>")
+               title = strings.TrimSuffix(title, "</p>")
                return blockQuoteAlert{
                        typ:   strings.ToLower(m[1]),
                        sign:  m[2],
index 1f671df2b206654a192221bc2488029e749c6833..93fe5b27d17548bf418185cc42774db6ccfde8f1 100644 (file)
@@ -48,10 +48,9 @@ Content: {{ .Content }}
 title: "p1"
 ---
 
-> [!NOTE]  
+> [!NOTE]
 > This is a note with some whitespace after the alert type.
 
-
 > [!TIP]
 > This is a tip.
 
@@ -64,29 +63,26 @@ title: "p1"
 > This is a tip with attributes.
 {class="foo bar" id="baz"}
 
-> [!NOTE]  
+> [!NOTE]
 > Note triggering showing the position.
 {showpos="true"}
 
-
-> [!nOtE]  
+> [!nOtE]
 > Mixed case alert type.
-
-
 `
 
        b := hugolib.Test(t, files)
        b.AssertFileContentExact("public/p1/index.html",
-               "Blockquote Alert: |<p>This is a note with some whitespace after the alert type.</p>\n|alert|",
+               "Blockquote Alert: |<p>This is a note with some whitespace after the alert type.</p>|alert|",
                "Blockquote Alert: |<p>This is a tip.</p>",
-               "Blockquote Alert: |<p>This is a caution with some whitespace before the alert type.</p>\n|alert|",
+               "Blockquote Alert: |<p>This is a caution with some whitespace before the alert type.</p>|alert|",
                "Blockquote: |<p>A regular blockquote.</p>\n|regular|",
-               "Blockquote Alert Attributes: |<p>This is a tip with attributes.</p>\n|map[class:foo bar id:baz]|",
-               filepath.FromSlash("/content/p1.md:20:3"),
-               "Blockquote Alert Page: |<p>This is a tip with attributes.</p>\n|p1|p1|",
+               "Blockquote Alert Attributes: |<p>This is a tip with attributes.</p>|map[class:foo bar id:baz]|",
+               filepath.FromSlash("/content/p1.md:19:3"),
+               "Blockquote Alert Page: |<p>This is a tip with attributes.</p>|p1|p1|",
 
                // Issue 12767.
-               "Blockquote Alert: |<p>Mixed case alert type.</p>\n|alert",
+               "Blockquote Alert: |<p>Mixed case alert type.</p>|alert",
        )
 }
 
@@ -142,17 +138,113 @@ title: "Home"
 {{ .Content }}
 -- layouts/_default/_markup/render-blockquote.html --
 AlertType: {{ .AlertType }}|AlertTitle: {{ .AlertTitle }}|AlertSign: {{ .AlertSign | safeHTML }}|Text: {{ .Text }}|
-       
+
        `
 
        b := hugolib.Test(t, files)
        b.AssertFileContentExact("public/index.html",
                "AlertType: tip|AlertTitle: Callouts can have custom titles|AlertSign: |",
                "AlertType: tip|AlertTitle: Title-only callout|AlertSign: |",
-               "AlertType: faq|AlertTitle: Foldable negated callout|AlertSign: -|Text: <p>Yes! In a foldable callout, the contents are hidden when the callout is collapsed</p>\n|",
-               "AlertType: faq|AlertTitle: Foldable callout|AlertSign: +|Text: <p>Yes! In a foldable callout, the contents are hidden when the callout is collapsed</p>\n|",
-               "AlertType: danger|AlertTitle: |AlertSign: |Text: <p>Do not approach or handle without protective gear.</p>\n|",
+               "AlertType: faq|AlertTitle: Foldable negated callout|AlertSign: -|Text: <p>Yes! In a foldable callout, the contents are hidden when the callout is collapsed</p>|",
+               "AlertType: faq|AlertTitle: Foldable callout|AlertSign: +|Text: <p>Yes! In a foldable callout, the contents are hidden when the callout is collapsed</p>|",
+               "AlertType: danger|AlertTitle: |AlertSign: |Text: <p>Do not approach or handle without protective gear.</p>|",
                "AlertTitle: Can callouts be nested?|",
                "AlertTitle: You can even use multiple layers of nesting.|",
        )
 }
+
+// Issue 12913
+// Issue 13119
+func TestBlockquoteRenderHookTextParsing(t *testing.T) {
+       t.Parallel()
+
+       files := `
+-- hugo.toml --
+disableKinds = ['page','rss','section','sitemap','taxonomy','term']
+-- layouts/index.html --
+{{ .Content }}
+-- layouts/_default/_markup/render-blockquote.html --
+AlertType: {{ .AlertType }}|AlertTitle: {{ .AlertTitle }}|Text: {{ .Text }}|
+-- content/_index.md --
+---
+title: home
+---
+
+> [!one]
+
+> [!two] title
+
+> [!three]
+> line 1
+
+> [!four] title
+> line 1
+
+> [!five]
+> line 1
+> line 2
+
+> [!six] title
+> line 1
+> line 2
+
+> [!seven]
+> - list item
+
+> [!eight] title
+> - list item
+
+> [!nine]
+> line 1
+> - list item
+
+> [!ten] title
+> line 1
+> - list item
+
+> [!eleven]
+> line 1
+> - list item
+>
+> line 2
+
+> [!twelve] title
+> line 1
+> - list item
+>
+> line 2
+
+> [!thirteen]
+> ![alt](a.jpg)
+
+> [!fourteen] title
+> ![alt](a.jpg)
+
+> [!fifteen] _title_
+
+> [!sixteen] _title_
+> line one
+
+`
+
+       b := hugolib.Test(t, files)
+
+       b.AssertFileContent("public/index.html",
+               "AlertType: one|AlertTitle: |Text: |",
+               "AlertType: two|AlertTitle: title|Text: |",
+               "AlertType: three|AlertTitle: |Text: <p>line 1</p>|",
+               "AlertType: four|AlertTitle: title|Text: <p>line 1</p>|",
+               "AlertType: five|AlertTitle: |Text: <p>line 1\nline 2</p>|",
+               "AlertType: six|AlertTitle: title|Text: <p>line 1\nline 2</p>|",
+               "AlertType: seven|AlertTitle: |Text: <ul>\n<li>list item</li>\n</ul>|",
+               "AlertType: eight|AlertTitle: title|Text: <ul>\n<li>list item</li>\n</ul>|",
+               "AlertType: nine|AlertTitle: |Text: <p>line 1</p>\n<ul>\n<li>list item</li>\n</ul>|",
+               "AlertType: ten|AlertTitle: title|Text: <p>line 1</p>\n<ul>\n<li>list item</li>\n</ul>|",
+               "AlertType: eleven|AlertTitle: |Text: <p>line 1</p>\n<ul>\n<li>list item</li>\n</ul>\n<p>line 2</p>|",
+               "AlertType: twelve|AlertTitle: title|Text: <p>line 1</p>\n<ul>\n<li>list item</li>\n</ul>\n<p>line 2</p>|",
+               "AlertType: thirteen|AlertTitle: |Text: <p><img src=\"a.jpg\" alt=\"alt\"></p>|",
+               "AlertType: fourteen|AlertTitle: title|Text: <p><img src=\"a.jpg\" alt=\"alt\"></p>|",
+               "AlertType: fifteen|AlertTitle: <em>title</em>|Text: |",
+               "AlertType: sixteen|AlertTitle: <em>title</em>|Text: <p>line one</p>|",
+       )
+}