hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 10928a4f781c2faf704825ef95234125812ad860
parent afd63bf7d56194a6aa5d32483151d71fa0b84f3a
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Sat, 26 Feb 2022 10:42:21 +0100

Remove the trailing new line in .Code

Fixes #9572

Diffstat:
Mcommon/text/transform.go | 16++++++++++++++++
Mcommon/text/transform_test.go | 15+++++++++++++++
Mhugolib/integrationtest_builder.go | 3+++
Mmarkup/goldmark/codeblocks/integration_test.go | 31+++++++++++++++++++++++++++++++
Mmarkup/goldmark/codeblocks/render.go | 4+++-
Mmarkup/highlight/highlight.go | 5++++-
Mtpl/strings/strings.go | 3++-
7 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/common/text/transform.go b/common/text/transform.go
@@ -14,6 +14,7 @@
 package text
 
 import (
+	"strings"
 	"sync"
 	"unicode"
 
@@ -45,3 +46,18 @@ func RemoveAccentsString(s string) string {
 	accentTransformerPool.Put(t)
 	return s
 }
+
+// Chomp removes trailing newline characters from s.
+func Chomp(s string) string {
+	return strings.TrimRightFunc(s, func(r rune) bool {
+		return r == '\n' || r == '\r'
+	})
+}
+
+// Puts adds a trailing \n none found.
+func Puts(s string) string {
+	if s == "" || s[len(s)-1] == '\n' {
+		return s
+	}
+	return s + "\n"
+}
diff --git a/common/text/transform_test.go b/common/text/transform_test.go
@@ -26,3 +26,18 @@ func TestRemoveAccents(t *testing.T) {
 	c.Assert(string(RemoveAccents([]byte("Hugo Rocks!"))), qt.Equals, "Hugo Rocks!")
 	c.Assert(string(RemoveAccentsString("Resumé")), qt.Equals, "Resume")
 }
+
+func TestChomp(t *testing.T) {
+	c := qt.New(t)
+
+	c.Assert(Chomp("\nA\n"), qt.Equals, "\nA")
+	c.Assert(Chomp("A\r\n"), qt.Equals, "A")
+}
+
+func TestPuts(t *testing.T) {
+	c := qt.New(t)
+
+	c.Assert(Puts("A"), qt.Equals, "A\n")
+	c.Assert(Puts("\nA\n"), qt.Equals, "\nA\n")
+	c.Assert(Puts(""), qt.Equals, "")
+}
diff --git a/hugolib/integrationtest_builder.go b/hugolib/integrationtest_builder.go
@@ -28,6 +28,9 @@ import (
 )
 
 func NewIntegrationTestBuilder(conf IntegrationTestConfig) *IntegrationTestBuilder {
+	// Code fences.
+	conf.TxtarString = strings.ReplaceAll(conf.TxtarString, "§§§", "```")
+
 	data := txtar.Parse([]byte(conf.TxtarString))
 
 	c, ok := conf.T.(*qt.C)
diff --git a/markup/goldmark/codeblocks/integration_test.go b/markup/goldmark/codeblocks/integration_test.go
@@ -113,3 +113,34 @@ Go Language: golang|
 		"<h2 id=\"bash-code\">Bash Code</h2>\n<div class=\"highlight blue\"><pre tabindex=\"0\" class=\"chroma\"><code class=\"language-bash\" data-lang=\"bash\"><span class=\"line\"><span class=\"ln\">32</span><span class=\"cl\"><span class=\"nb\">echo</span> <span class=\"s2\">&#34;l1&#34;</span><span class=\"p\">;</span>\n</span></span><span class=\"line hl\"><span class=\"ln\">33</span>",
 	)
 }
+
+func TestCodeChomp(t *testing.T) {
+	t.Parallel()
+
+	files := `
+-- config.toml --
+-- content/p1.md --
+---
+title: "p1"
+---
+
+§§§bash
+echo "p1";
+§§§
+-- layouts/_default/single.html --
+{{ .Content }}
+-- layouts/_default/_markup/render-codeblock.html --
+|{{ .Code | safeHTML }}|
+
+`
+
+	b := hugolib.NewIntegrationTestBuilder(
+		hugolib.IntegrationTestConfig{
+			T:           t,
+			TxtarString: files,
+			NeedsOsFS:   false,
+		},
+	).Build()
+
+	b.AssertFileContent("public/p1/index.html", "|echo \"p1\";|")
+}
diff --git a/markup/goldmark/codeblocks/render.go b/markup/goldmark/codeblocks/render.go
@@ -17,6 +17,7 @@ import (
 	"bytes"
 	"fmt"
 
+	htext "github.com/gohugoio/hugo/common/text"
 	"github.com/gohugoio/hugo/markup/converter/hooks"
 	"github.com/gohugoio/hugo/markup/goldmark/internal/render"
 	"github.com/gohugoio/hugo/markup/internal/attributes"
@@ -75,7 +76,8 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
 		line := n.b.Lines().At(i)
 		buff.Write(line.Value(src))
 	}
-	text := buff.String()
+
+	text := htext.Chomp(buff.String())
 
 	var info []byte
 	if n.b.Info != nil {
diff --git a/markup/highlight/highlight.go b/markup/highlight/highlight.go
@@ -25,6 +25,7 @@ import (
 	"github.com/alecthomas/chroma/lexers"
 	"github.com/alecthomas/chroma/styles"
 	"github.com/gohugoio/hugo/common/hugio"
+	"github.com/gohugoio/hugo/common/text"
 	"github.com/gohugoio/hugo/identity"
 	"github.com/gohugoio/hugo/markup/converter/hooks"
 	"github.com/gohugoio/hugo/markup/internal/attributes"
@@ -123,7 +124,9 @@ func (h chromaHighlighter) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.Codebl
 		return err
 	}
 
-	return highlight(w, ctx.Code(), ctx.Lang(), attributes, cfg)
+	code := text.Puts(ctx.Code())
+
+	return highlight(w, code, ctx.Lang(), attributes, cfg)
 }
 
 var id = identity.NewPathIdentity("chroma", "highlight")
diff --git a/tpl/strings/strings.go b/tpl/strings/strings.go
@@ -21,6 +21,7 @@ import (
 	"strings"
 	"unicode/utf8"
 
+	"github.com/gohugoio/hugo/common/text"
 	"github.com/gohugoio/hugo/deps"
 	"github.com/gohugoio/hugo/helpers"
 
@@ -119,7 +120,7 @@ func (ns *Namespace) Chomp(s interface{}) (interface{}, error) {
 		return "", err
 	}
 
-	res := strings.TrimRight(ss, "\r\n")
+	res := text.Chomp(ss)
 	switch s.(type) {
 	case template.HTML:
 		return template.HTML(res), nil