mirror of
https://github.com/PuerkitoBio/goquery
synced 2025-09-26 21:01:21 +08:00
review PR, fix WrapInner bug
This commit is contained in:
@@ -13,7 +13,7 @@ import (
|
||||
// If one of the matched elements in the selection is not currently in the
|
||||
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||
//
|
||||
// This follows the same rules outlined in Selection.Append.
|
||||
// This follows the same rules as Selection.Append.
|
||||
func (s *Selection) After(selector string) *Selection {
|
||||
return s.AfterMatcher(cascadia.MustCompile(selector))
|
||||
}
|
||||
@@ -24,7 +24,7 @@ func (s *Selection) After(selector string) *Selection {
|
||||
// If one of the matched elements in the selection is not currently in the
|
||||
// document, it's impossible to insert nodes after it, so it will be ignored.
|
||||
//
|
||||
// This follows the same rules outlined in Selection.Append.
|
||||
// This follows the same rules as Selection.Append.
|
||||
func (s *Selection) AfterMatcher(m Matcher) *Selection {
|
||||
return s.AfterNodes(m.MatchAll(s.document.rootNode)...)
|
||||
}
|
||||
@@ -32,21 +32,21 @@ func (s *Selection) AfterMatcher(m Matcher) *Selection {
|
||||
// AfterSelection inserts the elements in the selection after each element in the set of matched
|
||||
// elements.
|
||||
//
|
||||
// This follows the same rules outlined in Selection.Append.
|
||||
// This follows the same rules as Selection.Append.
|
||||
func (s *Selection) AfterSelection(sel *Selection) *Selection {
|
||||
return s.AfterNodes(sel.Nodes...)
|
||||
}
|
||||
|
||||
// AfterHtml parses the html and inserts it after the set of matched elements.
|
||||
//
|
||||
// This follows the same rules outlined in Selection.Append.
|
||||
// This follows the same rules as Selection.Append.
|
||||
func (s *Selection) AfterHtml(html string) *Selection {
|
||||
return s.AfterNodes(parseHtml(html)...)
|
||||
}
|
||||
|
||||
// AfterNodes inserts the nodes after each element in the set of matched elements.
|
||||
//
|
||||
// This follows the same rules outlined in Selection.Append.
|
||||
// This follows the same rules as Selection.Append.
|
||||
func (s *Selection) AfterNodes(ns ...*html.Node) *Selection {
|
||||
return s.manipulateNodes(ns, true, func(sn *html.Node, n *html.Node) {
|
||||
if sn.Parent != nil {
|
||||
@@ -237,6 +237,9 @@ func (s *Selection) ReplaceWithNodes(ns ...*html.Node) *Selection {
|
||||
// It returns the original selection.
|
||||
func (s *Selection) Unwrap() *Selection {
|
||||
s.Parent().Each(func(i int, ss *Selection) {
|
||||
// For some reason, jquery allows unwrap to remove the <head> element, so
|
||||
// allowing it here too. Same for <html>. Why it allows those elements to
|
||||
// be unwrapped while not allowing body is a mystery to me.
|
||||
if ss.Nodes[0].Data != "body" {
|
||||
ss.ReplaceWithSelection(ss.Contents())
|
||||
}
|
||||
@@ -248,6 +251,7 @@ func (s *Selection) Unwrap() *Selection {
|
||||
// Wrap wraps each element in the set of matched elements inside the first
|
||||
// element matched by the given selector. The matched child is cloned before
|
||||
// being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) Wrap(selector string) *Selection {
|
||||
return s.WrapMatcher(cascadia.MustCompile(selector))
|
||||
@@ -256,6 +260,7 @@ func (s *Selection) Wrap(selector string) *Selection {
|
||||
// WrapMatcher wraps each element in the set of matched elements inside the
|
||||
// first element matched by the given matcher. The matched child is cloned
|
||||
// before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapMatcher(m Matcher) *Selection {
|
||||
return s.wrapNodes(m.MatchAll(s.document.rootNode)...)
|
||||
@@ -264,6 +269,7 @@ func (s *Selection) WrapMatcher(m Matcher) *Selection {
|
||||
// WrapSelection wraps each element in the set of matched elements inside the
|
||||
// first element in the given Selection. The element is cloned before being
|
||||
// inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapSelection(sel *Selection) *Selection {
|
||||
return s.wrapNodes(sel.Nodes...)
|
||||
@@ -271,6 +277,7 @@ func (s *Selection) WrapSelection(sel *Selection) *Selection {
|
||||
|
||||
// WrapHtml wraps each element in the set of matched elements inside the inner-
|
||||
// most child of the given HTML.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapHtml(html string) *Selection {
|
||||
return s.wrapNodes(parseHtml(html)...)
|
||||
@@ -279,6 +286,7 @@ func (s *Selection) WrapHtml(html string) *Selection {
|
||||
// WrapNode wraps each element in the set of matched elements inside the inner-
|
||||
// most child of the given node. The given node is copied before being inserted
|
||||
// into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapNode(n *html.Node) *Selection {
|
||||
return s.wrapNodes(n)
|
||||
@@ -293,32 +301,36 @@ func (s *Selection) wrapNodes(ns ...*html.Node) *Selection {
|
||||
}
|
||||
|
||||
// WrapAll wraps a single HTML structure, matched by the given selector, around
|
||||
// each element in the set of matched elements. The matched child is cloned
|
||||
// all elements in the set of matched elements. The matched child is cloned
|
||||
// before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapAll(selector string) *Selection {
|
||||
return s.WrapAllMatcher(cascadia.MustCompile(selector))
|
||||
}
|
||||
|
||||
// WrapAllMatcher wraps a single HTML structure, matched by the given Matcher,
|
||||
// around each element in the set of matched elements. The matched child is
|
||||
// around all elements in the set of matched elements. The matched child is
|
||||
// cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapAllMatcher(m Matcher) *Selection {
|
||||
return s.wrapAllNodes(m.MatchAll(s.document.rootNode)...)
|
||||
}
|
||||
|
||||
// WrapAllSelection wraps a single HTML structure, the first node of the given
|
||||
// Selection, around each element in the set of matched elements. The matched
|
||||
// Selection, around all elements in the set of matched elements. The matched
|
||||
// child is cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapAllSelection(sel *Selection) *Selection {
|
||||
return s.wrapAllNodes(sel.Nodes...)
|
||||
}
|
||||
|
||||
// WrapAllHtml wraps the given HTML structure around each element in the set of
|
||||
// WrapAllHtml wraps the given HTML structure around all elements in the set of
|
||||
// matched elements. The matched child is cloned before being inserted into the
|
||||
// document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapAllHtml(html string) *Selection {
|
||||
return s.wrapAllNodes(parseHtml(html)...)
|
||||
@@ -334,6 +346,7 @@ func (s *Selection) wrapAllNodes(ns ...*html.Node) *Selection {
|
||||
// WrapAllNode wraps the given node around the first element in the Selection,
|
||||
// making all other nodes in the Selection children of the given node. The node
|
||||
// is cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapAllNode(n *html.Node) *Selection {
|
||||
if s.Size() == 0 {
|
||||
@@ -360,6 +373,7 @@ func (s *Selection) WrapAllNode(n *html.Node) *Selection {
|
||||
// WrapInner wraps an HTML structure, matched by the given selector, around the
|
||||
// content of element in the set of matched elements. The matched child is
|
||||
// cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapInner(selector string) *Selection {
|
||||
return s.WrapInnerMatcher(cascadia.MustCompile(selector))
|
||||
@@ -368,6 +382,7 @@ func (s *Selection) WrapInner(selector string) *Selection {
|
||||
// WrapInnerMatcher wraps an HTML structure, matched by the given selector,
|
||||
// around the content of element in the set of matched elements. The matched
|
||||
// child is cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapInnerMatcher(m Matcher) *Selection {
|
||||
return s.wrapInnerNodes(m.MatchAll(s.document.rootNode)...)
|
||||
@@ -376,6 +391,7 @@ func (s *Selection) WrapInnerMatcher(m Matcher) *Selection {
|
||||
// WrapInnerSelection wraps an HTML structure, matched by the given selector,
|
||||
// around the content of element in the set of matched elements. The matched
|
||||
// child is cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
|
||||
return s.wrapInnerNodes(sel.Nodes...)
|
||||
@@ -384,6 +400,7 @@ func (s *Selection) WrapInnerSelection(sel *Selection) *Selection {
|
||||
// WrapInnerHtml wraps an HTML structure, matched by the given selector, around
|
||||
// the content of element in the set of matched elements. The matched child is
|
||||
// cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapInnerHtml(html string) *Selection {
|
||||
return s.wrapInnerNodes(parseHtml(html)...)
|
||||
@@ -392,19 +409,24 @@ func (s *Selection) WrapInnerHtml(html string) *Selection {
|
||||
// WrapInnerNode wraps an HTML structure, matched by the given selector, around
|
||||
// the content of element in the set of matched elements. The matched child is
|
||||
// cloned before being inserted into the document.
|
||||
//
|
||||
// It returns the original set of elements.
|
||||
func (s *Selection) WrapInnerNode(n *html.Node) *Selection {
|
||||
return s.wrapInnerNodes(n)
|
||||
}
|
||||
|
||||
func (s *Selection) wrapInnerNodes(ns ...*html.Node) *Selection {
|
||||
if len(ns) == 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
s.Each(func(i int, s *Selection) {
|
||||
contents := s.Contents()
|
||||
|
||||
if contents.Size() > 0 {
|
||||
contents.wrapAllNodes(ns...)
|
||||
} else {
|
||||
s.AppendNodes(ns...)
|
||||
s.AppendNodes(cloneNode(ns[0]))
|
||||
}
|
||||
})
|
||||
|
||||
|
@@ -202,6 +202,7 @@ func TestReplaceWith(t *testing.T) {
|
||||
|
||||
doc.Find("#nf6").ReplaceWith("#main")
|
||||
assertLength(t, doc.Find("#foot #main:last-child").Nodes, 1)
|
||||
printSel(t, doc.Selection)
|
||||
|
||||
doc.Find("#foot").ReplaceWith("#main")
|
||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||
@@ -223,7 +224,7 @@ func TestReplaceWithSelection(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
sel := doc.Find("#nf6").ReplaceWithSelection(doc.Find("#nf5"))
|
||||
|
||||
assertLength(t, sel.Filter("#nf6").Nodes, 1)
|
||||
assertSelectionIs(t, sel, "#nf6")
|
||||
assertLength(t, doc.Find("#nf6").Nodes, 0)
|
||||
assertLength(t, doc.Find("#nf5").Nodes, 1)
|
||||
|
||||
@@ -235,11 +236,20 @@ func TestUnwrap(t *testing.T) {
|
||||
|
||||
doc.Find("#nf5").Unwrap()
|
||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||
|
||||
assertLength(t, doc.Find("body > #nf1").Nodes, 1)
|
||||
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
|
||||
doc = Doc2Clone()
|
||||
|
||||
doc.Find("#nf5, #n1").Unwrap()
|
||||
assertLength(t, doc.Find("#foot").Nodes, 0)
|
||||
assertLength(t, doc.Find("#main").Nodes, 0)
|
||||
assertLength(t, doc.Find("body > #n1").Nodes, 1)
|
||||
assertLength(t, doc.Find("body > #nf5").Nodes, 1)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestUnwrapBody(t *testing.T) {
|
||||
@@ -252,6 +262,28 @@ func TestUnwrapBody(t *testing.T) {
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestUnwrapHead(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
|
||||
doc.Find("title").Unwrap()
|
||||
assertLength(t, doc.Find("head").Nodes, 0)
|
||||
assertLength(t, doc.Find("head > title").Nodes, 0)
|
||||
assertLength(t, doc.Find("title").Nodes, 1)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestUnwrapHtml(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
|
||||
doc.Find("head").Unwrap()
|
||||
assertLength(t, doc.Find("html").Nodes, 0)
|
||||
assertLength(t, doc.Find("html head").Nodes, 0)
|
||||
assertLength(t, doc.Find("head").Nodes, 1)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
doc.Find("#nf1").Wrap("#nf2")
|
||||
@@ -280,9 +312,9 @@ func TestWrapEmpty(t *testing.T) {
|
||||
|
||||
func TestWrapHtml(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
doc.Find("#nf1").WrapHtml(wrapHtml)
|
||||
nf1 := doc.Find("#foot div#ins:first-child div p em b #nf1")
|
||||
assertLength(t, nf1.Nodes, 1)
|
||||
doc.Find(".odd").WrapHtml(wrapHtml)
|
||||
nf2 := doc.Find("#ins #nf2")
|
||||
assertLength(t, nf2.Nodes, 1)
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
@@ -318,12 +350,36 @@ func TestWrapAllHtml(t *testing.T) {
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestWrapInner(t *testing.T) {
|
||||
func TestWrapInnerNoContent(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
doc.Find(".one").WrapInner(".two")
|
||||
|
||||
nf1 := doc.Find("#foot #n2 ~ #nf2")
|
||||
assertLength(t, nf1.Nodes, 1)
|
||||
twos := doc.Find(".two")
|
||||
assertLength(t, twos.Nodes, 4)
|
||||
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestWrapInnerWithContent(t *testing.T) {
|
||||
doc := Doc3Clone()
|
||||
doc.Find(".one").WrapInner(".two")
|
||||
|
||||
twos := doc.Find(".two")
|
||||
assertLength(t, twos.Nodes, 4)
|
||||
assertLength(t, doc.Find(".one .two").Nodes, 2)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
||||
func TestWrapInnerNoWrapper(t *testing.T) {
|
||||
doc := Doc2Clone()
|
||||
doc.Find(".one").WrapInner(".not-exist")
|
||||
|
||||
twos := doc.Find(".two")
|
||||
assertLength(t, twos.Nodes, 2)
|
||||
assertLength(t, doc.Find(".one").Nodes, 2)
|
||||
assertLength(t, doc.Find(".one .two").Nodes, 0)
|
||||
|
||||
printSel(t, doc.Selection)
|
||||
}
|
||||
|
4
testdata/page2.html
vendored
4
testdata/page2.html
vendored
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<title>Tests for siblings</title>
|
||||
</head>
|
||||
<body>
|
||||
<BODY>
|
||||
<div id="main">
|
||||
<div id="n1" class="one even row"></div>
|
||||
<div id="n2" class="two odd row"></div>
|
||||
@@ -20,5 +20,5 @@
|
||||
<div id="nf5" class="five even row odder"></div>
|
||||
<div id="nf6" class="six odd row"></div>
|
||||
</div>
|
||||
</body>
|
||||
</BODY>
|
||||
</html>
|
||||
|
24
testdata/page3.html
vendored
Normal file
24
testdata/page3.html
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tests for siblings</title>
|
||||
</head>
|
||||
<BODY>
|
||||
<div id="main">
|
||||
<div id="n1" class="one even row">hello</div>
|
||||
<div id="n2" class="two odd row"></div>
|
||||
<div id="n3" class="three even row"></div>
|
||||
<div id="n4" class="four odd row"></div>
|
||||
<div id="n5" class="five even row"></div>
|
||||
<div id="n6" class="six odd row"></div>
|
||||
</div>
|
||||
<div id="foot">
|
||||
<div id="nf1" class="one even row">text</div>
|
||||
<div id="nf2" class="two odd row"></div>
|
||||
<div id="nf3" class="three even row"></div>
|
||||
<div id="nf4" class="four odd row"></div>
|
||||
<div id="nf5" class="five even row odder"></div>
|
||||
<div id="nf6" class="six odd row"></div>
|
||||
</div>
|
||||
</BODY>
|
||||
</html>
|
10
type_test.go
10
type_test.go
@@ -12,6 +12,7 @@ import (
|
||||
// Test helper functions and members
|
||||
var doc *Document
|
||||
var doc2 *Document
|
||||
var doc3 *Document
|
||||
var docB *Document
|
||||
var docW *Document
|
||||
|
||||
@@ -33,6 +34,15 @@ func Doc2() *Document {
|
||||
func Doc2Clone() *Document {
|
||||
return CloneDocument(Doc2())
|
||||
}
|
||||
func Doc3() *Document {
|
||||
if doc3 == nil {
|
||||
doc3 = loadDoc("page3.html")
|
||||
}
|
||||
return doc3
|
||||
}
|
||||
func Doc3Clone() *Document {
|
||||
return CloneDocument(Doc3())
|
||||
}
|
||||
func DocB() *Document {
|
||||
if docB == nil {
|
||||
docB = loadDoc("gotesting.html")
|
||||
|
Reference in New Issue
Block a user