rind 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,9 +1,13 @@
1
+ == 0.1.4 - 2010.06.26
2
+ * Xpath searches with attribute values containing a <tt>/</tt>, like <tt>style[@type="text/css"]</tt>, broke the query parser.
3
+ * The Manipulate::insert_after and Manipulate::insert_before functions and Xpath positions were not returning the correct nodes when other available nodes matched <tt>==</tt>.
4
+
1
5
  == 0.1.3 - 2010.06.20
2
6
  * The Xpath function 's' will return an empty Rind::Node rather than +nil+.
3
7
  * Processing instructions were not being treated as nodes.
4
8
  * DocType nodes were lacking proper equality checks.
5
- * The +next+, +next_sibling+, +prev+ and +prev_sibling+ functions were not returning the correct nodes when other available nodes matched <tt>==</tt>.
6
- * Adding +exact_index+ function to Rind::Nodes. (used in previous bug fix)
9
+ * The Traverse::next, Traverse::next_sibling, Traverse::prev and Traverse::prev_sibling functions were not returning the correct nodes when other available nodes matched <tt>==</tt>.
10
+ * Adding exact_index function to Rind::Nodes. (used in previous bug fix)
7
11
 
8
12
  == 0.1.2 - 2010.06.17
9
13
  * When parsing HTML, script and style tags will not break because of a "<" in their content.
@@ -1,27 +1,24 @@
1
1
  # Note: These functions are not available for the root node in a tree.
2
2
  module Manipulate
3
- # Calls {Rind::Children::insert}[link:classes/Rind/Children.html#insert]
4
- # to add nodes after <tt>self</tt>.
3
+ # Calls Rind::Children::insert to add nodes after <tt>self</tt>.
5
4
  # === Example
6
5
  # nodes = ['a', 'b', 'c']
7
6
  # nodes[0].insert_after('d', 'e') => ['a', 'd', 'e', 'b', 'c']
8
7
  def insert_after(*nodes)
9
8
  children = self.parent.children
10
- children.insert(children.index(self)+1, *nodes)
9
+ children.insert(children.exact_index(self)+1, *nodes)
11
10
  end
12
11
 
13
- # Calls {Rind::Children::insert}[link:classes/Rind/Children.html#insert]
14
- # to add nodes before <tt>self</tt>.
12
+ # Calls Rind::Children::insert to add nodes before <tt>self</tt>.
15
13
  # === Example
16
14
  # nodes = ['a', 'b', 'c']
17
15
  # nodes[2].insert_after('d', 'e') => ['a', 'b', 'd', 'e', 'c']
18
16
  def insert_before(*nodes)
19
17
  children = self.parent.children
20
- children.insert(children.index(self), *nodes)
18
+ children.insert(children.exact_index(self), *nodes)
21
19
  end
22
20
 
23
- # Calls {Rind::Children::delete}[link:classes/Rind/Children.html#delete]
24
- # on <tt>self</tt>.
21
+ # Calls Rind::Children::delete on <tt>self</tt>.
25
22
  # === Example
26
23
  # nodes = ['a', 'b', 'c']
27
24
  # nodes[1].delete => 'b'
data/lib/rind/xpath.rb CHANGED
@@ -4,38 +4,42 @@
4
4
  module Xpath
5
5
  # Xpath search of a node that returns a list of matching nodes.
6
6
  def s(path)
7
- node = self;
7
+ node = self
8
8
 
9
9
  # absolute paths to the top
10
10
  if '/' == path[0,1]
11
11
  while not node.parent.nil?
12
12
  node = node.parent
13
13
  end
14
- if 1 < path.length and '/' == path[1,1]
15
- path[0] = ''
16
- else
14
+ if '/' != path[1,1]
17
15
  path[0] = 'self::'
18
16
  end
19
17
  end
20
18
 
21
19
  # node check
22
20
  nodes = [node]
23
- path.split('/').each do |step|
24
- case step
25
- when ''
26
- step = 'descendant-or-self::node()'
21
+ path.scan(%r{(?:^\/?|\/)
22
+ (?:(.*?)::)? # axis
23
+ ([^\/\[]+)? # node test
24
+ ((?:\[.+?\])*) # predicates
25
+ }x) do |axis, node_test, predicates|
26
+ case node_test
27
+ when nil
28
+ axis = 'descendant-or-self'
29
+ node_test = 'node()'
27
30
  when '.'
28
- step = 'self::node()'
31
+ axis = 'self'
32
+ node_test = 'node()'
29
33
  when '..'
30
- step = 'parent::node()'
34
+ axis = 'parent'
35
+ node_test = 'node()'
31
36
  end
32
37
 
33
- step.gsub!(/^@/, 'attribute::')
34
-
35
- step =~ /^(?:(.*?)::)?(.+?)(\[.*?)?$/
36
- axis, node_test, predicates = $1, $2, $3
37
38
  axis = 'child' if axis.nil?
38
39
 
40
+ node_test.gsub!(/^@/, 'attribute::')
41
+ predicates.gsub!(/^@/, 'attribute::')
42
+
39
43
  # find matching nodes
40
44
  nodes = nodes.collect{|node| node.find_matching_nodes(axis, node_test)}.flatten.compact
41
45
 
@@ -51,7 +55,9 @@ module Xpath
51
55
  # last()
52
56
  predicate.gsub!(/last\(\)/, nodes.length.to_s)
53
57
 
54
- nodes = nodes.find_all{|node| node.validate_predicate(predicate.clone, nodes.index(node)+1)}
58
+ nodes = nodes.find_all do |node|
59
+ node.validate_predicate(predicate.clone, Rind::Nodes[*nodes].exact_index(node)+1)
60
+ end
55
61
  break if nodes.empty?
56
62
  end
57
63
  end
@@ -3,21 +3,22 @@ require 'rind'
3
3
 
4
4
  class ManipulateTest < Test::Unit::TestCase
5
5
  def setup
6
- @p = Rind::Html::P.new(:children => ['This is some text!'])
7
- @br = Rind::Html::Br.new()
8
- @hr = Rind::Html::Hr.new()
6
+ @a = Rind::Html::A.new()
7
+ @b1 = Rind::Html::B.new()
8
+ @b2 = Rind::Html::B.new()
9
+ @a.children.push(@b1, @b2)
9
10
  end
10
11
 
11
12
  def test_insert_after
12
- assert_equal(@p.children.first.insert_after(@br, @hr), ['This is some text!', @br, @hr])
13
+ assert_equal(@a.children[1].insert_after('foo'), [@b1, @b2, 'foo'])
13
14
  end
14
15
 
15
16
  def test_insert_before
16
- assert_equal(@p.children.first.insert_before(@br, @hr), [@br, @hr, 'This is some text!'])
17
+ assert_equal(@a.children[1].insert_before('foo'), [@b1, 'foo', @b2])
17
18
  end
18
19
 
19
20
  def test_remove
20
- assert_equal(@p.children.first.remove, 'This is some text!')
21
- assert(@p.children.empty?)
21
+ assert_equal(@a.children[1].remove, @b2)
22
+ assert(@a.children.empty?)
22
23
  end
23
24
  end
data/test/xml_test.rb CHANGED
@@ -4,11 +4,11 @@ require 'rind'
4
4
  class XmlTest < Test::Unit::TestCase
5
5
  def test_to_s
6
6
  # no children
7
- a_tag = Rind::Xml::A.new();
7
+ a_tag = Rind::Xml::A.new()
8
8
  assert_equal(a_tag.to_s, '<a />')
9
9
 
10
10
  # with children
11
- b_tag = Rind::Xml::B.new(:children => a_tag);
11
+ b_tag = Rind::Xml::B.new(:children => a_tag)
12
12
  assert_equal(b_tag.to_s, '<b><a /></b>')
13
13
  end
14
14
  end
data/test/xpath_test.rb CHANGED
@@ -3,28 +3,84 @@ require 'rind'
3
3
 
4
4
  class XpathTest < Test::Unit::TestCase
5
5
  def setup
6
- @br_one = Rind::Html::Br.new(:attributes => {:id => 'br_one', :class => '1'})
7
- @br_two = Rind::Html::Br.new(:attributes => {:id => 'br_two', :class => '2'})
8
- @br_three = Rind::Html::Br.new()
9
- @p_one = Rind::Html::P.new(:attributes => {:class => '1'}, :children => [@br_one, @br_two, @br_three])
6
+ @a = Rind::Html::A.new
7
+ @b1 = Rind::Html::B.new(:attributes => {:id => '1', :class => '1'})
8
+ @b2 = Rind::Html::B.new(:attributes => {:id => '2', :class => '2'})
9
+ @b3 = Rind::Html::B.new(:attributes => {:id => '3', :type => 'text/css'})
10
+ @c1 = Rind::Html::C.new()
11
+ @c2 = Rind::Html::C.new()
12
+ @c3 = Rind::Html::C.new()
13
+ @comment = Rind::Comment.new('comment')
14
+ @pi = Rind::ProcessingInstruction.new('pi')
15
+ @text = Rind::Text.new('text')
16
+ @b1.children.push(@c1)
17
+ @b2.children.push(@c2, @c3)
18
+ @b3.children.push(@comment, @pi, @text)
19
+ @a.children.push(@b1, @b2, @b3)
10
20
  end
11
21
 
12
22
  def test_s
13
- assert_equal(@p_one.s('br'), [@br_one, @br_two, @br_three])
23
+ assert_equal(@c1.s('/a'), [@a])
14
24
 
15
- # attribute tests
16
- assert_equal(@p_one.s('br[@class="1"]'), [@br_one])
25
+ assert_equal(@a.s('//c'), [@c1, @c2, @c3])
17
26
 
18
- # position tests
19
- assert_equal(@p_one.s('br[2]'), [@br_two])
20
- assert_equal(@p_one.s('br[position()=1]'), [@br_one])
21
- assert_equal(@p_one.s('br[last()]'), [@br_three])
27
+ assert_equal(@c2.s('..'), [@b2] )
22
28
 
23
- assert_equal(@p_one.s('a'), [])
29
+ assert_equal(@c2.s('.'), [@c2] )
30
+
31
+ assert_equal(@a.s('foo'), [])
24
32
  end
25
33
 
34
+ def test_s_axis
35
+ assert_equal(@c1.s('ancestor::*'), [@b1, @a])
36
+
37
+ assert_equal(@c1.s('ancestor-or-self::*'), [@c1, @b1, @a])
38
+
39
+ assert_equal(@a.s('child::*'), [@b1, @b2, @b3])
40
+
41
+ assert_equal(@a.s('descendant::*'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
42
+
43
+ assert_equal(@a.s('descendant-or-self::*'), [@a, @b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
44
+
45
+ assert_equal(@b2.s('following-sibling::*'), [@b3])
46
+
47
+ assert_equal(@b3.s('parent::*'), [@a])
48
+
49
+ assert_equal(@b2.s('preceding-sibling::*'), [@b1])
50
+
51
+ assert_equal(@a.s('self::*'), [@a])
52
+ end
53
+
54
+ def test_s_node_test
55
+ assert_equal(@a.s('//*'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi])
56
+
57
+ assert_equal(@a.s('//comment()'), [@comment])
58
+
59
+ assert_equal(@a.s('//node()'), [@b1, @b2, @b3, @c1, @c2, @c3, @comment, @pi, @text])
60
+
61
+ assert_equal(@a.s('//processing-instruction()'), [@pi])
62
+
63
+ assert_equal(@a.s('//text()'), [@text])
64
+
65
+ assert_equal(@a.s('b'), [@b1, @b2, @b3])
66
+ end
67
+
68
+ def test_s_attribute
69
+ assert_equal(@a.s('b[@class="1"]'), [@b1])
70
+
71
+ assert_equal(@a.s('//b[@type="text/css"]'), [@b3])
72
+ end
73
+
74
+ def test_s_position
75
+ assert_equal(@b2.s('c[2]'), [@c3])
76
+
77
+ assert_equal(@a.s('b[position()=1]'), [@b1])
78
+
79
+ assert_equal(@a.s('b[last()]'), [@b3])
80
+ end
81
+
26
82
  def test_sf
27
- assert_same(@p_one.sf('br'), @br_one)
28
- assert_nil(@p_one.sf('a'))
83
+ assert_same(@a.sf('b'), @b1)
84
+ assert_nil(@a.sf('foo'))
29
85
  end
30
86
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rind
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 3
10
- version: 0.1.3
9
+ - 4
10
+ version: 0.1.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Aaron Lasseigne
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-20 00:00:00 -05:00
18
+ date: 2010-06-26 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -25,8 +25,9 @@ executables: []
25
25
 
26
26
  extensions: []
27
27
 
28
- extra_rdoc_files: []
29
-
28
+ extra_rdoc_files:
29
+ - LICENSE
30
+ - CHANGELOG.rdoc
30
31
  files:
31
32
  - lib/rind/document.rb
32
33
  - lib/rind/html.rb