You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

node.go 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package html
  5. import (
  6. "golang.org/x/net/html/atom"
  7. )
  8. // A NodeType is the type of a Node.
  9. type NodeType uint32
  10. const (
  11. ErrorNode NodeType = iota
  12. TextNode
  13. DocumentNode
  14. ElementNode
  15. CommentNode
  16. DoctypeNode
  17. scopeMarkerNode
  18. )
  19. // Section 12.2.4.3 says "The markers are inserted when entering applet,
  20. // object, marquee, template, td, th, and caption elements, and are used
  21. // to prevent formatting from "leaking" into applet, object, marquee,
  22. // template, td, th, and caption elements".
  23. var scopeMarker = Node{Type: scopeMarkerNode}
  24. // A Node consists of a NodeType and some Data (tag name for element nodes,
  25. // content for text) and are part of a tree of Nodes. Element nodes may also
  26. // have a Namespace and contain a slice of Attributes. Data is unescaped, so
  27. // that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
  28. // is the atom for Data, or zero if Data is not a known tag name.
  29. //
  30. // An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
  31. // Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
  32. // "svg" is short for "http://www.w3.org/2000/svg".
  33. type Node struct {
  34. Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
  35. Type NodeType
  36. DataAtom atom.Atom
  37. Data string
  38. Namespace string
  39. Attr []Attribute
  40. }
  41. // InsertBefore inserts newChild as a child of n, immediately before oldChild
  42. // in the sequence of n's children. oldChild may be nil, in which case newChild
  43. // is appended to the end of n's children.
  44. //
  45. // It will panic if newChild already has a parent or siblings.
  46. func (n *Node) InsertBefore(newChild, oldChild *Node) {
  47. if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
  48. panic("html: InsertBefore called for an attached child Node")
  49. }
  50. var prev, next *Node
  51. if oldChild != nil {
  52. prev, next = oldChild.PrevSibling, oldChild
  53. } else {
  54. prev = n.LastChild
  55. }
  56. if prev != nil {
  57. prev.NextSibling = newChild
  58. } else {
  59. n.FirstChild = newChild
  60. }
  61. if next != nil {
  62. next.PrevSibling = newChild
  63. } else {
  64. n.LastChild = newChild
  65. }
  66. newChild.Parent = n
  67. newChild.PrevSibling = prev
  68. newChild.NextSibling = next
  69. }
  70. // AppendChild adds a node c as a child of n.
  71. //
  72. // It will panic if c already has a parent or siblings.
  73. func (n *Node) AppendChild(c *Node) {
  74. if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
  75. panic("html: AppendChild called for an attached child Node")
  76. }
  77. last := n.LastChild
  78. if last != nil {
  79. last.NextSibling = c
  80. } else {
  81. n.FirstChild = c
  82. }
  83. n.LastChild = c
  84. c.Parent = n
  85. c.PrevSibling = last
  86. }
  87. // RemoveChild removes a node c that is a child of n. Afterwards, c will have
  88. // no parent and no siblings.
  89. //
  90. // It will panic if c's parent is not n.
  91. func (n *Node) RemoveChild(c *Node) {
  92. if c.Parent != n {
  93. panic("html: RemoveChild called for a non-child Node")
  94. }
  95. if n.FirstChild == c {
  96. n.FirstChild = c.NextSibling
  97. }
  98. if c.NextSibling != nil {
  99. c.NextSibling.PrevSibling = c.PrevSibling
  100. }
  101. if n.LastChild == c {
  102. n.LastChild = c.PrevSibling
  103. }
  104. if c.PrevSibling != nil {
  105. c.PrevSibling.NextSibling = c.NextSibling
  106. }
  107. c.Parent = nil
  108. c.PrevSibling = nil
  109. c.NextSibling = nil
  110. }
  111. // reparentChildren reparents all of src's child nodes to dst.
  112. func reparentChildren(dst, src *Node) {
  113. for {
  114. child := src.FirstChild
  115. if child == nil {
  116. break
  117. }
  118. src.RemoveChild(child)
  119. dst.AppendChild(child)
  120. }
  121. }
  122. // clone returns a new node with the same type, data and attributes.
  123. // The clone has no parent, no siblings and no children.
  124. func (n *Node) clone() *Node {
  125. m := &Node{
  126. Type: n.Type,
  127. DataAtom: n.DataAtom,
  128. Data: n.Data,
  129. Attr: make([]Attribute, len(n.Attr)),
  130. }
  131. copy(m.Attr, n.Attr)
  132. return m
  133. }
  134. // nodeStack is a stack of nodes.
  135. type nodeStack []*Node
  136. // pop pops the stack. It will panic if s is empty.
  137. func (s *nodeStack) pop() *Node {
  138. i := len(*s)
  139. n := (*s)[i-1]
  140. *s = (*s)[:i-1]
  141. return n
  142. }
  143. // top returns the most recently pushed node, or nil if s is empty.
  144. func (s *nodeStack) top() *Node {
  145. if i := len(*s); i > 0 {
  146. return (*s)[i-1]
  147. }
  148. return nil
  149. }
  150. // index returns the index of the top-most occurrence of n in the stack, or -1
  151. // if n is not present.
  152. func (s *nodeStack) index(n *Node) int {
  153. for i := len(*s) - 1; i >= 0; i-- {
  154. if (*s)[i] == n {
  155. return i
  156. }
  157. }
  158. return -1
  159. }
  160. // contains returns whether a is within s.
  161. func (s *nodeStack) contains(a atom.Atom) bool {
  162. for _, n := range *s {
  163. if n.DataAtom == a && n.Namespace == "" {
  164. return true
  165. }
  166. }
  167. return false
  168. }
  169. // insert inserts a node at the given index.
  170. func (s *nodeStack) insert(i int, n *Node) {
  171. (*s) = append(*s, nil)
  172. copy((*s)[i+1:], (*s)[i:])
  173. (*s)[i] = n
  174. }
  175. // remove removes a node from the stack. It is a no-op if n is not present.
  176. func (s *nodeStack) remove(n *Node) {
  177. i := s.index(n)
  178. if i == -1 {
  179. return
  180. }
  181. copy((*s)[i:], (*s)[i+1:])
  182. j := len(*s) - 1
  183. (*s)[j] = nil
  184. *s = (*s)[:j]
  185. }
  186. type insertionModeStack []insertionMode
  187. func (s *insertionModeStack) pop() (im insertionMode) {
  188. i := len(*s)
  189. im = (*s)[i-1]
  190. *s = (*s)[:i-1]
  191. return im
  192. }
  193. func (s *insertionModeStack) top() insertionMode {
  194. if i := len(*s); i > 0 {
  195. return (*s)[i-1]
  196. }
  197. return nil
  198. }