Compare commits

...
84 Commits
Author SHA1 Message Date
Martin Angers 522e116ada doc again 2014-11-07 12:36:55 -05:00
Martin Angers b89597bb36 doc 2014-11-07 12:33:22 -05:00
Martin Angers fb2312a925 add final *Matcher* overloads 2014-11-07 12:19:01 -05:00
Martin Angers ef025592df more *Matcher overloads of selector string methods 2014-11-07 11:37:50 -05:00
Martin Angers c0464bb4c9 fix class manipulation issue 2014-11-07 11:22:08 -05:00
Martin Angers ac1e87b973 doc 2014-11-07 09:57:08 -05:00
Martin Angers 958027e55f fix failing test due to CloneDocument renaming 2014-11-07 09:32:11 -05:00
Martin Angers 1ff3f2a033 rename NewDocumentFromDocument to CloneDocument 2014-11-07 09:23:27 -05:00
Martin Angers 3aedb35ed4 remove lint warning 2014-11-07 09:21:01 -05:00
Martin Angers 409e94058f make test assert helpers private 2014-11-07 09:20:20 -05:00
Martin Angers 54d43ec4b0 add Go 1.3 target in travis tests 2014-11-07 08:38:44 -05:00
Martin Angers 875b65f385 finish transition for Matcher-based overloads 2014-11-07 08:36:55 -05:00
Martin Angers 251095afb5 start adding matcher functions 2014-11-06 21:43:08 -05:00
Martin Angers cc9b6f8c6f Merge branch 'master' into manipulation 2014-11-06 20:46:11 -05:00
Martin Angers 98316c249d changelog 2014-11-06 16:46:53 -05:00
Martin Angers 9324e7076d Merge branch 'golang-import-paths', fix #52 2014-11-06 16:41:10 -05:00
Martin Angers 040cf98281 change paths to golang.org/x/, fails to build because cascadia has to switch too 2014-11-05 20:30:33 -05:00
Andrew Stone e7ef1f75eb Update documentation to include manipulation functions 2014-10-29 11:58:26 -04:00
Andrew Stone 9b29a63ff5 property: Add Set/Remove Attr functions 2014-10-29 11:11:06 -04:00
Andrew Stone 25807d1884 property: Add/Remove/Toggle Class functions 2014-10-29 11:11:01 -04:00
Andrew Stone 2abc410148 manipulation: Add Before*() functions. 2014-10-24 11:49:20 -04:00
Andrew Stone 2bd0871a77 manipulation: Add After*() functions. 2014-10-24 11:49:20 -04:00
Andrew Stone b7dabffd85 manipulation: Add Empty() function. 2014-10-24 11:49:05 -04:00
Andrew Stone b800859dea manipulation: Add Remove*() functions. 2014-10-24 11:49:05 -04:00
Andrew Stone 9848519841 filter: Add *Selector for filtering methods that accepts a pre-compiled cascadia selector. 2014-10-24 11:49:05 -04:00
Andrew Stone 0e970f1f85 manipulation: Add Append*() functions 2014-10-24 11:49:01 -04:00
Martin Angers 12a8512778 mention go.text package to transform between encodings 2014-09-16 21:22:45 -04:00
Martin Angers 10e92b83fb links 2014-09-16 20:17:40 -04:00
Martin Angers 875035bc14 add tips and tricks doc, godoc badge 2014-09-16 20:11:24 -04:00
Martin Angers 1e5417b3db make example easier to understand (used from outside the goquery package) 2014-08-18 19:57:23 -04:00
Martin Angers 330b1c8132 simpler for-range construct to loop over selections 2014-07-29 22:55:19 -04:00
Martin Angers 41a4211e59 add test that loops with a standard for-loop (see #41) 2014-07-29 22:26:47 -04:00
Martin Angers 087eeef3f2 Merge pull request #40 from ithinco/master
Fixture on example code
2014-07-11 21:12:10 -04:00
Guan Ce d9e4d610c0 Fixture on example code
imported "github.com/PuerkitoBio/goquery", but if I didn't use goquery.NewDocument() method, the compiler would report "undefined: NewDocument" error
2014-07-12 08:48:07 +08:00
Martin Angers a3fdc62e31 add test with Html() for good measure 2014-04-25 15:31:01 -04:00
Martin Angers cf82003f7e add test to detect a   from a call to Text() 2014-04-25 15:28:38 -04:00
Martin Angers 308a3c0fda Merge pull request #37 from siriustnt/nilresponse
NewDocumentFromResponse crashes when nil pointer is passed
2014-04-22 14:39:56 -07:00
Noyb Cybot e7f5b65573 gofmt 2014-04-22 20:11:15 +02:00
Noyb Cybot d571e76106 Added test for NewDocumentFromResponse with nil response 2014-04-22 20:10:50 +02:00
Noyb Cybot 21918f0808 Check if response is nil pointer in NewDocumentFromResponse 2014-04-22 20:09:53 +02:00
Martin Angers 8e708aac7d add go1.1+ requirement 2014-04-11 12:38:16 -04:00
Martin Angers 6bab89f9f6 test go1.0 compat 2014-04-11 12:25:45 -04:00
Martin Angers 6938944908 final linting 2014-04-11 12:06:28 -04:00
Martin Angers 28cf4a77e1 more linting 2014-04-11 12:04:03 -04:00
Martin Angers 2c6687f6d3 lint 2014-04-11 12:00:17 -04:00
Martin Angers bc0c11b086 update doc, example 2014-04-11 11:32:03 -04:00
Martin Angers c44713447d Merge pull request #35 from aybabtme/patch-1
Fix indentation
2014-03-22 14:24:01 -04:00
Antoine Grondin 48358040e1 Fix indentation
Indentation is inconsistent in the docs.
2014-03-22 13:37:22 -04:00
Martin Angers 5329018c6a add travis badge, update copyright year 2014-02-28 21:36:06 -05:00
Martin Angers 8c07896774 Merge pull request #32 from siriustnt/mybranch
Eq now returns an empty Selector when an invalid index is given
2014-02-28 21:31:14 -05:00
tnt a6cc89ff58 Added test TestLastEmpty 2014-02-28 21:55:47 +01:00
tnt 076667ebf2 Updated docs for First() and Last() 2014-02-28 21:55:18 +01:00
tnt 48de68c2b7 Eq now returns an empty Selector when an invalid index is given 2014-02-28 21:54:48 +01:00
Martin Angers e273eed13e add benchmark file for go1.2 2013-12-02 19:52:21 -05:00
Martin Angers d247f5b79a add test for issue #26, cannot reproduce 2013-11-12 12:34:21 -05:00
Martin Angers aa0519aedd bench with go1.2rc1, getting 10-15% gains 2013-09-24 12:31:03 -04:00
Martin Angers f065786d41 add NewDocumentFromReader, closes #20 2013-09-07 10:57:54 -04:00
Martin Angers e8c0a63721 document new constructor, rename to NewDocumentFromResponse 2013-07-24 08:49:11 -04:00
Martin Angers 263b827b20 Merge pull request #19 from assassingj/myfeature
add another method to get html document
2013-07-24 05:40:37 -07:00
tesla.peng 2d2b626f0d add another method to get html document 2013-07-24 18:29:10 +08:00
Martin Angers 8a4ef5dbdd add v0.3.0 tag and benchmark EachWithBreak 2013-05-24 11:40:46 -04:00
Martin Angers 948b88c36f add EachWithBreak(), fixes #13 2013-05-24 11:25:42 -04:00
Martin Angers 27b24066a6 make regexp var package-level, compiled once. fixes #11 2013-05-06 20:19:21 -04:00
Martin Angers 485b1f5575 remove exp/html from comments, closes #10 2013-05-06 20:16:13 -04:00
Martin Angers 0d8bcaa448 add benchmark with go1.1rc1 2013-05-05 11:57:50 -04:00
Martin Angers d49fa5b2a1 update readme with new version 2013-04-26 19:44:22 -04:00
Martin Angers d84f346f92 update doc now that goquery is go-getable 2013-04-26 19:40:52 -04:00
Martin Angers f5309e0304 Merge pull request #7 from matrixik/master
Update exp/html import paths, closes #7
2013-04-26 16:32:17 -07:00
Martin Angers 4bdceda6d8 fix #8 2013-03-17 10:22:49 -04:00
Martin Angers fd221b178b install notes tweaked 2013-03-17 10:21:27 -04:00
Martin Angers ee5503bf12 update install instructions 2013-03-17 10:20:13 -04:00
Dobrosław Żybort 474b169363 Update exp/html import paths 2013-02-12 20:32:16 +01:00
Martin Angers a28d5edf42 fix doc for build instruction of exp package 2013-01-10 19:27:30 -05:00
Martin Angers 7f5775caed go.pkgdoc.org is case sensitive now. Closes #3. 2012-11-19 09:00:21 -05:00
Martin Angers b26e04175c fix comment in Slice(), negative indices are now supported 2012-11-15 17:15:47 -05:00
Martin Angers 6948b1bfac finalize tests and benchmarks for v0.2 2012-11-11 21:26:27 -05:00
Martin Angers f98d0dce50 add tests for closest with selector 2012-11-10 20:57:04 -05:00
Martin Angers 971be3c4e4 add nodes and selection overloads for Closest 2012-11-08 21:08:24 -05:00
Martin Angers 2f94000c0a start closest with selector string 2012-11-04 20:31:03 -05:00
Martin Angers 0f850e5c82 remove commented code 2012-10-18 21:18:56 -04:00
Martin Angers ae1a71636e update changelog, doc 2012-10-14 12:34:28 -04:00
Martin Angers 6669ef001f remove Document.Root, Document is itself a Selection (using embedded struct) 2012-10-14 12:28:27 -04:00
Martin Angers cbddb7a808 add support for negative indices in Slice(), with tests 2012-10-10 19:55:34 -04:00
Martin Angers 9ed3dce6b0 forgot changelog 2012-09-17 11:14:03 -04:00
45 changed files with 6211 additions and 1056 deletions
+5
View File
@@ -1,2 +1,7 @@
*.sublime-*
.DS_Store
*.swp
#*.*#
tags
goquery.test
+7
View File
@@ -0,0 +1,7 @@
language: go
go:
- 1.1
- 1.2
- 1.3
- tip
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2012, Martin Angers & Contributors
Copyright (c) 2012-2014, Martin Angers & Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+63 -64
View File
@@ -1,98 +1,95 @@
# 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][exphtml] 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).
[![build status](https://secure.travis-ci.org/PuerkitoBio/goquery.png)](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.
[![GoDoc](https://godoc.org/github.com/PuerkitoBio/goquery?status.png)](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]...).
## Installation
Since this library (and cascadia) depends on the experimental branch, this package must be installed first. Both GoQuery and Cascadia expect to find the experimental library with the `"exp/html"` import statement. To install it at this location, please [follow this guide][wikiexp].
Please note that because of the net/html dependency, goquery requires Go1.1+.
Once this is done, install GoQuery:
$ go get github.com/PuerkitoBio/goquery
`go get github.com/PuerkitoBio/goquery`
(optional) To run unit tests:
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test
To run unit tests, run this command in goquery's source directory (`$GOPATH/src/github.com/PuerkitoBio/goquery`):
(optional) To run benchmarks (warning: it runs for a few minutes):
`go test`
To run benchmarks, run this command in goquery's source directory:
`go test -bench=".*"`
$ cd $GOPATH/src/github.com/PuerkitoBio/goquery
$ go test -bench=".*"
## Changelog
* **v0.1** : Initial release. See [TODOs](#a1) for a list of upcoming features.
**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.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.2.1** : Make go-getable, now that [go.net/html is Go1.0-compatible][gonet] (thanks to @matrixik for pointing this out).
* **v0.2.0** : Add support for negative indices in Slice(). **BREAKING CHANGE** `Document.Root` is removed, `Document` is now a `Selection` itself (a selection of one, the root element, just like `Document.Root` was before). Add jQuery's Closest() method.
* **v0.1.1** : Add benchmarks to use as baseline for refactorings, refactor Next...() and Prev...() methods to use the new html package's linked list features (Next/PrevSibling, FirstChild). Good performance boost (40+% in some cases).
* **v0.1.0** : Initial release.
## 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 **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 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 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 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
Taken from example_test.go:
See some tips and tricks in the [wiki][].
import (
"fmt"
// In real use, this import would be required (not in this example, since it
// is part of the goquery package)
//"github.com/PuerkitoBio/goquery"
"strconv"
)
Taken (and adapted as if executed from outside the goquery package) from example_test.go:
// This example scrapes the 10 reviews shown on the home page of MetalReview.com,
// the best metal review site on the web :) (and no, I'm not affiliated to them!)
func ExampleScrape_MetalReview() {
// Load the HTML document (in real use, the type would be *goquery.Document)
var doc *Document
var e error
if doc, e = NewDocument("http://metalreview.com"); e != nil {
panic(e.Error())
}
```Go
package main
// Find the review items (the type of the Selection would be *goquery.Selection)
doc.Root.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
var band, title string
var score float64
import (
"fmt"
"log"
// 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).
"github.com/PuerkitoBio/goquery"
)
// xOutput: voluntarily fail the Example output.
}
func ExampleScrape() {
doc, err := goquery.NewDocument("http://metalsucks.net")
if err != nil {
log.Fatal(err)
}
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *goquery.Selection) {
band := s.Find("h3").Text()
title := s.Find("i").Text()
fmt.Printf("Review %d: %s - %s\n", i, band, title)
})
}
## TODOs
<a name="a1" />
* Add jQuery's `Closest()`? Other missing functions?
* Support negative indices in `Slice()`, like jQuery.
func main() {
ExampleScrape()
}
```
## License
@@ -100,11 +97,13 @@ The [BSD 3-Clause license][bsd], the same as the [Go language][golic]. Cascadia'
[jquery]: http://jquery.com/
[go]: http://golang.org/
[exphtml]: http://code.google.com/p/go/source/browse#hg%2Fsrc%2Fpkg%2Fexp
[cascadia]: http://code.google.com/p/cascadia/
[wikiexp]: http://code.google.com/p/go-wiki/wiki/InstallingExp
[bsd]: http://opensource.org/licenses/BSD-3-Clause
[golic]: http://golang.org/LICENSE
[caslic]: http://code.google.com/p/cascadia/source/browse/LICENSE
[doc]: http://go.pkgdoc.org/github.com/puerkitobio/goquery
[doc]: http://godoc.org/github.com/PuerkitoBio/goquery
[index]: http://api.jquery.com/index/
[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
+62 -39
View File
@@ -1,80 +1,103 @@
package goquery
import (
"exp/html"
"golang.org/x/net/html"
)
// First() reduces the set of matched elements to the first in the set.
// It returns a new Selection object.
func (this *Selection) First() *Selection {
return this.Eq(0)
// First reduces the set of matched elements to the first in the set.
// It returns a new Selection object, and an empty Selection object if the
// the selection is empty.
func (s *Selection) First() *Selection {
return s.Eq(0)
}
// Last() reduces the set of matched elements to the last in the set.
// It returns a new Selection object.
func (this *Selection) Last() *Selection {
return this.Eq(-1)
// Last reduces the set of matched elements to the last in the set.
// It returns a new Selection object, and an empty Selection object if
// the selection is empty.
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
// set. It returns a new Selection object, and an empty Selection object if the
// index is invalid.
func (this *Selection) Eq(index int) *Selection {
func (s *Selection) Eq(index int) *Selection {
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
// of indices. At the moment, negative indices are not supported.
func (this *Selection) Slice(start int, end int) *Selection {
// TODO : Negative indices, like jQuery
return pushStack(this, this.Nodes[start:end])
// Slice reduces the set of matched elements to a subset specified by a range
// of indices.
func (s *Selection) Slice(start, end int) *Selection {
if start < 0 {
start += len(s.Nodes)
}
if end < 0 {
end += len(s.Nodes)
}
return pushStack(s, s.Nodes[start:end])
}
// Get() retrieves the underlying node at the specified index.
// Get() without parameter is not implemented, since the node array is available
// Get retrieves the underlying node at the specified index.
// Get without parameter is not implemented, since the node array is available
// on the Selection object.
func (this *Selection) Get(index int) *html.Node {
func (s *Selection) Get(index int) *html.Node {
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.
func (this *Selection) Index() int {
if len(this.Nodes) > 0 {
return newSingleSelection(this.Nodes[0], this.document).PrevAll().Length()
func (s *Selection) Index() int {
if len(s.Nodes) > 0 {
return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length()
}
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
// not found.
func (this *Selection) IndexSelector(selector string) int {
if len(this.Nodes) > 0 {
sel := this.document.Root.Find(selector)
return indexInSlice(sel.Nodes, this.Nodes[0])
func (s *Selection) IndexSelector(selector string) int {
if len(s.Nodes) > 0 {
sel := s.document.Find(selector)
return indexInSlice(sel.Nodes, s.Nodes[0])
}
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.
func (this *Selection) IndexOfNode(node *html.Node) int {
return indexInSlice(this.Nodes, node)
func (s *Selection) IndexOfNode(node *html.Node) int {
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.
func (this *Selection) IndexOfSelection(s *Selection) int {
if s != nil && len(s.Nodes) > 0 {
return indexInSlice(this.Nodes, s.Nodes[0])
func (s *Selection) IndexOfSelection(sel *Selection) int {
if sel != nil && len(sel.Nodes) > 0 {
return indexInSlice(s.Nodes, sel.Nodes[0])
}
return -1
}
+79 -34
View File
@@ -5,79 +5,124 @@ import (
)
func TestFirst(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").First()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").First()
assertLength(t, sel.Nodes, 1)
}
func TestFirstEmpty(t *testing.T) {
defer AssertPanic(t)
Doc().Root.Find(".pvk-zzcontentzz").First()
sel := Doc().Find(".pvk-zzcontentzz").First()
assertLength(t, sel.Nodes, 0)
}
func TestFirstRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.First().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestLast(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").Last()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").Last()
assertLength(t, sel.Nodes, 1)
// Should contain Footer
foot := Doc().Root.Find(".footer")
foot := Doc().Find(".footer")
if !sel.Contains(foot.Nodes[0]) {
t.Error("Last .pvk-content should contain .footer.")
}
}
func TestLastEmpty(t *testing.T) {
sel := Doc().Find(".pvk-zzcontentzz").Last()
assertLength(t, sel.Nodes, 0)
}
func TestLastRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Last().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestEq(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").Eq(1)
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").Eq(1)
assertLength(t, sel.Nodes, 1)
}
func TestEqNegative(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").Eq(-1)
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").Eq(-1)
assertLength(t, sel.Nodes, 1)
// Should contain Footer
foot := Doc().Root.Find(".footer")
foot := Doc().Find(".footer")
if !sel.Contains(foot.Nodes[0]) {
t.Error("Index -1 of .pvk-content should contain .footer.")
}
}
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) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Eq(1).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestSlice(t *testing.T) {
sel := Doc().Root.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) {
defer AssertPanic(t)
Doc().Root.Find(".pvk-content").Slice(2, 12)
defer assertPanic(t)
Doc().Find(".pvk-content").Slice(2, 12)
}
func TestNegativeSliceStart(t *testing.T) {
sel := Doc().Find(".container-fluid").Slice(-2, 3)
assertLength(t, sel.Nodes, 1)
assertSelectionIs(t, sel.Eq(0), "#cf3")
}
func TestNegativeSliceEnd(t *testing.T) {
sel := Doc().Find(".container-fluid").Slice(1, -1)
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel.Eq(0), "#cf2")
assertSelectionIs(t, sel.Eq(1), "#cf3")
}
func TestNegativeSliceBoth(t *testing.T) {
sel := Doc().Find(".container-fluid").Slice(-3, -1)
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel.Eq(0), "#cf2")
assertSelectionIs(t, sel.Eq(1), "#cf3")
}
func TestNegativeSliceOutOfBounds(t *testing.T) {
defer assertPanic(t)
Doc().Find(".container-fluid").Slice(-12, -7)
}
func TestSliceRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Slice(0, 2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestGet(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
node := sel.Get(1)
if sel.Nodes[1] != node {
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[1])
@@ -85,7 +130,7 @@ func TestGet(t *testing.T) {
}
func TestGetNegative(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
node := sel.Get(-3)
if sel.Nodes[0] != node {
t.Errorf("Expected node %v to be %v.", node, sel.Nodes[0])
@@ -93,42 +138,42 @@ func TestGetNegative(t *testing.T) {
}
func TestGetInvalid(t *testing.T) {
defer AssertPanic(t)
sel := Doc().Root.Find(".pvk-content")
defer assertPanic(t)
sel := Doc().Find(".pvk-content")
sel.Get(129)
}
func TestIndex(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
if i := sel.Index(); i != 1 {
t.Errorf("Expected index of 1, got %v.", i)
}
}
func TestIndexSelector(t *testing.T) {
sel := Doc().Root.Find(".hero-unit")
sel := Doc().Find(".hero-unit")
if i := sel.IndexSelector("div"); i != 4 {
t.Errorf("Expected index of 4, got %v.", i)
}
}
func TestIndexOfNode(t *testing.T) {
sel := Doc().Root.Find("div.pvk-gutter")
sel := Doc().Find("div.pvk-gutter")
if i := sel.IndexOfNode(sel.Nodes[1]); i != 1 {
t.Errorf("Expected index of 1, got %v.", i)
}
}
func TestIndexOfNilNode(t *testing.T) {
sel := Doc().Root.Find("div.pvk-gutter")
sel := Doc().Find("div.pvk-gutter")
if i := sel.IndexOfNode(nil); i != -1 {
t.Errorf("Expected index of -1, got %v.", i)
}
}
func TestIndexOfSelection(t *testing.T) {
sel := Doc().Root.Find("div")
sel2 := Doc().Root.Find(".hero-unit")
sel := Doc().Find("div")
sel2 := Doc().Find(".hero-unit")
if i := sel.IndexOfSelection(sel2); i != 4 {
t.Errorf("Expected index of 4, got %v.", i)
}
+405
View File
@@ -0,0 +1,405 @@
<?xml version="1.0"?>
<!-- Generated by SVGo -->
<svg width="1024" height="768"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g style="font-size:20px;font-family:sans-serif">
<rect x="0" y="0" width="1024" height="768" style="fill:white"/>
<text x="100" y="50" style="font-size:150%"></text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="118" width="0" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="607" y="133" style="text-anchor:end">+0.10%</text>
</g>
<text x="100" y="138" style="text-anchor:start">BenchmarkFirst</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="144" width="0" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="617" y="159" style="text-anchor:start">-0.10%</text>
</g>
<text x="100" y="164" style="text-anchor:start">BenchmarkLast</text>
<g style="font-style:italic;font-size:75%">
<rect x="604" y="170" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="599" y="185" style="text-anchor:end">+2.86%</text>
</g>
<text x="100" y="190" style="text-anchor:start">BenchmarkEq</text>
<g style="font-style:italic;font-size:75%">
<rect x="604" y="196" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="599" y="211" style="text-anchor:end">+2.67%</text>
</g>
<text x="100" y="216" style="text-anchor:start">BenchmarkSlice</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="222" width="32" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="649" y="237" style="text-anchor:start">-10.82%</text>
</g>
<text x="100" y="242" style="text-anchor:start">BenchmarkGet</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="248" width="132" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="749" y="263" style="text-anchor:start">-44.06%</text>
</g>
<text x="100" y="268" style="text-anchor:start">BenchmarkIndex</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="274" width="156" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="773" y="289" style="text-anchor:start">-52.26%</text>
</g>
<text x="100" y="294" style="text-anchor:start">BenchmarkIndexSelector</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="300" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="644" y="315" style="text-anchor:start">-9.32%</text>
</g>
<text x="100" y="320" style="text-anchor:start">BenchmarkIndexOfNode</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="326" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="624" y="341" style="text-anchor:start">-2.48%</text>
</g>
<text x="100" y="346" style="text-anchor:start">BenchmarkIndexOfSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="352" width="104" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="721" y="367" style="text-anchor:start">-34.96%</text>
</g>
<text x="100" y="372" style="text-anchor:start">BenchmarkMetalReviewExample</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="378" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="794" y="393" style="text-anchor:start">-59.16%</text>
</g>
<text x="100" y="398" style="text-anchor:start">BenchmarkAdd</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="404" width="0" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="617" y="419" style="text-anchor:start">+0.00%</text>
</g>
<text x="100" y="424" style="text-anchor:start">BenchmarkAddSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="602" y="430" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="597" y="445" style="text-anchor:end">+3.47%</text>
</g>
<text x="100" y="450" style="text-anchor:start">BenchmarkAddNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="456" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="624" y="471" style="text-anchor:start">-2.51%</text>
</g>
<text x="100" y="476" style="text-anchor:start">BenchmarkAndSelf</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="482" width="41" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="658" y="497" style="text-anchor:start">-13.96%</text>
</g>
<text x="100" y="502" style="text-anchor:start">BenchmarkFilter</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="508" width="43" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="660" y="523" style="text-anchor:start">-14.53%</text>
</g>
<text x="100" y="528" style="text-anchor:start">BenchmarkNot</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="534" width="11" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="628" y="549" style="text-anchor:start">-3.81%</text>
</g>
<text x="100" y="554" style="text-anchor:start">BenchmarkFilterFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="560" width="8" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="625" y="575" style="text-anchor:start">-2.83%</text>
</g>
<text x="100" y="580" style="text-anchor:start">BenchmarkNotFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="586" width="13" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="630" y="601" style="text-anchor:start">-4.63%</text>
</g>
<text x="100" y="606" style="text-anchor:start">BenchmarkFilterNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="612" width="6" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="623" y="627" style="text-anchor:start">-2.32%</text>
</g>
<text x="100" y="632" style="text-anchor:start">BenchmarkNotNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="638" width="12" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="629" y="653" style="text-anchor:start">-4.23%</text>
</g>
<text x="100" y="658" style="text-anchor:start">BenchmarkFilterSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="664" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="626" y="679" style="text-anchor:start">-3.31%</text>
</g>
<text x="100" y="684" style="text-anchor:start">BenchmarkNotSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="690" width="101" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="718" y="705" style="text-anchor:start">-33.69%</text>
</g>
<text x="100" y="710" style="text-anchor:start">BenchmarkHas</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="716" width="13" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="630" y="731" style="text-anchor:start">-4.53%</text>
</g>
<text x="100" y="736" style="text-anchor:start">BenchmarkHasNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="742" width="15" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="632" y="757" style="text-anchor:start">-5.30%</text>
</g>
<text x="100" y="762" style="text-anchor:start">BenchmarkHasSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="578" y="768" width="34" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="573" y="783" style="text-anchor:end">+11.35%</text>
</g>
<text x="100" y="788" style="text-anchor:start">BenchmarkEnd</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="794" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="626" y="809" style="text-anchor:start">-3.33%</text>
</g>
<text x="100" y="814" style="text-anchor:start">BenchmarkEach</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="820" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="644" y="835" style="text-anchor:start">-9.16%</text>
</g>
<text x="100" y="840" style="text-anchor:start">BenchmarkMap</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="846" width="57" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="674" y="861" style="text-anchor:start">-19.15%</text>
</g>
<text x="100" y="866" style="text-anchor:start">BenchmarkAttr</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="872" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="626" y="887" style="text-anchor:start">-3.24%</text>
</g>
<text x="100" y="892" style="text-anchor:start">BenchmarkText</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="898" width="183" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="800" y="913" style="text-anchor:start">-61.25%</text>
</g>
<text x="100" y="918" style="text-anchor:start">BenchmarkLength</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="924" width="35" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="652" y="939" style="text-anchor:start">-11.92%</text>
</g>
<text x="100" y="944" style="text-anchor:start">BenchmarkHtml</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="950" width="49" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="666" y="965" style="text-anchor:start">-16.46%</text>
</g>
<text x="100" y="970" style="text-anchor:start">BenchmarkIs</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="976" width="81" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="698" y="991" style="text-anchor:start">-27.31%</text>
</g>
<text x="100" y="996" style="text-anchor:start">BenchmarkIsPositional</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1002" width="40" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="657" y="1017" style="text-anchor:start">-13.49%</text>
</g>
<text x="100" y="1022" style="text-anchor:start">BenchmarkIsFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1028" width="5" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="622" y="1043" style="text-anchor:start">-1.71%</text>
</g>
<text x="100" y="1048" style="text-anchor:start">BenchmarkIsSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1054" width="9" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="626" y="1069" style="text-anchor:start">-3.03%</text>
</g>
<text x="100" y="1074" style="text-anchor:start">BenchmarkIsNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1080" width="60" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="677" y="1095" style="text-anchor:start">-20.30%</text>
</g>
<text x="100" y="1100" style="text-anchor:start">BenchmarkHasClass</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1106" width="33" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="650" y="1121" style="text-anchor:start">-11.29%</text>
</g>
<text x="100" y="1126" style="text-anchor:start">BenchmarkContains</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1132" width="152" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="769" y="1147" style="text-anchor:start">-50.88%</text>
</g>
<text x="100" y="1152" style="text-anchor:start">BenchmarkFind</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1158" width="135" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="752" y="1173" style="text-anchor:start">-45.28%</text>
</g>
<text x="100" y="1178" style="text-anchor:start">BenchmarkFindWithinSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="544" y="1184" width="68" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="539" y="1199" style="text-anchor:end">+22.95%</text>
</g>
<text x="100" y="1204" style="text-anchor:start">BenchmarkFindSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="544" y="1210" width="68" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="539" y="1225" style="text-anchor:end">+22.68%</text>
</g>
<text x="100" y="1230" style="text-anchor:start">BenchmarkFindNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1236" width="195" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="812" y="1251" style="text-anchor:start">-65.08%</text>
</g>
<text x="100" y="1256" style="text-anchor:start">BenchmarkContents</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1262" width="179" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="796" y="1277" style="text-anchor:start">-59.77%</text>
</g>
<text x="100" y="1282" style="text-anchor:start">BenchmarkContentsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1288" width="192" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="809" y="1303" style="text-anchor:start">-64.31%</text>
</g>
<text x="100" y="1308" style="text-anchor:start">BenchmarkChildren</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1314" width="118" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="735" y="1329" style="text-anchor:start">-39.56%</text>
</g>
<text x="100" y="1334" style="text-anchor:start">BenchmarkChildrenFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1340" width="19" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="636" y="1355" style="text-anchor:start">-6.61%</text>
</g>
<text x="100" y="1360" style="text-anchor:start">BenchmarkParent</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1366" width="32" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="649" y="1381" style="text-anchor:start">-10.92%</text>
</g>
<text x="100" y="1386" style="text-anchor:start">BenchmarkParentFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1392" width="5" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="622" y="1407" style="text-anchor:start">-1.72%</text>
</g>
<text x="100" y="1412" style="text-anchor:start">BenchmarkParents</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1418" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="624" y="1433" style="text-anchor:start">-2.37%</text>
</g>
<text x="100" y="1438" style="text-anchor:start">BenchmarkParentsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1444" width="142" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="759" y="1459" style="text-anchor:start">-47.60%</text>
</g>
<text x="100" y="1464" style="text-anchor:start">BenchmarkParentsUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1470" width="109" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="726" y="1485" style="text-anchor:start">-36.39%</text>
</g>
<text x="100" y="1490" style="text-anchor:start">BenchmarkParentsUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1496" width="107" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="724" y="1511" style="text-anchor:start">-35.99%</text>
</g>
<text x="100" y="1516" style="text-anchor:start">BenchmarkParentsUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1522" width="146" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="763" y="1537" style="text-anchor:start">-48.84%</text>
</g>
<text x="100" y="1542" style="text-anchor:start">BenchmarkParentsFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1548" width="98" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="715" y="1563" style="text-anchor:start">-32.75%</text>
</g>
<text x="100" y="1568" style="text-anchor:start">BenchmarkParentsFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1574" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="716" y="1589" style="text-anchor:start">-33.12%</text>
</g>
<text x="100" y="1594" style="text-anchor:start">BenchmarkParentsFilteredUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1600" width="89" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="706" y="1615" style="text-anchor:start">-29.78%</text>
</g>
<text x="100" y="1620" style="text-anchor:start">BenchmarkSiblings</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1626" width="92" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="709" y="1641" style="text-anchor:start">-30.89%</text>
</g>
<text x="100" y="1646" style="text-anchor:start">BenchmarkSiblingsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1652" width="204" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="821" y="1667" style="text-anchor:start">-68.19%</text>
</g>
<text x="100" y="1672" style="text-anchor:start">BenchmarkNext</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1678" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="816" y="1693" style="text-anchor:start">-66.59%</text>
</g>
<text x="100" y="1698" style="text-anchor:start">BenchmarkNextFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1704" width="93" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="710" y="1719" style="text-anchor:start">-31.08%</text>
</g>
<text x="100" y="1724" style="text-anchor:start">BenchmarkNextAll</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1730" width="90" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="707" y="1745" style="text-anchor:start">-30.03%</text>
</g>
<text x="100" y="1750" style="text-anchor:start">BenchmarkNextAllFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1756" width="204" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="821" y="1771" style="text-anchor:start">-68.32%</text>
</g>
<text x="100" y="1776" style="text-anchor:start">BenchmarkPrev</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1782" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="816" y="1797" style="text-anchor:start">-66.65%</text>
</g>
<text x="100" y="1802" style="text-anchor:start">BenchmarkPrevFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1808" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="746" y="1823" style="text-anchor:start">-43.33%</text>
</g>
<text x="100" y="1828" style="text-anchor:start">BenchmarkPrevAll</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1834" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="746" y="1849" style="text-anchor:start">-43.24%</text>
</g>
<text x="100" y="1854" style="text-anchor:start">BenchmarkPrevAllFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1860" width="162" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="779" y="1875" style="text-anchor:start">-54.27%</text>
</g>
<text x="100" y="1880" style="text-anchor:start">BenchmarkNextUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1886" width="113" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="730" y="1901" style="text-anchor:start">-37.90%</text>
</g>
<text x="100" y="1906" style="text-anchor:start">BenchmarkNextUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1912" width="129" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="746" y="1927" style="text-anchor:start">-43.21%</text>
</g>
<text x="100" y="1932" style="text-anchor:start">BenchmarkNextUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1938" width="147" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="764" y="1953" style="text-anchor:start">-49.33%</text>
</g>
<text x="100" y="1958" style="text-anchor:start">BenchmarkPrevUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1964" width="111" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="728" y="1979" style="text-anchor:start">-37.02%</text>
</g>
<text x="100" y="1984" style="text-anchor:start">BenchmarkPrevUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1990" width="133" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="750" y="2005" style="text-anchor:start">-44.59%</text>
</g>
<text x="100" y="2010" style="text-anchor:start">BenchmarkPrevUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2016" width="173" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="790" y="2031" style="text-anchor:start">-57.79%</text>
</g>
<text x="100" y="2036" style="text-anchor:start">BenchmarkNextFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2042" width="109" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="726" y="2057" style="text-anchor:start">-36.61%</text>
</g>
<text x="100" y="2062" style="text-anchor:start">BenchmarkNextFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2068" width="113" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="730" y="2083" style="text-anchor:start">-37.81%</text>
</g>
<text x="100" y="2088" style="text-anchor:start">BenchmarkNextFilteredUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2094" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="794" y="2109" style="text-anchor:start">-59.21%</text>
</g>
<text x="100" y="2114" style="text-anchor:start">BenchmarkPrevFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2120" width="108" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="725" y="2135" style="text-anchor:start">-36.20%</text>
</g>
<text x="100" y="2140" style="text-anchor:start">BenchmarkPrevFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2146" width="108" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="725" y="2161" style="text-anchor:start">-36.05%</text>
</g>
<text x="100" y="2166" style="text-anchor:start">BenchmarkPrevFilteredUntilNodes</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 21 KiB

+459
View File
@@ -0,0 +1,459 @@
PASS
BenchmarkFirst 20000000 94.3 ns/op
BenchmarkLast 20000000 94.7 ns/op
BenchmarkEq 20000000 93.7 ns/op
BenchmarkSlice 20000000 89.9 ns/op
BenchmarkGet 1000000000 2.72 ns/op
BenchmarkIndex 1000000 1834 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
BenchmarkIndexSelector 50000 53958 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.1 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 10.9 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 5000 326712 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 50000 51776 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 196 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 191 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 2495 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 50000 30974 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 35322 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 65644 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 69245 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 64824 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 20000 76247 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 66154 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 20000 76336 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 569495 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 227059 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 227167 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 3.99 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 9354 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 16557 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
BenchmarkAttr 50000000 36.4 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 100000 18473 ns/op
BenchmarkLength 2000000000 0.76 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 666 ns/op
BenchmarkIs 50000 35174 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 50000 31814 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 2754 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 66260 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 64682 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 672953 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.3 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 50000 53780 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 10000 125963 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
BenchmarkFindSelection 5000 357318 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 357587 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 200000 9135 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 200000 12383 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 1000000 1809 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
BenchmarkChildrenFiltered 500000 5814 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 44810 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 48795 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 89102 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 93953 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 10000 130783 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
BenchmarkParentsUntilSelection 10000 231797 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 233761 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 50000 31360 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 50000 30272 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 50000 30327 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 20000 89862 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 20000 97948 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 50000 31975 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 50000 34887 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 60734 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 67428 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 50000 32399 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 50000 34944 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 29360 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 50000 32291 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 10000 191890 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
BenchmarkNextUntilSelection 20000 92054 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 50000 43401 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 5000 433383 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 10000 116423 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
BenchmarkPrevUntilNodes 50000 35338 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 10000 104686 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
BenchmarkNextFilteredUntilSelection 20000 99485 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 20000 99452 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 10000 112640 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
BenchmarkPrevFilteredUntilSelection 10000 103702 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
BenchmarkPrevFilteredUntilNodes 10000 103277 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
BenchmarkClosest 500000 6530 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 1000000 1135 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
BenchmarkClosestNodes 1000000 1133 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
ok github.com/PuerkitoBio/goquery 192.541s
+420
View File
@@ -0,0 +1,420 @@
<?xml version="1.0"?>
<!-- Generated by SVGo -->
<svg width="1024" height="768"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g style="font-size:20px;font-family:sans-serif">
<rect x="0" y="0" width="1024" height="768" style="fill:white"/>
<text x="100" y="50" style="font-size:150%"></text>
<g style="font-style:italic;font-size:75%">
<rect x="606" y="118" width="6" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="601" y="133" style="text-anchor:end">+2.12%</text>
</g>
<text x="100" y="138" style="text-anchor:start">BenchmarkFirst</text>
<g style="font-style:italic;font-size:75%">
<rect x="609" y="144" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="604" y="159" style="text-anchor:end">+1.06%</text>
</g>
<text x="100" y="164" style="text-anchor:start">BenchmarkLast</text>
<g style="font-style:italic;font-size:75%">
<rect x="602" y="170" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="597" y="185" style="text-anchor:end">+3.63%</text>
</g>
<text x="100" y="190" style="text-anchor:start">BenchmarkEq</text>
<g style="font-style:italic;font-size:75%">
<rect x="604" y="196" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="599" y="211" style="text-anchor:end">+2.67%</text>
</g>
<text x="100" y="216" style="text-anchor:start">BenchmarkSlice</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="222" width="72" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="689" y="237" style="text-anchor:start">-24.26%</text>
</g>
<text x="100" y="242" style="text-anchor:start">BenchmarkGet</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="248" width="125" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="742" y="263" style="text-anchor:start">-41.71%</text>
</g>
<text x="100" y="268" style="text-anchor:start">BenchmarkIndex</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="274" width="151" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="768" y="289" style="text-anchor:start">-50.42%</text>
</g>
<text x="100" y="294" style="text-anchor:start">BenchmarkIndexSelector</text>
<g style="font-style:italic;font-size:75%">
<rect x="595" y="300" width="17" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="590" y="315" style="text-anchor:end">+5.94%</text>
</g>
<text x="100" y="320" style="text-anchor:start">BenchmarkIndexOfNode</text>
<g style="font-style:italic;font-size:75%">
<rect x="588" y="326" width="24" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="583" y="341" style="text-anchor:end">+8.26%</text>
</g>
<text x="100" y="346" style="text-anchor:start">BenchmarkIndexOfSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="352" width="98" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="715" y="367" style="text-anchor:start">-32.94%</text>
</g>
<text x="100" y="372" style="text-anchor:start">BenchmarkMetalReviewExample</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="378" width="170" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="787" y="393" style="text-anchor:start">-56.84%</text>
</g>
<text x="100" y="398" style="text-anchor:start">BenchmarkAdd</text>
<g style="font-style:italic;font-size:75%">
<rect x="593" y="404" width="19" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="588" y="419" style="text-anchor:end">+6.63%</text>
</g>
<text x="100" y="424" style="text-anchor:start">BenchmarkAddSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="584" y="430" width="28" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="579" y="445" style="text-anchor:end">+9.42%</text>
</g>
<text x="100" y="450" style="text-anchor:start">BenchmarkAddNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="604" y="456" width="8" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="599" y="471" style="text-anchor:end">+2.93%</text>
</g>
<text x="100" y="476" style="text-anchor:start">BenchmarkAndSelf</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="482" width="41" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="658" y="497" style="text-anchor:start">-13.75%</text>
</g>
<text x="100" y="502" style="text-anchor:start">BenchmarkFilter</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="508" width="44" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="661" y="523" style="text-anchor:start">-14.90%</text>
</g>
<text x="100" y="528" style="text-anchor:start">BenchmarkNot</text>
<g style="font-style:italic;font-size:75%">
<rect x="609" y="534" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="604" y="549" style="text-anchor:end">+1.07%</text>
</g>
<text x="100" y="554" style="text-anchor:start">BenchmarkFilterFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="598" y="560" width="14" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="593" y="575" style="text-anchor:end">+4.91%</text>
</g>
<text x="100" y="580" style="text-anchor:start">BenchmarkNotFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="609" y="586" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="604" y="601" style="text-anchor:end">+1.03%</text>
</g>
<text x="100" y="606" style="text-anchor:start">BenchmarkFilterNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="600" y="612" width="12" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="595" y="627" style="text-anchor:end">+4.22%</text>
</g>
<text x="100" y="632" style="text-anchor:start">BenchmarkNotNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="638" width="3" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="620" y="653" style="text-anchor:start">-1.00%</text>
</g>
<text x="100" y="658" style="text-anchor:start">BenchmarkFilterSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="600" y="664" width="12" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="595" y="679" style="text-anchor:end">+4.00%</text>
</g>
<text x="100" y="684" style="text-anchor:start">BenchmarkNotSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="690" width="96" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="713" y="705" style="text-anchor:start">-32.12%</text>
</g>
<text x="100" y="710" style="text-anchor:start">BenchmarkHas</text>
<g style="font-style:italic;font-size:75%">
<rect x="608" y="716" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="603" y="731" style="text-anchor:end">+1.59%</text>
</g>
<text x="100" y="736" style="text-anchor:start">BenchmarkHasNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="608" y="742" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="603" y="757" style="text-anchor:end">+1.56%</text>
</g>
<text x="100" y="762" style="text-anchor:start">BenchmarkHasSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="566" y="768" width="46" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="561" y="783" style="text-anchor:end">+15.54%</text>
</g>
<text x="100" y="788" style="text-anchor:start">BenchmarkEnd</text>
<g style="font-style:italic;font-size:75%">
<rect x="607" y="794" width="5" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="602" y="809" style="text-anchor:end">+1.77%</text>
</g>
<text x="100" y="814" style="text-anchor:start">BenchmarkEach</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="820" width="10" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="627" y="835" style="text-anchor:start">-3.61%</text>
</g>
<text x="100" y="840" style="text-anchor:start">BenchmarkMap</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="846" width="49" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="666" y="861" style="text-anchor:start">-16.48%</text>
</g>
<text x="100" y="866" style="text-anchor:start">BenchmarkAttr</text>
<g style="font-style:italic;font-size:75%">
<rect x="609" y="872" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="604" y="887" style="text-anchor:end">+1.33%</text>
</g>
<text x="100" y="892" style="text-anchor:start">BenchmarkText</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="898" width="177" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="794" y="913" style="text-anchor:start">-59.21%</text>
</g>
<text x="100" y="918" style="text-anchor:start">BenchmarkLength</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="924" width="27" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="644" y="939" style="text-anchor:start">-9.01%</text>
</g>
<text x="100" y="944" style="text-anchor:start">BenchmarkHtml</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="950" width="50" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="667" y="965" style="text-anchor:start">-16.73%</text>
</g>
<text x="100" y="970" style="text-anchor:start">BenchmarkIs</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="976" width="75" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="692" y="991" style="text-anchor:start">-25.08%</text>
</g>
<text x="100" y="996" style="text-anchor:start">BenchmarkIsPositional</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1002" width="34" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="651" y="1017" style="text-anchor:start">-11.55%</text>
</g>
<text x="100" y="1022" style="text-anchor:start">BenchmarkIsFunction</text>
<g style="font-style:italic;font-size:75%">
<rect x="609" y="1028" width="3" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="604" y="1043" style="text-anchor:end">+1.28%</text>
</g>
<text x="100" y="1048" style="text-anchor:start">BenchmarkIsSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="606" y="1054" width="6" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="601" y="1069" style="text-anchor:end">+2.10%</text>
</g>
<text x="100" y="1074" style="text-anchor:start">BenchmarkIsNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1080" width="47" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="664" y="1095" style="text-anchor:start">-15.99%</text>
</g>
<text x="100" y="1100" style="text-anchor:start">BenchmarkHasClass</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1106" width="7" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="624" y="1121" style="text-anchor:start">-2.65%</text>
</g>
<text x="100" y="1126" style="text-anchor:start">BenchmarkContains</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1132" width="145" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="762" y="1147" style="text-anchor:start">-48.54%</text>
</g>
<text x="100" y="1152" style="text-anchor:start">BenchmarkFind</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1158" width="128" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="745" y="1173" style="text-anchor:start">-42.71%</text>
</g>
<text x="100" y="1178" style="text-anchor:start">BenchmarkFindWithinSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="526" y="1184" width="86" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="521" y="1199" style="text-anchor:end">+28.77%</text>
</g>
<text x="100" y="1204" style="text-anchor:start">BenchmarkFindSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="527" y="1210" width="85" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="522" y="1225" style="text-anchor:end">+28.47%</text>
</g>
<text x="100" y="1230" style="text-anchor:start">BenchmarkFindNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1236" width="188" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="805" y="1251" style="text-anchor:start">-62.84%</text>
</g>
<text x="100" y="1256" style="text-anchor:start">BenchmarkContents</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1262" width="174" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="791" y="1277" style="text-anchor:start">-58.06%</text>
</g>
<text x="100" y="1282" style="text-anchor:start">BenchmarkContentsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1288" width="189" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="806" y="1303" style="text-anchor:start">-63.13%</text>
</g>
<text x="100" y="1308" style="text-anchor:start">BenchmarkChildren</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1314" width="114" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="731" y="1329" style="text-anchor:start">-38.24%</text>
</g>
<text x="100" y="1334" style="text-anchor:start">BenchmarkChildrenFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1340" width="10" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="627" y="1355" style="text-anchor:start">-3.66%</text>
</g>
<text x="100" y="1360" style="text-anchor:start">BenchmarkParent</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1366" width="18" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="635" y="1381" style="text-anchor:start">-6.06%</text>
</g>
<text x="100" y="1386" style="text-anchor:start">BenchmarkParentFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="602" y="1392" width="10" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="597" y="1407" style="text-anchor:end">+3.64%</text>
</g>
<text x="100" y="1412" style="text-anchor:start">BenchmarkParents</text>
<g style="font-style:italic;font-size:75%">
<rect x="608" y="1418" width="4" height="20" style="fill-opacity:0.3;fill:red"/>
<text x="603" y="1433" style="text-anchor:end">+1.44%</text>
</g>
<text x="100" y="1438" style="text-anchor:start">BenchmarkParentsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1444" width="133" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="750" y="1459" style="text-anchor:start">-44.35%</text>
</g>
<text x="100" y="1464" style="text-anchor:start">BenchmarkParentsUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1470" width="95" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="712" y="1485" style="text-anchor:start">-31.99%</text>
</g>
<text x="100" y="1490" style="text-anchor:start">BenchmarkParentsUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1496" width="97" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="714" y="1511" style="text-anchor:start">-32.62%</text>
</g>
<text x="100" y="1516" style="text-anchor:start">BenchmarkParentsUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1522" width="137" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="754" y="1537" style="text-anchor:start">-45.83%</text>
</g>
<text x="100" y="1542" style="text-anchor:start">BenchmarkParentsFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1548" width="90" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="707" y="1563" style="text-anchor:start">-30.05%</text>
</g>
<text x="100" y="1568" style="text-anchor:start">BenchmarkParentsFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1574" width="89" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="706" y="1589" style="text-anchor:start">-29.97%</text>
</g>
<text x="100" y="1594" style="text-anchor:start">BenchmarkParentsFilteredUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1600" width="77" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="694" y="1615" style="text-anchor:start">-25.96%</text>
</g>
<text x="100" y="1620" style="text-anchor:start">BenchmarkSiblings</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1626" width="80" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="697" y="1641" style="text-anchor:start">-26.67%</text>
</g>
<text x="100" y="1646" style="text-anchor:start">BenchmarkSiblingsFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1652" width="199" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="816" y="1667" style="text-anchor:start">-66.40%</text>
</g>
<text x="100" y="1672" style="text-anchor:start">BenchmarkNext</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1678" width="193" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="810" y="1693" style="text-anchor:start">-64.46%</text>
</g>
<text x="100" y="1698" style="text-anchor:start">BenchmarkNextFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1704" width="79" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="696" y="1719" style="text-anchor:start">-26.50%</text>
</g>
<text x="100" y="1724" style="text-anchor:start">BenchmarkNextAll</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1730" width="78" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="695" y="1745" style="text-anchor:start">-26.27%</text>
</g>
<text x="100" y="1750" style="text-anchor:start">BenchmarkNextAllFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1756" width="200" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="817" y="1771" style="text-anchor:start">-66.84%</text>
</g>
<text x="100" y="1776" style="text-anchor:start">BenchmarkPrev</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1782" width="193" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="810" y="1797" style="text-anchor:start">-64.35%</text>
</g>
<text x="100" y="1802" style="text-anchor:start">BenchmarkPrevFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1808" width="120" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="737" y="1823" style="text-anchor:start">-40.05%</text>
</g>
<text x="100" y="1828" style="text-anchor:start">BenchmarkPrevAll</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1834" width="119" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="736" y="1849" style="text-anchor:start">-39.74%</text>
</g>
<text x="100" y="1854" style="text-anchor:start">BenchmarkPrevAllFiltered</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1860" width="155" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="772" y="1875" style="text-anchor:start">-51.73%</text>
</g>
<text x="100" y="1880" style="text-anchor:start">BenchmarkNextUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1886" width="100" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="717" y="1901" style="text-anchor:start">-33.42%</text>
</g>
<text x="100" y="1906" style="text-anchor:start">BenchmarkNextUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1912" width="121" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="738" y="1927" style="text-anchor:start">-40.42%</text>
</g>
<text x="100" y="1932" style="text-anchor:start">BenchmarkNextUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1938" width="140" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="757" y="1953" style="text-anchor:start">-46.87%</text>
</g>
<text x="100" y="1958" style="text-anchor:start">BenchmarkPrevUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1964" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="716" y="1979" style="text-anchor:start">-33.14%</text>
</g>
<text x="100" y="1984" style="text-anchor:start">BenchmarkPrevUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="1990" width="123" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="740" y="2005" style="text-anchor:start">-41.19%</text>
</g>
<text x="100" y="2010" style="text-anchor:start">BenchmarkPrevUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2016" width="167" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="784" y="2031" style="text-anchor:start">-55.92%</text>
</g>
<text x="100" y="2036" style="text-anchor:start">BenchmarkNextFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2042" width="97" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="714" y="2057" style="text-anchor:start">-32.49%</text>
</g>
<text x="100" y="2062" style="text-anchor:start">BenchmarkNextFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2068" width="99" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="716" y="2083" style="text-anchor:start">-33.00%</text>
</g>
<text x="100" y="2088" style="text-anchor:start">BenchmarkNextFilteredUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2094" width="175" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="792" y="2109" style="text-anchor:start">-58.54%</text>
</g>
<text x="100" y="2114" style="text-anchor:start">BenchmarkPrevFilteredUntil</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2120" width="101" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="718" y="2135" style="text-anchor:start">-33.80%</text>
</g>
<text x="100" y="2140" style="text-anchor:start">BenchmarkPrevFilteredUntilSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2146" width="100" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="717" y="2161" style="text-anchor:start">-33.44%</text>
</g>
<text x="100" y="2166" style="text-anchor:start">BenchmarkPrevFilteredUntilNodes</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2172" width="74" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="691" y="2187" style="text-anchor:start">-24.82%</text>
</g>
<text x="100" y="2192" style="text-anchor:start">BenchmarkClosest</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2198" width="103" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="720" y="2213" style="text-anchor:start">-34.45%</text>
</g>
<text x="100" y="2218" style="text-anchor:start">BenchmarkClosestSelection</text>
<g style="font-style:italic;font-size:75%">
<rect x="612" y="2224" width="105" height="20" style="fill-opacity:0.3;fill:green"/>
<text x="722" y="2239" style="text-anchor:start">-35.30%</text>
</g>
<text x="100" y="2244" style="text-anchor:start">BenchmarkClosestNodes</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

+470
View File
@@ -0,0 +1,470 @@
PASS
BenchmarkFirst 20000000 96.3 ns/op
BenchmarkLast 20000000 95.7 ns/op
BenchmarkEq 20000000 97.1 ns/op
BenchmarkSlice 20000000 92.3 ns/op
BenchmarkGet 1000000000 2.06 ns/op
BenchmarkIndex 1000000 1069 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
BenchmarkIndexSelector 100000 26750 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.7 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.8 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 219078 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 22345 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 209 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 209 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 2568 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 26715 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 30058 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 66346 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 72646 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 65493 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 20000 79466 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 65494 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 20000 79387 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 386571 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 230664 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 230705 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.61 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 9520 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 15960 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
BenchmarkAttr 50000000 30.4 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 100000 18718 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 606 ns/op
BenchmarkIs 100000 29289 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 23834 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 2436 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 67106 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 66042 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 565347 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 27677 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 72162 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 460124 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 459390 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 500000 3395 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 5193 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 667 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 3591 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 43168 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 45836 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 92348 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 95306 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 72782 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 157639 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 157510 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 16987 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 21174 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 21238 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 66536 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 71822 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 10745 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 12399 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 44640 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 49713 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 10743 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 12456 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 17600 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 19460 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 92630 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 61285 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 25859 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 230236 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 77837 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 20784 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 46147 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 67164 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 66628 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 46697 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 68646 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 68745 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 4909 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 744 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 733 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 220.793s
+476
View File
@@ -0,0 +1,476 @@
PASS
BenchmarkFirst 20000000 95.5 ns/op
BenchmarkLast 20000000 94.9 ns/op
BenchmarkEq 20000000 95.7 ns/op
BenchmarkSlice 20000000 91.7 ns/op
BenchmarkGet 1000000000 2.05 ns/op
BenchmarkIndex 1000000 1079 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
BenchmarkIndexSelector 100000 26972 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.8 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.7 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 213800 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 21811 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 205 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 202 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 2467 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 25643 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 29566 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 66894 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 72183 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 65516 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 20000 78880 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 65232 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 20000 78813 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 388834 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 228552 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 228365 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.62 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 9548 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 15900 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 1650 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.5 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 100000 18873 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 616 ns/op
BenchmarkIs 100000 29499 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 23733 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 2404 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 65376 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 65322 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 558933 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.1 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 27841 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 72096 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 457349 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 459324 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 500000 3435 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 5241 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 667 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 3639 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 44867 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 46476 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 92559 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 96142 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 73931 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 159820 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 158811 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 17203 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 21358 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 21338 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 66463 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 72503 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 10881 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 12588 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 45075 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 50455 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 10933 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 12579 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 17751 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 19702 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 93586 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 61155 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 25805 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 232225 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 78316 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 20657 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 46567 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 67227 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 66995 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 47361 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 68802 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 68928 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 4922 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 738 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 737 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 224.003s
+478
View File
@@ -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
+477
View File
@@ -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
+477
View File
@@ -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
+11 -11
View File
@@ -6,7 +6,7 @@ import (
func BenchmarkFirst(b *testing.B) {
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
b.StartTimer()
for i := 0; i < b.N; i++ {
sel.First()
@@ -15,7 +15,7 @@ func BenchmarkFirst(b *testing.B) {
func BenchmarkLast(b *testing.B) {
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
b.StartTimer()
for i := 0; i < b.N; i++ {
sel.Last()
@@ -24,7 +24,7 @@ func BenchmarkLast(b *testing.B) {
func BenchmarkEq(b *testing.B) {
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
j := 0
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -37,7 +37,7 @@ func BenchmarkEq(b *testing.B) {
func BenchmarkSlice(b *testing.B) {
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
j := 0
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -50,7 +50,7 @@ func BenchmarkSlice(b *testing.B) {
func BenchmarkGet(b *testing.B) {
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
j := 0
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -65,7 +65,7 @@ func BenchmarkIndex(b *testing.B) {
var j int
b.StopTimer()
sel := DocB().Root.Find("#Main")
sel := DocB().Find("#Main")
b.StartTimer()
for i := 0; i < b.N; i++ {
j = sel.Index()
@@ -77,7 +77,7 @@ func BenchmarkIndexSelector(b *testing.B) {
var j int
b.StopTimer()
sel := DocB().Root.Find("#manual-nav dl dd:nth-child(1)")
sel := DocB().Find("#manual-nav dl dd:nth-child(1)")
b.StartTimer()
for i := 0; i < b.N; i++ {
j = sel.IndexSelector("dd")
@@ -89,8 +89,8 @@ func BenchmarkIndexOfNode(b *testing.B) {
var j int
b.StopTimer()
sel := DocB().Root.Find("span a")
sel2 := DocB().Root.Find("span a:nth-child(3)")
sel := DocB().Find("span a")
sel2 := DocB().Find("span a:nth-child(3)")
n := sel2.Get(0)
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -102,8 +102,8 @@ func BenchmarkIndexOfNode(b *testing.B) {
func BenchmarkIndexOfSelection(b *testing.B) {
var j int
b.StopTimer()
sel := DocB().Root.Find("span a")
sel2 := DocB().Root.Find("span a:nth-child(3)")
sel := DocB().Find("span a")
sel2 := DocB().Find("span a:nth-child(3)")
b.StartTimer()
for i := 0; i < b.N; i++ {
j = sel.IndexOfSelection(sel2)
+2 -2
View File
@@ -12,10 +12,10 @@ func BenchmarkMetalReviewExample(b *testing.B) {
var buf bytes.Buffer
b.StopTimer()
doc := LoadDoc("metalreview.html")
doc := loadDoc("metalreview.html")
b.StartTimer()
for i := 0; i < b.N; i++ {
doc.Root.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) {
var band, title string
var score float64
var e error
+6 -6
View File
@@ -8,7 +8,7 @@ func BenchmarkAdd(b *testing.B) {
var n int
b.StopTimer()
sel := DocB().Root.Find("dd")
sel := DocB().Find("dd")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -24,8 +24,8 @@ func BenchmarkAddSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocB().Root.Find("dd")
sel2 := DocB().Root.Find("h2[title]")
sel := DocB().Find("dd")
sel2 := DocB().Find("h2[title]")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -41,8 +41,8 @@ func BenchmarkAddNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocB().Root.Find("dd")
sel2 := DocB().Root.Find("h2[title]")
sel := DocB().Find("dd")
sel2 := DocB().Find("h2[title]")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -59,7 +59,7 @@ func BenchmarkAndSelf(b *testing.B) {
var n int
b.StopTimer()
sel := DocB().Root.Find("dd").Parent()
sel := DocB().Find("dd").Parent()
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
+18 -18
View File
@@ -8,7 +8,7 @@ func BenchmarkFilter(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -24,7 +24,7 @@ func BenchmarkNot(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -40,7 +40,7 @@ func BenchmarkFilterFunction(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
f := func(i int, s *Selection) bool {
return len(s.Get(0).Attr) > 0
}
@@ -59,7 +59,7 @@ func BenchmarkNotFunction(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
f := func(i int, s *Selection) bool {
return len(s.Get(0).Attr) > 0
}
@@ -78,8 +78,8 @@ func BenchmarkFilterNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-2")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-2")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -96,8 +96,8 @@ func BenchmarkNotNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-1")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-1")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -114,8 +114,8 @@ func BenchmarkFilterSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-2")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-2")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -131,8 +131,8 @@ func BenchmarkNotSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-1")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-1")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -148,7 +148,7 @@ func BenchmarkHas(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -164,8 +164,8 @@ func BenchmarkHasNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".tocnumber")
sel := DocW().Find("li")
sel2 := DocW().Find(".tocnumber")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -182,8 +182,8 @@ func BenchmarkHasSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".tocnumber")
sel := DocW().Find("li")
sel2 := DocW().Find(".tocnumber")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -199,7 +199,7 @@ func BenchmarkEnd(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li").Has(".tocnumber")
sel := DocW().Find("li").Has(".tocnumber")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
+22 -2
View File
@@ -8,7 +8,7 @@ func BenchmarkEach(b *testing.B) {
var tmp, n int
b.StopTimer()
sel := DocW().Root.Find("td")
sel := DocW().Find("td")
f := func(i int, s *Selection) {
tmp++
}
@@ -26,7 +26,7 @@ func BenchmarkMap(b *testing.B) {
var tmp, n int
b.StopTimer()
sel := DocW().Root.Find("td")
sel := DocW().Find("td")
f := func(i int, s *Selection) string {
tmp++
return string(tmp)
@@ -40,3 +40,23 @@ func BenchmarkMap(b *testing.B) {
}
b.Logf("Map=%d", n)
}
func BenchmarkEachWithBreak(b *testing.B) {
var tmp, n int
b.StopTimer()
sel := DocW().Find("td")
f := func(i int, s *Selection) bool {
tmp++
return tmp < 10
}
b.StartTimer()
for i := 0; i < b.N; i++ {
tmp = 0
sel.EachWithBreak(f)
if n == 0 {
n = tmp
}
}
b.Logf("Each=%d", n)
}
+4 -4
View File
@@ -8,7 +8,7 @@ func BenchmarkAttr(b *testing.B) {
var s string
b.StopTimer()
sel := DocW().Root.Find("h1")
sel := DocW().Find("h1")
b.StartTimer()
for i := 0; i < b.N; i++ {
s, _ = sel.Attr("id")
@@ -18,7 +18,7 @@ func BenchmarkAttr(b *testing.B) {
func BenchmarkText(b *testing.B) {
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
sel.Text()
@@ -29,7 +29,7 @@ func BenchmarkLength(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
n = sel.Length()
@@ -39,7 +39,7 @@ func BenchmarkLength(b *testing.B) {
func BenchmarkHtml(b *testing.B) {
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
sel.Html()
+10 -10
View File
@@ -8,7 +8,7 @@ func BenchmarkIs(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
y = sel.Is(".toclevel-2")
@@ -20,7 +20,7 @@ func BenchmarkIsPositional(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
y = sel.Is("li:nth-child(2)")
@@ -32,7 +32,7 @@ func BenchmarkIsFunction(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1")
sel := DocW().Find(".toclevel-1")
f := func(i int, s *Selection) bool {
return i == 8
}
@@ -47,8 +47,8 @@ func BenchmarkIsSelection(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-2")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-2")
b.StartTimer()
for i := 0; i < b.N; i++ {
y = sel.IsSelection(sel2)
@@ -60,8 +60,8 @@ func BenchmarkIsNodes(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("li")
sel2 := DocW().Root.Find(".toclevel-2")
sel := DocW().Find("li")
sel2 := DocW().Find(".toclevel-2")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -74,7 +74,7 @@ func BenchmarkHasClass(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("span")
sel := DocW().Find("span")
b.StartTimer()
for i := 0; i < b.N; i++ {
y = sel.HasClass("official")
@@ -86,8 +86,8 @@ func BenchmarkContains(b *testing.B) {
var y bool
b.StopTimer()
sel := DocW().Root.Find("span.url")
sel2 := DocW().Root.Find("a[rel=\"nofollow\"]")
sel := DocW().Find("span.url")
sel2 := DocW().Find("a[rel=\"nofollow\"]")
node := sel2.Nodes[0]
b.StartTimer()
for i := 0; i < b.N; i++ {
+105 -55
View File
@@ -9,10 +9,10 @@ func BenchmarkFind(b *testing.B) {
for i := 0; i < b.N; i++ {
if n == 0 {
n = DocB().Root.Find("dd").Length()
n = DocB().Find("dd").Length()
} else {
DocB().Root.Find("dd")
DocB().Find("dd")
}
}
b.Logf("Find=%d", n)
@@ -22,7 +22,7 @@ func BenchmarkFindWithinSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("ul")
sel := DocW().Find("ul")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -38,8 +38,8 @@ func BenchmarkFindSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("ul")
sel2 := DocW().Root.Find("span")
sel := DocW().Find("ul")
sel2 := DocW().Find("span")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -55,8 +55,8 @@ func BenchmarkFindNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("ul")
sel2 := DocW().Root.Find("span")
sel := DocW().Find("ul")
sel2 := DocW().Find("span")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -73,7 +73,7 @@ func BenchmarkContents(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1")
sel := DocW().Find(".toclevel-1")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -89,7 +89,7 @@ func BenchmarkContentsFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1")
sel := DocW().Find(".toclevel-1")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -105,7 +105,7 @@ func BenchmarkChildren(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-2")
sel := DocW().Find(".toclevel-2")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -121,7 +121,7 @@ func BenchmarkChildrenFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h3")
sel := DocW().Find("h3")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -137,7 +137,7 @@ func BenchmarkParent(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -153,7 +153,7 @@ func BenchmarkParentFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li")
sel := DocW().Find("li")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -169,7 +169,7 @@ func BenchmarkParents(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("th a")
sel := DocW().Find("th a")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -185,7 +185,7 @@ func BenchmarkParentsFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("th a")
sel := DocW().Find("th a")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -201,7 +201,7 @@ func BenchmarkParentsUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("th a")
sel := DocW().Find("th a")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -217,8 +217,8 @@ func BenchmarkParentsUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("th a")
sel2 := DocW().Root.Find("#content")
sel := DocW().Find("th a")
sel2 := DocW().Find("#content")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -234,8 +234,8 @@ func BenchmarkParentsUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("th a")
sel2 := DocW().Root.Find("#content")
sel := DocW().Find("th a")
sel2 := DocW().Find("#content")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -252,7 +252,7 @@ func BenchmarkParentsFilteredUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1 a")
sel := DocW().Find(".toclevel-1 a")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -268,8 +268,8 @@ func BenchmarkParentsFilteredUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1 a")
sel2 := DocW().Root.Find("ul")
sel := DocW().Find(".toclevel-1 a")
sel2 := DocW().Find("ul")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -285,8 +285,8 @@ func BenchmarkParentsFilteredUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find(".toclevel-1 a")
sel2 := DocW().Root.Find("ul")
sel := DocW().Find(".toclevel-1 a")
sel2 := DocW().Find("ul")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -303,7 +303,7 @@ func BenchmarkSiblings(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("ul li:nth-child(1)")
sel := DocW().Find("ul li:nth-child(1)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -319,7 +319,7 @@ func BenchmarkSiblingsFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("ul li:nth-child(1)")
sel := DocW().Find("ul li:nth-child(1)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -335,7 +335,7 @@ func BenchmarkNext(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(1)")
sel := DocW().Find("li:nth-child(1)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -351,7 +351,7 @@ func BenchmarkNextFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(1)")
sel := DocW().Find("li:nth-child(1)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -367,7 +367,7 @@ func BenchmarkNextAll(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(3)")
sel := DocW().Find("li:nth-child(3)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -383,7 +383,7 @@ func BenchmarkNextAllFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(3)")
sel := DocW().Find("li:nth-child(3)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -399,7 +399,7 @@ func BenchmarkPrev(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:last-child")
sel := DocW().Find("li:last-child")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -415,7 +415,7 @@ func BenchmarkPrevFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:last-child")
sel := DocW().Find("li:last-child")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -433,7 +433,7 @@ func BenchmarkPrevAll(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(4)")
sel := DocW().Find("li:nth-child(4)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -449,7 +449,7 @@ func BenchmarkPrevAllFiltered(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:nth-child(4)")
sel := DocW().Find("li:nth-child(4)")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -465,7 +465,7 @@ func BenchmarkNextUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:first-child")
sel := DocW().Find("li:first-child")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -481,8 +481,8 @@ func BenchmarkNextUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("ul")
sel := DocW().Find("h2")
sel2 := DocW().Find("ul")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -498,8 +498,8 @@ func BenchmarkNextUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("p")
sel := DocW().Find("h2")
sel2 := DocW().Find("p")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -516,7 +516,7 @@ func BenchmarkPrevUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("li:last-child")
sel := DocW().Find("li:last-child")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -532,8 +532,8 @@ func BenchmarkPrevUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("ul")
sel := DocW().Find("h2")
sel2 := DocW().Find("ul")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -549,8 +549,8 @@ func BenchmarkPrevUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("p")
sel := DocW().Find("h2")
sel2 := DocW().Find("p")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -567,7 +567,7 @@ func BenchmarkNextFilteredUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -583,8 +583,8 @@ func BenchmarkNextFilteredUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("div")
sel := DocW().Find("h2")
sel2 := DocW().Find("div")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -600,8 +600,8 @@ func BenchmarkNextFilteredUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("div")
sel := DocW().Find("h2")
sel2 := DocW().Find("div")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -618,7 +618,7 @@ func BenchmarkPrevFilteredUntil(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel := DocW().Find("h2")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -634,8 +634,8 @@ func BenchmarkPrevFilteredUntilSelection(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("div")
sel := DocW().Find("h2")
sel2 := DocW().Find("div")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
@@ -651,8 +651,8 @@ func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
var n int
b.StopTimer()
sel := DocW().Root.Find("h2")
sel2 := DocW().Root.Find("div")
sel := DocW().Find("h2")
sel2 := DocW().Find("div")
nodes := sel2.Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -664,3 +664,53 @@ func BenchmarkPrevFilteredUntilNodes(b *testing.B) {
}
b.Logf("PrevFilteredUntilNodes=%d", n)
}
func BenchmarkClosest(b *testing.B) {
var n int
b.StopTimer()
sel := Doc().Find(".container-fluid")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
n = sel.Closest(".pvk-content").Length()
} else {
sel.Closest(".pvk-content")
}
}
b.Logf("Closest=%d", n)
}
func BenchmarkClosestSelection(b *testing.B) {
var n int
b.StopTimer()
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".pvk-content")
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
n = sel.ClosestSelection(sel2).Length()
} else {
sel.ClosestSelection(sel2)
}
}
b.Logf("ClosestSelection=%d", n)
}
func BenchmarkClosestNodes(b *testing.B) {
var n int
b.StopTimer()
sel := Doc().Find(".container-fluid")
nodes := Doc().Find(".pvk-content").Nodes
b.StartTimer()
for i := 0; i < b.N; i++ {
if n == 0 {
n = sel.ClosestNodes(nodes...).Length()
} else {
sel.ClosestNodes(nodes...)
}
}
b.Logf("ClosestNodes=%d", n)
}
+33 -16
View File
@@ -1,4 +1,4 @@
// Copyright (c) 2012, Martin Angers & Contributors
// Copyright (c) 2012-2014, Martin Angers & Contributors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
@@ -23,25 +23,32 @@
/*
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 depends on Go's experimental html package, which must be installed so that it
can be imported as "exp/html". See this tutorial on how to install it
accordingly: http://code.google.com/p/go-wiki/wiki/InstallingExp
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.
It uses Cascadia as CSS selector (similar to Sizzle for jQuery). This dependency
is automatically installed when using "go get ..." to install GoQuery.
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 repository's wiki for various options on how to do this.
To provide a chainable interface, error management is strict, and goquery panics
if an invalid Cascadia selector is used (this is consistent with the behavior of
jQuery/Sizzle/document.querySelectorAll, where an error is thrown). This is
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
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.
- Eq()
@@ -65,10 +72,20 @@ The various methods are split into files based on the category of behavior:
* iteration.go : methods to loop over the selection's nodes.
- Each()
- EachWithBreak()
- 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.
- Attr()
- Attr(), RemoveAttr(), SetAttr()
- AddClass(), HasClass(), RemoveClass(), ToggleClass()
- Html()
- Length()
- Size(), which is an alias for Length()
@@ -76,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.
- Contains()
- HasClass()
- Is...()
* traversal.go : methods to traverse the HTML document tree.
@@ -88,8 +104,9 @@ The various methods are split into files based on the category of behavior:
- Prev...()
- Siblings...()
* type.go : definition of the types exposed by GoQuery.
* type.go : definition of the types exposed by goquery.
- Document
- Selection
- Matcher
*/
package goquery
+68
View File
@@ -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
View File
@@ -2,38 +2,27 @@ package goquery
import (
"fmt"
"log"
// In real use, this import would be required (not in this example, since it
// is part of the goquery package)
//"github.com/PuerkitoBio/goquery"
"strconv"
)
// This example scrapes the 10 reviews shown on the home page of MetalReview.com,
// the best metal review site on the web :) (and no, I'm not affiliated to them!)
func ExampleScrape_MetalReview() {
// This example scrapes the reviews shown on the home page of metalsucks.net.
func ExampleScrape_MetalSucks() {
// Load the HTML document (in real use, the type would be *goquery.Document)
var doc *Document
var e error
if doc, e = NewDocument("http://metalreview.com"); e != nil {
panic(e.Error())
doc, err := NewDocument("http://metalsucks.net")
if err != nil {
log.Fatal(err)
}
// Find the review items (the type of the Selection would be *goquery.Selection)
doc.Root.Find(".slider-row:nth-child(1) .slider-item").Each(func(i int, s *Selection) {
var band, title string
var score float64
// 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)
}
doc.Find(".reviews-wrap article .review-rhs").Each(func(i int, s *Selection) {
// For each item found, get the band and title
band := s.Find("h3").Text()
title := s.Find("i").Text()
fmt.Printf("Review %d: %s - %s\n", i, band, title)
})
// 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
+26 -17
View File
@@ -1,40 +1,49 @@
package goquery
import (
"exp/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.
// The selector string is run in the context of the document of the current
// Selection object.
func (this *Selection) Add(selector string) *Selection {
return this.AddNodes(findWithSelector([]*html.Node{this.document.rootNode}, selector)...)
func (s *Selection) Add(selector string) *Selection {
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.
func (this *Selection) AddSelection(sel *Selection) *Selection {
func (s *Selection) AddSelection(sel *Selection) *Selection {
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().
func (this *Selection) Union(sel *Selection) *Selection {
return this.AddSelection(sel)
// Union is an alias for AddSelection.
func (s *Selection) Union(sel *Selection) *Selection {
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.
func (this *Selection) AddNodes(nodes ...*html.Node) *Selection {
return pushStack(this, appendWithoutDuplicates(this.Nodes, nodes))
func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
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
// with the previous one.
func (this *Selection) AndSelf() *Selection {
return this.AddSelection(this.prevSel)
func (s *Selection) AndSelf() *Selection {
return s.AddSelection(s.prevSel)
}
+23 -23
View File
@@ -5,64 +5,64 @@ import (
)
func TestAdd(t *testing.T) {
sel := Doc().Root.Find("div.row-fluid").Add("a")
AssertLength(t, sel.Nodes, 19)
sel := Doc().Find("div.row-fluid").Add("a")
assertLength(t, sel.Nodes, 19)
}
func TestAddRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Add("a").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestAddSelection(t *testing.T) {
sel := Doc().Root.Find("div.row-fluid")
sel2 := Doc().Root.Find("a")
sel := Doc().Find("div.row-fluid")
sel2 := Doc().Find("a")
sel = sel.AddSelection(sel2)
AssertLength(t, sel.Nodes, 19)
assertLength(t, sel.Nodes, 19)
}
func TestAddSelectionNil(t *testing.T) {
sel := Doc().Root.Find("div.row-fluid")
AssertLength(t, sel.Nodes, 9)
sel := Doc().Find("div.row-fluid")
assertLength(t, sel.Nodes, 9)
sel = sel.AddSelection(nil)
AssertLength(t, sel.Nodes, 9)
assertLength(t, sel.Nodes, 9)
}
func TestAddSelectionRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Find("a")
sel2 = sel.AddSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestAddNodes(t *testing.T) {
sel := Doc().Root.Find("div.pvk-gutter")
sel2 := Doc().Root.Find(".pvk-content")
sel := Doc().Find("div.pvk-gutter")
sel2 := Doc().Find(".pvk-content")
sel = sel.AddNodes(sel2.Nodes...)
AssertLength(t, sel.Nodes, 9)
assertLength(t, sel.Nodes, 9)
}
func TestAddNodesNone(t *testing.T) {
sel := Doc().Root.Find("div.pvk-gutter").AddNodes()
AssertLength(t, sel.Nodes, 6)
sel := Doc().Find("div.pvk-gutter").AddNodes()
assertLength(t, sel.Nodes, 6)
}
func TestAddNodesRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Find("a")
sel2 = sel.AddNodes(sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestAndSelf(t *testing.T) {
sel := Doc().Root.Find(".span12").Last().AndSelf()
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find(".span12").Last().AndSelf()
assertLength(t, sel.Nodes, 2)
}
func TestAndSelfRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Find("a").AndSelf().End().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
+76 -61
View File
@@ -2,85 +2,104 @@ package goquery
import (
"code.google.com/p/cascadia"
"exp/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.
func (this *Selection) Filter(selector string) *Selection {
return pushStack(this, winnow(this, selector, true))
func (s *Selection) Filter(selector string) *Selection {
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.
func (this *Selection) Not(selector string) *Selection {
return pushStack(this, winnow(this, selector, false))
func (s *Selection) Not(selector string) *Selection {
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.
func (this *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
return pushStack(this, winnowFunction(this, f, true))
func (s *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
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.
func (this *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
return pushStack(this, winnowFunction(this, f, false))
func (s *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
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.
func (this *Selection) FilterNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, true))
func (s *Selection) FilterNodes(nodes ...*html.Node) *Selection {
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.
func (this *Selection) NotNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, false))
func (s *Selection) NotNodes(nodes ...*html.Node) *Selection {
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.
// It returns a new Selection object for this subset of elements.
func (this *Selection) FilterSelection(s *Selection) *Selection {
if s == nil {
return pushStack(this, winnowNodes(this, nil, true))
func (s *Selection) FilterSelection(sel *Selection) *Selection {
if sel == nil {
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
// Selection object.
// It returns a new Selection object with the matching elements removed.
func (this *Selection) NotSelection(s *Selection) *Selection {
if s == nil {
return pushStack(this, winnowNodes(this, nil, false))
// NotSelection removes elements from the Selection that match a node in the specified
// Selection object. It returns a new Selection object with the matching elements removed.
func (s *Selection) NotSelection(sel *Selection) *Selection {
if sel == nil {
return pushStack(s, winnowNodes(s, nil, false))
}
return pushStack(this, winnowNodes(this, s.Nodes, false))
return pushStack(s, winnowNodes(s, sel.Nodes, false))
}
// Intersection() is an alias for FilterSelection().
func (this *Selection) Intersection(s *Selection) *Selection {
return this.FilterSelection(s)
// Intersection is an alias for FilterSelection.
func (s *Selection) Intersection(sel *Selection) *Selection {
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.
// It returns a new Selection object with the matching elements.
func (this *Selection) Has(selector string) *Selection {
return this.HasSelection(this.document.Root.Find(selector))
func (s *Selection) Has(selector string) *Selection {
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.
// It returns a new Selection object with the matching elements.
func (this *Selection) HasNodes(nodes ...*html.Node) *Selection {
return this.FilterFunction(func(_ int, s *Selection) bool {
func (s *Selection) HasNodes(nodes ...*html.Node) *Selection {
return s.FilterFunction(func(_ int, sel *Selection) bool {
// Add all nodes that contain one of the specified nodes
for _, n := range nodes {
if s.Contains(n) {
if sel.Contains(n) {
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.
// 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 {
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.
func (this *Selection) End() *Selection {
if this.prevSel != nil {
return this.prevSel
func (s *Selection) End() *Selection {
if s.prevSel != nil {
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.
func winnow(sel *Selection, selector string, keep bool) []*html.Node {
cs := cascadia.MustCompile(selector)
func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
// Optimize if keep is requested
if keep {
return cs.Filter(sel.Nodes)
} else {
// Use grep
return grep(sel, func(i int, s *Selection) bool {
return !cs.Match(s.Get(0))
})
return m.Filter(sel.Nodes)
}
return nil
// Use grep
return grep(sel, func(i int, s *Selection) bool {
return !m.Match(s.Get(0))
})
}
// Filter based on an array of nodes, and the indicator to keep (Filter) or
+68 -68
View File
@@ -5,187 +5,187 @@ import (
)
func TestFilter(t *testing.T) {
sel := Doc().Root.Find(".span12").Filter(".alert")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".span12").Filter(".alert")
assertLength(t, sel.Nodes, 1)
}
func TestFilterNone(t *testing.T) {
sel := Doc().Root.Find(".span12").Filter(".zzalert")
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find(".span12").Filter(".zzalert")
assertLength(t, sel.Nodes, 0)
}
func TestFilterRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Filter(".alert").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestFilterFunction(t *testing.T) {
sel := Doc().Root.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
})
AssertLength(t, sel.Nodes, 2)
assertLength(t, sel.Nodes, 2)
}
func TestFilterFunctionRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.FilterFunction(func(i int, s *Selection) bool {
return i > 0
}).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestFilterNode(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.FilterNodes(sel.Nodes[2])
AssertLength(t, sel2.Nodes, 1)
assertLength(t, sel2.Nodes, 1)
}
func TestFilterNodeRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.FilterNodes(sel.Nodes[2]).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestFilterSelection(t *testing.T) {
sel := Doc().Root.Find(".link")
sel2 := Doc().Root.Find("a[ng-click]")
sel := Doc().Find(".link")
sel2 := Doc().Find("a[ng-click]")
sel3 := sel.FilterSelection(sel2)
AssertLength(t, sel3.Nodes, 1)
assertLength(t, sel3.Nodes, 1)
}
func TestFilterSelectionRollback(t *testing.T) {
sel := Doc().Root.Find(".link")
sel2 := Doc().Root.Find("a[ng-click]")
sel := Doc().Find(".link")
sel2 := Doc().Find("a[ng-click]")
sel2 = sel.FilterSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestFilterSelectionNil(t *testing.T) {
var sel2 *Selection
sel := Doc().Root.Find(".link")
sel := Doc().Find(".link")
sel3 := sel.FilterSelection(sel2)
AssertLength(t, sel3.Nodes, 0)
assertLength(t, sel3.Nodes, 0)
}
func TestNot(t *testing.T) {
sel := Doc().Root.Find(".span12").Not(".alert")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".span12").Not(".alert")
assertLength(t, sel.Nodes, 1)
}
func TestNotRollback(t *testing.T) {
sel := Doc().Root.Find(".span12")
sel := Doc().Find(".span12")
sel2 := sel.Not(".alert").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNotNone(t *testing.T) {
sel := Doc().Root.Find(".span12").Not(".zzalert")
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find(".span12").Not(".zzalert")
assertLength(t, sel.Nodes, 2)
}
func TestNotFunction(t *testing.T) {
sel := Doc().Root.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
})
AssertLength(t, sel.Nodes, 1)
assertLength(t, sel.Nodes, 1)
}
func TestNotFunctionRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.NotFunction(func(i int, s *Selection) bool {
return i > 0
}).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNotNode(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.NotNodes(sel.Nodes[2])
AssertLength(t, sel2.Nodes, 2)
assertLength(t, sel2.Nodes, 2)
}
func TestNotNodeRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.NotNodes(sel.Nodes[2]).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNotSelection(t *testing.T) {
sel := Doc().Root.Find(".link")
sel2 := Doc().Root.Find("a[ng-click]")
sel := Doc().Find(".link")
sel2 := Doc().Find("a[ng-click]")
sel3 := sel.NotSelection(sel2)
AssertLength(t, sel3.Nodes, 6)
assertLength(t, sel3.Nodes, 6)
}
func TestNotSelectionRollback(t *testing.T) {
sel := Doc().Root.Find(".link")
sel2 := Doc().Root.Find("a[ng-click]")
sel := Doc().Find(".link")
sel2 := Doc().Find("a[ng-click]")
sel2 = sel.NotSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestIntersection(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter")
sel2 := Doc().Root.Find("div").Intersection(sel)
AssertLength(t, sel2.Nodes, 6)
sel := Doc().Find(".pvk-gutter")
sel2 := Doc().Find("div").Intersection(sel)
assertLength(t, sel2.Nodes, 6)
}
func TestIntersectionRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter")
sel2 := Doc().Root.Find("div")
sel := Doc().Find(".pvk-gutter")
sel2 := Doc().Find("div")
sel2 = sel.Intersection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestHas(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").Has(".center-content")
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find(".container-fluid").Has(".center-content")
assertLength(t, sel.Nodes, 2)
// Has() returns the high-level .container-fluid div, and the one that is the immediate parent of center-content
}
func TestHasRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.Has(".center-content").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestHasNodes(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".center-content")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".center-content")
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
}
func TestHasNodesRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".center-content")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".center-content")
sel2 = sel.HasNodes(sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestHasSelection(t *testing.T) {
sel := Doc().Root.Find("p")
sel2 := Doc().Root.Find("small")
sel := Doc().Find("p")
sel2 := Doc().Find("small")
sel = sel.HasSelection(sel2)
AssertLength(t, sel.Nodes, 1)
assertLength(t, sel.Nodes, 1)
}
func TestHasSelectionRollback(t *testing.T) {
sel := Doc().Root.Find("p")
sel2 := Doc().Root.Find("small")
sel := Doc().Find("p")
sel2 := Doc().Find("small")
sel2 = sel.HasSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestEnd(t *testing.T) {
sel := Doc().Root.Find("p").Has("small").End()
AssertLength(t, sel.Nodes, 4)
sel := Doc().Find("p").Has("small").End()
assertLength(t, sel.Nodes, 4)
}
func TestEndToTop(t *testing.T) {
sel := Doc().Root.Find("p").Has("small").End().End().End()
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find("p").Has("small").End().End().End()
assertLength(t, sel.Nodes, 0)
}
+22 -9
View File
@@ -1,19 +1,32 @@
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.
func (this *Selection) Each(f func(int, *Selection)) *Selection {
for i, n := range this.Nodes {
f(i, newSingleSelection(n, this.document))
func (s *Selection) Each(f func(int, *Selection)) *Selection {
for i, n := range s.Nodes {
f(i, newSingleSelection(n, s.document))
}
return this
return s
}
// Map() passes each element in the current matched set through a function,
// 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
// out of the loop by returning false in the callback function. It returns the
// current Selection object.
func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
for i, n := range s.Nodes {
if !f(i, newSingleSelection(n, s.document)) {
return s
}
}
return s
}
// Map passes each element in the current matched set through a function,
// producing a slice of string holding the returned values.
func (this *Selection) Map(f func(int, *Selection) string) (result []string) {
for i, n := range this.Nodes {
result = append(result, f(i, newSingleSelection(n, this.document)))
func (s *Selection) Map(f func(int, *Selection) string) (result []string) {
for i, n := range s.Nodes {
result = append(result, f(i, newSingleSelection(n, s.document)))
}
return result
+41 -6
View File
@@ -1,14 +1,15 @@
package goquery
import (
"exp/html"
"testing"
"golang.org/x/net/html"
)
func TestEach(t *testing.T) {
var cnt int
sel := Doc().Root.Find(".hero-unit .row-fluid").Each(func(i int, n *Selection) {
sel := Doc().Find(".hero-unit .row-fluid").Each(func(i int, n *Selection) {
cnt++
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
}).Find("a")
@@ -16,13 +17,28 @@ func TestEach(t *testing.T) {
if cnt != 4 {
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) {
var cnt int
sel := Doc().Find(".hero-unit .row-fluid").EachWithBreak(func(i int, n *Selection) bool {
cnt++
t.Logf("At index %v, node %v", i, n.Nodes[0].Data)
return false
}).Find("a")
if cnt != 1 {
t.Errorf("Expected Each() to call function 1 time, got %v times.", cnt)
}
assertLength(t, sel.Nodes, 6)
}
func TestEachEmptySelection(t *testing.T) {
var cnt int
sel := Doc().Root.Find("zzzz")
sel := Doc().Find("zzzz")
sel.Each(func(i int, n *Selection) {
cnt++
})
@@ -30,11 +46,11 @@ func TestEachEmptySelection(t *testing.T) {
t.Error("Expected Each() to not be called on empty Selection.")
}
sel2 := sel.Find("div")
AssertLength(t, sel2.Nodes, 0)
assertLength(t, sel2.Nodes, 0)
}
func TestMap(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
vals := sel.Map(func(i int, s *Selection) string {
n := s.Get(0)
if n.Type == html.ElementNode {
@@ -51,3 +67,22 @@ func TestMap(t *testing.T) {
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
View File
@@ -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
}
+194
View File
@@ -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)
}
+37
View File
@@ -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
+197 -28
View File
@@ -2,50 +2,75 @@ package goquery
import (
"bytes"
"exp/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
// construct such as Each() or Map() method.
func (this *Selection) Attr(attrName string) (val string, exists bool) {
if len(this.Nodes) == 0 {
// construct such as Each or Map method.
func (s *Selection) Attr(attrName string) (val string, exists bool) {
if len(s.Nodes) == 0 {
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.
func (this *Selection) Text() string {
func (s *Selection) Text() string {
var buf bytes.Buffer
// Slightly optimized vs calling Each(): no single selection object created
for _, n := range this.Nodes {
// Slightly optimized vs calling Each: no single selection object created
for _, n := range s.Nodes {
buf.WriteString(getNodeText(n))
}
return buf.String()
}
// Size() is an alias for Length().
func (this *Selection) Size() int {
return this.Length()
// Size is an alias for Length.
func (s *Selection) Size() int {
return s.Length()
}
// Length() returns the number of elements in the Selection object.
func (this *Selection) Length() int {
return len(this.Nodes)
// Length returns the number of elements in the Selection object.
func (s *Selection) Length() int {
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.
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
// the nodes usint html.Render().
// the nodes using html.Render.
var buf bytes.Buffer
if len(this.Nodes) > 0 {
for c := this.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
if len(s.Nodes) > 0 {
for c := s.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
e = html.Render(&buf, c)
if e != nil {
return
@@ -57,6 +82,97 @@ func (this *Selection) Html() (ret string, e error) {
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.
func getNodeText(node *html.Node) string {
if node.Type == html.TextNode {
@@ -73,18 +189,71 @@ func getNodeText(node *html.Node) string {
return ""
}
// Private function to get the specified attribute's value from a node.
func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
if n == nil {
return
return nil
}
for _, a := range n.Attr {
for i, a := range n.Attr {
if a.Key == attrName {
val = a.Val
exists = true
return
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
exists = true
}
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
}
+167 -6
View File
@@ -7,7 +7,7 @@ import (
)
func TestAttrExists(t *testing.T) {
if val, ok := Doc().Root.Find("a").Attr("href"); !ok {
if val, ok := Doc().Find("a").Attr("href"); !ok {
t.Error("Expected a value for the href attribute.")
} else {
t.Logf("Href of first anchor: %v.", val)
@@ -15,20 +15,46 @@ func TestAttrExists(t *testing.T) {
}
func TestAttrNotExist(t *testing.T) {
if val, ok := Doc().Root.Find("div.row-fluid").Attr("href"); ok {
if val, ok := Doc().Find("div.row-fluid").Attr("href"); ok {
t.Errorf("Expected no value for the href attribute, got %v.", val)
}
}
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) {
txt := Doc().Root.Find("h1").Text()
txt := Doc().Find("h1").Text()
if strings.Trim(txt, " \n\r\t") != "Provok.in" {
t.Errorf("Expected text to be Provok.in, found %s.", txt)
}
}
func TestText2(t *testing.T) {
txt := Doc().Root.Find(".hero-unit .container-fluid .row-fluid:nth-child(1)").Text()
txt := Doc().Find(".hero-unit .container-fluid .row-fluid:nth-child(1)").Text()
if ok, e := regexp.MatchString(`^\s+Provok\.in\s+Prove your point.\s+$`, txt); !ok || e != nil {
t.Errorf("Expected text to be Provok.in Prove your point., found %s.", txt)
if e != nil {
@@ -38,7 +64,7 @@ func TestText2(t *testing.T) {
}
func TestText3(t *testing.T) {
txt := Doc().Root.Find(".pvk-gutter").First().Text()
txt := Doc().Find(".pvk-gutter").First().Text()
// There's an &nbsp; character in there...
if ok, e := regexp.MatchString(`^[\s\x{00A0}]+$`, txt); !ok || e != nil {
t.Errorf("Expected spaces, found <%v>.", txt)
@@ -49,7 +75,7 @@ func TestText3(t *testing.T) {
}
func TestHtml(t *testing.T) {
txt, e := Doc().Root.Find("h1").Html()
txt, e := Doc().Find("h1").Html()
if e != nil {
t.Errorf("Error: %s.", e)
}
@@ -61,3 +87,138 @@ func TestHtml(t *testing.T) {
}
}
}
func TestNbsp(t *testing.T) {
src := `<p>Some&nbsp;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)
}
}
+34 -70
View File
@@ -2,91 +2,55 @@ package goquery
import (
"code.google.com/p/cascadia"
"exp/html"
"regexp"
"strings"
"golang.org/x/net/html"
)
//var rxNeedsContext = `^[\x20\t\r\n\f]*[>+~]|:(nth|eq|gt|lt|first|last|even|odd)(-child)?(?:\((\d*)\)|)(?:[^-]|$)`
// 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.
func (this *Selection) Is(selector string) bool {
if len(this.Nodes) > 0 {
// The selector must be done on the document if it has positional criteria
// TODO : Not sure it is required, as Cascadia's selector checks within the parent of the
// node when there is such a positionaly selector... In jQuery, this is for the
// non-css selectors (Sizzle-implemented selectors, an extension of CSS)
/*if ok, e := regexp.MatchString(rxNeedsContext, selector); ok {
sel := this.document.Root.Find(selector)
for _, n := range this.Nodes {
if sel.IndexOfNode(n) > -1 {
return true
}
}
} else if e != nil {
panic(e.Error())
} else {*/
// Attempt a match with the selector
cs := cascadia.MustCompile(selector)
if len(this.Nodes) == 1 {
return cs.Match(this.Nodes[0])
} else {
return len(cs.Filter(this.Nodes)) > 0
}
//}
func (s *Selection) Is(selector string) bool {
if len(s.Nodes) > 0 {
return s.IsMatcher(cascadia.MustCompile(selector))
}
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.
func (this *Selection) IsFunction(f func(int, *Selection) bool) bool {
return this.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 (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 {
var rx = regexp.MustCompile("[\t\r\n]")
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 = rx.ReplaceAllString(" "+elClass+" ", " ")
if strings.Index(elClass, class) > -1 {
return true
}
}
func (s *Selection) IsMatcher(m Matcher) bool {
if len(s.Nodes) > 0 {
if len(s.Nodes) == 1 {
return m.Match(s.Nodes[0])
}
return len(m.Filter(s.Nodes)) > 0
}
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.
// 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.
func (this *Selection) Contains(n *html.Node) bool {
return sliceContains(this.Nodes, n)
func (s *Selection) Contains(n *html.Node) bool {
return sliceContains(s.Nodes, n)
}
+17 -38
View File
@@ -5,28 +5,28 @@ import (
)
func TestIs(t *testing.T) {
sel := Doc().Root.Find(".footer p:nth-child(1)")
sel := Doc().Find(".footer p:nth-child(1)")
if !sel.Is("p") {
t.Error("Expected .footer p:nth-child(1) to be p.")
}
}
func TestIsPositional(t *testing.T) {
sel := Doc().Root.Find(".footer p:nth-child(2)")
sel := Doc().Find(".footer p:nth-child(2)")
if !sel.Is("p:nth-child(2)") {
t.Error("Expected .footer p:nth-child(2) to be p:nth-child(2).")
}
}
func TestIsPositionalNot(t *testing.T) {
sel := Doc().Root.Find(".footer p:nth-child(1)")
sel := Doc().Find(".footer p:nth-child(1)")
if sel.Is("p:nth-child(2)") {
t.Error("Expected .footer p:nth-child(1) NOT to be p:nth-child(2).")
}
}
func TestIsFunction(t *testing.T) {
ok := Doc().Root.Find("div").IsFunction(func(i int, s *Selection) bool {
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
return s.HasClass("container-fluid")
})
@@ -36,7 +36,7 @@ func TestIsFunction(t *testing.T) {
}
func TestIsFunctionRollback(t *testing.T) {
ok := Doc().Root.Find("div").IsFunction(func(i int, s *Selection) bool {
ok := Doc().Find("div").IsFunction(func(i int, s *Selection) bool {
return s.HasClass("container-fluid")
})
@@ -46,8 +46,8 @@ func TestIsFunctionRollback(t *testing.T) {
}
func TestIsSelection(t *testing.T) {
sel := Doc().Root.Find("div")
sel2 := Doc().Root.Find(".pvk-gutter")
sel := Doc().Find("div")
sel2 := Doc().Find(".pvk-gutter")
if !sel.IsSelection(sel2) {
t.Error("Expected some div to have a pvk-gutter class.")
@@ -55,8 +55,8 @@ func TestIsSelection(t *testing.T) {
}
func TestIsSelectionNot(t *testing.T) {
sel := Doc().Root.Find("div")
sel2 := Doc().Root.Find("a")
sel := Doc().Find("div")
sel2 := Doc().Find("a")
if sel.IsSelection(sel2) {
t.Error("Expected some div NOT to be an anchor.")
@@ -64,53 +64,32 @@ func TestIsSelectionNot(t *testing.T) {
}
func TestIsNodes(t *testing.T) {
sel := Doc().Root.Find("div")
sel2 := Doc().Root.Find(".footer")
sel := Doc().Find("div")
sel2 := Doc().Find(".footer")
if !sel.IsNodes(sel2.Nodes[0]) {
t.Error("Expected some div to have a footer class.")
}
}
func TestHasClass(t *testing.T) {
sel := Doc().Root.Find("div")
if !sel.HasClass("span12") {
t.Error("Expected at least one div to have class span12.")
}
}
func TestHasClassNone(t *testing.T) {
sel := Doc().Root.Find("h2")
if sel.HasClass("toto") {
t.Error("Expected h1 to have no class.")
}
}
func TestHasClassNotFirst(t *testing.T) {
sel := Doc().Root.Find(".alert")
if !sel.HasClass("alert-error") {
t.Error("Expected .alert to also have class .alert-error.")
}
}
func TestDocContains(t *testing.T) {
sel := Doc().Root.Find("h1")
if !Doc().Root.Contains(sel.Nodes[0]) {
sel := Doc().Find("h1")
if !Doc().Contains(sel.Nodes[0]) {
t.Error("Expected document to contain H1 tag.")
}
}
func TestSelContains(t *testing.T) {
sel := Doc().Root.Find(".row-fluid")
sel2 := Doc().Root.Find("a[ng-click]")
sel := Doc().Find(".row-fluid")
sel2 := Doc().Find("a[ng-click]")
if !sel.Contains(sel2.Nodes[0]) {
t.Error("Expected .row-fluid to contain a[ng-click] tag.")
}
}
func TestSelNotContains(t *testing.T) {
sel := Doc().Root.Find("a.link")
sel2 := Doc().Root.Find("span")
sel := Doc().Find("a.link")
sel2 := Doc().Find("span")
if sel.Contains(sel2.Nodes[0]) {
t.Error("Expected a.link to NOT contain span tag.")
}
+2 -2
View File
@@ -19,7 +19,7 @@
<div class="pvk-gutter">
&nbsp;
</div>
<div class="pvk-content">
<div class="pvk-content" id="pc1">
<div ng-controller="HeroCtrl" class="hero-unit">
<div class="container-fluid" id="cf2">
<div class="row-fluid" id="cf2-1">
@@ -54,7 +54,7 @@
<div class="pvk-gutter">
&nbsp;
</div>
<div class="pvk-content">
<div class="pvk-content" id="pc2">
<div class="container-fluid" id="cf3">
<div class="row-fluid">
<div ng-cloak="" view-on-display="" ng-controller="MsgCtrl" ng-class="{'displayed': blockIsDisplayed}" class="message-box">
+1 -1
View File
@@ -17,7 +17,7 @@
<div id="nf2" class="two odd row"></div>
<div id="nf3" class="three even 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>
</body>
+361 -161
View File
@@ -2,7 +2,7 @@ package goquery
import (
"code.google.com/p/cascadia"
"exp/html"
"golang.org/x/net/html"
)
type siblingType int
@@ -20,341 +20,544 @@ const (
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
// containing these matched elements.
func (this *Selection) Find(selector string) *Selection {
return pushStack(this, findWithSelector(this.Nodes, selector))
func (s *Selection) Find(selector string) *Selection {
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
// containing these matched elements.
func (this *Selection) FindSelection(sel *Selection) *Selection {
func (s *Selection) FindSelection(sel *Selection) *Selection {
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
// containing these matched elements.
func (this *Selection) FindNodes(nodes ...*html.Node) *Selection {
return pushStack(this, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
if sliceContains(this.Nodes, n) {
func (s *Selection) FindNodes(nodes ...*html.Node) *Selection {
return pushStack(s, mapNodes(nodes, func(i int, n *html.Node) []*html.Node {
if sliceContains(s.Nodes, n) {
return []*html.Node{n}
}
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
// containing these elements.
func (this *Selection) Contents() *Selection {
return pushStack(this, getChildrenNodes(this.Nodes, siblingAllIncludingNonElements))
func (s *Selection) Contents() *Selection {
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
// object containing these elements. Since selectors only act on Element nodes,
// this function is an alias to ChildrenFiltered() unless the selector is empty,
// in which case it is an alias to Contents().
func (this *Selection) ContentsFiltered(selector string) *Selection {
// this function is an alias to ChildrenFiltered unless the selector is empty,
// in which case it is an alias to Contents.
func (s *Selection) ContentsFiltered(selector string) *Selection {
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.
func (this *Selection) Children() *Selection {
return pushStack(this, getChildrenNodes(this.Nodes, siblingAll))
func (s *Selection) Children() *Selection {
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
// Selection object containing these elements.
func (this *Selection) ChildrenFiltered(selector string) *Selection {
return filterAndPush(this, getChildrenNodes(this.Nodes, siblingAll), selector)
func (s *Selection) ChildrenFiltered(selector string) *Selection {
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.
func (this *Selection) Parent() *Selection {
return pushStack(this, getParentNodes(this.Nodes))
func (s *Selection) Parent() *Selection {
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.
func (this *Selection) ParentFiltered(selector string) *Selection {
return filterAndPush(this, getParentNodes(this.Nodes), selector)
func (s *Selection) ParentFiltered(selector string) *Selection {
return filterAndPush(s, getParentNodes(s.Nodes), cascadia.MustCompile(selector))
}
// Parents() gets the ancestors of each element in the current Selection. It
// ParentMatcher gets the parent of each element in the Selection filtered by a
// matcher. It returns a new Selection object containing the matched elements.
func (s *Selection) ParentMatcher(m Matcher) *Selection {
return filterAndPush(s, getParentNodes(s.Nodes), m)
}
// 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
// until a match is found.
for ; n != nil; n = n.Parent {
if m.Match(n) {
return []*html.Node{n}
}
}
return nil
}))
}
// 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.
func (s *Selection) ClosestNodes(nodes ...*html.Node) *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
// until a match is found.
for ; n != nil; n = n.Parent {
if isInSlice(nodes, n) {
return []*html.Node{n}
}
}
return nil
}))
}
// 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
// in the DOM tree.
func (s *Selection) ClosestSelection(sel *Selection) *Selection {
if sel == nil {
return pushStack(s, nil)
}
return s.ClosestNodes(sel.Nodes...)
}
// Parents gets the ancestors of each element in the current Selection. It
// returns a new Selection object with the matched elements.
func (this *Selection) Parents() *Selection {
return pushStack(this, getParentsNodes(this.Nodes, "", nil))
func (s *Selection) Parents() *Selection {
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.
func (this *Selection) ParentsFiltered(selector string) *Selection {
return filterAndPush(this, getParentsNodes(this.Nodes, "", nil), selector)
func (s *Selection) ParentsFiltered(selector string) *Selection {
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
// object containing the matched elements.
func (this *Selection) ParentsUntil(selector string) *Selection {
return pushStack(this, getParentsNodes(this.Nodes, selector, nil))
func (s *Selection) ParentsUntil(selector string) *Selection {
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
// new Selection object containing the matched elements.
func (this *Selection) ParentsUntilSelection(sel *Selection) *Selection {
func (s *Selection) ParentsUntilSelection(sel *Selection) *Selection {
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
// new Selection object containing the matched elements.
func (this *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
return pushStack(this, getParentsNodes(this.Nodes, "", nodes))
func (s *Selection) ParentsUntilNodes(nodes ...*html.Node) *Selection {
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
// object containing the matched elements.
func (this *Selection) ParentsFilteredUntil(filterSelector string, untilSelector string) *Selection {
return filterAndPush(this, getParentsNodes(this.Nodes, untilSelector, nil), filterSelector)
func (s *Selection) ParentsFilteredUntil(filterSelector, untilSelector string) *Selection {
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
// 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 {
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
// Selection object containing the matched elements.
func (this *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(this, getParentsNodes(this.Nodes, "", nodes), filterSelector)
func (s *Selection) ParentsFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
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.
func (this *Selection) Siblings() *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingAll, "", nil))
func (s *Selection) Siblings() *Selection {
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
// matched elements.
func (this *Selection) SiblingsFiltered(selector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingAll, "", nil), selector)
func (s *Selection) SiblingsFiltered(selector string) *Selection {
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.
func (this *Selection) Next() *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingNext, "", nil))
func (s *Selection) Next() *Selection {
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
// containing the matched elements.
func (this *Selection) NextFiltered(selector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNext, "", nil), selector)
func (s *Selection) NextFiltered(selector string) *Selection {
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.
func (this *Selection) NextAll() *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextAll, "", nil))
func (s *Selection) NextAll() *Selection {
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
// containing the matched elements.
func (this *Selection) NextAllFiltered(selector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextAll, "", nil), selector)
func (s *Selection) NextAllFiltered(selector string) *Selection {
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.
func (this *Selection) Prev() *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrev, "", nil))
func (s *Selection) Prev() *Selection {
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
// containing the matched elements.
func (this *Selection) PrevFiltered(selector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrev, "", nil), selector)
func (s *Selection) PrevFiltered(selector string) *Selection {
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.
func (this *Selection) PrevAll() *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevAll, "", nil))
func (s *Selection) PrevAll() *Selection {
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
// containing the matched elements.
func (this *Selection) PrevAllFiltered(selector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevAll, "", nil), selector)
func (s *Selection) PrevAllFiltered(selector string) *Selection {
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
// object containing the matched elements.
func (this *Selection) NextUntil(selector string) *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextUntil,
selector, nil))
func (s *Selection) NextUntil(selector string) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
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
// object containing the matched elements.
func (this *Selection) NextUntilSelection(sel *Selection) *Selection {
func (s *Selection) NextUntilSelection(sel *Selection) *Selection {
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
// object containing the matched elements.
func (this *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingNextUntil,
"", nodes))
func (s *Selection) NextUntilNodes(nodes ...*html.Node) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingNextUntil,
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
// object containing the matched elements.
func (this *Selection) PrevUntil(selector string) *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
selector, nil))
func (s *Selection) PrevUntil(selector string) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
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
// object containing the matched elements.
func (this *Selection) PrevUntilSelection(sel *Selection) *Selection {
func (s *Selection) PrevUntilSelection(sel *Selection) *Selection {
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
// object containing the matched elements.
func (this *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
return pushStack(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
"", nodes))
func (s *Selection) PrevUntilNodes(nodes ...*html.Node) *Selection {
return pushStack(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
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.
// It returns a new Selection object containing the matched elements.
func (this *Selection) NextFilteredUntil(filterSelector string, untilSelector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextUntil,
untilSelector, nil), filterSelector)
func (s *Selection) NextFilteredUntil(filterSelector, untilSelector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
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
// 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 {
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
// Selection object containing the matched elements.
func (this *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingNextUntil,
"", nodes), filterSelector)
func (s *Selection) NextFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingNextUntil,
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.
// It returns a new Selection object containing the matched elements.
func (this *Selection) PrevFilteredUntil(filterSelector string, untilSelector string) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
untilSelector, nil), filterSelector)
func (s *Selection) PrevFilteredUntil(filterSelector, untilSelector string) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
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
// 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 {
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
// Selection object containing the matched elements.
func (this *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(this, getSiblingNodes(this.Nodes, siblingPrevUntil,
"", nodes), filterSelector)
func (s *Selection) PrevFilteredUntilNodes(filterSelector string, nodes ...*html.Node) *Selection {
return filterAndPush(s, getSiblingNodes(s.Nodes, siblingPrevUntil,
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.
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
sel := &Selection{nodes, srcSel.document, nil}
// Filter based on selector and push on stack
return pushStack(srcSel, winnow(sel, selector, true))
// Filter based on matcher and push on stack
return pushStack(srcSel, winnow(sel, m, true))
}
// Internal implementation of Find that return raw nodes.
func findWithSelector(nodes []*html.Node, selector string) []*html.Node {
// Compile the selector once
sel := cascadia.MustCompile(selector)
func findWithMatcher(nodes []*html.Node, m Matcher) []*html.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) {
// 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 {
if c.Type == html.ElementNode {
result = append(result, sel.MatchAll(c)...)
result = append(result, m.MatchAll(c)...)
}
}
return
})
}
// 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).
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) {
for p := n.Parent; p != nil; p = p.Parent {
sel := newSingleSelection(p, nil)
if stopSelector != "" {
if sel.Is(stopSelector) {
if stopm != nil {
if sel.IsMatcher(stopm) {
break
}
} else if len(stopNodes) > 0 {
@@ -371,18 +574,17 @@ func getParentsNodes(nodes []*html.Node, stopSelector string, stopNodes []*html.
}
// 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
// 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)
if st == siblingNextUntil || st == siblingPrevUntil {
f = func(n *html.Node) bool {
if untilSelector != "" {
// Selector-based condition
if untilm != nil {
// Matcher-based condition
sel := newSingleSelection(n, nil)
return sel.Is(untilSelector)
return sel.IsMatcher(untilm)
} else if len(untilNodes) > 0 {
// Nodes-based condition
sel := newSingleSelection(n, nil)
@@ -447,16 +649,14 @@ func getChildrenWithSiblingType(parent *html.Node, st siblingType, skipNode *htm
}
if ret == nil || ret.Type == html.ElementNode || st == siblingAllIncludingNonElements {
return
} else {
// Not a valid node, try again from this one
cur = ret
}
// Not a valid node, try again from this one
cur = ret
}
panic("Unreachable code reached.")
}
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 st == siblingNextUntil || st == siblingPrevUntil {
if untilFunc(c) {
+355 -236
View File
@@ -1,578 +1,697 @@
package goquery
import (
"strings"
"testing"
)
func TestFind(t *testing.T) {
sel := Doc().Root.Find("div.row-fluid")
AssertLength(t, sel.Nodes, 9)
sel := Doc().Find("div.row-fluid")
assertLength(t, sel.Nodes, 9)
}
func TestFindRollback(t *testing.T) {
sel := Doc().Root.Find("div.row-fluid")
sel := Doc().Find("div.row-fluid")
sel2 := sel.Find("a").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestFindNotSelf(t *testing.T) {
sel := Doc().Root.Find("h1").Find("h1")
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find("h1").Find("h1")
assertLength(t, sel.Nodes, 0)
}
func TestFindInvalidSelector(t *testing.T) {
defer AssertPanic(t)
Doc().Root.Find(":+ ^")
defer assertPanic(t)
Doc().Find(":+ ^")
}
func TestChainedFind(t *testing.T) {
sel := Doc().Root.Find("div.hero-unit").Find(".row-fluid")
AssertLength(t, sel.Nodes, 4)
sel := Doc().Find("div.hero-unit").Find(".row-fluid")
assertLength(t, sel.Nodes, 4)
}
func TestChildren(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").Children()
AssertLength(t, sel.Nodes, 5)
sel := Doc().Find(".pvk-content").Children()
assertLength(t, sel.Nodes, 5)
}
func TestChildrenRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Children().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestContents(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").Contents()
AssertLength(t, sel.Nodes, 13)
sel := Doc().Find(".pvk-content").Contents()
assertLength(t, sel.Nodes, 13)
}
func TestContentsRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.Contents().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestChildrenFiltered(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").ChildrenFiltered(".hero-unit")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").ChildrenFiltered(".hero-unit")
assertLength(t, sel.Nodes, 1)
}
func TestChildrenFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.ChildrenFiltered(".hero-unit").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestContentsFiltered(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").ContentsFiltered(".hero-unit")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".pvk-content").ContentsFiltered(".hero-unit")
assertLength(t, sel.Nodes, 1)
}
func TestContentsFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".pvk-content")
sel2 := sel.ContentsFiltered(".hero-unit").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestChildrenFilteredNone(t *testing.T) {
sel := Doc().Root.Find(".pvk-content").ChildrenFiltered("a.btn")
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find(".pvk-content").ChildrenFiltered("a.btn")
assertLength(t, sel.Nodes, 0)
}
func TestParent(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").Parent()
AssertLength(t, sel.Nodes, 3)
sel := Doc().Find(".container-fluid").Parent()
assertLength(t, sel.Nodes, 3)
}
func TestParentRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.Parent().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentBody(t *testing.T) {
sel := Doc().Root.Find("body").Parent()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find("body").Parent()
assertLength(t, sel.Nodes, 1)
}
func TestParentFiltered(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").ParentFiltered(".hero-unit")
AssertLength(t, sel.Nodes, 1)
AssertClass(t, sel, "hero-unit")
sel := Doc().Find(".container-fluid").ParentFiltered(".hero-unit")
assertLength(t, sel.Nodes, 1)
assertClass(t, sel, "hero-unit")
}
func TestParentFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.ParentFiltered(".hero-unit").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParents(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").Parents()
AssertLength(t, sel.Nodes, 8)
sel := Doc().Find(".container-fluid").Parents()
assertLength(t, sel.Nodes, 8)
}
func TestParentsOrder(t *testing.T) {
sel := Doc().Root.Find("#cf2").Parents()
AssertLength(t, sel.Nodes, 6)
AssertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
sel := Doc().Find("#cf2").Parents()
assertLength(t, sel.Nodes, 6)
assertSelectionIs(t, sel, ".hero-unit", ".pvk-content", "div.row-fluid", "#cf1", "body", "html")
}
func TestParentsRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.Parents().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsFiltered(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").ParentsFiltered("body")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".container-fluid").ParentsFiltered("body")
assertLength(t, sel.Nodes, 1)
}
func TestParentsFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.ParentsFiltered("body").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsUntil(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").ParentsUntil("body")
AssertLength(t, sel.Nodes, 6)
sel := Doc().Find(".container-fluid").ParentsUntil("body")
assertLength(t, sel.Nodes, 6)
}
func TestParentsUntilRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.ParentsUntil("body").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsUntilSelection(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".pvk-content")
sel = sel.ParentsUntilSelection(sel2)
AssertLength(t, sel.Nodes, 3)
assertLength(t, sel.Nodes, 3)
}
func TestParentsUntilSelectionRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".pvk-content")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".pvk-content")
sel2 = sel.ParentsUntilSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsUntilNodes(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".pvk-content, .hero-unit")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".pvk-content, .hero-unit")
sel = sel.ParentsUntilNodes(sel2.Nodes...)
AssertLength(t, sel.Nodes, 2)
assertLength(t, sel.Nodes, 2)
}
func TestParentsUntilNodesRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".pvk-content, .hero-unit")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".pvk-content, .hero-unit")
sel2 = sel.ParentsUntilNodes(sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsFilteredUntil(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find(".container-fluid").ParentsFilteredUntil(".pvk-content", "body")
assertLength(t, sel.Nodes, 2)
}
func TestParentsFilteredUntilRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.ParentsFilteredUntil(".pvk-content", "body").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsFilteredUntilSelection(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".row-fluid")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".row-fluid")
sel = sel.ParentsFilteredUntilSelection("div", sel2)
AssertLength(t, sel.Nodes, 3)
assertLength(t, sel.Nodes, 3)
}
func TestParentsFilteredUntilSelectionRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".row-fluid")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".row-fluid")
sel2 = sel.ParentsFilteredUntilSelection("div", sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestParentsFilteredUntilNodes(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".row-fluid")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".row-fluid")
sel = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...)
AssertLength(t, sel.Nodes, 1)
assertLength(t, sel.Nodes, 1)
}
func TestParentsFilteredUntilNodesRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel2 := Doc().Root.Find(".row-fluid")
sel := Doc().Find(".container-fluid")
sel2 := Doc().Find(".row-fluid")
sel2 = sel.ParentsFilteredUntilNodes("body", sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestSiblings(t *testing.T) {
sel := Doc().Root.Find("h1").Siblings()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find("h1").Siblings()
assertLength(t, sel.Nodes, 1)
}
func TestSiblingsRollback(t *testing.T) {
sel := Doc().Root.Find("h1")
sel := Doc().Find("h1")
sel2 := sel.Siblings().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestSiblings2(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter").Siblings()
AssertLength(t, sel.Nodes, 9)
sel := Doc().Find(".pvk-gutter").Siblings()
assertLength(t, sel.Nodes, 9)
}
func TestSiblings3(t *testing.T) {
sel := Doc().Root.Find("body>.container-fluid").Siblings()
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find("body>.container-fluid").Siblings()
assertLength(t, sel.Nodes, 0)
}
func TestSiblingsFiltered(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
AssertLength(t, sel.Nodes, 3)
sel := Doc().Find(".pvk-gutter").SiblingsFiltered(".pvk-content")
assertLength(t, sel.Nodes, 3)
}
func TestSiblingsFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter")
sel := Doc().Find(".pvk-gutter")
sel2 := sel.SiblingsFiltered(".pvk-content").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNext(t *testing.T) {
sel := Doc().Root.Find("h1").Next()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find("h1").Next()
assertLength(t, sel.Nodes, 1)
}
func TestNextRollback(t *testing.T) {
sel := Doc().Root.Find("h1")
sel := Doc().Find("h1")
sel2 := sel.Next().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNext2(t *testing.T) {
sel := Doc().Root.Find(".close").Next()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".close").Next()
assertLength(t, sel.Nodes, 1)
}
func TestNextNone(t *testing.T) {
sel := Doc().Root.Find("small").Next()
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find("small").Next()
assertLength(t, sel.Nodes, 0)
}
func TestNextFiltered(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").NextFiltered("div")
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find(".container-fluid").NextFiltered("div")
assertLength(t, sel.Nodes, 2)
}
func TestNextFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".container-fluid")
sel := Doc().Find(".container-fluid")
sel2 := sel.NextFiltered("div").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextFiltered2(t *testing.T) {
sel := Doc().Root.Find(".container-fluid").NextFiltered("[ng-view]")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".container-fluid").NextFiltered("[ng-view]")
assertLength(t, sel.Nodes, 1)
}
func TestPrev(t *testing.T) {
sel := Doc().Root.Find(".red").Prev()
AssertLength(t, sel.Nodes, 1)
AssertClass(t, sel, "green")
sel := Doc().Find(".red").Prev()
assertLength(t, sel.Nodes, 1)
assertClass(t, sel, "green")
}
func TestPrevRollback(t *testing.T) {
sel := Doc().Root.Find(".red")
sel := Doc().Find(".red")
sel2 := sel.Prev().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrev2(t *testing.T) {
sel := Doc().Root.Find(".row-fluid").Prev()
AssertLength(t, sel.Nodes, 5)
sel := Doc().Find(".row-fluid").Prev()
assertLength(t, sel.Nodes, 5)
}
func TestPrevNone(t *testing.T) {
sel := Doc().Root.Find("h2").Prev()
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find("h2").Prev()
assertLength(t, sel.Nodes, 0)
}
func TestPrevFiltered(t *testing.T) {
sel := Doc().Root.Find(".row-fluid").PrevFiltered(".row-fluid")
AssertLength(t, sel.Nodes, 5)
sel := Doc().Find(".row-fluid").PrevFiltered(".row-fluid")
assertLength(t, sel.Nodes, 5)
}
func TestPrevFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".row-fluid")
sel := Doc().Find(".row-fluid")
sel2 := sel.PrevFiltered(".row-fluid").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextAll(t *testing.T) {
sel := Doc().Root.Find("#cf2 div:nth-child(1)").NextAll()
AssertLength(t, sel.Nodes, 3)
sel := Doc().Find("#cf2 div:nth-child(1)").NextAll()
assertLength(t, sel.Nodes, 3)
}
func TestNextAllRollback(t *testing.T) {
sel := Doc().Root.Find("#cf2 div:nth-child(1)")
sel := Doc().Find("#cf2 div:nth-child(1)")
sel2 := sel.NextAll().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextAll2(t *testing.T) {
sel := Doc().Root.Find("div[ng-cloak]").NextAll()
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find("div[ng-cloak]").NextAll()
assertLength(t, sel.Nodes, 1)
}
func TestNextAllNone(t *testing.T) {
sel := Doc().Root.Find(".footer").NextAll()
AssertLength(t, sel.Nodes, 0)
sel := Doc().Find(".footer").NextAll()
assertLength(t, sel.Nodes, 0)
}
func TestNextAllFiltered(t *testing.T) {
sel := Doc().Root.Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find("#cf2 .row-fluid").NextAllFiltered("[ng-cloak]")
assertLength(t, sel.Nodes, 2)
}
func TestNextAllFilteredRollback(t *testing.T) {
sel := Doc().Root.Find("#cf2 .row-fluid")
sel := Doc().Find("#cf2 .row-fluid")
sel2 := sel.NextAllFiltered("[ng-cloak]").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextAllFiltered2(t *testing.T) {
sel := Doc().Root.Find(".close").NextAllFiltered("h4")
AssertLength(t, sel.Nodes, 1)
sel := Doc().Find(".close").NextAllFiltered("h4")
assertLength(t, sel.Nodes, 1)
}
func TestPrevAll(t *testing.T) {
sel := Doc().Root.Find("[ng-view]").PrevAll()
AssertLength(t, sel.Nodes, 2)
sel := Doc().Find("[ng-view]").PrevAll()
assertLength(t, sel.Nodes, 2)
}
func TestPrevAllOrder(t *testing.T) {
sel := Doc().Root.Find("[ng-view]").PrevAll()
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#cf4", "#cf3")
sel := Doc().Find("[ng-view]").PrevAll()
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#cf4", "#cf3")
}
func TestPrevAllRollback(t *testing.T) {
sel := Doc().Root.Find("[ng-view]")
sel := Doc().Find("[ng-view]")
sel2 := sel.PrevAll().End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrevAll2(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter").PrevAll()
AssertLength(t, sel.Nodes, 6)
sel := Doc().Find(".pvk-gutter").PrevAll()
assertLength(t, sel.Nodes, 6)
}
func TestPrevAllFiltered(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
AssertLength(t, sel.Nodes, 3)
sel := Doc().Find(".pvk-gutter").PrevAllFiltered(".pvk-content")
assertLength(t, sel.Nodes, 3)
}
func TestPrevAllFilteredRollback(t *testing.T) {
sel := Doc().Root.Find(".pvk-gutter")
sel := Doc().Find(".pvk-gutter")
sel2 := sel.PrevAllFiltered(".pvk-content").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextUntil(t *testing.T) {
sel := Doc().Root.Find(".alert a").NextUntil("p")
AssertLength(t, sel.Nodes, 1)
AssertSelectionIs(t, sel, "h4")
sel := Doc().Find(".alert a").NextUntil("p")
assertLength(t, sel.Nodes, 1)
assertSelectionIs(t, sel, "h4")
}
func TestNextUntil2(t *testing.T) {
sel := Doc().Root.Find("#cf2-1").NextUntil("[ng-cloak]")
AssertLength(t, sel.Nodes, 1)
AssertSelectionIs(t, sel, "#cf2-2")
sel := Doc().Find("#cf2-1").NextUntil("[ng-cloak]")
assertLength(t, sel.Nodes, 1)
assertSelectionIs(t, sel, "#cf2-2")
}
func TestNextUntilOrder(t *testing.T) {
sel := Doc().Root.Find("#cf2-1").NextUntil("#cf2-4")
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
sel := Doc().Find("#cf2-1").NextUntil("#cf2-4")
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#cf2-2", "#cf2-3")
}
func TestNextUntilRollback(t *testing.T) {
sel := Doc().Root.Find("#cf2-1")
sel := Doc().Find("#cf2-1")
sel2 := sel.PrevUntil("#cf2-4").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextUntilSelection(t *testing.T) {
sel := Doc2().Root.Find("#n2")
sel2 := Doc2().Root.Find("#n4")
sel := Doc2().Find("#n2")
sel2 := Doc2().Find("#n4")
sel2 = sel.NextUntilSelection(sel2)
AssertLength(t, sel2.Nodes, 1)
AssertSelectionIs(t, sel2, "#n3")
assertLength(t, sel2.Nodes, 1)
assertSelectionIs(t, sel2, "#n3")
}
func TestNextUntilSelectionRollback(t *testing.T) {
sel := Doc2().Root.Find("#n2")
sel2 := Doc2().Root.Find("#n4")
sel := Doc2().Find("#n2")
sel2 := Doc2().Find("#n4")
sel2 = sel.NextUntilSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextUntilNodes(t *testing.T) {
sel := Doc2().Root.Find("#n2")
sel2 := Doc2().Root.Find("#n5")
sel := Doc2().Find("#n2")
sel2 := Doc2().Find("#n5")
sel2 = sel.NextUntilNodes(sel2.Nodes...)
AssertLength(t, sel2.Nodes, 2)
AssertSelectionIs(t, sel2, "#n3", "#n4")
assertLength(t, sel2.Nodes, 2)
assertSelectionIs(t, sel2, "#n3", "#n4")
}
func TestNextUntilNodesRollback(t *testing.T) {
sel := Doc2().Root.Find("#n2")
sel2 := Doc2().Root.Find("#n5")
sel := Doc2().Find("#n2")
sel2 := Doc2().Find("#n5")
sel2 = sel.NextUntilNodes(sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrevUntil(t *testing.T) {
sel := Doc().Root.Find(".alert p").PrevUntil("a")
AssertLength(t, sel.Nodes, 1)
AssertSelectionIs(t, sel, "h4")
sel := Doc().Find(".alert p").PrevUntil("a")
assertLength(t, sel.Nodes, 1)
assertSelectionIs(t, sel, "h4")
}
func TestPrevUntil2(t *testing.T) {
sel := Doc().Root.Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
AssertLength(t, sel.Nodes, 1)
AssertSelectionIs(t, sel, "[ng-cloak]")
sel := Doc().Find("[ng-cloak]").PrevUntil(":not([ng-cloak])")
assertLength(t, sel.Nodes, 1)
assertSelectionIs(t, sel, "[ng-cloak]")
}
func TestPrevUntilOrder(t *testing.T) {
sel := Doc().Root.Find("#cf2-4").PrevUntil("#cf2-1")
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
sel := Doc().Find("#cf2-4").PrevUntil("#cf2-1")
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#cf2-3", "#cf2-2")
}
func TestPrevUntilRollback(t *testing.T) {
sel := Doc().Root.Find("#cf2-4")
sel := Doc().Find("#cf2-4")
sel2 := sel.PrevUntil("#cf2-1").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrevUntilSelection(t *testing.T) {
sel := Doc2().Root.Find("#n4")
sel2 := Doc2().Root.Find("#n2")
sel := Doc2().Find("#n4")
sel2 := Doc2().Find("#n2")
sel2 = sel.PrevUntilSelection(sel2)
AssertLength(t, sel2.Nodes, 1)
AssertSelectionIs(t, sel2, "#n3")
assertLength(t, sel2.Nodes, 1)
assertSelectionIs(t, sel2, "#n3")
}
func TestPrevUntilSelectionRollback(t *testing.T) {
sel := Doc2().Root.Find("#n4")
sel2 := Doc2().Root.Find("#n2")
sel := Doc2().Find("#n4")
sel2 := Doc2().Find("#n2")
sel2 = sel.PrevUntilSelection(sel2).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrevUntilNodes(t *testing.T) {
sel := Doc2().Root.Find("#n5")
sel2 := Doc2().Root.Find("#n2")
sel := Doc2().Find("#n5")
sel2 := Doc2().Find("#n2")
sel2 = sel.PrevUntilNodes(sel2.Nodes...)
AssertLength(t, sel2.Nodes, 2)
AssertSelectionIs(t, sel2, "#n4", "#n3")
assertLength(t, sel2.Nodes, 2)
assertSelectionIs(t, sel2, "#n4", "#n3")
}
func TestPrevUntilNodesRollback(t *testing.T) {
sel := Doc2().Root.Find("#n5")
sel2 := Doc2().Root.Find("#n2")
sel := Doc2().Find("#n5")
sel2 := Doc2().Find("#n2")
sel2 = sel.PrevUntilNodes(sel2.Nodes...).End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextFilteredUntil(t *testing.T) {
sel := Doc2().Root.Find(".two").NextFilteredUntil(".even", ".six")
AssertLength(t, sel.Nodes, 4)
AssertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
sel := Doc2().Find(".two").NextFilteredUntil(".even", ".six")
assertLength(t, sel.Nodes, 4)
assertSelectionIs(t, sel, "#n3", "#n5", "#nf3", "#nf5")
}
func TestNextFilteredUntilRollback(t *testing.T) {
sel := Doc2().Root.Find(".two")
sel := Doc2().Find(".two")
sel2 := sel.NextFilteredUntil(".even", ".six").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestNextFilteredUntilSelection(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".five")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".five")
sel = sel.NextFilteredUntilSelection(".even", sel2)
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#n3", "#nf3")
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#n3", "#nf3")
}
func TestNextFilteredUntilSelectionRollback(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".five")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".five")
sel3 := sel.NextFilteredUntilSelection(".even", sel2).End()
AssertEqual(t, sel, sel3)
assertEqual(t, sel, sel3)
}
func TestNextFilteredUntilNodes(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".four")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".four")
sel = sel.NextFilteredUntilNodes(".odd", sel2.Nodes...)
AssertLength(t, sel.Nodes, 4)
AssertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
assertLength(t, sel.Nodes, 4)
assertSelectionIs(t, sel, "#n2", "#n6", "#nf2", "#nf6")
}
func TestNextFilteredUntilNodesRollback(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".four")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".four")
sel3 := sel.NextFilteredUntilNodes(".odd", sel2.Nodes...).End()
AssertEqual(t, sel, sel3)
assertEqual(t, sel, sel3)
}
func TestPrevFilteredUntil(t *testing.T) {
sel := Doc2().Root.Find(".five").PrevFilteredUntil(".odd", ".one")
AssertLength(t, sel.Nodes, 4)
AssertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
sel := Doc2().Find(".five").PrevFilteredUntil(".odd", ".one")
assertLength(t, sel.Nodes, 4)
assertSelectionIs(t, sel, "#n4", "#n2", "#nf4", "#nf2")
}
func TestPrevFilteredUntilRollback(t *testing.T) {
sel := Doc2().Root.Find(".four")
sel := Doc2().Find(".four")
sel2 := sel.PrevFilteredUntil(".odd", ".one").End()
AssertEqual(t, sel, sel2)
assertEqual(t, sel, sel2)
}
func TestPrevFilteredUntilSelection(t *testing.T) {
sel := Doc2().Root.Find(".odd")
sel2 := Doc2().Root.Find(".two")
sel := Doc2().Find(".odd")
sel2 := Doc2().Find(".two")
sel = sel.PrevFilteredUntilSelection(".odd", sel2)
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#n4", "#nf4")
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#n4", "#nf4")
}
func TestPrevFilteredUntilSelectionRollback(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".five")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".five")
sel3 := sel.PrevFilteredUntilSelection(".even", sel2).End()
AssertEqual(t, sel, sel3)
assertEqual(t, sel, sel3)
}
func TestPrevFilteredUntilNodes(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".four")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".four")
sel = sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...)
AssertLength(t, sel.Nodes, 2)
AssertSelectionIs(t, sel, "#n2", "#nf2")
assertLength(t, sel.Nodes, 2)
assertSelectionIs(t, sel, "#n2", "#nf2")
}
func TestPrevFilteredUntilNodesRollback(t *testing.T) {
sel := Doc2().Root.Find(".even")
sel2 := Doc2().Root.Find(".four")
sel := Doc2().Find(".even")
sel2 := Doc2().Find(".four")
sel3 := sel.PrevFilteredUntilNodes(".odd", sel2.Nodes...).End()
AssertEqual(t, sel, sel3)
assertEqual(t, sel, sel3)
}
func TestClosestItself(t *testing.T) {
sel := Doc2().Find(".three")
sel2 := sel.Closest(".row")
assertLength(t, sel2.Nodes, sel.Length())
assertSelectionIs(t, sel2, "#n3", "#nf3")
}
func TestClosestNoDupes(t *testing.T) {
sel := Doc().Find(".span12")
sel2 := sel.Closest(".pvk-content")
assertLength(t, sel2.Nodes, 1)
assertClass(t, sel2, "pvk-content")
}
func TestClosestNone(t *testing.T) {
sel := Doc().Find("h4")
sel2 := sel.Closest("a")
assertLength(t, sel2.Nodes, 0)
}
func TestClosestMany(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.Closest(".pvk-content")
assertLength(t, sel2.Nodes, 2)
assertSelectionIs(t, sel2, "#pc1", "#pc2")
}
func TestClosestRollback(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.Closest(".pvk-content").End()
assertEqual(t, sel, sel2)
}
func TestClosestSelectionItself(t *testing.T) {
sel := Doc2().Find(".three")
sel2 := sel.ClosestSelection(Doc2().Find(".row"))
assertLength(t, sel2.Nodes, sel.Length())
}
func TestClosestSelectionNoDupes(t *testing.T) {
sel := Doc().Find(".span12")
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
assertLength(t, sel2.Nodes, 1)
assertClass(t, sel2, "pvk-content")
}
func TestClosestSelectionNone(t *testing.T) {
sel := Doc().Find("h4")
sel2 := sel.ClosestSelection(Doc().Find("a"))
assertLength(t, sel2.Nodes, 0)
}
func TestClosestSelectionMany(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content"))
assertLength(t, sel2.Nodes, 2)
assertSelectionIs(t, sel2, "#pc1", "#pc2")
}
func TestClosestSelectionRollback(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.ClosestSelection(Doc().Find(".pvk-content")).End()
assertEqual(t, sel, sel2)
}
func TestClosestNodesItself(t *testing.T) {
sel := Doc2().Find(".three")
sel2 := sel.ClosestNodes(Doc2().Find(".row").Nodes...)
assertLength(t, sel2.Nodes, sel.Length())
}
func TestClosestNodesNoDupes(t *testing.T) {
sel := Doc().Find(".span12")
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
assertLength(t, sel2.Nodes, 1)
assertClass(t, sel2, "pvk-content")
}
func TestClosestNodesNone(t *testing.T) {
sel := Doc().Find("h4")
sel2 := sel.ClosestNodes(Doc().Find("a").Nodes...)
assertLength(t, sel2.Nodes, 0)
}
func TestClosestNodesMany(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...)
assertLength(t, sel2.Nodes, 2)
assertSelectionIs(t, sel2, "#pc1", "#pc2")
}
func TestClosestNodesRollback(t *testing.T) {
sel := Doc().Find(".container-fluid")
sel2 := sel.ClosestNodes(Doc().Find(".pvk-content").Nodes...).End()
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)
}
}
+55 -15
View File
@@ -1,9 +1,12 @@
package goquery
import (
"exp/html"
"errors"
"io"
"net/http"
"net/url"
"golang.org/x/net/html"
)
// Document represents an HTML document to be manipulated. Unlike jQuery, which
@@ -12,49 +15,77 @@ import (
// to be told, and that's what the Document class is for. It holds the root
// document node to manipulate, and can make selections on this document.
type Document struct {
Root *Selection
*Selection
Url *url.URL
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.
func NewDocumentFromNode(root *html.Node) (d *Document) {
func NewDocumentFromNode(root *html.Node) *Document {
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
// node, ready to be manipulated.
func NewDocument(url string) (d *Document, e error) {
func NewDocument(url string) (*Document, error) {
// Load the URL
res, e := http.Get(url)
if e != nil {
return
return nil, e
}
return NewDocumentFromResponse(res)
}
// NewDocumentFromReader returns a Document from a generic reader.
// 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
// provided reader is never closed by this call, it is the responsibility
// of the caller to close it if required.
func NewDocumentFromReader(r io.Reader) (*Document, error) {
root, e := html.Parse(r)
if e != nil {
return nil, e
}
return newDocument(root, nil), nil
}
// 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
// node, ready to be manipulated. The response's body is closed on return.
func NewDocumentFromResponse(res *http.Response) (*Document, error) {
if res == nil {
return nil, errors.New("Response is nil pointer")
}
defer res.Body.Close()
// Parse the HTML into nodes
root, e := html.Parse(res.Body)
if e != nil {
return
return nil, e
}
// Create and fill the document
d = newDocument(root, res.Request.URL)
return
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.
func newDocument(root *html.Node, url *url.URL) (d *Document) {
func newDocument(root *html.Node, url *url.URL) *Document {
// Create and fill the document
d = &Document{nil, url, root}
d.Root = newSingleSelection(root, d)
return
d := &Document{nil, url, root}
d.Selection = newSingleSelection(root, d)
return d
}
// 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.
type Selection struct {
Nodes []*html.Node
@@ -71,3 +102,12 @@ func newEmptySelection(doc *Document) *Selection {
func newSingleSelection(node *html.Node, doc *Document) *Selection {
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
}
+101 -20
View File
@@ -1,10 +1,12 @@
package goquery
import (
"exp/html"
"bytes"
"fmt"
"os"
"testing"
"golang.org/x/net/html"
)
// Test helper functions and members
@@ -15,30 +17,42 @@ var docW *Document
func Doc() *Document {
if doc == nil {
doc = LoadDoc("page.html")
doc = loadDoc("page.html")
}
return doc
}
func DocClone() *Document {
return CloneDocument(Doc())
}
func Doc2() *Document {
if doc2 == nil {
doc2 = LoadDoc("page2.html")
doc2 = loadDoc("page2.html")
}
return doc2
}
func Doc2Clone() *Document {
return CloneDocument(Doc2())
}
func DocB() *Document {
if docB == nil {
docB = LoadDoc("gotesting.html")
docB = loadDoc("gotesting.html")
}
return docB
}
func DocBClone() *Document {
return CloneDocument(DocB())
}
func DocW() *Document {
if docW == nil {
docW = LoadDoc("gowiki.html")
docW = loadDoc("gowiki.html")
}
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 {
t.Errorf("Expected %d nodes, found %d.", length, len(nodes))
for i, n := range nodes {
@@ -47,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) {
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 {
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 {
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++ {
if !sel.Eq(i).Is(is[i]) {
t.Errorf("Expected node %d to be %s, found %+v", i, is[i], sel.Get(i))
@@ -73,18 +87,30 @@ func AssertSelectionIs(t *testing.T, sel *Selection, is ...string) {
}
}
func LoadDoc(page string) *Document {
if f, e := os.Open(fmt.Sprintf("./testdata/%s", page)); e != nil {
panic(e.Error())
} else {
defer f.Close()
if node, e := html.Parse(f); e != nil {
panic(e.Error())
} else {
return NewDocumentFromNode(node)
func printSel(t *testing.T, sel *Selection) {
if testing.Verbose() {
h, err := sel.Html()
if err != nil {
t.Fatal(err)
}
t.Log(h)
}
return nil
}
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())
}
defer f.Close()
var node *html.Node
if node, e = html.Parse(f); e != nil {
panic(e.Error())
}
return NewDocumentFromNode(node)
}
func TestNewDocument(t *testing.T) {
@@ -99,3 +125,58 @@ func TestNewDocument(t *testing.T) {
}
}
}
func TestNewDocumentFromReader(t *testing.T) {
cases := []struct {
src string
err bool
sel string
cnt int
}{
0: {
src: `
<html>
<head>
<title>Test</title>
<body>
<h1>Hi</h1>
</body>
</html>`,
sel: "h1",
cnt: 1,
},
1: {
// Actually pretty hard to make html.Parse return an error
// based on content...
src: `<html><body><aef<eqf>>>qq></body></ht>`,
},
}
buf := bytes.NewBuffer(nil)
for i, c := range cases {
buf.Reset()
buf.WriteString(c.src)
d, e := NewDocumentFromReader(buf)
if (e != nil) != c.err {
if c.err {
t.Errorf("[%d] - expected error, got none", i)
} else {
t.Errorf("[%d] - expected no error, got %s", i, e)
}
}
if c.sel != "" {
s := d.Find(c.sel)
if s.Length() != c.cnt {
t.Errorf("[%d] - expected %d nodes, found %d", i, c.cnt, s.Length())
}
}
}
}
func TestNewDocumentFromResponseNil(t *testing.T) {
_, e := NewDocumentFromResponse(nil)
if e == nil {
t.Error("Expected error, got none")
}
}
+7 -10
View File
@@ -1,14 +1,14 @@
package goquery
import (
"exp/html"
"golang.org/x/net/html"
)
func getChildren(n *html.Node) (result []*html.Node) {
for c := n.FirstChild; c != nil; c = c.NextSibling {
result = append(result, c)
}
return
return result
}
// 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
// contain duplicates. The target slice is returned because append() may create
// a new underlying array.
func appendWithoutDuplicates(target []*html.Node,
nodes []*html.Node) []*html.Node {
func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node) []*html.Node {
for _, n := range nodes {
if !isInSlice(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
// function.
func grep(sel *Selection, predicate func(i int, s *Selection) bool) (result []*html.Node) {
for i, n := range sel.Nodes {
if predicate(i, newSingleSelection(n, sel.document)) {
result = append(result, n)
}
}
return
return result
}
// Creates a new Selection object based on the specified nodes, and keeps the
// source Selection object on the stack (linked list).
func pushStack(fromSel *Selection, nodes []*html.Node) (result *Selection) {
result = &Selection{nodes, fromSel.document, fromSel}
return
func pushStack(fromSel *Selection, nodes []*html.Node) *Selection {
result := &Selection{nodes, fromSel.document, fromSel}
return result
}