hugo

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

git clone git://git.shimmy1996.com/hugo.git
commit 579ff9b6524ed4e55c191ab94251f5a2fe315f68
parent 928a89696273b1a5defa0e85115c9bd0e167cbf0
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Sat, 26 Feb 2022 17:24:10 +0100

markup/goldmark: Improve attributes vs options

Fixes #9571

Diffstat:
Mhugolib/site.go | 4++++
Mmarkup/converter/hooks/hooks.go | 4++--
Mmarkup/goldmark/codeblocks/integration_test.go | 29+++++++++++++++++------------
Mmarkup/goldmark/codeblocks/render.go | 17++++++++++++-----
Mmarkup/highlight/highlight.go | 5+++++
Mmarkup/internal/attributes/attributes.go | 5+++--
6 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/hugolib/site.go b/hugolib/site.go
@@ -1798,6 +1798,10 @@ func (hr hookRendererTemplate) ResolvePosition(ctx interface{}) text.Position {
 	return hr.resolvePosition(ctx)
 }
 
+func (hr hookRendererTemplate) IsDefaultCodeBlockRenderer() bool {
+	return false
+}
+
 func (s *Site) renderForTemplate(name, outputFormat string, d interface{}, w io.Writer, templ tpl.Template) (err error) {
 	if templ == nil {
 		s.logMissingLayout(name, "", "", outputFormat)
diff --git a/markup/converter/hooks/hooks.go b/markup/converter/hooks/hooks.go
@@ -90,11 +90,11 @@ type HeadingRenderer interface {
 	identity.Provider
 }
 
-// ElementPositionRevolver provides a way to resolve the start Position
+// ElementPositionResolver provides a way to resolve the start Position
 // of a markdown element in the original source document.
 // This may be both slow and aproximate, so should only be
 // used for error logging.
-type ElementPositionRevolver interface {
+type ElementPositionResolver interface {
 	ResolvePosition(ctx interface{}) text.Position
 }
 
diff --git a/markup/goldmark/codeblocks/integration_test.go b/markup/goldmark/codeblocks/integration_test.go
@@ -14,6 +14,7 @@
 package codeblocks_test
 
 import (
+	"strings"
 	"testing"
 
 	"github.com/gohugoio/hugo/hugolib"
@@ -176,7 +177,7 @@ Position: {{ .Position | safeHTML }}
 }
 
 // Issue 9571
-func TestOptionsNonChroma(t *testing.T) {
+func TestAttributesChroma(t *testing.T) {
 	t.Parallel()
 
 	files := `
@@ -188,23 +189,27 @@ title: "p1"
 
 ##   Code
 
-§§§bash {style=monokai}
+§§§LANGUAGE {style=monokai}
 echo "p1";
 §§§
 -- layouts/_default/single.html --
 {{ .Content }}
 -- layouts/_default/_markup/render-codeblock.html --
-Style: {{ .Attributes }}|
+Attributes: {{ .Attributes }}|Options: {{ .Options }}|
 
 
 `
-
-	b := hugolib.NewIntegrationTestBuilder(
-		hugolib.IntegrationTestConfig{
-			T:           t,
-			TxtarString: files,
-		},
-	).Build()
-
-	b.AssertFileContent("public/p1/index.html", "asdfadf")
+	testLanguage := func(language, expect string) {
+		b := hugolib.NewIntegrationTestBuilder(
+			hugolib.IntegrationTestConfig{
+				T:           t,
+				TxtarString: strings.ReplaceAll(files, "LANGUAGE", language),
+			},
+		).Build()
+
+		b.AssertFileContent("public/p1/index.html", expect)
+	}
+
+	testLanguage("bash", "Attributes: map[]|Options: map[style:monokai]|")
+	testLanguage("hugo", "Attributes: map[style:monokai]|Options: map[]|")
 }
diff --git a/markup/goldmark/codeblocks/render.go b/markup/goldmark/codeblocks/render.go
@@ -18,7 +18,7 @@ import (
 	"fmt"
 	"sync"
 
-	"github.com/gohugoio/hugo/common/herrors"
+	"github.com/alecthomas/chroma/lexers"
 	htext "github.com/gohugoio/hugo/common/text"
 	"github.com/gohugoio/hugo/markup/converter/hooks"
 	"github.com/gohugoio/hugo/markup/goldmark/internal/render"
@@ -61,8 +61,6 @@ func (r *htmlRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
 }
 
 func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
-	defer herrors.Recover()
-
 	ctx := w.(*render.Context)
 
 	if entering {
@@ -92,17 +90,26 @@ func (r *htmlRenderer) renderCodeBlock(w util.BufWriter, src []byte, node ast.No
 	if n.b.Info != nil {
 		info = n.b.Info.Segment.Value(src)
 	}
+
+	attrtp := attributes.AttributesOwnerCodeBlockCustom
+	if isd, ok := renderer.(hooks.IsDefaultCodeBlockRendererProvider); (ok && isd.IsDefaultCodeBlockRenderer()) || lexers.Get(lang) != nil {
+		// We say that this is a Chroma code block if it's the default code block renderer
+		// or if the language is supported by Chroma.
+		attrtp = attributes.AttributesOwnerCodeBlockChroma
+	}
+
+	// IsDefaultCodeBlockRendererProvider
 	attrs := getAttributes(n.b, info)
 	cbctx := &codeBlockContext{
 		page:             ctx.DocumentContext().Document,
 		lang:             lang,
 		code:             s,
 		ordinal:          ordinal,
-		AttributesHolder: attributes.New(attrs, attributes.AttributesOwnerCodeBlock),
+		AttributesHolder: attributes.New(attrs, attrtp),
 	}
 
 	cbctx.createPos = func() htext.Position {
-		if resolver, ok := renderer.(hooks.ElementPositionRevolver); ok {
+		if resolver, ok := renderer.(hooks.ElementPositionResolver); ok {
 			return resolver.ResolvePosition(cbctx)
 		}
 		return htext.Position{
diff --git a/markup/highlight/highlight.go b/markup/highlight/highlight.go
@@ -61,6 +61,7 @@ type Highlighter interface {
 	Highlight(code, lang string, opts interface{}) (string, error)
 	HighlightCodeBlock(ctx hooks.CodeblockContext, opts interface{}) (HightlightResult, error)
 	hooks.CodeBlockRenderer
+	hooks.IsDefaultCodeBlockRendererProvider
 }
 
 type chromaHighlighter struct {
@@ -129,6 +130,10 @@ func (h chromaHighlighter) RenderCodeblock(w hugio.FlexiWriter, ctx hooks.Codebl
 	return highlight(w, code, ctx.Lang(), attributes, cfg)
 }
 
+func (h chromaHighlighter) IsDefaultCodeBlockRenderer() bool {
+	return true
+}
+
 var id = identity.NewPathIdentity("chroma", "highlight")
 
 func (h chromaHighlighter) GetIdentity() identity.Identity {
diff --git a/markup/internal/attributes/attributes.go b/markup/internal/attributes/attributes.go
@@ -50,7 +50,8 @@ type AttributesOwnerType int
 
 const (
 	AttributesOwnerGeneral AttributesOwnerType = iota
-	AttributesOwnerCodeBlock
+	AttributesOwnerCodeBlockChroma
+	AttributesOwnerCodeBlockCustom
 )
 
 func New(astAttributes []ast.Attribute, ownerType AttributesOwnerType) *AttributesHolder {
@@ -99,7 +100,7 @@ func New(astAttributes []ast.Attribute, ownerType AttributesOwnerType) *Attribut
 			panic(fmt.Sprintf("not implemented: %T", vvv))
 		}
 
-		if ownerType == AttributesOwnerCodeBlock && chromaHightlightProcessingAttributes[nameLower] {
+		if ownerType == AttributesOwnerCodeBlockChroma && chromaHightlightProcessingAttributes[nameLower] {
 			attr := Attribute{Name: string(v.Name), Value: vv}
 			opts = append(opts, attr)
 		} else {