Permalink
Browse files

Merge pull request #366 from choueric/master

fix duplicate and recursive footnotes. (#241)
  • Loading branch information...
2 parents 0ba0f2b + 5b2fb1b commit 067529f716f4c3f5e37c8c95ddd59df1007290ae @rtfb rtfb committed on GitHub Jun 10, 2017
Showing with 61 additions and 2 deletions.
  1. +3 −1 inline.go
  2. +50 −0 inline_test.go
  3. +8 −1 markdown.go
View
@@ -488,6 +488,7 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
}
p.notes = append(p.notes, ref)
+ p.notesRecord[string(ref.link)] = struct{}{}
link = ref.link
title = ref.title
@@ -498,9 +499,10 @@ func link(p *parser, out *bytes.Buffer, data []byte, offset int) int {
return 0
}
- if t == linkDeferredFootnote {
+ if t == linkDeferredFootnote && !p.isFootnote(lr) {
lr.noteId = len(p.notes) + 1
p.notes = append(p.notes, lr)
+ p.notesRecord[string(lr.link)] = struct{}{}
}
// keep link and title from reference
View
@@ -1024,6 +1024,28 @@ what happens here
</ol>
</div>
`,
+ `testing footnotes.[^a]
+
+test footnotes the second.[^b]
+
+[^a]: This is the first note[^a].
+[^b]: this is the second note.[^a]
+`,
+ `<p>testing footnotes.<sup class="footnote-ref" id="fnref:a"><a rel="footnote" href="#fn:a">1</a></sup></p>
+
+<p>test footnotes the second.<sup class="footnote-ref" id="fnref:b"><a rel="footnote" href="#fn:b">2</a></sup></p>
+<div class="footnotes">
+
+<hr />
+
+<ol>
+<li id="fn:a">This is the first note<sup class="footnote-ref" id="fnref:a"><a rel="footnote" href="#fn:a">1</a></sup>.
+</li>
+<li id="fn:b">this is the second note.<sup class="footnote-ref" id="fnref:a"><a rel="footnote" href="#fn:a">1</a></sup>
+</li>
+</ol>
+</div>
+`,
}
func TestFootnotes(t *testing.T) {
@@ -1077,6 +1099,34 @@ func TestNestedFootnotes(t *testing.T) {
</ol>
</div>
`,
+ `This uses footnote A.[^A]
+
+This uses footnote C.[^C]
+
+[^A]:
+ A note. use itself.[^A]
+[^B]:
+ B note, uses A to test duplicate.[^A]
+[^C]:
+ C note, uses B.[^B]
+`,
+ `<p>This uses footnote A.<sup class="footnote-ref" id="fnref:A"><a rel="footnote" href="#fn:A">1</a></sup></p>
+
+<p>This uses footnote C.<sup class="footnote-ref" id="fnref:C"><a rel="footnote" href="#fn:C">2</a></sup></p>
+<div class="footnotes">
+
+<hr />
+
+<ol>
+<li id="fn:A">A note. use itself.<sup class="footnote-ref" id="fnref:A"><a rel="footnote" href="#fn:A">1</a></sup>
+</li>
+<li id="fn:C">C note, uses B.<sup class="footnote-ref" id="fnref:B"><a rel="footnote" href="#fn:B">3</a></sup>
+</li>
+<li id="fn:B">B note, uses A to test duplicate.<sup class="footnote-ref" id="fnref:A"><a rel="footnote" href="#fn:A">1</a></sup>
+</li>
+</ol>
+</div>
+`,
}
doTestsInlineParam(t, tests, Options{Extensions: EXTENSION_FOOTNOTES}, 0,
HtmlRendererParameters{})
View
@@ -218,7 +218,8 @@ type parser struct {
// Footnotes need to be ordered as well as available to quickly check for
// presence. If a ref is also a footnote, it's stored both in refs and here
// in notes. Slice is nil if footnotes not enabled.
- notes []*reference
+ notes []*reference
+ notesRecord map[string]struct{}
}
func (p *parser) getRef(refid string) (ref *reference, found bool) {
@@ -241,6 +242,11 @@ func (p *parser) getRef(refid string) (ref *reference, found bool) {
return ref, found
}
+func (p *parser) isFootnote(ref *reference) bool {
+ _, ok := p.notesRecord[string(ref.link)]
+ return ok
+}
+
//
//
// Public interface
@@ -376,6 +382,7 @@ func MarkdownOptions(input []byte, renderer Renderer, opts Options) []byte {
if extensions&EXTENSION_FOOTNOTES != 0 {
p.notes = make([]*reference, 0)
+ p.notesRecord = make(map[string]struct{})
}
first := firstPass(p, input)

0 comments on commit 067529f

Please sign in to comment.