Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/gohugoio/hugo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/markup
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2021-02-23 20:04:05 +0300
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2021-02-24 13:16:06 +0300
commitaed7df62a811b07b73ec5cbbf03e69e4bbf00919 (patch)
tree6099181308f9f6fe5126a3eac85a73ff601df52e /markup
parentcd0c5d7ef32cbd570af00c50ce760452381df64e (diff)
markup: Handle attribute lists in code fences
Fixes #8278
Diffstat (limited to 'markup')
-rw-r--r--markup/goldmark/convert.go24
-rw-r--r--markup/goldmark/convert_test.go19
-rw-r--r--markup/goldmark/render_hooks.go41
3 files changed, 78 insertions, 6 deletions
diff --git a/markup/goldmark/convert.go b/markup/goldmark/convert.go
index 629e2b15a..639fddace 100644
--- a/markup/goldmark/convert.go
+++ b/markup/goldmark/convert.go
@@ -22,6 +22,7 @@ import (
"runtime/debug"
"github.com/gohugoio/hugo/markup/goldmark/internal/extensions/attributes"
+ "github.com/yuin/goldmark/ast"
"github.com/gohugoio/hugo/identity"
@@ -321,7 +322,28 @@ func newHighlighting(cfg highlight.Config) goldmark.Extender {
highlight.WriteCodeTag(w, language)
return
}
- w.WriteString(`<div class="highlight">`)
+
+ w.WriteString(`<div class="highlight`)
+
+ var attributes []ast.Attribute
+ if ctx.Attributes() != nil {
+ attributes = ctx.Attributes().All()
+ }
+
+ if attributes != nil {
+ class, found := ctx.Attributes().GetString("class")
+ if found {
+ w.WriteString(" ")
+ w.Write(util.EscapeHTML(class.([]byte)))
+
+ }
+ _, _ = w.WriteString("\"")
+ renderAttributes(w, true, attributes...)
+ } else {
+ _, _ = w.WriteString("\"")
+ }
+
+ w.WriteString(">")
return
}
diff --git a/markup/goldmark/convert_test.go b/markup/goldmark/convert_test.go
index d35d4d1fd..c7367dd01 100644
--- a/markup/goldmark/convert_test.go
+++ b/markup/goldmark/convert_test.go
@@ -226,6 +226,25 @@ func TestConvertAttributes(t *testing.T) {
"> foo\n> bar\n{#id .className attrName=attrValue class=\"class1 class2\"}\n",
"<blockquote id=\"id\" class=\"className class1 class2\"><p>foo\nbar</p>\n</blockquote>\n",
},
+ /*{
+ // TODO(bep) this needs an upstream fix, see https://github.com/yuin/goldmark/issues/195
+ "Code block, CodeFences=false",
+ func(conf *markup_config.Config) {
+ withBlockAttributes(conf)
+ conf.Highlight.CodeFences = false
+ },
+ "```bash\necho 'foo';\n```\n{.myclass}",
+ "TODO",
+ },*/
+ {
+ "Code block, CodeFences=true",
+ func(conf *markup_config.Config) {
+ withBlockAttributes(conf)
+ conf.Highlight.CodeFences = true
+ },
+ "```bash\necho 'foo';\n````\n{.myclass id=\"myid\"}",
+ "<div class=\"highlight myclass\" id=\"myid\"><pre style",
+ },
{
"Paragraph",
withBlockAttributes,
diff --git a/markup/goldmark/render_hooks.go b/markup/goldmark/render_hooks.go
index 6bedc897e..41db4011b 100644
--- a/markup/goldmark/render_hooks.go
+++ b/markup/goldmark/render_hooks.go
@@ -14,8 +14,11 @@
package goldmark
import (
+ "bytes"
"sync"
+ "github.com/spf13/cast"
+
"github.com/gohugoio/hugo/markup/converter/hooks"
"github.com/yuin/goldmark"
@@ -135,13 +138,41 @@ func (r *hookedRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer)
reg.Register(ast.KindHeading, r.renderHeading)
}
-// https://github.com/yuin/goldmark/blob/b611cd333a492416b56aa8d94b04a67bf0096ab2/renderer/html/html.go#L404
-func (r *hookedRenderer) RenderAttributes(w util.BufWriter, node ast.Node) {
- for _, attr := range node.Attributes() {
+func (r *hookedRenderer) renderAttributesForNode(w util.BufWriter, node ast.Node) {
+ renderAttributes(w, false, node.Attributes()...)
+}
+
+var (
+
+ // Attributes with special meaning that does not make sense to render in HTML.
+ attributeExcludes = map[string]bool{
+ "linenos": true,
+ "hl_lines": true,
+ "linenostart": true,
+ }
+)
+
+func renderAttributes(w util.BufWriter, skipClass bool, attributes ...ast.Attribute) {
+ for _, attr := range attributes {
+ if skipClass && bytes.Equal(attr.Name, []byte("class")) {
+ continue
+ }
+
+ if attributeExcludes[string(attr.Name)] {
+ continue
+ }
+
_, _ = w.WriteString(" ")
_, _ = w.Write(attr.Name)
_, _ = w.WriteString(`="`)
- _, _ = w.Write(util.EscapeHTML(attr.Value.([]byte)))
+
+ switch v := attr.Value.(type) {
+ case []byte:
+ _, _ = w.Write(util.EscapeHTML(v))
+ default:
+ w.WriteString(cast.ToString(v))
+ }
+
_ = w.WriteByte('"')
}
}
@@ -282,7 +313,7 @@ func (r *hookedRenderer) renderDefaultHeading(w util.BufWriter, source []byte, n
_, _ = w.WriteString("<h")
_ = w.WriteByte("0123456"[n.Level])
if n.Attributes() != nil {
- r.RenderAttributes(w, node)
+ r.renderAttributesForNode(w, node)
}
_ = w.WriteByte('>')
} else {