hyp_diff 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,2 @@
1
+ --non-transitive-tag api
2
+ --api public
data/Gemfile CHANGED
@@ -3,3 +3,5 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem "pry"
6
+ gem "yard"
7
+ gem "redcarpet"
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
- For more examples, take a look at the [specs](spec/hyp_diff_spec.rb).
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
 
@@ -1,3 +1,5 @@
1
+ module HypDiff
2
+
1
3
  class TextFromNode
2
4
  def initialize(raw_text, node)
3
5
  @text = raw_text.strip == "" ? " " : raw_text
@@ -29,3 +31,4 @@ class TextFromNode
29
31
  end
30
32
  end
31
33
 
34
+ end
@@ -1,3 +1,3 @@
1
1
  module HypDiff
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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
- def compare(before, after)
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
- NodeMap.for(text_changes).each do |node, changes|
15
- node.replace(ChangeRenderer.render(changes))
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.to_html
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(changes)
25
- new.build(changes).map
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(changes)
36
- changes.each do |change|
37
- if change.new_element
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
- "<ins>#{text}</ins>"
146
+ @render_insertion.call(text)
125
147
  end
126
148
 
127
149
  def deletion_tag(text)
128
- "<del>#{text}</del>"
150
+ @render_deletion.call(text)
129
151
  end
130
152
 
131
153
  end
@@ -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")
@@ -1,4 +1,6 @@
1
- require "text_from_node"
1
+ require "hyp_diff/text_from_node"
2
+
3
+ module HypDiff
2
4
 
3
5
  describe TextFromNode do
4
6
 
@@ -24,3 +26,4 @@ describe TextFromNode do
24
26
 
25
27
  end
26
28
 
29
+ end
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.1
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-04 00:00:00.000000000 Z
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: ! "\nHypDiff compares HTML snippets. It generates a diff between two
95
- input snippets. The diff is a new HTML snippet that highlights textual changes.
96
- The tag structure and formatting of the input snippets is preserved. The generated
97
- diff snippet is valid, well-formed HTML and suitable for presentation inside a WYSIWYG
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: 1.8.23
127
+ rubygems_version: 2.0.14
145
128
  signing_key:
146
- specification_version: 3
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: