From 6947216efb48973a448b15f18c97acab6e151004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vytautas=20=C5=A0altenis?= Date: Sat, 3 Sep 2016 12:39:16 +0300 Subject: [PATCH] Move footnote rendering to the renderer Clean up footnotes part of an AST: don't force HTML-specific pieces there, just keep a clean list of footnotes. Since some renderers might want to process footnotes differently, let them know about footnotes by having a flag on that list. --- html.go | 12 ++++++++---- inline_test.go | 6 ++++++ markdown.go | 4 +--- node.go | 19 ++++++++++--------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/html.go b/html.go index 3f3cf32..54f2bea 100644 --- a/html.go +++ b/html.go @@ -589,10 +589,11 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt tagName = "dl" } if entering { - // var start = node.listStart; - // if (start !== null && start !== 1) { - // attrs.push(['start', start.toString()]); - // } + if node.IsFootnotesList { + r.out(w, []byte("\n
\n\n")) + r.out(w, tag("hr", attrs, r.Flags&UseXHTML != 0)) + r.cr(w) + } r.cr(w) if node.Parent.Type == Item && node.Parent.Parent.Tight { r.cr(w) @@ -611,6 +612,9 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt if node.Parent.Type == Document || node.Parent.Type == BlockQuote { r.cr(w) } + if node.IsFootnotesList { + r.out(w, []byte("\n
\n")) + } } case Item: tagName := "li" diff --git a/inline_test.go b/inline_test.go index 4be754c..598e5e6 100644 --- a/inline_test.go +++ b/inline_test.go @@ -922,6 +922,12 @@ what happens here `, + + `This text does not reference a footnote. + +[^footnote]: But it has a footnote! And it gets omitted. +`, + "

This text does not reference a footnote.

\n", } func TestFootnotes(t *testing.T) { diff --git a/markdown.go b/markdown.go index 13a18d3..f377a48 100644 --- a/markdown.go +++ b/markdown.go @@ -416,9 +416,8 @@ func (p *parser) parseRefsToAST() { return } p.tip = p.doc - finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte(`
`))) - p.addBlock(HorizontalRule, nil) block := p.addBlock(List, nil) + block.IsFootnotesList = true block.ListFlags = ListTypeOrdered flags := ListItemBeginningOfList // Note: this loop is intentionally explicit, not range-form. This is @@ -441,7 +440,6 @@ func (p *parser) parseRefsToAST() { above := block.Parent finalizeList(block) p.tip = above - finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte("
"))) block.Walk(func(node *Node, entering bool) WalkStatus { if node.Type == Paragraph || node.Type == Header { p.inline(node, node.content) diff --git a/node.go b/node.go index 3cebd11..983ec10 100644 --- a/node.go +++ b/node.go @@ -69,20 +69,21 @@ func (t NodeType) String() string { return nodeTypeNames[t] } -// ListData contains fields relevant to a List node type. +// ListData contains fields relevant to a List and Item node type. type ListData struct { - ListFlags ListType - Tight bool // Skip

s around list item data if true - BulletChar byte // '*', '+' or '-' in bullet lists - Delimiter byte // '.' or ')' after the number in ordered lists - RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering + ListFlags ListType + Tight bool // Skip

s around list item data if true + BulletChar byte // '*', '+' or '-' in bullet lists + Delimiter byte // '.' or ')' after the number in ordered lists + RefLink []byte // If not nil, turns this list item into a footnote item and triggers different rendering + IsFootnotesList bool // This is a list of footnotes } // LinkData contains fields relevant to a Link node type. type LinkData struct { - Destination []byte - Title []byte - NoteID int + Destination []byte // Destination is what goes into a href + Title []byte // Title is the tooltip thing that goes in a title attribute + NoteID int // NoteID contains a serial number of a footnote, zero if it's not a footnote } // CodeBlockData contains fields relevant to a CodeBlock node type.