mirror of
https://github.com/PuerkitoBio/goquery.git
synced 2024-04-21 12:31:36 +00:00
Compare commits
56
Commits
v0.3.2
...
manipulation
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
522e116ada | ||
|
|
b89597bb36 | ||
|
|
fb2312a925 | ||
|
|
ef025592df | ||
|
|
c0464bb4c9 | ||
|
|
ac1e87b973 | ||
|
|
958027e55f | ||
|
|
1ff3f2a033 | ||
|
|
3aedb35ed4 | ||
|
|
409e94058f | ||
|
|
54d43ec4b0 | ||
|
|
875b65f385 | ||
|
|
251095afb5 | ||
|
|
cc9b6f8c6f | ||
|
|
98316c249d | ||
|
|
9324e7076d | ||
|
|
040cf98281 | ||
|
|
e7ef1f75eb | ||
|
|
9b29a63ff5 | ||
|
|
25807d1884 | ||
|
|
2abc410148 | ||
|
|
2bd0871a77 | ||
|
|
b7dabffd85 | ||
|
|
b800859dea | ||
|
|
9848519841 | ||
|
|
0e970f1f85 | ||
|
|
12a8512778 | ||
|
|
10e92b83fb | ||
|
|
875035bc14 | ||
|
|
1e5417b3db | ||
|
|
330b1c8132 | ||
|
|
41a4211e59 | ||
|
|
087eeef3f2 | ||
|
|
d9e4d610c0 | ||
|
|
a3fdc62e31 | ||
|
|
cf82003f7e | ||
|
|
308a3c0fda | ||
|
|
e7f5b65573 | ||
|
|
d571e76106 | ||
|
|
21918f0808 | ||
|
|
8e708aac7d | ||
|
|
6bab89f9f6 | ||
|
|
6938944908 | ||
|
|
28cf4a77e1 | ||
|
|
2c6687f6d3 | ||
|
|
bc0c11b086 | ||
|
|
c44713447d | ||
|
|
48358040e1 | ||
|
|
5329018c6a | ||
|
|
8c07896774 | ||
|
|
a6cc89ff58 | ||
|
|
076667ebf2 | ||
|
|
48de68c2b7 | ||
|
|
e273eed13e | ||
|
|
d247f5b79a | ||
|
|
aa0519aedd |
@@ -3,3 +3,5 @@
|
|||||||
*.swp
|
*.swp
|
||||||
#*.*#
|
#*.*#
|
||||||
tags
|
tags
|
||||||
|
goquery.test
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.1
|
||||||
|
- 1.2
|
||||||
|
- 1.3
|
||||||
|
- tip
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2012-2013, Martin Angers & Contributors
|
Copyright (c) 2012-2014, Martin Angers & Contributors
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
# goquery - a little like that j-thing, only in Go
|
# goquery - a little like that j-thing, only in Go
|
||||||
|
|
||||||
GoQuery brings a syntax and a set of features similar to [jQuery][] to the [Go language][go]. It is based on the experimental html package and the CSS Selector library [cascadia][]. Since the experimental html parser returns tokens (nodes), and not a full-featured DOM object, jQuery's manipulation and modification functions have been left off (no point in modifying data in the parsed tree of the HTML, it has no effect).
|
[](http://travis-ci.org/PuerkitoBio/goquery)
|
||||||
|
|
||||||
Supported functions are query-oriented features (`hasClass()`, `attr()` and the likes), as well as traversing functions that make sense given what we have to work with. This makes GoQuery a great library for scraping web pages.
|
[](http://godoc.org/github.com/PuerkitoBio/goquery)
|
||||||
|
|
||||||
|
goquery brings a syntax and a set of features similar to [jQuery][] to the [Go language][go]. It is based on Go's [net/html package][html] and the CSS Selector library [cascadia][]. Since the net/html parser returns nodes, and not a full-featured DOM tree, jQuery's stateful manipulation functions (like height(), css(), detach()) have been left off.
|
||||||
|
|
||||||
|
Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML. See the [wiki][] for various options to do this.
|
||||||
|
|
||||||
Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's `fmt` package), even though some of its methods are less than intuitive (looking at you, [index()][index]...).
|
Syntax-wise, it is as close as possible to jQuery, with the same function names when possible, and that warm and fuzzy chainable interface. jQuery being the ultra-popular library that it is, I felt that writing a similar HTML-manipulating library was better to follow its API than to start anew (in the same spirit as Go's `fmt` package), even though some of its methods are less than intuitive (looking at you, [index()][index]...).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
Please note that because of the net/html dependency, goquery requires Go1.1+.
|
||||||
|
|
||||||
$ go get github.com/PuerkitoBio/goquery
|
$ go get github.com/PuerkitoBio/goquery
|
||||||
|
|
||||||
(optional) To run unit tests:
|
(optional) To run unit tests:
|
||||||
@@ -15,13 +21,17 @@ Syntax-wise, it is as close as possible to jQuery, with the same function names
|
|||||||
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
||||||
$ go test
|
$ go test
|
||||||
|
|
||||||
(optional) To run benchmarks:
|
(optional) To run benchmarks (warning: it runs for a few minutes):
|
||||||
|
|
||||||
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
|
||||||
$ go test -bench=".*"
|
$ go test -bench=".*"
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
**Note that goquery's API is now stable, and will not break.**
|
||||||
|
|
||||||
|
* **2014-11-07** : Add manipulation functions (thanks to [Andrew Stone][thatguystone]) and `*Matcher` functions, that receive compiled cascadia selectors instead of selector strings, thus avoiding potential panics thrown by goquery via `cascadia.MustCompile` calls. This results in better performance (selectors can be compiled once and reused) and more idiomatic error handling (you can handle cascadia's compilation errors, instead of recovering from panics, which had been bugging me for a long time). Note that the actual type expected is a `Matcher` interface, that `cascadia.Selector` implements. Other matcher implementations could be used.
|
||||||
|
* **2014-11-06** : Change import paths of net/html to golang.org/x/net/html (see https://groups.google.com/forum/#!topic/golang-nuts/eD8dh3T9yyA). Make sure to update your code to use the new import path too when you call goquery with `html.Node`s.
|
||||||
* **v0.3.2** : Add `NewDocumentFromReader()` (thanks jweir) which allows creating a goquery document from an io.Reader.
|
* **v0.3.2** : Add `NewDocumentFromReader()` (thanks jweir) which allows creating a goquery document from an io.Reader.
|
||||||
* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response.
|
* **v0.3.1** : Add `NewDocumentFromResponse()` (thanks assassingj) which allows creating a goquery document from an http response.
|
||||||
* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility.
|
* **v0.3.0** : Add `EachWithBreak()` which allows to break out of an `Each()` loop by returning false. This function was added instead of changing the existing `Each()` to avoid breaking compatibility.
|
||||||
@@ -32,65 +42,52 @@ Syntax-wise, it is as close as possible to jQuery, with the same function names
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
GoQuery exposes two classes, `Document` and `Selection`. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, GoQuery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` class is for. It holds the root document node as the initial Selection object to manipulate.
|
goquery exposes two structs, `Document` and `Selection`, and the `Matcher` interface. Unlike jQuery, which is loaded as part of a DOM document, and thus acts on its containing document, goquery doesn't know which HTML document to act upon. So it needs to be told, and that's what the `Document` type is for. It holds the root document node as the initial Selection value to manipulate.
|
||||||
|
|
||||||
jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in GoQuery as a single method with variadic empty interface arguments, I use statically-typed signatures following this naming convention:
|
jQuery often has many variants for the same function (no argument, a selector string argument, a jQuery object argument, a DOM element argument, ...). Instead of exposing the same features in goquery as a single method with variadic empty interface arguments, statically-typed signatures are used following this naming convention:
|
||||||
|
|
||||||
* When the jQuery equivalent can be called with no argument, it has the same name as jQuery for the no argument signature (e.g.: `Prev()`), and the version with a selector string argument is called `XxxFiltered()` (e.g.: `PrevFiltered()`)
|
* When the jQuery equivalent can be called with no argument, it has the same name as jQuery for the no argument signature (e.g.: `Prev()`), and the version with a selector string argument is called `XxxFiltered()` (e.g.: `PrevFiltered()`)
|
||||||
* When the jQuery equivalent **requires** one argument, the same name as jQuery is used for the selector string version (e.g.: `Is()`)
|
* When the jQuery equivalent **requires** one argument, the same name as jQuery is used for the selector string version (e.g.: `Is()`)
|
||||||
* The signatures accepting a jQuery object as argument are defined in GoQuery as `XxxSelection()` and take a `*Selection` object as argument (e.g.: `FilterSelection()`)
|
* The signatures accepting a jQuery object as argument are defined in goquery as `XxxSelection()` and take a `*Selection` object as argument (e.g.: `FilterSelection()`)
|
||||||
* The signatures accepting a DOM element as argument in jQuery are defined in GoQuery as `XxxNodes()` and take a variadic argument of type `*html.Node` (e.g.: `FilterNodes()`)
|
* The signatures accepting a DOM element as argument in jQuery are defined in goquery as `XxxNodes()` and take a variadic argument of type `*html.Node` (e.g.: `FilterNodes()`)
|
||||||
* Finally, the signatures accepting a function as argument in jQuery are defined in GoQuery as `XxxFunction()` and take a function as argument (e.g.: `FilterFunction()`)
|
* The signatures accepting a function as argument in jQuery are defined in goquery as `XxxFunction()` and take a function as argument (e.g.: `FilterFunction()`)
|
||||||
|
* The goquery methods that can be called with a selector string have a corresponding version that take a `Matcher` interface and are defined as `XxxMatcher()` (e.g.: `IsMatcher()`)
|
||||||
|
|
||||||
GoQuery's complete [godoc reference documentation can be found here][doc].
|
The complete [godoc reference documentation can be found here][doc].
|
||||||
|
|
||||||
Please note that Cascadia's selectors do NOT necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details.
|
Please note that Cascadia's selectors do not necessarily match all supported selectors of jQuery (Sizzle). See the [cascadia project][cascadia] for details.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
Taken from example_test.go:
|
See some tips and tricks in the [wiki][].
|
||||||
|
|
||||||
|
Taken (and adapted as if executed from outside the goquery package) from example_test.go:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
// In real use, this import would be required (not in this example, since it
|
"log"
|
||||||
// is part of the goquery package)
|
|
||||||
//"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This example scrapes the 10 reviews shown on the home page of MetalReview.com,
|
func ExampleScrape() {
|
||||||
// the best metal review site on the web :) (and no, I'm not affiliated to them!)
|
doc, err := goquery.NewDocument("http://metalsucks.net")
|
||||||
func ExampleScrape_MetalReview() {
|
if err != nil {
|
||||||
// Load the HTML document (in real use, the type would be *goquery.Document)
|
log.Fatal(err)
|
||||||
var doc *Document
|
|
||||||
var e error
|
|
||||||
|
|
||||||
if doc, e = NewDocument("http://metalreview.com"); e != nil {
|
|
||||||
panic(e.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the review items (the type of the Selection would be *goquery.Selection)
|
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *goquery.Selection) {
|
||||||
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
band := s.Find("h3").Text()
|
||||||
var band, title string
|
title := s.Find("i").Text()
|
||||||
var score float64
|
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
||||||
|
|
||||||
// For each item found, get the band, title and score, and print it
|
|
||||||
band = s.Find("strong").Text()
|
|
||||||
title = s.Find("em").Text()
|
|
||||||
if score, e = strconv.ParseFloat(s.Find(".score").Text(), 64); e != nil {
|
|
||||||
// Not a valid float, ignore score
|
|
||||||
fmt.Printf("Review %d: %s - %s.\n", i, band, title)
|
|
||||||
} else {
|
|
||||||
// Print all, including score
|
|
||||||
fmt.Printf("Review %d: %s - %s (%2.1f).\n", i, band, title, score)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
// To see the output of the Example while running the test suite (go test), simply
|
}
|
||||||
// remove the leading "x" before Output on the next line. This will cause the
|
|
||||||
// example to fail (all the "real" tests should pass).
|
|
||||||
|
|
||||||
// xOutput: voluntarily fail the Example output.
|
func main() {
|
||||||
|
ExampleScrape()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -107,3 +104,6 @@ The [BSD 3-Clause license][bsd], the same as the [Go language][golic]. Cascadia'
|
|||||||
[doc]: http://godoc.org/github.com/PuerkitoBio/goquery
|
[doc]: http://godoc.org/github.com/PuerkitoBio/goquery
|
||||||
[index]: http://api.jquery.com/index/
|
[index]: http://api.jquery.com/index/
|
||||||
[gonet]: http://code.google.com/p/go/source/detail?r=f7f5159120f51ba0070774d3c5907969b5fe7858&repo=net
|
[gonet]: http://code.google.com/p/go/source/detail?r=f7f5159120f51ba0070774d3c5907969b5fe7858&repo=net
|
||||||
|
[html]: http://godoc.org/code.google.com/p/go.net/html
|
||||||
|
[wiki]: https://github.com/PuerkitoBio/goquery/wiki/Tips-and-tricks
|
||||||
|
[thatguystone]: https://github.com/thatguystone
|
||||||
|
|||||||
@@ -1,85 +1,103 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// First() reduces the set of matched elements to the first in the set.
|
// First reduces the set of matched elements to the first in the set.
|
||||||
// It returns a new Selection object.
|
// It returns a new Selection object, and an empty Selection object if the
|
||||||
func (this *Selection) First() *Selection {
|
// the selection is empty.
|
||||||
return this.Eq(0)
|
func (s *Selection) First() *Selection {
|
||||||
|
return s.Eq(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last() reduces the set of matched elements to the last in the set.
|
// Last reduces the set of matched elements to the last in the set.
|
||||||
// It returns a new Selection object.
|
// It returns a new Selection object, and an empty Selection object if
|
||||||
func (this *Selection) Last() *Selection {
|
// the selection is empty.
|
||||||
return this.Eq(-1)
|
func (s *Selection) Last() *Selection {
|
||||||
|
return s.Eq(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eq() reduces the set of matched elements to the one at the specified index.
|
// Eq reduces the set of matched elements to the one at the specified index.
|
||||||
// If a negative index is given, it counts backwards starting at the end of the
|
// If a negative index is given, it counts backwards starting at the end of the
|
||||||
// set. It returns a new Selection object, and an empty Selection object if the
|
// set. It returns a new Selection object, and an empty Selection object if the
|
||||||
// index is invalid.
|
// index is invalid.
|
||||||
func (this *Selection) Eq(index int) *Selection {
|
func (s *Selection) Eq(index int) *Selection {
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
index += len(this.Nodes)
|
index += len(s.Nodes)
|
||||||
}
|
}
|
||||||
return this.Slice(index, index+1)
|
|
||||||
|
if index >= len(s.Nodes) || index < 0 {
|
||||||
|
return newEmptySelection(s.document)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.Slice(index, index+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice() reduces the set of matched elements to a subset specified by a range
|
// Slice reduces the set of matched elements to a subset specified by a range
|
||||||
// of indices.
|
// of indices.
|
||||||
func (this *Selection) Slice(start int, end int) *Selection {
|
func (s *Selection) Slice(start, end int) *Selection {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
start += len(this.Nodes)
|
start += len(s.Nodes)
|
||||||
}
|
}
|
||||||
if end < 0 {
|
if end < 0 {
|
||||||
end += len(this.Nodes)
|
end += len(s.Nodes)
|
||||||
}
|
}
|
||||||
return pushStack(this, this.Nodes[start:end])
|
return pushStack(s, s.Nodes[start:end])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get() retrieves the underlying node at the specified index.
|
// Get retrieves the underlying node at the specified index.
|
||||||
// Get() without parameter is not implemented, since the node array is available
|
// Get without parameter is not implemented, since the node array is available
|
||||||
// on the Selection object.
|
// on the Selection object.
|
||||||
func (this *Selection) Get(index int) *html.Node {
|
func (s *Selection) Get(index int) *html.Node {
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
index += len(this.Nodes) // Negative index gets from the end
|
index += len(s.Nodes) // Negative index gets from the end
|
||||||
}
|
}
|
||||||
return this.Nodes[index]
|
return s.Nodes[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index() returns the position of the first element within the Selection object
|
// Index returns the position of the first element within the Selection object
|
||||||
// relative to its sibling elements.
|
// relative to its sibling elements.
|
||||||
func (this *Selection) Index() int {
|
func (s *Selection) Index() int {
|
||||||
if len(this.Nodes) > 0 {
|
if len(s.Nodes) > 0 {
|
||||||
return newSingleSelection(this.Nodes[0], this.document).PrevAll().Length()
|
return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length()
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexSelector() returns the position of the first element within the
|
// IndexSelector returns the position of the first element within the
|
||||||
// Selection object relative to the elements matched by the selector, or -1 if
|
// Selection object relative to the elements matched by the selector, or -1 if
|
||||||
// not found.
|
// not found.
|
||||||
func (this *Selection) IndexSelector(selector string) int {
|
func (s *Selection) IndexSelector(selector string) int {
|
||||||
if len(this.Nodes) > 0 {
|
if len(s.Nodes) > 0 {
|
||||||
sel := this.document.Find(selector)
|
sel := s.document.Find(selector)
|
||||||
return indexInSlice(sel.Nodes, this.Nodes[0])
|
return indexInSlice(sel.Nodes, s.Nodes[0])
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexOfNode() returns the position of the specified node within the Selection
|
// IndexMatcher returns the position of the first element within the
|
||||||
|
// Selection object relative to the elements matched by the matcher, or -1 if
|
||||||
|
// not found.
|
||||||
|
func (s *Selection) IndexMatcher(m Matcher) int {
|
||||||
|
if len(s.Nodes) > 0 {
|
||||||
|
sel := s.document.FindMatcher(m)
|
||||||
|
return indexInSlice(sel.Nodes, s.Nodes[0])
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexOfNode returns the position of the specified node within the Selection
|
||||||
// object, or -1 if not found.
|
// object, or -1 if not found.
|
||||||
func (this *Selection) IndexOfNode(node *html.Node) int {
|
func (s *Selection) IndexOfNode(node *html.Node) int {
|
||||||
return indexInSlice(this.Nodes, node)
|
return indexInSlice(s.Nodes, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IndexOfSelection() returns the position of the first node in the specified
|
// IndexOfSelection returns the position of the first node in the specified
|
||||||
// Selection object within this Selection object, or -1 if not found.
|
// Selection object within this Selection object, or -1 if not found.
|
||||||
func (this *Selection) IndexOfSelection(s *Selection) int {
|
func (s *Selection) IndexOfSelection(sel *Selection) int {
|
||||||
if s != nil && len(s.Nodes) > 0 {
|
if sel != nil && len(sel.Nodes) > 0 {
|
||||||
return indexInSlice(this.Nodes, s.Nodes[0])
|
return indexInSlice(s.Nodes, sel.Nodes[0])
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-22
@@ -6,23 +6,23 @@ import (
|
|||||||
|
|
||||||
func TestFirst(t *testing.T) {
|
func TestFirst(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").First()
|
sel := Doc().Find(".pvk-content").First()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFirstEmpty(t *testing.T) {
|
func TestFirstEmpty(t *testing.T) {
|
||||||
defer AssertPanic(t)
|
sel := Doc().Find(".pvk-zzcontentzz").First()
|
||||||
Doc().Find(".pvk-zzcontentzz").First()
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFirstRollback(t *testing.T) {
|
func TestFirstRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.First().End()
|
sel2 := sel.First().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLast(t *testing.T) {
|
func TestLast(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Last()
|
sel := Doc().Find(".pvk-content").Last()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
|
||||||
// Should contain Footer
|
// Should contain Footer
|
||||||
foot := Doc().Find(".footer")
|
foot := Doc().Find(".footer")
|
||||||
@@ -31,20 +31,25 @@ func TestLast(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLastEmpty(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-zzcontentzz").Last()
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func TestLastRollback(t *testing.T) {
|
func TestLastRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Last().End()
|
sel2 := sel.Last().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEq(t *testing.T) {
|
func TestEq(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Eq(1)
|
sel := Doc().Find(".pvk-content").Eq(1)
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEqNegative(t *testing.T) {
|
func TestEqNegative(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Eq(-1)
|
sel := Doc().Find(".pvk-content").Eq(-1)
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
|
|
||||||
// Should contain Footer
|
// Should contain Footer
|
||||||
foot := Doc().Find(".footer")
|
foot := Doc().Find(".footer")
|
||||||
@@ -53,52 +58,67 @@ func TestEqNegative(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestEqEmpty(t *testing.T) {
|
||||||
|
sel := Doc().Find("something_random_that_does_not_exists").Eq(0)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqInvalidPositive(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(3)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqInvalidNegative(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content").Eq(-4)
|
||||||
|
assertLength(t, sel.Nodes, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func TestEqRollback(t *testing.T) {
|
func TestEqRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Eq(1).End()
|
sel2 := sel.Eq(1).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlice(t *testing.T) {
|
func TestSlice(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Slice(0, 2)
|
sel := Doc().Find(".pvk-content").Slice(0, 2)
|
||||||
|
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceOutOfBounds(t *testing.T) {
|
func TestSliceOutOfBounds(t *testing.T) {
|
||||||
defer AssertPanic(t)
|
defer assertPanic(t)
|
||||||
Doc().Find(".pvk-content").Slice(2, 12)
|
Doc().Find(".pvk-content").Slice(2, 12)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNegativeSliceStart(t *testing.T) {
|
func TestNegativeSliceStart(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Slice(-2, 3)
|
sel := Doc().Find(".container-fluid").Slice(-2, 3)
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel.Eq(0), "#cf3")
|
assertSelectionIs(t, sel.Eq(0), "#cf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNegativeSliceEnd(t *testing.T) {
|
func TestNegativeSliceEnd(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Slice(1, -1)
|
sel := Doc().Find(".container-fluid").Slice(1, -1)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel.Eq(0), "#cf2")
|
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
||||||
AssertSelectionIs(t, sel.Eq(1), "#cf3")
|
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNegativeSliceBoth(t *testing.T) {
|
func TestNegativeSliceBoth(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Slice(-3, -1)
|
sel := Doc().Find(".container-fluid").Slice(-3, -1)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel.Eq(0), "#cf2")
|
assertSelectionIs(t, sel.Eq(0), "#cf2")
|
||||||
AssertSelectionIs(t, sel.Eq(1), "#cf3")
|
assertSelectionIs(t, sel.Eq(1), "#cf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNegativeSliceOutOfBounds(t *testing.T) {
|
func TestNegativeSliceOutOfBounds(t *testing.T) {
|
||||||
defer AssertPanic(t)
|
defer assertPanic(t)
|
||||||
Doc().Find(".container-fluid").Slice(-12, -7)
|
Doc().Find(".container-fluid").Slice(-12, -7)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSliceRollback(t *testing.T) {
|
func TestSliceRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Slice(0, 2).End()
|
sel2 := sel.Slice(0, 2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
@@ -118,7 +138,7 @@ func TestGetNegative(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetInvalid(t *testing.T) {
|
func TestGetInvalid(t *testing.T) {
|
||||||
defer AssertPanic(t)
|
defer assertPanic(t)
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel.Get(129)
|
sel.Get(129)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,478 @@
|
|||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 88.4 ns/op
|
||||||
|
BenchmarkLast 20000000 88.2 ns/op
|
||||||
|
BenchmarkEq 20000000 87.4 ns/op
|
||||||
|
BenchmarkSlice 20000000 84.9 ns/op
|
||||||
|
BenchmarkGet 2000000000 1.99 ns/op
|
||||||
|
BenchmarkIndex 2000000 906 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 22276 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 200000000 9.72 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 10.4 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 199277 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 18277 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 200 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 189 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2569 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 25195 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 100000 29003 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 60690 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66008 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59723 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 72698 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 59598 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 72526 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 367076 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 219710 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 219105 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.58 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8615 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 200000 14271 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1497 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 30.9 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 13729 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 537 ns/op
|
||||||
|
BenchmarkIs 100000 28904 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23556 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2195 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 60100 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 59962 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 388679 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 22779 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 62033 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 446918 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 441753 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2807 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4477 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 548 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3304 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 38248 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 40677 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 83043 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 85391 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65118 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 144028 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 146713 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 15113 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 18881 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 18926 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63221 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 69028 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9133 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10601 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 43089 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 47867 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9104 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 10579 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 15185 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 17108 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 81087 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 55831 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23130 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 204673 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 50000 70965 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 18591 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 42004 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 61953 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62124 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 42861 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 62451 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 62631 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4684 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 622 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 617 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 218.724s
|
||||||
@@ -0,0 +1,477 @@
|
|||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 88.3 ns/op
|
||||||
|
BenchmarkLast 20000000 88.9 ns/op
|
||||||
|
BenchmarkEq 20000000 86.7 ns/op
|
||||||
|
BenchmarkSlice 20000000 84.1 ns/op
|
||||||
|
BenchmarkGet 2000000000 1.99 ns/op
|
||||||
|
BenchmarkIndex 2000000 907 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 200000 13052 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.5 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.6 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 189556 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 200000 13714 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 200 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 186 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2532 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 25199 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 100000 29162 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 60733 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66124 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59489 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 73623 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 60053 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 73477 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 364859 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 226980 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 220471 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.64 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8811 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 100000 15365 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1559 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 31.7 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 13901 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 541 ns/op
|
||||||
|
BenchmarkIs 100000 29435 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 22938 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2185 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 60607 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 61599 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 395436 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 200000 13788 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 54253 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 438879 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 437225 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2844 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4528 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 552 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3345 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 39482 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 42113 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 84136 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 86041 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65844 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 146903 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 146638 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 16413 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 20366 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 18800 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63443 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 69250 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9193 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10767 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 42829 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 48174 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9114 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 11114 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 16387 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 18322 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 83828 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 58822 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23173 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 219407 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 20000 76033 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 19417 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 44648 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 62751 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62035 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 43331 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 64767 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 67808 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 4870 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 656 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 663 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 218.007s
|
||||||
@@ -0,0 +1,477 @@
|
|||||||
|
PASS
|
||||||
|
BenchmarkFirst 20000000 91.0 ns/op
|
||||||
|
BenchmarkLast 20000000 90.5 ns/op
|
||||||
|
BenchmarkEq 20000000 90.2 ns/op
|
||||||
|
BenchmarkSlice 20000000 88.0 ns/op
|
||||||
|
BenchmarkGet 1000000000 2.04 ns/op
|
||||||
|
BenchmarkIndex 2000000 935 ns/op
|
||||||
|
--- BENCH: BenchmarkIndex
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
bench_array_test.go:73: Index=3
|
||||||
|
BenchmarkIndexSelector 100000 23613 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexSelector
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
bench_array_test.go:85: IndexSelector=4
|
||||||
|
BenchmarkIndexOfNode 100000000 10.2 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfNode
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
bench_array_test.go:99: IndexOfNode=2
|
||||||
|
BenchmarkIndexOfSelection 100000000 11.0 ns/op
|
||||||
|
--- BENCH: BenchmarkIndexOfSelection
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
bench_array_test.go:111: IndexOfSelection=2
|
||||||
|
BenchmarkMetalReviewExample 10000 213843 ns/op
|
||||||
|
--- BENCH: BenchmarkMetalReviewExample
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
|
||||||
|
bench_example_test.go:41: MetalReviewExample=10
|
||||||
|
bench_example_test.go:40: Review 0: Midnight - Complete and Total Hell (8.5).
|
||||||
|
Review 1: Over Your Threshold - Facticity (6.0).
|
||||||
|
Review 2: Nuclear Death Terror - Chaos Reigns (7.5).
|
||||||
|
Review 3: Evoken - Atra Mors (9.5).
|
||||||
|
... [output truncated]
|
||||||
|
BenchmarkAdd 100000 18671 ns/op
|
||||||
|
--- BENCH: BenchmarkAdd
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
bench_expand_test.go:20: Add=43
|
||||||
|
BenchmarkAddSelection 10000000 204 ns/op
|
||||||
|
--- BENCH: BenchmarkAddSelection
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
bench_expand_test.go:37: AddSelection=43
|
||||||
|
BenchmarkAddNodes 10000000 195 ns/op
|
||||||
|
--- BENCH: BenchmarkAddNodes
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
bench_expand_test.go:55: AddNodes=43
|
||||||
|
BenchmarkAndSelf 1000000 2611 ns/op
|
||||||
|
--- BENCH: BenchmarkAndSelf
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
bench_expand_test.go:71: AndSelf=44
|
||||||
|
BenchmarkFilter 100000 27571 ns/op
|
||||||
|
--- BENCH: BenchmarkFilter
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
bench_filter_test.go:20: Filter=13
|
||||||
|
BenchmarkNot 50000 32006 ns/op
|
||||||
|
--- BENCH: BenchmarkNot
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
bench_filter_test.go:36: Not=371
|
||||||
|
BenchmarkFilterFunction 50000 61388 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterFunction
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
bench_filter_test.go:55: FilterFunction=112
|
||||||
|
BenchmarkNotFunction 50000 66702 ns/op
|
||||||
|
--- BENCH: BenchmarkNotFunction
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
bench_filter_test.go:74: NotFunction=261
|
||||||
|
BenchmarkFilterNodes 50000 59699 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterNodes
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
bench_filter_test.go:92: FilterNodes=2
|
||||||
|
BenchmarkNotNodes 50000 73248 ns/op
|
||||||
|
--- BENCH: BenchmarkNotNodes
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
bench_filter_test.go:110: NotNodes=360
|
||||||
|
BenchmarkFilterSelection 50000 59242 ns/op
|
||||||
|
--- BENCH: BenchmarkFilterSelection
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
bench_filter_test.go:127: FilterSelection=2
|
||||||
|
BenchmarkNotSelection 50000 73211 ns/op
|
||||||
|
--- BENCH: BenchmarkNotSelection
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
bench_filter_test.go:144: NotSelection=360
|
||||||
|
BenchmarkHas 5000 395087 ns/op
|
||||||
|
--- BENCH: BenchmarkHas
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
bench_filter_test.go:160: Has=13
|
||||||
|
BenchmarkHasNodes 10000 215849 ns/op
|
||||||
|
--- BENCH: BenchmarkHasNodes
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
bench_filter_test.go:178: HasNodes=15
|
||||||
|
BenchmarkHasSelection 10000 215612 ns/op
|
||||||
|
--- BENCH: BenchmarkHasSelection
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
bench_filter_test.go:195: HasSelection=15
|
||||||
|
BenchmarkEnd 500000000 4.59 ns/op
|
||||||
|
--- BENCH: BenchmarkEnd
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
bench_filter_test.go:211: End=373
|
||||||
|
BenchmarkEach 200000 8588 ns/op
|
||||||
|
--- BENCH: BenchmarkEach
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
bench_iteration_test.go:22: Each=59
|
||||||
|
BenchmarkMap 200000 14444 ns/op
|
||||||
|
--- BENCH: BenchmarkMap
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
bench_iteration_test.go:41: Map=59
|
||||||
|
BenchmarkEachWithBreak 1000000 1490 ns/op
|
||||||
|
--- BENCH: BenchmarkEachWithBreak
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
bench_iteration_test.go:61: Each=10
|
||||||
|
BenchmarkAttr 50000000 30.9 ns/op
|
||||||
|
--- BENCH: BenchmarkAttr
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
bench_property_test.go:16: Attr=firstHeading
|
||||||
|
BenchmarkText 200000 14017 ns/op
|
||||||
|
BenchmarkLength 2000000000 0.31 ns/op
|
||||||
|
--- BENCH: BenchmarkLength
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
bench_property_test.go:37: Length=14
|
||||||
|
BenchmarkHtml 5000000 577 ns/op
|
||||||
|
BenchmarkIs 50000 31936 ns/op
|
||||||
|
--- BENCH: BenchmarkIs
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
bench_query_test.go:16: Is=true
|
||||||
|
BenchmarkIsPositional 100000 23372 ns/op
|
||||||
|
--- BENCH: BenchmarkIsPositional
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
bench_query_test.go:28: IsPositional=true
|
||||||
|
BenchmarkIsFunction 1000000 2170 ns/op
|
||||||
|
--- BENCH: BenchmarkIsFunction
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
bench_query_test.go:43: IsFunction=true
|
||||||
|
BenchmarkIsSelection 50000 59814 ns/op
|
||||||
|
--- BENCH: BenchmarkIsSelection
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
bench_query_test.go:56: IsSelection=true
|
||||||
|
BenchmarkIsNodes 50000 59629 ns/op
|
||||||
|
--- BENCH: BenchmarkIsNodes
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
bench_query_test.go:70: IsNodes=true
|
||||||
|
BenchmarkHasClass 5000 384894 ns/op
|
||||||
|
--- BENCH: BenchmarkHasClass
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
bench_query_test.go:82: HasClass=true
|
||||||
|
BenchmarkContains 100000000 11.4 ns/op
|
||||||
|
--- BENCH: BenchmarkContains
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
bench_query_test.go:96: Contains=true
|
||||||
|
BenchmarkFind 100000 23545 ns/op
|
||||||
|
--- BENCH: BenchmarkFind
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
bench_traversal_test.go:18: Find=41
|
||||||
|
BenchmarkFindWithinSelection 50000 63775 ns/op
|
||||||
|
--- BENCH: BenchmarkFindWithinSelection
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
bench_traversal_test.go:34: FindWithinSelection=39
|
||||||
|
BenchmarkFindSelection 5000 441958 ns/op
|
||||||
|
--- BENCH: BenchmarkFindSelection
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
bench_traversal_test.go:51: FindSelection=73
|
||||||
|
BenchmarkFindNodes 5000 437717 ns/op
|
||||||
|
--- BENCH: BenchmarkFindNodes
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
bench_traversal_test.go:69: FindNodes=73
|
||||||
|
BenchmarkContents 1000000 2799 ns/op
|
||||||
|
--- BENCH: BenchmarkContents
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
bench_traversal_test.go:85: Contents=16
|
||||||
|
BenchmarkContentsFiltered 500000 4489 ns/op
|
||||||
|
--- BENCH: BenchmarkContentsFiltered
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
bench_traversal_test.go:101: ContentsFiltered=1
|
||||||
|
BenchmarkChildren 5000000 546 ns/op
|
||||||
|
--- BENCH: BenchmarkChildren
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
bench_traversal_test.go:117: Children=2
|
||||||
|
BenchmarkChildrenFiltered 500000 3472 ns/op
|
||||||
|
--- BENCH: BenchmarkChildrenFiltered
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
bench_traversal_test.go:133: ChildrenFiltered=2
|
||||||
|
BenchmarkParent 50000 39067 ns/op
|
||||||
|
--- BENCH: BenchmarkParent
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
bench_traversal_test.go:149: Parent=55
|
||||||
|
BenchmarkParentFiltered 50000 41450 ns/op
|
||||||
|
--- BENCH: BenchmarkParentFiltered
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
bench_traversal_test.go:165: ParentFiltered=4
|
||||||
|
BenchmarkParents 20000 84864 ns/op
|
||||||
|
--- BENCH: BenchmarkParents
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
bench_traversal_test.go:181: Parents=73
|
||||||
|
BenchmarkParentsFiltered 20000 87823 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFiltered
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
bench_traversal_test.go:197: ParentsFiltered=18
|
||||||
|
BenchmarkParentsUntil 50000 65986 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntil
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
bench_traversal_test.go:213: ParentsUntil=52
|
||||||
|
BenchmarkParentsUntilSelection 10000 149798 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilSelection
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
bench_traversal_test.go:230: ParentsUntilSelection=70
|
||||||
|
BenchmarkParentsUntilNodes 10000 148144 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsUntilNodes
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
bench_traversal_test.go:248: ParentsUntilNodes=70
|
||||||
|
BenchmarkParentsFilteredUntil 100000 15579 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntil
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
bench_traversal_test.go:264: ParentsFilteredUntil=2
|
||||||
|
BenchmarkParentsFilteredUntilSelection 100000 19094 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
bench_traversal_test.go:281: ParentsFilteredUntilSelection=2
|
||||||
|
BenchmarkParentsFilteredUntilNodes 100000 19037 ns/op
|
||||||
|
--- BENCH: BenchmarkParentsFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
bench_traversal_test.go:299: ParentsFilteredUntilNodes=2
|
||||||
|
BenchmarkSiblings 50000 63891 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblings
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
bench_traversal_test.go:315: Siblings=293
|
||||||
|
BenchmarkSiblingsFiltered 50000 70424 ns/op
|
||||||
|
--- BENCH: BenchmarkSiblingsFiltered
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
bench_traversal_test.go:331: SiblingsFiltered=46
|
||||||
|
BenchmarkNext 200000 9350 ns/op
|
||||||
|
--- BENCH: BenchmarkNext
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
bench_traversal_test.go:347: Next=49
|
||||||
|
BenchmarkNextFiltered 200000 10929 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFiltered
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
bench_traversal_test.go:363: NextFiltered=6
|
||||||
|
BenchmarkNextAll 50000 43398 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAll
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
bench_traversal_test.go:379: NextAll=234
|
||||||
|
BenchmarkNextAllFiltered 50000 48519 ns/op
|
||||||
|
--- BENCH: BenchmarkNextAllFiltered
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
bench_traversal_test.go:395: NextAllFiltered=33
|
||||||
|
BenchmarkPrev 200000 9181 ns/op
|
||||||
|
--- BENCH: BenchmarkPrev
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
bench_traversal_test.go:411: Prev=49
|
||||||
|
BenchmarkPrevFiltered 200000 10811 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFiltered
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
bench_traversal_test.go:429: PrevFiltered=7
|
||||||
|
BenchmarkPrevAll 100000 15589 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAll
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
bench_traversal_test.go:445: PrevAll=78
|
||||||
|
BenchmarkPrevAllFiltered 100000 17341 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevAllFiltered
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
bench_traversal_test.go:461: PrevAllFiltered=6
|
||||||
|
BenchmarkNextUntil 20000 80663 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntil
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
bench_traversal_test.go:477: NextUntil=84
|
||||||
|
BenchmarkNextUntilSelection 50000 56496 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilSelection
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
bench_traversal_test.go:494: NextUntilSelection=42
|
||||||
|
BenchmarkNextUntilNodes 100000 23729 ns/op
|
||||||
|
--- BENCH: BenchmarkNextUntilNodes
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
bench_traversal_test.go:512: NextUntilNodes=12
|
||||||
|
BenchmarkPrevUntil 10000 208267 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntil
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
bench_traversal_test.go:528: PrevUntil=238
|
||||||
|
BenchmarkPrevUntilSelection 50000 72119 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilSelection
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
bench_traversal_test.go:545: PrevUntilSelection=49
|
||||||
|
BenchmarkPrevUntilNodes 100000 18549 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevUntilNodes
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
bench_traversal_test.go:563: PrevUntilNodes=11
|
||||||
|
BenchmarkNextFilteredUntil 50000 42339 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntil
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
bench_traversal_test.go:579: NextFilteredUntil=22
|
||||||
|
BenchmarkNextFilteredUntilSelection 50000 61916 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
bench_traversal_test.go:596: NextFilteredUntilSelection=22
|
||||||
|
BenchmarkNextFilteredUntilNodes 50000 62139 ns/op
|
||||||
|
--- BENCH: BenchmarkNextFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
bench_traversal_test.go:614: NextFilteredUntilNodes=22
|
||||||
|
BenchmarkPrevFilteredUntil 50000 43409 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntil
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
bench_traversal_test.go:630: PrevFilteredUntil=20
|
||||||
|
BenchmarkPrevFilteredUntilSelection 50000 63768 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilSelection
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
bench_traversal_test.go:647: PrevFilteredUntilSelection=20
|
||||||
|
BenchmarkPrevFilteredUntilNodes 50000 63543 ns/op
|
||||||
|
--- BENCH: BenchmarkPrevFilteredUntilNodes
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
bench_traversal_test.go:665: PrevFilteredUntilNodes=20
|
||||||
|
BenchmarkClosest 500000 5110 ns/op
|
||||||
|
--- BENCH: BenchmarkClosest
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
bench_traversal_test.go:681: Closest=2
|
||||||
|
BenchmarkClosestSelection 5000000 629 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestSelection
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
bench_traversal_test.go:698: ClosestSelection=2
|
||||||
|
BenchmarkClosestNodes 5000000 627 ns/op
|
||||||
|
--- BENCH: BenchmarkClosestNodes
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
bench_traversal_test.go:715: ClosestNodes=2
|
||||||
|
ok github.com/PuerkitoBio/goquery 215.785s
|
||||||
@@ -12,7 +12,7 @@ func BenchmarkMetalReviewExample(b *testing.B) {
|
|||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
doc := LoadDoc("metalreview.html")
|
doc := loadDoc("metalreview.html")
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2013, Martin Angers & Contributors
|
// Copyright (c) 2012-2014, Martin Angers & Contributors
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without modification,
|
// Redistribution and use in source and binary forms, with or without modification,
|
||||||
@@ -23,20 +23,32 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Package goquery implements features similar to jQuery, including the chainable
|
Package goquery implements features similar to jQuery, including the chainable
|
||||||
syntax, to manipulate and query an HTML document (the modification functions of jQuery are not included).
|
syntax, to manipulate and query an HTML document.
|
||||||
|
|
||||||
It uses Cascadia as CSS selector (similar to Sizzle for jQuery).
|
It brings a syntax and a set of features similar to jQuery to the Go language.
|
||||||
|
It is based on Go's net/html package and the CSS Selector library cascadia.
|
||||||
|
Since the net/html parser returns nodes, and not a full-featured DOM
|
||||||
|
tree, jQuery's stateful manipulation functions (like height(), css(), detach())
|
||||||
|
have been left off.
|
||||||
|
|
||||||
To provide a chainable interface, error management is strict, and goquery panics
|
Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is
|
||||||
if an invalid Cascadia selector is used (this is consistent with the behavior of
|
the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML.
|
||||||
jQuery/Sizzle/document.querySelectorAll, where an error is thrown). This is
|
See the repository's wiki for various options on how to do this.
|
||||||
necessary since multiple return values cannot be used to allow a chainable
|
|
||||||
interface.
|
Syntax-wise, it is as close as possible to jQuery, with the same function names when
|
||||||
|
possible, and that warm and fuzzy chainable interface. jQuery being the
|
||||||
|
ultra-popular library that it is, writing a similar HTML-manipulating
|
||||||
|
library was better to follow its API than to start anew (in the same spirit as
|
||||||
|
Go's fmt package), even though some of its methods are less than intuitive (looking
|
||||||
|
at you, index()...).
|
||||||
|
|
||||||
It is hosted on GitHub, along with additional documentation in the README.md
|
It is hosted on GitHub, along with additional documentation in the README.md
|
||||||
file: https://github.com/puerkitobio/goquery
|
file: https://github.com/puerkitobio/goquery
|
||||||
|
|
||||||
The various methods are split into files based on the category of behavior:
|
Please note that because of the net/html dependency, goquery requires Go1.1+.
|
||||||
|
|
||||||
|
The various methods are split into files based on the category of behavior.
|
||||||
|
The three dots (...) indicate that various "overloads" are available.
|
||||||
|
|
||||||
* array.go : array-like positional manipulation of the selection.
|
* array.go : array-like positional manipulation of the selection.
|
||||||
- Eq()
|
- Eq()
|
||||||
@@ -63,8 +75,17 @@ The various methods are split into files based on the category of behavior:
|
|||||||
- EachWithBreak()
|
- EachWithBreak()
|
||||||
- Map()
|
- Map()
|
||||||
|
|
||||||
|
* manipulation.go : methods for modifying the document
|
||||||
|
- After...()
|
||||||
|
- Append...()
|
||||||
|
- Before...()
|
||||||
|
- Clone()
|
||||||
|
- Empty()
|
||||||
|
- Remove...()
|
||||||
|
|
||||||
* property.go : methods that inspect and get the node's properties values.
|
* property.go : methods that inspect and get the node's properties values.
|
||||||
- Attr()
|
- Attr(), RemoveAttr(), SetAttr()
|
||||||
|
- AddClass(), HasClass(), RemoveClass(), ToggleClass()
|
||||||
- Html()
|
- Html()
|
||||||
- Length()
|
- Length()
|
||||||
- Size(), which is an alias for Length()
|
- Size(), which is an alias for Length()
|
||||||
@@ -72,7 +93,6 @@ The various methods are split into files based on the category of behavior:
|
|||||||
|
|
||||||
* query.go : methods that query, or reflect, a node's identity.
|
* query.go : methods that query, or reflect, a node's identity.
|
||||||
- Contains()
|
- Contains()
|
||||||
- HasClass()
|
|
||||||
- Is...()
|
- Is...()
|
||||||
|
|
||||||
* traversal.go : methods to traverse the HTML document tree.
|
* traversal.go : methods to traverse the HTML document tree.
|
||||||
@@ -84,8 +104,9 @@ The various methods are split into files based on the category of behavior:
|
|||||||
- Prev...()
|
- Prev...()
|
||||||
- Siblings...()
|
- Siblings...()
|
||||||
|
|
||||||
* type.go : definition of the types exposed by GoQuery.
|
* type.go : definition of the types exposed by goquery.
|
||||||
- Document
|
- Document
|
||||||
- Selection
|
- Selection
|
||||||
|
- Matcher
|
||||||
*/
|
*/
|
||||||
package goquery
|
package goquery
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
# Tips and tricks
|
||||||
|
|
||||||
|
## Handle Non-UTF8 html Pages
|
||||||
|
|
||||||
|
The `go.net/html` package used by `goquery` requires that the html document is UTF-8 encoded. When you know the encoding of the html page is not UTF-8, you can use the `iconv` package to convert it to UTF-8 (there are various implementation of the `iconv` API, see [godoc.org][iconv] for other options):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get -u github.com/djimenez/iconv-go
|
||||||
|
```
|
||||||
|
|
||||||
|
and then:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Load the URL
|
||||||
|
res, err := http.Get(url)
|
||||||
|
if e != nil {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// Convert the designated charset HTML to utf-8 encoded HTML.
|
||||||
|
// `charset` being one of the charsets known by the iconv package.
|
||||||
|
utfBody, err := iconv.NewReader(res.Body, charset, "utf-8")
|
||||||
|
if err != nil {
|
||||||
|
// handler error
|
||||||
|
}
|
||||||
|
|
||||||
|
// use utfBody using goquery
|
||||||
|
doc, err := goquery.NewDocumentFromReader(utfBody)
|
||||||
|
if err != nil {
|
||||||
|
// handler error
|
||||||
|
}
|
||||||
|
// use doc...
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks to github user @YuheiNakasaka.
|
||||||
|
|
||||||
|
Actually, the official go.text repository covers this use case too, see its [godoc page][text] for the details.
|
||||||
|
|
||||||
|
|
||||||
|
## Handle Javascript-based Pages
|
||||||
|
|
||||||
|
`goquery` is great to handle normal html pages, but when most of the page is build dynamically using javascript, there's not much it can do. There are various options when faced with this problem:
|
||||||
|
|
||||||
|
* Use a headless browser such as [webloop][].
|
||||||
|
* Use a Go javascript parser package, such as [otto][].
|
||||||
|
|
||||||
|
You can find a code example using `otto` [in this gist][exotto]. Thanks to github user @cryptix.
|
||||||
|
|
||||||
|
## For Loop
|
||||||
|
|
||||||
|
If all you need is a normal `for` loop over all nodes in the current selection, where `Map/Each`-style iteration is not necessary, you can use the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
sel := Doc().Find(".selector")
|
||||||
|
for i := range sel.Nodes {
|
||||||
|
single := sel.Eq(i)
|
||||||
|
// use `single` as a selection of 1 node
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks to github user @jmoiron.
|
||||||
|
|
||||||
|
[webloop]: https://github.com/sourcegraph/webloop
|
||||||
|
[otto]: https://github.com/robertkrimen/otto
|
||||||
|
[exotto]: https://gist.github.com/cryptix/87127f76a94183747b53
|
||||||
|
[iconv]: http://godoc.org/?q=iconv
|
||||||
|
[text]: http://godoc.org/code.google.com/p/go.text/encoding
|
||||||
+12
-23
@@ -2,38 +2,27 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
// In real use, this import would be required (not in this example, since it
|
// In real use, this import would be required (not in this example, since it
|
||||||
// is part of the goquery package)
|
// is part of the goquery package)
|
||||||
//"github.com/PuerkitoBio/goquery"
|
//"github.com/PuerkitoBio/goquery"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// This example scrapes the 10 reviews shown on the home page of MetalReview.com,
|
// This example scrapes the reviews shown on the home page of metalsucks.net.
|
||||||
// the best metal review site on the web :) (and no, I'm not affiliated to them!)
|
func ExampleScrape_MetalSucks() {
|
||||||
func ExampleScrape_MetalReview() {
|
|
||||||
// Load the HTML document (in real use, the type would be *goquery.Document)
|
// Load the HTML document (in real use, the type would be *goquery.Document)
|
||||||
var doc *Document
|
doc, err := NewDocument("http://metalsucks.net")
|
||||||
var e error
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
if doc, e = NewDocument("http://metalreview.com"); e != nil {
|
|
||||||
panic(e.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the review items (the type of the Selection would be *goquery.Selection)
|
// Find the review items (the type of the Selection would be *goquery.Selection)
|
||||||
doc.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
|
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *Selection) {
|
||||||
var band, title string
|
// For each item found, get the band and title
|
||||||
var score float64
|
band := s.Find("h3").Text()
|
||||||
|
title := s.Find("i").Text()
|
||||||
// For each item found, get the band, title and score, and print it
|
fmt.Printf("Review %d: %s - %s\n", i, band, title)
|
||||||
band = s.Find("strong").Text()
|
|
||||||
title = s.Find("em").Text()
|
|
||||||
if score, e = strconv.ParseFloat(s.Find(".score").Text(), 64); e != nil {
|
|
||||||
// Not a valid float, ignore score
|
|
||||||
fmt.Printf("Review %d: %s - %s.\n", i, band, title)
|
|
||||||
} else {
|
|
||||||
// Print all, including score
|
|
||||||
fmt.Printf("Review %d: %s - %s (%2.1f).\n", i, band, title, score)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
// To see the output of the Example while running the test suite (go test), simply
|
// To see the output of the Example while running the test suite (go test), simply
|
||||||
// remove the leading "x" before Output on the next line. This will cause the
|
// remove the leading "x" before Output on the next line. This will cause the
|
||||||
|
|||||||
@@ -1,40 +1,49 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
"code.google.com/p/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add() adds the selector string's matching nodes to those in the current
|
// Add adds the selector string's matching nodes to those in the current
|
||||||
// selection and returns a new Selection object.
|
// selection and returns a new Selection object.
|
||||||
// The selector string is run in the context of the document of the current
|
// The selector string is run in the context of the document of the current
|
||||||
// Selection object.
|
// Selection object.
|
||||||
func (this *Selection) Add(selector string) *Selection {
|
func (s *Selection) Add(selector string) *Selection {
|
||||||
return this.AddNodes(findWithSelector([]*html.Node{this.document.rootNode}, selector)...)
|
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, cascadia.MustCompile(selector))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddSelection() adds the specified Selection object's nodes to those in the
|
// AddMatcher adds the matcher's matching nodes to those in the current
|
||||||
|
// selection and returns a new Selection object.
|
||||||
|
// The matcher is run in the context of the document of the current
|
||||||
|
// Selection object.
|
||||||
|
func (s *Selection) AddMatcher(m Matcher) *Selection {
|
||||||
|
return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, m)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddSelection adds the specified Selection object's nodes to those in the
|
||||||
// current selection and returns a new Selection object.
|
// current selection and returns a new Selection object.
|
||||||
func (this *Selection) AddSelection(sel *Selection) *Selection {
|
func (s *Selection) AddSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.AddNodes()
|
return s.AddNodes()
|
||||||
}
|
}
|
||||||
return this.AddNodes(sel.Nodes...)
|
return s.AddNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Union() is an alias for AddSelection().
|
// Union is an alias for AddSelection.
|
||||||
func (this *Selection) Union(sel *Selection) *Selection {
|
func (s *Selection) Union(sel *Selection) *Selection {
|
||||||
return this.AddSelection(sel)
|
return s.AddSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNodes() adds the specified nodes to those in the
|
// AddNodes adds the specified nodes to those in the
|
||||||
// current selection and returns a new Selection object.
|
// current selection and returns a new Selection object.
|
||||||
func (this *Selection) AddNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, appendWithoutDuplicates(this.Nodes, nodes))
|
return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AndSelf() adds the previous set of elements on the stack to the current set.
|
// AndSelf adds the previous set of elements on the stack to the current set.
|
||||||
// It returns a new Selection object containing the current Selection combined
|
// It returns a new Selection object containing the current Selection combined
|
||||||
// with the previous one.
|
// with the previous one.
|
||||||
func (this *Selection) AndSelf() *Selection {
|
func (s *Selection) AndSelf() *Selection {
|
||||||
return this.AddSelection(this.prevSel)
|
return s.AddSelection(s.prevSel)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -6,63 +6,63 @@ import (
|
|||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
func TestAdd(t *testing.T) {
|
||||||
sel := Doc().Find("div.row-fluid").Add("a")
|
sel := Doc().Find("div.row-fluid").Add("a")
|
||||||
AssertLength(t, sel.Nodes, 19)
|
assertLength(t, sel.Nodes, 19)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddRollback(t *testing.T) {
|
func TestAddRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Add("a").End()
|
sel2 := sel.Add("a").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddSelection(t *testing.T) {
|
func TestAddSelection(t *testing.T) {
|
||||||
sel := Doc().Find("div.row-fluid")
|
sel := Doc().Find("div.row-fluid")
|
||||||
sel2 := Doc().Find("a")
|
sel2 := Doc().Find("a")
|
||||||
sel = sel.AddSelection(sel2)
|
sel = sel.AddSelection(sel2)
|
||||||
AssertLength(t, sel.Nodes, 19)
|
assertLength(t, sel.Nodes, 19)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddSelectionNil(t *testing.T) {
|
func TestAddSelectionNil(t *testing.T) {
|
||||||
sel := Doc().Find("div.row-fluid")
|
sel := Doc().Find("div.row-fluid")
|
||||||
AssertLength(t, sel.Nodes, 9)
|
assertLength(t, sel.Nodes, 9)
|
||||||
|
|
||||||
sel = sel.AddSelection(nil)
|
sel = sel.AddSelection(nil)
|
||||||
AssertLength(t, sel.Nodes, 9)
|
assertLength(t, sel.Nodes, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddSelectionRollback(t *testing.T) {
|
func TestAddSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Find("a")
|
sel2 := sel.Find("a")
|
||||||
sel2 = sel.AddSelection(sel2).End()
|
sel2 = sel.AddSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddNodes(t *testing.T) {
|
func TestAddNodes(t *testing.T) {
|
||||||
sel := Doc().Find("div.pvk-gutter")
|
sel := Doc().Find("div.pvk-gutter")
|
||||||
sel2 := Doc().Find(".pvk-content")
|
sel2 := Doc().Find(".pvk-content")
|
||||||
sel = sel.AddNodes(sel2.Nodes...)
|
sel = sel.AddNodes(sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 9)
|
assertLength(t, sel.Nodes, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddNodesNone(t *testing.T) {
|
func TestAddNodesNone(t *testing.T) {
|
||||||
sel := Doc().Find("div.pvk-gutter").AddNodes()
|
sel := Doc().Find("div.pvk-gutter").AddNodes()
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddNodesRollback(t *testing.T) {
|
func TestAddNodesRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Find("a")
|
sel2 := sel.Find("a")
|
||||||
sel2 = sel.AddNodes(sel2.Nodes...).End()
|
sel2 = sel.AddNodes(sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAndSelf(t *testing.T) {
|
func TestAndSelf(t *testing.T) {
|
||||||
sel := Doc().Find(".span12").Last().AndSelf()
|
sel := Doc().Find(".span12").Last().AndSelf()
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAndSelfRollback(t *testing.T) {
|
func TestAndSelfRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Find("a").AndSelf().End().End()
|
sel2 := sel.Find("a").AndSelf().End().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,85 +2,104 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/cascadia"
|
"code.google.com/p/cascadia"
|
||||||
"code.google.com/p/go.net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Filter() reduces the set of matched elements to those that match the selector string.
|
// Filter reduces the set of matched elements to those that match the selector string.
|
||||||
// It returns a new Selection object for this subset of matching elements.
|
// It returns a new Selection object for this subset of matching elements.
|
||||||
func (this *Selection) Filter(selector string) *Selection {
|
func (s *Selection) Filter(selector string) *Selection {
|
||||||
return pushStack(this, winnow(this, selector, true))
|
return s.FilterMatcher(cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not() removes elements from the Selection that match the selector string.
|
// FilterMatcher reduces the set of matched elements to those that match
|
||||||
|
// the given matcher.
|
||||||
|
// It returns a new Selection object for this subset of matching elements.
|
||||||
|
func (s *Selection) FilterMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, winnow(s, m, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not removes elements from the Selection that match the selector string.
|
||||||
// It returns a new Selection object with the matching elements removed.
|
// It returns a new Selection object with the matching elements removed.
|
||||||
func (this *Selection) Not(selector string) *Selection {
|
func (s *Selection) Not(selector string) *Selection {
|
||||||
return pushStack(this, winnow(this, selector, false))
|
return s.NotMatcher(cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterFunction() reduces the set of matched elements to those that pass the function's test.
|
// NotMatcher removes elements from the Selection that match the given matcher.
|
||||||
|
// It returns a new Selection object with the matching elements removed.
|
||||||
|
func (s *Selection) NotMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, winnow(s, m, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterFunction reduces the set of matched elements to those that pass the function's test.
|
||||||
// It returns a new Selection object for this subset of elements.
|
// It returns a new Selection object for this subset of elements.
|
||||||
func (this *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
|
func (s *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
|
||||||
return pushStack(this, winnowFunction(this, f, true))
|
return pushStack(s, winnowFunction(s, f, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not() removes elements from the Selection that pass the function's test.
|
// NotFunction removes elements from the Selection that pass the function's test.
|
||||||
// It returns a new Selection object with the matching elements removed.
|
// It returns a new Selection object with the matching elements removed.
|
||||||
func (this *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
|
func (s *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
|
||||||
return pushStack(this, winnowFunction(this, f, false))
|
return pushStack(s, winnowFunction(s, f, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterNodes() reduces the set of matched elements to those that match the specified nodes.
|
// FilterNodes reduces the set of matched elements to those that match the specified nodes.
|
||||||
// It returns a new Selection object for this subset of elements.
|
// It returns a new Selection object for this subset of elements.
|
||||||
func (this *Selection) FilterNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) FilterNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, winnowNodes(this, nodes, true))
|
return pushStack(s, winnowNodes(s, nodes, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not() removes elements from the Selection that match the specified nodes.
|
// NotNodes removes elements from the Selection that match the specified nodes.
|
||||||
// It returns a new Selection object with the matching elements removed.
|
// It returns a new Selection object with the matching elements removed.
|
||||||
func (this *Selection) NotNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) NotNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, winnowNodes(this, nodes, false))
|
return pushStack(s, winnowNodes(s, nodes, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterSelection() reduces the set of matched elements to those that match a
|
// FilterSelection reduces the set of matched elements to those that match a
|
||||||
// node in the specified Selection object.
|
// node in the specified Selection object.
|
||||||
// It returns a new Selection object for this subset of elements.
|
// It returns a new Selection object for this subset of elements.
|
||||||
func (this *Selection) FilterSelection(s *Selection) *Selection {
|
func (s *Selection) FilterSelection(sel *Selection) *Selection {
|
||||||
if s == nil {
|
if sel == nil {
|
||||||
return pushStack(this, winnowNodes(this, nil, true))
|
return pushStack(s, winnowNodes(s, nil, true))
|
||||||
}
|
}
|
||||||
return pushStack(this, winnowNodes(this, s.Nodes, true))
|
return pushStack(s, winnowNodes(s, sel.Nodes, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not() removes elements from the Selection that match a node in the specified
|
// NotSelection removes elements from the Selection that match a node in the specified
|
||||||
// Selection object.
|
// Selection object. It returns a new Selection object with the matching elements removed.
|
||||||
// It returns a new Selection object with the matching elements removed.
|
func (s *Selection) NotSelection(sel *Selection) *Selection {
|
||||||
func (this *Selection) NotSelection(s *Selection) *Selection {
|
if sel == nil {
|
||||||
if s == nil {
|
return pushStack(s, winnowNodes(s, nil, false))
|
||||||
return pushStack(this, winnowNodes(this, nil, false))
|
|
||||||
}
|
}
|
||||||
return pushStack(this, winnowNodes(this, s.Nodes, false))
|
return pushStack(s, winnowNodes(s, sel.Nodes, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intersection() is an alias for FilterSelection().
|
// Intersection is an alias for FilterSelection.
|
||||||
func (this *Selection) Intersection(s *Selection) *Selection {
|
func (s *Selection) Intersection(sel *Selection) *Selection {
|
||||||
return this.FilterSelection(s)
|
return s.FilterSelection(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has() reduces the set of matched elements to those that have a descendant
|
// Has reduces the set of matched elements to those that have a descendant
|
||||||
// that matches the selector.
|
// that matches the selector.
|
||||||
// It returns a new Selection object with the matching elements.
|
// It returns a new Selection object with the matching elements.
|
||||||
func (this *Selection) Has(selector string) *Selection {
|
func (s *Selection) Has(selector string) *Selection {
|
||||||
return this.HasSelection(this.document.Find(selector))
|
return s.HasSelection(s.document.Find(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasNodes() reduces the set of matched elements to those that have a
|
// HasMatcher reduces the set of matched elements to those that have a descendant
|
||||||
|
// that matches the matcher.
|
||||||
|
// It returns a new Selection object with the matching elements.
|
||||||
|
func (s *Selection) HasMatcher(m Matcher) *Selection {
|
||||||
|
return s.HasSelection(s.document.FindMatcher(m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNodes reduces the set of matched elements to those that have a
|
||||||
// descendant that matches one of the nodes.
|
// descendant that matches one of the nodes.
|
||||||
// It returns a new Selection object with the matching elements.
|
// It returns a new Selection object with the matching elements.
|
||||||
func (this *Selection) HasNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) HasNodes(nodes ...*html.Node) *Selection {
|
||||||
return this.FilterFunction(func(_ int, s *Selection) bool {
|
return s.FilterFunction(func(_ int, sel *Selection) bool {
|
||||||
// Add all nodes that contain one of the specified nodes
|
// Add all nodes that contain one of the specified nodes
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if s.Contains(n) {
|
if sel.Contains(n) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,40 +107,36 @@ func (this *Selection) HasNodes(nodes ...*html.Node) *Selection {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSelection() reduces the set of matched elements to those that have a
|
// HasSelection reduces the set of matched elements to those that have a
|
||||||
// descendant that matches one of the nodes of the specified Selection object.
|
// descendant that matches one of the nodes of the specified Selection object.
|
||||||
// It returns a new Selection object with the matching elements.
|
// It returns a new Selection object with the matching elements.
|
||||||
func (this *Selection) HasSelection(sel *Selection) *Selection {
|
func (s *Selection) HasSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.HasNodes()
|
return s.HasNodes()
|
||||||
}
|
}
|
||||||
return this.HasNodes(sel.Nodes...)
|
return s.HasNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// End() ends the most recent filtering operation in the current chain and
|
// End ends the most recent filtering operation in the current chain and
|
||||||
// returns the set of matched elements to its previous state.
|
// returns the set of matched elements to its previous state.
|
||||||
func (this *Selection) End() *Selection {
|
func (s *Selection) End() *Selection {
|
||||||
if this.prevSel != nil {
|
if s.prevSel != nil {
|
||||||
return this.prevSel
|
return s.prevSel
|
||||||
}
|
}
|
||||||
return newEmptySelection(this.document)
|
return newEmptySelection(s.document)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter based on a selector string, and the indicator to keep (Filter) or
|
// Filter based on the matcher, and the indicator to keep (Filter) or
|
||||||
// to get rid of (Not) the matching elements.
|
// to get rid of (Not) the matching elements.
|
||||||
func winnow(sel *Selection, selector string, keep bool) []*html.Node {
|
func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
|
||||||
cs := cascadia.MustCompile(selector)
|
|
||||||
|
|
||||||
// Optimize if keep is requested
|
// Optimize if keep is requested
|
||||||
if keep {
|
if keep {
|
||||||
return cs.Filter(sel.Nodes)
|
return m.Filter(sel.Nodes)
|
||||||
} else {
|
}
|
||||||
// Use grep
|
// Use grep
|
||||||
return grep(sel, func(i int, s *Selection) bool {
|
return grep(sel, func(i int, s *Selection) bool {
|
||||||
return !cs.Match(s.Get(0))
|
return !m.Match(s.Get(0))
|
||||||
})
|
})
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter based on an array of nodes, and the indicator to keep (Filter) or
|
// Filter based on an array of nodes, and the indicator to keep (Filter) or
|
||||||
|
|||||||
+29
-29
@@ -6,25 +6,25 @@ import (
|
|||||||
|
|
||||||
func TestFilter(t *testing.T) {
|
func TestFilter(t *testing.T) {
|
||||||
sel := Doc().Find(".span12").Filter(".alert")
|
sel := Doc().Find(".span12").Filter(".alert")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterNone(t *testing.T) {
|
func TestFilterNone(t *testing.T) {
|
||||||
sel := Doc().Find(".span12").Filter(".zzalert")
|
sel := Doc().Find(".span12").Filter(".zzalert")
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterRollback(t *testing.T) {
|
func TestFilterRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Filter(".alert").End()
|
sel2 := sel.Filter(".alert").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterFunction(t *testing.T) {
|
func TestFilterFunction(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").FilterFunction(func(i int, s *Selection) bool {
|
sel := Doc().Find(".pvk-content").FilterFunction(func(i int, s *Selection) bool {
|
||||||
return i > 0
|
return i > 0
|
||||||
})
|
})
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterFunctionRollback(t *testing.T) {
|
func TestFilterFunctionRollback(t *testing.T) {
|
||||||
@@ -32,33 +32,33 @@ func TestFilterFunctionRollback(t *testing.T) {
|
|||||||
sel2 := sel.FilterFunction(func(i int, s *Selection) bool {
|
sel2 := sel.FilterFunction(func(i int, s *Selection) bool {
|
||||||
return i > 0
|
return i > 0
|
||||||
}).End()
|
}).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterNode(t *testing.T) {
|
func TestFilterNode(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.FilterNodes(sel.Nodes[2])
|
sel2 := sel.FilterNodes(sel.Nodes[2])
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterNodeRollback(t *testing.T) {
|
func TestFilterNodeRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.FilterNodes(sel.Nodes[2]).End()
|
sel2 := sel.FilterNodes(sel.Nodes[2]).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterSelection(t *testing.T) {
|
func TestFilterSelection(t *testing.T) {
|
||||||
sel := Doc().Find(".link")
|
sel := Doc().Find(".link")
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
sel3 := sel.FilterSelection(sel2)
|
sel3 := sel.FilterSelection(sel2)
|
||||||
AssertLength(t, sel3.Nodes, 1)
|
assertLength(t, sel3.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterSelectionRollback(t *testing.T) {
|
func TestFilterSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".link")
|
sel := Doc().Find(".link")
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
sel2 = sel.FilterSelection(sel2).End()
|
sel2 = sel.FilterSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilterSelectionNil(t *testing.T) {
|
func TestFilterSelectionNil(t *testing.T) {
|
||||||
@@ -66,30 +66,30 @@ func TestFilterSelectionNil(t *testing.T) {
|
|||||||
|
|
||||||
sel := Doc().Find(".link")
|
sel := Doc().Find(".link")
|
||||||
sel3 := sel.FilterSelection(sel2)
|
sel3 := sel.FilterSelection(sel2)
|
||||||
AssertLength(t, sel3.Nodes, 0)
|
assertLength(t, sel3.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNot(t *testing.T) {
|
func TestNot(t *testing.T) {
|
||||||
sel := Doc().Find(".span12").Not(".alert")
|
sel := Doc().Find(".span12").Not(".alert")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotRollback(t *testing.T) {
|
func TestNotRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".span12")
|
sel := Doc().Find(".span12")
|
||||||
sel2 := sel.Not(".alert").End()
|
sel2 := sel.Not(".alert").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotNone(t *testing.T) {
|
func TestNotNone(t *testing.T) {
|
||||||
sel := Doc().Find(".span12").Not(".zzalert")
|
sel := Doc().Find(".span12").Not(".zzalert")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotFunction(t *testing.T) {
|
func TestNotFunction(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").NotFunction(func(i int, s *Selection) bool {
|
sel := Doc().Find(".pvk-content").NotFunction(func(i int, s *Selection) bool {
|
||||||
return i > 0
|
return i > 0
|
||||||
})
|
})
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotFunctionRollback(t *testing.T) {
|
func TestNotFunctionRollback(t *testing.T) {
|
||||||
@@ -97,65 +97,65 @@ func TestNotFunctionRollback(t *testing.T) {
|
|||||||
sel2 := sel.NotFunction(func(i int, s *Selection) bool {
|
sel2 := sel.NotFunction(func(i int, s *Selection) bool {
|
||||||
return i > 0
|
return i > 0
|
||||||
}).End()
|
}).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotNode(t *testing.T) {
|
func TestNotNode(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.NotNodes(sel.Nodes[2])
|
sel2 := sel.NotNodes(sel.Nodes[2])
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotNodeRollback(t *testing.T) {
|
func TestNotNodeRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.NotNodes(sel.Nodes[2]).End()
|
sel2 := sel.NotNodes(sel.Nodes[2]).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotSelection(t *testing.T) {
|
func TestNotSelection(t *testing.T) {
|
||||||
sel := Doc().Find(".link")
|
sel := Doc().Find(".link")
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
sel3 := sel.NotSelection(sel2)
|
sel3 := sel.NotSelection(sel2)
|
||||||
AssertLength(t, sel3.Nodes, 6)
|
assertLength(t, sel3.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotSelectionRollback(t *testing.T) {
|
func TestNotSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".link")
|
sel := Doc().Find(".link")
|
||||||
sel2 := Doc().Find("a[ng-click]")
|
sel2 := Doc().Find("a[ng-click]")
|
||||||
sel2 = sel.NotSelection(sel2).End()
|
sel2 = sel.NotSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntersection(t *testing.T) {
|
func TestIntersection(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter")
|
sel := Doc().Find(".pvk-gutter")
|
||||||
sel2 := Doc().Find("div").Intersection(sel)
|
sel2 := Doc().Find("div").Intersection(sel)
|
||||||
AssertLength(t, sel2.Nodes, 6)
|
assertLength(t, sel2.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntersectionRollback(t *testing.T) {
|
func TestIntersectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter")
|
sel := Doc().Find(".pvk-gutter")
|
||||||
sel2 := Doc().Find("div")
|
sel2 := Doc().Find("div")
|
||||||
sel2 = sel.Intersection(sel2).End()
|
sel2 = sel.Intersection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHas(t *testing.T) {
|
func TestHas(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Has(".center-content")
|
sel := Doc().Find(".container-fluid").Has(".center-content")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasRollback(t *testing.T) {
|
func TestHasRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.Has(".center-content").End()
|
sel2 := sel.Has(".center-content").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasNodes(t *testing.T) {
|
func TestHasNodes(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".center-content")
|
sel2 := Doc().Find(".center-content")
|
||||||
sel = sel.HasNodes(sel2.Nodes...)
|
sel = sel.HasNodes(sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,29 +163,29 @@ func TestHasNodesRollback(t *testing.T) {
|
|||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".center-content")
|
sel2 := Doc().Find(".center-content")
|
||||||
sel2 = sel.HasNodes(sel2.Nodes...).End()
|
sel2 = sel.HasNodes(sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasSelection(t *testing.T) {
|
func TestHasSelection(t *testing.T) {
|
||||||
sel := Doc().Find("p")
|
sel := Doc().Find("p")
|
||||||
sel2 := Doc().Find("small")
|
sel2 := Doc().Find("small")
|
||||||
sel = sel.HasSelection(sel2)
|
sel = sel.HasSelection(sel2)
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasSelectionRollback(t *testing.T) {
|
func TestHasSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find("p")
|
sel := Doc().Find("p")
|
||||||
sel2 := Doc().Find("small")
|
sel2 := Doc().Find("small")
|
||||||
sel2 = sel.HasSelection(sel2).End()
|
sel2 = sel.HasSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnd(t *testing.T) {
|
func TestEnd(t *testing.T) {
|
||||||
sel := Doc().Find("p").Has("small").End()
|
sel := Doc().Find("p").Has("small").End()
|
||||||
AssertLength(t, sel.Nodes, 4)
|
assertLength(t, sel.Nodes, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEndToTop(t *testing.T) {
|
func TestEndToTop(t *testing.T) {
|
||||||
sel := Doc().Find("p").Has("small").End().End().End()
|
sel := Doc().Find("p").Has("small").End().End().End()
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-17
@@ -1,32 +1,32 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
// Each() iterates over a Selection object, executing a function for each
|
// Each iterates over a Selection object, executing a function for each
|
||||||
// matched element. It returns the current Selection object.
|
// matched element. It returns the current Selection object.
|
||||||
func (this *Selection) Each(f func(int, *Selection)) *Selection {
|
func (s *Selection) Each(f func(int, *Selection)) *Selection {
|
||||||
for i, n := range this.Nodes {
|
for i, n := range s.Nodes {
|
||||||
f(i, newSingleSelection(n, this.document))
|
f(i, newSingleSelection(n, s.document))
|
||||||
}
|
}
|
||||||
return this
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// EachWithBreak() iterates over a Selection object, executing a function for each
|
// EachWithBreak iterates over a Selection object, executing a function for each
|
||||||
// matched element. It is identical to `Each()` except that it is possible to break
|
// matched element. It is identical to Each except that it is possible to break
|
||||||
// out of the loop by returning `false` in the callback function. It returns the
|
// out of the loop by returning false in the callback function. It returns the
|
||||||
// current Selection object.
|
// current Selection object.
|
||||||
func (this *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
|
func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
|
||||||
for i, n := range this.Nodes {
|
for i, n := range s.Nodes {
|
||||||
if !f(i, newSingleSelection(n, this.document)) {
|
if !f(i, newSingleSelection(n, s.document)) {
|
||||||
return this
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map() passes each element in the current matched set through a function,
|
// Map passes each element in the current matched set through a function,
|
||||||
// producing a slice of string holding the returned values.
|
// producing a slice of string holding the returned values.
|
||||||
func (this *Selection) Map(f func(int, *Selection) string) (result []string) {
|
func (s *Selection) Map(f func(int, *Selection) string) (result []string) {
|
||||||
for i, n := range this.Nodes {
|
for i, n := range s.Nodes {
|
||||||
result = append(result, f(i, newSingleSelection(n, this.document)))
|
result = append(result, f(i, newSingleSelection(n, s.document)))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
+24
-4
@@ -1,8 +1,9 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEach(t *testing.T) {
|
func TestEach(t *testing.T) {
|
||||||
@@ -16,7 +17,7 @@ func TestEach(t *testing.T) {
|
|||||||
if cnt != 4 {
|
if cnt != 4 {
|
||||||
t.Errorf("Expected Each() to call function 4 times, got %v times.", cnt)
|
t.Errorf("Expected Each() to call function 4 times, got %v times.", cnt)
|
||||||
}
|
}
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEachWithBreak(t *testing.T) {
|
func TestEachWithBreak(t *testing.T) {
|
||||||
@@ -31,7 +32,7 @@ func TestEachWithBreak(t *testing.T) {
|
|||||||
if cnt != 1 {
|
if cnt != 1 {
|
||||||
t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt)
|
t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt)
|
||||||
}
|
}
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEachEmptySelection(t *testing.T) {
|
func TestEachEmptySelection(t *testing.T) {
|
||||||
@@ -45,7 +46,7 @@ func TestEachEmptySelection(t *testing.T) {
|
|||||||
t.Error("Expected Each() to not be called on empty Selection.")
|
t.Error("Expected Each() to not be called on empty Selection.")
|
||||||
}
|
}
|
||||||
sel2 := sel.Find("div")
|
sel2 := sel.Find("div")
|
||||||
AssertLength(t, sel2.Nodes, 0)
|
assertLength(t, sel2.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMap(t *testing.T) {
|
func TestMap(t *testing.T) {
|
||||||
@@ -66,3 +67,22 @@ func TestMap(t *testing.T) {
|
|||||||
t.Errorf("Expected Map array result to have a length of 3, found %v.", len(vals))
|
t.Errorf("Expected Map array result to have a length of 3, found %v.", len(vals))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForRange(t *testing.T) {
|
||||||
|
sel := Doc().Find(".pvk-content")
|
||||||
|
initLen := sel.Length()
|
||||||
|
for i := range sel.Nodes {
|
||||||
|
single := sel.Eq(i)
|
||||||
|
//h, err := single.Html()
|
||||||
|
//if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
//}
|
||||||
|
//fmt.Println(i, h)
|
||||||
|
if single.Length() != 1 {
|
||||||
|
t.Errorf("%d: expected length of 1, got %d", i, single.Length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sel.Length() != initLen {
|
||||||
|
t.Errorf("expected initial selection to still have length %d, got %d", initLen, sel.Length())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+257
@@ -0,0 +1,257 @@
|
|||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.google.com/p/cascadia"
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
// After applies the selector from the root document and inserts the matched elements
|
||||||
|
// after the elements in the set of matched elements.
|
||||||
|
//
|
||||||
|
// If one of the matched elements in the selection is not currently in the
|
||||||
|
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||||
|
//
|
||||||
|
// This follows the same rules outlined in Selection.Append.
|
||||||
|
func (s *Selection) After(selector string) *Selection {
|
||||||
|
return s.AfterMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterMatcher applies the matcher from the root document and inserts the matched elements
|
||||||
|
// after the elements in the set of matched elements.
|
||||||
|
//
|
||||||
|
// If one of the matched elements in the selection is not currently in the
|
||||||
|
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||||
|
//
|
||||||
|
// This follows the same rules outlined in Selection.Append.
|
||||||
|
func (s *Selection) AfterMatcher(m Matcher) *Selection {
|
||||||
|
return s.AfterNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterSelection inserts the elements in the selection after each element in the set of matched
|
||||||
|
// elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules outlined in Selection.Append.
|
||||||
|
func (s *Selection) AfterSelection(sel *Selection) *Selection {
|
||||||
|
return s.AfterNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterHtml parses the html and inserts it after the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules outlined in Selection.Append.
|
||||||
|
func (s *Selection) AfterHtml(html string) *Selection {
|
||||||
|
return s.AfterNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AfterNodes inserts the nodes after each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules outlined in Selection.Append.
|
||||||
|
func (s *Selection) AfterNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
|
||||||
|
if sn.Parent != nil {
|
||||||
|
sn.Parent.InsertBefore(n, sn.NextSibling)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append appends the elements specified by the selector to the end of each element
|
||||||
|
// in the set of matched elements, following those rules:
|
||||||
|
//
|
||||||
|
// 1) The selector is applied to the root document.
|
||||||
|
//
|
||||||
|
// 2) Elements that are part of the document will be moved to the new location.
|
||||||
|
//
|
||||||
|
// 3) If there are multiple locations to append to, cloned nodes will be
|
||||||
|
// appended to all target locations except the last one, which will be moved
|
||||||
|
// as noted in (2).
|
||||||
|
func (s *Selection) Append(selector string) *Selection {
|
||||||
|
return s.AppendMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendMatcher appends the elements specified by the matcher to the end of each element
|
||||||
|
// in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendMatcher(m Matcher) *Selection {
|
||||||
|
return s.AppendNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendSelection appends the elements in the selection to the end of each element
|
||||||
|
// in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendSelection(sel *Selection) *Selection {
|
||||||
|
return s.AppendNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendHtml parses the html and appends it to the set of matched elements.
|
||||||
|
func (s *Selection) AppendHtml(html string) *Selection {
|
||||||
|
return s.AppendNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AppendNodes appends the specified nodes to each node in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) AppendNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
|
||||||
|
sn.AppendChild(n)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Before inserts the matched elements before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) Before(selector string) *Selection {
|
||||||
|
return s.BeforeMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeMatcher inserts the matched elements before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeMatcher(m Matcher) *Selection {
|
||||||
|
return s.BeforeNodes(m.MatchAll(s.document.rootNode)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeSelection inserts the elements in the selection before each element in the set of matched
|
||||||
|
// elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeSelection(sel *Selection) *Selection {
|
||||||
|
return s.BeforeNodes(sel.Nodes...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeHtml parses the html and inserts it before the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeHtml(html string) *Selection {
|
||||||
|
return s.BeforeNodes(parseHtml(html)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeforeNodes inserts the nodes before each element in the set of matched elements.
|
||||||
|
//
|
||||||
|
// This follows the same rules as Selection.Append.
|
||||||
|
func (s *Selection) BeforeNodes(ns ...*html.Node) *Selection {
|
||||||
|
return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
|
||||||
|
if sn.Parent != nil {
|
||||||
|
sn.Parent.InsertBefore(n, sn)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone creates a deep copy of the set of matched nodes. The new nodes will not be
|
||||||
|
// attached to the document.
|
||||||
|
func (s *Selection) Clone() *Selection {
|
||||||
|
ns := newEmptySelection(s.document)
|
||||||
|
ns.Nodes = cloneNodes(s.Nodes)
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty removes all children nodes from the set of matched elements.
|
||||||
|
// It returns the children nodes in a new Selection.
|
||||||
|
func (s *Selection) Empty() *Selection {
|
||||||
|
var nodes []*html.Node
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
for c := n.FirstChild; c != nil; c = n.FirstChild {
|
||||||
|
n.RemoveChild(c)
|
||||||
|
nodes = append(nodes, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pushStack(s, nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes the set of matched elements from the document.
|
||||||
|
// It returns the same selection, now consisting of nodes not in the document.
|
||||||
|
func (s *Selection) Remove() *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
if n.Parent != nil {
|
||||||
|
n.Parent.RemoveChild(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveFiltered removes the set of matched elements by selector.
|
||||||
|
// It returns the Selection of removed nodes.
|
||||||
|
func (s *Selection) RemoveFiltered(selector string) *Selection {
|
||||||
|
return s.RemoveMatcher(cascadia.MustCompile(selector))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveMatcher removes the set of matched elements.
|
||||||
|
// It returns the Selection of removed nodes.
|
||||||
|
func (s *Selection) RemoveMatcher(m Matcher) *Selection {
|
||||||
|
return s.FilterMatcher(m).Remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHtml(h string) []*html.Node {
|
||||||
|
// Errors are only returned when the io.Reader returns any error besides
|
||||||
|
// EOF, but strings.Reader never will
|
||||||
|
nodes, err := html.ParseFragment(strings.NewReader(h), &html.Node{Type: html.ElementNode})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("goquery: failed to parse HTML: %s", err))
|
||||||
|
}
|
||||||
|
return nodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy a slice of nodes.
|
||||||
|
func cloneNodes(ns []*html.Node) []*html.Node {
|
||||||
|
cns := make([]*html.Node, 0, len(ns))
|
||||||
|
|
||||||
|
for _, n := range ns {
|
||||||
|
cns = append(cns, cloneNode(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cns
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy a node. The new node has clones of all the original node's
|
||||||
|
// children but none of its parents or siblings.
|
||||||
|
func cloneNode(n *html.Node) *html.Node {
|
||||||
|
nn := &html.Node{
|
||||||
|
Type: n.Type,
|
||||||
|
DataAtom: n.DataAtom,
|
||||||
|
Data: n.Data,
|
||||||
|
Attr: make([]html.Attribute, len(n.Attr)),
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(nn.Attr, n.Attr)
|
||||||
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
|
nn.AppendChild(cloneNode(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Selection) manipulateNodes(ns []*html.Node, reverse bool,
|
||||||
|
f func(sn *html.Node, n *html.Node)) *Selection {
|
||||||
|
|
||||||
|
lasti := s.Size() - 1
|
||||||
|
|
||||||
|
// net.Html doesn't provide document fragments for insertion, so to get
|
||||||
|
// things in the correct order with After() and Prepend(), the callback
|
||||||
|
// needs to be called on the reverse of the nodes.
|
||||||
|
if reverse {
|
||||||
|
for i, j := 0, len(ns)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
ns[i], ns[j] = ns[j], ns[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, sn := range s.Nodes {
|
||||||
|
for _, n := range ns {
|
||||||
|
if i != lasti {
|
||||||
|
f(sn, cloneNode(n))
|
||||||
|
} else {
|
||||||
|
if n.Parent != nil {
|
||||||
|
n.Parent.RemoveChild(n)
|
||||||
|
}
|
||||||
|
f(sn, n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
package goquery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAfter(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main + #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterMany(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find(".one").After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find(".one + #nf6").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterWithRemoved(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Remove()
|
||||||
|
s.After("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, s.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AfterSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main + #nf1, #nf1 + #nf2").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAfterHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AfterHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main + strong").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppend(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").Append("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendBody(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("body").Append("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf6").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AppendSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf2").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendSelectionExisting(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").AppendSelection(doc.Find("#n1, #n2"))
|
||||||
|
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(1)"), "three")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(5)"), "one")
|
||||||
|
assertClass(t, doc.Find("#main :nth-child(6)"), "two")
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendClone(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#n1").AppendSelection(doc.Find("#nf1").Clone())
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 1)
|
||||||
|
assertLength(t, doc.Find("#main #nf1").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAppendHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("div").AppendHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("strong").Nodes, 14)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBefore(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").Before("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf6:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeWithRemoved(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Remove()
|
||||||
|
s.Before("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, s.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeSelection(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").BeforeSelection(doc.Find("#nf1, #nf2"))
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main #nf1, #main #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("#foot #nf1, #foot #nf2").Nodes, 0)
|
||||||
|
assertLength(t, doc.Find("body > #nf1:first-child, #nf1 + #nf2").Nodes, 2)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBeforeHtml(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#main").BeforeHtml("<strong>new node</strong>")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("body > strong:first-child").Nodes, 1)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmpty(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
s := doc.Find("#main").Empty()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#main").Children().Nodes, 0)
|
||||||
|
assertLength(t, s.Filter("div").Nodes, 6)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemove(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("#nf1").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#foot #nf1").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("*").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("*").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveRoot(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
doc.Find("html").Remove()
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("html").Nodes, 0)
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveFiltered(t *testing.T) {
|
||||||
|
doc := Doc2Clone()
|
||||||
|
nf6 := doc.Find("#nf6")
|
||||||
|
s := doc.Find("div").RemoveFiltered("#nf6")
|
||||||
|
|
||||||
|
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||||
|
assertLength(t, s.Nodes, 1)
|
||||||
|
if nf6.Nodes[0] != s.Nodes[0] {
|
||||||
|
t.Error("Removed node does not match original")
|
||||||
|
}
|
||||||
|
printSel(t, doc.Selection)
|
||||||
|
}
|
||||||
Executable
+37
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Copyright 2012 The Go Authors. All rights reserved.
|
||||||
|
# Use of this source code is governed by a BSD-style
|
||||||
|
# license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
# git gofmt pre-commit hook
|
||||||
|
#
|
||||||
|
# To use, store as .git/hooks/pre-commit inside your repository and make sure
|
||||||
|
# it has execute permissions.
|
||||||
|
#
|
||||||
|
# This script does not handle file names that contain spaces.
|
||||||
|
|
||||||
|
# golint is purely informational, it doesn't fail with exit code != 0 if it finds something,
|
||||||
|
# because it may find a lot of false positives. Just print out its result for information.
|
||||||
|
echo "lint result (informational only):"
|
||||||
|
golint .
|
||||||
|
|
||||||
|
# go vet returns 1 if an error was found. Exit the hook with this exit code.
|
||||||
|
go vet ./...
|
||||||
|
vetres=$?
|
||||||
|
|
||||||
|
# Check for gofmt problems and report if any.
|
||||||
|
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '.go$')
|
||||||
|
[ -z "$gofiles" ] && echo "EXIT $vetres" && exit $vetres
|
||||||
|
|
||||||
|
unformatted=$(gofmt -l $gofiles)
|
||||||
|
[ -z "$unformatted" ] && echo "EXIT $vetres" && exit $vetres
|
||||||
|
|
||||||
|
# Some files are not gofmt'd. Print message and fail.
|
||||||
|
|
||||||
|
echo >&2 "Go files must be formatted with gofmt. Please run:"
|
||||||
|
for fn in $unformatted; do
|
||||||
|
echo >&2 " gofmt -w $PWD/$fn"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "EXIT 1"
|
||||||
|
exit 1
|
||||||
+196
-27
@@ -2,50 +2,75 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.google.com/p/go.net/html"
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Attr() gets the specified attribute's value for the first element in the
|
var rxClassTrim = regexp.MustCompile("[\t\r\n]")
|
||||||
|
|
||||||
|
// Attr gets the specified attribute's value for the first element in the
|
||||||
// Selection. To get the value for each element individually, use a looping
|
// Selection. To get the value for each element individually, use a looping
|
||||||
// construct such as Each() or Map() method.
|
// construct such as Each or Map method.
|
||||||
func (this *Selection) Attr(attrName string) (val string, exists bool) {
|
func (s *Selection) Attr(attrName string) (val string, exists bool) {
|
||||||
if len(this.Nodes) == 0 {
|
if len(s.Nodes) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return getAttributeValue(attrName, this.Nodes[0])
|
return getAttributeValue(attrName, s.Nodes[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text() gets the combined text contents of each element in the set of matched
|
// RemoveAttr removes the named attribute from each element in the set of matched elements.
|
||||||
|
func (s *Selection) RemoveAttr(attrName string) *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
removeAttr(n, attrName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAttr sets the given attribute on each element in the set of matched elements.
|
||||||
|
func (s *Selection) SetAttr(attrName, val string) *Selection {
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
if attr := getAttributePtr(attrName, n); attr != nil {
|
||||||
|
attr.Val = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text gets the combined text contents of each element in the set of matched
|
||||||
// elements, including their descendants.
|
// elements, including their descendants.
|
||||||
func (this *Selection) Text() string {
|
func (s *Selection) Text() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
// Slightly optimized vs calling Each(): no single selection object created
|
// Slightly optimized vs calling Each: no single selection object created
|
||||||
for _, n := range this.Nodes {
|
for _, n := range s.Nodes {
|
||||||
buf.WriteString(getNodeText(n))
|
buf.WriteString(getNodeText(n))
|
||||||
}
|
}
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size() is an alias for Length().
|
// Size is an alias for Length.
|
||||||
func (this *Selection) Size() int {
|
func (s *Selection) Size() int {
|
||||||
return this.Length()
|
return s.Length()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length() returns the number of elements in the Selection object.
|
// Length returns the number of elements in the Selection object.
|
||||||
func (this *Selection) Length() int {
|
func (s *Selection) Length() int {
|
||||||
return len(this.Nodes)
|
return len(s.Nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Html() gets the HTML contents of the first element in the set of matched
|
// Html gets the HTML contents of the first element in the set of matched
|
||||||
// elements. It includes text and comment nodes.
|
// elements. It includes text and comment nodes.
|
||||||
func (this *Selection) Html() (ret string, e error) {
|
func (s *Selection) Html() (ret string, e error) {
|
||||||
// Since there is no .innerHtml, the HTML content must be re-created from
|
// Since there is no .innerHtml, the HTML content must be re-created from
|
||||||
// the nodes usint html.Render().
|
// the nodes using html.Render.
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
if len(this.Nodes) > 0 {
|
if len(s.Nodes) > 0 {
|
||||||
for c := this.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
|
for c := s.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
|
||||||
e = html.Render(&buf, c)
|
e = html.Render(&buf, c)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return
|
return
|
||||||
@@ -57,6 +82,97 @@ func (this *Selection) Html() (ret string, e error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddClass adds the given class(es) to each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space.
|
||||||
|
func (s *Selection) AddClass(class string) *Selection {
|
||||||
|
if class == "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
slClasses := getClassesSlice(class)
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
curClasses, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, newClass := range slClasses {
|
||||||
|
if strings.Index(curClasses, " "+newClass+" ") == -1 {
|
||||||
|
curClasses += newClass + " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, curClasses)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasClass determines whether any of the matched elements are assigned the
|
||||||
|
// given class.
|
||||||
|
func (s *Selection) HasClass(class string) bool {
|
||||||
|
class = " " + class + " "
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
classes, _ := getClassesAndAttr(n, false)
|
||||||
|
if strings.Index(classes, class) > -1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveClass removes the given class(es) from each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
||||||
|
// If no class name is provided, all classes are removed.
|
||||||
|
func (s *Selection) RemoveClass(class ...string) *Selection {
|
||||||
|
var rclasses []string
|
||||||
|
|
||||||
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
||||||
|
remove := classStr == ""
|
||||||
|
|
||||||
|
if !remove {
|
||||||
|
rclasses = getClassesSlice(classStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
if remove {
|
||||||
|
removeAttr(n, "class")
|
||||||
|
} else {
|
||||||
|
classes, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, rcl := range rclasses {
|
||||||
|
classes = strings.Replace(classes, " "+rcl+" ", " ", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, classes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleClass adds or removes the given class(es) for each element in the set of matched elements.
|
||||||
|
// Multiple class names can be specified, separated by a space or via multiple arguments.
|
||||||
|
func (s *Selection) ToggleClass(class ...string) *Selection {
|
||||||
|
classStr := strings.TrimSpace(strings.Join(class, " "))
|
||||||
|
|
||||||
|
if classStr == "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
tcls := getClassesSlice(classStr)
|
||||||
|
|
||||||
|
for _, n := range s.Nodes {
|
||||||
|
classes, attr := getClassesAndAttr(n, true)
|
||||||
|
for _, tcl := range tcls {
|
||||||
|
if strings.Index(classes, " "+tcl+" ") != -1 {
|
||||||
|
classes = strings.Replace(classes, " "+tcl+" ", " ", -1)
|
||||||
|
} else {
|
||||||
|
classes += tcl + " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setClasses(n, attr, classes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
// Get the specified node's text content.
|
// Get the specified node's text content.
|
||||||
func getNodeText(node *html.Node) string {
|
func getNodeText(node *html.Node) string {
|
||||||
if node.Type == html.TextNode {
|
if node.Type == html.TextNode {
|
||||||
@@ -73,18 +189,71 @@ func getNodeText(node *html.Node) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private function to get the specified attribute's value from a node.
|
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
|
||||||
func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
|
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, a := range n.Attr {
|
for i, a := range n.Attr {
|
||||||
if a.Key == attrName {
|
if a.Key == attrName {
|
||||||
|
return &n.Attr[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private function to get the specified attribute's value from a node.
|
||||||
|
func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
|
||||||
|
if a := getAttributePtr(attrName, n); a != nil {
|
||||||
val = a.Val
|
val = a.Val
|
||||||
exists = true
|
exists = true
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get and normalize the "class" attribute from the node.
|
||||||
|
func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.Attribute) {
|
||||||
|
// Applies only to element nodes
|
||||||
|
if n.Type == html.ElementNode {
|
||||||
|
attr = getAttributePtr("class", n)
|
||||||
|
if attr == nil && create {
|
||||||
|
n.Attr = append(n.Attr, html.Attribute{
|
||||||
|
Key: "class",
|
||||||
|
Val: "",
|
||||||
|
})
|
||||||
|
attr = &n.Attr[len(n.Attr)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if attr == nil {
|
||||||
|
classes = " "
|
||||||
|
} else {
|
||||||
|
classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getClassesSlice(classes string) []string {
|
||||||
|
return strings.Split(rxClassTrim.ReplaceAllString(" "+classes+" ", " "), " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeAttr(n *html.Node, attrName string) {
|
||||||
|
for i, a := range n.Attr {
|
||||||
|
if a.Key == attrName {
|
||||||
|
n.Attr[i], n.Attr[len(n.Attr)-1], n.Attr =
|
||||||
|
n.Attr[len(n.Attr)-1], html.Attribute{}, n.Attr[:len(n.Attr)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setClasses(n *html.Node, attr *html.Attribute, classes string) {
|
||||||
|
classes = strings.TrimSpace(classes)
|
||||||
|
if classes == "" {
|
||||||
|
removeAttr(n, "class")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.Val = classes
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,32 @@ func TestAttrNotExist(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveAttr(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("div")
|
||||||
|
|
||||||
|
sel.RemoveAttr("id")
|
||||||
|
|
||||||
|
_, ok := sel.Attr("id")
|
||||||
|
if ok {
|
||||||
|
t.Error("Expected there to be no id attributes set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAttr(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
|
||||||
|
sel.SetAttr("id", "not-main")
|
||||||
|
|
||||||
|
val, ok := sel.Attr("id")
|
||||||
|
if !ok {
|
||||||
|
t.Error("Expected an id attribute on main")
|
||||||
|
}
|
||||||
|
|
||||||
|
if val != "not-main" {
|
||||||
|
t.Errorf("Expected an attribute id to be not-main, got %s", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestText(t *testing.T) {
|
func TestText(t *testing.T) {
|
||||||
txt := Doc().Find("h1").Text()
|
txt := Doc().Find("h1").Text()
|
||||||
if strings.Trim(txt, " \n\r\t") != "Provok.in" {
|
if strings.Trim(txt, " \n\r\t") != "Provok.in" {
|
||||||
@@ -61,3 +87,138 @@ func TestHtml(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNbsp(t *testing.T) {
|
||||||
|
src := `<p>Some text</p>`
|
||||||
|
d, err := NewDocumentFromReader(strings.NewReader(src))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
txt := d.Find("p").Text()
|
||||||
|
ix := strings.Index(txt, "\u00a0")
|
||||||
|
if ix != 4 {
|
||||||
|
t.Errorf("Text: expected a non-breaking space at index 4, got %d", ix)
|
||||||
|
}
|
||||||
|
|
||||||
|
h, err := d.Find("p").Html()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
ix = strings.Index(h, "\u00a0")
|
||||||
|
if ix != 4 {
|
||||||
|
t.Errorf("Html: expected a non-breaking space at index 4, got %d", ix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("main main main")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if a, ok := sel.Attr("class"); !ok || a != "main" {
|
||||||
|
t.Error("Expected #main to have class main")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClassSimilar(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf5")
|
||||||
|
sel.AddClass("odd")
|
||||||
|
|
||||||
|
assertClass(t, sel, "odd")
|
||||||
|
assertClass(t, sel, "odder")
|
||||||
|
printSel(t, sel.Parent())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddEmptyClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Errorf("Expected #main to not to have a class, have: %s", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddClasses(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#main")
|
||||||
|
sel.AddClass("a b")
|
||||||
|
|
||||||
|
// Make sure that class was only added once
|
||||||
|
if !sel.HasClass("a") || !sel.HasClass("b") {
|
||||||
|
t.Errorf("#main does not have classes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClass(t *testing.T) {
|
||||||
|
sel := Doc().Find("div")
|
||||||
|
if !sel.HasClass("span12") {
|
||||||
|
t.Error("Expected at least one div to have class span12.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClassNone(t *testing.T) {
|
||||||
|
sel := Doc().Find("h2")
|
||||||
|
if sel.HasClass("toto") {
|
||||||
|
t.Error("Expected h1 to have no class.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasClassNotFirst(t *testing.T) {
|
||||||
|
sel := Doc().Find(".alert")
|
||||||
|
if !sel.HasClass("alert-error") {
|
||||||
|
t.Error("Expected .alert to also have class .alert-error.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
sel.RemoveClass("one row")
|
||||||
|
|
||||||
|
if !sel.HasClass("even") || sel.HasClass("one") || sel.HasClass("row") {
|
||||||
|
classes, _ := sel.Attr("class")
|
||||||
|
t.Error("Expected #nf1 to have class even, has ", classes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveClassSimilar(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf5, #nf6")
|
||||||
|
assertLength(t, sel.Nodes, 2)
|
||||||
|
|
||||||
|
sel.RemoveClass("odd")
|
||||||
|
assertClass(t, sel.Eq(0), "odder")
|
||||||
|
printSel(t, sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveAllClasses(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
sel.RemoveClass()
|
||||||
|
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Error("All classes were not removed, has ", a)
|
||||||
|
}
|
||||||
|
|
||||||
|
sel = Doc2Clone().Find("#main")
|
||||||
|
sel.RemoveClass()
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Error("All classes were not removed, has ", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToggleClass(t *testing.T) {
|
||||||
|
sel := Doc2Clone().Find("#nf1")
|
||||||
|
|
||||||
|
sel.ToggleClass("one")
|
||||||
|
if sel.HasClass("one") {
|
||||||
|
t.Error("Expected #nf1 to not have class one")
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.ToggleClass("one")
|
||||||
|
if !sel.HasClass("one") {
|
||||||
|
t.Error("Expected #nf1 to have class one")
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.ToggleClass("one even row")
|
||||||
|
if a, ok := sel.Attr("class"); ok {
|
||||||
|
t.Errorf("Expected #nf1 to have no classes, have %q", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,70 +2,55 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/cascadia"
|
"code.google.com/p/cascadia"
|
||||||
"code.google.com/p/go.net/html"
|
"golang.org/x/net/html"
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var rxClassTrim = regexp.MustCompile("[\t\r\n]")
|
// Is checks the current matched set of elements against a selector and
|
||||||
|
|
||||||
// Is() checks the current matched set of elements against a selector and
|
|
||||||
// returns true if at least one of these elements matches.
|
// returns true if at least one of these elements matches.
|
||||||
func (this *Selection) Is(selector string) bool {
|
func (s *Selection) Is(selector string) bool {
|
||||||
if len(this.Nodes) > 0 {
|
if len(s.Nodes) > 0 {
|
||||||
// Attempt a match with the selector
|
return s.IsMatcher(cascadia.MustCompile(selector))
|
||||||
cs := cascadia.MustCompile(selector)
|
|
||||||
if len(this.Nodes) == 1 {
|
|
||||||
return cs.Match(this.Nodes[0])
|
|
||||||
} else {
|
|
||||||
return len(cs.Filter(this.Nodes)) > 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFunction() checks the current matched set of elements against a predicate and
|
// IsMatcher checks the current matched set of elements against a matcher and
|
||||||
// returns true if at least one of these elements matches.
|
// returns true if at least one of these elements matches.
|
||||||
func (this *Selection) IsFunction(f func(int, *Selection) bool) bool {
|
func (s *Selection) IsMatcher(m Matcher) bool {
|
||||||
return this.FilterFunction(f).Length() > 0
|
if len(s.Nodes) > 0 {
|
||||||
}
|
if len(s.Nodes) == 1 {
|
||||||
|
return m.Match(s.Nodes[0])
|
||||||
|
}
|
||||||
|
return len(m.Filter(s.Nodes)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
// IsSelection() checks the current matched set of elements against a Selection object
|
|
||||||
// and returns true if at least one of these elements matches.
|
|
||||||
func (this *Selection) IsSelection(s *Selection) bool {
|
|
||||||
return this.FilterSelection(s).Length() > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsNodes() checks the current matched set of elements against the specified nodes
|
|
||||||
// and returns true if at least one of these elements matches.
|
|
||||||
func (this *Selection) IsNodes(nodes ...*html.Node) bool {
|
|
||||||
return this.FilterNodes(nodes...).Length() > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasClass() determines whether any of the matched elements are assigned the
|
|
||||||
// given class.
|
|
||||||
func (this *Selection) HasClass(class string) bool {
|
|
||||||
class = " " + class + " "
|
|
||||||
for _, n := range this.Nodes {
|
|
||||||
// Applies only to element nodes
|
|
||||||
if n.Type == html.ElementNode {
|
|
||||||
if elClass, ok := getAttributeValue("class", n); ok {
|
|
||||||
elClass = rxClassTrim.ReplaceAllString(" "+elClass+" ", " ")
|
|
||||||
if strings.Index(elClass, class) > -1 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains() returns true if the specified Node is within,
|
// IsFunction checks the current matched set of elements against a predicate and
|
||||||
|
// returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsFunction(f func(int, *Selection) bool) bool {
|
||||||
|
return s.FilterFunction(f).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSelection checks the current matched set of elements against a Selection object
|
||||||
|
// and returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsSelection(sel *Selection) bool {
|
||||||
|
return s.FilterSelection(sel).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNodes checks the current matched set of elements against the specified nodes
|
||||||
|
// and returns true if at least one of these elements matches.
|
||||||
|
func (s *Selection) IsNodes(nodes ...*html.Node) bool {
|
||||||
|
return s.FilterNodes(nodes...).Length() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains returns true if the specified Node is within,
|
||||||
// at any depth, one of the nodes in the Selection object.
|
// at any depth, one of the nodes in the Selection object.
|
||||||
// It is NOT inclusive, to behave like jQuery's implementation, and
|
// It is NOT inclusive, to behave like jQuery's implementation, and
|
||||||
// unlike Javascript's .contains(), so if the contained
|
// unlike Javascript's .contains, so if the contained
|
||||||
// node is itself in the selection, it returns false.
|
// node is itself in the selection, it returns false.
|
||||||
func (this *Selection) Contains(n *html.Node) bool {
|
func (s *Selection) Contains(n *html.Node) bool {
|
||||||
return sliceContains(this.Nodes, n)
|
return sliceContains(s.Nodes, n)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,27 +72,6 @@ func TestIsNodes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasClass(t *testing.T) {
|
|
||||||
sel := Doc().Find("div")
|
|
||||||
if !sel.HasClass("span12") {
|
|
||||||
t.Error("Expected at least one div to have class span12.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasClassNone(t *testing.T) {
|
|
||||||
sel := Doc().Find("h2")
|
|
||||||
if sel.HasClass("toto") {
|
|
||||||
t.Error("Expected h1 to have no class.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHasClassNotFirst(t *testing.T) {
|
|
||||||
sel := Doc().Find(".alert")
|
|
||||||
if !sel.HasClass("alert-error") {
|
|
||||||
t.Error("Expected .alert to also have class .alert-error.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDocContains(t *testing.T) {
|
func TestDocContains(t *testing.T) {
|
||||||
sel := Doc().Find("h1")
|
sel := Doc().Find("h1")
|
||||||
if !Doc().Contains(sel.Nodes[0]) {
|
if !Doc().Contains(sel.Nodes[0]) {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
<div id="nf2" class="two odd row"></div>
|
<div id="nf2" class="two odd row"></div>
|
||||||
<div id="nf3" class="three even row"></div>
|
<div id="nf3" class="three even row"></div>
|
||||||
<div id="nf4" class="four odd row"></div>
|
<div id="nf4" class="four odd row"></div>
|
||||||
<div id="nf5" class="five even row"></div>
|
<div id="nf5" class="five even row odder"></div>
|
||||||
<div id="nf6" class="six odd row"></div>
|
<div id="nf6" class="six odd row"></div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+331
-172
@@ -2,7 +2,7 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/cascadia"
|
"code.google.com/p/cascadia"
|
||||||
"code.google.com/p/go.net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
type siblingType int
|
type siblingType int
|
||||||
@@ -20,89 +20,122 @@ const (
|
|||||||
siblingAllIncludingNonElements
|
siblingAllIncludingNonElements
|
||||||
)
|
)
|
||||||
|
|
||||||
// Find() gets the descendants of each element in the current set of matched
|
// Find gets the descendants of each element in the current set of matched
|
||||||
// elements, filtered by a selector. It returns a new Selection object
|
// elements, filtered by a selector. It returns a new Selection object
|
||||||
// containing these matched elements.
|
// containing these matched elements.
|
||||||
func (this *Selection) Find(selector string) *Selection {
|
func (s *Selection) Find(selector string) *Selection {
|
||||||
return pushStack(this, findWithSelector(this.Nodes, selector))
|
return pushStack(s, findWithMatcher(s.Nodes, cascadia.MustCompile(selector)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSelection() gets the descendants of each element in the current
|
// FindMatcher gets the descendants of each element in the current set of matched
|
||||||
|
// elements, filtered by the matcher. It returns a new Selection object
|
||||||
|
// containing these matched elements.
|
||||||
|
func (s *Selection) FindMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, findWithMatcher(s.Nodes, m))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindSelection gets the descendants of each element in the current
|
||||||
// Selection, filtered by a Selection. It returns a new Selection object
|
// Selection, filtered by a Selection. It returns a new Selection object
|
||||||
// containing these matched elements.
|
// containing these matched elements.
|
||||||
func (this *Selection) FindSelection(sel *Selection) *Selection {
|
func (s *Selection) FindSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return pushStack(this, nil)
|
return pushStack(s, nil)
|
||||||
}
|
}
|
||||||
return this.FindNodes(sel.Nodes...)
|
return s.FindNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindNodes() gets the descendants of each element in the current
|
// FindNodes gets the descendants of each element in the current
|
||||||
// Selection, filtered by some nodes. It returns a new Selection object
|
// Selection, filtered by some nodes. It returns a new Selection object
|
||||||
// containing these matched elements.
|
// containing these matched elements.
|
||||||
func (this *Selection) FindNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
if sliceContains(this.Nodes, n) {
|
if sliceContains(s.Nodes, n) {
|
||||||
return []*html.Node{n}
|
return []*html.Node{n}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contents() gets the children of each element in the Selection,
|
// Contents gets the children of each element in the Selection,
|
||||||
// including text and comment nodes. It returns a new Selection object
|
// including text and comment nodes. It returns a new Selection object
|
||||||
// containing these elements.
|
// containing these elements.
|
||||||
func (this *Selection) Contents() *Selection {
|
func (s *Selection) Contents() *Selection {
|
||||||
return pushStack(this, getChildrenNodes(this.Nodes, siblingAllIncludingNonElements))
|
return pushStack(s, getChildrenNodes(s.Nodes, siblingAllIncludingNonElements))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContentsFiltered() gets the children of each element in the Selection,
|
// ContentsFiltered gets the children of each element in the Selection,
|
||||||
// filtered by the specified selector. It returns a new Selection
|
// filtered by the specified selector. It returns a new Selection
|
||||||
// object containing these elements. Since selectors only act on Element nodes,
|
// object containing these elements. Since selectors only act on Element nodes,
|
||||||
// this function is an alias to ChildrenFiltered() unless the selector is empty,
|
// this function is an alias to ChildrenFiltered unless the selector is empty,
|
||||||
// in which case it is an alias to Contents().
|
// in which case it is an alias to Contents.
|
||||||
func (this *Selection) ContentsFiltered(selector string) *Selection {
|
func (s *Selection) ContentsFiltered(selector string) *Selection {
|
||||||
if selector != "" {
|
if selector != "" {
|
||||||
return this.ChildrenFiltered(selector)
|
return s.ChildrenFiltered(selector)
|
||||||
}
|
}
|
||||||
return this.Contents()
|
return s.Contents()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Children() gets the child elements of each element in the Selection.
|
// ContentsMatcher gets the children of each element in the Selection,
|
||||||
|
// filtered by the specified matcher. It returns a new Selection
|
||||||
|
// object containing these elements. Since matchers only act on Element nodes,
|
||||||
|
// this function is an alias to ChildrenMatcher.
|
||||||
|
func (s *Selection) ContentsMatcher(m Matcher) *Selection {
|
||||||
|
return s.ChildrenMatcher(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children gets the child elements of each element in the Selection.
|
||||||
// It returns a new Selection object containing these elements.
|
// It returns a new Selection object containing these elements.
|
||||||
func (this *Selection) Children() *Selection {
|
func (s *Selection) Children() *Selection {
|
||||||
return pushStack(this, getChildrenNodes(this.Nodes, siblingAll))
|
return pushStack(s, getChildrenNodes(s.Nodes, siblingAll))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChildrenFiltered() gets the child elements of each element in the Selection,
|
// ChildrenFiltered gets the child elements of each element in the Selection,
|
||||||
// filtered by the specified selector. It returns a new
|
// filtered by the specified selector. It returns a new
|
||||||
// Selection object containing these elements.
|
// Selection object containing these elements.
|
||||||
func (this *Selection) ChildrenFiltered(selector string) *Selection {
|
func (s *Selection) ChildrenFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getChildrenNodes(this.Nodes, siblingAll), selector)
|
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent() gets the parent of each element in the Selection. It returns a
|
// ChildrenMatcher gets the child elements of each element in the Selection,
|
||||||
|
// filtered by the specified matcher. It returns a new
|
||||||
|
// Selection object containing these elements.
|
||||||
|
func (s *Selection) ChildrenMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getChildrenNodes(s.Nodes, siblingAll), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent gets the parent of each element in the Selection. It returns a
|
||||||
// new Selection object containing the matched elements.
|
// new Selection object containing the matched elements.
|
||||||
func (this *Selection) Parent() *Selection {
|
func (s *Selection) Parent() *Selection {
|
||||||
return pushStack(this, getParentNodes(this.Nodes))
|
return pushStack(s, getParentNodes(s.Nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentFiltered() gets the parent of each element in the Selection filtered by a
|
// ParentFiltered gets the parent of each element in the Selection filtered by a
|
||||||
// selector. It returns a new Selection object containing the matched elements.
|
// selector. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) ParentFiltered(selector string) *Selection {
|
func (s *Selection) ParentFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getParentNodes(this.Nodes), selector)
|
return filterAndPush(s, getParentNodes(s.Nodes), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Closest() gets the first element that matches the selector by testing the
|
// ParentMatcher gets the parent of each element in the Selection filtered by a
|
||||||
// element itself and traversing up through its ancestors in the DOM tree.
|
// matcher. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) Closest(selector string) *Selection {
|
func (s *Selection) ParentMatcher(m Matcher) *Selection {
|
||||||
cs := cascadia.MustCompile(selector)
|
return filterAndPush(s, getParentNodes(s.Nodes), m)
|
||||||
|
}
|
||||||
|
|
||||||
return pushStack(this, mapNodes(this.Nodes, func(i int, n *html.Node) []*html.Node {
|
// Closest gets the first element that matches the selector by testing the
|
||||||
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
|
func (s *Selection) Closest(selector string) *Selection {
|
||||||
|
cs := cascadia.MustCompile(selector)
|
||||||
|
return s.ClosestMatcher(cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClosestMatcher gets the first element that matches the matcher by testing the
|
||||||
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
|
func (s *Selection) ClosestMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
// For each node in the selection, test the node itself, then each parent
|
// For each node in the selection, test the node itself, then each parent
|
||||||
// until a match is found.
|
// until a match is found.
|
||||||
for ; n != nil; n = n.Parent {
|
for ; n != nil; n = n.Parent {
|
||||||
if cs.Match(n) {
|
if m.Match(n) {
|
||||||
return []*html.Node{n}
|
return []*html.Node{n}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,10 +143,10 @@ func (this *Selection) Closest(selector string) *Selection {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClosestNodes() gets the first element that matches one of the nodes by testing the
|
// ClosestNodes gets the first element that matches one of the nodes by testing the
|
||||||
// element itself and traversing up through its ancestors in the DOM tree.
|
// element itself and traversing up through its ancestors in the DOM tree.
|
||||||
func (this *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, mapNodes(this.Nodes, func(i int, n *html.Node) []*html.Node {
|
return pushStack(s, mapNodes(s.Nodes, func(i int, n *html.Node) []*html.Node {
|
||||||
// For each node in the selection, test the node itself, then each parent
|
// For each node in the selection, test the node itself, then each parent
|
||||||
// until a match is found.
|
// until a match is found.
|
||||||
for ; n != nil; n = n.Parent {
|
for ; n != nil; n = n.Parent {
|
||||||
@@ -125,264 +158,392 @@ func (this *Selection) ClosestNodes(nodes ...*html.Node) *Selection {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClosestSelection() gets the first element that matches one of the nodes in the
|
// ClosestSelection gets the first element that matches one of the nodes in the
|
||||||
// Selection by testing the element itself and traversing up through its ancestors
|
// Selection by testing the element itself and traversing up through its ancestors
|
||||||
// in the DOM tree.
|
// in the DOM tree.
|
||||||
func (this *Selection) ClosestSelection(s *Selection) *Selection {
|
func (s *Selection) ClosestSelection(sel *Selection) *Selection {
|
||||||
if s == nil {
|
if sel == nil {
|
||||||
return pushStack(this, nil)
|
return pushStack(s, nil)
|
||||||
}
|
}
|
||||||
return this.ClosestNodes(s.Nodes...)
|
return s.ClosestNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parents() gets the ancestors of each element in the current Selection. It
|
// Parents gets the ancestors of each element in the current Selection. It
|
||||||
// returns a new Selection object with the matched elements.
|
// returns a new Selection object with the matched elements.
|
||||||
func (this *Selection) Parents() *Selection {
|
func (s *Selection) Parents() *Selection {
|
||||||
return pushStack(this, getParentsNodes(this.Nodes, "", nil))
|
return pushStack(s, getParentsNodes(s.Nodes, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsFiltered() gets the ancestors of each element in the current
|
// ParentsFiltered gets the ancestors of each element in the current
|
||||||
// Selection. It returns a new Selection object with the matched elements.
|
// Selection. It returns a new Selection object with the matched elements.
|
||||||
func (this *Selection) ParentsFiltered(selector string) *Selection {
|
func (s *Selection) ParentsFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getParentsNodes(this.Nodes, "", nil), selector)
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsUntil() gets the ancestors of each element in the Selection, up to but
|
// ParentsMatcher gets the ancestors of each element in the current
|
||||||
|
// Selection. It returns a new Selection object with the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntil gets the ancestors of each element in the Selection, up to but
|
||||||
// not including the element matched by the selector. It returns a new Selection
|
// not including the element matched by the selector. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) ParentsUntil(selector string) *Selection {
|
func (s *Selection) ParentsUntil(selector string) *Selection {
|
||||||
return pushStack(this, getParentsNodes(this.Nodes, selector, nil))
|
return pushStack(s, getParentsNodes(s.Nodes, cascadia.MustCompile(selector), nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsUntilSelection() gets the ancestors of each element in the Selection,
|
// ParentsUntilMatcher gets the ancestors of each element in the Selection, up to but
|
||||||
|
// not including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getParentsNodes(s.Nodes, m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsUntilSelection gets the ancestors of each element in the Selection,
|
||||||
// up to but not including the elements in the specified Selection. It returns a
|
// up to but not including the elements in the specified Selection. It returns a
|
||||||
// new Selection object containing the matched elements.
|
// new Selection object containing the matched elements.
|
||||||
func (this *Selection) ParentsUntilSelection(sel *Selection) *Selection {
|
func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.Parents()
|
return s.Parents()
|
||||||
}
|
}
|
||||||
return this.ParentsUntilNodes(sel.Nodes...)
|
return s.ParentsUntilNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsUntilNodes() gets the ancestors of each element in the Selection,
|
// ParentsUntilNodes gets the ancestors of each element in the Selection,
|
||||||
// up to but not including the specified nodes. It returns a
|
// up to but not including the specified nodes. It returns a
|
||||||
// new Selection object containing the matched elements.
|
// new Selection object containing the matched elements.
|
||||||
func (this *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, getParentsNodes(this.Nodes, "", nodes))
|
return pushStack(s, getParentsNodes(s.Nodes, nil, nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsFilteredUntil() is like ParentsUntil(), with the option to filter the
|
// ParentsFilteredUntil is like ParentsUntil, with the option to filter the
|
||||||
// results based on a selector string. It returns a new Selection
|
// results based on a selector string. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) ParentsFilteredUntil(filterSelector string, untilSelector string) *Selection {
|
func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
return filterAndPush(this, getParentsNodes(this.Nodes, untilSelector, nil), filterSelector)
|
return filterAndPush(s, getParentsNodes(s.Nodes, cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsFilteredUntilSelection() is like ParentsUntilSelection(), with the
|
// ParentsFilteredUntilMatcher is like ParentsUntilMatcher, with the option to filter the
|
||||||
|
// results based on a matcher. It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsFilteredUntilSelection is like ParentsUntilSelection, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
func (s *Selection) ParentsFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.ParentsMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentsMatcherUntilSelection is like ParentsUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.ParentsFiltered(filterSelector)
|
return s.ParentsMatcher(filter)
|
||||||
}
|
}
|
||||||
return this.ParentsFilteredUntilNodes(filterSelector, sel.Nodes...)
|
return s.ParentsMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParentsFilteredUntilNodes() is like ParentsUntilNodes(), with the
|
// ParentsFilteredUntilNodes is like ParentsUntilNodes, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
return filterAndPush(this, getParentsNodes(this.Nodes, "", nodes), filterSelector)
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Siblings() gets the siblings of each element in the Selection. It returns
|
// ParentsMatcherUntilNodes is like ParentsUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) ParentsMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getParentsNodes(s.Nodes, nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Siblings gets the siblings of each element in the Selection. It returns
|
||||||
// a new Selection object containing the matched elements.
|
// a new Selection object containing the matched elements.
|
||||||
func (this *Selection) Siblings() *Selection {
|
func (s *Selection) Siblings() *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingAll, "", nil))
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SiblingsFiltered() gets the siblings of each element in the Selection
|
// SiblingsFiltered gets the siblings of each element in the Selection
|
||||||
// filtered by a selector. It returns a new Selection object containing the
|
// filtered by a selector. It returns a new Selection object containing the
|
||||||
// matched elements.
|
// matched elements.
|
||||||
func (this *Selection) SiblingsFiltered(selector string) *Selection {
|
func (s *Selection) SiblingsFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingAll, "", nil), selector)
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next() gets the immediately following sibling of each element in the
|
// SiblingsMatcher gets the siblings of each element in the Selection
|
||||||
|
// filtered by a matcher. It returns a new Selection object containing the
|
||||||
|
// matched elements.
|
||||||
|
func (s *Selection) SiblingsMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next gets the immediately following sibling of each element in the
|
||||||
// Selection. It returns a new Selection object containing the matched elements.
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) Next() *Selection {
|
func (s *Selection) Next() *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingNext, "", nil))
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextFiltered() gets the immediately following sibling of each element in the
|
// NextFiltered gets the immediately following sibling of each element in the
|
||||||
// Selection filtered by a selector. It returns a new Selection object
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
// containing the matched elements.
|
// containing the matched elements.
|
||||||
func (this *Selection) NextFiltered(selector string) *Selection {
|
func (s *Selection) NextFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNext, "", nil), selector)
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextAll() gets all the following siblings of each element in the
|
// NextMatcher gets the immediately following sibling of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNext, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextAll gets all the following siblings of each element in the
|
||||||
// Selection. It returns a new Selection object containing the matched elements.
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) NextAll() *Selection {
|
func (s *Selection) NextAll() *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextAll, "", nil))
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextAllFiltered() gets all the following siblings of each element in the
|
// NextAllFiltered gets all the following siblings of each element in the
|
||||||
// Selection filtered by a selector. It returns a new Selection object
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
// containing the matched elements.
|
// containing the matched elements.
|
||||||
func (this *Selection) NextAllFiltered(selector string) *Selection {
|
func (s *Selection) NextAllFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextAll, "", nil), selector)
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prev() gets the immediately preceding sibling of each element in the
|
// NextAllMatcher gets all the following siblings of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) NextAllMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prev gets the immediately preceding sibling of each element in the
|
||||||
// Selection. It returns a new Selection object containing the matched elements.
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) Prev() *Selection {
|
func (s *Selection) Prev() *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrev, "", nil))
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevFiltered() gets the immediately preceding sibling of each element in the
|
// PrevFiltered gets the immediately preceding sibling of each element in the
|
||||||
// Selection filtered by a selector. It returns a new Selection object
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
// containing the matched elements.
|
// containing the matched elements.
|
||||||
func (this *Selection) PrevFiltered(selector string) *Selection {
|
func (s *Selection) PrevFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrev, "", nil), selector)
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevAll() gets all the preceding siblings of each element in the
|
// PrevMatcher gets the immediately preceding sibling of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrev, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevAll gets all the preceding siblings of each element in the
|
||||||
// Selection. It returns a new Selection object containing the matched elements.
|
// Selection. It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) PrevAll() *Selection {
|
func (s *Selection) PrevAll() *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevAll, "", nil))
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevAllFiltered() gets all the preceding siblings of each element in the
|
// PrevAllFiltered gets all the preceding siblings of each element in the
|
||||||
// Selection filtered by a selector. It returns a new Selection object
|
// Selection filtered by a selector. It returns a new Selection object
|
||||||
// containing the matched elements.
|
// containing the matched elements.
|
||||||
func (this *Selection) PrevAllFiltered(selector string) *Selection {
|
func (s *Selection) PrevAllFiltered(selector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevAll, "", nil), selector)
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), cascadia.MustCompile(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextUntil() gets all following siblings of each element up to but not
|
// PrevAllMatcher gets all the preceding siblings of each element in the
|
||||||
|
// Selection filtered by a matcher. It returns a new Selection object
|
||||||
|
// containing the matched elements.
|
||||||
|
func (s *Selection) PrevAllMatcher(m Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevAll, nil, nil), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntil gets all following siblings of each element up to but not
|
||||||
// including the element matched by the selector. It returns a new Selection
|
// including the element matched by the selector. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) NextUntil(selector string) *Selection {
|
func (s *Selection) NextUntil(selector string) *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextUntil,
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
selector, nil))
|
cascadia.MustCompile(selector), nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextUntilSelection() gets all following siblings of each element up to but not
|
// NextUntilMatcher gets all following siblings of each element up to but not
|
||||||
|
// including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) NextUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextUntilSelection gets all following siblings of each element up to but not
|
||||||
// including the element matched by the Selection. It returns a new Selection
|
// including the element matched by the Selection. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) NextUntilSelection(sel *Selection) *Selection {
|
func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.NextAll()
|
return s.NextAll()
|
||||||
}
|
}
|
||||||
return this.NextUntilNodes(sel.Nodes...)
|
return s.NextUntilNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextUntilNodes() gets all following siblings of each element up to but not
|
// NextUntilNodes gets all following siblings of each element up to but not
|
||||||
// including the element matched by the nodes. It returns a new Selection
|
// including the element matched by the nodes. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextUntil,
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
"", nodes))
|
nil, nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevUntil() gets all preceding siblings of each element up to but not
|
// PrevUntil gets all preceding siblings of each element up to but not
|
||||||
// including the element matched by the selector. It returns a new Selection
|
// including the element matched by the selector. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) PrevUntil(selector string) *Selection {
|
func (s *Selection) PrevUntil(selector string) *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
selector, nil))
|
cascadia.MustCompile(selector), nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevUntilSelection() gets all preceding siblings of each element up to but not
|
// PrevUntilMatcher gets all preceding siblings of each element up to but not
|
||||||
|
// including the element matched by the matcher. It returns a new Selection
|
||||||
|
// object containing the matched elements.
|
||||||
|
func (s *Selection) PrevUntilMatcher(m Matcher) *Selection {
|
||||||
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
m, nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevUntilSelection gets all preceding siblings of each element up to but not
|
||||||
// including the element matched by the Selection. It returns a new Selection
|
// including the element matched by the Selection. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) PrevUntilSelection(sel *Selection) *Selection {
|
func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.PrevAll()
|
return s.PrevAll()
|
||||||
}
|
}
|
||||||
return this.PrevUntilNodes(sel.Nodes...)
|
return s.PrevUntilNodes(sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevUntilNodes() gets all preceding siblings of each element up to but not
|
// PrevUntilNodes gets all preceding siblings of each element up to but not
|
||||||
// including the element matched by the nodes. It returns a new Selection
|
// including the element matched by the nodes. It returns a new Selection
|
||||||
// object containing the matched elements.
|
// object containing the matched elements.
|
||||||
func (this *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
|
func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
|
||||||
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
|
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
"", nodes))
|
nil, nodes))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextFilteredUntil() is like NextUntil(), with the option to filter
|
// NextFilteredUntil is like NextUntil, with the option to filter
|
||||||
// the results based on a selector string.
|
// the results based on a selector string.
|
||||||
// It returns a new Selection object containing the matched elements.
|
// It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) NextFilteredUntil(filterSelector string, untilSelector string) *Selection {
|
func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextUntil,
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
untilSelector, nil), filterSelector)
|
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextFilteredUntilSelection() is like NextUntilSelection(), with the
|
// NextFilteredUntilMatcher is like NextUntilMatcher, with the option to filter
|
||||||
|
// the results based on a matcher.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextFilteredUntilSelection is like NextUntilSelection, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
func (s *Selection) NextFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.NextMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextMatcherUntilSelection is like NextUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.NextFiltered(filterSelector)
|
return s.NextMatcher(filter)
|
||||||
}
|
}
|
||||||
return this.NextFilteredUntilNodes(filterSelector, sel.Nodes...)
|
return s.NextMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextFilteredUntilNodes() is like NextUntilNodes(), with the
|
// NextFilteredUntilNodes is like NextUntilNodes, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextUntil,
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
"", nodes), filterSelector)
|
nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevFilteredUntil() is like PrevUntil(), with the option to filter
|
// NextMatcherUntilNodes is like NextUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) NextMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
|
||||||
|
nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntil is like PrevUntil, with the option to filter
|
||||||
// the results based on a selector string.
|
// the results based on a selector string.
|
||||||
// It returns a new Selection object containing the matched elements.
|
// It returns a new Selection object containing the matched elements.
|
||||||
func (this *Selection) PrevFilteredUntil(filterSelector string, untilSelector string) *Selection {
|
func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
untilSelector, nil), filterSelector)
|
cascadia.MustCompile(untilSelector), nil), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevFilteredUntilSelection() is like PrevUntilSelection(), with the
|
// PrevFilteredUntilMatcher is like PrevUntilMatcher, with the option to filter
|
||||||
|
// the results based on a matcher.
|
||||||
|
// It returns a new Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevFilteredUntilMatcher(filter, until Matcher) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
until, nil), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevFilteredUntilSelection is like PrevUntilSelection, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
func (s *Selection) PrevFilteredUntilSelection(filterSelector string, sel *Selection) *Selection {
|
||||||
|
return s.PrevMatcherUntilSelection(cascadia.MustCompile(filterSelector), sel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrevMatcherUntilSelection is like PrevUntilSelection, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcherUntilSelection(filter Matcher, sel *Selection) *Selection {
|
||||||
if sel == nil {
|
if sel == nil {
|
||||||
return this.PrevFiltered(filterSelector)
|
return s.PrevMatcher(filter)
|
||||||
}
|
}
|
||||||
return this.PrevFilteredUntilNodes(filterSelector, sel.Nodes...)
|
return s.PrevMatcherUntilNodes(filter, sel.Nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrevFilteredUntilNodes() is like PrevUntilNodes(), with the
|
// PrevFilteredUntilNodes is like PrevUntilNodes, with the
|
||||||
// option to filter the results based on a selector string. It returns a new
|
// option to filter the results based on a selector string. It returns a new
|
||||||
// Selection object containing the matched elements.
|
// Selection object containing the matched elements.
|
||||||
func (this *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
|
||||||
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
"", nodes), filterSelector)
|
nil, nodes), cascadia.MustCompile(filterSelector))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter and push filters the nodes based on a selector, and pushes the results
|
// PrevMatcherUntilNodes is like PrevUntilNodes, with the
|
||||||
|
// option to filter the results based on a matcher. It returns a new
|
||||||
|
// Selection object containing the matched elements.
|
||||||
|
func (s *Selection) PrevMatcherUntilNodes(filter Matcher, nodes ...*html.Node) *Selection {
|
||||||
|
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
|
||||||
|
nil, nodes), filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter and push filters the nodes based on a matcher, and pushes the results
|
||||||
// on the stack, with the srcSel as previous selection.
|
// on the stack, with the srcSel as previous selection.
|
||||||
func filterAndPush(srcSel *Selection, nodes []*html.Node, selector string) *Selection {
|
func filterAndPush(srcSel *Selection, nodes []*html.Node, m Matcher) *Selection {
|
||||||
// Create a temporary Selection with the specified nodes to filter using winnow
|
// Create a temporary Selection with the specified nodes to filter using winnow
|
||||||
sel := &Selection{nodes, srcSel.document, nil}
|
sel := &Selection{nodes, srcSel.document, nil}
|
||||||
// Filter based on selector and push on stack
|
// Filter based on matcher and push on stack
|
||||||
return pushStack(srcSel, winnow(sel, selector, true))
|
return pushStack(srcSel, winnow(sel, m, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal implementation of Find that return raw nodes.
|
// Internal implementation of Find that return raw nodes.
|
||||||
func findWithSelector(nodes []*html.Node, selector string) []*html.Node {
|
func findWithMatcher(nodes []*html.Node, m Matcher) []*html.Node {
|
||||||
// Compile the selector once
|
|
||||||
sel := cascadia.MustCompile(selector)
|
|
||||||
// Map nodes to find the matches within the children of each node
|
// Map nodes to find the matches within the children of each node
|
||||||
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
||||||
// Go down one level, becausejQuery's Find() selects only within descendants
|
// Go down one level, becausejQuery's Find selects only within descendants
|
||||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
if c.Type == html.ElementNode {
|
if c.Type == html.ElementNode {
|
||||||
result = append(result, sel.MatchAll(c)...)
|
result = append(result, m.MatchAll(c)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -391,12 +552,12 @@ func findWithSelector(nodes []*html.Node, selector string) []*html.Node {
|
|||||||
|
|
||||||
// Internal implementation to get all parent nodes, stopping at the specified
|
// Internal implementation to get all parent nodes, stopping at the specified
|
||||||
// node (or nil if no stop).
|
// node (or nil if no stop).
|
||||||
func getParentsNodes(nodes []*html.Node, stopSelector string, stopNodes []*html.Node) []*html.Node {
|
func getParentsNodes(nodes []*html.Node, stopm Matcher, stopNodes []*html.Node) []*html.Node {
|
||||||
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
return mapNodes(nodes, func(i int, n *html.Node) (result []*html.Node) {
|
||||||
for p := n.Parent; p != nil; p = p.Parent {
|
for p := n.Parent; p != nil; p = p.Parent {
|
||||||
sel := newSingleSelection(p, nil)
|
sel := newSingleSelection(p, nil)
|
||||||
if stopSelector != "" {
|
if stopm != nil {
|
||||||
if sel.Is(stopSelector) {
|
if sel.IsMatcher(stopm) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if len(stopNodes) > 0 {
|
} else if len(stopNodes) > 0 {
|
||||||
@@ -413,17 +574,17 @@ func getParentsNodes(nodes []*html.Node, stopSelector string, stopNodes []*html.
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Internal implementation of sibling nodes that return a raw slice of matches.
|
// Internal implementation of sibling nodes that return a raw slice of matches.
|
||||||
func getSiblingNodes(nodes []*html.Node, st siblingType, untilSelector string, untilNodes []*html.Node) []*html.Node {
|
func getSiblingNodes(nodes []*html.Node, st siblingType, untilm Matcher, untilNodes []*html.Node) []*html.Node {
|
||||||
var f func(*html.Node) bool
|
var f func(*html.Node) bool
|
||||||
|
|
||||||
// If the requested siblings are ...Until(), create the test function to
|
// If the requested siblings are ...Until, create the test function to
|
||||||
// determine if the until condition is reached (returns true if it is)
|
// determine if the until condition is reached (returns true if it is)
|
||||||
if st == siblingNextUntil || st == siblingPrevUntil {
|
if st == siblingNextUntil || st == siblingPrevUntil {
|
||||||
f = func(n *html.Node) bool {
|
f = func(n *html.Node) bool {
|
||||||
if untilSelector != "" {
|
if untilm != nil {
|
||||||
// Selector-based condition
|
// Matcher-based condition
|
||||||
sel := newSingleSelection(n, nil)
|
sel := newSingleSelection(n, nil)
|
||||||
return sel.Is(untilSelector)
|
return sel.IsMatcher(untilm)
|
||||||
} else if len(untilNodes) > 0 {
|
} else if len(untilNodes) > 0 {
|
||||||
// Nodes-based condition
|
// Nodes-based condition
|
||||||
sel := newSingleSelection(n, nil)
|
sel := newSingleSelection(n, nil)
|
||||||
@@ -488,16 +649,14 @@ func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *htm
|
|||||||
}
|
}
|
||||||
if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
|
if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
|
||||||
return
|
return
|
||||||
} else {
|
}
|
||||||
// Not a valid node, try again from this one
|
// Not a valid node, try again from this one
|
||||||
cur = ret
|
cur = ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic("Unreachable code reached.")
|
|
||||||
}
|
|
||||||
|
|
||||||
for c := iter(nil); c != nil; c = iter(c) {
|
for c := iter(nil); c != nil; c = iter(c) {
|
||||||
// If this is an ...Until() case, test before append (returns true
|
// If this is an ...Until case, test before append (returns true
|
||||||
// if the until condition is reached)
|
// if the until condition is reached)
|
||||||
if st == siblingNextUntil || st == siblingPrevUntil {
|
if st == siblingNextUntil || st == siblingPrevUntil {
|
||||||
if untilFunc(c) {
|
if untilFunc(c) {
|
||||||
|
|||||||
+160
-138
@@ -1,675 +1,697 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFind(t *testing.T) {
|
func TestFind(t *testing.T) {
|
||||||
sel := Doc().Find("div.row-fluid")
|
sel := Doc().Find("div.row-fluid")
|
||||||
AssertLength(t, sel.Nodes, 9)
|
assertLength(t, sel.Nodes, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindRollback(t *testing.T) {
|
func TestFindRollback(t *testing.T) {
|
||||||
sel := Doc().Find("div.row-fluid")
|
sel := Doc().Find("div.row-fluid")
|
||||||
sel2 := sel.Find("a").End()
|
sel2 := sel.Find("a").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindNotSelf(t *testing.T) {
|
func TestFindNotSelf(t *testing.T) {
|
||||||
sel := Doc().Find("h1").Find("h1")
|
sel := Doc().Find("h1").Find("h1")
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFindInvalidSelector(t *testing.T) {
|
func TestFindInvalidSelector(t *testing.T) {
|
||||||
defer AssertPanic(t)
|
defer assertPanic(t)
|
||||||
Doc().Find(":+ ^")
|
Doc().Find(":+ ^")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChainedFind(t *testing.T) {
|
func TestChainedFind(t *testing.T) {
|
||||||
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
|
||||||
AssertLength(t, sel.Nodes, 4)
|
assertLength(t, sel.Nodes, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChildren(t *testing.T) {
|
func TestChildren(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Children()
|
sel := Doc().Find(".pvk-content").Children()
|
||||||
AssertLength(t, sel.Nodes, 5)
|
assertLength(t, sel.Nodes, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChildrenRollback(t *testing.T) {
|
func TestChildrenRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Children().End()
|
sel2 := sel.Children().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContents(t *testing.T) {
|
func TestContents(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").Contents()
|
sel := Doc().Find(".pvk-content").Contents()
|
||||||
AssertLength(t, sel.Nodes, 13)
|
assertLength(t, sel.Nodes, 13)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContentsRollback(t *testing.T) {
|
func TestContentsRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.Contents().End()
|
sel2 := sel.Contents().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChildrenFiltered(t *testing.T) {
|
func TestChildrenFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").ChildrenFiltered(".hero-unit")
|
sel := Doc().Find(".pvk-content").ChildrenFiltered(".hero-unit")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChildrenFilteredRollback(t *testing.T) {
|
func TestChildrenFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.ChildrenFiltered(".hero-unit").End()
|
sel2 := sel.ChildrenFiltered(".hero-unit").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContentsFiltered(t *testing.T) {
|
func TestContentsFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
|
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContentsFilteredRollback(t *testing.T) {
|
func TestContentsFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content")
|
sel := Doc().Find(".pvk-content")
|
||||||
sel2 := sel.ContentsFiltered(".hero-unit").End()
|
sel2 := sel.ContentsFiltered(".hero-unit").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestChildrenFilteredNone(t *testing.T) {
|
func TestChildrenFilteredNone(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParent(t *testing.T) {
|
func TestParent(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Parent()
|
sel := Doc().Find(".container-fluid").Parent()
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentRollback(t *testing.T) {
|
func TestParentRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.Parent().End()
|
sel2 := sel.Parent().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentBody(t *testing.T) {
|
func TestParentBody(t *testing.T) {
|
||||||
sel := Doc().Find("body").Parent()
|
sel := Doc().Find("body").Parent()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentFiltered(t *testing.T) {
|
func TestParentFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").ParentFiltered(".hero-unit")
|
sel := Doc().Find(".container-fluid").ParentFiltered(".hero-unit")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertClass(t, sel, "hero-unit")
|
assertClass(t, sel, "hero-unit")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentFilteredRollback(t *testing.T) {
|
func TestParentFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ParentFiltered(".hero-unit").End()
|
sel2 := sel.ParentFiltered(".hero-unit").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParents(t *testing.T) {
|
func TestParents(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").Parents()
|
sel := Doc().Find(".container-fluid").Parents()
|
||||||
AssertLength(t, sel.Nodes, 8)
|
assertLength(t, sel.Nodes, 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsOrder(t *testing.T) {
|
func TestParentsOrder(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2").Parents()
|
sel := Doc().Find("#cf2").Parents()
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
AssertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
|
assertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsRollback(t *testing.T) {
|
func TestParentsRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.Parents().End()
|
sel2 := sel.Parents().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFiltered(t *testing.T) {
|
func TestParentsFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").ParentsFiltered("body")
|
sel := Doc().Find(".container-fluid").ParentsFiltered("body")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredRollback(t *testing.T) {
|
func TestParentsFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ParentsFiltered("body").End()
|
sel2 := sel.ParentsFiltered("body").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntil(t *testing.T) {
|
func TestParentsUntil(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").ParentsUntil("body")
|
sel := Doc().Find(".container-fluid").ParentsUntil("body")
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntilRollback(t *testing.T) {
|
func TestParentsUntilRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ParentsUntil("body").End()
|
sel2 := sel.ParentsUntil("body").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntilSelection(t *testing.T) {
|
func TestParentsUntilSelection(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".pvk-content")
|
sel2 := Doc().Find(".pvk-content")
|
||||||
sel = sel.ParentsUntilSelection(sel2)
|
sel = sel.ParentsUntilSelection(sel2)
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntilSelectionRollback(t *testing.T) {
|
func TestParentsUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".pvk-content")
|
sel2 := Doc().Find(".pvk-content")
|
||||||
sel2 = sel.ParentsUntilSelection(sel2).End()
|
sel2 = sel.ParentsUntilSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntilNodes(t *testing.T) {
|
func TestParentsUntilNodes(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
||||||
sel = sel.ParentsUntilNodes(sel2.Nodes...)
|
sel = sel.ParentsUntilNodes(sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsUntilNodesRollback(t *testing.T) {
|
func TestParentsUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
sel2 := Doc().Find(".pvk-content, .hero-unit")
|
||||||
sel2 = sel.ParentsUntilNodes(sel2.Nodes...).End()
|
sel2 = sel.ParentsUntilNodes(sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntil(t *testing.T) {
|
func TestParentsFilteredUntil(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
|
sel := Doc().Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntilRollback(t *testing.T) {
|
func TestParentsFilteredUntilRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ParentsFilteredUntil(".pvk-content", "body").End()
|
sel2 := sel.ParentsFilteredUntil(".pvk-content", "body").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntilSelection(t *testing.T) {
|
func TestParentsFilteredUntilSelection(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".row-fluid")
|
sel2 := Doc().Find(".row-fluid")
|
||||||
sel = sel.ParentsFilteredUntilSelection("div", sel2)
|
sel = sel.ParentsFilteredUntilSelection("div", sel2)
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntilSelectionRollback(t *testing.T) {
|
func TestParentsFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".row-fluid")
|
sel2 := Doc().Find(".row-fluid")
|
||||||
sel2 = sel.ParentsFilteredUntilSelection("div", sel2).End()
|
sel2 = sel.ParentsFilteredUntilSelection("div", sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntilNodes(t *testing.T) {
|
func TestParentsFilteredUntilNodes(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".row-fluid")
|
sel2 := Doc().Find(".row-fluid")
|
||||||
sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...)
|
sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParentsFilteredUntilNodesRollback(t *testing.T) {
|
func TestParentsFilteredUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := Doc().Find(".row-fluid")
|
sel2 := Doc().Find(".row-fluid")
|
||||||
sel2 = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...).End()
|
sel2 = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblings(t *testing.T) {
|
func TestSiblings(t *testing.T) {
|
||||||
sel := Doc().Find("h1").Siblings()
|
sel := Doc().Find("h1").Siblings()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblingsRollback(t *testing.T) {
|
func TestSiblingsRollback(t *testing.T) {
|
||||||
sel := Doc().Find("h1")
|
sel := Doc().Find("h1")
|
||||||
sel2 := sel.Siblings().End()
|
sel2 := sel.Siblings().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblings2(t *testing.T) {
|
func TestSiblings2(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter").Siblings()
|
sel := Doc().Find(".pvk-gutter").Siblings()
|
||||||
AssertLength(t, sel.Nodes, 9)
|
assertLength(t, sel.Nodes, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblings3(t *testing.T) {
|
func TestSiblings3(t *testing.T) {
|
||||||
sel := Doc().Find("body>.container-fluid").Siblings()
|
sel := Doc().Find("body>.container-fluid").Siblings()
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblingsFiltered(t *testing.T) {
|
func TestSiblingsFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
|
sel := Doc().Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSiblingsFilteredRollback(t *testing.T) {
|
func TestSiblingsFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter")
|
sel := Doc().Find(".pvk-gutter")
|
||||||
sel2 := sel.SiblingsFiltered(".pvk-content").End()
|
sel2 := sel.SiblingsFiltered(".pvk-content").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNext(t *testing.T) {
|
func TestNext(t *testing.T) {
|
||||||
sel := Doc().Find("h1").Next()
|
sel := Doc().Find("h1").Next()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextRollback(t *testing.T) {
|
func TestNextRollback(t *testing.T) {
|
||||||
sel := Doc().Find("h1")
|
sel := Doc().Find("h1")
|
||||||
sel2 := sel.Next().End()
|
sel2 := sel.Next().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNext2(t *testing.T) {
|
func TestNext2(t *testing.T) {
|
||||||
sel := Doc().Find(".close").Next()
|
sel := Doc().Find(".close").Next()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextNone(t *testing.T) {
|
func TestNextNone(t *testing.T) {
|
||||||
sel := Doc().Find("small").Next()
|
sel := Doc().Find("small").Next()
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFiltered(t *testing.T) {
|
func TestNextFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").NextFiltered("div")
|
sel := Doc().Find(".container-fluid").NextFiltered("div")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredRollback(t *testing.T) {
|
func TestNextFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.NextFiltered("div").End()
|
sel2 := sel.NextFiltered("div").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFiltered2(t *testing.T) {
|
func TestNextFiltered2(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid").NextFiltered("[ng-view]")
|
sel := Doc().Find(".container-fluid").NextFiltered("[ng-view]")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrev(t *testing.T) {
|
func TestPrev(t *testing.T) {
|
||||||
sel := Doc().Find(".red").Prev()
|
sel := Doc().Find(".red").Prev()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertClass(t, sel, "green")
|
assertClass(t, sel, "green")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevRollback(t *testing.T) {
|
func TestPrevRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".red")
|
sel := Doc().Find(".red")
|
||||||
sel2 := sel.Prev().End()
|
sel2 := sel.Prev().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrev2(t *testing.T) {
|
func TestPrev2(t *testing.T) {
|
||||||
sel := Doc().Find(".row-fluid").Prev()
|
sel := Doc().Find(".row-fluid").Prev()
|
||||||
AssertLength(t, sel.Nodes, 5)
|
assertLength(t, sel.Nodes, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevNone(t *testing.T) {
|
func TestPrevNone(t *testing.T) {
|
||||||
sel := Doc().Find("h2").Prev()
|
sel := Doc().Find("h2").Prev()
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFiltered(t *testing.T) {
|
func TestPrevFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".row-fluid").PrevFiltered(".row-fluid")
|
sel := Doc().Find(".row-fluid").PrevFiltered(".row-fluid")
|
||||||
AssertLength(t, sel.Nodes, 5)
|
assertLength(t, sel.Nodes, 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredRollback(t *testing.T) {
|
func TestPrevFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".row-fluid")
|
sel := Doc().Find(".row-fluid")
|
||||||
sel2 := sel.PrevFiltered(".row-fluid").End()
|
sel2 := sel.PrevFiltered(".row-fluid").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAll(t *testing.T) {
|
func TestNextAll(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2 div:nth-child(1)").NextAll()
|
sel := Doc().Find("#cf2 div:nth-child(1)").NextAll()
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAllRollback(t *testing.T) {
|
func TestNextAllRollback(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2 div:nth-child(1)")
|
sel := Doc().Find("#cf2 div:nth-child(1)")
|
||||||
sel2 := sel.NextAll().End()
|
sel2 := sel.NextAll().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAll2(t *testing.T) {
|
func TestNextAll2(t *testing.T) {
|
||||||
sel := Doc().Find("div[ng-cloak]").NextAll()
|
sel := Doc().Find("div[ng-cloak]").NextAll()
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAllNone(t *testing.T) {
|
func TestNextAllNone(t *testing.T) {
|
||||||
sel := Doc().Find(".footer").NextAll()
|
sel := Doc().Find(".footer").NextAll()
|
||||||
AssertLength(t, sel.Nodes, 0)
|
assertLength(t, sel.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAllFiltered(t *testing.T) {
|
func TestNextAllFiltered(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
|
sel := Doc().Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAllFilteredRollback(t *testing.T) {
|
func TestNextAllFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2 .row-fluid")
|
sel := Doc().Find("#cf2 .row-fluid")
|
||||||
sel2 := sel.NextAllFiltered("[ng-cloak]").End()
|
sel2 := sel.NextAllFiltered("[ng-cloak]").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextAllFiltered2(t *testing.T) {
|
func TestNextAllFiltered2(t *testing.T) {
|
||||||
sel := Doc().Find(".close").NextAllFiltered("h4")
|
sel := Doc().Find(".close").NextAllFiltered("h4")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAll(t *testing.T) {
|
func TestPrevAll(t *testing.T) {
|
||||||
sel := Doc().Find("[ng-view]").PrevAll()
|
sel := Doc().Find("[ng-view]").PrevAll()
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAllOrder(t *testing.T) {
|
func TestPrevAllOrder(t *testing.T) {
|
||||||
sel := Doc().Find("[ng-view]").PrevAll()
|
sel := Doc().Find("[ng-view]").PrevAll()
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#cf4", "#cf3")
|
assertSelectionIs(t, sel, "#cf4", "#cf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAllRollback(t *testing.T) {
|
func TestPrevAllRollback(t *testing.T) {
|
||||||
sel := Doc().Find("[ng-view]")
|
sel := Doc().Find("[ng-view]")
|
||||||
sel2 := sel.PrevAll().End()
|
sel2 := sel.PrevAll().End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAll2(t *testing.T) {
|
func TestPrevAll2(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter").PrevAll()
|
sel := Doc().Find(".pvk-gutter").PrevAll()
|
||||||
AssertLength(t, sel.Nodes, 6)
|
assertLength(t, sel.Nodes, 6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAllFiltered(t *testing.T) {
|
func TestPrevAllFiltered(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
|
sel := Doc().Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
|
||||||
AssertLength(t, sel.Nodes, 3)
|
assertLength(t, sel.Nodes, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevAllFilteredRollback(t *testing.T) {
|
func TestPrevAllFilteredRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".pvk-gutter")
|
sel := Doc().Find(".pvk-gutter")
|
||||||
sel2 := sel.PrevAllFiltered(".pvk-content").End()
|
sel2 := sel.PrevAllFiltered(".pvk-content").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntil(t *testing.T) {
|
func TestNextUntil(t *testing.T) {
|
||||||
sel := Doc().Find(".alert a").NextUntil("p")
|
sel := Doc().Find(".alert a").NextUntil("p")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel, "h4")
|
assertSelectionIs(t, sel, "h4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntil2(t *testing.T) {
|
func TestNextUntil2(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2-1").NextUntil("[ng-cloak]")
|
sel := Doc().Find("#cf2-1").NextUntil("[ng-cloak]")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel, "#cf2-2")
|
assertSelectionIs(t, sel, "#cf2-2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilOrder(t *testing.T) {
|
func TestNextUntilOrder(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2-1").NextUntil("#cf2-4")
|
sel := Doc().Find("#cf2-1").NextUntil("#cf2-4")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
|
assertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilRollback(t *testing.T) {
|
func TestNextUntilRollback(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2-1")
|
sel := Doc().Find("#cf2-1")
|
||||||
sel2 := sel.PrevUntil("#cf2-4").End()
|
sel2 := sel.PrevUntil("#cf2-4").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilSelection(t *testing.T) {
|
func TestNextUntilSelection(t *testing.T) {
|
||||||
sel := Doc2().Find("#n2")
|
sel := Doc2().Find("#n2")
|
||||||
sel2 := Doc2().Find("#n4")
|
sel2 := Doc2().Find("#n4")
|
||||||
sel2 = sel.NextUntilSelection(sel2)
|
sel2 = sel.NextUntilSelection(sel2)
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel2, "#n3")
|
assertSelectionIs(t, sel2, "#n3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilSelectionRollback(t *testing.T) {
|
func TestNextUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc2().Find("#n2")
|
sel := Doc2().Find("#n2")
|
||||||
sel2 := Doc2().Find("#n4")
|
sel2 := Doc2().Find("#n4")
|
||||||
sel2 = sel.NextUntilSelection(sel2).End()
|
sel2 = sel.NextUntilSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilNodes(t *testing.T) {
|
func TestNextUntilNodes(t *testing.T) {
|
||||||
sel := Doc2().Find("#n2")
|
sel := Doc2().Find("#n2")
|
||||||
sel2 := Doc2().Find("#n5")
|
sel2 := Doc2().Find("#n5")
|
||||||
sel2 = sel.NextUntilNodes(sel2.Nodes...)
|
sel2 = sel.NextUntilNodes(sel2.Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel2, "#n3", "#n4")
|
assertSelectionIs(t, sel2, "#n3", "#n4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextUntilNodesRollback(t *testing.T) {
|
func TestNextUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc2().Find("#n2")
|
sel := Doc2().Find("#n2")
|
||||||
sel2 := Doc2().Find("#n5")
|
sel2 := Doc2().Find("#n5")
|
||||||
sel2 = sel.NextUntilNodes(sel2.Nodes...).End()
|
sel2 = sel.NextUntilNodes(sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntil(t *testing.T) {
|
func TestPrevUntil(t *testing.T) {
|
||||||
sel := Doc().Find(".alert p").PrevUntil("a")
|
sel := Doc().Find(".alert p").PrevUntil("a")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel, "h4")
|
assertSelectionIs(t, sel, "h4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntil2(t *testing.T) {
|
func TestPrevUntil2(t *testing.T) {
|
||||||
sel := Doc().Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
|
sel := Doc().Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
|
||||||
AssertLength(t, sel.Nodes, 1)
|
assertLength(t, sel.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel, "[ng-cloak]")
|
assertSelectionIs(t, sel, "[ng-cloak]")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilOrder(t *testing.T) {
|
func TestPrevUntilOrder(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2-4").PrevUntil("#cf2-1")
|
sel := Doc().Find("#cf2-4").PrevUntil("#cf2-1")
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
|
assertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilRollback(t *testing.T) {
|
func TestPrevUntilRollback(t *testing.T) {
|
||||||
sel := Doc().Find("#cf2-4")
|
sel := Doc().Find("#cf2-4")
|
||||||
sel2 := sel.PrevUntil("#cf2-1").End()
|
sel2 := sel.PrevUntil("#cf2-1").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilSelection(t *testing.T) {
|
func TestPrevUntilSelection(t *testing.T) {
|
||||||
sel := Doc2().Find("#n4")
|
sel := Doc2().Find("#n4")
|
||||||
sel2 := Doc2().Find("#n2")
|
sel2 := Doc2().Find("#n2")
|
||||||
sel2 = sel.PrevUntilSelection(sel2)
|
sel2 = sel.PrevUntilSelection(sel2)
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
AssertSelectionIs(t, sel2, "#n3")
|
assertSelectionIs(t, sel2, "#n3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilSelectionRollback(t *testing.T) {
|
func TestPrevUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc2().Find("#n4")
|
sel := Doc2().Find("#n4")
|
||||||
sel2 := Doc2().Find("#n2")
|
sel2 := Doc2().Find("#n2")
|
||||||
sel2 = sel.PrevUntilSelection(sel2).End()
|
sel2 = sel.PrevUntilSelection(sel2).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilNodes(t *testing.T) {
|
func TestPrevUntilNodes(t *testing.T) {
|
||||||
sel := Doc2().Find("#n5")
|
sel := Doc2().Find("#n5")
|
||||||
sel2 := Doc2().Find("#n2")
|
sel2 := Doc2().Find("#n2")
|
||||||
sel2 = sel.PrevUntilNodes(sel2.Nodes...)
|
sel2 = sel.PrevUntilNodes(sel2.Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel2, "#n4", "#n3")
|
assertSelectionIs(t, sel2, "#n4", "#n3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevUntilNodesRollback(t *testing.T) {
|
func TestPrevUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc2().Find("#n5")
|
sel := Doc2().Find("#n5")
|
||||||
sel2 := Doc2().Find("#n2")
|
sel2 := Doc2().Find("#n2")
|
||||||
sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
|
sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntil(t *testing.T) {
|
func TestNextFilteredUntil(t *testing.T) {
|
||||||
sel := Doc2().Find(".two").NextFilteredUntil(".even", ".six")
|
sel := Doc2().Find(".two").NextFilteredUntil(".even", ".six")
|
||||||
AssertLength(t, sel.Nodes, 4)
|
assertLength(t, sel.Nodes, 4)
|
||||||
AssertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
|
assertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntilRollback(t *testing.T) {
|
func TestNextFilteredUntilRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".two")
|
sel := Doc2().Find(".two")
|
||||||
sel2 := sel.NextFilteredUntil(".even", ".six").End()
|
sel2 := sel.NextFilteredUntil(".even", ".six").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntilSelection(t *testing.T) {
|
func TestNextFilteredUntilSelection(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".five")
|
sel2 := Doc2().Find(".five")
|
||||||
sel = sel.NextFilteredUntilSelection(".even", sel2)
|
sel = sel.NextFilteredUntilSelection(".even", sel2)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#n3", "#nf3")
|
assertSelectionIs(t, sel, "#n3", "#nf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntilSelectionRollback(t *testing.T) {
|
func TestNextFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".five")
|
sel2 := Doc2().Find(".five")
|
||||||
sel3 := sel.NextFilteredUntilSelection(".even", sel2).End()
|
sel3 := sel.NextFilteredUntilSelection(".even", sel2).End()
|
||||||
AssertEqual(t, sel, sel3)
|
assertEqual(t, sel, sel3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntilNodes(t *testing.T) {
|
func TestNextFilteredUntilNodes(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".four")
|
sel2 := Doc2().Find(".four")
|
||||||
sel = sel.NextFilteredUntilNodes(".odd", sel2.Nodes...)
|
sel = sel.NextFilteredUntilNodes(".odd", sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 4)
|
assertLength(t, sel.Nodes, 4)
|
||||||
AssertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
|
assertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNextFilteredUntilNodesRollback(t *testing.T) {
|
func TestNextFilteredUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".four")
|
sel2 := Doc2().Find(".four")
|
||||||
sel3 := sel.NextFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
sel3 := sel.NextFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel3)
|
assertEqual(t, sel, sel3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntil(t *testing.T) {
|
func TestPrevFilteredUntil(t *testing.T) {
|
||||||
sel := Doc2().Find(".five").PrevFilteredUntil(".odd", ".one")
|
sel := Doc2().Find(".five").PrevFilteredUntil(".odd", ".one")
|
||||||
AssertLength(t, sel.Nodes, 4)
|
assertLength(t, sel.Nodes, 4)
|
||||||
AssertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
|
assertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntilRollback(t *testing.T) {
|
func TestPrevFilteredUntilRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".four")
|
sel := Doc2().Find(".four")
|
||||||
sel2 := sel.PrevFilteredUntil(".odd", ".one").End()
|
sel2 := sel.PrevFilteredUntil(".odd", ".one").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntilSelection(t *testing.T) {
|
func TestPrevFilteredUntilSelection(t *testing.T) {
|
||||||
sel := Doc2().Find(".odd")
|
sel := Doc2().Find(".odd")
|
||||||
sel2 := Doc2().Find(".two")
|
sel2 := Doc2().Find(".two")
|
||||||
sel = sel.PrevFilteredUntilSelection(".odd", sel2)
|
sel = sel.PrevFilteredUntilSelection(".odd", sel2)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#n4", "#nf4")
|
assertSelectionIs(t, sel, "#n4", "#nf4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntilSelectionRollback(t *testing.T) {
|
func TestPrevFilteredUntilSelectionRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".five")
|
sel2 := Doc2().Find(".five")
|
||||||
sel3 := sel.PrevFilteredUntilSelection(".even", sel2).End()
|
sel3 := sel.PrevFilteredUntilSelection(".even", sel2).End()
|
||||||
AssertEqual(t, sel, sel3)
|
assertEqual(t, sel, sel3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntilNodes(t *testing.T) {
|
func TestPrevFilteredUntilNodes(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".four")
|
sel2 := Doc2().Find(".four")
|
||||||
sel = sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...)
|
sel = sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...)
|
||||||
AssertLength(t, sel.Nodes, 2)
|
assertLength(t, sel.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel, "#n2", "#nf2")
|
assertSelectionIs(t, sel, "#n2", "#nf2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrevFilteredUntilNodesRollback(t *testing.T) {
|
func TestPrevFilteredUntilNodesRollback(t *testing.T) {
|
||||||
sel := Doc2().Find(".even")
|
sel := Doc2().Find(".even")
|
||||||
sel2 := Doc2().Find(".four")
|
sel2 := Doc2().Find(".four")
|
||||||
sel3 := sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
sel3 := sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...).End()
|
||||||
AssertEqual(t, sel, sel3)
|
assertEqual(t, sel, sel3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestItself(t *testing.T) {
|
func TestClosestItself(t *testing.T) {
|
||||||
sel := Doc2().Find(".three")
|
sel := Doc2().Find(".three")
|
||||||
sel2 := sel.Closest(".row")
|
sel2 := sel.Closest(".row")
|
||||||
AssertLength(t, sel2.Nodes, sel.Length())
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
AssertSelectionIs(t, sel2, "#n3", "#nf3")
|
assertSelectionIs(t, sel2, "#n3", "#nf3")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNoDupes(t *testing.T) {
|
func TestClosestNoDupes(t *testing.T) {
|
||||||
sel := Doc().Find(".span12")
|
sel := Doc().Find(".span12")
|
||||||
sel2 := sel.Closest(".pvk-content")
|
sel2 := sel.Closest(".pvk-content")
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
AssertClass(t, sel2, "pvk-content")
|
assertClass(t, sel2, "pvk-content")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNone(t *testing.T) {
|
func TestClosestNone(t *testing.T) {
|
||||||
sel := Doc().Find("h4")
|
sel := Doc().Find("h4")
|
||||||
sel2 := sel.Closest("a")
|
sel2 := sel.Closest("a")
|
||||||
AssertLength(t, sel2.Nodes, 0)
|
assertLength(t, sel2.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestMany(t *testing.T) {
|
func TestClosestMany(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.Closest(".pvk-content")
|
sel2 := sel.Closest(".pvk-content")
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel2, "#pc1", "#pc2")
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestRollback(t *testing.T) {
|
func TestClosestRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.Closest(".pvk-content").End()
|
sel2 := sel.Closest(".pvk-content").End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestSelectionItself(t *testing.T) {
|
func TestClosestSelectionItself(t *testing.T) {
|
||||||
sel := Doc2().Find(".three")
|
sel := Doc2().Find(".three")
|
||||||
sel2 := sel.ClosestSelection(Doc2().Find(".row"))
|
sel2 := sel.ClosestSelection(Doc2().Find(".row"))
|
||||||
AssertLength(t, sel2.Nodes, sel.Length())
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestSelectionNoDupes(t *testing.T) {
|
func TestClosestSelectionNoDupes(t *testing.T) {
|
||||||
sel := Doc().Find(".span12")
|
sel := Doc().Find(".span12")
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
AssertClass(t, sel2, "pvk-content")
|
assertClass(t, sel2, "pvk-content")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestSelectionNone(t *testing.T) {
|
func TestClosestSelectionNone(t *testing.T) {
|
||||||
sel := Doc().Find("h4")
|
sel := Doc().Find("h4")
|
||||||
sel2 := sel.ClosestSelection(Doc().Find("a"))
|
sel2 := sel.ClosestSelection(Doc().Find("a"))
|
||||||
AssertLength(t, sel2.Nodes, 0)
|
assertLength(t, sel2.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestSelectionMany(t *testing.T) {
|
func TestClosestSelectionMany(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel2, "#pc1", "#pc2")
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestSelectionRollback(t *testing.T) {
|
func TestClosestSelectionRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content")).End()
|
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content")).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNodesItself(t *testing.T) {
|
func TestClosestNodesItself(t *testing.T) {
|
||||||
sel := Doc2().Find(".three")
|
sel := Doc2().Find(".three")
|
||||||
sel2 := sel.ClosestNodes(Doc2().Find(".row").Nodes...)
|
sel2 := sel.ClosestNodes(Doc2().Find(".row").Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, sel.Length())
|
assertLength(t, sel2.Nodes, sel.Length())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNodesNoDupes(t *testing.T) {
|
func TestClosestNodesNoDupes(t *testing.T) {
|
||||||
sel := Doc().Find(".span12")
|
sel := Doc().Find(".span12")
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, 1)
|
assertLength(t, sel2.Nodes, 1)
|
||||||
AssertClass(t, sel2, "pvk-content")
|
assertClass(t, sel2, "pvk-content")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNodesNone(t *testing.T) {
|
func TestClosestNodesNone(t *testing.T) {
|
||||||
sel := Doc().Find("h4")
|
sel := Doc().Find("h4")
|
||||||
sel2 := sel.ClosestNodes(Doc().Find("a").Nodes...)
|
sel2 := sel.ClosestNodes(Doc().Find("a").Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, 0)
|
assertLength(t, sel2.Nodes, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNodesMany(t *testing.T) {
|
func TestClosestNodesMany(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
|
||||||
AssertLength(t, sel2.Nodes, 2)
|
assertLength(t, sel2.Nodes, 2)
|
||||||
AssertSelectionIs(t, sel2, "#pc1", "#pc2")
|
assertSelectionIs(t, sel2, "#pc1", "#pc2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClosestNodesRollback(t *testing.T) {
|
func TestClosestNodesRollback(t *testing.T) {
|
||||||
sel := Doc().Find(".container-fluid")
|
sel := Doc().Find(".container-fluid")
|
||||||
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...).End()
|
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...).End()
|
||||||
AssertEqual(t, sel, sel2)
|
assertEqual(t, sel, sel2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssue26(t *testing.T) {
|
||||||
|
img1 := `<img src="assets/images/gallery/thumb-1.jpg" alt="150x150" />`
|
||||||
|
img2 := `<img alt="150x150" src="assets/images/gallery/thumb-1.jpg" />`
|
||||||
|
cases := []struct {
|
||||||
|
s string
|
||||||
|
l int
|
||||||
|
}{
|
||||||
|
{s: img1 + img2, l: 2},
|
||||||
|
{s: img1, l: 1},
|
||||||
|
{s: img2, l: 1},
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
doc, err := NewDocumentFromReader(strings.NewReader(c.s))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
sel := doc.Find("img[src]")
|
||||||
|
assertLength(t, sel.Nodes, c.l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Document represents an HTML document to be manipulated. Unlike jQuery, which
|
// Document represents an HTML document to be manipulated. Unlike jQuery, which
|
||||||
@@ -18,30 +20,30 @@ type Document struct {
|
|||||||
rootNode *html.Node
|
rootNode *html.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocumentFromNode() is a Document constructor that takes a root html Node
|
// NewDocumentFromNode is a Document constructor that takes a root html Node
|
||||||
// as argument.
|
// as argument.
|
||||||
func NewDocumentFromNode(root *html.Node) (d *Document) {
|
func NewDocumentFromNode(root *html.Node) *Document {
|
||||||
return newDocument(root, nil)
|
return newDocument(root, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocument() is a Document constructor that takes a string URL as argument.
|
// NewDocument is a Document constructor that takes a string URL as argument.
|
||||||
// It loads the specified document, parses it, and stores the root Document
|
// It loads the specified document, parses it, and stores the root Document
|
||||||
// node, ready to be manipulated.
|
// node, ready to be manipulated.
|
||||||
func NewDocument(url string) (d *Document, e error) {
|
func NewDocument(url string) (*Document, error) {
|
||||||
// Load the URL
|
// Load the URL
|
||||||
res, e := http.Get(url)
|
res, e := http.Get(url)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return
|
return nil, e
|
||||||
}
|
}
|
||||||
return NewDocumentFromResponse(res)
|
return NewDocumentFromResponse(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocumentFromReader() returns a Document from a generic reader.
|
// NewDocumentFromReader returns a Document from a generic reader.
|
||||||
// It returns an error as second value if the reader's data cannot be parsed
|
// It returns an error as second value if the reader's data cannot be parsed
|
||||||
// as html. It does *not* check if the reader is also an io.Closer, so the
|
// as html. It does *not* check if the reader is also an io.Closer, so the
|
||||||
// provided reader is never closed by this call, it is the responsibility
|
// provided reader is never closed by this call, it is the responsibility
|
||||||
// of the caller to close it if required.
|
// of the caller to close it if required.
|
||||||
func NewDocumentFromReader(r io.Reader) (d *Document, e error) {
|
func NewDocumentFromReader(r io.Reader) (*Document, error) {
|
||||||
root, e := html.Parse(r)
|
root, e := html.Parse(r)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
@@ -49,22 +51,31 @@ func NewDocumentFromReader(r io.Reader) (d *Document, e error) {
|
|||||||
return newDocument(root, nil), nil
|
return newDocument(root, nil), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDocumentFromResponse() is another Document constructor that takes an http resonse as argument.
|
// NewDocumentFromResponse is another Document constructor that takes an http resonse as argument.
|
||||||
// It loads the specified response's document, parses it, and stores the root Document
|
// It loads the specified response's document, parses it, and stores the root Document
|
||||||
// node, ready to be manipulated.
|
// node, ready to be manipulated. The response's body is closed on return.
|
||||||
func NewDocumentFromResponse(res *http.Response) (d *Document, e error) {
|
func NewDocumentFromResponse(res *http.Response) (*Document, error) {
|
||||||
|
if res == nil {
|
||||||
|
return nil, errors.New("Response is nil pointer")
|
||||||
|
}
|
||||||
|
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
// Parse the HTML into nodes
|
// Parse the HTML into nodes
|
||||||
root, e := html.Parse(res.Body)
|
root, e := html.Parse(res.Body)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and fill the document
|
// Create and fill the document
|
||||||
return newDocument(root, res.Request.URL), nil
|
return newDocument(root, res.Request.URL), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloneDocument creates a deep-clone of a document.
|
||||||
|
func CloneDocument(doc *Document) *Document {
|
||||||
|
return newDocument(cloneNode(doc.rootNode), doc.Url)
|
||||||
|
}
|
||||||
|
|
||||||
// Private constructor, make sure all fields are correctly filled.
|
// Private constructor, make sure all fields are correctly filled.
|
||||||
func newDocument(root *html.Node, url *url.URL) *Document {
|
func newDocument(root *html.Node, url *url.URL) *Document {
|
||||||
// Create and fill the document
|
// Create and fill the document
|
||||||
@@ -74,7 +85,7 @@ func newDocument(root *html.Node, url *url.URL) *Document {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Selection represents a collection of nodes matching some criteria. The
|
// Selection represents a collection of nodes matching some criteria. The
|
||||||
// initial Selection can be created by using Document.Find(), and then
|
// initial Selection can be created by using Document.Find, and then
|
||||||
// manipulated using the jQuery-like chainable syntax and methods.
|
// manipulated using the jQuery-like chainable syntax and methods.
|
||||||
type Selection struct {
|
type Selection struct {
|
||||||
Nodes []*html.Node
|
Nodes []*html.Node
|
||||||
@@ -91,3 +102,12 @@ func newEmptySelection(doc *Document) *Selection {
|
|||||||
func newSingleSelection(node *html.Node, doc *Document) *Selection {
|
func newSingleSelection(node *html.Node, doc *Document) *Selection {
|
||||||
return &Selection{[]*html.Node{node}, doc, nil}
|
return &Selection{[]*html.Node{node}, doc, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Matcher is an interface that defines the methods to match
|
||||||
|
// HTML nodes against a compiled selector string. Cascadia's
|
||||||
|
// Selector implements this interface.
|
||||||
|
type Matcher interface {
|
||||||
|
Match(*html.Node) bool
|
||||||
|
MatchAll(*html.Node) []*html.Node
|
||||||
|
Filter([]*html.Node) []*html.Node
|
||||||
|
}
|
||||||
|
|||||||
+50
-18
@@ -2,10 +2,11 @@ package goquery
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"code.google.com/p/go.net/html"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test helper functions and members
|
// Test helper functions and members
|
||||||
@@ -16,30 +17,42 @@ var docW *Document
|
|||||||
|
|
||||||
func Doc() *Document {
|
func Doc() *Document {
|
||||||
if doc == nil {
|
if doc == nil {
|
||||||
doc = LoadDoc("page.html")
|
doc = loadDoc("page.html")
|
||||||
}
|
}
|
||||||
return doc
|
return doc
|
||||||
}
|
}
|
||||||
|
func DocClone() *Document {
|
||||||
|
return CloneDocument(Doc())
|
||||||
|
}
|
||||||
func Doc2() *Document {
|
func Doc2() *Document {
|
||||||
if doc2 == nil {
|
if doc2 == nil {
|
||||||
doc2 = LoadDoc("page2.html")
|
doc2 = loadDoc("page2.html")
|
||||||
}
|
}
|
||||||
return doc2
|
return doc2
|
||||||
}
|
}
|
||||||
|
func Doc2Clone() *Document {
|
||||||
|
return CloneDocument(Doc2())
|
||||||
|
}
|
||||||
func DocB() *Document {
|
func DocB() *Document {
|
||||||
if docB == nil {
|
if docB == nil {
|
||||||
docB = LoadDoc("gotesting.html")
|
docB = loadDoc("gotesting.html")
|
||||||
}
|
}
|
||||||
return docB
|
return docB
|
||||||
}
|
}
|
||||||
|
func DocBClone() *Document {
|
||||||
|
return CloneDocument(DocB())
|
||||||
|
}
|
||||||
func DocW() *Document {
|
func DocW() *Document {
|
||||||
if docW == nil {
|
if docW == nil {
|
||||||
docW = LoadDoc("gowiki.html")
|
docW = loadDoc("gowiki.html")
|
||||||
}
|
}
|
||||||
return docW
|
return docW
|
||||||
}
|
}
|
||||||
|
func DocWClone() *Document {
|
||||||
|
return CloneDocument(DocW())
|
||||||
|
}
|
||||||
|
|
||||||
func AssertLength(t *testing.T, nodes []*html.Node, length int) {
|
func assertLength(t *testing.T, nodes []*html.Node, length int) {
|
||||||
if len(nodes) != length {
|
if len(nodes) != length {
|
||||||
t.Errorf("Expected %d nodes, found %d.", length, len(nodes))
|
t.Errorf("Expected %d nodes, found %d.", length, len(nodes))
|
||||||
for i, n := range nodes {
|
for i, n := range nodes {
|
||||||
@@ -48,25 +61,25 @@ func AssertLength(t *testing.T, nodes []*html.Node, length int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertClass(t *testing.T, sel *Selection, class string) {
|
func assertClass(t *testing.T, sel *Selection, class string) {
|
||||||
if !sel.HasClass(class) {
|
if !sel.HasClass(class) {
|
||||||
t.Errorf("Expected node to have class %s, found %+v.", class, sel.Get(0))
|
t.Errorf("Expected node to have class %s, found %+v.", class, sel.Get(0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertPanic(t *testing.T) {
|
func assertPanic(t *testing.T) {
|
||||||
if e := recover(); e == nil {
|
if e := recover(); e == nil {
|
||||||
t.Error("Expected a panic.")
|
t.Error("Expected a panic.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertEqual(t *testing.T, s1 *Selection, s2 *Selection) {
|
func assertEqual(t *testing.T, s1 *Selection, s2 *Selection) {
|
||||||
if s1 != s2 {
|
if s1 != s2 {
|
||||||
t.Error("Expected selection objects to be the same.")
|
t.Error("Expected selection objects to be the same.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertSelectionIs(t *testing.T, sel *Selection, is ...string) {
|
func assertSelectionIs(t *testing.T, sel *Selection, is ...string) {
|
||||||
for i := 0; i < sel.Length(); i++ {
|
for i := 0; i < sel.Length(); i++ {
|
||||||
if !sel.Eq(i).Is(is[i]) {
|
if !sel.Eq(i).Is(is[i]) {
|
||||||
t.Errorf("Expected node %d to be %s, found %+v", i, is[i], sel.Get(i))
|
t.Errorf("Expected node %d to be %s, found %+v", i, is[i], sel.Get(i))
|
||||||
@@ -74,18 +87,30 @@ func AssertSelectionIs(t *testing.T, sel *Selection, is ...string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadDoc(page string) *Document {
|
func printSel(t *testing.T, sel *Selection) {
|
||||||
if f, e := os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
|
if testing.Verbose() {
|
||||||
|
h, err := sel.Html()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadDoc(page string) *Document {
|
||||||
|
var f *os.File
|
||||||
|
var e error
|
||||||
|
|
||||||
|
if f, e = os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
|
||||||
panic(e.Error())
|
panic(e.Error())
|
||||||
} else {
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
if node, e := html.Parse(f); e != nil {
|
|
||||||
|
var node *html.Node
|
||||||
|
if node, e = html.Parse(f); e != nil {
|
||||||
panic(e.Error())
|
panic(e.Error())
|
||||||
} else {
|
}
|
||||||
return NewDocumentFromNode(node)
|
return NewDocumentFromNode(node)
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument(t *testing.T) {
|
func TestNewDocument(t *testing.T) {
|
||||||
@@ -148,3 +173,10 @@ func TestNewDocumentFromReader(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewDocumentFromResponseNil(t *testing.T) {
|
||||||
|
_, e := NewDocumentFromResponse(nil)
|
||||||
|
if e == nil {
|
||||||
|
t.Error("Expected error, got none")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+7
-10
@@ -1,14 +1,14 @@
|
|||||||
package goquery
|
package goquery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.google.com/p/go.net/html"
|
"golang.org/x/net/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getChildren(n *html.Node) (result []*html.Node) {
|
func getChildren(n *html.Node) (result []*html.Node) {
|
||||||
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
for c := n.FirstChild; c != nil; c = c.NextSibling {
|
||||||
result = append(result, c)
|
result = append(result, c)
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all container nodes to search for the target node.
|
// Loop through all container nodes to search for the target node.
|
||||||
@@ -55,9 +55,7 @@ func indexInSlice(slice []*html.Node, node *html.Node) int {
|
|||||||
// There is no check to the original state of the target slice, so it may still
|
// There is no check to the original state of the target slice, so it may still
|
||||||
// contain duplicates. The target slice is returned because append() may create
|
// contain duplicates. The target slice is returned because append() may create
|
||||||
// a new underlying array.
|
// a new underlying array.
|
||||||
func appendWithoutDuplicates(target []*html.Node,
|
func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node) []*html.Node {
|
||||||
nodes []*html.Node) []*html.Node {
|
|
||||||
|
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
if !isInSlice(target, n) {
|
if !isInSlice(target, n) {
|
||||||
target = append(target, n)
|
target = append(target, n)
|
||||||
@@ -70,18 +68,17 @@ func appendWithoutDuplicates(target []*html.Node,
|
|||||||
// Loop through a selection, returning only those nodes that pass the predicate
|
// Loop through a selection, returning only those nodes that pass the predicate
|
||||||
// function.
|
// function.
|
||||||
func grep(sel *Selection, predicate func(i int, s *Selection) bool) (result []*html.Node) {
|
func grep(sel *Selection, predicate func(i int, s *Selection) bool) (result []*html.Node) {
|
||||||
|
|
||||||
for i, n := range sel.Nodes {
|
for i, n := range sel.Nodes {
|
||||||
if predicate(i, newSingleSelection(n, sel.document)) {
|
if predicate(i, newSingleSelection(n, sel.document)) {
|
||||||
result = append(result, n)
|
result = append(result, n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a new Selection object based on the specified nodes, and keeps the
|
// Creates a new Selection object based on the specified nodes, and keeps the
|
||||||
// source Selection object on the stack (linked list).
|
// source Selection object on the stack (linked list).
|
||||||
func pushStack(fromSel *Selection, nodes []*html.Node) (result *Selection) {
|
func pushStack(fromSel *Selection, nodes []*html.Node) *Selection {
|
||||||
result = &Selection{nodes, fromSel.document, fromSel}
|
result := &Selection{nodes, fromSel.document, fromSel}
|
||||||
return
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user