all repos — grayfriday @ 4d756003cd4d43b837fffc8916825ddabe9b674e

blackfriday fork with a few changes

Move TOC generation to the HTML Renderer
Pierre Neidhardt ambrevar@gmail.com
Tue, 09 Aug 2016 12:37:44 +0530
commit

4d756003cd4d43b837fffc8916825ddabe9b674e

parent

0f3eafddfa07d57c2d0fd289a9d6520a0f766220

2 files changed, 51 insertions(+), 64 deletions(-)

jump to
M html.gohtml.go

@@ -745,6 +745,54 @@ w.WriteString("</head>\n")

w.WriteString("<body>\n\n") } +func (r *HTMLRenderer) writeTOC(w *bytes.Buffer, ast *Node) { + w.WriteString("<nav>\n") + inHeader := false + tocLevel := 0 + headerCount := 0 + + ast.Walk(func(node *Node, entering bool) WalkStatus { + if node.Type == Header && !node.HeaderData.IsTitleblock { + inHeader = entering + if entering { + headerCount++ + node.HeaderID = fmt.Sprintf("toc_%d", headerCount) + if node.Level == tocLevel { + w.WriteString("</li>\n<li>") + } else if node.Level < tocLevel { + for node.Level < tocLevel { + tocLevel-- + w.WriteString("</li>\n</ul>\n") + } + w.WriteString("<li>") + } else { + for node.Level > tocLevel { + tocLevel++ + w.WriteString("\n<ul>\n<li>") + } + } + + fmt.Fprintf(w, `<a href="#toc_%d">`, headerCount) + } else { + w.WriteString("</a>") + } + return GoToNext + } + + if inHeader { + return r.RenderNode(w, node, entering) + } + + return GoToNext + }) + + for ; tocLevel > 0; tocLevel-- { + w.WriteString("</li>\n</ul>\n") + } + + w.WriteString("</nav>\n") +} + func (r *HTMLRenderer) writeDocumentFooter(w *bytes.Buffer) { if r.Flags&CompletePage == 0 { return

@@ -770,6 +818,9 @@ return GoToNext

}) var buff bytes.Buffer r.writeDocumentHeader(&buff, sr) + if r.Extensions&TOC != 0 || r.Extensions&OmitContents != 0 { + r.writeTOC(&buff, ast) + } ast.Walk(func(node *Node, entering bool) WalkStatus { return r.RenderNode(&buff, node, entering) })
M markdown.gomarkdown.go

@@ -415,71 +415,7 @@ }

return GoToNext }) p.parseRefsToAST() - p.generateTOC() return p.doc -} - -func (p *parser) generateTOC() { - if p.flags&TOC == 0 && p.flags&OmitContents == 0 { - return - } - navNode := NewNode(HTMLBlock) - navNode.Literal = []byte("<nav>") - navNode.open = false - - var topList *Node - var listNode *Node - var lastItem *Node - headerCount := 0 - currentLevel := 0 - p.doc.Walk(func(node *Node, entering bool) WalkStatus { - if entering && node.Type == Header { - if node.Level > currentLevel { - currentLevel++ - newList := NewNode(List) - if lastItem != nil { - lastItem.appendChild(newList) - listNode = newList - } else { - listNode = newList - topList = listNode - } - } - if node.Level < currentLevel { - finalizeList(listNode) - lastItem = listNode.Parent - listNode = lastItem.Parent - } - node.HeaderID = fmt.Sprintf("toc_%d", headerCount) - headerCount++ - lastItem = NewNode(Item) - listNode.appendChild(lastItem) - anchorNode := NewNode(Link) - anchorNode.Destination = []byte("#" + node.HeaderID) - lastItem.appendChild(anchorNode) - anchorNode.appendChild(text(node.FirstChild.Literal)) - } - return GoToNext - }) - firstChild := p.doc.FirstChild - // Insert TOC only if there is anything to insert - if topList != nil { - finalizeList(topList) - firstChild.insertBefore(navNode) - firstChild.insertBefore(topList) - navCloseNode := NewNode(HTMLBlock) - navCloseNode.Literal = []byte("</nav>") - navCloseNode.open = false - firstChild.insertBefore(navCloseNode) - } - // Drop everything after the TOC if OmitContents was requested - if p.flags&OmitContents != 0 { - for firstChild != nil { - next := firstChild.Next - firstChild.unlink() - firstChild = next - } - } } func (p *parser) parseRefsToAST() {