nokogiri-diff 0.1.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +28 -0
- data/.gitignore +4 -2
- data/ChangeLog.md +15 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +1 -1
- data/README.md +39 -32
- data/Rakefile +6 -32
- data/gemspec.yml +10 -5
- data/lib/nokogiri/diff/version.rb +3 -1
- data/lib/nokogiri/diff/xml/document.rb +5 -3
- data/lib/nokogiri/diff/xml/node.rb +9 -7
- data/lib/nokogiri/diff/xml.rb +4 -2
- data/lib/nokogiri/diff.rb +4 -2
- data/nokogiri-diff.gemspec +1 -4
- data/spec/diff_spec.rb +131 -120
- data/spec/spec_helper.rb +2 -1
- metadata +28 -74
- data/.gemtest +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4374cae69c49465afb2391000bc4c57c0f30db34155afe50c463cf54a86fe719
|
4
|
+
data.tar.gz: eb6e14af7ddca3cf72555d83f8f608cd90310d532c18bd6645afedd3bf3d8437
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d67440441d4581bf0ab7a59dc9ce7ab34fbc3c8078a36f305ee91b3835d808c9cdd7221c5e080fcd6dd7552f61698cb72b7a2df9d0bc1208ddfdc4b46ef7d364
|
7
|
+
data.tar.gz: 995fe16d4e4299b02f4d34a3a1c6a4061ae8f727343e64d5692c9fdeca89bd128d9eb8fa40ff934178580326c35fe63a07ed8fa5dc61458330c4dfe22cc1bd92
|
@@ -0,0 +1,28 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on: [ push, pull_request ]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
tests:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
strategy:
|
9
|
+
fail-fast: false
|
10
|
+
matrix:
|
11
|
+
ruby:
|
12
|
+
- '3.0'
|
13
|
+
- '3.1'
|
14
|
+
- '3.2'
|
15
|
+
- '3.3'
|
16
|
+
- jruby
|
17
|
+
- truffleruby
|
18
|
+
name: Ruby ${{ matrix.ruby }}
|
19
|
+
steps:
|
20
|
+
- uses: actions/checkout@v4
|
21
|
+
- name: Set up Ruby
|
22
|
+
uses: ruby/setup-ruby@v1
|
23
|
+
with:
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
25
|
+
- name: Install dependencies
|
26
|
+
run: bundle install --jobs 4 --retry 3
|
27
|
+
- name: Run tests
|
28
|
+
run: bundle exec rake test
|
data/.gitignore
CHANGED
data/ChangeLog.md
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
### 0.3.0 / 2024-01-24
|
2
|
+
|
3
|
+
* Require [ruby](http://www.ruby-lang.org/) >= 2.0.0.
|
4
|
+
* Require [tdiff](http://github.com/postmodern/tdiff) ~> 0.4.
|
5
|
+
* Switched to using `require_relative` to improve load-times.
|
6
|
+
* Added `# frozen_string_literal: true` to all files.
|
7
|
+
|
8
|
+
### 0.2.0 / 2013-04-22
|
9
|
+
|
10
|
+
* {Nokogiri::XML::Node#tdiff_each_child} now sorts attributes by name, so that
|
11
|
+
changes in attribute order is ignored. (thanks @bhollis)
|
12
|
+
* {Nokogiri::XML::Node#tdiff_equal} now supports `Nokogiri::XML::Comment`
|
13
|
+
and `Nokogiri::XML::ProcessingInstruction` objects. (thanks @bhollis)
|
14
|
+
|
1
15
|
### 0.1.2 / 2012-05-28
|
2
16
|
|
3
17
|
* Require tdiff ~> 0.3, >= 0.3.2.
|
18
|
+
* Added {Nokogiri::Diff::VERSION}.
|
4
19
|
* Replaced ore-tasks with
|
5
20
|
[rubygems-tasks](https://github.com/postmodern/rubygems-tasks#readme).
|
6
21
|
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem 'rake'
|
7
|
+
gem 'rubygems-tasks', '~> 0.2'
|
8
|
+
|
9
|
+
gem 'rspec', '~> 3.0'
|
10
|
+
gem 'simplecov', '~> 0.20', require: false
|
11
|
+
|
12
|
+
gem 'kramdown'
|
13
|
+
gem 'redcarpet', platform: :mri
|
14
|
+
gem 'yard', '~> 0.9'
|
15
|
+
end
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# nokogiri-diff
|
2
2
|
|
3
|
+
[](https://github.com/postmodern/nokogiri-diff/actions/workflows/ruby.yml)
|
4
|
+
|
3
5
|
* [Source](https://github.com/postmodern/nokogiri-diff)
|
4
6
|
* [Issues](https://github.com/postmodern/nokogiri-diff/issues)
|
5
7
|
* [Documentation](http://rubydoc.info/gems/nokogiri-diff/frames)
|
6
|
-
* [Email](mailto:postmodern.mod3 at gmail.com)
|
7
8
|
|
8
9
|
## Description
|
9
10
|
|
@@ -19,56 +20,62 @@ removed nodes) between two XML/HTML documents.
|
|
19
20
|
|
20
21
|
## Examples
|
21
22
|
|
22
|
-
Enumerate over the
|
23
|
+
Enumerate over the differences between two HTML documents:
|
23
24
|
|
24
|
-
|
25
|
+
```ruby
|
26
|
+
require 'nokogiri/diff'
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
+
doc1 = Nokogiri::HTML('<div><p>one</p> two </div>')
|
29
|
+
doc2 = Nokogiri::HTML('<div><p id="1">one</p> <p>three</p></div>')
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
doc1.diff(doc2) do |change,node|
|
32
|
+
puts "#{change} #{node.to_html}".ljust(30) + node.parent.path
|
33
|
+
end
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
# <div>
|
36
|
+
# <p>one</p> two </div> /
|
37
|
+
# <p>one</p> /div
|
38
|
+
# - two /div
|
39
|
+
# + /div
|
40
|
+
# + <p>three</p> /div
|
41
|
+
# + id="1" /div/p[1]
|
42
|
+
# one /div/p
|
43
|
+
```
|
41
44
|
|
42
45
|
Only find the added nodes:
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
```ruby
|
48
|
+
doc1.diff(doc2, :added => true) do |change,node|
|
49
|
+
puts node.to_html.ljust(30) + node.parent.path
|
50
|
+
end
|
47
51
|
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
# /div
|
53
|
+
# <p>three</p> /div
|
54
|
+
# id="1" /div/p[1]
|
55
|
+
```
|
51
56
|
|
52
57
|
Only find the removed nodes:
|
53
58
|
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
```ruby
|
60
|
+
doc1.diff(doc2, :removed => true) do |change,node|
|
61
|
+
puts node.to_html.ljust(30) + node.parent.path
|
62
|
+
end
|
57
63
|
|
58
|
-
|
64
|
+
# two /div
|
65
|
+
```
|
59
66
|
|
60
67
|
## Requirements
|
61
68
|
|
62
|
-
* [ruby](http://www.ruby-lang.org/) >=
|
63
|
-
* [tdiff](http://github.com/postmodern/tdiff) ~> 0.
|
69
|
+
* [ruby](http://www.ruby-lang.org/) >= 2.0.0
|
70
|
+
* [tdiff](http://github.com/postmodern/tdiff) ~> 0.4
|
64
71
|
* [nokogiri](http://nokogiri.rubyforge.org/) ~> 1.5
|
65
72
|
|
66
73
|
## Install
|
67
74
|
|
68
|
-
|
69
|
-
|
70
|
-
|
75
|
+
```shell
|
76
|
+
$ gem install nokogiri-diff
|
77
|
+
```
|
71
78
|
|
72
|
-
|
79
|
+
## License
|
73
80
|
|
74
81
|
See {file:LICENSE.txt} for details.
|
data/Rakefile
CHANGED
@@ -1,36 +1,10 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
1
|
+
require 'rubygems/tasks'
|
2
|
+
Gem::Tasks.new
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
require 'rubygems/tasks'
|
7
|
-
|
8
|
-
Gem::Tasks.new
|
9
|
-
rescue LoadError => e
|
10
|
-
warn e.message
|
11
|
-
warn "Run `gem install rubygems-tasks` to install 'rubygems/tasks'."
|
12
|
-
end
|
13
|
-
|
14
|
-
begin
|
15
|
-
gem 'rspec', '~> 2.4'
|
16
|
-
require 'rspec/core/rake_task'
|
17
|
-
|
18
|
-
RSpec::Core::RakeTask.new
|
19
|
-
rescue LoadError => e
|
20
|
-
task :spec do
|
21
|
-
abort "Please run `gem install rspec` to install RSpec."
|
22
|
-
end
|
23
|
-
end
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
RSpec::Core::RakeTask.new
|
24
6
|
task :test => :spec
|
25
7
|
task :default => :spec
|
26
8
|
|
27
|
-
|
28
|
-
|
29
|
-
require 'yard'
|
30
|
-
|
31
|
-
YARD::Rake::YardocTask.new
|
32
|
-
rescue LoadError => e
|
33
|
-
task :yard do
|
34
|
-
abort "Please run `gem install yard` to install YARD."
|
35
|
-
end
|
36
|
-
end
|
9
|
+
require 'yard'
|
10
|
+
YARD::Rake::YardocTask.new
|
data/gemspec.yml
CHANGED
@@ -10,13 +10,18 @@ email: postmodern.mod3@gmail.com
|
|
10
10
|
homepage: https://github.com/postmodern/nokogiri-diff#readme
|
11
11
|
has_yard: true
|
12
12
|
|
13
|
-
|
13
|
+
metadata:
|
14
|
+
documentation_uri: https://rubydoc.info/gems/nokogiri-diff
|
15
|
+
source_code_uri: https://github.com/postmodern/nokogiri-diff
|
16
|
+
bug_tracker_uri: https://github.com/postmodern/nokogiri-diff/issues
|
17
|
+
changelog_uri: https://github.com/postmodern/nokogiri-diff/blob/main/ChangeLog.md
|
18
|
+
rubygems_mfa_required: 'true'
|
19
|
+
|
20
|
+
required_ruby_version: ">= 2.0.0"
|
14
21
|
|
15
22
|
dependencies:
|
16
|
-
tdiff: ~> 0.
|
23
|
+
tdiff: ~> 0.4
|
17
24
|
nokogiri: ~> 1.5
|
18
25
|
|
19
26
|
development_dependencies:
|
20
|
-
|
21
|
-
rspec: ~> 2.4
|
22
|
-
yard: ~> 0.7
|
27
|
+
bundler: ~> 2.0
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'node'
|
2
4
|
|
3
5
|
class Nokogiri::XML::Document < Nokogiri::XML::Node
|
4
6
|
|
@@ -6,7 +8,7 @@ class Nokogiri::XML::Document < Nokogiri::XML::Node
|
|
6
8
|
# Overrides `tdiff` to only compare the child nodes of the document.
|
7
9
|
#
|
8
10
|
def tdiff(tree,&block)
|
9
|
-
return enum_for(
|
11
|
+
return enum_for(__method__,tree) unless block
|
10
12
|
|
11
13
|
tdiff_recursive(tree,&block)
|
12
14
|
return self
|
@@ -16,7 +18,7 @@ class Nokogiri::XML::Document < Nokogiri::XML::Node
|
|
16
18
|
# Overrides `tdiff_unordered` to only compare the child nodes of the document.
|
17
19
|
#
|
18
20
|
def tdiff_unordered(tree,&block)
|
19
|
-
return enum_for(
|
21
|
+
return enum_for(__method__,tree) unless block
|
20
22
|
|
21
23
|
tdiff_recursive_unordered(tree,&block)
|
22
24
|
return self
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
require 'tdiff'
|
3
5
|
|
@@ -22,8 +24,10 @@ class Nokogiri::XML::Node
|
|
22
24
|
(self.name == node.name && self.value == node.value)
|
23
25
|
when Nokogiri::XML::Element, Nokogiri::XML::DTD
|
24
26
|
self.name == node.name
|
25
|
-
when Nokogiri::XML::Text
|
27
|
+
when Nokogiri::XML::Text, Nokogiri::XML::Comment
|
26
28
|
self.text == node.text
|
29
|
+
when Nokogiri::XML::ProcessingInstruction
|
30
|
+
(self.name == node.name && self.content == node.content)
|
27
31
|
else
|
28
32
|
false
|
29
33
|
end
|
@@ -46,7 +50,7 @@ class Nokogiri::XML::Node
|
|
46
50
|
#
|
47
51
|
def tdiff_each_child(node,&block)
|
48
52
|
if node.kind_of?(Nokogiri::XML::Element)
|
49
|
-
node.attribute_nodes.each(&block)
|
53
|
+
node.attribute_nodes.sort_by(&:name).each(&block)
|
50
54
|
end
|
51
55
|
|
52
56
|
node.children.each(&block)
|
@@ -80,14 +84,12 @@ class Nokogiri::XML::Node
|
|
80
84
|
# If no block was given, an Enumerator object will be returned.
|
81
85
|
#
|
82
86
|
def diff(other,options={},&block)
|
83
|
-
return enum_for(
|
87
|
+
return enum_for(__method__,other,options) unless block
|
84
88
|
|
85
89
|
if (options[:added] || options[:removed])
|
86
90
|
tdiff_unordered(other) do |change,node|
|
87
|
-
if
|
88
|
-
|
89
|
-
elsif (change == '-' && options[:removed])
|
90
|
-
yield change, node
|
91
|
+
if (change == '+' && options[:added]) then yield change, node
|
92
|
+
elsif (change == '-' && options[:removed]) then yield change, node
|
91
93
|
end
|
92
94
|
end
|
93
95
|
else
|
data/lib/nokogiri/diff/xml.rb
CHANGED
data/lib/nokogiri/diff.rb
CHANGED
data/nokogiri-diff.gemspec
CHANGED
@@ -7,10 +7,7 @@ Gem::Specification.new do |gem|
|
|
7
7
|
|
8
8
|
gem.name = gemspec.fetch('name')
|
9
9
|
gem.version = gemspec.fetch('version') do
|
10
|
-
|
11
|
-
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
|
-
|
13
|
-
require 'nokogiri/diff/version'
|
10
|
+
require_relative 'lib/nokogiri/diff/version'
|
14
11
|
Nokogiri::Diff::VERSION
|
15
12
|
end
|
16
13
|
|
data/spec/diff_spec.rb
CHANGED
@@ -3,253 +3,264 @@ require 'nokogiri/diff'
|
|
3
3
|
|
4
4
|
describe "nokogiri/diff" do
|
5
5
|
let(:contents) { '<div><p>one</p></div>' }
|
6
|
-
let(:doc)
|
6
|
+
let(:doc) { Nokogiri::XML(contents) }
|
7
7
|
|
8
|
-
let(:added_text)
|
8
|
+
let(:added_text) { Nokogiri::XML('<div><p>one</p>two</div>') }
|
9
9
|
let(:added_element) { Nokogiri::XML('<div><p>one</p><p>two</p></div>') }
|
10
|
-
let(:added_attr)
|
10
|
+
let(:added_attr) { Nokogiri::XML('<div><p id="1">one</p></div>') }
|
11
|
+
let(:added_attrs) { Nokogiri::XML('<div><p id="1" class="2">one</p></div>') }
|
11
12
|
|
12
|
-
let(:changed_text)
|
13
|
-
let(:changed_element)
|
14
|
-
let(:changed_attr_name)
|
13
|
+
let(:changed_text) { Nokogiri::XML('<div><p>two</p></div>') }
|
14
|
+
let(:changed_element) { Nokogiri::XML('<div><span>one</span></div>') }
|
15
|
+
let(:changed_attr_name) { Nokogiri::XML('<div><p i="1">one</p></div>') }
|
15
16
|
let(:changed_attr_value) { Nokogiri::XML('<div><p id="2">one</p></div>') }
|
17
|
+
let(:changed_attr_order) { Nokogiri::XML('<div><p class="2" id="1">one</p></div>') }
|
16
18
|
|
17
|
-
let(:removed_text)
|
19
|
+
let(:removed_text) { Nokogiri::XML('<div><p></p>two</div>') }
|
18
20
|
let(:removed_element) { Nokogiri::XML('<div></div>') }
|
19
|
-
let(:removed_attr)
|
21
|
+
let(:removed_attr) { Nokogiri::XML('<div><p>one</p></div>') }
|
20
22
|
|
21
23
|
it "should add #diff to Nokogiri::XML::Docuemnt" do
|
22
|
-
doc.
|
24
|
+
expect(doc).to respond_to(:diff)
|
23
25
|
end
|
24
26
|
|
25
27
|
it "should add #diff to Nokogiri::XML::Element" do
|
26
|
-
added_element.at('div').
|
28
|
+
expect(added_element.at('div')).to respond_to(:diff)
|
27
29
|
end
|
28
30
|
|
29
31
|
it "should add #diff to Nokogiri::XML::Text" do
|
30
|
-
added_text.at('p/text()').
|
32
|
+
expect(added_text.at('p/text()')).to respond_to(:diff)
|
31
33
|
end
|
32
34
|
|
33
35
|
it "should add #diff to Nokogiri::XML::Attr" do
|
34
|
-
added_attr.at('p/@id').
|
36
|
+
expect(added_attr.at('p/@id')).to respond_to(:diff)
|
35
37
|
end
|
36
38
|
|
37
39
|
it "should not compare the Document objects" do
|
38
40
|
change = doc.diff(doc).first
|
39
41
|
|
40
|
-
change[0].
|
41
|
-
change[1].
|
42
|
+
expect(change[0]).to eq(' ')
|
43
|
+
expect(change[1]).to eq(doc.root)
|
42
44
|
end
|
43
45
|
|
44
46
|
it "should determine when two different documents are identical" do
|
45
|
-
doc.diff(Nokogiri::XML(contents)).all? { |change,node|
|
47
|
+
expect(doc.diff(Nokogiri::XML(contents)).all? { |change,node|
|
46
48
|
change == ' '
|
47
|
-
}.
|
49
|
+
}).to eq(true)
|
48
50
|
end
|
49
51
|
|
50
52
|
it "should search down within Nokogiri::XML::Document objects" do
|
51
|
-
doc.diff(changed_text).any? { |change,node|
|
53
|
+
expect(doc.diff(changed_text).any? { |change,node|
|
52
54
|
change != ' '
|
53
|
-
}.
|
55
|
+
}).to eq(true)
|
54
56
|
end
|
55
57
|
|
56
58
|
it "should determine when text nodes are added" do
|
57
59
|
changes = doc.at('div').diff(added_text.at('div')).to_a
|
58
60
|
|
59
|
-
changes.length.
|
61
|
+
expect(changes.length).to eq(4)
|
60
62
|
|
61
|
-
changes[0][0].
|
62
|
-
changes[0][1].
|
63
|
+
expect(changes[0][0]).to eq(' ')
|
64
|
+
expect(changes[0][1]).to eq(doc.at('div'))
|
63
65
|
|
64
|
-
changes[1][0].
|
65
|
-
changes[1][1].
|
66
|
+
expect(changes[1][0]).to eq(' ')
|
67
|
+
expect(changes[1][1]).to eq(doc.at('//p'))
|
66
68
|
|
67
|
-
changes[2][0].
|
68
|
-
changes[2][1].
|
69
|
+
expect(changes[2][0]).to eq('+')
|
70
|
+
expect(changes[2][1]).to eq(added_text.at('//div/text()'))
|
69
71
|
|
70
|
-
changes[3][0].
|
71
|
-
changes[3][1].
|
72
|
+
expect(changes[3][0]).to eq(' ')
|
73
|
+
expect(changes[3][1]).to eq(doc.at('//p/text()'))
|
72
74
|
end
|
73
75
|
|
74
76
|
it "should determine when elements are added" do
|
75
77
|
changes = doc.at('div').diff(added_element.at('div')).to_a
|
76
78
|
|
77
|
-
changes.length.
|
79
|
+
expect(changes.length).to eq(5)
|
78
80
|
|
79
|
-
changes[0][0].
|
80
|
-
changes[0][1].
|
81
|
+
expect(changes[0][0]).to eq(' ')
|
82
|
+
expect(changes[0][1]).to eq(doc.at('div'))
|
81
83
|
|
82
|
-
changes[1][0].
|
83
|
-
changes[1][1].
|
84
|
+
expect(changes[1][0]).to eq('+')
|
85
|
+
expect(changes[1][1]).to eq(added_element.at('//p[1]'))
|
84
86
|
|
85
|
-
changes[2][0].
|
86
|
-
changes[2][1].
|
87
|
+
expect(changes[2][0]).to eq(' ')
|
88
|
+
expect(changes[2][1]).to eq(doc.at('//p'))
|
87
89
|
|
88
|
-
changes[3][0].
|
89
|
-
changes[3][1].
|
90
|
+
expect(changes[3][0]).to eq('-')
|
91
|
+
expect(changes[3][1]).to eq(doc.at('//p/text()'))
|
90
92
|
|
91
|
-
changes[4][0].
|
92
|
-
changes[4][1].
|
93
|
+
expect(changes[4][0]).to eq('+')
|
94
|
+
expect(changes[4][1]).to eq(added_element.at('//p[2]/text()'))
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should ignore when attribute order changes" do
|
98
|
+
changes = added_attrs.at('p').diff(changed_attr_order.at('p')).to_a
|
99
|
+
|
100
|
+
expect(changes.all? { |change| change[0] == ' ' }).to be_truthy
|
93
101
|
end
|
94
102
|
|
95
103
|
it "should determine when attributes are added" do
|
96
104
|
changes = doc.at('p').diff(added_attr.at('p')).to_a
|
97
105
|
|
98
|
-
changes.length.
|
106
|
+
expect(changes.length).to eq(3)
|
99
107
|
|
100
|
-
changes[0][0].
|
101
|
-
changes[0][1].
|
108
|
+
expect(changes[0][0]).to eq(' ')
|
109
|
+
expect(changes[0][1]).to eq(doc.at('p'))
|
102
110
|
|
103
|
-
changes[1][0].
|
104
|
-
changes[1][1].
|
111
|
+
expect(changes[1][0]).to eq('+')
|
112
|
+
expect(changes[1][1]).to eq(added_attr.at('//p/@id'))
|
105
113
|
|
106
|
-
changes[2][0].
|
107
|
-
changes[2][1].
|
114
|
+
expect(changes[2][0]).to eq(' ')
|
115
|
+
expect(changes[2][1]).to eq(doc.at('//p/text()'))
|
108
116
|
end
|
109
117
|
|
110
118
|
it "should determine when text nodes differ" do
|
111
119
|
changes = doc.at('p').diff(changed_text.at('p')).to_a
|
112
120
|
|
113
|
-
changes.length.
|
121
|
+
expect(changes.length).to eq(3)
|
114
122
|
|
115
|
-
changes[0][0].
|
116
|
-
changes[0][1].
|
123
|
+
expect(changes[0][0]).to eq(' ')
|
124
|
+
expect(changes[0][1]).to eq(doc.at('p'))
|
117
125
|
|
118
|
-
changes[1][0].
|
119
|
-
changes[1][1].
|
126
|
+
expect(changes[1][0]).to eq('-')
|
127
|
+
expect(changes[1][1]).to eq(doc.at('//p/text()'))
|
120
128
|
|
121
|
-
changes[2][0].
|
122
|
-
changes[2][1].
|
129
|
+
expect(changes[2][0]).to eq('+')
|
130
|
+
expect(changes[2][1]).to eq(changed_text.at('//p/text()'))
|
123
131
|
end
|
124
132
|
|
125
133
|
it "should determine when element names differ" do
|
126
134
|
changes = doc.at('div').diff(changed_element.at('div')).to_a
|
127
135
|
|
128
|
-
changes.length.
|
136
|
+
expect(changes.length).to eq(3)
|
129
137
|
|
130
|
-
changes[0][0].
|
131
|
-
changes[0][1].
|
138
|
+
expect(changes[0][0]).to eq(' ')
|
139
|
+
expect(changes[0][1]).to eq(doc.at('div'))
|
132
140
|
|
133
|
-
changes[1][0].
|
134
|
-
changes[1][1].
|
141
|
+
expect(changes[1][0]).to eq('-')
|
142
|
+
expect(changes[1][1]).to eq(doc.at('p'))
|
135
143
|
|
136
|
-
changes[2][0].
|
137
|
-
changes[2][1].
|
144
|
+
expect(changes[2][0]).to eq('+')
|
145
|
+
expect(changes[2][1]).to eq(changed_element.at('span'))
|
138
146
|
end
|
139
147
|
|
140
148
|
it "should determine when attribute names differ" do
|
141
149
|
changes = added_attr.at('p').diff(changed_attr_name.at('p')).to_a
|
142
150
|
|
143
|
-
changes.length.
|
151
|
+
expect(changes.length).to eq(4)
|
144
152
|
|
145
|
-
changes[0][0].
|
146
|
-
changes[0][1].
|
153
|
+
expect(changes[0][0]).to eq(' ')
|
154
|
+
expect(changes[0][1]).to eq(added_attr.at('p'))
|
147
155
|
|
148
|
-
changes[1][0].
|
149
|
-
changes[1][1].
|
156
|
+
expect(changes[1][0]).to eq('-')
|
157
|
+
expect(changes[1][1]).to eq(added_attr.at('//p/@id'))
|
150
158
|
|
151
|
-
changes[2][0].
|
152
|
-
changes[2][1].
|
159
|
+
expect(changes[2][0]).to eq('+')
|
160
|
+
expect(changes[2][1]).to eq(changed_attr_name.at('//p/@i'))
|
153
161
|
|
154
|
-
changes[3][0].
|
155
|
-
changes[3][1].
|
162
|
+
expect(changes[3][0]).to eq(' ')
|
163
|
+
expect(changes[3][1]).to eq(added_attr.at('//p/text()'))
|
156
164
|
end
|
157
165
|
|
158
166
|
it "should determine when attribute values differ" do
|
159
167
|
changes = added_attr.at('p').diff(changed_attr_value.at('p')).to_a
|
160
168
|
|
161
|
-
changes.length.
|
169
|
+
expect(changes.length).to eq(4)
|
162
170
|
|
163
|
-
changes[0][0].
|
164
|
-
changes[0][1].
|
171
|
+
expect(changes[0][0]).to eq(' ')
|
172
|
+
expect(changes[0][1]).to eq(added_attr.at('p'))
|
165
173
|
|
166
|
-
changes[1][0].
|
167
|
-
changes[1][1].
|
174
|
+
expect(changes[1][0]).to eq('-')
|
175
|
+
expect(changes[1][1]).to eq(added_attr.at('//p/@id'))
|
168
176
|
|
169
|
-
changes[2][0].
|
170
|
-
changes[2][1].
|
177
|
+
expect(changes[2][0]).to eq('+')
|
178
|
+
expect(changes[2][1]).to eq(changed_attr_value.at('//p/@id'))
|
171
179
|
|
172
|
-
changes[3][0].
|
173
|
-
changes[3][1].
|
180
|
+
expect(changes[3][0]).to eq(' ')
|
181
|
+
expect(changes[3][1]).to eq(added_attr.at('//p/text()'))
|
174
182
|
end
|
175
183
|
|
176
184
|
it "should determine when text nodes are removed" do
|
177
185
|
changes = added_text.at('div').diff(removed_text.at('div')).to_a
|
178
186
|
|
179
|
-
changes.length.
|
187
|
+
expect(changes.length).to eq(4)
|
180
188
|
|
181
|
-
changes[0][0].
|
182
|
-
changes[0][1].
|
189
|
+
expect(changes[0][0]).to eq(' ')
|
190
|
+
expect(changes[0][1]).to eq(added_text.at('div'))
|
183
191
|
|
184
|
-
changes[1][0].
|
185
|
-
changes[1][1].
|
192
|
+
expect(changes[1][0]).to eq(' ')
|
193
|
+
expect(changes[1][1]).to eq(added_text.at('p'))
|
186
194
|
|
187
|
-
changes[2][0].
|
188
|
-
changes[2][1].
|
195
|
+
expect(changes[2][0]).to eq(' ')
|
196
|
+
expect(changes[2][1]).to eq(added_text.at('//div/text()'))
|
189
197
|
|
190
|
-
changes[3][0].
|
191
|
-
changes[3][1].
|
198
|
+
expect(changes[3][0]).to eq('-')
|
199
|
+
expect(changes[3][1]).to eq(added_text.at('//p/text()'))
|
192
200
|
end
|
193
201
|
|
194
202
|
it "should determine when elements are removed" do
|
195
203
|
changes = added_element.at('div').diff(removed_element.at('div')).to_a
|
196
204
|
|
197
|
-
changes.length.
|
205
|
+
expect(changes.length).to eq(3)
|
198
206
|
|
199
|
-
changes[0][0].
|
200
|
-
changes[0][1].
|
207
|
+
expect(changes[0][0]).to eq(' ')
|
208
|
+
expect(changes[0][1]).to eq(added_element.at('div'))
|
201
209
|
|
202
|
-
changes[1][0].
|
203
|
-
changes[1][1].
|
210
|
+
expect(changes[1][0]).to eq('-')
|
211
|
+
expect(changes[1][1]).to eq(added_element.at('//p[1]'))
|
212
|
+
|
213
|
+
expect(changes[2][0]).to eq('-')
|
214
|
+
expect(changes[2][1]).to eq(added_element.at('//p[2]'))
|
215
|
+
end
|
204
216
|
|
205
|
-
|
206
|
-
changes[2][1].should == added_element.at('//p[2]')
|
217
|
+
it "should ignore when attributes change order" do
|
207
218
|
end
|
208
219
|
|
209
220
|
it "should determine when attributes are removed" do
|
210
221
|
changes = added_attr.at('div').diff(removed_attr.at('div')).to_a
|
211
222
|
|
212
|
-
changes.length.
|
223
|
+
expect(changes.length).to eq(4)
|
213
224
|
|
214
|
-
changes[0][0].
|
215
|
-
changes[0][1].
|
225
|
+
expect(changes[0][0]).to eq(' ')
|
226
|
+
expect(changes[0][1]).to eq(added_attr.at('div'))
|
216
227
|
|
217
|
-
changes[1][0].
|
218
|
-
changes[1][1].
|
228
|
+
expect(changes[1][0]).to eq(' ')
|
229
|
+
expect(changes[1][1]).to eq(added_attr.at('p'))
|
219
230
|
|
220
|
-
changes[2][0].
|
221
|
-
changes[2][1].
|
231
|
+
expect(changes[2][0]).to eq('-')
|
232
|
+
expect(changes[2][1]).to eq(added_attr.at('//p/@id'))
|
222
233
|
|
223
|
-
changes[3][0].
|
224
|
-
changes[3][1].
|
234
|
+
expect(changes[3][0]).to eq(' ')
|
235
|
+
expect(changes[3][1]).to eq(added_attr.at('//p/text()'))
|
225
236
|
end
|
226
237
|
|
227
238
|
context ":added" do
|
228
239
|
it "should determine only when text nodes are added" do
|
229
240
|
changes = doc.at('div').diff(added_text.at('div'), :added => true).to_a
|
230
241
|
|
231
|
-
changes.length.
|
242
|
+
expect(changes.length).to eq(1)
|
232
243
|
|
233
|
-
changes[0][0].
|
234
|
-
changes[0][1].
|
244
|
+
expect(changes[0][0]).to eq('+')
|
245
|
+
expect(changes[0][1]).to eq(added_text.at('//div/text()'))
|
235
246
|
end
|
236
247
|
|
237
248
|
it "should determine only when elements are added" do
|
238
249
|
changes = doc.at('div').diff(added_element.at('div'), :added => true).to_a
|
239
250
|
|
240
|
-
changes.length.
|
251
|
+
expect(changes.length).to eq(1)
|
241
252
|
|
242
|
-
changes[0][0].
|
243
|
-
changes[0][1].
|
253
|
+
expect(changes[0][0]).to eq('+')
|
254
|
+
expect(changes[0][1]).to eq(added_element.at('//div/p[2]'))
|
244
255
|
end
|
245
256
|
|
246
257
|
it "should determine only when attributes are added" do
|
247
258
|
changes = doc.at('div').diff(added_attr.at('div'), :added => true).to_a
|
248
259
|
|
249
|
-
changes.length.
|
260
|
+
expect(changes.length).to eq(1)
|
250
261
|
|
251
|
-
changes[0][0].
|
252
|
-
changes[0][1].
|
262
|
+
expect(changes[0][0]).to eq('+')
|
263
|
+
expect(changes[0][1]).to eq(added_attr.at('//p/@id'))
|
253
264
|
end
|
254
265
|
end
|
255
266
|
|
@@ -257,28 +268,28 @@ describe "nokogiri/diff" do
|
|
257
268
|
it "should determine only when text nodes are removed" do
|
258
269
|
changes = doc.at('div').diff(removed_text.at('div'), :removed => true).to_a
|
259
270
|
|
260
|
-
changes.length.
|
271
|
+
expect(changes.length).to eq(1)
|
261
272
|
|
262
|
-
changes[0][0].
|
263
|
-
changes[0][1].
|
273
|
+
expect(changes[0][0]).to eq('-')
|
274
|
+
expect(changes[0][1]).to eq(doc.at('//p/text()'))
|
264
275
|
end
|
265
276
|
|
266
277
|
it "should determine only when elements are removed" do
|
267
278
|
changes = doc.at('div').diff(removed_element.at('div'), :removed => true).to_a
|
268
279
|
|
269
|
-
changes.length.
|
280
|
+
expect(changes.length).to eq(1)
|
270
281
|
|
271
|
-
changes[0][0].
|
272
|
-
changes[0][1].
|
282
|
+
expect(changes[0][0]).to eq('-')
|
283
|
+
expect(changes[0][1]).to eq(doc.at('//div/p'))
|
273
284
|
end
|
274
285
|
|
275
286
|
it "should determine only when attributes are removed" do
|
276
287
|
changes = added_attr.at('div').diff(removed_attr.at('div'), :removed => true).to_a
|
277
288
|
|
278
|
-
changes.length.
|
289
|
+
expect(changes.length).to eq(1)
|
279
290
|
|
280
|
-
changes[0][0].
|
281
|
-
changes[0][1].
|
291
|
+
expect(changes[0][0]).to eq('-')
|
292
|
+
expect(changes[0][1]).to eq(added_attr.at('//p/@id'))
|
282
293
|
end
|
283
294
|
end
|
284
295
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,102 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nokogiri-diff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Postmodern
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2024-01-25 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: tdiff
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- - ~>
|
17
|
+
- - "~>"
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '0.
|
22
|
-
- - ! '>='
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: 0.3.2
|
19
|
+
version: '0.4'
|
25
20
|
type: :runtime
|
26
21
|
prerelease: false
|
27
22
|
version_requirements: !ruby/object:Gem::Requirement
|
28
|
-
none: false
|
29
23
|
requirements:
|
30
|
-
- - ~>
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '0.3'
|
33
|
-
- - ! '>='
|
24
|
+
- - "~>"
|
34
25
|
- !ruby/object:Gem::Version
|
35
|
-
version: 0.
|
26
|
+
version: '0.4'
|
36
27
|
- !ruby/object:Gem::Dependency
|
37
28
|
name: nokogiri
|
38
29
|
requirement: !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
30
|
requirements:
|
41
|
-
- - ~>
|
31
|
+
- - "~>"
|
42
32
|
- !ruby/object:Gem::Version
|
43
33
|
version: '1.5'
|
44
34
|
type: :runtime
|
45
35
|
prerelease: false
|
46
36
|
version_requirements: !ruby/object:Gem::Requirement
|
47
|
-
none: false
|
48
37
|
requirements:
|
49
|
-
- - ~>
|
38
|
+
- - "~>"
|
50
39
|
- !ruby/object:Gem::Version
|
51
40
|
version: '1.5'
|
52
41
|
- !ruby/object:Gem::Dependency
|
53
|
-
name:
|
54
|
-
requirement: !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
|
-
requirements:
|
57
|
-
- - ~>
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
version: '0.1'
|
60
|
-
type: :development
|
61
|
-
prerelease: false
|
62
|
-
version_requirements: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
|
-
requirements:
|
65
|
-
- - ~>
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: '0.1'
|
68
|
-
- !ruby/object:Gem::Dependency
|
69
|
-
name: rspec
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
71
|
-
none: false
|
72
|
-
requirements:
|
73
|
-
- - ~>
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '2.4'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
|
-
requirements:
|
81
|
-
- - ~>
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: '2.4'
|
84
|
-
- !ruby/object:Gem::Dependency
|
85
|
-
name: yard
|
42
|
+
name: bundler
|
86
43
|
requirement: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
44
|
requirements:
|
89
|
-
- - ~>
|
45
|
+
- - "~>"
|
90
46
|
- !ruby/object:Gem::Version
|
91
|
-
version: '0
|
47
|
+
version: '2.0'
|
92
48
|
type: :development
|
93
49
|
prerelease: false
|
94
50
|
version_requirements: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
51
|
requirements:
|
97
|
-
- - ~>
|
52
|
+
- - "~>"
|
98
53
|
- !ruby/object:Gem::Version
|
99
|
-
version: '0
|
54
|
+
version: '2.0'
|
100
55
|
description: Nokogiri::Diff adds the ability to calculate the differences (added or
|
101
56
|
removed nodes) between two XML/HTML documents.
|
102
57
|
email: postmodern.mod3@gmail.com
|
@@ -107,12 +62,13 @@ extra_rdoc_files:
|
|
107
62
|
- LICENSE.txt
|
108
63
|
- README.md
|
109
64
|
files:
|
110
|
-
- .document
|
111
|
-
- .
|
112
|
-
- .gitignore
|
113
|
-
- .rspec
|
114
|
-
- .yardopts
|
65
|
+
- ".document"
|
66
|
+
- ".github/workflows/ruby.yml"
|
67
|
+
- ".gitignore"
|
68
|
+
- ".rspec"
|
69
|
+
- ".yardopts"
|
115
70
|
- ChangeLog.md
|
71
|
+
- Gemfile
|
116
72
|
- LICENSE.txt
|
117
73
|
- README.md
|
118
74
|
- Rakefile
|
@@ -128,26 +84,24 @@ files:
|
|
128
84
|
homepage: https://github.com/postmodern/nokogiri-diff#readme
|
129
85
|
licenses:
|
130
86
|
- MIT
|
131
|
-
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
132
89
|
rdoc_options: []
|
133
90
|
require_paths:
|
134
91
|
- lib
|
135
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
136
|
-
none: false
|
137
93
|
requirements:
|
138
|
-
- -
|
94
|
+
- - ">="
|
139
95
|
- !ruby/object:Gem::Version
|
140
|
-
version:
|
96
|
+
version: 2.0.0
|
141
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
142
|
-
none: false
|
143
98
|
requirements:
|
144
|
-
- -
|
99
|
+
- - ">="
|
145
100
|
- !ruby/object:Gem::Version
|
146
101
|
version: '0'
|
147
102
|
requirements: []
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
specification_version: 3
|
103
|
+
rubygems_version: 3.4.10
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
152
106
|
summary: Calculate the differences between two XML/HTML documents.
|
153
107
|
test_files: []
|
data/.gemtest
DELETED
File without changes
|