Path: blob/main/vendor/golang.org/x/net/html/node.go
2880 views
// Copyright 2011 The Go Authors. All rights reserved.1// Use of this source code is governed by a BSD-style2// license that can be found in the LICENSE file.34package html56import (7"golang.org/x/net/html/atom"8)910// A NodeType is the type of a Node.11type NodeType uint321213const (14ErrorNode NodeType = iota15TextNode16DocumentNode17ElementNode18CommentNode19DoctypeNode20// RawNode nodes are not returned by the parser, but can be part of the21// Node tree passed to func Render to insert raw HTML (without escaping).22// If so, this package makes no guarantee that the rendered HTML is secure23// (from e.g. Cross Site Scripting attacks) or well-formed.24RawNode25scopeMarkerNode26)2728// Section 12.2.4.3 says "The markers are inserted when entering applet,29// object, marquee, template, td, th, and caption elements, and are used30// to prevent formatting from "leaking" into applet, object, marquee,31// template, td, th, and caption elements".32var scopeMarker = Node{Type: scopeMarkerNode}3334// A Node consists of a NodeType and some Data (tag name for element nodes,35// content for text) and are part of a tree of Nodes. Element nodes may also36// have a Namespace and contain a slice of Attributes. Data is unescaped, so37// that it looks like "a<b" rather than "a<b". For element nodes, DataAtom38// is the atom for Data, or zero if Data is not a known tag name.39//40// Node trees may be navigated using the link fields (Parent,41// FirstChild, and so on) or a range loop over iterators such as42// [Node.Descendants].43//44// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.45// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and46// "svg" is short for "http://www.w3.org/2000/svg".47type Node struct {48Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node4950Type NodeType51DataAtom atom.Atom52Data string53Namespace string54Attr []Attribute55}5657// InsertBefore inserts newChild as a child of n, immediately before oldChild58// in the sequence of n's children. oldChild may be nil, in which case newChild59// is appended to the end of n's children.60//61// It will panic if newChild already has a parent or siblings.62func (n *Node) InsertBefore(newChild, oldChild *Node) {63if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {64panic("html: InsertBefore called for an attached child Node")65}66var prev, next *Node67if oldChild != nil {68prev, next = oldChild.PrevSibling, oldChild69} else {70prev = n.LastChild71}72if prev != nil {73prev.NextSibling = newChild74} else {75n.FirstChild = newChild76}77if next != nil {78next.PrevSibling = newChild79} else {80n.LastChild = newChild81}82newChild.Parent = n83newChild.PrevSibling = prev84newChild.NextSibling = next85}8687// AppendChild adds a node c as a child of n.88//89// It will panic if c already has a parent or siblings.90func (n *Node) AppendChild(c *Node) {91if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {92panic("html: AppendChild called for an attached child Node")93}94last := n.LastChild95if last != nil {96last.NextSibling = c97} else {98n.FirstChild = c99}100n.LastChild = c101c.Parent = n102c.PrevSibling = last103}104105// RemoveChild removes a node c that is a child of n. Afterwards, c will have106// no parent and no siblings.107//108// It will panic if c's parent is not n.109func (n *Node) RemoveChild(c *Node) {110if c.Parent != n {111panic("html: RemoveChild called for a non-child Node")112}113if n.FirstChild == c {114n.FirstChild = c.NextSibling115}116if c.NextSibling != nil {117c.NextSibling.PrevSibling = c.PrevSibling118}119if n.LastChild == c {120n.LastChild = c.PrevSibling121}122if c.PrevSibling != nil {123c.PrevSibling.NextSibling = c.NextSibling124}125c.Parent = nil126c.PrevSibling = nil127c.NextSibling = nil128}129130// reparentChildren reparents all of src's child nodes to dst.131func reparentChildren(dst, src *Node) {132for {133child := src.FirstChild134if child == nil {135break136}137src.RemoveChild(child)138dst.AppendChild(child)139}140}141142// clone returns a new node with the same type, data and attributes.143// The clone has no parent, no siblings and no children.144func (n *Node) clone() *Node {145m := &Node{146Type: n.Type,147DataAtom: n.DataAtom,148Data: n.Data,149Attr: make([]Attribute, len(n.Attr)),150}151copy(m.Attr, n.Attr)152return m153}154155// nodeStack is a stack of nodes.156type nodeStack []*Node157158// pop pops the stack. It will panic if s is empty.159func (s *nodeStack) pop() *Node {160i := len(*s)161n := (*s)[i-1]162*s = (*s)[:i-1]163return n164}165166// top returns the most recently pushed node, or nil if s is empty.167func (s *nodeStack) top() *Node {168if i := len(*s); i > 0 {169return (*s)[i-1]170}171return nil172}173174// index returns the index of the top-most occurrence of n in the stack, or -1175// if n is not present.176func (s *nodeStack) index(n *Node) int {177for i := len(*s) - 1; i >= 0; i-- {178if (*s)[i] == n {179return i180}181}182return -1183}184185// contains returns whether a is within s.186func (s *nodeStack) contains(a atom.Atom) bool {187for _, n := range *s {188if n.DataAtom == a && n.Namespace == "" {189return true190}191}192return false193}194195// insert inserts a node at the given index.196func (s *nodeStack) insert(i int, n *Node) {197(*s) = append(*s, nil)198copy((*s)[i+1:], (*s)[i:])199(*s)[i] = n200}201202// remove removes a node from the stack. It is a no-op if n is not present.203func (s *nodeStack) remove(n *Node) {204i := s.index(n)205if i == -1 {206return207}208copy((*s)[i:], (*s)[i+1:])209j := len(*s) - 1210(*s)[j] = nil211*s = (*s)[:j]212}213214type insertionModeStack []insertionMode215216func (s *insertionModeStack) pop() (im insertionMode) {217i := len(*s)218im = (*s)[i-1]219*s = (*s)[:i-1]220return im221}222223func (s *insertionModeStack) top() insertionMode {224if i := len(*s); i > 0 {225return (*s)[i-1]226}227return nil228}229230231