-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunc.go
179 lines (149 loc) · 3.44 KB
/
func.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package htmlx
import (
"bytes"
"strings"
"github.com/mdigger/wstat"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
// Rename HTML element.
func Rename(n *html.Node, name string) {
if n == nil || n.Type != html.ElementNode || name == "" {
return
}
n.Data = name
n.DataAtom = atom.Lookup([]byte(name))
}
// Remove removes the specified element from the HTML tree.
func Remove(n *html.Node) {
if n == nil || n.Parent == nil {
return
}
n.Parent.RemoveChild(n)
}
// RemoveChilds removes all child elements if they are.
func RemoveChilds(n *html.Node) {
if n == nil {
return
}
for c := n.FirstChild; c != nil; c = n.FirstChild {
n.RemoveChild(c)
}
}
// HTML returns a string with HTML representation.
func HTML(n *html.Node, self bool) (string, error) {
if n == nil {
return "", nil
}
var (
b bytes.Buffer
err error
)
if self {
err = html.Render(&b, n)
} else {
for c := n.FirstChild; c != nil; c = c.NextSibling {
if err = html.Render(&b, c); err != nil {
break
}
}
}
if err != nil {
return "", err
}
return b.String(), nil
}
// SetHTML parses an HTML fragment in the context of the current element and
// replaces them the child elements.
func SetHTML(n *html.Node, data string) (err error) {
if n == nil {
return nil
}
r := strings.NewReader(data)
nodes, err := html.ParseFragment(r, n)
if err != nil {
return err
}
RemoveChilds(n)
for _, node := range nodes {
n.AppendChild(node)
}
return nil
}
// SetText replaces the text of the element to the new one.
func SetText(n *html.Node, text string) error {
return SetHTML(n, html.EscapeString(text))
}
// Text returns only a text representation, without HTML elements.
// Elements from the TextignoreAtom list are ignored with all the daughter
// elements.
func Text(n *html.Node) string {
var buf strings.Builder
_ = WriteText(&buf, n, TextIgnoreAtom)
return buf.String()
}
// Stats returns statistics on the text.
func Stats(n *html.Node) (c wstat.Counter) {
_ = WriteText(&c, n, TextIgnoreAtom)
return
}
// Find finds the first coincidence on the element, including himself, and returns it.
func Find(n *html.Node, m Matcher) *html.Node {
if n == nil || m == nil {
return nil
}
var walker func(node *html.Node) *html.Node
walker = func(node *html.Node) *html.Node {
if node.Type == html.ElementNode && m(node) {
return node
}
for c := node.FirstChild; c != nil; c = c.NextSibling {
if n := walker(c); n != nil {
return n
}
}
return nil
}
return walker(n)
}
// FindAll finds and returns all coincidences with the specified template.
func FindAll(n *html.Node, m Matcher) (result []*html.Node) {
if n == nil || m == nil {
return
}
var walker func(node *html.Node)
walker = func(node *html.Node) {
if node.Type == html.ElementNode && m(node) {
result = append(result, node)
}
for c := node.FirstChild; c != nil; c = c.NextSibling {
walker(c)
}
}
walker(n)
return
}
// FindNext finds the first siblings element.
func FindNext(n *html.Node, m Matcher) *html.Node {
if n == nil || m == nil {
return nil
}
for c := n.NextSibling; c != nil; c = c.NextSibling {
if c.Type == html.ElementNode && m(c) {
return c
}
}
return nil
}
// FindPrev finds the previous siblin element.
func FindPrev(n *html.Node, m Matcher) *html.Node {
if n == nil || m == nil {
return nil
}
for c := n.PrevSibling; c != nil; c = c.PrevSibling {
if c.Type == html.ElementNode && m(c) {
return c
}
}
return nil
}