add LeafNode type
This commit is contained in:
parent
54d85c47da
commit
439dda2727
115
ast/node.go
115
ast/node.go
|
@ -37,9 +37,12 @@ const (
|
|||
type Node interface {
|
||||
AsTreeNode() *TreeNode
|
||||
GetParent() Node
|
||||
SetParent(newParent Node)
|
||||
GetChildren() []Node
|
||||
SetChildren(newChildren []Node)
|
||||
FirstChild() Node
|
||||
LastChild() Node
|
||||
SetContent(c []byte)
|
||||
}
|
||||
|
||||
// TreeNode is a common part of all nodes, used to represent tree and contain
|
||||
|
@ -64,11 +67,75 @@ func (n *TreeNode) GetParent() Node {
|
|||
return n.Parent
|
||||
}
|
||||
|
||||
// SetParent sets the parent
|
||||
func (n *TreeNode) SetParent(newParent Node) {
|
||||
n.Parent = newParent
|
||||
}
|
||||
|
||||
// GetChildren returns children
|
||||
func (n *TreeNode) GetChildren() []Node {
|
||||
return n.Children
|
||||
}
|
||||
|
||||
// SetChildren sets children
|
||||
func (n *TreeNode) SetChildren(newChildren []Node) {
|
||||
n.Children = newChildren
|
||||
}
|
||||
|
||||
// SetContent sets content of the node
|
||||
func (n *TreeNode) SetContent(c []byte) {
|
||||
n.Content = c
|
||||
}
|
||||
|
||||
// LeafNode is a common part of all nodes, used to represent tree and contain
|
||||
// data that all nodes have in common
|
||||
type LeafNode struct {
|
||||
Parent Node
|
||||
|
||||
Literal []byte // Text contents of the leaf nodes
|
||||
Content []byte // Markdown content of the block nodes
|
||||
}
|
||||
|
||||
// AsTreeNode returns itself as *TreeNode
|
||||
func (n *LeafNode) AsTreeNode() *TreeNode {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParent returns parent
|
||||
func (n *LeafNode) GetParent() Node {
|
||||
return n.Parent
|
||||
}
|
||||
|
||||
// SetParent sets the parent
|
||||
func (n *LeafNode) SetParent(newParent Node) {
|
||||
n.Parent = newParent
|
||||
}
|
||||
|
||||
// GetChildren returns children
|
||||
func (n *LeafNode) GetChildren() []Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetChildren sets children
|
||||
func (n *LeafNode) SetChildren(newChildren []Node) {
|
||||
// do nothing, LeafNode has no children
|
||||
}
|
||||
|
||||
// FirstChild returns children
|
||||
func (n *LeafNode) FirstChild() Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LastChild returns children
|
||||
func (n *LeafNode) LastChild() Node {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetContent sets content of the node
|
||||
func (n *LeafNode) SetContent(c []byte) {
|
||||
n.Content = c
|
||||
}
|
||||
|
||||
// PanicIfTreeNode will panic if node is *TreeNode
|
||||
func PanicIfTreeNode(node Node) {
|
||||
if _, ok := node.(*TreeNode); ok {
|
||||
|
@ -135,7 +202,7 @@ type Heading struct {
|
|||
|
||||
// HorizontalRule represents data for horizontal rule node
|
||||
type HorizontalRule struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// Emph represents data for emp node
|
||||
|
@ -173,17 +240,17 @@ type Image struct {
|
|||
|
||||
// Text represents data for text node
|
||||
type Text struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// HTMLBlock represents data for html node
|
||||
type HTMLBlock struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// CodeBlock contains fields relevant to a CodeBlock node type.
|
||||
type CodeBlock struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
|
||||
IsFenced bool // Specifies whether it's a fenced code block or an indented one
|
||||
Info []byte // This holds the info string
|
||||
|
@ -195,22 +262,22 @@ type CodeBlock struct {
|
|||
// Softbreak represents data for softbreak node
|
||||
// Note: not used currently
|
||||
type Softbreak struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// Hardbreak represents data for hard break node
|
||||
type Hardbreak struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// Code represents data for code node
|
||||
type Code struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// HTMLSpan represents data for html span node
|
||||
type HTMLSpan struct {
|
||||
TreeNode
|
||||
LeafNode
|
||||
}
|
||||
|
||||
// Table represents data for table node
|
||||
|
@ -265,27 +332,29 @@ func removeNodeFromArray(a []Node, node Node) []Node {
|
|||
|
||||
// RemoveFromTree removes this node from tree
|
||||
func RemoveFromTree(n Node) {
|
||||
nt := n.AsTreeNode()
|
||||
if nt.Parent == nil {
|
||||
if n.GetParent() == nil {
|
||||
return
|
||||
}
|
||||
// important: don't clear n.Children if n has no parent
|
||||
// we're called from AppendChild and that might happen on a node
|
||||
// that accumulated Children but hasn't been inserted into the tree
|
||||
p := nt.Parent.AsTreeNode()
|
||||
p.Children = removeNodeFromArray(p.Children, n)
|
||||
nt.Parent = nil
|
||||
nt.Children = nil
|
||||
p := n.GetParent()
|
||||
newChildren := removeNodeFromArray(p.GetChildren(), n)
|
||||
p.SetChildren(newChildren)
|
||||
n.SetChildren(nil)
|
||||
}
|
||||
|
||||
// AppendChild adds a node 'child' as a child of 'n'.
|
||||
// It panics if either node is nil.
|
||||
func AppendChild(n Node, child Node) {
|
||||
childTN := child.AsTreeNode()
|
||||
RemoveFromTree(child)
|
||||
childTN.Parent = n
|
||||
nTN := n.AsTreeNode()
|
||||
nTN.Children = append(nTN.Children, child)
|
||||
child.SetParent(n)
|
||||
newChildren := append(n.GetChildren(), child)
|
||||
n.SetChildren(newChildren)
|
||||
}
|
||||
|
||||
func isContainer(n Node) bool {
|
||||
return n.AsTreeNode() != nil
|
||||
}
|
||||
|
||||
// LastChild returns last child of this node
|
||||
|
@ -336,16 +405,6 @@ func PrevNode(n Node) Node {
|
|||
return nil
|
||||
}
|
||||
|
||||
func isContainer(n Node) bool {
|
||||
// list of non-containers is smaller so we check against that for speed
|
||||
switch n.(type) {
|
||||
case *HorizontalRule, *Text, *HTMLBlock, *CodeBlock, *Softbreak, *Hardbreak, *Code, *HTMLSpan:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// WalkStatus allows NodeVisitor to have some control over the tree traversal.
|
||||
// It is returned from NodeVisitor and different values allow Node.Walk to
|
||||
// decide which node to go to next.
|
||||
|
|
|
@ -253,7 +253,7 @@ func (p *Parser) block(data []byte) {
|
|||
func (p *Parser) addBlock(n ast.Node, content []byte) ast.Node {
|
||||
p.closeUnmatchedBlocks()
|
||||
container := p.addChild(n, 0)
|
||||
container.AsTreeNode().Content = content
|
||||
container.SetContent(content)
|
||||
return container
|
||||
}
|
||||
|
||||
|
@ -455,14 +455,15 @@ func (p *Parser) html(data []byte, doRender bool) int {
|
|||
if doRender {
|
||||
// trim newlines
|
||||
end := backChar(data, i, '\n')
|
||||
finalizeHTMLBlock(p.addBlock(&ast.HTMLBlock{}, data[:end]))
|
||||
htmlBlock := &ast.HTMLBlock{}
|
||||
p.addBlock(htmlBlock, data[:end])
|
||||
finalizeHTMLBlock(htmlBlock)
|
||||
}
|
||||
|
||||
return i
|
||||
}
|
||||
|
||||
func finalizeHTMLBlock(blockNode ast.Node) {
|
||||
block := blockNode.AsTreeNode()
|
||||
func finalizeHTMLBlock(block *ast.HTMLBlock) {
|
||||
block.Literal = block.Content
|
||||
block.Content = nil
|
||||
}
|
||||
|
@ -476,8 +477,9 @@ func (p *Parser) htmlComment(data []byte, doRender bool) int {
|
|||
if doRender {
|
||||
// trim trailing newlines
|
||||
end := backChar(data, size, '\n')
|
||||
block := p.addBlock(&ast.HTMLBlock{}, data[:end])
|
||||
finalizeHTMLBlock(block)
|
||||
htmlBLock := &ast.HTMLBlock{}
|
||||
p.addBlock(htmlBLock, data[:end])
|
||||
finalizeHTMLBlock(htmlBLock)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
@ -507,7 +509,9 @@ func (p *Parser) htmlHr(data []byte, doRender bool) int {
|
|||
if doRender {
|
||||
// trim newlines
|
||||
end := backChar(data, size, '\n')
|
||||
finalizeHTMLBlock(p.addBlock(&ast.HTMLBlock{}, data[:end]))
|
||||
htmlBlock := &ast.HTMLBlock{}
|
||||
p.addBlock(htmlBlock, data[:end])
|
||||
finalizeHTMLBlock(htmlBlock)
|
||||
}
|
||||
return size
|
||||
}
|
||||
|
@ -742,11 +746,11 @@ func (p *Parser) fencedCodeBlock(data []byte, doRender bool) int {
|
|||
}
|
||||
|
||||
if doRender {
|
||||
d := &ast.CodeBlock{
|
||||
codeBlock := &ast.CodeBlock{
|
||||
IsFenced: true,
|
||||
}
|
||||
block := p.addBlock(d, work.Bytes()) // TODO: get rid of temp buffer
|
||||
finalizeCodeBlock(block, d)
|
||||
p.addBlock(codeBlock, work.Bytes()) // TODO: get rid of temp buffer
|
||||
finalizeCodeBlock(codeBlock)
|
||||
}
|
||||
|
||||
return beg
|
||||
|
@ -766,18 +770,18 @@ func unescapeString(str []byte) []byte {
|
|||
return str
|
||||
}
|
||||
|
||||
func finalizeCodeBlock(blockNode ast.Node, code *ast.CodeBlock) {
|
||||
block := blockNode.AsTreeNode()
|
||||
func finalizeCodeBlock(code *ast.CodeBlock) {
|
||||
c := code.Content
|
||||
if code.IsFenced {
|
||||
newlinePos := bytes.IndexByte(block.Content, '\n')
|
||||
firstLine := block.Content[:newlinePos]
|
||||
rest := block.Content[newlinePos+1:]
|
||||
newlinePos := bytes.IndexByte(c, '\n')
|
||||
firstLine := c[:newlinePos]
|
||||
rest := c[newlinePos+1:]
|
||||
code.Info = unescapeString(bytes.Trim(firstLine, "\n"))
|
||||
block.Literal = rest
|
||||
code.Literal = rest
|
||||
} else {
|
||||
block.Literal = block.Content
|
||||
code.Literal = c
|
||||
}
|
||||
block.Content = nil
|
||||
code.Content = nil
|
||||
}
|
||||
|
||||
func (p *Parser) table(data []byte) int {
|
||||
|
@ -1087,11 +1091,11 @@ func (p *Parser) code(data []byte) int {
|
|||
|
||||
work.WriteByte('\n')
|
||||
|
||||
d := &ast.CodeBlock{
|
||||
codeBlock := &ast.CodeBlock{
|
||||
IsFenced: false,
|
||||
}
|
||||
block := p.addBlock(d, work.Bytes()) // TODO: get rid of temp buffer
|
||||
finalizeCodeBlock(block, d)
|
||||
p.addBlock(codeBlock, work.Bytes()) // TODO: get rid of temp buffer
|
||||
finalizeCodeBlock(codeBlock)
|
||||
|
||||
return i
|
||||
}
|
||||
|
|
|
@ -1181,7 +1181,7 @@ func helperTripleEmphasis(p *Parser, data []byte, offset int, c byte) (int, ast.
|
|||
}
|
||||
|
||||
func newTextNode(d []byte) *ast.Text {
|
||||
return &ast.Text{ast.TreeNode{Literal: d}}
|
||||
return &ast.Text{ast.LeafNode{Literal: d}}
|
||||
}
|
||||
|
||||
func normalizeURI(s []byte) []byte {
|
||||
|
|
Loading…
Reference in New Issue