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