mirror of
https://github.com/yuin/goldmark
synced 2025-03-04 23:04:52 +00:00
Use user input as part of footnote identifier
Named footnotes (`[^foo]` instead of `[^42]`) use the name in HTML node identifiers. This allows for stable references. Cool URLs don't change. Fixes #92
This commit is contained in:
parent
70ad9d5b30
commit
b72024d2b0
2 changed files with 46 additions and 8 deletions
|
|
@ -66,3 +66,21 @@ test![^1]
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
//= = = = = = = = = = = = = = = = = = = = = = = =//
|
//= = = = = = = = = = = = = = = = = = = = = = = =//
|
||||||
|
|
||||||
|
|
||||||
|
6
|
||||||
|
//- - - - - - - - -//
|
||||||
|
That's some text with a footnote.[^mynameisjeff]
|
||||||
|
|
||||||
|
[^mynameisjeff]: And that's the footnote.
|
||||||
|
//- - - - - - - - -//
|
||||||
|
<p>That's some text with a footnote.<sup id="fnref:mynameisjeff"><a href="#fn:mynameisjeff" class="footnote-ref" role="doc-noteref">1</a></sup></p>
|
||||||
|
<section class="footnotes" role="doc-endnotes">
|
||||||
|
<hr>
|
||||||
|
<ol>
|
||||||
|
<li id="fn:mynameisjeff" role="doc-endnote">
|
||||||
|
<p>And that's the footnote. <a href="#fnref:mynameisjeff" class="footnote-backref" role="doc-backlink">↩︎</a></p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
//= = = = = = = = = = = = = = = = = = = = = = = =//
|
||||||
|
|
|
||||||
|
|
@ -242,16 +242,36 @@ func (r *FootnoteHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegist
|
||||||
reg.Register(ast.KindFootnoteList, r.renderFootnoteList)
|
reg.Register(ast.KindFootnoteList, r.renderFootnoteList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isNumeric(b []byte) bool {
|
||||||
|
for _, c := range b {
|
||||||
|
if c < '0' || c > '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// footnoteRef decides what to use to refer to the footnote. The
|
||||||
|
// returned string is safe to use in HTML attributes.
|
||||||
|
func footnoteRef(index int, ref []byte) []byte {
|
||||||
|
if !isNumeric(ref) {
|
||||||
|
return util.EscapeHTML(ref)
|
||||||
|
}
|
||||||
|
return strconv.AppendInt(nil, int64(index), 10)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
||||||
if entering {
|
if entering {
|
||||||
n := node.(*ast.FootnoteLink)
|
n := node.(*ast.FootnoteLink)
|
||||||
is := strconv.Itoa(n.Index)
|
ref := footnoteRef(n.Index, n.Ref)
|
||||||
_, _ = w.WriteString(`<sup id="fnref:`)
|
_, _ = w.WriteString(`<sup id="fnref:`)
|
||||||
_, _ = w.WriteString(is)
|
_, _ = w.Write(ref)
|
||||||
_, _ = w.WriteString(`"><a href="#fn:`)
|
_, _ = w.WriteString(`"><a href="#fn:`)
|
||||||
_, _ = w.WriteString(is)
|
_, _ = w.Write(ref)
|
||||||
_, _ = w.WriteString(`" class="footnote-ref" role="doc-noteref">`)
|
_, _ = w.WriteString(`" class="footnote-ref" role="doc-noteref">`)
|
||||||
_, _ = w.WriteString(is)
|
// the content itself refers to footnotes by number, even when
|
||||||
|
// they are named
|
||||||
|
_, _ = w.WriteString(strconv.Itoa(n.Index))
|
||||||
_, _ = w.WriteString(`</a></sup>`)
|
_, _ = w.WriteString(`</a></sup>`)
|
||||||
}
|
}
|
||||||
return gast.WalkContinue, nil
|
return gast.WalkContinue, nil
|
||||||
|
|
@ -260,9 +280,9 @@ func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byt
|
||||||
func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
||||||
if entering {
|
if entering {
|
||||||
n := node.(*ast.FootnoteBackLink)
|
n := node.(*ast.FootnoteBackLink)
|
||||||
is := strconv.Itoa(n.Index)
|
ref := footnoteRef(n.Index, n.Ref)
|
||||||
_, _ = w.WriteString(` <a href="#fnref:`)
|
_, _ = w.WriteString(` <a href="#fnref:`)
|
||||||
_, _ = w.WriteString(is)
|
_, _ = w.Write(ref)
|
||||||
_, _ = w.WriteString(`" class="footnote-backref" role="doc-backlink">`)
|
_, _ = w.WriteString(`" class="footnote-backref" role="doc-backlink">`)
|
||||||
_, _ = w.WriteString("↩︎")
|
_, _ = w.WriteString("↩︎")
|
||||||
_, _ = w.WriteString(`</a>`)
|
_, _ = w.WriteString(`</a>`)
|
||||||
|
|
@ -272,10 +292,10 @@ func (r *FootnoteHTMLRenderer) renderFootnoteBackLink(w util.BufWriter, source [
|
||||||
|
|
||||||
func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
func (r *FootnoteHTMLRenderer) renderFootnote(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) {
|
||||||
n := node.(*ast.Footnote)
|
n := node.(*ast.Footnote)
|
||||||
is := strconv.Itoa(n.Index)
|
|
||||||
if entering {
|
if entering {
|
||||||
|
ref := footnoteRef(n.Index, n.Ref)
|
||||||
_, _ = w.WriteString(`<li id="fn:`)
|
_, _ = w.WriteString(`<li id="fn:`)
|
||||||
_, _ = w.WriteString(is)
|
_, _ = w.Write(ref)
|
||||||
_, _ = w.WriteString(`" role="doc-endnote"`)
|
_, _ = w.WriteString(`" role="doc-endnote"`)
|
||||||
if node.Attributes() != nil {
|
if node.Attributes() != nil {
|
||||||
html.RenderAttributes(w, node, html.ListItemAttributeFilter)
|
html.RenderAttributes(w, node, html.ListItemAttributeFilter)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue