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 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: