config := `
 baseURL="https://example.org"
 workingDir="/mywork"
+
+[markup]
+[markup.goldmark]
+[markup.goldmark.parser]
+autoHeadingID = true
+autoHeadingIDType = "github"
+[markup.goldmark.parser.attribute]
+block = true
+title = true
+
 `
        b := newTestSitesBuilder(t).WithWorkingDir("/mywork").WithConfigFile("toml", config).Running()
        b.WithTemplatesAdded("_default/single.html", `{{ .Content }}`)
        b.WithTemplatesAdded("_default/_markup/render-link.html", `{{ with .Page }}{{ .Title }}{{ end }}|{{ .Destination | safeURL }}|Title: {{ .Title | safeHTML }}|Text: {{ .Text | safeHTML }}|END`)
        b.WithTemplatesAdded("docs/_markup/render-link.html", `Link docs section: {{ .Text | safeHTML }}|END`)
        b.WithTemplatesAdded("_default/_markup/render-image.html", `IMAGE: {{ .Page.Title }}||{{ .Destination | safeURL }}|Title: {{ .Title | safeHTML }}|Text: {{ .Text | safeHTML }}|END`)
-       b.WithTemplatesAdded("_default/_markup/render-heading.html", `HEADING: {{ .Page.Title }}||Level: {{ .Level }}|Anchor: {{ .Anchor | safeURL }}|Text: {{ .Text | safeHTML }}|END`)
+       b.WithTemplatesAdded("_default/_markup/render-heading.html", `HEADING: {{ .Page.Title }}||Level: {{ .Level }}|Anchor: {{ .Anchor | safeURL }}|Text: {{ .Text | safeHTML }}|Attributes: {{ .Attributes }}|END`)
        b.WithTemplatesAdded("docs/_markup/render-heading.html", `Docs Level: {{ .Level }}|END`)
 
        b.WithContent("customview/p1.md", `---
 
 
 
+Attributes:
+
+## Some Heading {.text-serif #a-heading title="Hovered"} 
+
 
 `, "blog/p2.md", `---
 title: Cool Page2
        // We may add type template support later, keep this for then. b.AssertFileContent("public/docs/docs1/index.html", `DOCS EDITED: https://www.google.com|</p>`)
        b.AssertFileContent("public/blog/p4/index.html", `IMAGE EDITED: /images/Dragster.jpg|`)
        b.AssertFileContent("public/blog/p6/index.html", "<p>Inner Link: EDITED: https://www.gohugo.io|</p>")
-       b.AssertFileContent("public/blog/p7/index.html", "HEADING: With Headings||Level: 1|Anchor: heading-level-1|Text: Heading Level 1|END<p>some text</p>\nHEADING: With Headings||Level: 2|Anchor: heading-level-2|Text: Heading Level 2|ENDHEADING: With Headings||Level: 3|Anchor: heading-level-3|Text: Heading Level 3|END")
+       b.AssertFileContent("public/blog/p7/index.html", "HEADING: With Headings||Level: 1|Anchor: heading-level-1|Text: Heading Level 1|Attributes: map[id:heading-level-1]|END<p>some text</p>\nHEADING: With Headings||Level: 2|Anchor: heading-level-2|Text: Heading Level 2|Attributes: map[id:heading-level-2]|ENDHEADING: With Headings||Level: 3|Anchor: heading-level-3|Text: Heading Level 3|Attributes: map[id:heading-level-3]|END")
 
        // https://github.com/gohugoio/hugo/issues/7349
        b.AssertFileContent("public/docs/p8/index.html", "Docs Level: 1")
 
        "github.com/gohugoio/hugo/identity"
 )
 
+type AttributesProvider interface {
+       Attributes() map[string]string
+}
+
 type LinkContext interface {
        Page() interface{}
        Destination() string
        Text() string
        // PlainText is the unrendered version of Text.
        PlainText() string
+
+       // Attributes (e.g. CSS classes)
+       AttributesProvider
 }
 
 // HeadingRenderer describes a uniquely identifiable rendering hook.
 
 package goldmark
 
 import (
+       "sync"
+
        "github.com/gohugoio/hugo/markup/converter/hooks"
 
        "github.com/yuin/goldmark"
        return &links{}
 }
 
+type attributesHolder struct {
+       // What we get from Goldmark.
+       astAttributes []ast.Attribute
+
+       // What we send to the the render hooks.
+       attributesInit sync.Once
+       attributes     map[string]string
+}
+
+func (a *attributesHolder) Attributes() map[string]string {
+       a.attributesInit.Do(func() {
+               a.attributes = make(map[string]string)
+               for _, attr := range a.astAttributes {
+                       a.attributes[string(attr.Name)] = string(util.EscapeHTML(attr.Value.([]byte)))
+               }
+       })
+       return a.attributes
+}
+
 type linkContext struct {
        page        interface{}
        destination string
        anchor    string
        text      string
        plainText string
+       *attributesHolder
 }
 
 func (ctx headingContext) Page() interface{} {
        err := h.HeadingRenderer.RenderHeading(
                w,
                headingContext{
-                       page:      ctx.DocumentContext().Document,
-                       level:     n.Level,
-                       anchor:    string(anchor),
-                       text:      string(text),
-                       plainText: string(n.Text(source)),
+                       page:             ctx.DocumentContext().Document,
+                       level:            n.Level,
+                       anchor:           string(anchor),
+                       text:             string(text),
+                       plainText:        string(n.Text(source)),
+                       attributesHolder: &attributesHolder{astAttributes: n.Attributes()},
                },
        )