ast.go (13070B)
1 // Package ast defines AST nodes that represent markdown elements. 2 package ast 3 4 import ( 5 "bytes" 6 "fmt" 7 "strings" 8 9 textm "github.com/yuin/goldmark/text" 10 "github.com/yuin/goldmark/util" 11 ) 12 13 // A NodeType indicates what type a node belongs to. 14 type NodeType int 15 16 const ( 17 // TypeBlock indicates that a node is kind of block nodes. 18 TypeBlock NodeType = iota + 1 19 // TypeInline indicates that a node is kind of inline nodes. 20 TypeInline 21 // TypeDocument indicates that a node is kind of document nodes. 22 TypeDocument 23 ) 24 25 // NodeKind indicates more specific type than NodeType. 26 type NodeKind int 27 28 func (k NodeKind) String() string { 29 return kindNames[k] 30 } 31 32 var kindMax NodeKind 33 var kindNames = []string{""} 34 35 // NewNodeKind returns a new Kind value. 36 func NewNodeKind(name string) NodeKind { 37 kindMax++ 38 kindNames = append(kindNames, name) 39 return kindMax 40 } 41 42 // An Attribute is an attribute of the Node 43 type Attribute struct { 44 Name []byte 45 Value interface{} 46 } 47 48 // A Node interface defines basic AST node functionalities. 49 type Node interface { 50 // Type returns a type of this node. 51 Type() NodeType 52 53 // Kind returns a kind of this node. 54 Kind() NodeKind 55 56 // NextSibling returns a next sibling node of this node. 57 NextSibling() Node 58 59 // PreviousSibling returns a previous sibling node of this node. 60 PreviousSibling() Node 61 62 // Parent returns a parent node of this node. 63 Parent() Node 64 65 // SetParent sets a parent node to this node. 66 SetParent(Node) 67 68 // SetPreviousSibling sets a previous sibling node to this node. 69 SetPreviousSibling(Node) 70 71 // SetNextSibling sets a next sibling node to this node. 72 SetNextSibling(Node) 73 74 // HasChildren returns true if this node has any children, otherwise false. 75 HasChildren() bool 76 77 // ChildCount returns a total number of children. 78 ChildCount() int 79 80 // FirstChild returns a first child of this node. 81 FirstChild() Node 82 83 // LastChild returns a last child of this node. 84 LastChild() Node 85 86 // AppendChild append a node child to the tail of the children. 87 AppendChild(self, child Node) 88 89 // RemoveChild removes a node child from this node. 90 // If a node child is not children of this node, RemoveChild nothing to do. 91 RemoveChild(self, child Node) 92 93 // RemoveChildren removes all children from this node. 94 RemoveChildren(self Node) 95 96 // SortChildren sorts childrens by comparator. 97 SortChildren(comparator func(n1, n2 Node) int) 98 99 // ReplaceChild replace a node v1 with a node insertee. 100 // If v1 is not children of this node, ReplaceChild append a insetee to the 101 // tail of the children. 102 ReplaceChild(self, v1, insertee Node) 103 104 // InsertBefore inserts a node insertee before a node v1. 105 // If v1 is not children of this node, InsertBefore append a insetee to the 106 // tail of the children. 107 InsertBefore(self, v1, insertee Node) 108 109 // InsertAfterinserts a node insertee after a node v1. 110 // If v1 is not children of this node, InsertBefore append a insetee to the 111 // tail of the children. 112 InsertAfter(self, v1, insertee Node) 113 114 // OwnerDocument returns this node's owner document. 115 // If this node is not a child of the Document node, OwnerDocument 116 // returns nil. 117 OwnerDocument() *Document 118 119 // Dump dumps an AST tree structure to stdout. 120 // This function completely aimed for debugging. 121 // level is a indent level. Implementer should indent informations with 122 // 2 * level spaces. 123 Dump(source []byte, level int) 124 125 // Text returns text values of this node. 126 Text(source []byte) []byte 127 128 // HasBlankPreviousLines returns true if the row before this node is blank, 129 // otherwise false. 130 // This method is valid only for block nodes. 131 HasBlankPreviousLines() bool 132 133 // SetBlankPreviousLines sets whether the row before this node is blank. 134 // This method is valid only for block nodes. 135 SetBlankPreviousLines(v bool) 136 137 // Lines returns text segments that hold positions in a source. 138 // This method is valid only for block nodes. 139 Lines() *textm.Segments 140 141 // SetLines sets text segments that hold positions in a source. 142 // This method is valid only for block nodes. 143 SetLines(*textm.Segments) 144 145 // IsRaw returns true if contents should be rendered as 'raw' contents. 146 IsRaw() bool 147 148 // SetAttribute sets the given value to the attributes. 149 SetAttribute(name []byte, value interface{}) 150 151 // SetAttributeString sets the given value to the attributes. 152 SetAttributeString(name string, value interface{}) 153 154 // Attribute returns a (attribute value, true) if an attribute 155 // associated with the given name is found, otherwise 156 // (nil, false) 157 Attribute(name []byte) (interface{}, bool) 158 159 // AttributeString returns a (attribute value, true) if an attribute 160 // associated with the given name is found, otherwise 161 // (nil, false) 162 AttributeString(name string) (interface{}, bool) 163 164 // Attributes returns a list of attributes. 165 // This may be a nil if there are no attributes. 166 Attributes() []Attribute 167 168 // RemoveAttributes removes all attributes from this node. 169 RemoveAttributes() 170 } 171 172 // A BaseNode struct implements the Node interface partialliy. 173 type BaseNode struct { 174 firstChild Node 175 lastChild Node 176 parent Node 177 next Node 178 prev Node 179 childCount int 180 attributes []Attribute 181 } 182 183 func ensureIsolated(v Node) { 184 if p := v.Parent(); p != nil { 185 p.RemoveChild(p, v) 186 } 187 } 188 189 // HasChildren implements Node.HasChildren . 190 func (n *BaseNode) HasChildren() bool { 191 return n.firstChild != nil 192 } 193 194 // SetPreviousSibling implements Node.SetPreviousSibling . 195 func (n *BaseNode) SetPreviousSibling(v Node) { 196 n.prev = v 197 } 198 199 // SetNextSibling implements Node.SetNextSibling . 200 func (n *BaseNode) SetNextSibling(v Node) { 201 n.next = v 202 } 203 204 // PreviousSibling implements Node.PreviousSibling . 205 func (n *BaseNode) PreviousSibling() Node { 206 return n.prev 207 } 208 209 // NextSibling implements Node.NextSibling . 210 func (n *BaseNode) NextSibling() Node { 211 return n.next 212 } 213 214 // RemoveChild implements Node.RemoveChild . 215 func (n *BaseNode) RemoveChild(self, v Node) { 216 if v.Parent() != self { 217 return 218 } 219 n.childCount-- 220 prev := v.PreviousSibling() 221 next := v.NextSibling() 222 if prev != nil { 223 prev.SetNextSibling(next) 224 } else { 225 n.firstChild = next 226 } 227 if next != nil { 228 next.SetPreviousSibling(prev) 229 } else { 230 n.lastChild = prev 231 } 232 v.SetParent(nil) 233 v.SetPreviousSibling(nil) 234 v.SetNextSibling(nil) 235 } 236 237 // RemoveChildren implements Node.RemoveChildren . 238 func (n *BaseNode) RemoveChildren(self Node) { 239 for c := n.firstChild; c != nil; { 240 c.SetParent(nil) 241 c.SetPreviousSibling(nil) 242 next := c.NextSibling() 243 c.SetNextSibling(nil) 244 c = next 245 } 246 n.firstChild = nil 247 n.lastChild = nil 248 n.childCount = 0 249 } 250 251 // SortChildren implements Node.SortChildren 252 func (n *BaseNode) SortChildren(comparator func(n1, n2 Node) int) { 253 var sorted Node 254 current := n.firstChild 255 for current != nil { 256 next := current.NextSibling() 257 if sorted == nil || comparator(sorted, current) >= 0 { 258 current.SetNextSibling(sorted) 259 if sorted != nil { 260 sorted.SetPreviousSibling(current) 261 } 262 sorted = current 263 sorted.SetPreviousSibling(nil) 264 } else { 265 c := sorted 266 for c.NextSibling() != nil && comparator(c.NextSibling(), current) < 0 { 267 c = c.NextSibling() 268 } 269 current.SetNextSibling(c.NextSibling()) 270 current.SetPreviousSibling(c) 271 if c.NextSibling() != nil { 272 c.NextSibling().SetPreviousSibling(current) 273 } 274 c.SetNextSibling(current) 275 } 276 current = next 277 } 278 n.firstChild = sorted 279 for c := n.firstChild; c != nil; c = c.NextSibling() { 280 n.lastChild = c 281 } 282 } 283 284 // FirstChild implements Node.FirstChild . 285 func (n *BaseNode) FirstChild() Node { 286 return n.firstChild 287 } 288 289 // LastChild implements Node.LastChild . 290 func (n *BaseNode) LastChild() Node { 291 return n.lastChild 292 } 293 294 // ChildCount implements Node.ChildCount . 295 func (n *BaseNode) ChildCount() int { 296 return n.childCount 297 } 298 299 // Parent implements Node.Parent . 300 func (n *BaseNode) Parent() Node { 301 return n.parent 302 } 303 304 // SetParent implements Node.SetParent . 305 func (n *BaseNode) SetParent(v Node) { 306 n.parent = v 307 } 308 309 // AppendChild implements Node.AppendChild . 310 func (n *BaseNode) AppendChild(self, v Node) { 311 ensureIsolated(v) 312 if n.firstChild == nil { 313 n.firstChild = v 314 v.SetNextSibling(nil) 315 v.SetPreviousSibling(nil) 316 } else { 317 last := n.lastChild 318 last.SetNextSibling(v) 319 v.SetPreviousSibling(last) 320 } 321 v.SetParent(self) 322 n.lastChild = v 323 n.childCount++ 324 } 325 326 // ReplaceChild implements Node.ReplaceChild . 327 func (n *BaseNode) ReplaceChild(self, v1, insertee Node) { 328 n.InsertBefore(self, v1, insertee) 329 n.RemoveChild(self, v1) 330 } 331 332 // InsertAfter implements Node.InsertAfter . 333 func (n *BaseNode) InsertAfter(self, v1, insertee Node) { 334 n.InsertBefore(self, v1.NextSibling(), insertee) 335 } 336 337 // InsertBefore implements Node.InsertBefore . 338 func (n *BaseNode) InsertBefore(self, v1, insertee Node) { 339 n.childCount++ 340 if v1 == nil { 341 n.AppendChild(self, insertee) 342 return 343 } 344 ensureIsolated(insertee) 345 if v1.Parent() == self { 346 c := v1 347 prev := c.PreviousSibling() 348 if prev != nil { 349 prev.SetNextSibling(insertee) 350 insertee.SetPreviousSibling(prev) 351 } else { 352 n.firstChild = insertee 353 insertee.SetPreviousSibling(nil) 354 } 355 insertee.SetNextSibling(c) 356 c.SetPreviousSibling(insertee) 357 insertee.SetParent(self) 358 } 359 } 360 361 // OwnerDocument implements Node.OwnerDocument 362 func (n *BaseNode) OwnerDocument() *Document { 363 d := n.Parent() 364 for { 365 p := d.Parent() 366 if p == nil { 367 if v, ok := d.(*Document); ok { 368 return v 369 } 370 break 371 } 372 d = p 373 } 374 return nil 375 } 376 377 // Text implements Node.Text . 378 func (n *BaseNode) Text(source []byte) []byte { 379 var buf bytes.Buffer 380 for c := n.firstChild; c != nil; c = c.NextSibling() { 381 buf.Write(c.Text(source)) 382 } 383 return buf.Bytes() 384 } 385 386 // SetAttribute implements Node.SetAttribute. 387 func (n *BaseNode) SetAttribute(name []byte, value interface{}) { 388 if n.attributes == nil { 389 n.attributes = make([]Attribute, 0, 10) 390 } else { 391 for i, a := range n.attributes { 392 if bytes.Equal(a.Name, name) { 393 n.attributes[i].Name = name 394 n.attributes[i].Value = value 395 return 396 } 397 } 398 } 399 n.attributes = append(n.attributes, Attribute{name, value}) 400 } 401 402 // SetAttributeString implements Node.SetAttributeString 403 func (n *BaseNode) SetAttributeString(name string, value interface{}) { 404 n.SetAttribute(util.StringToReadOnlyBytes(name), value) 405 } 406 407 // Attribute implements Node.Attribute. 408 func (n *BaseNode) Attribute(name []byte) (interface{}, bool) { 409 if n.attributes == nil { 410 return nil, false 411 } 412 for i, a := range n.attributes { 413 if bytes.Equal(a.Name, name) { 414 return n.attributes[i].Value, true 415 } 416 } 417 return nil, false 418 } 419 420 // AttributeString implements Node.AttributeString. 421 func (n *BaseNode) AttributeString(s string) (interface{}, bool) { 422 return n.Attribute(util.StringToReadOnlyBytes(s)) 423 } 424 425 // Attributes implements Node.Attributes 426 func (n *BaseNode) Attributes() []Attribute { 427 return n.attributes 428 } 429 430 // RemoveAttributes implements Node.RemoveAttributes 431 func (n *BaseNode) RemoveAttributes() { 432 n.attributes = nil 433 } 434 435 // DumpHelper is a helper function to implement Node.Dump. 436 // kv is pairs of an attribute name and an attribute value. 437 // cb is a function called after wrote a name and attributes. 438 func DumpHelper(v Node, source []byte, level int, kv map[string]string, cb func(int)) { 439 name := v.Kind().String() 440 indent := strings.Repeat(" ", level) 441 fmt.Printf("%s%s {\n", indent, name) 442 indent2 := strings.Repeat(" ", level+1) 443 if v.Type() == TypeBlock { 444 fmt.Printf("%sRawText: \"", indent2) 445 for i := 0; i < v.Lines().Len(); i++ { 446 line := v.Lines().At(i) 447 fmt.Printf("%s", line.Value(source)) 448 } 449 fmt.Printf("\"\n") 450 fmt.Printf("%sHasBlankPreviousLines: %v\n", indent2, v.HasBlankPreviousLines()) 451 } 452 for name, value := range kv { 453 fmt.Printf("%s%s: %s\n", indent2, name, value) 454 } 455 if cb != nil { 456 cb(level + 1) 457 } 458 for c := v.FirstChild(); c != nil; c = c.NextSibling() { 459 c.Dump(source, level+1) 460 } 461 fmt.Printf("%s}\n", indent) 462 } 463 464 // WalkStatus represents a current status of the Walk function. 465 type WalkStatus int 466 467 const ( 468 // WalkStop indicates no more walking needed. 469 WalkStop WalkStatus = iota + 1 470 471 // WalkSkipChildren indicates that Walk wont walk on children of current 472 // node. 473 WalkSkipChildren 474 475 // WalkContinue indicates that Walk can continue to walk. 476 WalkContinue 477 ) 478 479 // Walker is a function that will be called when Walk find a 480 // new node. 481 // entering is set true before walks children, false after walked children. 482 // If Walker returns error, Walk function immediately stop walking. 483 type Walker func(n Node, entering bool) (WalkStatus, error) 484 485 // Walk walks a AST tree by the depth first search algorithm. 486 func Walk(n Node, walker Walker) error { 487 _, err := walkHelper(n, walker) 488 return err 489 } 490 491 func walkHelper(n Node, walker Walker) (WalkStatus, error) { 492 status, err := walker(n, true) 493 if err != nil || status == WalkStop { 494 return status, err 495 } 496 if status != WalkSkipChildren { 497 for c := n.FirstChild(); c != nil; c = c.NextSibling() { 498 if st, err := walkHelper(c, walker); err != nil || st == WalkStop { 499 return WalkStop, err 500 } 501 } 502 } 503 status, err = walker(n, false) 504 if err != nil || status == WalkStop { 505 return WalkStop, err 506 } 507 return WalkContinue, nil 508 }