all repos

rss-tools @ 58cc1bd492af31e6c9acf65e690474c8c1edf164

get rss feed from sources that(i need and) dont provide one

rss-tools/vendor/github.com/PuerkitoBio/goquery/traversal.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
we're vendoring now, 7 days ago
1
package goquery
2
3
import "golang.org/x/net/html"
4
5
type siblingType int
6
7
// Sibling type, used internally when iterating over children at the same
8
// level (siblings) to specify which nodes are requested.
9
const (
10
	siblingPrevUntil siblingType = iota - 3
11
	siblingPrevAll
12
	siblingPrev
13
	siblingAll
14
	siblingNext
15
	siblingNextAll
16
	siblingNextUntil
17
	siblingAllIncludingNonElements
18
)
19
20
// Find gets the descendants of each element in the current set of matched
21
// elements, filtered by a selector. It returns a new Selection object
22
// containing these matched elements.
23
//
24
// Note that as for all methods accepting a selector string, the selector is
25
// compiled and applied by the cascadia package and inherits its behavior and
26
// constraints regarding supported selectors. See the note on cascadia in
27
// the goquery documentation here:
28
// https://github.com/PuerkitoBio/goquery?tab=readme-ov-file#api
29
func (s *Selection) Find(selector string) *Selection {
30
	return pushStack(s, findWithMatcher(s.Nodes, compileMatcher(selector)))
31
}
32
33
// FindMatcher gets the descendants of each element in the current set of matched
34
// elements, filtered by the matcher. It returns a new Selection object
35
// containing these matched elements.
36
func (s *Selection) FindMatcher(m Matcher) *Selection {
37
	return pushStack(s, findWithMatcher(s.Nodes, m))
38
}
39
40
// FindSelection gets the descendants of each element in the current
41
// Selection, filtered by a Selection. It returns a new Selection object
42
// containing these matched elements.
43
func (s *Selection) FindSelection(sel *Selection) *Selection {
44
	if sel == nil {
45
		return pushStack(s, nil)
46
	}
47
	return s.FindNodes(sel.Nodes...)
48
}
49
50
// FindNodes gets the descendants of each element in the current
51
// Selection, filtered by some nodes. It returns a new Selection object
52
// containing these matched elements.
53
func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
54
	return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
55
		if sliceContains(s.Nodes, n) {
56
			return []*html.Node{n}
57
		}
58
		return nil
59
	}))
60
}
61
62
// Contents gets the children of each element in the Selection,
63
// including text and comment nodes. It returns a new Selection object
64
// containing these elements.
65
func (s *Selection) Contents() *Selection {
66
	return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
67
}
68
69
// ContentsFiltered gets the children of each element in the Selection,
70
// filtered by the specified selector. It returns a new Selection
71
// object containing these elements. Since selectors only act on Element nodes,
72
// this function is an alias to ChildrenFiltered unless the selector is empty,
73
// in which case it is an alias to Contents.
74
func (s *Selection) ContentsFiltered(selector string) *Selection {
75
	if selector != "" {
76
		return s.ChildrenFiltered(selector)
77
	}
78
	return s.Contents()
79
}
80
81
// ContentsMatcher gets the children of each element in the Selection,
82
// filtered by the specified matcher. It returns a new Selection
83
// object containing these elements. Since matchers only act on Element nodes,
84
// this function is an alias to ChildrenMatcher.
85
func (s *Selection) ContentsMatcher(m Matcher) *Selection {
86
	return s.ChildrenMatcher(m)
87
}
88
89
// Children gets the child elements of each element in the Selection.
90
// It returns a new Selection object containing these elements.
91
func (s *Selection) Children() *Selection {
92
	return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
93
}
94
95
// ChildrenFiltered gets the child elements of each element in the Selection,
96
// filtered by the specified selector. It returns a new
97
// Selection object containing these elements.
98
func (s *Selection) ChildrenFiltered(selector string) *Selection {
99
	return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), compileMatcher(selector))
100
}
101
102
// ChildrenMatcher gets the child elements of each element in the Selection,
103
// filtered by the specified matcher. It returns a new
104
// Selection object containing these elements.
105
func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
106
	return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
107
}
108
109
// Parent gets the parent of each element in the Selection. It returns a
110
// new Selection object containing the matched elements.
111
func (s *Selection) Parent() *Selection {
112
	return pushStack(s, getParentNodes(s.Nodes))
113
}
114
115
// ParentFiltered gets the parent of each element in the Selection filtered by a
116
// selector. It returns a new Selection object containing the matched elements.
117
func (s *Selection) ParentFiltered(selector string) *Selection {
118
	return filterAndPush(s, getParentNodes(s.Nodes), compileMatcher(selector))
119
}
120
121
// ParentMatcher gets the parent of each element in the Selection filtered by a
122
// matcher. It returns a new Selection object containing the matched elements.
123
func (s *Selection) ParentMatcher(m Matcher) *Selection {
124
	return filterAndPush(s, getParentNodes(s.Nodes), m)
125
}
126
127
// Closest gets the first element that matches the selector by testing the
128
// element itself and traversing up through its ancestors in the DOM tree.
129
func (s *Selection) Closest(selector string) *Selection {
130
	cs := compileMatcher(selector)
131
	return s.ClosestMatcher(cs)
132
}
133
134
// ClosestMatcher gets the first element that matches the matcher by testing the
135
// element itself and traversing up through its ancestors in the DOM tree.
136
func (s *Selection) ClosestMatcher(m Matcher) *Selection {
137
	return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
138
		// For each node in the selection, test the node itself, then each parent
139
		// until a match is found.
140
		for ; n != nil; n = n.Parent {
141
			if m.Match(n) {
142
				return []*html.Node{n}
143
			}
144
		}
145
		return nil
146
	}))
147
}
148
149
// ClosestNodes gets the first element that matches one of the nodes by testing the
150
// element itself and traversing up through its ancestors in the DOM tree.
151
func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
152
	set := make(map[*html.Node]bool)
153
	for _, n := range nodes {
154
		set[n] = true
155
	}
156
	return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
157
		// For each node in the selection, test the node itself, then each parent
158
		// until a match is found.
159
		for ; n != nil; n = n.Parent {
160
			if set[n] {
161
				return []*html.Node{n}
162
			}
163
		}
164
		return nil
165
	}))
166
}
167
168
// ClosestSelection gets the first element that matches one of the nodes in the
169
// Selection by testing the element itself and traversing up through its ancestors
170
// in the DOM tree.
171
func (s *Selection) ClosestSelection(sel *Selection) *Selection {
172
	if sel == nil {
173
		return pushStack(s, nil)
174
	}
175
	return s.ClosestNodes(sel.Nodes...)
176
}
177
178
// Parents gets the ancestors of each element in the current Selection. It
179
// returns a new Selection object with the matched elements.
180
func (s *Selection) Parents() *Selection {
181
	return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
182
}
183
184
// ParentsFiltered gets the ancestors of each element in the current
185
// Selection. It returns a new Selection object with the matched elements.
186
func (s *Selection) ParentsFiltered(selector string) *Selection {
187
	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), compileMatcher(selector))
188
}
189
190
// ParentsMatcher gets the ancestors of each element in the current
191
// Selection. It returns a new Selection object with the matched elements.
192
func (s *Selection) ParentsMatcher(m Matcher) *Selection {
193
	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
194
}
195
196
// ParentsUntil gets the ancestors of each element in the Selection, up to but
197
// not including the element matched by the selector. It returns a new Selection
198
// object containing the matched elements.
199
func (s *Selection) ParentsUntil(selector string) *Selection {
200
	return pushStack(s, getParentsNodes(s.Nodes, compileMatcher(selector), nil))
201
}
202
203
// ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
204
// not including the element matched by the matcher. It returns a new Selection
205
// object containing the matched elements.
206
func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
207
	return pushStack(s, getParentsNodes(s.Nodes, m, nil))
208
}
209
210
// ParentsUntilSelection gets the ancestors of each element in the Selection,
211
// up to but not including the elements in the specified Selection. It returns a
212
// new Selection object containing the matched elements.
213
func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
214
	if sel == nil {
215
		return s.Parents()
216
	}
217
	return s.ParentsUntilNodes(sel.Nodes...)
218
}
219
220
// ParentsUntilNodes gets the ancestors of each element in the Selection,
221
// up to but not including the specified nodes. It returns a
222
// new Selection object containing the matched elements.
223
func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
224
	return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
225
}
226
227
// ParentsFilteredUntil is like ParentsUntil, with the option to filter the
228
// results based on a selector string. It returns a new Selection
229
// object containing the matched elements.
230
func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
231
	return filterAndPush(s, getParentsNodes(s.Nodes, compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
232
}
233
234
// ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
235
// results based on a matcher. It returns a new Selection object containing the matched elements.
236
func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
237
	return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
238
}
239
240
// ParentsFilteredUntilSelection is like ParentsUntilSelection, with the
241
// option to filter the results based on a selector string. It returns a new
242
// Selection object containing the matched elements.
243
func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
244
	return s.ParentsMatcherUntilSelection(compileMatcher(filterSelector), sel)
245
}
246
247
// ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
248
// option to filter the results based on a matcher. It returns a new
249
// Selection object containing the matched elements.
250
func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
251
	if sel == nil {
252
		return s.ParentsMatcher(filter)
253
	}
254
	return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
255
}
256
257
// ParentsFilteredUntilNodes is like ParentsUntilNodes, with the
258
// option to filter the results based on a selector string. It returns a new
259
// Selection object containing the matched elements.
260
func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
261
	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), compileMatcher(filterSelector))
262
}
263
264
// ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
265
// option to filter the results based on a matcher. It returns a new
266
// Selection object containing the matched elements.
267
func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
268
	return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
269
}
270
271
// Siblings gets the siblings of each element in the Selection. It returns
272
// a new Selection object containing the matched elements.
273
func (s *Selection) Siblings() *Selection {
274
	return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
275
}
276
277
// SiblingsFiltered gets the siblings of each element in the Selection
278
// filtered by a selector. It returns a new Selection object containing the
279
// matched elements.
280
func (s *Selection) SiblingsFiltered(selector string) *Selection {
281
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), compileMatcher(selector))
282
}
283
284
// SiblingsMatcher gets the siblings of each element in the Selection
285
// filtered by a matcher. It returns a new Selection object containing the
286
// matched elements.
287
func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
288
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
289
}
290
291
// Next gets the immediately following sibling of each element in the
292
// Selection. It returns a new Selection object containing the matched elements.
293
func (s *Selection) Next() *Selection {
294
	return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
295
}
296
297
// NextFiltered gets the immediately following sibling of each element in the
298
// Selection filtered by a selector. It returns a new Selection object
299
// containing the matched elements.
300
func (s *Selection) NextFiltered(selector string) *Selection {
301
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), compileMatcher(selector))
302
}
303
304
// NextMatcher gets the immediately following sibling of each element in the
305
// Selection filtered by a matcher. It returns a new Selection object
306
// containing the matched elements.
307
func (s *Selection) NextMatcher(m Matcher) *Selection {
308
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
309
}
310
311
// NextAll gets all the following siblings of each element in the
312
// Selection. It returns a new Selection object containing the matched elements.
313
func (s *Selection) NextAll() *Selection {
314
	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
315
}
316
317
// NextAllFiltered gets all the following siblings of each element in the
318
// Selection filtered by a selector. It returns a new Selection object
319
// containing the matched elements.
320
func (s *Selection) NextAllFiltered(selector string) *Selection {
321
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), compileMatcher(selector))
322
}
323
324
// NextAllMatcher gets all the following siblings of each element in the
325
// Selection filtered by a matcher. It returns a new Selection object
326
// containing the matched elements.
327
func (s *Selection) NextAllMatcher(m Matcher) *Selection {
328
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
329
}
330
331
// Prev gets the immediately preceding sibling of each element in the
332
// Selection. It returns a new Selection object containing the matched elements.
333
func (s *Selection) Prev() *Selection {
334
	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
335
}
336
337
// PrevFiltered gets the immediately preceding sibling of each element in the
338
// Selection filtered by a selector. It returns a new Selection object
339
// containing the matched elements.
340
func (s *Selection) PrevFiltered(selector string) *Selection {
341
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), compileMatcher(selector))
342
}
343
344
// PrevMatcher gets the immediately preceding sibling of each element in the
345
// Selection filtered by a matcher. It returns a new Selection object
346
// containing the matched elements.
347
func (s *Selection) PrevMatcher(m Matcher) *Selection {
348
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
349
}
350
351
// PrevAll gets all the preceding siblings of each element in the
352
// Selection. It returns a new Selection object containing the matched elements.
353
func (s *Selection) PrevAll() *Selection {
354
	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
355
}
356
357
// PrevAllFiltered gets all the preceding siblings of each element in the
358
// Selection filtered by a selector. It returns a new Selection object
359
// containing the matched elements.
360
func (s *Selection) PrevAllFiltered(selector string) *Selection {
361
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), compileMatcher(selector))
362
}
363
364
// PrevAllMatcher gets all the preceding siblings of each element in the
365
// Selection filtered by a matcher. It returns a new Selection object
366
// containing the matched elements.
367
func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
368
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
369
}
370
371
// NextUntil gets all following siblings of each element up to but not
372
// including the element matched by the selector. It returns a new Selection
373
// object containing the matched elements.
374
func (s *Selection) NextUntil(selector string) *Selection {
375
	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
376
		compileMatcher(selector), nil))
377
}
378
379
// NextUntilMatcher gets all following siblings of each element up to but not
380
// including the element matched by the matcher. It returns a new Selection
381
// object containing the matched elements.
382
func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
383
	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
384
		m, nil))
385
}
386
387
// NextUntilSelection gets all following siblings of each element up to but not
388
// including the element matched by the Selection. It returns a new Selection
389
// object containing the matched elements.
390
func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
391
	if sel == nil {
392
		return s.NextAll()
393
	}
394
	return s.NextUntilNodes(sel.Nodes...)
395
}
396
397
// NextUntilNodes gets all following siblings of each element up to but not
398
// including the element matched by the nodes. It returns a new Selection
399
// object containing the matched elements.
400
func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
401
	return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
402
		nil, nodes))
403
}
404
405
// PrevUntil gets all preceding siblings of each element up to but not
406
// including the element matched by the selector. It returns a new Selection
407
// object containing the matched elements.
408
func (s *Selection) PrevUntil(selector string) *Selection {
409
	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
410
		compileMatcher(selector), nil))
411
}
412
413
// PrevUntilMatcher gets all preceding siblings of each element up to but not
414
// including the element matched by the matcher. It returns a new Selection
415
// object containing the matched elements.
416
func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
417
	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
418
		m, nil))
419
}
420
421
// PrevUntilSelection gets all preceding siblings of each element up to but not
422
// including the element matched by the Selection. It returns a new Selection
423
// object containing the matched elements.
424
func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
425
	if sel == nil {
426
		return s.PrevAll()
427
	}
428
	return s.PrevUntilNodes(sel.Nodes...)
429
}
430
431
// PrevUntilNodes gets all preceding siblings of each element up to but not
432
// including the element matched by the nodes. It returns a new Selection
433
// object containing the matched elements.
434
func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
435
	return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
436
		nil, nodes))
437
}
438
439
// NextFilteredUntil is like NextUntil, with the option to filter
440
// the results based on a selector string.
441
// It returns a new Selection object containing the matched elements.
442
func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
443
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
444
		compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
445
}
446
447
// NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
448
// the results based on a matcher.
449
// It returns a new Selection object containing the matched elements.
450
func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
451
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
452
		until, nil), filter)
453
}
454
455
// NextFilteredUntilSelection is like NextUntilSelection, with the
456
// option to filter the results based on a selector string. It returns a new
457
// Selection object containing the matched elements.
458
func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
459
	return s.NextMatcherUntilSelection(compileMatcher(filterSelector), sel)
460
}
461
462
// NextMatcherUntilSelection is like NextUntilSelection, with the
463
// option to filter the results based on a matcher. It returns a new
464
// Selection object containing the matched elements.
465
func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
466
	if sel == nil {
467
		return s.NextMatcher(filter)
468
	}
469
	return s.NextMatcherUntilNodes(filter, sel.Nodes...)
470
}
471
472
// NextFilteredUntilNodes is like NextUntilNodes, with the
473
// option to filter the results based on a selector string. It returns a new
474
// Selection object containing the matched elements.
475
func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
476
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
477
		nil, nodes), compileMatcher(filterSelector))
478
}
479
480
// NextMatcherUntilNodes is like NextUntilNodes, with the
481
// option to filter the results based on a matcher. It returns a new
482
// Selection object containing the matched elements.
483
func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
484
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
485
		nil, nodes), filter)
486
}
487
488
// PrevFilteredUntil is like PrevUntil, with the option to filter
489
// the results based on a selector string.
490
// It returns a new Selection object containing the matched elements.
491
func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
492
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
493
		compileMatcher(untilSelector), nil), compileMatcher(filterSelector))
494
}
495
496
// PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
497
// the results based on a matcher.
498
// It returns a new Selection object containing the matched elements.
499
func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
500
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
501
		until, nil), filter)
502
}
503
504
// PrevFilteredUntilSelection is like PrevUntilSelection, with the
505
// option to filter the results based on a selector string. It returns a new
506
// Selection object containing the matched elements.
507
func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
508
	return s.PrevMatcherUntilSelection(compileMatcher(filterSelector), sel)
509
}
510
511
// PrevMatcherUntilSelection is like PrevUntilSelection, with the
512
// option to filter the results based on a matcher. It returns a new
513
// Selection object containing the matched elements.
514
func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
515
	if sel == nil {
516
		return s.PrevMatcher(filter)
517
	}
518
	return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
519
}
520
521
// PrevFilteredUntilNodes is like PrevUntilNodes, with the
522
// option to filter the results based on a selector string. It returns a new
523
// Selection object containing the matched elements.
524
func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
525
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
526
		nil, nodes), compileMatcher(filterSelector))
527
}
528
529
// PrevMatcherUntilNodes is like PrevUntilNodes, with the
530
// option to filter the results based on a matcher. It returns a new
531
// Selection object containing the matched elements.
532
func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
533
	return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
534
		nil, nodes), filter)
535
}
536
537
// Filter and push filters the nodes based on a matcher, and pushes the results
538
// on the stack, with the srcSel as previous selection.
539
func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
540
	// Create a temporary Selection with the specified nodes to filter using winnow
541
	sel := &Selection{nodes, srcSel.document, nil}
542
	// Filter based on matcher and push on stack
543
	return pushStack(srcSel, winnow(sel, m, true))
544
}
545
546
// Internal implementation of Find that return raw nodes.
547
func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
548
	// Map nodes to find the matches within the children of each node
549
	return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
550
		// Go down one level, becausejQuery's Find selects only within descendants
551
		for c := n.FirstChild; c != nil; c = c.NextSibling {
552
			if c.Type == html.ElementNode {
553
				result = append(result, m.MatchAll(c)...)
554
			}
555
		}
556
		return
557
	})
558
}
559
560
// Internal implementation to get all parent nodes, stopping at the specified
561
// node (or nil if no stop).
562
func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
563
	return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
564
		for p := n.Parent; p != nil; p = p.Parent {
565
			sel := newSingleSelection(p, nil)
566
			if stopm != nil {
567
				if sel.IsMatcher(stopm) {
568
					break
569
				}
570
			} else if len(stopNodes) > 0 {
571
				if sel.IsNodes(stopNodes...) {
572
					break
573
				}
574
			}
575
			if p.Type == html.ElementNode {
576
				result = append(result, p)
577
			}
578
		}
579
		return
580
	})
581
}
582
583
// Internal implementation of sibling nodes that return a raw slice of matches.
584
func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
585
	var f func(*html.Node) bool
586
587
	// If the requested siblings are ...Until, create the test function to
588
	// determine if the until condition is reached (returns true if it is)
589
	if st == siblingNextUntil || st == siblingPrevUntil {
590
		f = func(n *html.Node) bool {
591
			if untilm != nil {
592
				// Matcher-based condition
593
				sel := newSingleSelection(n, nil)
594
				return sel.IsMatcher(untilm)
595
			} else if len(untilNodes) > 0 {
596
				// Nodes-based condition
597
				sel := newSingleSelection(n, nil)
598
				return sel.IsNodes(untilNodes...)
599
			}
600
			return false
601
		}
602
	}
603
604
	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
605
		return getChildrenWithSiblingType(n.Parent, st, n, f)
606
	})
607
}
608
609
// Gets the children nodes of each node in the specified slice of nodes,
610
// based on the sibling type request.
611
func getChildrenNodes(nodes []*html.Node, st siblingType) []*html.Node {
612
	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
613
		return getChildrenWithSiblingType(n, st, nil, nil)
614
	})
615
}
616
617
// Gets the children of the specified parent, based on the requested sibling
618
// type, skipping a specified node if required.
619
func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *html.Node,
620
	untilFunc func(*html.Node) bool) (result []*html.Node) {
621
622
	// Create the iterator function
623
	var iter = func(cur *html.Node) (ret *html.Node) {
624
		// Based on the sibling type requested, iterate the right way
625
		for {
626
			switch st {
627
			case siblingAll, siblingAllIncludingNonElements:
628
				if cur == nil {
629
					// First iteration, start with first child of parent
630
					// Skip node if required
631
					if ret = parent.FirstChild; ret == skipNode && skipNode != nil {
632
						ret = skipNode.NextSibling
633
					}
634
				} else {
635
					// Skip node if required
636
					if ret = cur.NextSibling; ret == skipNode && skipNode != nil {
637
						ret = skipNode.NextSibling
638
					}
639
				}
640
			case siblingPrev, siblingPrevAll, siblingPrevUntil:
641
				if cur == nil {
642
					// Start with previous sibling of the skip node
643
					ret = skipNode.PrevSibling
644
				} else {
645
					ret = cur.PrevSibling
646
				}
647
			case siblingNext, siblingNextAll, siblingNextUntil:
648
				if cur == nil {
649
					// Start with next sibling of the skip node
650
					ret = skipNode.NextSibling
651
				} else {
652
					ret = cur.NextSibling
653
				}
654
			default:
655
				panic("Invalid sibling type.")
656
			}
657
			if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
658
				return
659
			}
660
			// Not a valid node, try again from this one
661
			cur = ret
662
		}
663
	}
664
665
	for c := iter(nil); c != nil; c = iter(c) {
666
		// If this is an ...Until case, test before append (returns true
667
		// if the until condition is reached)
668
		if st == siblingNextUntil || st == siblingPrevUntil {
669
			if untilFunc(c) {
670
				return
671
			}
672
		}
673
		result = append(result, c)
674
		if st == siblingNext || st == siblingPrev {
675
			// Only one node was requested (immediate next or previous), so exit
676
			return
677
		}
678
	}
679
	return
680
}
681
682
// Internal implementation of parent nodes that return a raw slice of Nodes.
683
func getParentNodes(nodes []*html.Node) []*html.Node {
684
	return mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
685
		if n.Parent != nil && n.Parent.Type == html.ElementNode {
686
			return []*html.Node{n.Parent}
687
		}
688
		return nil
689
	})
690
}
691
692
// Internal map function used by many traversing methods. Takes the source nodes
693
// to iterate on and the mapping function that returns an array of nodes.
694
// Returns an array of nodes mapped by calling the callback function once for
695
// each node in the source nodes.
696
func mapNodes(nodes []*html.Node, f func(int, *html.Node) []*html.Node) (result []*html.Node) {
697
	set := make(map[*html.Node]bool)
698
	for i, n := range nodes {
699
		if vals := f(i, n); len(vals) > 0 {
700
			result = appendWithoutDuplicates(result, vals, set)
701
		}
702
	}
703
	return result
704
}