Browse Source

Vendoring update

Dashie der otter 8 months ago
parent
commit
76d26943bb
Signed by: Dashie <dashie@sigpipe.me> GPG Key ID: C2D57B325840B755
84 changed files with 21553 additions and 1 deletions
  1. 43
    1
      Gopkg.lock
  2. 1
    0
      vendor/github.com/PuerkitoBio/goquery/.gitattributes
  3. 16
    0
      vendor/github.com/PuerkitoBio/goquery/.gitignore
  4. 15
    0
      vendor/github.com/PuerkitoBio/goquery/.travis.yml
  5. 12
    0
      vendor/github.com/PuerkitoBio/goquery/LICENSE
  6. 164
    0
      vendor/github.com/PuerkitoBio/goquery/README.md
  7. 124
    0
      vendor/github.com/PuerkitoBio/goquery/array.go
  8. 123
    0
      vendor/github.com/PuerkitoBio/goquery/doc.go
  9. 70
    0
      vendor/github.com/PuerkitoBio/goquery/expand.go
  10. 163
    0
      vendor/github.com/PuerkitoBio/goquery/filter.go
  11. 39
    0
      vendor/github.com/PuerkitoBio/goquery/iteration.go
  12. 574
    0
      vendor/github.com/PuerkitoBio/goquery/manipulation.go
  13. 275
    0
      vendor/github.com/PuerkitoBio/goquery/property.go
  14. 49
    0
      vendor/github.com/PuerkitoBio/goquery/query.go
  15. 698
    0
      vendor/github.com/PuerkitoBio/goquery/traversal.go
  16. 141
    0
      vendor/github.com/PuerkitoBio/goquery/type.go
  17. 161
    0
      vendor/github.com/PuerkitoBio/goquery/utilities.go
  18. 14
    0
      vendor/github.com/andybalholm/cascadia/.travis.yml
  19. 24
    0
      vendor/github.com/andybalholm/cascadia/LICENSE
  20. 7
    0
      vendor/github.com/andybalholm/cascadia/README.md
  21. 3
    0
      vendor/github.com/andybalholm/cascadia/go.mod
  22. 835
    0
      vendor/github.com/andybalholm/cascadia/parser.go
  23. 622
    0
      vendor/github.com/andybalholm/cascadia/selector.go
  24. 15
    0
      vendor/github.com/davecgh/go-spew/LICENSE
  25. 152
    0
      vendor/github.com/davecgh/go-spew/spew/bypass.go
  26. 38
    0
      vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
  27. 341
    0
      vendor/github.com/davecgh/go-spew/spew/common.go
  28. 306
    0
      vendor/github.com/davecgh/go-spew/spew/config.go
  29. 211
    0
      vendor/github.com/davecgh/go-spew/spew/doc.go
  30. 509
    0
      vendor/github.com/davecgh/go-spew/spew/dump.go
  31. 419
    0
      vendor/github.com/davecgh/go-spew/spew/format.go
  32. 148
    0
      vendor/github.com/davecgh/go-spew/spew/spew.go
  33. 15
    0
      vendor/github.com/go-testfixtures/testfixtures/.editorconfig
  34. 5
    0
      vendor/github.com/go-testfixtures/testfixtures/.env
  35. 1
    0
      vendor/github.com/go-testfixtures/testfixtures/.gitattributes
  36. 27
    0
      vendor/github.com/go-testfixtures/testfixtures/.gitignore
  37. 18
    0
      vendor/github.com/go-testfixtures/testfixtures/.travis.yml
  38. 21
    0
      vendor/github.com/go-testfixtures/testfixtures/LICENSE
  39. 368
    0
      vendor/github.com/go-testfixtures/testfixtures/README.md
  40. 62
    0
      vendor/github.com/go-testfixtures/testfixtures/Taskfile.yml
  41. 75
    0
      vendor/github.com/go-testfixtures/testfixtures/deprecated.go
  42. 41
    0
      vendor/github.com/go-testfixtures/testfixtures/errors.go
  43. 110
    0
      vendor/github.com/go-testfixtures/testfixtures/generate.go
  44. 63
    0
      vendor/github.com/go-testfixtures/testfixtures/helper.go
  45. 44
    0
      vendor/github.com/go-testfixtures/testfixtures/json.go
  46. 133
    0
      vendor/github.com/go-testfixtures/testfixtures/mysql.go
  47. 19
    0
      vendor/github.com/go-testfixtures/testfixtures/options.go
  48. 171
    0
      vendor/github.com/go-testfixtures/testfixtures/oracle.go
  49. 291
    0
      vendor/github.com/go-testfixtures/testfixtures/postgresql.go
  50. 76
    0
      vendor/github.com/go-testfixtures/testfixtures/sqlite.go
  51. 122
    0
      vendor/github.com/go-testfixtures/testfixtures/sqlserver.go
  52. 294
    0
      vendor/github.com/go-testfixtures/testfixtures/testfixtures.go
  53. 34
    0
      vendor/github.com/go-testfixtures/testfixtures/time.go
  54. 27
    0
      vendor/github.com/pmezard/go-difflib/LICENSE
  55. 772
    0
      vendor/github.com/pmezard/go-difflib/difflib/difflib.go
  56. 22
    0
      vendor/github.com/stretchr/testify/LICENSE
  57. 349
    0
      vendor/github.com/stretchr/testify/assert/assertion_format.go
  58. 4
    0
      vendor/github.com/stretchr/testify/assert/assertion_format.go.tmpl
  59. 686
    0
      vendor/github.com/stretchr/testify/assert/assertion_forward.go
  60. 4
    0
      vendor/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
  61. 1256
    0
      vendor/github.com/stretchr/testify/assert/assertions.go
  62. 45
    0
      vendor/github.com/stretchr/testify/assert/doc.go
  63. 10
    0
      vendor/github.com/stretchr/testify/assert/errors.go
  64. 16
    0
      vendor/github.com/stretchr/testify/assert/forward_assertions.go
  65. 127
    0
      vendor/github.com/stretchr/testify/assert/http_assertions.go
  66. 12
    0
      vendor/gopkg.in/yaml.v2/.travis.yml
  67. 201
    0
      vendor/gopkg.in/yaml.v2/LICENSE
  68. 31
    0
      vendor/gopkg.in/yaml.v2/LICENSE.libyaml
  69. 13
    0
      vendor/gopkg.in/yaml.v2/NOTICE
  70. 133
    0
      vendor/gopkg.in/yaml.v2/README.md
  71. 739
    0
      vendor/gopkg.in/yaml.v2/apic.go
  72. 775
    0
      vendor/gopkg.in/yaml.v2/decode.go
  73. 1685
    0
      vendor/gopkg.in/yaml.v2/emitterc.go
  74. 362
    0
      vendor/gopkg.in/yaml.v2/encode.go
  75. 5
    0
      vendor/gopkg.in/yaml.v2/go.mod
  76. 1095
    0
      vendor/gopkg.in/yaml.v2/parserc.go
  77. 412
    0
      vendor/gopkg.in/yaml.v2/readerc.go
  78. 258
    0
      vendor/gopkg.in/yaml.v2/resolve.go
  79. 2696
    0
      vendor/gopkg.in/yaml.v2/scannerc.go
  80. 113
    0
      vendor/gopkg.in/yaml.v2/sorter.go
  81. 26
    0
      vendor/gopkg.in/yaml.v2/writerc.go
  82. 466
    0
      vendor/gopkg.in/yaml.v2/yaml.go
  83. 738
    0
      vendor/gopkg.in/yaml.v2/yamlh.go
  84. 173
    0
      vendor/gopkg.in/yaml.v2/yamlprivateh.go

+ 43
- 1
Gopkg.lock View File

@@ -1,6 +1,12 @@
1 1
 # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 2
 
3 3
 
4
+[[projects]]
5
+  name = "github.com/PuerkitoBio/goquery"
6
+  packages = ["."]
7
+  revision = "a86ea073017a6beddef78c8659e7224e8ca634b0"
8
+  version = "v1.4.0"
9
+
4 10
 [[projects]]
5 11
   branch = "master"
6 12
   name = "github.com/Unknwon/com"
@@ -13,12 +19,24 @@
13 19
   packages = ["."]
14 20
   revision = "b64d336589669d317928070e70ba0ae558f16633"
15 21
 
22
+[[projects]]
23
+  name = "github.com/andybalholm/cascadia"
24
+  packages = ["."]
25
+  revision = "901648c87902174f774fac311d7f176f8647bdaa"
26
+  version = "v1.0.0"
27
+
16 28
 [[projects]]
17 29
   name = "github.com/certifi/gocertifi"
18 30
   packages = ["."]
19 31
   revision = "deb3ae2ef2610fde3330947281941c562861188b"
20 32
   version = "2018.01.18"
21 33
 
34
+[[projects]]
35
+  name = "github.com/davecgh/go-spew"
36
+  packages = ["spew"]
37
+  revision = "346938d642f2ec3594ed81d874461961cd0faa76"
38
+  version = "v1.1.0"
39
+
22 40
 [[projects]]
23 41
   branch = "master"
24 42
   name = "github.com/denisenkom/go-mssqldb"
@@ -88,6 +106,12 @@
88 106
   revision = "a0583e0143b1624142adab07e0e97fe106d99561"
89 107
   version = "v1.3"
90 108
 
109
+[[projects]]
110
+  name = "github.com/go-testfixtures/testfixtures"
111
+  packages = ["."]
112
+  revision = "f79bf941e2785516a66bcf4de9a21b0b827ed716"
113
+  version = "v2.4.3"
114
+
91 115
 [[projects]]
92 116
   name = "github.com/gogits/cron"
93 117
   packages = ["."]
@@ -182,6 +206,12 @@
182 206
   revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
183 207
   version = "v0.8.0"
184 208
 
209
+[[projects]]
210
+  name = "github.com/pmezard/go-difflib"
211
+  packages = ["difflib"]
212
+  revision = "792786c7400a136282c1664665ae0a8db921c6c2"
213
+  version = "v1.0.0"
214
+
185 215
 [[projects]]
186 216
   name = "github.com/russross/blackfriday"
187 217
   packages = ["."]
@@ -214,6 +244,12 @@
214 244
   packages = ["."]
215 245
   revision = "6386211fdfcf24c0bfbdaceafd02849ed9a8a509"
216 246
 
247
+[[projects]]
248
+  name = "github.com/stretchr/testify"
249
+  packages = ["assert"]
250
+  revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
251
+  version = "v1.2.1"
252
+
217 253
 [[projects]]
218 254
   name = "github.com/urfave/cli"
219 255
   packages = ["."]
@@ -285,9 +321,15 @@
285 321
   revision = "c1be95e6d21e769e44e1ec33cec9da5837861c10"
286 322
   version = "v1.3.1"
287 323
 
324
+[[projects]]
325
+  name = "gopkg.in/yaml.v2"
326
+  packages = ["."]
327
+  revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
328
+  version = "v2.2.1"
329
+
288 330
 [solve-meta]
289 331
   analyzer-name = "dep"
290 332
   analyzer-version = 1
291
-  inputs-digest = "fe7d05c1bc31d42dbef4597c69e4bd8f54c6aa81548cc15292a0f2696ae94cc8"
333
+  inputs-digest = "16e3061b79299bd473a5b9c4797b3b776b129eea676107d926f531dd76822354"
292 334
   solver-name = "gps-cdcl"
293 335
   solver-version = 1

+ 1
- 0
vendor/github.com/PuerkitoBio/goquery/.gitattributes View File

@@ -0,0 +1 @@
1
+testdata/* linguist-vendored

+ 16
- 0
vendor/github.com/PuerkitoBio/goquery/.gitignore View File

@@ -0,0 +1,16 @@
1
+# editor temporary files
2
+*.sublime-*
3
+.DS_Store
4
+*.swp
5
+#*.*#
6
+tags
7
+
8
+# direnv config
9
+.env*
10
+
11
+# test binaries
12
+*.test
13
+
14
+# coverage and profilte outputs
15
+*.out
16
+

+ 15
- 0
vendor/github.com/PuerkitoBio/goquery/.travis.yml View File

@@ -0,0 +1,15 @@
1
+language: go
2
+
3
+go:
4
+    - 1.1
5
+    - 1.2.x
6
+    - 1.3.x
7
+    - 1.4.x
8
+    - 1.5.x
9
+    - 1.6.x
10
+    - 1.7.x
11
+    - 1.8.x
12
+    - 1.9.x
13
+    - "1.10.x"
14
+    - tip
15
+

+ 12
- 0
vendor/github.com/PuerkitoBio/goquery/LICENSE
File diff suppressed because it is too large
View File


+ 164
- 0
vendor/github.com/PuerkitoBio/goquery/README.md
File diff suppressed because it is too large
View File


+ 124
- 0
vendor/github.com/PuerkitoBio/goquery/array.go View File

@@ -0,0 +1,124 @@
1
+package goquery
2
+
3
+import (
4
+	"golang.org/x/net/html"
5
+)
6
+
7
+const (
8
+	maxUint = ^uint(0)
9
+	maxInt  = int(maxUint >> 1)
10
+
11
+	// ToEnd is a special index value that can be used as end index in a call
12
+	// to Slice so that all elements are selected until the end of the Selection.
13
+	// It is equivalent to passing (*Selection).Length().
14
+	ToEnd = maxInt
15
+)
16
+
17
+// First reduces the set of matched elements to the first in the set.
18
+// It returns a new Selection object, and an empty Selection object if the
19
+// the selection is empty.
20
+func (s *Selection) First() *Selection {
21
+	return s.Eq(0)
22
+}
23
+
24
+// Last reduces the set of matched elements to the last in the set.
25
+// It returns a new Selection object, and an empty Selection object if
26
+// the selection is empty.
27
+func (s *Selection) Last() *Selection {
28
+	return s.Eq(-1)
29
+}
30
+
31
+// Eq reduces the set of matched elements to the one at the specified index.
32
+// If a negative index is given, it counts backwards starting at the end of the
33
+// set. It returns a new Selection object, and an empty Selection object if the
34
+// index is invalid.
35
+func (s *Selection) Eq(index int) *Selection {
36
+	if index < 0 {
37
+		index += len(s.Nodes)
38
+	}
39
+
40
+	if index >= len(s.Nodes) || index < 0 {
41
+		return newEmptySelection(s.document)
42
+	}
43
+
44
+	return s.Slice(index, index+1)
45
+}
46
+
47
+// Slice reduces the set of matched elements to a subset specified by a range
48
+// of indices. The start index is 0-based and indicates the index of the first
49
+// element to select. The end index is 0-based and indicates the index at which
50
+// the elements stop being selected (the end index is not selected).
51
+//
52
+// The indices may be negative, in which case they represent an offset from the
53
+// end of the selection.
54
+//
55
+// The special value ToEnd may be specified as end index, in which case all elements
56
+// until the end are selected. This works both for a positive and negative start
57
+// index.
58
+func (s *Selection) Slice(start, end int) *Selection {
59
+	if start < 0 {
60
+		start += len(s.Nodes)
61
+	}
62
+	if end == ToEnd {
63
+		end = len(s.Nodes)
64
+	} else if end < 0 {
65
+		end += len(s.Nodes)
66
+	}
67
+	return pushStack(s, s.Nodes[start:end])
68
+}
69
+
70
+// Get retrieves the underlying node at the specified index.
71
+// Get without parameter is not implemented, since the node array is available
72
+// on the Selection object.
73
+func (s *Selection) Get(index int) *html.Node {
74
+	if index < 0 {
75
+		index += len(s.Nodes) // Negative index gets from the end
76
+	}
77
+	return s.Nodes[index]
78
+}
79
+
80
+// Index returns the position of the first element within the Selection object
81
+// relative to its sibling elements.
82
+func (s *Selection) Index() int {
83
+	if len(s.Nodes) > 0 {
84
+		return newSingleSelection(s.Nodes[0], s.document).PrevAll().Length()
85
+	}
86
+	return -1
87
+}
88
+
89
+// IndexSelector returns the position of the first element within the
90
+// Selection object relative to the elements matched by the selector, or -1 if
91
+// not found.
92
+func (s *Selection) IndexSelector(selector string) int {
93
+	if len(s.Nodes) > 0 {
94
+		sel := s.document.Find(selector)
95
+		return indexInSlice(sel.Nodes, s.Nodes[0])
96
+	}
97
+	return -1
98
+}
99
+
100
+// IndexMatcher returns the position of the first element within the
101
+// Selection object relative to the elements matched by the matcher, or -1 if
102
+// not found.
103
+func (s *Selection) IndexMatcher(m Matcher) int {
104
+	if len(s.Nodes) > 0 {
105
+		sel := s.document.FindMatcher(m)
106
+		return indexInSlice(sel.Nodes, s.Nodes[0])
107
+	}
108
+	return -1
109
+}
110
+
111
+// IndexOfNode returns the position of the specified node within the Selection
112
+// object, or -1 if not found.
113
+func (s *Selection) IndexOfNode(node *html.Node) int {
114
+	return indexInSlice(s.Nodes, node)
115
+}
116
+
117
+// IndexOfSelection returns the position of the first node in the specified
118
+// Selection object within this Selection object, or -1 if not found.
119
+func (s *Selection) IndexOfSelection(sel *Selection) int {
120
+	if sel != nil && len(sel.Nodes) > 0 {
121
+		return indexInSlice(s.Nodes, sel.Nodes[0])
122
+	}
123
+	return -1
124
+}

+ 123
- 0
vendor/github.com/PuerkitoBio/goquery/doc.go View File

@@ -0,0 +1,123 @@
1
+// Copyright (c) 2012-2016, Martin Angers & Contributors
2
+// All rights reserved.
3
+//
4
+// Redistribution and use in source and binary forms, with or without modification,
5
+// are permitted provided that the following conditions are met:
6
+//
7
+// * Redistributions of source code must retain the above copyright notice,
8
+// this list of conditions and the following disclaimer.
9
+// * Redistributions in binary form must reproduce the above copyright notice,
10
+// this list of conditions and the following disclaimer in the documentation and/or
11
+// other materials provided with the distribution.
12
+// * Neither the name of the author nor the names of its contributors may be used to
13
+// endorse or promote products derived from this software without specific prior written permission.
14
+//
15
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
16
+// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
17
+// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
18
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
22
+// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+/*
25
+Package goquery implements features similar to jQuery, including the chainable
26
+syntax, to manipulate and query an HTML document.
27
+
28
+It brings a syntax and a set of features similar to jQuery to the Go language.
29
+It is based on Go's net/html package and the CSS Selector library cascadia.
30
+Since the net/html parser returns nodes, and not a full-featured DOM
31
+tree, jQuery's stateful manipulation functions (like height(), css(), detach())
32
+have been left off.
33
+
34
+Also, because the net/html parser requires UTF-8 encoding, so does goquery: it is
35
+the caller's responsibility to ensure that the source document provides UTF-8 encoded HTML.
36
+See the repository's wiki for various options on how to do this.
37
+
38
+Syntax-wise, it is as close as possible to jQuery, with the same method names when
39
+possible, and that warm and fuzzy chainable interface. jQuery being the
40
+ultra-popular library that it is, writing a similar HTML-manipulating
41
+library was better to follow its API than to start anew (in the same spirit as
42
+Go's fmt package), even though some of its methods are less than intuitive (looking
43
+at you, index()...).
44
+
45
+It is hosted on GitHub, along with additional documentation in the README.md
46
+file: https://github.com/puerkitobio/goquery
47
+
48
+Please note that because of the net/html dependency, goquery requires Go1.1+.
49
+
50
+The various methods are split into files based on the category of behavior.
51
+The three dots (...) indicate that various "overloads" are available.
52
+
53
+* array.go : array-like positional manipulation of the selection.
54
+    - Eq()
55
+    - First()
56
+    - Get()
57
+    - Index...()
58
+    - Last()
59
+    - Slice()
60
+
61
+* expand.go : methods that expand or augment the selection's set.
62
+    - Add...()
63
+    - AndSelf()
64
+    - Union(), which is an alias for AddSelection()
65
+
66
+* filter.go : filtering methods, that reduce the selection's set.
67
+    - End()
68
+    - Filter...()
69
+    - Has...()
70
+    - Intersection(), which is an alias of FilterSelection()
71
+    - Not...()
72
+
73
+* iteration.go : methods to loop over the selection's nodes.
74
+    - Each()
75
+    - EachWithBreak()
76
+    - Map()
77
+
78
+* manipulation.go : methods for modifying the document
79
+    - After...()
80
+    - Append...()
81
+    - Before...()
82
+    - Clone()
83
+    - Empty()
84
+    - Prepend...()
85
+    - Remove...()
86
+    - ReplaceWith...()
87
+    - Unwrap()
88
+    - Wrap...()
89
+    - WrapAll...()
90
+    - WrapInner...()
91
+
92
+* property.go : methods that inspect and get the node's properties values.
93
+    - Attr*(), RemoveAttr(), SetAttr()
94
+    - AddClass(), HasClass(), RemoveClass(), ToggleClass()
95
+    - Html()
96
+    - Length()
97
+    - Size(), which is an alias for Length()
98
+    - Text()
99
+
100
+* query.go : methods that query, or reflect, a node's identity.
101
+    - Contains()
102
+    - Is...()
103
+
104
+* traversal.go : methods to traverse the HTML document tree.
105
+    - Children...()
106
+    - Contents()
107
+    - Find...()
108
+    - Next...()
109
+    - Parent[s]...()
110
+    - Prev...()
111
+    - Siblings...()
112
+
113
+* type.go : definition of the types exposed by goquery.
114
+    - Document
115
+    - Selection
116
+    - Matcher
117
+
118
+* utilities.go : definition of helper functions (and not methods on a *Selection)
119
+that are not part of jQuery, but are useful to goquery.
120
+    - NodeName
121
+    - OuterHtml
122
+*/
123
+package goquery

+ 70
- 0
vendor/github.com/PuerkitoBio/goquery/expand.go View File

@@ -0,0 +1,70 @@
1
+package goquery
2
+
3
+import "golang.org/x/net/html"
4
+
5
+// Add adds the selector string's matching nodes to those in the current
6
+// selection and returns a new Selection object.
7
+// The selector string is run in the context of the document of the current
8
+// Selection object.
9
+func (s *Selection) Add(selector string) *Selection {
10
+	return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, compileMatcher(selector))...)
11
+}
12
+
13
+// AddMatcher adds the matcher's matching nodes to those in the current
14
+// selection and returns a new Selection object.
15
+// The matcher is run in the context of the document of the current
16
+// Selection object.
17
+func (s *Selection) AddMatcher(m Matcher) *Selection {
18
+	return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, m)...)
19
+}
20
+
21
+// AddSelection adds the specified Selection object's nodes to those in the
22
+// current selection and returns a new Selection object.
23
+func (s *Selection) AddSelection(sel *Selection) *Selection {
24
+	if sel == nil {
25
+		return s.AddNodes()
26
+	}
27
+	return s.AddNodes(sel.Nodes...)
28
+}
29
+
30
+// Union is an alias for AddSelection.
31
+func (s *Selection) Union(sel *Selection) *Selection {
32
+	return s.AddSelection(sel)
33
+}
34
+
35
+// AddNodes adds the specified nodes to those in the
36
+// current selection and returns a new Selection object.
37
+func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
38
+	return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes, nil))
39
+}
40
+
41
+// AndSelf adds the previous set of elements on the stack to the current set.
42
+// It returns a new Selection object containing the current Selection combined
43
+// with the previous one.
44
+// Deprecated: This function has been deprecated and is now an alias for AddBack().
45
+func (s *Selection) AndSelf() *Selection {
46
+	return s.AddBack()
47
+}
48
+
49
+// AddBack adds the previous set of elements on the stack to the current set.
50
+// It returns a new Selection object containing the current Selection combined
51
+// with the previous one.
52
+func (s *Selection) AddBack() *Selection {
53
+	return s.AddSelection(s.prevSel)
54
+}
55
+
56
+// AddBackFiltered reduces the previous set of elements on the stack to those that
57
+// match the selector string, and adds them to the current set.
58
+// It returns a new Selection object containing the current Selection combined
59
+// with the filtered previous one
60
+func (s *Selection) AddBackFiltered(selector string) *Selection {
61
+	return s.AddSelection(s.prevSel.Filter(selector))
62
+}
63
+
64
+// AddBackMatcher reduces the previous set of elements on the stack to those that match
65
+// the mateher, and adds them to the curernt set.
66
+// It returns a new Selection object containing the current Selection combined
67
+// with the filtered previous one
68
+func (s *Selection) AddBackMatcher(m Matcher) *Selection {
69
+	return s.AddSelection(s.prevSel.FilterMatcher(m))
70
+}

+ 163
- 0
vendor/github.com/PuerkitoBio/goquery/filter.go View File

@@ -0,0 +1,163 @@
1
+package goquery
2
+
3
+import "golang.org/x/net/html"
4
+
5
+// Filter reduces the set of matched elements to those that match the selector string.
6
+// It returns a new Selection object for this subset of matching elements.
7
+func (s *Selection) Filter(selector string) *Selection {
8
+	return s.FilterMatcher(compileMatcher(selector))
9
+}
10
+
11
+// FilterMatcher reduces the set of matched elements to those that match
12
+// the given matcher. It returns a new Selection object for this subset
13
+// of matching elements.
14
+func (s *Selection) FilterMatcher(m Matcher) *Selection {
15
+	return pushStack(s, winnow(s, m, true))
16
+}
17
+
18
+// Not removes elements from the Selection that match the selector string.
19
+// It returns a new Selection object with the matching elements removed.
20
+func (s *Selection) Not(selector string) *Selection {
21
+	return s.NotMatcher(compileMatcher(selector))
22
+}
23
+
24
+// NotMatcher removes elements from the Selection that match the given matcher.
25
+// It returns a new Selection object with the matching elements removed.
26
+func (s *Selection) NotMatcher(m Matcher) *Selection {
27
+	return pushStack(s, winnow(s, m, false))
28
+}
29
+
30
+// FilterFunction reduces the set of matched elements to those that pass the function's test.
31
+// It returns a new Selection object for this subset of elements.
32
+func (s *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
33
+	return pushStack(s, winnowFunction(s, f, true))
34
+}
35
+
36
+// NotFunction removes elements from the Selection that pass the function's test.
37
+// It returns a new Selection object with the matching elements removed.
38
+func (s *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
39
+	return pushStack(s, winnowFunction(s, f, false))
40
+}
41
+
42
+// FilterNodes reduces the set of matched elements to those that match the specified nodes.
43
+// It returns a new Selection object for this subset of elements.
44
+func (s *Selection) FilterNodes(nodes ...*html.Node) *Selection {
45
+	return pushStack(s, winnowNodes(s, nodes, true))
46
+}
47
+
48
+// NotNodes removes elements from the Selection that match the specified nodes.
49
+// It returns a new Selection object with the matching elements removed.
50
+func (s *Selection) NotNodes(nodes ...*html.Node) *Selection {
51
+	return pushStack(s, winnowNodes(s, nodes, false))
52
+}
53
+
54
+// FilterSelection reduces the set of matched elements to those that match a
55
+// node in the specified Selection object.
56
+// It returns a new Selection object for this subset of elements.
57
+func (s *Selection) FilterSelection(sel *Selection) *Selection {
58
+	if sel == nil {
59
+		return pushStack(s, winnowNodes(s, nil, true))
60
+	}
61
+	return pushStack(s, winnowNodes(s, sel.Nodes, true))
62
+}
63
+
64
+// NotSelection removes elements from the Selection that match a node in the specified
65
+// Selection object. It returns a new Selection object with the matching elements removed.
66
+func (s *Selection) NotSelection(sel *Selection) *Selection {
67
+	if sel == nil {
68
+		return pushStack(s, winnowNodes(s, nil, false))
69
+	}
70
+	return pushStack(s, winnowNodes(s, sel.Nodes, false))
71
+}
72
+
73
+// Intersection is an alias for FilterSelection.
74
+func (s *Selection) Intersection(sel *Selection) *Selection {
75
+	return s.FilterSelection(sel)
76
+}
77
+
78
+// Has reduces the set of matched elements to those that have a descendant
79
+// that matches the selector.
80
+// It returns a new Selection object with the matching elements.
81
+func (s *Selection) Has(selector string) *Selection {
82
+	return s.HasSelection(s.document.Find(selector))
83
+}
84
+
85
+// HasMatcher reduces the set of matched elements to those that have a descendant
86
+// that matches the matcher.
87
+// It returns a new Selection object with the matching elements.
88
+func (s *Selection) HasMatcher(m Matcher) *Selection {
89
+	return s.HasSelection(s.document.FindMatcher(m))
90
+}
91
+
92
+// HasNodes reduces the set of matched elements to those that have a
93
+// descendant that matches one of the nodes.
94
+// It returns a new Selection object with the matching elements.
95
+func (s *Selection) HasNodes(nodes ...*html.Node) *Selection {
96
+	return s.FilterFunction(func(_ int, sel *Selection) bool {
97
+		// Add all nodes that contain one of the specified nodes
98
+		for _, n := range nodes {
99
+			if sel.Contains(n) {
100
+				return true
101
+			}
102
+		}
103
+		return false
104
+	})
105
+}
106
+
107
+// HasSelection reduces the set of matched elements to those that have a
108
+// descendant that matches one of the nodes of the specified Selection object.
109
+// It returns a new Selection object with the matching elements.
110
+func (s *Selection) HasSelection(sel *Selection) *Selection {
111
+	if sel == nil {
112
+		return s.HasNodes()
113
+	}
114
+	return s.HasNodes(sel.Nodes...)
115
+}
116
+
117
+// End ends the most recent filtering operation in the current chain and
118
+// returns the set of matched elements to its previous state.
119
+func (s *Selection) End() *Selection {
120
+	if s.prevSel != nil {
121
+		return s.prevSel
122
+	}
123
+	return newEmptySelection(s.document)
124
+}
125
+
126
+// Filter based on the matcher, and the indicator to keep (Filter) or
127
+// to get rid of (Not) the matching elements.
128
+func winnow(sel *Selection, m Matcher, keep bool) []*html.Node {
129
+	// Optimize if keep is requested
130
+	if keep {
131
+		return m.Filter(sel.Nodes)
132
+	}
133
+	// Use grep
134
+	return grep(sel, func(i int, s *Selection) bool {
135
+		return !m.Match(s.Get(0))
136
+	})
137
+}
138
+
139
+// Filter based on an array of nodes, and the indicator to keep (Filter) or
140
+// to get rid of (Not) the matching elements.
141
+func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
142
+	if len(nodes)+len(sel.Nodes) < minNodesForSet {
143
+		return grep(sel, func(i int, s *Selection) bool {
144
+			return isInSlice(nodes, s.Get(0)) == keep
145
+		})
146
+	}
147
+
148
+	set := make(map[*html.Node]bool)
149
+	for _, n := range nodes {
150
+		set[n] = true
151
+	}
152
+	return grep(sel, func(i int, s *Selection) bool {
153
+		return set[s.Get(0)] == keep
154
+	})
155
+}
156
+
157
+// Filter based on a function test, and the indicator to keep (Filter) or
158
+// to get rid of (Not) the matching elements.
159
+func winnowFunction(sel *Selection, f func(int, *Selection) bool, keep bool) []*html.Node {
160
+	return grep(sel, func(i int, s *Selection) bool {
161
+		return f(i, s) == keep
162
+	})
163
+}

+ 39
- 0
vendor/github.com/PuerkitoBio/goquery/iteration.go View File

@@ -0,0 +1,39 @@
1
+package goquery
2
+
3
+// Each iterates over a Selection object, executing a function for each
4
+// matched element. It returns the current Selection object. The function
5
+// f is called for each element in the selection with the index of the
6
+// element in that selection starting at 0, and a *Selection that contains
7
+// only that element.
8
+func (s *Selection) Each(f func(int, *Selection)) *Selection {
9
+	for i, n := range s.Nodes {
10
+		f(i, newSingleSelection(n, s.document))
11
+	}
12
+	return s
13
+}
14
+
15
+// EachWithBreak iterates over a Selection object, executing a function for each
16
+// matched element. It is identical to Each except that it is possible to break
17
+// out of the loop by returning false in the callback function. It returns the
18
+// current Selection object.
19
+func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
20
+	for i, n := range s.Nodes {
21
+		if !f(i, newSingleSelection(n, s.document)) {
22
+			return s
23
+		}
24
+	}
25
+	return s
26
+}
27
+
28
+// Map passes each element in the current matched set through a function,
29
+// producing a slice of string holding the returned values. The function
30
+// f is called for each element in the selection with the index of the
31
+// element in that selection starting at 0, and a *Selection that contains
32
+// only that element.
33
+func (s *Selection) Map(f func(int, *Selection) string) (result []string) {
34
+	for i, n := range s.Nodes {
35
+		result = append(result, f(i, newSingleSelection(n, s.document)))
36
+	}
37
+
38
+	return result
39
+}

+ 574
- 0
vendor/github.com/PuerkitoBio/goquery/manipulation.go View File

@@ -0,0 +1,574 @@
1
+package goquery
2
+
3
+import (
4
+	"strings"
5
+
6
+	"golang.org/x/net/html"
7
+)
8
+
9
+// After applies the selector from the root document and inserts the matched elements
10
+// after the elements in the set of matched elements.
11
+//
12
+// If one of the matched elements in the selection is not currently in the
13
+// document, it's impossible to insert nodes after it, so it will be ignored.
14
+//
15
+// This follows the same rules as Selection.Append.
16
+func (s *Selection) After(selector string) *Selection {
17
+	return s.AfterMatcher(compileMatcher(selector))
18
+}
19
+
20
+// AfterMatcher applies the matcher from the root document and inserts the matched elements
21
+// after the elements in the set of matched elements.
22
+//
23
+// If one of the matched elements in the selection is not currently in the
24
+// document, it's impossible to insert nodes after it, so it will be ignored.
25
+//
26
+// This follows the same rules as Selection.Append.
27
+func (s *Selection) AfterMatcher(m Matcher) *Selection {
28
+	return s.AfterNodes(m.MatchAll(s.document.rootNode)...)
29
+}
30
+
31
+// AfterSelection inserts the elements in the selection after each element in the set of matched
32
+// elements.
33
+//
34
+// This follows the same rules as Selection.Append.
35
+func (s *Selection) AfterSelection(sel *Selection) *Selection {
36
+	return s.AfterNodes(sel.Nodes...)
37
+}
38
+
39
+// AfterHtml parses the html and inserts it after the set of matched elements.
40
+//
41
+// This follows the same rules as Selection.Append.
42
+func (s *Selection) AfterHtml(html string) *Selection {
43
+	return s.AfterNodes(parseHtml(html)...)
44
+}
45
+
46
+// AfterNodes inserts the nodes after each element in the set of matched elements.
47
+//
48
+// This follows the same rules as Selection.Append.
49
+func (s *Selection) AfterNodes(ns ...*html.Node) *Selection {
50
+	return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
51
+		if sn.Parent != nil {
52
+			sn.Parent.InsertBefore(n, sn.NextSibling)
53
+		}
54
+	})
55
+}
56
+
57
+// Append appends the elements specified by the selector to the end of each element
58
+// in the set of matched elements, following those rules:
59
+//
60
+// 1) The selector is applied to the root document.
61
+//
62
+// 2) Elements that are part of the document will be moved to the new location.
63
+//
64
+// 3) If there are multiple locations to append to, cloned nodes will be
65
+// appended to all target locations except the last one, which will be moved
66
+// as noted in (2).
67
+func (s *Selection) Append(selector string) *Selection {
68
+	return s.AppendMatcher(compileMatcher(selector))
69
+}
70
+
71
+// AppendMatcher appends the elements specified by the matcher to the end of each element
72
+// in the set of matched elements.
73
+//
74
+// This follows the same rules as Selection.Append.
75
+func (s *Selection) AppendMatcher(m Matcher) *Selection {
76
+	return s.AppendNodes(m.MatchAll(s.document.rootNode)...)
77
+}
78
+
79
+// AppendSelection appends the elements in the selection to the end of each element
80
+// in the set of matched elements.
81
+//
82
+// This follows the same rules as Selection.Append.
83
+func (s *Selection) AppendSelection(sel *Selection) *Selection {
84
+	return s.AppendNodes(sel.Nodes...)
85
+}
86
+
87
+// AppendHtml parses the html and appends it to the set of matched elements.
88
+func (s *Selection) AppendHtml(html string) *Selection {
89
+	return s.AppendNodes(parseHtml(html)...)
90
+}
91
+
92
+// AppendNodes appends the specified nodes to each node in the set of matched elements.
93
+//
94
+// This follows the same rules as Selection.Append.
95
+func (s *Selection) AppendNodes(ns ...*html.Node) *Selection {
96
+	return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
97
+		sn.AppendChild(n)
98
+	})
99
+}
100
+
101
+// Before inserts the matched elements before each element in the set of matched elements.
102
+//
103
+// This follows the same rules as Selection.Append.
104
+func (s *Selection) Before(selector string) *Selection {
105
+	return s.BeforeMatcher(compileMatcher(selector))
106
+}
107
+
108
+// BeforeMatcher inserts the matched elements before each element in the set of matched elements.
109
+//
110
+// This follows the same rules as Selection.Append.
111
+func (s *Selection) BeforeMatcher(m Matcher) *Selection {
112
+	return s.BeforeNodes(m.MatchAll(s.document.rootNode)...)
113
+}
114
+
115
+// BeforeSelection inserts the elements in the selection before each element in the set of matched
116
+// elements.
117
+//
118
+// This follows the same rules as Selection.Append.
119
+func (s *Selection) BeforeSelection(sel *Selection) *Selection {
120
+	return s.BeforeNodes(sel.Nodes...)
121
+}
122
+
123
+// BeforeHtml parses the html and inserts it before the set of matched elements.
124
+//
125
+// This follows the same rules as Selection.Append.
126
+func (s *Selection) BeforeHtml(html string) *Selection {
127
+	return s.BeforeNodes(parseHtml(html)...)
128
+}
129
+
130
+// BeforeNodes inserts the nodes before each element in the set of matched elements.
131
+//
132
+// This follows the same rules as Selection.Append.
133
+func (s *Selection) BeforeNodes(ns ...*html.Node) *Selection {
134
+	return s.manipulateNodes(ns, false, func(sn *html.Node, n *html.Node) {
135
+		if sn.Parent != nil {
136
+			sn.Parent.InsertBefore(n, sn)
137
+		}
138
+	})
139
+}
140
+
141
+// Clone creates a deep copy of the set of matched nodes. The new nodes will not be
142
+// attached to the document.
143
+func (s *Selection) Clone() *Selection {
144
+	ns := newEmptySelection(s.document)
145
+	ns.Nodes = cloneNodes(s.Nodes)
146
+	return ns
147
+}
148
+
149
+// Empty removes all children nodes from the set of matched elements.
150
+// It returns the children nodes in a new Selection.
151
+func (s *Selection) Empty() *Selection {
152
+	var nodes []*html.Node
153
+
154
+	for _, n := range s.Nodes {
155
+		for c := n.FirstChild; c != nil; c = n.FirstChild {
156
+			n.RemoveChild(c)
157
+			nodes = append(nodes, c)
158
+		}
159
+	}
160
+
161
+	return pushStack(s, nodes)
162
+}
163
+
164
+// Prepend prepends the elements specified by the selector to each element in
165
+// the set of matched elements, following the same rules as Append.
166
+func (s *Selection) Prepend(selector string) *Selection {
167
+	return s.PrependMatcher(compileMatcher(selector))
168
+}
169
+
170
+// PrependMatcher prepends the elements specified by the matcher to each
171
+// element in the set of matched elements.
172
+//
173
+// This follows the same rules as Selection.Append.
174
+func (s *Selection) PrependMatcher(m Matcher) *Selection {
175
+	return s.PrependNodes(m.MatchAll(s.document.rootNode)...)
176
+}
177
+
178
+// PrependSelection prepends the elements in the selection to each element in
179
+// the set of matched elements.
180
+//
181
+// This follows the same rules as Selection.Append.
182
+func (s *Selection) PrependSelection(sel *Selection) *Selection {
183
+	return s.PrependNodes(sel.Nodes...)
184
+}
185
+
186
+// PrependHtml parses the html and prepends it to the set of matched elements.
187
+func (s *Selection) PrependHtml(html string) *Selection {
188
+	return s.PrependNodes(parseHtml(html)...)
189
+}
190
+
191
+// PrependNodes prepends the specified nodes to each node in the set of
192
+// matched elements.
193
+//
194
+// This follows the same rules as Selection.Append.
195
+func (s *Selection) PrependNodes(ns ...*html.Node) *Selection {
196
+	return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
197
+		// sn.FirstChild may be nil, in which case this functions like
198
+		// sn.AppendChild()
199
+		sn.InsertBefore(n, sn.FirstChild)
200
+	})
201
+}
202
+
203
+// Remove removes the set of matched elements from the document.
204
+// It returns the same selection, now consisting of nodes not in the document.
205
+func (s *Selection) Remove() *Selection {
206
+	for _, n := range s.Nodes {
207
+		if n.Parent != nil {
208
+			n.Parent.RemoveChild(n)
209
+		}
210
+	}
211
+
212
+	return s
213
+}
214
+
215
+// RemoveFiltered removes the set of matched elements by selector.
216
+// It returns the Selection of removed nodes.
217
+func (s *Selection) RemoveFiltered(selector string) *Selection {
218
+	return s.RemoveMatcher(compileMatcher(selector))
219
+}
220
+
221
+// RemoveMatcher removes the set of matched elements.
222
+// It returns the Selection of removed nodes.
223
+func (s *Selection) RemoveMatcher(m Matcher) *Selection {
224
+	return s.FilterMatcher(m).Remove()
225
+}
226
+
227
+// ReplaceWith replaces each element in the set of matched elements with the
228
+// nodes matched by the given selector.
229
+// It returns the removed elements.
230
+//
231
+// This follows the same rules as Selection.Append.
232
+func (s *Selection) ReplaceWith(selector string) *Selection {
233
+	return s.ReplaceWithMatcher(compileMatcher(selector))
234
+}
235
+
236
+// ReplaceWithMatcher replaces each element in the set of matched elements with
237
+// the nodes matched by the given Matcher.
238
+// It returns the removed elements.
239
+//
240
+// This follows the same rules as Selection.Append.
241
+func (s *Selection) ReplaceWithMatcher(m Matcher) *Selection {
242
+	return s.ReplaceWithNodes(m.MatchAll(s.document.rootNode)...)
243
+}
244
+
245
+// ReplaceWithSelection replaces each element in the set of matched elements with
246
+// the nodes from the given Selection.
247
+// It returns the removed elements.
248
+//
249
+// This follows the same rules as Selection.Append.
250
+func (s *Selection) ReplaceWithSelection(sel *Selection) *Selection {
251
+	return s.ReplaceWithNodes(sel.Nodes...)
252
+}
253
+
254
+// ReplaceWithHtml replaces each element in the set of matched elements with
255
+// the parsed HTML.
256
+// It returns the removed elements.
257
+//
258
+// This follows the same rules as Selection.Append.
259
+func (s *Selection) ReplaceWithHtml(html string) *Selection {
260
+	return s.ReplaceWithNodes(parseHtml(html)...)
261
+}
262
+
263
+// ReplaceWithNodes replaces each element in the set of matched elements with
264
+// the given nodes.
265
+// It returns the removed elements.
266
+//
267
+// This follows the same rules as Selection.Append.
268
+func (s *Selection) ReplaceWithNodes(ns ...*html.Node) *Selection {
269
+	s.AfterNodes(ns...)
270
+	return s.Remove()
271
+}
272
+
273
+// SetHtml sets the html content of each element in the selection to
274
+// specified html string.
275
+func (s *Selection) SetHtml(html string) *Selection {
276
+	return setHtmlNodes(s, parseHtml(html)...)
277
+}
278
+
279
+// SetText sets the content of each element in the selection to specified content.
280
+// The provided text string is escaped.
281
+func (s *Selection) SetText(text string) *Selection {
282
+	return s.SetHtml(html.EscapeString(text))
283
+}
284
+
285
+// Unwrap removes the parents of the set of matched elements, leaving the matched
286
+// elements (and their siblings, if any) in their place.
287
+// It returns the original selection.
288
+func (s *Selection) Unwrap() *Selection {
289
+	s.Parent().Each(func(i int, ss *Selection) {
290
+		// For some reason, jquery allows unwrap to remove the <head> element, so
291
+		// allowing it here too. Same for <html>. Why it allows those elements to
292
+		// be unwrapped while not allowing body is a mystery to me.
293
+		if ss.Nodes[0].Data != "body" {
294
+			ss.ReplaceWithSelection(ss.Contents())
295
+		}
296
+	})
297
+
298
+	return s
299
+}
300
+
301
+// Wrap wraps each element in the set of matched elements inside the first
302
+// element matched by the given selector. The matched child is cloned before
303
+// being inserted into the document.
304
+//
305
+// It returns the original set of elements.
306
+func (s *Selection) Wrap(selector string) *Selection {
307
+	return s.WrapMatcher(compileMatcher(selector))
308
+}
309
+
310
+// WrapMatcher wraps each element in the set of matched elements inside the
311
+// first element matched by the given matcher. The matched child is cloned
312
+// before being inserted into the document.
313
+//
314
+// It returns the original set of elements.
315
+func (s *Selection) WrapMatcher(m Matcher) *Selection {
316
+	return s.wrapNodes(m.MatchAll(s.document.rootNode)...)
317
+}
318
+
319
+// WrapSelection wraps each element in the set of matched elements inside the
320
+// first element in the given Selection. The element is cloned before being
321
+// inserted into the document.
322
+//
323
+// It returns the original set of elements.
324
+func (s *Selection) WrapSelection(sel *Selection) *Selection {
325
+	return s.wrapNodes(sel.Nodes...)
326
+}
327
+
328
+// WrapHtml wraps each element in the set of matched elements inside the inner-
329
+// most child of the given HTML.
330
+//
331
+// It returns the original set of elements.
332
+func (s *Selection) WrapHtml(html string) *Selection {
333
+	return s.wrapNodes(parseHtml(html)...)
334
+}
335
+
336
+// WrapNode wraps each element in the set of matched elements inside the inner-
337
+// most child of the given node. The given node is copied before being inserted
338
+// into the document.
339
+//
340
+// It returns the original set of elements.
341
+func (s *Selection) WrapNode(n *html.Node) *Selection {
342
+	return s.wrapNodes(n)
343
+}
344
+
345
+func (s *Selection) wrapNodes(ns ...*html.Node) *Selection {
346
+	s.Each(func(i int, ss *Selection) {
347
+		ss.wrapAllNodes(ns...)
348
+	})
349
+
350
+	return s
351
+}
352
+
353
+// WrapAll wraps a single HTML structure, matched by the given selector, around
354
+// all elements in the set of matched elements. The matched child is cloned
355
+// before being inserted into the document.
356
+//
357
+// It returns the original set of elements.
358
+func (s *Selection) WrapAll(selector string) *Selection {
359
+	return s.WrapAllMatcher(compileMatcher(selector))
360
+}
361
+
362
+// WrapAllMatcher wraps a single HTML structure, matched by the given Matcher,
363
+// around all elements in the set of matched elements. The matched child is
364
+// cloned before being inserted into the document.
365
+//
366
+// It returns the original set of elements.
367
+func (s *Selection) WrapAllMatcher(m Matcher) *Selection {
368
+	return s.wrapAllNodes(m.MatchAll(s.document.rootNode)...)
369
+}
370
+
371
+// WrapAllSelection wraps a single HTML structure, the first node of the given
372
+// Selection, around all elements in the set of matched elements. The matched
373
+// child is cloned before being inserted into the document.
374
+//
375
+// It returns the original set of elements.
376
+func (s *Selection) WrapAllSelection(sel *Selection) *Selection {
377
+	return s.wrapAllNodes(sel.Nodes...)
378
+}
379
+
380
+// WrapAllHtml wraps the given HTML structure around all elements in the set of
381
+// matched elements. The matched child is cloned before being inserted into the
382
+// document.
383
+//
384
+// It returns the original set of elements.
385
+func (s *Selection) WrapAllHtml(html string) *Selection {
386
+	return s.wrapAllNodes(parseHtml(html)...)
387
+}
388
+
389
+func (s *Selection) wrapAllNodes(ns ...*html.Node) *Selection {
390
+	if len(ns) > 0 {
391
+		return s.WrapAllNode(ns[0])
392
+	}
393
+	return s
394
+}
395
+
396
+// WrapAllNode wraps the given node around the first element in the Selection,
397
+// making all other nodes in the Selection children of the given node. The node
398
+// is cloned before being inserted into the document.
399
+//
400
+// It returns the original set of elements.
401
+func (s *Selection) WrapAllNode(n *html.Node) *Selection {
402
+	if s.Size() == 0 {
403
+		return s
404
+	}
405
+
406
+	wrap := cloneNode(n)
407
+
408
+	first := s.Nodes[0]
409
+	if first.Parent != nil {
410
+		first.Parent.InsertBefore(wrap, first)
411
+		first.Parent.RemoveChild(first)
412
+	}
413
+
414
+	for c := getFirstChildEl(wrap); c != nil; c = getFirstChildEl(wrap) {
415
+		wrap = c
416
+	}
417
+
418
+	newSingleSelection(wrap, s.document).AppendSelection(s)
419
+
420
+	return s
421
+}
422
+
423
+// WrapInner wraps an HTML structure, matched by the given selector, around the
424
+// content of element in the set of matched elements. The matched child is
425
+// cloned before being inserted into the document.
426
+//
427
+// It returns the original set of elements.
428
+func (s *Selection) WrapInner(selector string) *Selection {
429
+	return s.WrapInnerMatcher(compileMatcher(selector))
430
+}
431
+
432
+// WrapInnerMatcher wraps an HTML structure, matched by the given selector,
433
+// around the content of element in the set of matched elements. The matched
434
+// child is cloned before being inserted into the document.
435
+//
436
+// It returns the original set of elements.
437
+func (s *Selection) WrapInnerMatcher(m Matcher) *Selection {
438
+	return s.wrapInnerNodes(m.MatchAll(s.document.rootNode)...)
439
+}
440
+
441
+// WrapInnerSelection wraps an HTML structure, matched by the given selector,
442
+// around the content of element in the set of matched elements. The matched
443
+// child is cloned before being inserted into the document.
444
+//
445
+// It returns the original set of elements.
446
+func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
447
+	return s.wrapInnerNodes(sel.Nodes...)
448
+}
449
+
450
+// WrapInnerHtml wraps an HTML structure, matched by the given selector, around
451
+// the content of element in the set of matched elements. The matched child is
452
+// cloned before being inserted into the document.
453
+//
454
+// It returns the original set of elements.
455
+func (s *Selection) WrapInnerHtml(html string) *Selection {
456
+	return s.wrapInnerNodes(parseHtml(html)...)
457
+}
458
+
459
+// WrapInnerNode wraps an HTML structure, matched by the given selector, around
460
+// the content of element in the set of matched elements. The matched child is
461
+// cloned before being inserted into the document.
462
+//
463
+// It returns the original set of elements.
464
+func (s *Selection) WrapInnerNode(n *html.Node) *Selection {
465
+	return s.wrapInnerNodes(n)
466
+}
467
+
468
+func (s *Selection) wrapInnerNodes(ns ...*html.Node) *Selection {
469
+	if len(ns) == 0 {
470
+		return s
471
+	}
472
+
473
+	s.Each(func(i int, s *Selection) {
474
+		contents := s.Contents()
475
+
476
+		if contents.Size() > 0 {
477
+			contents.wrapAllNodes(ns...)
478
+		} else {
479
+			s.AppendNodes(cloneNode(ns[0]))
480
+		}
481
+	})
482
+
483
+	return s
484
+}
485
+
486
+func parseHtml(h string) []*html.Node {
487
+	// Errors are only returned when the io.Reader returns any error besides
488
+	// EOF, but strings.Reader never will
489
+	nodes, err := html.ParseFragment(strings.NewReader(h), &html.Node{Type: html.ElementNode})
490
+	if err != nil {
491
+		panic("goquery: failed to parse HTML: " + err.Error())
492
+	}
493
+	return nodes
494
+}
495
+
496
+func setHtmlNodes(s *Selection, ns ...*html.Node) *Selection {
497
+	for _, n := range s.Nodes {
498
+		for c := n.FirstChild; c != nil; c = n.FirstChild {
499
+			n.RemoveChild(c)
500
+		}
501
+		for _, c := range ns {
502
+			n.AppendChild(cloneNode(c))
503
+		}
504
+	}
505
+	return s
506
+}
507
+
508
+// Get the first child that is an ElementNode
509
+func getFirstChildEl(n *html.Node) *html.Node {
510
+	c := n.FirstChild
511
+	for c != nil && c.Type != html.ElementNode {
512
+		c = c.NextSibling
513
+	}
514
+	return c
515
+}
516
+
517
+// Deep copy a slice of nodes.
518
+func cloneNodes(ns []*html.Node) []*html.Node {
519
+	cns := make([]*html.Node, 0, len(ns))
520
+
521
+	for _, n := range ns {
522
+		cns = append(cns, cloneNode(n))
523
+	}
524
+
525
+	return cns
526
+}
527
+
528
+// Deep copy a node. The new node has clones of all the original node's
529
+// children but none of its parents or siblings.
530
+func cloneNode(n *html.Node) *html.Node {
531
+	nn := &html.Node{
532
+		Type:     n.Type,
533
+		DataAtom: n.DataAtom,
534
+		Data:     n.Data,
535
+		Attr:     make([]html.Attribute, len(n.Attr)),
536
+	}
537
+
538
+	copy(nn.Attr, n.Attr)
539
+	for c := n.FirstChild; c != nil; c = c.NextSibling {
540
+		nn.AppendChild(cloneNode(c))
541
+	}
542
+
543
+	return nn
544
+}
545
+
546
+func (s *Selection) manipulateNodes(ns []*html.Node, reverse bool,
547
+	f func(sn *html.Node, n *html.Node)) *Selection {
548
+
549
+	lasti := s.Size() - 1
550
+
551
+	// net.Html doesn't provide document fragments for insertion, so to get
552
+	// things in the correct order with After() and Prepend(), the callback
553
+	// needs to be called on the reverse of the nodes.
554
+	if reverse {
555
+		for i, j := 0, len(ns)-1; i < j; i, j = i+1, j-1 {
556
+			ns[i], ns[j] = ns[j], ns[i]
557
+		}
558
+	}
559
+
560
+	for i, sn := range s.Nodes {
561
+		for _, n := range ns {
562
+			if i != lasti {
563
+				f(sn, cloneNode(n))
564
+			} else {
565
+				if n.Parent != nil {
566
+					n.Parent.RemoveChild(n)
567
+				}
568
+				f(sn, n)
569
+			}
570
+		}
571
+	}
572
+
573
+	return s
574
+}

+ 275
- 0
vendor/github.com/PuerkitoBio/goquery/property.go View File

@@ -0,0 +1,275 @@
1
+package goquery
2
+
3
+import (
4
+	"bytes"
5
+	"regexp"
6
+	"strings"
7
+
8
+	"golang.org/x/net/html"
9
+)
10
+
11
+var rxClassTrim = regexp.MustCompile("[\t\r\n]")
12
+
13
+// Attr gets the specified attribute's value for the first element in the
14
+// Selection. To get the value for each element individually, use a looping
15
+// construct such as Each or Map method.
16
+func (s *Selection) Attr(attrName string) (val string, exists bool) {
17
+	if len(s.Nodes) == 0 {
18
+		return
19
+	}
20
+	return getAttributeValue(attrName, s.Nodes[0])
21
+}
22
+
23
+// AttrOr works like Attr but returns default value if attribute is not present.
24
+func (s *Selection) AttrOr(attrName, defaultValue string) string {
25
+	if len(s.Nodes) == 0 {
26
+		return defaultValue
27
+	}
28
+
29
+	val, exists := getAttributeValue(attrName, s.Nodes[0])
30
+	if !exists {
31
+		return defaultValue
32
+	}
33
+
34
+	return val
35
+}
36
+
37
+// RemoveAttr removes the named attribute from each element in the set of matched elements.
38
+func (s *Selection) RemoveAttr(attrName string) *Selection {
39
+	for _, n := range s.Nodes {
40
+		removeAttr(n, attrName)
41
+	}
42
+
43
+	return s
44
+}
45
+
46
+// SetAttr sets the given attribute on each element in the set of matched elements.
47
+func (s *Selection) SetAttr(attrName, val string) *Selection {
48
+	for _, n := range s.Nodes {
49
+		attr := getAttributePtr(attrName, n)
50
+		if attr == nil {
51
+			n.Attr = append(n.Attr, html.Attribute{Key: attrName, Val: val})
52
+		} else {
53
+			attr.Val = val
54
+		}
55
+	}
56
+
57
+	return s
58
+}
59
+
60
+// Text gets the combined text contents of each element in the set of matched
61
+// elements, including their descendants.
62
+func (s *Selection) Text() string {
63
+	var buf bytes.Buffer
64
+
65
+	// Slightly optimized vs calling Each: no single selection object created
66
+	var f func(*html.Node)
67
+	f = func(n *html.Node) {
68
+		if n.Type == html.TextNode {
69
+			// Keep newlines and spaces, like jQuery
70
+			buf.WriteString(n.Data)
71
+		}
72
+		if n.FirstChild != nil {
73
+			for c := n.FirstChild; c != nil; c = c.NextSibling {
74
+				f(c)
75
+			}
76
+		}
77
+	}
78
+	for _, n := range s.Nodes {
79
+		f(n)
80
+	}
81
+
82
+	return buf.String()
83
+}
84
+
85
+// Size is an alias for Length.
86
+func (s *Selection) Size() int {
87
+	return s.Length()
88
+}
89
+
90
+// Length returns the number of elements in the Selection object.
91
+func (s *Selection) Length() int {
92
+	return len(s.Nodes)
93
+}
94
+
95
+// Html gets the HTML contents of the first element in the set of matched
96
+// elements. It includes text and comment nodes.
97
+func (s *Selection) Html() (ret string, e error) {
98
+	// Since there is no .innerHtml, the HTML content must be re-created from
99
+	// the nodes using html.Render.
100
+	var buf bytes.Buffer
101
+
102
+	if len(s.Nodes) > 0 {
103
+		for c := s.Nodes[0].FirstChild; c != nil; c = c.NextSibling {
104
+			e = html.Render(&buf, c)
105
+			if e != nil {
106
+				return
107
+			}
108
+		}
109
+		ret = buf.String()
110
+	}
111
+
112
+	return
113
+}
114
+
115
+// AddClass adds the given class(es) to each element in the set of matched elements.
116
+// Multiple class names can be specified, separated by a space or via multiple arguments.
117
+func (s *Selection) AddClass(class ...string) *Selection {
118
+	classStr := strings.TrimSpace(strings.Join(class, " "))
119
+
120
+	if classStr == "" {
121
+		return s
122
+	}
123
+
124
+	tcls := getClassesSlice(classStr)
125
+	for _, n := range s.Nodes {
126
+		curClasses, attr := getClassesAndAttr(n, true)
127
+		for _, newClass := range tcls {
128
+			if !strings.Contains(curClasses, " "+newClass+" ") {
129
+				curClasses += newClass + " "
130
+			}
131
+		}
132
+
133
+		setClasses(n, attr, curClasses)
134
+	}
135
+
136
+	return s
137
+}
138
+
139
+// HasClass determines whether any of the matched elements are assigned the
140
+// given class.
141
+func (s *Selection) HasClass(class string) bool {
142
+	class = " " + class + " "
143
+	for _, n := range s.Nodes {
144
+		classes, _ := getClassesAndAttr(n, false)
145
+		if strings.Contains(classes, class) {
146
+			return true
147
+		}
148
+	}
149
+	return false
150
+}
151
+
152
+// RemoveClass removes the given class(es) from each element in the set of matched elements.
153
+// Multiple class names can be specified, separated by a space or via multiple arguments.
154
+// If no class name is provided, all classes are removed.
155
+func (s *Selection) RemoveClass(class ...string) *Selection {
156
+	var rclasses []string
157
+
158
+	classStr := strings.TrimSpace(strings.Join(class, " "))
159
+	remove := classStr == ""
160
+
161
+	if !remove {
162
+		rclasses = getClassesSlice(classStr)
163
+	}
164
+
165
+	for _, n := range s.Nodes {
166
+		if remove {
167
+			removeAttr(n, "class")
168
+		} else {
169
+			classes, attr := getClassesAndAttr(n, true)
170
+			for _, rcl := range rclasses {
171
+				classes = strings.Replace(classes, " "+rcl+" ", " ", -1)
172
+			}
173
+
174
+			setClasses(n, attr, classes)
175
+		}
176
+	}
177
+
178
+	return s
179
+}
180
+
181
+// ToggleClass adds or removes the given class(es) for each element in the set of matched elements.
182
+// Multiple class names can be specified, separated by a space or via multiple arguments.
183
+func (s *Selection) ToggleClass(class ...string) *Selection {
184
+	classStr := strings.TrimSpace(strings.Join(class, " "))
185
+
186
+	if classStr == "" {
187
+		return s
188
+	}
189
+
190
+	tcls := getClassesSlice(classStr)
191
+
192
+	for _, n := range s.Nodes {
193
+		classes, attr := getClassesAndAttr(n, true)
194
+		for _, tcl := range tcls {
195
+			if strings.Contains(classes, " "+tcl+" ") {
196
+				classes = strings.Replace(classes, " "+tcl+" ", " ", -1)
197
+			} else {
198
+				classes += tcl + " "
199
+			}
200
+		}
201
+
202
+		setClasses(n, attr, classes)
203
+	}
204
+
205
+	return s
206
+}
207
+
208
+func getAttributePtr(attrName string, n *html.Node) *html.Attribute {
209
+	if n == nil {
210
+		return nil
211
+	}
212
+
213
+	for i, a := range n.Attr {
214
+		if a.Key == attrName {
215
+			return &n.Attr[i]
216
+		}
217
+	}
218
+	return nil
219
+}
220
+
221
+// Private function to get the specified attribute's value from a node.
222
+func getAttributeValue(attrName string, n *html.Node) (val string, exists bool) {
223
+	if a := getAttributePtr(attrName, n); a != nil {
224
+		val = a.Val
225
+		exists = true
226
+	}
227
+	return
228
+}
229
+
230
+// Get and normalize the "class" attribute from the node.
231
+func getClassesAndAttr(n *html.Node, create bool) (classes string, attr *html.Attribute) {
232
+	// Applies only to element nodes
233
+	if n.Type == html.ElementNode {
234
+		attr = getAttributePtr("class", n)
235
+		if attr == nil && create {
236
+			n.Attr = append(n.Attr, html.Attribute{
237
+				Key: "class",
238
+				Val: "",
239
+			})
240
+			attr = &n.Attr[len(n.Attr)-1]
241
+		}
242
+	}
243
+
244
+	if attr == nil {
245
+		classes = " "
246
+	} else {
247
+		classes = rxClassTrim.ReplaceAllString(" "+attr.Val+" ", " ")
248
+	}
249
+
250
+	return
251
+}
252
+
253
+func getClassesSlice(classes string) []string {
254
+	return strings.Split(rxClassTrim.ReplaceAllString(" "+classes+" ", " "), " ")
255
+}
256
+
257
+func removeAttr(n *html.Node, attrName string) {
258
+	for i, a := range n.Attr {
259
+		if a.Key == attrName {
260
+			n.Attr[i], n.Attr[len(n.Attr)-1], n.Attr =
261
+				n.Attr[len(n.Attr)-1], html.Attribute{}, n.Attr[:len(n.Attr)-1]
262
+			return
263
+		}
264
+	}
265
+}
266
+
267
+func setClasses(n *html.Node, attr *html.Attribute, classes string) {
268
+	classes = strings.TrimSpace(classes)
269
+	if classes == "" {
270
+		removeAttr(n, "class")
271
+		return
272
+	}
273
+
274
+	attr.Val = classes
275
+}

+ 49
- 0
vendor/github.com/PuerkitoBio/goquery/query.go View File

@@ -0,0 +1,49 @@
1
+package goquery
2
+
3
+import "golang.org/x/net/html"
4
+
5
+// Is checks the current matched set of elements against a selector and
6
+// returns true if at least one of these elements matches.
7
+func (s *Selection) Is(selector string) bool {
8
+	return s.IsMatcher(compileMatcher(selector))
9
+}
10
+
11
+// IsMatcher checks the current matched set of elements against a matcher and
12
+// returns true if at least one of these elements matches.
13
+func (s *Selection) IsMatcher(m Matcher) bool {
14
+	if len(s.Nodes) > 0 {
15
+		if len(s.Nodes) == 1 {
16
+			return m.Match(s.Nodes[0])
17
+		}
18
+		return len(m.Filter(s.Nodes)) > 0
19
+	}
20
+
21
+	return false
22
+}
23
+
24
+// IsFunction checks the current matched set of elements against a predicate and
25
+// returns true if at least one of these elements matches.
26
+func (s *Selection) IsFunction(f func(int, *Selection) bool) bool {
27
+	return s.FilterFunction(f).Length() > 0
28
+}
29
+
30
+// IsSelection checks the current matched set of elements against a Selection object
31
+// and returns true if at least one of these elements matches.
32
+func (s *Selection) IsSelection(sel *Selection) bool {
33
+	return s.FilterSelection(sel).Length() > 0
34
+}
35
+
36
+// IsNodes checks the current matched set of elements against the specified nodes
37
+// and returns true if at least one of these elements matches.
38
+func (s *Selection) IsNodes(nodes ...*html.Node) bool {
39
+	return s.FilterNodes(nodes...).Length() > 0
40
+}
41
+
42
+// Contains returns true if the specified Node is within,
43
+// at any depth, one of the nodes in the Selection object.
44
+// It is NOT inclusive, to behave like jQuery's implementation, and
45
+// unlike Javascript's .contains, so if the contained
46
+// node is itself in the selection, it returns false.
47
+func (s *Selection) Contains(n *html.Node) bool {
48
+	return sliceContains(s.Nodes, n)
49
+}

+ 698
- 0
vendor/github.com/PuerkitoBio/goquery/traversal.go View File

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

+ 141
- 0
vendor/github.com/PuerkitoBio/goquery/type.go View File

@@ -0,0 +1,141 @@
1
+package goquery
2
+
3
+import (
4
+	"errors"
5
+	"io"
6
+	"net/http"
7
+	"net/url"
8
+
9
+	"github.com/andybalholm/cascadia"
10
+
11
+	"golang.org/x/net/html"
12
+)
13
+
14
+// Document represents an HTML document to be manipulated. Unlike jQuery, which
15
+// is loaded as part of a DOM document, and thus acts upon its containing
16
+// document, GoQuery doesn't know which HTML document to act upon. So it needs
17
+// to be told, and that's what the Document class is for. It holds the root
18
+// document node to manipulate, and can make selections on this document.
19
+type Document struct {
20
+	*Selection
21
+	Url      *url.URL
22
+	rootNode *html.Node
23
+}
24
+
25
+// NewDocumentFromNode is a Document constructor that takes a root html Node
26
+// as argument.
27
+func NewDocumentFromNode(root *html.Node) *Document {
28
+	return newDocument(root, nil)
29
+}
30
+
31
+// NewDocument is a Document constructor that takes a string URL as argument.
32
+// It loads the specified document, parses it, and stores the root Document
33
+// node, ready to be manipulated.
34
+//
35
+// Deprecated: Use the net/http standard library package to make the request
36
+// and validate the response before calling goquery.NewDocumentFromReader
37
+// with the response's body.
38
+func NewDocument(url string) (*Document, error) {
39
+	// Load the URL
40
+	res, e := http.Get(url)
41
+	if e != nil {
42
+		return nil, e
43
+	}
44
+	return NewDocumentFromResponse(res)
45
+}
46
+
47
+// NewDocumentFromReader returns a Document from an io.Reader.
48
+// It returns an error as second value if the reader's data cannot be parsed
49
+// as html. It does not check if the reader is also an io.Closer, the
50
+// provided reader is never closed by this call. It is the responsibility
51
+// of the caller to close it if required.
52
+func NewDocumentFromReader(r io.Reader) (*Document, error) {
53
+	root, e := html.Parse(r)
54
+	if e != nil {
55
+		return nil, e
56
+	}
57
+	return newDocument(root, nil), nil
58
+}
59
+
60
+// NewDocumentFromResponse is another Document constructor that takes an http response as argument.
61
+// It loads the specified response's document, parses it, and stores the root Document
62
+// node, ready to be manipulated. The response's body is closed on return.
63
+//
64
+// Deprecated: Use goquery.NewDocumentFromReader with the response's body.
65
+func NewDocumentFromResponse(res *http.Response) (*Document, error) {
66
+	if res == nil {
67
+		return nil, errors.New("Response is nil")
68
+	}
69
+	defer res.Body.Close()
70
+	if res.Request == nil {
71
+		return nil, errors.New("Response.Request is nil")
72
+	}
73
+
74
+	// Parse the HTML into nodes
75
+	root, e := html.Parse(res.Body)
76
+	if e != nil {
77
+		return nil, e
78
+	}
79
+
80
+	// Create and fill the document
81
+	return newDocument(root, res.Request.URL), nil
82
+}
83
+
84
+// CloneDocument creates a deep-clone of a document.
85
+func CloneDocument(doc *Document) *Document {
86
+	return newDocument(cloneNode(doc.rootNode), doc.Url)
87
+}
88
+
89
+// Private constructor, make sure all fields are correctly filled.
90
+func newDocument(root *html.Node, url *url.URL) *Document {
91
+	// Create and fill the document
92
+	d := &Document{nil, url, root}
93
+	d.Selection = newSingleSelection(root, d)
94
+	return d
95
+}
96
+
97
+// Selection represents a collection of nodes matching some criteria. The
98
+// initial Selection can be created by using Document.Find, and then
99
+// manipulated using the jQuery-like chainable syntax and methods.
100
+type Selection struct {
101
+	Nodes    []*html.Node
102
+	document *Document
103
+	prevSel  *Selection
104
+}
105
+
106
+// Helper constructor to create an empty selection
107
+func newEmptySelection(doc *Document) *Selection {
108
+	return &Selection{nil, doc, nil}
109
+}
110
+
111
+// Helper constructor to create a selection of only one node
112
+func newSingleSelection(node *html.Node, doc *Document) *Selection {
113
+	return &Selection{[]*html.Node{node}, doc, nil}
114
+}
115
+
116
+// Matcher is an interface that defines the methods to match
117
+// HTML nodes against a compiled selector string. Cascadia's
118
+// Selector implements this interface.
119
+type Matcher interface {
120
+	Match(*html.Node) bool
121
+	MatchAll(*html.Node) []*html.Node
122
+	Filter([]*html.Node) []*html.Node
123
+}
124
+
125
+// compileMatcher compiles the selector string s and returns
126
+// the corresponding Matcher. If s is an invalid selector string,
127
+// it returns a Matcher that fails all matches.
128
+func compileMatcher(s string) Matcher {
129
+	cs, err := cascadia.Compile(s)
130
+	if err != nil {
131
+		return invalidMatcher{}
132
+	}
133
+	return cs
134
+}
135
+
136
+// invalidMatcher is a Matcher that always fails to match.
137
+type invalidMatcher struct{}
138
+
139
+func (invalidMatcher) Match(n *html.Node) bool             { return false }
140
+func (invalidMatcher) MatchAll(n *html.Node) []*html.Node  { return nil }
141
+func (invalidMatcher) Filter(ns []*html.Node) []*html.Node { return nil }

+ 161
- 0
vendor/github.com/PuerkitoBio/goquery/utilities.go View File

@@ -0,0 +1,161 @@
1
+package goquery
2
+
3
+import (
4
+	"bytes"
5
+
6
+	"golang.org/x/net/html"
7
+)
8
+
9
+// used to determine if a set (map[*html.Node]bool) should be used
10
+// instead of iterating over a slice. The set uses more memory and
11
+// is slower than slice iteration for small N.
12
+const minNodesForSet = 1000
13
+
14
+var nodeNames = []string{
15
+	html.ErrorNode:    "#error",
16
+	html.TextNode:     "#text",
17
+	html.DocumentNode: "#document",
18
+	html.CommentNode:  "#comment",
19
+}
20
+
21
+// NodeName returns the node name of the first element in the selection.
22
+// It tries to behave in a similar way as the DOM's nodeName property
23
+// (https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeName).
24
+//
25
+// Go's net/html package defines the following node types, listed with
26
+// the corresponding returned value from this function:
27
+//
28
+//     ErrorNode : #error
29
+//     TextNode : #text
30
+//     DocumentNode : #document
31
+//     ElementNode : the element's tag name
32
+//     CommentNode : #comment
33
+//     DoctypeNode : the name of the document type
34
+//
35
+func NodeName(s *Selection) string {
36
+	if s.Length() == 0 {
37
+		return ""
38
+	}
39
+	switch n := s.Get(0); n.Type {
40
+	case html.ElementNode, html.DoctypeNode:
41
+		return n.Data
42
+	default:
43
+		if n.Type >= 0 && int(n.Type) < len(nodeNames) {
44
+			return nodeNames[n.Type]
45
+		}
46
+		return ""
47
+	}
48
+}
49
+
50
+// OuterHtml returns the outer HTML rendering of the first item in
51
+// the selection - that is, the HTML including the first element's
52
+// tag and attributes.
53
+//
54
+// Unlike InnerHtml, this is a function and not a method on the Selection,
55
+// because this is not a jQuery method (in javascript-land, this is
56
+// a property provided by the DOM).
57
+func OuterHtml(s *Selection) (string, error) {
58
+	var buf bytes.Buffer
59
+
60
+	if s.Length() == 0 {
61
+		return "", nil
62
+	}
63
+	n := s.Get(0)
64
+	if err := html.Render(&buf, n); err != nil {
65
+		return "", err
66
+	}
67
+	return buf.String(), nil
68
+}
69
+
70
+// Loop through all container nodes to search for the target node.
71
+func sliceContains(container []*html.Node, contained *html.Node) bool {
72
+	for _, n := range container {
73
+		if nodeContains(n, contained) {
74
+			return true
75
+		}
76
+	}
77
+
78
+	return false
79
+}
80
+
81
+// Checks if the contained node is within the container node.
82
+func nodeContains(container *html.Node, contained *html.Node) bool {
83
+	// Check if the parent of the contained node is the container node, traversing
84
+	// upward until the top is reached, or the container is found.
85
+	for contained = contained.Parent; contained != nil; contained = contained.Parent {
86
+		if container == contained {
87
+			return true
88
+		}
89
+	}
90
+	return false
91
+}
92
+
93
+// Checks if the target node is in the slice of nodes.
94
+func isInSlice(slice []*html.Node, node *html.Node) bool {
95
+	return indexInSlice(slice, node) > -1
96
+}
97
+
98
+// Returns the index of the target node in the slice, or -1.
99
+func indexInSlice(slice []*html.Node, node *html.Node) int {
100
+	if node != nil {
101
+		for i, n := range slice {
102
+			if n == node {
103
+				return i
104
+			}
105
+		}
106
+	}
107
+	return -1
108
+}
109
+
110
+// Appends the new nodes to the target slice, making sure no duplicate is added.
111
+// There is no check to the original state of the target slice, so it may still
112
+// contain duplicates. The target slice is returned because append() may create
113
+// a new underlying array. If targetSet is nil, a local set is created with the
114
+// target if len(target) + len(nodes) is greater than minNodesForSet.
115
+func appendWithoutDuplicates(target []*html.Node, nodes []*html.Node, targetSet map[*html.Node]bool) []*html.Node {
116
+	// if there are not that many nodes, don't use the map, faster to just use nested loops
117
+	// (unless a non-nil targetSet is passed, in which case the caller knows better).
118
+	if targetSet == nil && len(target)+len(nodes) < minNodesForSet {
119
+		for _, n := range nodes {
120
+			if !isInSlice(target, n) {
121
+				target = append(target, n)
122
+			}