markup/goldmark: Add attributes support for blocks (tables etc.)

E.g.:

```
> foo
> bar
{.myclass}
```

There are some current limitations: For tables you can currently only apply it to the full table, and for lists the ul/ol-nodes only, e.g.:

```
* Fruit
  * Apple
  * Orange
  * Banana
  {.fruits}
* Dairy
  * Milk
  * Cheese
  {.dairies}
{.list}
```

Fixes #7548
This commit is contained in:
Bjørn Erik Pedersen
2021-02-07 18:08:46 +01:00
parent 1b24728256
commit 2681633db8
8 changed files with 303 additions and 6 deletions

View File

@@ -17,6 +17,8 @@ import (
"strings"
"testing"
"github.com/spf13/cast"
"github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
"github.com/gohugoio/hugo/markup/highlight"
@@ -193,6 +195,103 @@ func TestConvertAutoIDBlackfriday(t *testing.T) {
c.Assert(got, qt.Contains, "<h2 id=\"let-s-try-this-shall-we\">")
}
func TestConvertAttributes(t *testing.T) {
c := qt.New(t)
withBlockAttributes := func(conf *markup_config.Config) {
conf.Goldmark.Parser.Attribute.Block = true
conf.Goldmark.Parser.Attribute.Title = false
}
withTitleAndBlockAttributes := func(conf *markup_config.Config) {
conf.Goldmark.Parser.Attribute.Block = true
conf.Goldmark.Parser.Attribute.Title = true
}
for _, test := range []struct {
name string
withConfig func(conf *markup_config.Config)
input string
expect interface{}
}{
{
"Title",
nil,
"## heading {#id .className attrName=attrValue class=\"class1 class2\"}",
"<h2 id=\"id\" class=\"className class1 class2\" attrName=\"attrValue\">heading</h2>\n",
},
{
"Blockquote",
withBlockAttributes,
"> 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",
},
{
"Paragraph",
withBlockAttributes,
"\nHi there.\n{.myclass }",
"<p class=\"myclass\">Hi there.</p>\n",
},
{
"Ordered list",
withBlockAttributes,
"\n1. First\n2. Second\n{.myclass }",
"<ol class=\"myclass\">\n<li>First</li>\n<li>Second</li>\n</ol>\n",
},
{
"Unordered list",
withBlockAttributes,
"\n* First\n* Second\n{.myclass }",
"<ul class=\"myclass\">\n<li>First</li>\n<li>Second</li>\n</ul>\n",
},
{
"Unordered list, indented",
withBlockAttributes,
`* Fruit
* Apple
* Orange
* Banana
{.fruits}
* Dairy
* Milk
* Cheese
{.dairies}
{.list}`,
[]string{"<ul class=\"list\">\n<li>Fruit\n<ul class=\"fruits\">", "<li>Dairy\n<ul class=\"dairies\">"},
},
{
"Table",
withBlockAttributes,
`| A | B |
| ------------- |:-------------:| -----:|
| AV | BV |
{.myclass }`,
"<table class=\"myclass\">\n<thead>",
},
{
"Title and Blockquote",
withTitleAndBlockAttributes,
"## heading {#id .className attrName=attrValue class=\"class1 class2\"}\n> foo\n> bar\n{.myclass}",
"<h2 id=\"id\" class=\"className class1 class2\" attrName=\"attrValue\">heading</h2>\n<blockquote class=\"myclass\"><p>foo\nbar</p>\n</blockquote>\n",
},
} {
c.Run(test.name, func(c *qt.C) {
mconf := markup_config.Default
if test.withConfig != nil {
test.withConfig(&mconf)
}
b := convert(c, mconf, test.input)
got := string(b.Bytes())
for _, s := range cast.ToStringSlice(test.expect) {
c.Assert(got, qt.Contains, s)
}
})
}
}
func TestConvertIssues(t *testing.T) {
c := qt.New(t)