review PR, fix WrapInner bug

This commit is contained in:
Martin Angers
2014-11-28 11:46:58 -05:00
parent 2455631714
commit a923db6a4b
5 changed files with 132 additions and 20 deletions

View File

@@ -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]))
}
})

View File

@@ -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
View File

@@ -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
View 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>

View File

@@ -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")