From 743f08bde8500a59a8f638eb80a372461bc2f6c0 Mon Sep 17 00:00:00 2001 From: Brad Erickson Date: Thu, 24 Dec 2020 09:27:54 -0800 Subject: [PATCH] feat: Support named footnote reference links Uses the provided name for a PHP Markdown Extra Footnote reference when it is not an incorrectly ordered number value, such as: [^named]. The reference names were previously ignored and replaced with ordered index integers. According to: https://michelf.ca/projects/php-markdown/extra/#footnotes > Names can contain any character valid within an id attribute in HTML. --- extension/_test/footnote.txt | 23 ++++++++++++++ extension/ast/footnote.go | 8 +++-- extension/footnote.go | 59 +++++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/extension/_test/footnote.txt b/extension/_test/footnote.txt index 0270c62..0546ae5 100644 --- a/extension/_test/footnote.txt +++ b/extension/_test/footnote.txt @@ -66,3 +66,26 @@ test![^1] //= = = = = = = = = = = = = = = = = = = = = = = =// +6 +//- - - - - - - - -// +test named[^named]. + +test incorrect index number[^42] + +[^named]: footnote +[^42]: footnote +//- - - - - - - - -// +

test namednamed.

+

test incorrect index number2

+
+
+
    +
  1. +

    footnote ↩︎

    +
  2. +
  3. +

    footnote ↩︎

    +
  4. +
+
+//= = = = = = = = = = = = = = = = = = = = = = = =// diff --git a/extension/ast/footnote.go b/extension/ast/footnote.go index dedbab4..caa08e5 100644 --- a/extension/ast/footnote.go +++ b/extension/ast/footnote.go @@ -12,6 +12,7 @@ type FootnoteLink struct { gast.BaseInline Index int RefCount int + Ref []byte } // Dump implements Node.Dump. @@ -31,10 +32,11 @@ func (n *FootnoteLink) Kind() gast.NodeKind { } // NewFootnoteLink returns a new FootnoteLink node. -func NewFootnoteLink(index int) *FootnoteLink { +func NewFootnoteLink(index int, ref []byte) *FootnoteLink { return &FootnoteLink{ Index: index, RefCount: 0, + Ref: ref, } } @@ -44,6 +46,7 @@ type FootnoteBacklink struct { gast.BaseInline Index int RefCount int + Ref []byte } // Dump implements Node.Dump. @@ -63,10 +66,11 @@ func (n *FootnoteBacklink) Kind() gast.NodeKind { } // NewFootnoteBacklink returns a new FootnoteBacklink node. -func NewFootnoteBacklink(index int) *FootnoteBacklink { +func NewFootnoteBacklink(index int, ref []byte) *FootnoteBacklink { return &FootnoteBacklink{ Index: index, RefCount: 0, + Ref: ref, } } diff --git a/extension/footnote.go b/extension/footnote.go index 62f5ee6..9133d41 100644 --- a/extension/footnote.go +++ b/extension/footnote.go @@ -140,7 +140,7 @@ func (s *footnoteParser) Parse(parent gast.Node, block text.Reader, pc parser.Co return nil } closes := pos + closure - value := block.Value(text.NewSegment(segment.Start+open, segment.Start+closes)) + ref := block.Value(text.NewSegment(segment.Start+open, segment.Start+closes)) block.Advance(closes + 1) var list *ast.FootnoteList @@ -153,9 +153,9 @@ func (s *footnoteParser) Parse(parent gast.Node, block text.Reader, pc parser.Co index := 0 for def := list.FirstChild(); def != nil; def = def.NextSibling() { d := def.(*ast.Footnote) - if bytes.Equal(d.Ref, value) { + if bytes.Equal(d.Ref, ref) { if d.Index < 0 { - list.Count += 1 + list.Count++ d.Index = list.Count } index = d.Index @@ -166,7 +166,7 @@ func (s *footnoteParser) Parse(parent gast.Node, block text.Reader, pc parser.Co return nil } - fnlink := ast.NewFootnoteLink(index) + fnlink := ast.NewFootnoteLink(index, ref) var fnlist []*ast.FootnoteLink if tmp := pc.Get(footnoteLinkListKey); tmp != nil { fnlist = tmp.([]*ast.FootnoteLink) @@ -232,7 +232,7 @@ func (a *footnoteASTTransformer) Transform(node *gast.Document, reader text.Read if index < 0 { list.RemoveChild(list, footnote) } else { - backLink := ast.NewFootnoteBacklink(index) + backLink := ast.NewFootnoteBacklink(index, fn.Ref) backLink.RefCount = counter[index] container.AppendChild(container, backLink) } @@ -511,25 +511,26 @@ func (r *FootnoteHTMLRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegist func (r *FootnoteHTMLRenderer) renderFootnoteLink(w util.BufWriter, source []byte, node gast.Node, entering bool) (gast.WalkStatus, error) { if entering { n := node.(*ast.FootnoteLink) - is := strconv.Itoa(n.Index) + + reference := r.getReference(n.Index, n.Ref) _, _ = w.WriteString(``) - _, _ = w.WriteString(is) + _, _ = w.Write(reference) _, _ = w.WriteString(``) } return gast.WalkContinue, nil @@ -538,19 +539,20 @@ 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) { if entering { n := node.(*ast.FootnoteBacklink) - is := strconv.Itoa(n.Index) + + reference := r.getReference(n.Index, n.Ref) _, _ = w.WriteString(` `) - _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkHTML, n.Index, n.RefCount)) + _, _ = w.Write(applyFootnoteTemplate(r.FootnoteConfig.BacklinkHTML, reference, n.RefCount)) _, _ = w.WriteString(``) } return gast.WalkContinue, nil @@ -558,12 +560,13 @@ 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) { n := node.(*ast.Footnote) - is := strconv.Itoa(n.Index) + + reference := r.getReference(n.Index, n.Ref) if entering { _, _ = w.WriteString(`