Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5bfe080

Browse files
committedAug 29, 2024·
Make changes based on feedback
Incorporates https://go-review.googlesource.com/c/net/+/606595
1 parent 5bd809a commit 5bfe080

File tree

4 files changed

+53
-55
lines changed

4 files changed

+53
-55
lines changed
 

‎html/example_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func ExampleParse() {
2222
if err != nil {
2323
log.Fatal(err)
2424
}
25-
for n := range doc.All() {
25+
for n := range doc.Descendants() {
2626
if n.Type == html.ElementNode && n.DataAtom == atom.A {
2727
for _, a := range n.Attr {
2828
if a.Key == "href" {

‎html/iter.go

+30-30
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,55 @@ package html
88

99
import "iter"
1010

11-
// Parents returns an sequence yielding the node and its parents.
11+
// Ancestors returns an iterator over the ancestors of n, starting with n.Parent.
12+
//
13+
// Example:
14+
//
15+
// for ancestor := range n.Ancestors() { ... }
1216
//
1317
// Mutating a Node or its parents while iterating may have unexpected results.
14-
func (n *Node) Parents() iter.Seq[*Node] {
18+
func (n *Node) Ancestors() iter.Seq[*Node] {
19+
_ = n.Parent // eager nil check
20+
1521
return func(yield func(*Node) bool) {
16-
for p := n; p != nil; p = p.Parent {
17-
if !yield(p) {
18-
return
19-
}
22+
for p := n.Parent; p != nil && yield(p); p = p.Parent {
2023
}
2124
}
2225
}
2326

24-
// ChildNodes returns a sequence yielding the immediate children of n.
27+
// Children returns an iterator over the immediate children of n,
28+
// starting with n.FirstChild.
2529
//
26-
// Mutating a Node or its ChildNodes while iterating may have unexpected results.
27-
func (n *Node) ChildNodes() iter.Seq[*Node] {
30+
// Example:
31+
//
32+
// for child := range n.Children() { ... }
33+
func (n *Node) Children() iter.Seq[*Node] {
34+
_ = n.FirstChild // eager nil check
35+
2836
return func(yield func(*Node) bool) {
29-
if n == nil {
30-
return
31-
}
32-
for c := n.FirstChild; c != nil; c = c.NextSibling {
33-
if !yield(c) {
34-
return
35-
}
37+
for c := n.FirstChild; c != nil && yield(c); c = c.NextSibling {
3638
}
3739
}
3840

3941
}
4042

41-
// All returns a sequence yielding all descendents of n in depth-first pre-order.
43+
// Descendants returns an iterator over all nodes recursively beneath
44+
// n, excluding n itself. Nodes are visited in depth-first preorder.
4245
//
43-
// Mutating a Node or its descendents while iterating may have unexpected results.
44-
func (n *Node) All() iter.Seq[*Node] {
46+
// Example:
47+
//
48+
// for desc := range n.Descendants() { ... }
49+
func (n *Node) Descendants() iter.Seq[*Node] {
50+
_ = n.FirstChild // eager nil check
51+
4552
return func(yield func(*Node) bool) {
46-
if n == nil {
47-
return
48-
}
49-
n.all(yield)
53+
_ = n.descendants(yield)
5054
}
5155
}
5256

53-
func (n *Node) all(yield func(*Node) bool) bool {
54-
if !yield(n) {
55-
return false
56-
}
57-
58-
for c := range n.ChildNodes() {
59-
if !c.all(yield) {
57+
func (n *Node) descendants(yield func(*Node) bool) bool {
58+
for c := range n.Children() {
59+
if !yield(c) || !c.descendants(yield) {
6060
return false
6161
}
6262
}

‎html/iter_test.go

+18-24
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ import (
1111
"testing"
1212
)
1313

14-
func TestNode_ChildNodes(t *testing.T) {
14+
func TestNode_Children(t *testing.T) {
1515
tests := []struct {
1616
in string
1717
want string
1818
}{
19-
{"", ""},
2019
{"<a></a>", ""},
2120
{"<a><b></b></a>", "b"},
2221
{"<a>b</a>", "b"},
@@ -30,19 +29,19 @@ func TestNode_ChildNodes(t *testing.T) {
3029
if err != nil {
3130
t.Fatal(err)
3231
}
33-
// Drill to <html><head></head><body> test.in
32+
// Drill to <html><head></head><body><a>
3433
n := doc.FirstChild.FirstChild.NextSibling.FirstChild
3534
var results []string
36-
for c := range n.ChildNodes() {
35+
for c := range n.Children() {
3736
results = append(results, c.Data)
3837
}
3938
if got := strings.Join(results, " "); got != test.want {
40-
t.Errorf("unexpected children yielded by ChildNodes; want: %q got: %q", test.want, got)
39+
t.Errorf("unexpected children yielded by Children; want: %q got: %q", test.want, got)
4140
}
4241
}
4342
}
4443

45-
func TestNode_All(t *testing.T) {
44+
func TestNode_Descendants(t *testing.T) {
4645
tests := []struct {
4746
in string
4847
want string
@@ -61,24 +60,29 @@ func TestNode_All(t *testing.T) {
6160
if err != nil {
6261
t.Fatal(err)
6362
}
64-
// Drill to <html><head></head><body> test.in
65-
n := doc.FirstChild.FirstChild.NextSibling.FirstChild
63+
// Drill to <html><head></head><body>
64+
n := doc.FirstChild.FirstChild.NextSibling
6665
var results []string
67-
for c := range n.All() {
66+
for c := range n.Descendants() {
6867
results = append(results, c.Data)
6968
}
7069
if got := strings.Join(results, " "); got != test.want {
71-
t.Errorf("unexpected children yielded by All; want: %q got: %q",
70+
t.Errorf("unexpected children yielded by Descendants; want: %q got: %q",
7271
test.want, got)
7372
}
7473
}
7574
}
7675

77-
func TestNode_Parents(t *testing.T) {
78-
testParents(t, nil, 0)
79-
for size := range 100 {
76+
func TestNode_Ancestors(t *testing.T) {
77+
for _, size := range []int{0, 1, 2, 10, 100, 10_000} {
8078
n := buildChain(size)
81-
testParents(t, n, size+1)
79+
nParents := 0
80+
for _ = range n.Ancestors() {
81+
nParents++
82+
}
83+
if nParents != size {
84+
t.Errorf("unexpected number of Ancestors; want %d got: %d", size, nParents)
85+
}
8286
}
8387
}
8488

@@ -91,13 +95,3 @@ func buildChain(size int) *Node {
9195
}
9296
return child
9397
}
94-
95-
func testParents(t *testing.T, n *Node, wantSize int) {
96-
nParents := 0
97-
for _ = range n.Parents() {
98-
nParents++
99-
}
100-
if nParents != wantSize {
101-
t.Errorf("unexpected number of Parents; want %d got: %d", wantSize, nParents)
102-
}
103-
}

‎html/node.go

+4
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ var scopeMarker = Node{Type: scopeMarkerNode}
3838
// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
3939
// is the atom for Data, or zero if Data is not a known tag name.
4040
//
41+
// Node trees may be navigated using the link fields (Parent,
42+
// FirstChild, and so on) or a range loop over iterators such as
43+
// [Node.Descendants].
44+
//
4145
// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
4246
// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
4347
// "svg" is short for "http://www.w3.org/2000/svg".

0 commit comments

Comments
 (0)
Please sign in to comment.