-
Notifications
You must be signed in to change notification settings - Fork 17
/
nodes.go
68 lines (62 loc) · 1.51 KB
/
nodes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package htmldiff
import (
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
func copyNode(to, from *html.Node) {
to.Attr = from.Attr
to.Data = from.Data
to.DataAtom = from.DataAtom
to.Namespace = from.Namespace
to.Type = from.Type
}
func nodeEqual(base, comp *html.Node) bool {
return base.Data == comp.Data && nodeEqualExText(base, comp)
}
// findBody finds the first body HTML node if it exists in the tree. Required to bypass the page title text.
func findBody(n *html.Node) *html.Node {
if n.Type == html.ElementNode && n.DataAtom == atom.Body {
return n
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
r := findBody(c)
if r != nil {
return r
}
}
return nil
}
// find the first leaf in the tree that is a text node.
func firstLeaf(n *html.Node) (*html.Node, bool) {
if n != nil {
switch n.Type {
case html.TextNode:
return n, true
}
// no valid node found
for c := n.FirstChild; c != nil; c = c.NextSibling {
r, ok := firstLeaf(c)
if ok {
return r, ok
}
}
}
return nil, false
}
// find if this or any parent is a container element where position is important like a list or table.
func inContainer(n *html.Node) bool {
if n == nil {
return false
}
if n.Type == html.ElementNode {
switch n.DataAtom {
case atom.Body:
return false
case atom.Td, atom.Th, atom.Tr, atom.Tbody, atom.Thead, atom.Tfoot,
atom.Table, atom.Caption, atom.Colgroup, atom.Col, // tables
atom.Li, atom.Ul, atom.Ol: // lists
return true
}
}
return inContainer(n.Parent)
}