/
renderer.go
116 lines (105 loc) · 3.79 KB
/
renderer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package renderers
import (
"io"
md "github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
"github.com/gomarkdown/markdown/parser"
)
type renderer interface {
prepareText(node *ast.Text, entering bool)
prepareBlockQuote(node *ast.BlockQuote, entering bool)
prepareCode(node *ast.Code, entering bool)
prepareCodeBlock(node *ast.CodeBlock, entering bool)
prepareList(node *ast.List, entering bool)
prepareListItem(node *ast.ListItem, entering bool)
prepareParagraph(node *ast.Paragraph, entering bool)
prepareHeading(node *ast.Heading, entering bool)
prepareStrong(node *ast.Strong, entering bool)
prepareDel(node *ast.Del, entering bool)
prepareEmph(node *ast.Emph, entering bool)
prepareLink(node *ast.Link, entering bool)
prepareTable(node *ast.Table, entering bool)
prepareTableCell(node *ast.TableCell, entering bool)
prepareTableRow(node *ast.TableRow, entering bool)
prepareHorizontalRule(node *ast.HorizontalRule, entering bool)
renderSoftBreak()
renderHardBreak()
}
type nodeWalker struct {
rootNode ast.Node
renderer renderer
}
func newNodeWalker(doc string, renderer renderer) *nodeWalker {
extensions := parser.NoIntraEmphasis // Ignore emphasis markers inside words
extensions |= parser.Tables // Parse tables
extensions |= parser.FencedCode // Parse fenced code blocks
extensions |= parser.Autolink // Detect embedded URLs that are not explicitly marked
extensions |= parser.Strikethrough // Strikethrough text using ~~test~~
extensions |= parser.SpaceHeadings // Be strict about prefix heading rules
extensions |= parser.HeadingIDs // specify heading IDs with {#id}
extensions |= parser.BackslashLineBreak // Translate trailing backslashes into line breaks
extensions |= parser.DefinitionLists // Parse definition lists
extensions |= parser.LaxHTMLBlocks // more in HTMLBlock, less in HTMLSpan
extensions |= parser.NoEmptyLineBeforeBlock // no need for new line before a list
extensions |= parser.Attributes
extensions |= parser.EmptyLinesBreakList
extensions |= parser.Mmark
extensions |= parser.LaxHTMLBlocks
p := parser.NewWithExtensions(extensions)
return &nodeWalker{
rootNode: md.Parse([]byte(doc), p),
renderer: renderer,
}
}
func (nw *nodeWalker) walk() {
md.Render(nw.rootNode, nw)
}
func (nw *nodeWalker) RenderNode(_ io.Writer, node ast.Node, entering bool) ast.WalkStatus {
switch node := node.(type) {
case *ast.Document:
case *ast.BlockQuote:
nw.renderer.prepareBlockQuote(node, entering)
case *ast.Code:
nw.renderer.prepareCode(node, entering)
case *ast.CodeBlock:
nw.renderer.prepareCodeBlock(node, entering)
case *ast.List:
nw.renderer.prepareList(node, entering)
case *ast.ListItem:
nw.renderer.prepareListItem(node, entering)
case *ast.Paragraph:
nw.renderer.prepareParagraph(node, entering)
case *ast.Heading:
nw.renderer.prepareHeading(node, entering)
case *ast.Strong:
nw.renderer.prepareStrong(node, entering)
case *ast.Del:
nw.renderer.prepareDel(node, entering)
case *ast.Emph:
nw.renderer.prepareEmph(node, entering)
case *ast.Link:
if !entering {
nw.renderer.prepareLink(node, entering)
return ast.SkipChildren
}
case *ast.Softbreak:
nw.renderer.renderSoftBreak()
case *ast.Hardbreak:
nw.renderer.renderSoftBreak()
case *ast.Text:
nw.renderer.prepareText(node, entering)
case *ast.HorizontalRule:
nw.renderer.prepareHorizontalRule(node, entering)
case *ast.Table:
nw.renderer.prepareTable(node, entering)
case *ast.TableRow:
nw.renderer.prepareTableRow(node, entering)
case *ast.TableCell:
if !entering {
nw.renderer.prepareTableCell(node, entering)
}
}
return ast.GoToNext
}
func (*nodeWalker) RenderHeader(_ io.Writer, _ ast.Node) {}
func (*nodeWalker) RenderFooter(_ io.Writer, _ ast.Node) {}