gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

node.go (5649B)


      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 	"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 	// RawNode nodes are not returned by the parser, but can be part of the
     22 	// Node tree passed to func Render to insert raw HTML (without escaping).
     23 	// If so, this package makes no guarantee that the rendered HTML is secure
     24 	// (from e.g. Cross Site Scripting attacks) or well-formed.
     25 	RawNode
     26 	scopeMarkerNode
     27 )
     28 
     29 // Section 12.2.4.3 says "The markers are inserted when entering applet,
     30 // object, marquee, template, td, th, and caption elements, and are used
     31 // to prevent formatting from "leaking" into applet, object, marquee,
     32 // template, td, th, and caption elements".
     33 var scopeMarker = Node{Type: scopeMarkerNode}
     34 
     35 // A Node consists of a NodeType and some Data (tag name for element nodes,
     36 // content for text) and are part of a tree of Nodes. Element nodes may also
     37 // have a Namespace and contain a slice of Attributes. Data is unescaped, so
     38 // that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
     39 // is the atom for Data, or zero if Data is not a known tag name.
     40 //
     41 // An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
     42 // Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
     43 // "svg" is short for "http://www.w3.org/2000/svg".
     44 type Node struct {
     45 	Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
     46 
     47 	Type      NodeType
     48 	DataAtom  atom.Atom
     49 	Data      string
     50 	Namespace string
     51 	Attr      []Attribute
     52 }
     53 
     54 // InsertBefore inserts newChild as a child of n, immediately before oldChild
     55 // in the sequence of n's children. oldChild may be nil, in which case newChild
     56 // is appended to the end of n's children.
     57 //
     58 // It will panic if newChild already has a parent or siblings.
     59 func (n *Node) InsertBefore(newChild, oldChild *Node) {
     60 	if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
     61 		panic("html: InsertBefore called for an attached child Node")
     62 	}
     63 	var prev, next *Node
     64 	if oldChild != nil {
     65 		prev, next = oldChild.PrevSibling, oldChild
     66 	} else {
     67 		prev = n.LastChild
     68 	}
     69 	if prev != nil {
     70 		prev.NextSibling = newChild
     71 	} else {
     72 		n.FirstChild = newChild
     73 	}
     74 	if next != nil {
     75 		next.PrevSibling = newChild
     76 	} else {
     77 		n.LastChild = newChild
     78 	}
     79 	newChild.Parent = n
     80 	newChild.PrevSibling = prev
     81 	newChild.NextSibling = next
     82 }
     83 
     84 // AppendChild adds a node c as a child of n.
     85 //
     86 // It will panic if c already has a parent or siblings.
     87 func (n *Node) AppendChild(c *Node) {
     88 	if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
     89 		panic("html: AppendChild called for an attached child Node")
     90 	}
     91 	last := n.LastChild
     92 	if last != nil {
     93 		last.NextSibling = c
     94 	} else {
     95 		n.FirstChild = c
     96 	}
     97 	n.LastChild = c
     98 	c.Parent = n
     99 	c.PrevSibling = last
    100 }
    101 
    102 // RemoveChild removes a node c that is a child of n. Afterwards, c will have
    103 // no parent and no siblings.
    104 //
    105 // It will panic if c's parent is not n.
    106 func (n *Node) RemoveChild(c *Node) {
    107 	if c.Parent != n {
    108 		panic("html: RemoveChild called for a non-child Node")
    109 	}
    110 	if n.FirstChild == c {
    111 		n.FirstChild = c.NextSibling
    112 	}
    113 	if c.NextSibling != nil {
    114 		c.NextSibling.PrevSibling = c.PrevSibling
    115 	}
    116 	if n.LastChild == c {
    117 		n.LastChild = c.PrevSibling
    118 	}
    119 	if c.PrevSibling != nil {
    120 		c.PrevSibling.NextSibling = c.NextSibling
    121 	}
    122 	c.Parent = nil
    123 	c.PrevSibling = nil
    124 	c.NextSibling = nil
    125 }
    126 
    127 // reparentChildren reparents all of src's child nodes to dst.
    128 func reparentChildren(dst, src *Node) {
    129 	for {
    130 		child := src.FirstChild
    131 		if child == nil {
    132 			break
    133 		}
    134 		src.RemoveChild(child)
    135 		dst.AppendChild(child)
    136 	}
    137 }
    138 
    139 // clone returns a new node with the same type, data and attributes.
    140 // The clone has no parent, no siblings and no children.
    141 func (n *Node) clone() *Node {
    142 	m := &Node{
    143 		Type:     n.Type,
    144 		DataAtom: n.DataAtom,
    145 		Data:     n.Data,
    146 		Attr:     make([]Attribute, len(n.Attr)),
    147 	}
    148 	copy(m.Attr, n.Attr)
    149 	return m
    150 }
    151 
    152 // nodeStack is a stack of nodes.
    153 type nodeStack []*Node
    154 
    155 // pop pops the stack. It will panic if s is empty.
    156 func (s *nodeStack) pop() *Node {
    157 	i := len(*s)
    158 	n := (*s)[i-1]
    159 	*s = (*s)[:i-1]
    160 	return n
    161 }
    162 
    163 // top returns the most recently pushed node, or nil if s is empty.
    164 func (s *nodeStack) top() *Node {
    165 	if i := len(*s); i > 0 {
    166 		return (*s)[i-1]
    167 	}
    168 	return nil
    169 }
    170 
    171 // index returns the index of the top-most occurrence of n in the stack, or -1
    172 // if n is not present.
    173 func (s *nodeStack) index(n *Node) int {
    174 	for i := len(*s) - 1; i >= 0; i-- {
    175 		if (*s)[i] == n {
    176 			return i
    177 		}
    178 	}
    179 	return -1
    180 }
    181 
    182 // contains returns whether a is within s.
    183 func (s *nodeStack) contains(a atom.Atom) bool {
    184 	for _, n := range *s {
    185 		if n.DataAtom == a && n.Namespace == "" {
    186 			return true
    187 		}
    188 	}
    189 	return false
    190 }
    191 
    192 // insert inserts a node at the given index.
    193 func (s *nodeStack) insert(i int, n *Node) {
    194 	(*s) = append(*s, nil)
    195 	copy((*s)[i+1:], (*s)[i:])
    196 	(*s)[i] = n
    197 }
    198 
    199 // remove removes a node from the stack. It is a no-op if n is not present.
    200 func (s *nodeStack) remove(n *Node) {
    201 	i := s.index(n)
    202 	if i == -1 {
    203 		return
    204 	}
    205 	copy((*s)[i:], (*s)[i+1:])
    206 	j := len(*s) - 1
    207 	(*s)[j] = nil
    208 	*s = (*s)[:j]
    209 }
    210 
    211 type insertionModeStack []insertionMode
    212 
    213 func (s *insertionModeStack) pop() (im insertionMode) {
    214 	i := len(*s)
    215 	im = (*s)[i-1]
    216 	*s = (*s)[:i-1]
    217 	return im
    218 }
    219 
    220 func (s *insertionModeStack) top() insertionMode {
    221 	if i := len(*s); i > 0 {
    222 		return (*s)[i-1]
    223 	}
    224 	return nil
    225 }