Skip to content

Commit

Permalink
html: add PrependChild and InsertAfter
Browse files Browse the repository at this point in the history
These methods complement the already existing AppendChild and
InsertBefore methods in allowing for easy and safe manipulation of
Node trees.

For example code like

oldChild.Parent.InsertBefore(newChild, oldChild.NextSibling)

can now be written like

oldChild.Parent.InsertAfter(newChild, oldChild)

and code like

node.InsertBefore(newNode, node.FirstChild)

can now be written like

node.PrependChild(newNode)

Fixes #46960
  • Loading branch information
olavfosse committed Nov 10, 2021
1 parent 04defd4 commit f7e0d51
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion html/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,37 @@ func (n *Node) InsertBefore(newChild, oldChild *Node) {
newChild.NextSibling = next
}

// AppendChild adds a node c as a child of n.
// InsertAfter inserts newChild as a child of n, immediately after oldChild
// in the sequence of n's children. oldChild may be nil, in which case newChild
// is prepended to the beginning of n's children.
//
// It will panic if newChild already has a parent or siblings.
func (n *Node) InsertAfter(newChild, oldChild *Node) {
if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
panic("html: InsertAfter called for an attached child Node")
}
var prev, next *Node
if oldChild != nil {
prev, next = oldChild, oldChild.NextSibling
} else {
next = n.FirstChild
}
if next != nil {
next.PrevSibling = newChild
} else {
n.LastChild = newChild
}
if prev != nil {
prev.NextSibling = newChild
} else {
n.FirstChild = newChild
}
newChild.Parent = n
newChild.PrevSibling = prev
newChild.NextSibling = next
}

// AppendChild adds a node c as the last child of n.
//
// It will panic if c already has a parent or siblings.
func (n *Node) AppendChild(c *Node) {
Expand All @@ -99,6 +129,24 @@ func (n *Node) AppendChild(c *Node) {
c.PrevSibling = last
}

// PrependChild adds a node c as the first child of n.
//
// It will panic if c already has a parent or siblings.
func (n *Node) PrependChild(c *Node) {
if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
panic("html: PrependChild called for an attached child Node")
}
first := n.FirstChild
if first != nil {
first.PrevSibling = c
} else {
n.LastChild = c
}
n.FirstChild = c
c.Parent = n
c.NextSibling = first
}

// RemoveChild removes a node c that is a child of n. Afterwards, c will have
// no parent and no siblings.
//
Expand Down

0 comments on commit f7e0d51

Please sign in to comment.