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.
This commit is contained in:
parent
ea8dfc4880
commit
6947216efb
12
html.go
12
html.go
|
@ -589,10 +589,11 @@ func (r *HTMLRenderer) RenderNode(w io.Writer, node *Node, entering bool) WalkSt
|
||||||
tagName = "dl"
|
tagName = "dl"
|
||||||
}
|
}
|
||||||
if entering {
|
if entering {
|
||||||
// var start = node.listStart;
|
if node.IsFootnotesList {
|
||||||
// if (start !== null && start !== 1) {
|
r.out(w, []byte("\n<div class=\"footnotes\">\n\n"))
|
||||||
// attrs.push(['start', start.toString()]);
|
r.out(w, tag("hr", attrs, r.Flags&UseXHTML != 0))
|
||||||
// }
|
r.cr(w)
|
||||||
|
}
|
||||||
r.cr(w)
|
r.cr(w)
|
||||||
if node.Parent.Type == Item && node.Parent.Parent.Tight {
|
if node.Parent.Type == Item && node.Parent.Parent.Tight {
|
||||||
r.cr(w)
|
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 {
|
if node.Parent.Type == Document || node.Parent.Type == BlockQuote {
|
||||||
r.cr(w)
|
r.cr(w)
|
||||||
}
|
}
|
||||||
|
if node.IsFootnotesList {
|
||||||
|
r.out(w, []byte("\n</div>\n"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case Item:
|
case Item:
|
||||||
tagName := "li"
|
tagName := "li"
|
||||||
|
|
|
@ -922,6 +922,12 @@ what happens here
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
|
|
||||||
|
`This text does not reference a footnote.
|
||||||
|
|
||||||
|
[^footnote]: But it has a footnote! And it gets omitted.
|
||||||
|
`,
|
||||||
|
"<p>This text does not reference a footnote.</p>\n",
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFootnotes(t *testing.T) {
|
func TestFootnotes(t *testing.T) {
|
||||||
|
|
|
@ -416,9 +416,8 @@ func (p *parser) parseRefsToAST() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p.tip = p.doc
|
p.tip = p.doc
|
||||||
finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte(`<div class="footnotes">`)))
|
|
||||||
p.addBlock(HorizontalRule, nil)
|
|
||||||
block := p.addBlock(List, nil)
|
block := p.addBlock(List, nil)
|
||||||
|
block.IsFootnotesList = true
|
||||||
block.ListFlags = ListTypeOrdered
|
block.ListFlags = ListTypeOrdered
|
||||||
flags := ListItemBeginningOfList
|
flags := ListItemBeginningOfList
|
||||||
// Note: this loop is intentionally explicit, not range-form. This is
|
// Note: this loop is intentionally explicit, not range-form. This is
|
||||||
|
@ -441,7 +440,6 @@ func (p *parser) parseRefsToAST() {
|
||||||
above := block.Parent
|
above := block.Parent
|
||||||
finalizeList(block)
|
finalizeList(block)
|
||||||
p.tip = above
|
p.tip = above
|
||||||
finalizeHTMLBlock(p.addBlock(HTMLBlock, []byte("</div>")))
|
|
||||||
block.Walk(func(node *Node, entering bool) WalkStatus {
|
block.Walk(func(node *Node, entering bool) WalkStatus {
|
||||||
if node.Type == Paragraph || node.Type == Header {
|
if node.Type == Paragraph || node.Type == Header {
|
||||||
p.inline(node, node.content)
|
p.inline(node, node.content)
|
||||||
|
|
19
node.go
19
node.go
|
@ -69,20 +69,21 @@ func (t NodeType) String() string {
|
||||||
return nodeTypeNames[t]
|
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 {
|
type ListData struct {
|
||||||
ListFlags ListType
|
ListFlags ListType
|
||||||
Tight bool // Skip <p>s around list item data if true
|
Tight bool // Skip <p>s around list item data if true
|
||||||
BulletChar byte // '*', '+' or '-' in bullet lists
|
BulletChar byte // '*', '+' or '-' in bullet lists
|
||||||
Delimiter byte // '.' or ')' after the number in ordered 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
|
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.
|
// LinkData contains fields relevant to a Link node type.
|
||||||
type LinkData struct {
|
type LinkData struct {
|
||||||
Destination []byte
|
Destination []byte // Destination is what goes into a href
|
||||||
Title []byte
|
Title []byte // Title is the tooltip thing that goes in a title attribute
|
||||||
NoteID int
|
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.
|
// CodeBlockData contains fields relevant to a CodeBlock node type.
|
||||||
|
|
Loading…
Reference in New Issue