Repository: gohugoio/hugo (language: go)

Issue:
Footnotes: Multiple references to the same footnotes cause duplicate "id"s in HTML [goldmark]
<!-- Please answer these questions before submitting your issue. Thanks! -->

### What version of Hugo are you using (`hugo version`)?

<pre>
$ hugo version
hugo v0.97.0-DEV-9e360d3844f5077c65649e4c9c98f5cbd1c3efc0
</pre>

### Does this issue reproduce with the latest release?

Yes

---

_This issue probably stems from Goldmark's Footnote extension. But I am opening the issue here first as it was found through Hugo._

## Issue

When there are multiple references to the same footnote, the generated `<sup>` elements for backreferences from the footnote are generated with the same `id`. This prevents a user to jump back to each of those references separately from the footnote.

The generated HTML page also shows "Duplicate ID" errors on the [HTML Validator](https://html5.validator.nu/?doc=https%3A%2F%2Fmultiple-refs-same-footnote--hugo-mwe.netlify.app%2Fposts%2Fmultiple-refs-same-footnote&showsource=yes) site.

## Recipe to reproduce the issue

```md
something[^fn:1]

something[^fn:1]

something[^fn:1]

[^fn:1]: footnote text
```

- [Markdown source][1]
- [Hugo generated HTML page][2]

## More Info

The Goldmark Footnote extension is inspired from the _PHP Markdown Extra - Footnotes_ extension.

When the above snippet is pasted in the [PHP Markdown dingus](https://michelf.ca/projects/php-markdown/dingus/), we not see this issue of Duplicate IDs:

```html
<p>something<sup id="fnref:fn:1"><a href="#fn:fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>

<p>something<sup id="fnref2:fn:1"><a href="#fn:fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>

<p>something<sup id="fnref3:fn:1"><a href="#fn:fn:1" class="footnote-ref" role="doc-noteref">1</a></sup></p>

<div class="footnotes" role="doc-endnotes">
<hr />
<ol>

<li id="fn:fn:1" role="doc-endnote">
<p>footnote text&#160;<a href="#fnref:fn:1" class="footnote-backref" role="doc-backlink">&#8617;&#xFE0E;</a> <a href="#fnref2:fn:1" class="footnote-backref" role="doc-backlink">&#8617;&#xFE0E;</a> <a href="#fnref3:fn:1" class="footnote-backref" role="doc-backlink">&#8617;&#xFE0E;</a></p>
</li>

</ol>
</div>
```

Note that the points from where the same footnote is referenced shows unique IDs: `fnref:fn:1`, `fnref2:fn:1`, `fnref3:fn:1`




## References

-   [Hugo Discourse thread](https://discourse.gohugo.io/t/multiple-references-to-footnotes/38068)


[1]: https://gitlab.com/hugo-mwe/hugo-mwe/-/raw/multiple-refs-same-footnote/content/posts/multiple-refs-same-footnote.md
[2]: https://multiple-refs-same-footnote--hugo-mwe.netlify.app/posts/multiple-refs-same-footnote/



Discussion / hints:

Fix patch:
diff --git a/go.mod b/go.mod
index 8094916fb77..dac1c8e1cc9 100644
--- a/go.mod
+++ b/go.mod
@@ -56,7 +56,7 @@ require (
 	github.com/spf13/jwalterweatherman v1.1.0
 	github.com/spf13/pflag v1.0.5
 	github.com/tdewolff/minify/v2 v2.11.2
-	github.com/yuin/goldmark v1.4.11
+	github.com/yuin/goldmark v1.4.12
 	go.uber.org/atomic v1.9.0
 	gocloud.dev v0.20.0
 	golang.org/x/image v0.0.0-20211028202545-6944b10bf410
diff --git a/go.sum b/go.sum
index a70ba43146a..d2846fa1292 100644
--- a/go.sum
+++ b/go.sum
@@ -448,8 +448,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.11 h1:i45YIzqLnUc2tGaTlJCyUxSG8TvgyGqhqOZOUKIjJ6w=
-github.com/yuin/goldmark v1.4.11/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
+github.com/yuin/goldmark v1.4.12 h1:6hffw6vALvEDqJ19dOJvJKOoAOKe4NDaTqvd2sktGN0=
+github.com/yuin/goldmark v1.4.12/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=


Test patch:
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index c16754cd9d2..84e54306a2c 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -456,7 +456,7 @@ func TestPageWithDelimiterForMarkdownThatCrossesBorder(t *testing.T) {
 	}
 
 	cnt := content(p)
-	if cnt != "<p>The <a href=\"http://gohugo.io/\">best static site generator</a>.<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup></p>\n<section class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"fn:1\" role=\"doc-endnote\">\n<p>Many people say so.&#160;<a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">&#x21a9;&#xfe0e;</a></p>\n</li>\n</ol>\n</section>" {
+	if cnt != "<p>The <a href=\"http://gohugo.io/\">best static site generator</a>.<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"fn:1\">\n<p>Many people say so.&#160;<a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">&#x21a9;&#xfe0e;</a></p>\n</li>\n</ol>\n</div>" {
 		t.Fatalf("Got content:\n%q", cnt)
 	}
 }
diff --git a/markup/goldmark/convert_test.go b/markup/goldmark/convert_test.go
index e37e81c97ad..ab96b8c85d2 100644
--- a/markup/goldmark/convert_test.go
+++ b/markup/goldmark/convert_test.go
@@ -177,8 +177,8 @@ description
 	c.Assert(got, qt.Contains, `Dashes (“&ndash;” and “&mdash;”) `)
 	c.Assert(got, qt.Contains, `Three consecutive dots (“&hellip;”)`)
 	c.Assert(got, qt.Contains, `&ldquo;That was back in the &rsquo;90s, that&rsquo;s a long time ago&rdquo;`)
-	c.Assert(got, qt.Contains, `footnote.<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>`)
-	c.Assert(got, qt.Contains, `<section class="footnotes" role="doc-endnotes">`)
+	c.Assert(got, qt.Contains, `footnote.<sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>`)
+	c.Assert(got, qt.Contains, `<div class="footnotes" role="doc-endnotes">`)
 	c.Assert(got, qt.Contains, `<dt>date</dt>`)
 
 	toc, ok := b.(converter.TableOfContentsProvider)