panic on error, instead of empty selection (like jQuery/Sizzle)

This commit is contained in:
Martin Angers
2012-08-30 15:08:36 -04:00
parent 2db07845a9
commit e4467e0f04
7 changed files with 60 additions and 58 deletions
+2
View File
@@ -4,6 +4,8 @@ import (
"exp/html"
)
// TODO : Should return a new Selection object, use pushStack()
// Adds matching nodes to the current selection. Returns the same Selection object.
// The new selector string is run in the context of the document of the Selection object.
func (this *Selection) Add(selector string) *Selection {
+1 -5
View File
@@ -32,17 +32,13 @@ func childrenWithContext(selector string, nodes ...*html.Node) []*html.Node {
var matches []*html.Node
var allChildren bool
var sel cascadia.Selector
var e error
selector = strings.TrimSpace(selector)
if selector == "*" || selector == "" {
// Get all children
allChildren = true
} else {
if sel, e = cascadia.Compile(selector); e != nil {
// Selector doesn't compile, empty selection
return nil
}
sel = cascadia.MustCompile(selector)
}
for _, n := range nodes {
+9 -6
View File
@@ -37,11 +37,14 @@ necessary since multiple return values cannot be used to allow a chainable inter
*/
package goquery
// Positional Filtering: First(), Last(), Eq(), Get(), Index()
// Positional Manipulation: First(), Last(), Eq(), Get(), Index(), Slice()
// Filtering: Filter(), Not(), Has(), End()
// "Expanding": Add(), AndSelf()
// Reflect (query) node: Is(), Contains(), HasClass()
// Inspect node: Contents(), Html(), Text(), Attr()
// Inspect node: Contents(), Html(), Text(), Attr(), Val()
// Selection "properties": Length(), Size()
// Traversal: Find(), Children(), Parents...(), Next...(), Prev...(), Closest(), Siblings()
// Iteration: Each(), Map()
// TODO : Benchmarks
@@ -73,17 +76,17 @@ package goquery
// - Next() - Tree traversal
// - NextAll() - Tree traversal
// - NextUntil() - Tree traversal
// - Not() - Filtering
// x Not() - Filtering
// - Parent() - Tree traversal
// - Parents() - Tree traversal
// - ParentsUntil() - Tree traversal
// - Prev() - Tree traversal
// - PrevAll() - Tree traversal
// - PrevUntil() - Tree traversal
// - PushStack() ? - Internals
// x PushStack() ? - Internals
// - Siblings() - Tree traversal
// - Slice() - Filtering
// - Text() - DOM Manipulation
// - ToArray() Is not implemented, is Selection.Nodes
// - Unique() ? Or internally only, to remove duplicates and maintain node order? - Utilities
// x ToArray() Is not implemented, is Selection.Nodes
// x Unique() ? Or internally only, to remove duplicates and maintain node order? - Utilities
// - Val() ? - Attributes
+35 -36
View File
@@ -6,61 +6,60 @@ import (
)
func (this *Selection) Filter(selector string) *Selection {
sel, e := cascadia.Compile(selector)
if e != nil {
// Selector doesn't compile, which means empty selection
return newEmptySelection(this.document)
}
return pushStack(this, winnow(this, selector, true))
}
return &Selection{sel.Filter(this.Nodes), this.document, nil}
func (this *Selection) Not(selector string) *Selection {
return pushStack(this, winnow(this, selector, false))
}
func (this *Selection) FilterFunction(f func(int, *Selection) bool) *Selection {
return &Selection{winnowFunction(this, f, true), this.document, nil}
return pushStack(this, winnowFunction(this, f, true))
}
func (this *Selection) NotFunction(f func(int, *Selection) bool) *Selection {
return &Selection{winnowFunction(this, f, false), this.document, nil}
return pushStack(this, winnowFunction(this, f, false))
}
func (this *Selection) FilterNode(node *html.Node) *Selection {
if isInSlice(this.Nodes, node) {
return newSingleSelection(node, this.document)
}
return newEmptySelection(this.document)
func (this *Selection) FilterNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, true))
}
func (this *Selection) NotNodes(nodes ...*html.Node) *Selection {
return pushStack(this, winnowNodes(this, nodes, false))
}
func (this *Selection) FilterSelection(s *Selection) *Selection {
return pushStack(this, winnowNodes(this, s.Nodes, true))
}
func (this *Selection) NotSelection(s *Selection) *Selection {
return pushStack(this, winnowNodes(this, s.Nodes, false))
}
func (this *Selection) Union(s *Selection) *Selection {
return this.FilterSelection(s)
}
func (this *Selection) FilterSelection(s *Selection) *Selection {
var matches []*html.Node
func winnow(sel *Selection, selector string, keep bool) []*html.Node {
cs := cascadia.MustCompile(selector)
if s == nil {
return newEmptySelection(this.document)
// Optimize if keep is requested
if keep {
return cs.Filter(sel.Nodes)
} else {
// Use grep
return grep(sel, func(i int, s *Selection) bool {
return !cs(s.Get(0))
})
}
// Check for a match for each current selection
for _, n1 := range this.Nodes {
for _, n2 := range s.Nodes {
if n1 == n2 && !isInSlice(matches, n2) {
matches = append(matches, n1)
break
}
}
}
return &Selection{matches, this.document, nil}
return nil
}
func winnow(sel *Selection, selector string) []*html.Node {
cs, e := cascadia.Compile(selector)
if e != nil {
// Selector doesn't compile, which means empty selection
return nil
}
return cs.Filter(sel.Nodes)
func winnowNodes(sel *Selection, nodes []*html.Node, keep bool) []*html.Node {
return grep(sel, func(i int, s *Selection) bool {
return isInSlice(nodes, s.Get(0)) == keep
})
}
// Identical functionality for FilterFunction() and NotFunction(), only keep changes.
+1 -1
View File
@@ -29,7 +29,7 @@ func TestFilterFunction(t *testing.T) {
func TestFilterNode(t *testing.T) {
sel := doc.Find(".pvk-content")
sel2 := sel.FilterNode(sel.Nodes[2])
sel2 := sel.FilterNodes(sel.Nodes[2])
if len(sel2.Nodes) != 1 {
t.Errorf("Expected 1 node, found %v.", len(sel2.Nodes))
}
+1 -6
View File
@@ -19,12 +19,7 @@ func (this *Selection) Find(selector string) *Selection {
func findWithContext(selector string, nodes ...*html.Node) []*html.Node {
var matches []*html.Node
sel, e := cascadia.Compile(selector)
if e != nil {
// Selector doesn't compile, which means empty selection
return nil
}
sel := cascadia.MustCompile(selector)
// Match the selector on each node
for _, n := range nodes {
matches = append(matches, sel.MatchAll(n)...)
+11 -4
View File
@@ -12,12 +12,19 @@ func TestFind(t *testing.T) {
}
func TestFindInvalidSelector(t *testing.T) {
defer func() {
if e := recover(); e == nil {
t.Error("Expected panic due to invalid selector.")
}
}()
doc.Find(":+ ^")
}
func TestEachEmptySelection(t *testing.T) {
var cnt int
sel := doc.Find(":+ ^")
if sel.Nodes != nil {
t.Error("Expected a Selection object with Nodes == nil.")
}
sel := doc.Find("zzzz")
sel.Each(func(i int, n *Selection) {
cnt++
})