hyp_diff 0.0.1 → 0.0.2
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/.yardopts +2 -0
- data/Gemfile +2 -0
- data/README.md +17 -3
- data/lib/{text_from_node.rb → hyp_diff/text_from_node.rb} +3 -0
- data/lib/hyp_diff/version.rb +1 -1
- data/lib/hyp_diff.rb +39 -17
- data/spec/hyp_diff_spec.rb +32 -0
- data/spec/text_from_node_spec.rb +4 -1
- metadata +14 -30
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7f4edc59168406b4b1194beb77ecde74bd4e2645
|
4
|
+
data.tar.gz: e89d6a3a2a7c55250d3d9183c6f2b6fcdbb16a80
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d0197e591ec496470791dd49b63bcb78f88fa44d9d86e42bca2ddf95633f9f6576094cb4173aa7d29c71088482e2544c16fbb4ab30e29009947a1f6330f6e2a5
|
7
|
+
data.tar.gz: ed945683196fe5997645ba09f38d16853c9d2acac68d72cf531d8590d8f42227ad3e8389c73d2e254b12ee58d9e6200e16aedd269f026d195323f51cf08cf07d
|
data/.yardopts
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,10 +4,24 @@ HypDiff compares HTML snippets. It generates a diff between two input snippets.
|
|
4
4
|
|
5
5
|
## Usage
|
6
6
|
|
7
|
+
# compare using the defaults: <ins> and <del> tags are inserted into the markup
|
7
8
|
HypDiff.compare("<p>byebye world</p>", "<p>hello world</p>")
|
8
|
-
# '<p><del>byebye</del><ins>hello</ins> world</p> '
|
9
|
-
|
10
|
-
|
9
|
+
# => '<p><del>byebye</del><ins>hello</ins> world</p> '
|
10
|
+
|
11
|
+
# use custom markup by providing callbacks for rendering insertions and deletions
|
12
|
+
HypDiff.compare("<p>byebye world</p>", "<p>hello world</p>",
|
13
|
+
render_insertion: proc { |html| "<span data-diff='ins'>#{html}</span>" },
|
14
|
+
render_deletion: proc { |html| "<span data-diff='del'>#{html}</span>" }
|
15
|
+
)
|
16
|
+
# '<p><span data-diff='del'>byebye</span><span data-diff='ins'>hello</span> world</p> '
|
17
|
+
|
18
|
+
# choose which markup should be the basis for the results:
|
19
|
+
HypDiff.compare("<div>byebye world</div>", "<p>hello world</p>", markup_from: "before")
|
20
|
+
# => '<div><del>byebye</del><ins>hello</ins> world</div> '
|
21
|
+
HypDiff.compare("<div>byebye world</div>", "<p>hello world</p>", markup_from: "after")
|
22
|
+
# => '<p><del>byebye</del><ins>hello</ins> world</p> '
|
23
|
+
|
24
|
+
For more examples, take a look at the [specs](https://github.com/krishan/hyp_diff/blob/master/spec/hyp_diff_spec.rb).
|
11
25
|
|
12
26
|
## Why another diff tool?
|
13
27
|
|
data/lib/hyp_diff/version.rb
CHANGED
data/lib/hyp_diff.rb
CHANGED
@@ -1,28 +1,49 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
require "diff-lcs"
|
3
3
|
|
4
|
-
require "text_from_node"
|
4
|
+
require "hyp_diff/text_from_node"
|
5
5
|
|
6
|
+
# @api public
|
6
7
|
module HypDiff; class << self
|
7
8
|
|
8
|
-
|
9
|
+
# Compare two html snippets.
|
10
|
+
# @param before [String] the first html snippet
|
11
|
+
# @param after [String] the second html snippet
|
12
|
+
# @option options [Proc] :render_insertion provide a callback to render insertions. The callback will receive the inserted text as a html snippet. It should return a new html snippet that will be used in the output. If no callback is given, `<ins>`-Tags will be used to highlight insertions.
|
13
|
+
# @option options [Proc] :render_deletion provide a callback to render deletions. The callback will receive the deleted text as a html snippet. It should return a new html snippet that will be used in the output. If no callback is given, `<del>`-Tags will be used to highlight deletions.
|
14
|
+
# @option options [String] :markup_from specify if the markup from `before` or `after` should be used as the basis for the output. Possible values: "before" and "after". Default: "after"
|
15
|
+
# @return [String] a new html snippet that highlights changes between `before` and `after`
|
16
|
+
# @api public
|
17
|
+
def compare(before, after, options = {})
|
9
18
|
parsed_after = parse(after)
|
10
19
|
parsed_before = parse(before)
|
11
20
|
|
12
21
|
text_changes = Diff::LCS.sdiff(extract_text(parsed_before), extract_text(parsed_after))
|
13
22
|
|
14
|
-
|
15
|
-
|
23
|
+
markup_from_before = options[:markup_from] == "before"
|
24
|
+
|
25
|
+
change_node_tuples = text_changes.map do |change|
|
26
|
+
text_from_node = markup_from_before ? change.old_element : change.new_element
|
27
|
+
[change, text_from_node && text_from_node.node]
|
28
|
+
end
|
29
|
+
|
30
|
+
render_deletion = options[:render_deletion] || proc { |html| "<del>#{html}</del>" }
|
31
|
+
render_insertion = options[:render_insertion] || proc { |html| "<ins>#{html}</ins>" }
|
32
|
+
|
33
|
+
NodeMap.for(change_node_tuples).each do |node, changes|
|
34
|
+
node.replace(ChangeRenderer.render(changes, render_deletion, render_insertion))
|
16
35
|
end
|
17
36
|
|
18
|
-
parsed_after
|
37
|
+
modified_fragment = markup_from_before ? parsed_before : parsed_after
|
38
|
+
modified_fragment.to_html
|
19
39
|
end
|
20
40
|
|
21
41
|
private
|
22
42
|
|
43
|
+
# @api private
|
23
44
|
class NodeMap
|
24
|
-
def self.for(
|
25
|
-
new.build(
|
45
|
+
def self.for(change_node_tuples, &block)
|
46
|
+
new.build(change_node_tuples).map
|
26
47
|
end
|
27
48
|
|
28
49
|
attr_reader :map
|
@@ -32,11 +53,9 @@ module HypDiff; class << self
|
|
32
53
|
@stashed = []
|
33
54
|
end
|
34
55
|
|
35
|
-
def build(
|
36
|
-
|
37
|
-
if
|
38
|
-
node = change.new_element.node
|
39
|
-
|
56
|
+
def build(change_node_tuples)
|
57
|
+
change_node_tuples.each do |change, node|
|
58
|
+
if node
|
40
59
|
if @stashed.length > 0
|
41
60
|
@stashed.each do |stashed_change|
|
42
61
|
append_to_node(node, stashed_change)
|
@@ -65,13 +84,16 @@ module HypDiff; class << self
|
|
65
84
|
end
|
66
85
|
end
|
67
86
|
|
87
|
+
# @api private
|
68
88
|
class ChangeRenderer
|
69
|
-
def self.render(changes)
|
70
|
-
renderer = new.render(changes).rendered_text
|
89
|
+
def self.render(changes, render_deletion, render_insertion)
|
90
|
+
renderer = new(render_deletion, render_insertion).render(changes).rendered_text
|
71
91
|
end
|
72
92
|
|
73
|
-
def initialize
|
93
|
+
def initialize(render_deletion, render_insertion)
|
74
94
|
@new_text = []
|
95
|
+
@render_deletion = render_deletion
|
96
|
+
@render_insertion = render_insertion
|
75
97
|
end
|
76
98
|
|
77
99
|
def render(changes)
|
@@ -121,11 +143,11 @@ module HypDiff; class << self
|
|
121
143
|
end
|
122
144
|
|
123
145
|
def insertion_tag(text)
|
124
|
-
|
146
|
+
@render_insertion.call(text)
|
125
147
|
end
|
126
148
|
|
127
149
|
def deletion_tag(text)
|
128
|
-
|
150
|
+
@render_deletion.call(text)
|
129
151
|
end
|
130
152
|
|
131
153
|
end
|
data/spec/hyp_diff_spec.rb
CHANGED
@@ -66,6 +66,38 @@ describe HypDiff do
|
|
66
66
|
)
|
67
67
|
end
|
68
68
|
|
69
|
+
describe "with callbacks for custom markup" do
|
70
|
+
it "uses them to generate the insertions and deletions" do
|
71
|
+
HypDiff.compare(
|
72
|
+
"byebye world",
|
73
|
+
"hello world",
|
74
|
+
render_insertion: proc { |html| "<new>#{html}</new>" },
|
75
|
+
render_deletion: proc { |html| "<old>#{html}</old>" }
|
76
|
+
).should ==
|
77
|
+
"<old>byebye</old><new>hello</new> world"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "choosing which markup to use" do
|
82
|
+
it "allows to choose 'after'" do
|
83
|
+
HypDiff.compare(
|
84
|
+
"<b>byebye world</b>",
|
85
|
+
"<i>hello world</i>",
|
86
|
+
markup_from: "after"
|
87
|
+
).should ==
|
88
|
+
"<i><del>byebye</del><ins>hello</ins> world</i>"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "allows to choose 'before'" do
|
92
|
+
HypDiff.compare(
|
93
|
+
"<b>byebye world</b>",
|
94
|
+
"<i>hello world</i>",
|
95
|
+
markup_from: "before"
|
96
|
+
).should ==
|
97
|
+
"<b><del>byebye</del><ins>hello</ins> world</b>"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
69
101
|
describe "handling whitespace" do
|
70
102
|
it "treats consecutive whitespace as a single whitespace" do
|
71
103
|
expect_diff("hello world", "hello world", "hello world")
|
data/spec/text_from_node_spec.rb
CHANGED
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyp_diff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Kristian Hanekamp
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-18 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: nokogiri
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: diff-lcs
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: bundler
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -62,7 +55,6 @@ dependencies:
|
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: rspec
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
59
|
- - ~>
|
68
60
|
- !ruby/object:Gem::Version
|
@@ -70,7 +62,6 @@ dependencies:
|
|
70
62
|
type: :development
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
66
|
- - ~>
|
76
67
|
- !ruby/object:Gem::Version
|
@@ -78,7 +69,6 @@ dependencies:
|
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: rake
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
73
|
- - ~>
|
84
74
|
- !ruby/object:Gem::Version
|
@@ -86,15 +76,14 @@ dependencies:
|
|
86
76
|
type: :development
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
80
|
- - ~>
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '10.1'
|
94
|
-
description:
|
95
|
-
|
96
|
-
|
97
|
-
|
83
|
+
description: "\nHypDiff compares HTML snippets. It generates a diff between two input
|
84
|
+
snippets. The diff is a new HTML snippet that highlights textual changes. The tag
|
85
|
+
structure and formatting of the input snippets is preserved. The generated diff
|
86
|
+
snippet is valid, well-formed HTML and suitable for presentation inside a WYSIWYG
|
98
87
|
environment.\n "
|
99
88
|
email:
|
100
89
|
- kris.hanekamp@gmail.com
|
@@ -103,49 +92,44 @@ extensions: []
|
|
103
92
|
extra_rdoc_files: []
|
104
93
|
files:
|
105
94
|
- .gitignore
|
95
|
+
- .yardopts
|
106
96
|
- Gemfile
|
107
97
|
- LICENSE.txt
|
108
98
|
- README.md
|
109
99
|
- Rakefile
|
110
100
|
- hyp_diff.gemspec
|
111
101
|
- lib/hyp_diff.rb
|
102
|
+
- lib/hyp_diff/text_from_node.rb
|
112
103
|
- lib/hyp_diff/version.rb
|
113
|
-
- lib/text_from_node.rb
|
114
104
|
- spec/hyp_diff_spec.rb
|
115
105
|
- spec/spec_helper.rb
|
116
106
|
- spec/text_from_node_spec.rb
|
117
107
|
homepage: https://github.com/krishan/hyp_diff
|
118
108
|
licenses:
|
119
109
|
- MIT
|
110
|
+
metadata: {}
|
120
111
|
post_install_message:
|
121
112
|
rdoc_options: []
|
122
113
|
require_paths:
|
123
114
|
- lib
|
124
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
-
none: false
|
126
116
|
requirements:
|
127
|
-
- -
|
117
|
+
- - '>='
|
128
118
|
- !ruby/object:Gem::Version
|
129
119
|
version: '0'
|
130
|
-
segments:
|
131
|
-
- 0
|
132
|
-
hash: 4061769782701953502
|
133
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
-
none: false
|
135
121
|
requirements:
|
136
|
-
- -
|
122
|
+
- - '>='
|
137
123
|
- !ruby/object:Gem::Version
|
138
124
|
version: '0'
|
139
|
-
segments:
|
140
|
-
- 0
|
141
|
-
hash: 4061769782701953502
|
142
125
|
requirements: []
|
143
126
|
rubyforge_project:
|
144
|
-
rubygems_version:
|
127
|
+
rubygems_version: 2.0.14
|
145
128
|
signing_key:
|
146
|
-
specification_version:
|
129
|
+
specification_version: 4
|
147
130
|
summary: HypDiff compares html snippets
|
148
131
|
test_files:
|
149
132
|
- spec/hyp_diff_spec.rb
|
150
133
|
- spec/spec_helper.rb
|
151
134
|
- spec/text_from_node_spec.rb
|
135
|
+
has_rdoc:
|