Source File
node.go
Belonging Package
github.com/russross/blackfriday/v2
package blackfriday
import (
)
const (
Document NodeType = iota
BlockQuote
List
Item
Paragraph
Heading
HorizontalRule
Emph
Strong
Del
Link
Image
Text
HTMLBlock
CodeBlock
Softbreak
Hardbreak
Code
HTMLSpan
Table
TableCell
TableHead
TableBody
TableRow
)
var nodeTypeNames = []string{
Document: "Document",
BlockQuote: "BlockQuote",
List: "List",
Item: "Item",
Paragraph: "Paragraph",
Heading: "Heading",
HorizontalRule: "HorizontalRule",
Emph: "Emph",
Strong: "Strong",
Del: "Del",
Link: "Link",
Image: "Image",
Text: "Text",
HTMLBlock: "HTMLBlock",
CodeBlock: "CodeBlock",
Softbreak: "Softbreak",
Hardbreak: "Hardbreak",
Code: "Code",
HTMLSpan: "HTMLSpan",
Table: "Table",
TableCell: "TableCell",
TableHead: "TableHead",
TableBody: "TableBody",
TableRow: "TableRow",
}
func ( NodeType) () string {
return nodeTypeNames[]
}
type ListData struct {
ListFlags ListType
Tight bool // Skip <p>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
}
type LinkData struct {
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
Footnote *Node // If it's a footnote, this is a direct link to the footnote Node. Otherwise nil.
}
type CodeBlockData struct {
IsFenced bool // Specifies whether it's a fenced code block or an indented one
Info []byte // This holds the info string
FenceChar byte
FenceLength int
FenceOffset int
}
type TableCellData struct {
IsHeader bool // This tells if it's under the header row
Align CellAlignFlags // This holds the value for align attribute
}
type HeadingData struct {
Level int // This holds the heading level number
HeadingID string // This might hold heading ID, if present
IsTitleblock bool // Specifies whether it's a title block
}
type Node struct {
Type NodeType // Determines the type of the node
Parent *Node // Points to the parent
FirstChild *Node // Points to the first child, if any
LastChild *Node // Points to the last child, if any
Prev *Node // Previous sibling; nil if it's the first child
Next *Node // Next sibling; nil if it's the last child
Literal []byte // Text contents of the leaf nodes
HeadingData // Populated if Type is Heading
ListData // Populated if Type is List
CodeBlockData // Populated if Type is CodeBlock
LinkData // Populated if Type is Link
TableCellData // Populated if Type is TableCell
content []byte // Markdown content of the block nodes
open bool // Specifies an open block node that has not been finished to process yet
}
func ( *Node) ( *Node) {
.Unlink()
.Prev = .Prev
if .Prev != nil {
.Prev.Next =
}
.Next =
.Prev =
.Parent = .Parent
if .Prev == nil {
.Parent.FirstChild =
}
}
func ( *Node) () bool {
switch .Type {
case Document:
fallthrough
case BlockQuote:
fallthrough
case List:
fallthrough
case Item:
fallthrough
case Paragraph:
fallthrough
case Heading:
fallthrough
case Emph:
fallthrough
case Strong:
fallthrough
case Del:
fallthrough
case Link:
fallthrough
case Image:
fallthrough
case Table:
fallthrough
case TableHead:
fallthrough
case TableBody:
fallthrough
case TableRow:
fallthrough
case TableCell:
return true
default:
return false
}
}
func ( *Node) ( NodeType) bool {
if .Type == List {
return == Item
}
if .Type == Document || .Type == BlockQuote || .Type == Item {
return != Item
}
if .Type == Table {
return == TableHead || == TableBody
}
if .Type == TableHead || .Type == TableBody {
return == TableRow
}
if .Type == TableRow {
return == TableCell
}
return false
}
type WalkStatus int
type NodeVisitor func(node *Node, entering bool) WalkStatus
func ( *Node) ( NodeVisitor) {
:= newNodeWalker()
for .current != nil {
:= (.current, .entering)
switch {
case GoToNext:
.next()
case SkipChildren:
.entering = false
.next()
case Terminate:
return
}
}
}
type nodeWalker struct {
current *Node
root *Node
entering bool
}
func ( *Node) *nodeWalker {
return &nodeWalker{
current: ,
root: ,
entering: true,
}
}
func ( *nodeWalker) () {
if (!.current.isContainer() || !.entering) && .current == .root {
.current = nil
return
}
if .entering && .current.isContainer() {
if .current.FirstChild != nil {
.current = .current.FirstChild
.entering = true
} else {
.entering = false
}
} else if .current.Next == nil {
.current = .current.Parent
.entering = false
} else {
.current = .current.Next
.entering = true
}
}
func ( *Node) {
fmt.Println(dumpString())
}
func ( *Node, int) string {
if == nil {
return ""
}
:= bytes.Repeat([]byte("\t"), )
:= .Literal
if == nil {
= .content
}
:= fmt.Sprintf("%s%s(%q)\n", , .Type, )
for := .FirstChild; != nil; = .Next {
+= (, +1)
}
return
}
func ( *Node) string {
return dumpR(, 0)
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |