From e2dab952d0cda20d4d2adcde2e7ccdfd8fbbdc54 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 9 Sep 2014 22:48:31 +0200 Subject: [PATCH] Added XML::Node#before and XML::Node#after These methods can be used to insert nodes before/after other nodes without manually having to mess around with node sets. This fixes #28. --- lib/oga/xml/node.rb | 22 ++++++++++++++++++ lib/oga/xml/node_set.rb | 14 ++++++++++++ spec/oga/xml/node_set_spec.rb | 43 +++++++++++++++++++++++++++++++++++ spec/oga/xml/node_spec.rb | 32 ++++++++++++++++++++++++++ 4 files changed, 111 insertions(+) diff --git a/lib/oga/xml/node.rb b/lib/oga/xml/node.rb index 1d6d76b..5ddfc90 100644 --- a/lib/oga/xml/node.rb +++ b/lib/oga/xml/node.rb @@ -142,6 +142,28 @@ module Oga return node_set.delete(self) if node_set end + ## + # Inserts the given node before the current node. + # + # @param [Oga::XML::Node] other + # + def before(other) + index = node_set.index(self) + + node_set.insert(index, other) + end + + ## + # Inserts the given node after the current node. + # + # @param [Oga::XML::Node] other + # + def after(other) + index = node_set.index(self) + 1 + + node_set.insert(index, other) + end + ## # @return [Symbol] # diff --git a/lib/oga/xml/node_set.rb b/lib/oga/xml/node_set.rb index b2d7f46..cead831 100644 --- a/lib/oga/xml/node_set.rb +++ b/lib/oga/xml/node_set.rb @@ -153,6 +153,20 @@ module Oga return node end + ## + # Inserts a node into the set at the given index. + # + # @param [Fixnum] index The index to insert the node at. + # @param [Oga::XML::Node] node + # + def insert(index, node) + return if @nodes.include?(node) + + @nodes.insert(index, node) + + take_ownership(node) + end + ## # Returns the node for the given index. # diff --git a/spec/oga/xml/node_set_spec.rb b/spec/oga/xml/node_set_spec.rb index 3204c3d..bc2de1e 100644 --- a/spec/oga/xml/node_set_spec.rb +++ b/spec/oga/xml/node_set_spec.rb @@ -196,6 +196,49 @@ describe Oga::XML::NodeSet do end end + context '#insert' do + before do + @set = described_class.new + @owned_set = described_class.new([], Oga::XML::Node.new) + end + + example 'insert a node into an empty node set' do + node = Oga::XML::Node.new + + @set.insert(0, node) + + @set[0].should == node + end + + example 'do not insert a node that is already in the set' do + node = Oga::XML::Node.new + + @set.insert(0, node) + @set.insert(0, node) + + @set.length.should == 1 + end + + example 'insert a node before another node' do + node1 = Oga::XML::Node.new + node2 = Oga::XML::Node.new + + @set.insert(0, node1) + @set.insert(0, node2) + + @set[0].should == node2 + @set[1].should == node1 + end + + example 'take ownership of a node when inserting into an owned set' do + node = Oga::XML::Node.new + + @owned_set.insert(0, node) + + node.node_set.should == @owned_set + end + end + context '#[]' do before do @n1 = Oga::XML::Element.new(:name => 'a') diff --git a/spec/oga/xml/node_spec.rb b/spec/oga/xml/node_spec.rb index f4a87fe..a568343 100644 --- a/spec/oga/xml/node_spec.rb +++ b/spec/oga/xml/node_spec.rb @@ -178,4 +178,36 @@ describe Oga::XML::Node do @n1.node_set.nil?.should == true end end + + context '#before' do + before do + @node = described_class.new + @container = described_class.new(:children => [@node]) + end + + example 'insert a node before another node' do + other = described_class.new + + @node.before(other) + + @container.children[0].should == other + @container.children[1].should == @node + end + end + + context '#after' do + before do + @node = described_class.new + @container = described_class.new(:children => [@node]) + end + + example 'insert a node after another node' do + other = described_class.new + + @node.after(other) + + @container.children[0].should == @node + @container.children[1].should == other + end + end end