ydiffy 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/.gitignore +5 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CHANGELOG +40 -0
- data/CONTRIBUTORS +13 -0
- data/Gemfile +7 -0
- data/LICENSE +19 -0
- data/README.md +334 -0
- data/Rakefile +11 -0
- data/lib/diffy.rb +13 -0
- data/lib/diffy/css.rb +34 -0
- data/lib/diffy/diff.rb +171 -0
- data/lib/diffy/format.rb +37 -0
- data/lib/diffy/html_formatter.rb +135 -0
- data/lib/diffy/split_diff.rb +49 -0
- data/lib/diffy/version.rb +3 -0
- data/spec/demo_app.rb +46 -0
- data/spec/diffy_spec.rb +676 -0
- data/ydiffy.gemspec +23 -0
- metadata +93 -0
data/spec/demo_app.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'json'
|
4
|
+
require File.dirname(__FILE__) + '/../lib/diffy'
|
5
|
+
|
6
|
+
blk = proc do
|
7
|
+
Diffy::Diff.default_options.merge! JSON.parse(params[:options]) rescue {}
|
8
|
+
haml "- d = Diffy::Diff.new(params[:one].to_s, params[:two].to_s)\n%div= d.to_s(:html)\n%pre= d.to_s"
|
9
|
+
end
|
10
|
+
post '/', &blk
|
11
|
+
get '/', &blk
|
12
|
+
__END__
|
13
|
+
|
14
|
+
@@ layout
|
15
|
+
%html
|
16
|
+
%head
|
17
|
+
:css
|
18
|
+
.diff{overflow:auto;}
|
19
|
+
.diff ul{background:#fff;overflow:auto;font-size:13px;list-style:none;margin:0;padding:0;display:table;width:100%;}
|
20
|
+
.diff del, .diff ins{display:block;text-decoration:none;}
|
21
|
+
.diff li{padding:0; display:table-row;margin: 0;height:1em;}
|
22
|
+
.diff li.ins{background:#dfd; color:#080}
|
23
|
+
.diff li.del{background:#fee; color:#b00}
|
24
|
+
.diff li:hover{background:#ffc}
|
25
|
+
.diff del, .diff ins, .diff span{white-space:pre-wrap;font-family:courier;}
|
26
|
+
.diff del strong{font-weight:normal;background:#fcc;}
|
27
|
+
.diff ins strong{font-weight:normal;background:#9f9;}
|
28
|
+
.diff li.diff-comment { display: none; }
|
29
|
+
.diff li.diff-block-info { background: none repeat scroll 0 0 gray; }
|
30
|
+
%body
|
31
|
+
= yield
|
32
|
+
%form{:action => '', :method => 'post'}
|
33
|
+
%label JSON diff options
|
34
|
+
%textarea{:name => 'options', :style => 'width:100%;height:250px;'}= params[:options]
|
35
|
+
%label One
|
36
|
+
%textarea{:name => 'one', :style => 'width:100%;height:250px;'}= params[:one]
|
37
|
+
%br/
|
38
|
+
%label Two
|
39
|
+
%textarea{:name => 'two', :style => 'width:100%;height:250px;'}= params[:two]
|
40
|
+
%br/
|
41
|
+
%input{:type => 'submit'}
|
42
|
+
%br/
|
43
|
+
|
44
|
+
@@ index
|
45
|
+
%div.title Hello world!!!!!
|
46
|
+
|
data/spec/diffy_spec.rb
ADDED
@@ -0,0 +1,676 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'diffy'))
|
3
|
+
|
4
|
+
class Diffy::Diff
|
5
|
+
attr_reader :tempfiles
|
6
|
+
end
|
7
|
+
describe Diffy::Diff do
|
8
|
+
|
9
|
+
describe "diffing two files" do
|
10
|
+
def tempfile(string, fn = 'diffy-spec')
|
11
|
+
t = Tempfile.new(fn)
|
12
|
+
# ensure tempfiles aren't unlinked when GC runs by maintaining a
|
13
|
+
# reference to them.
|
14
|
+
@tempfiles ||=[]
|
15
|
+
@tempfiles.push(t)
|
16
|
+
t.print(string)
|
17
|
+
t.flush
|
18
|
+
t.close
|
19
|
+
t.path
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should accept file paths as arguments" do
|
23
|
+
string1 = "foo\nbar\nbang\n"
|
24
|
+
string2 = "foo\nbang\n"
|
25
|
+
path1, path2 = tempfile(string1), tempfile(string2)
|
26
|
+
expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF
|
27
|
+
foo
|
28
|
+
-bar
|
29
|
+
bang
|
30
|
+
DIFF
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should accept file paths with spaces as arguments" do
|
34
|
+
string1 = "foo\nbar\nbang\n"
|
35
|
+
string2 = "foo\nbang\n"
|
36
|
+
path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces')
|
37
|
+
expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF
|
38
|
+
foo
|
39
|
+
-bar
|
40
|
+
bang
|
41
|
+
DIFF
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have and empty tempfiles variable after calling diff" do
|
45
|
+
string1 = "foo\nbar\nbang\n"
|
46
|
+
string2 = "foo\nbang\n"
|
47
|
+
path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces')
|
48
|
+
res = Diffy::Diff.new(path1, path2, :source => 'strings')
|
49
|
+
expect(res.tempfiles).to eq nil
|
50
|
+
res.diff
|
51
|
+
expect(res.tempfiles).to eq []
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should accept file paths with spaces as arguments on windows" do
|
55
|
+
begin
|
56
|
+
|
57
|
+
orig_verbose, $VERBOSE = $VERBOSE, nil #silence redefine constant warnings
|
58
|
+
orig_windows, Diffy::WINDOWS = Diffy::WINDOWS, true
|
59
|
+
string1 = "foo\nbar\nbang\n"
|
60
|
+
string2 = "foo\nbang\n"
|
61
|
+
path1, path2 = tempfile(string1, 'path with spaces'), tempfile(string2, 'path with spaces')
|
62
|
+
expect(Diffy::Diff.new(path1, path2, :source => 'files').to_s).to eq <<-DIFF
|
63
|
+
foo
|
64
|
+
-bar
|
65
|
+
bang
|
66
|
+
DIFF
|
67
|
+
ensure
|
68
|
+
Diffy::WINDOWS, $VERBOSE = orig_windows, orig_verbose
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "with no line different" do
|
74
|
+
before do
|
75
|
+
string1 = "foo\nbar\nbang\n"
|
76
|
+
string2 = "foo\nbar\nbang\n"
|
77
|
+
@path1, @path2 = tempfile(string1), tempfile(string2)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should show everything" do
|
81
|
+
expect(Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => false).
|
82
|
+
to_s).to eq <<-DIFF
|
83
|
+
foo
|
84
|
+
bar
|
85
|
+
bang
|
86
|
+
DIFF
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should not show everything if the :allow_empty_diff option is set" do
|
90
|
+
expect(Diffy::Diff.new(@path1, @path2, :source => 'files', :allow_empty_diff => true).to_s).to eq('')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
describe "with lines that start with backslashes" do
|
94
|
+
before do
|
95
|
+
string1 = "foo\n\\\\bag\nbang\n"
|
96
|
+
string2 = "foo\n\\\\bar\nbang\n"
|
97
|
+
@path1, @path2 = tempfile(string1), tempfile(string2)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should not leave lines out" do
|
101
|
+
expect(Diffy::Diff.new(@path1, @path2, :source => 'files').to_s).to eq <<-DIFF
|
102
|
+
foo
|
103
|
+
-\\\\bag
|
104
|
+
+\\\\bar
|
105
|
+
bang
|
106
|
+
DIFF
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "with non valid UTF bytes" do
|
111
|
+
before do
|
112
|
+
string1 = "Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n"
|
113
|
+
string2 = "Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000\n"
|
114
|
+
@path1, @path2 = tempfile(string1), tempfile(string2)
|
115
|
+
end
|
116
|
+
it "should not raise invalid encoding issues" do
|
117
|
+
desired = <<-DIFF
|
118
|
+
-Foo ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000
|
119
|
+
+Bar ICS95095010000000000083320000BS01030000004100+\xFF00000000000000000
|
120
|
+
DIFF
|
121
|
+
desired.force_encoding("ASCII-8BIT") if desired.respond_to?(:force_encoding)
|
122
|
+
expect(Diffy::Diff.new(@path1, @path2, :source => 'files').to_s).to eq(desired)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "handling temp files" do
|
129
|
+
it "should unlink tempfiles after generating the diff" do
|
130
|
+
before_tmpfiles = Dir.entries(Dir.tmpdir)
|
131
|
+
::Diffy::Diff.new("a", "b").to_s
|
132
|
+
after_tmpfiles = Dir.entries(Dir.tmpdir)
|
133
|
+
expect(before_tmpfiles).to match_array(after_tmpfiles)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should still be able to generate multiple diffs" do
|
137
|
+
d = ::Diffy::Diff.new("a", "b")
|
138
|
+
expect(d.to_s).to be_a String
|
139
|
+
expect(d.to_s(:html)).to be_a String
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "options[:context]" do
|
144
|
+
it "should limit context lines to 1" do
|
145
|
+
diff = Diffy::Diff.new("foo\nfoo\nBAR\nbang\nbaz", "foo\nfoo\nbar\nbang\nbaz", :context => 1)
|
146
|
+
expect(diff.to_s).to eq <<-DIFF
|
147
|
+
foo
|
148
|
+
-BAR
|
149
|
+
+bar
|
150
|
+
bang
|
151
|
+
DIFF
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "options[:include_plus_and_minus_in_html]" do
|
156
|
+
it "defaults to false" do
|
157
|
+
@diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n")
|
158
|
+
expect(@diffy.options[:include_plus_and_minus_in_html]).to eq(false)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "can be set to true" do
|
162
|
+
@diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_plus_and_minus_in_html=> true )
|
163
|
+
expect(@diffy.options[:include_plus_and_minus_in_html]).to eq(true)
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "formats" do
|
167
|
+
it "includes symbols in html_simple" do
|
168
|
+
output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_plus_and_minus_in_html => true ).
|
169
|
+
to_s(:html_simple)
|
170
|
+
expect(output).to eq <<-HTML
|
171
|
+
<div class="diff">
|
172
|
+
<ul>
|
173
|
+
<li class="unchanged"><span><span class="symbol"> </span>foo</span></li>
|
174
|
+
<li class="del"><del><span class="symbol">-</span>bar</del></li>
|
175
|
+
<li class="unchanged"><span><span class="symbol"> </span>bang</span></li>
|
176
|
+
</ul>
|
177
|
+
</div>
|
178
|
+
HTML
|
179
|
+
end
|
180
|
+
|
181
|
+
it "includes symbols in html" do
|
182
|
+
output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\naba\nbang\n", :include_plus_and_minus_in_html => true ).
|
183
|
+
to_s(:html)
|
184
|
+
expect(output).to eq <<-HTML
|
185
|
+
<div class="diff">
|
186
|
+
<ul>
|
187
|
+
<li class="unchanged"><span><span class="symbol"> </span>foo</span></li>
|
188
|
+
<li class="del"><del><span class="symbol">-</span>ba<strong>r</strong></del></li>
|
189
|
+
<li class="ins"><ins><span class="symbol">+</span><strong>a</strong>ba</ins></li>
|
190
|
+
<li class="unchanged"><span><span class="symbol"> </span>bang</span></li>
|
191
|
+
</ul>
|
192
|
+
</div>
|
193
|
+
HTML
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "options[:include_diff_info]" do
|
201
|
+
it "defaults to false" do
|
202
|
+
@diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n")
|
203
|
+
expect(@diffy.options[:include_diff_info]).to eq(false)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "can be set to true" do
|
207
|
+
@diffy = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :include_diff_info => true )
|
208
|
+
expect(@diffy.options[:include_diff_info]).to eq(true)
|
209
|
+
end
|
210
|
+
|
211
|
+
it "includes all diff output" do
|
212
|
+
output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s
|
213
|
+
expect(output.to_s).to match( /@@/)
|
214
|
+
expect(output).to match( /---/)
|
215
|
+
expect(output).to match( /\+\+\+/)
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "formats" do
|
219
|
+
it "works for :color" do
|
220
|
+
output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:color)
|
221
|
+
expect(output).to match( /\e\[0m\n\e\[36m\@\@/ )
|
222
|
+
expect(output.to_s).to match( /\e\[90m---/)
|
223
|
+
expect(output.to_s).to match( /\e\[0m\n\e\[90m\+\+\+/)
|
224
|
+
end
|
225
|
+
|
226
|
+
it "works for :html_simple" do
|
227
|
+
output = Diffy::Diff.new("foo\nbar\nbang\n", "foo\nbang\n", :include_diff_info => true ).to_s(:html_simple)
|
228
|
+
expect(output.split("\n")).to include( " <li class=\"diff-block-info\"><span>@@ -1,3 +1,2 @@</span></li>" )
|
229
|
+
expect(output).to include( "<li class=\"diff-comment\"><span>---")
|
230
|
+
expect(output).to include( "<li class=\"diff-comment\"><span>+++")
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
describe "options[:diff]" do
|
236
|
+
it "should accept an option to diff" do
|
237
|
+
@diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbar\n", :diff => "-w", :allow_empty_diff => false)
|
238
|
+
expect(@diff.to_s).to eq <<-DIFF
|
239
|
+
foo
|
240
|
+
bar
|
241
|
+
DIFF
|
242
|
+
end
|
243
|
+
|
244
|
+
it "should accept multiple arguments to diff" do
|
245
|
+
@diff = Diffy::Diff.new(" foo\nbar\n", "foo\nbaz\n", :diff => ["-w", "-U 3"])
|
246
|
+
expect(@diff.to_s).to eq <<-DIFF
|
247
|
+
foo
|
248
|
+
-bar
|
249
|
+
+baz
|
250
|
+
DIFF
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "#to_s" do
|
255
|
+
describe "with no line different" do
|
256
|
+
before do
|
257
|
+
@string1 = "foo\nbar\nbang\n"
|
258
|
+
@string2 = "foo\nbar\nbang\n"
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should show everything" do
|
262
|
+
expect(Diffy::Diff.new(@string1, @string2, :allow_empty_diff => false).to_s).to eq <<-DIFF
|
263
|
+
foo
|
264
|
+
bar
|
265
|
+
bang
|
266
|
+
DIFF
|
267
|
+
end
|
268
|
+
end
|
269
|
+
describe "with one line different" do
|
270
|
+
before do
|
271
|
+
@string1 = "foo\nbar\nbang\n"
|
272
|
+
@string2 = "foo\nbang\n"
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should show one line removed" do
|
276
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF
|
277
|
+
foo
|
278
|
+
-bar
|
279
|
+
bang
|
280
|
+
DIFF
|
281
|
+
end
|
282
|
+
|
283
|
+
it "to_s should accept a format key" do
|
284
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s(:color)).
|
285
|
+
to eq(" foo\n\e[31m-bar\e[0m\n bang\n")
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should accept a default format option" do
|
289
|
+
old_format = Diffy::Diff.default_format
|
290
|
+
Diffy::Diff.default_format = :color
|
291
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s).
|
292
|
+
to eq(" foo\n\e[31m-bar\e[0m\n bang\n")
|
293
|
+
Diffy::Diff.default_format = old_format
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should accept a default options" do
|
297
|
+
old_options = Diffy::Diff.default_options
|
298
|
+
Diffy::Diff.default_options = old_options.merge(:include_diff_info => true)
|
299
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s).
|
300
|
+
to include('@@ -1,3 +1,2 @@')
|
301
|
+
Diffy::Diff.default_options = old_options
|
302
|
+
end
|
303
|
+
|
304
|
+
it "should show one line added" do
|
305
|
+
expect(Diffy::Diff.new(@string2, @string1).to_s).
|
306
|
+
to eq <<-DIFF
|
307
|
+
foo
|
308
|
+
+bar
|
309
|
+
bang
|
310
|
+
DIFF
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
describe "with one line changed" do
|
315
|
+
before do
|
316
|
+
@string1 = "foo\nbar\nbang\n"
|
317
|
+
@string2 = "foo\nbong\nbang\n"
|
318
|
+
end
|
319
|
+
it "should show one line added and one removed" do
|
320
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF
|
321
|
+
foo
|
322
|
+
-bar
|
323
|
+
+bong
|
324
|
+
bang
|
325
|
+
DIFF
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
describe "with totally different strings" do
|
330
|
+
before do
|
331
|
+
@string1 = "foo\nbar\nbang\n"
|
332
|
+
@string2 = "one\ntwo\nthree\n"
|
333
|
+
end
|
334
|
+
it "should show one line added and one removed" do
|
335
|
+
expect(Diffy::Diff.new(@string1, @string2).to_s).to eq <<-DIFF
|
336
|
+
-foo
|
337
|
+
-bar
|
338
|
+
-bang
|
339
|
+
+one
|
340
|
+
+two
|
341
|
+
+three
|
342
|
+
DIFF
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
describe "with a somewhat complicated diff" do
|
347
|
+
before do
|
348
|
+
@string1 = "foo\nbar\nbang\nwoot\n"
|
349
|
+
@string2 = "one\ntwo\nthree\nbar\nbang\nbaz\n"
|
350
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
351
|
+
end
|
352
|
+
it "should show one line added and one removed" do
|
353
|
+
expect(@diff.to_s).to eq <<-DIFF
|
354
|
+
-foo
|
355
|
+
+one
|
356
|
+
+two
|
357
|
+
+three
|
358
|
+
bar
|
359
|
+
bang
|
360
|
+
-woot
|
361
|
+
+baz
|
362
|
+
DIFF
|
363
|
+
end
|
364
|
+
|
365
|
+
it "should make an awesome simple html diff" do
|
366
|
+
expect(@diff.to_s(:html_simple)).to eq <<-HTML
|
367
|
+
<div class="diff">
|
368
|
+
<ul>
|
369
|
+
<li class="del"><del>foo</del></li>
|
370
|
+
<li class="ins"><ins>one</ins></li>
|
371
|
+
<li class="ins"><ins>two</ins></li>
|
372
|
+
<li class="ins"><ins>three</ins></li>
|
373
|
+
<li class="unchanged"><span>bar</span></li>
|
374
|
+
<li class="unchanged"><span>bang</span></li>
|
375
|
+
<li class="del"><del>woot</del></li>
|
376
|
+
<li class="ins"><ins>baz</ins></li>
|
377
|
+
</ul>
|
378
|
+
</div>
|
379
|
+
HTML
|
380
|
+
end
|
381
|
+
|
382
|
+
it "should accept overrides to diff's options" do
|
383
|
+
@diff = Diffy::Diff.new(@string1, @string2, :diff => "--rcs")
|
384
|
+
expect(@diff.to_s).to eq <<-DIFF
|
385
|
+
d1 1
|
386
|
+
a1 3
|
387
|
+
one
|
388
|
+
two
|
389
|
+
three
|
390
|
+
d4 1
|
391
|
+
a4 1
|
392
|
+
baz
|
393
|
+
DIFF
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
describe "html" do
|
398
|
+
it "should not allow html injection on the last line" do
|
399
|
+
@string1 = "hahaha\ntime flies like an arrow\nfoo bar\nbang baz\n<script>\n"
|
400
|
+
@string2 = "hahaha\nfruit flies like a banana\nbang baz\n<script>\n"
|
401
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
402
|
+
html = <<-HTML
|
403
|
+
<div class="diff">
|
404
|
+
<ul>
|
405
|
+
<li class="unchanged"><span>hahaha</span></li>
|
406
|
+
<li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
|
407
|
+
<li class="del"><del><strong>foo bar</strong></del></li>
|
408
|
+
<li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
|
409
|
+
<li class="unchanged"><span>bang baz</span></li>
|
410
|
+
<li class="unchanged"><span><script></span></li>
|
411
|
+
</ul>
|
412
|
+
</div>
|
413
|
+
HTML
|
414
|
+
expect(@diff.to_s(:html)).to eq(html)
|
415
|
+
end
|
416
|
+
|
417
|
+
it "should highlight the changes within the line" do
|
418
|
+
@string1 = "hahaha\ntime flies like an arrow\nfoo bar\nbang baz\n"
|
419
|
+
@string2 = "hahaha\nfruit flies like a banana\nbang baz\n"
|
420
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
421
|
+
html = <<-HTML
|
422
|
+
<div class="diff">
|
423
|
+
<ul>
|
424
|
+
<li class="unchanged"><span>hahaha</span></li>
|
425
|
+
<li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
|
426
|
+
<li class="del"><del><strong>foo bar</strong></del></li>
|
427
|
+
<li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
|
428
|
+
<li class="unchanged"><span>bang baz</span></li>
|
429
|
+
</ul>
|
430
|
+
</div>
|
431
|
+
HTML
|
432
|
+
expect(@diff.to_s(:html)).to eq(html)
|
433
|
+
end
|
434
|
+
|
435
|
+
it "should not duplicate some lines" do
|
436
|
+
@string1 = "hahaha\ntime flies like an arrow\n"
|
437
|
+
@string2 = "hahaha\nfruit flies like a banana\nbang baz"
|
438
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
439
|
+
html = <<-HTML
|
440
|
+
<div class="diff">
|
441
|
+
<ul>
|
442
|
+
<li class="unchanged"><span>hahaha</span></li>
|
443
|
+
<li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
|
444
|
+
<li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
|
445
|
+
<li class="ins"><ins><strong>bang baz</strong></ins></li>
|
446
|
+
</ul>
|
447
|
+
</div>
|
448
|
+
HTML
|
449
|
+
expect(@diff.to_s(:html)).to eq(html)
|
450
|
+
end
|
451
|
+
|
452
|
+
it "should escape html" do
|
453
|
+
@string1 = "ha<br>haha\ntime flies like an arrow\n"
|
454
|
+
@string2 = "ha<br>haha\nfruit flies like a banana\nbang baz"
|
455
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
456
|
+
html = <<-HTML
|
457
|
+
<div class="diff">
|
458
|
+
<ul>
|
459
|
+
<li class="unchanged"><span>ha<br>haha</span></li>
|
460
|
+
<li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
|
461
|
+
<li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
|
462
|
+
<li class="ins"><ins><strong>bang baz</strong></ins></li>
|
463
|
+
</ul>
|
464
|
+
</div>
|
465
|
+
HTML
|
466
|
+
expect(@diff.to_s(:html)).to eq(html)
|
467
|
+
end
|
468
|
+
|
469
|
+
it "should not double escape html in wierd edge cases" do
|
470
|
+
@string1 = "preface = (! title .)+ title &{YYACCEPT}\n"
|
471
|
+
@string2 = "preface = << (! title .)+ title >> &{YYACCEPT}\n"
|
472
|
+
@diff = Diffy::Diff.new @string1, @string2
|
473
|
+
html = <<-HTML
|
474
|
+
<div class="diff">
|
475
|
+
<ul>
|
476
|
+
<li class="del"><del>preface = (! title .)+ title &{YYACCEPT}</del></li>
|
477
|
+
<li class="ins"><ins>preface = <strong><< </strong>(! title .)+ title <strong>>> </strong>&{YYACCEPT}</ins></li>
|
478
|
+
</ul>
|
479
|
+
</div>
|
480
|
+
HTML
|
481
|
+
expect(@diff.to_s(:html)).to eq(html)
|
482
|
+
end
|
483
|
+
|
484
|
+
it "should highlight the changes within the line with windows style line breaks" do
|
485
|
+
@string1 = "hahaha\r\ntime flies like an arrow\r\nfoo bar\r\nbang baz\n"
|
486
|
+
@string2 = "hahaha\r\nfruit flies like a banana\r\nbang baz\n"
|
487
|
+
@diff = Diffy::Diff.new(@string1, @string2)
|
488
|
+
html = <<-HTML
|
489
|
+
<div class="diff">
|
490
|
+
<ul>
|
491
|
+
<li class="unchanged"><span>hahaha</span></li>
|
492
|
+
<li class="del"><del><strong>time</strong> flies like a<strong>n arrow</strong></del></li>
|
493
|
+
<li class="del"><del><strong>foo bar</strong></del></li>
|
494
|
+
<li class="ins"><ins><strong>fruit</strong> flies like a<strong> banana</strong></ins></li>
|
495
|
+
<li class="unchanged"><span>bang baz</span></li>
|
496
|
+
</ul>
|
497
|
+
</div>
|
498
|
+
HTML
|
499
|
+
expect(@diff.to_s(:html)).to eq(html)
|
500
|
+
end
|
501
|
+
|
502
|
+
it "should treat unix vs windows newlines as differences" do
|
503
|
+
@diff = Diffy::Diff.new("one\ntwo\nthree\n", "one\r\ntwo\r\nthree\r\n")
|
504
|
+
html = <<-HTML
|
505
|
+
<div class="diff">
|
506
|
+
<ul>
|
507
|
+
<li class="del"><del>one</del></li>
|
508
|
+
<li class="del"><del>two</del></li>
|
509
|
+
<li class="del"><del>three</del></li>
|
510
|
+
<li class="ins"><ins>one<strong></strong></ins></li>
|
511
|
+
<li class="ins"><ins>two<strong></strong></ins></li>
|
512
|
+
<li class="ins"><ins>three<strong></strong></ins></li>
|
513
|
+
</ul>
|
514
|
+
</div>
|
515
|
+
HTML
|
516
|
+
expect(@diff.to_s(:html)).to eq(html)
|
517
|
+
end
|
518
|
+
|
519
|
+
describe 'with lines that include \n' do
|
520
|
+
before do
|
521
|
+
string1 = 'a\nb'"\n"
|
522
|
+
|
523
|
+
string2 = 'acb'"\n"
|
524
|
+
@string1, @string2 = string1, string2
|
525
|
+
end
|
526
|
+
|
527
|
+
it "should not leave lines out" do
|
528
|
+
expect(Diffy::Diff.new(@string1, @string2 ).to_s(:html)).to eq <<-DIFF
|
529
|
+
<div class="diff">
|
530
|
+
<ul>
|
531
|
+
<li class="del"><del>a<strong>\\n</strong>b</del></li>
|
532
|
+
<li class="ins"><ins>a<strong>c</strong>b</ins></li>
|
533
|
+
</ul>
|
534
|
+
</div>
|
535
|
+
DIFF
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
it "should do highlighting on the last line when there's no trailing newlines" do
|
540
|
+
s1 = "foo\nbar\nbang"
|
541
|
+
s2 = "foo\nbar\nbangleize"
|
542
|
+
expect(Diffy::Diff.new(s1,s2).to_s(:html)).to eq <<-DIFF
|
543
|
+
<div class="diff">
|
544
|
+
<ul>
|
545
|
+
<li class="unchanged"><span>foo</span></li>
|
546
|
+
<li class="unchanged"><span>bar</span></li>
|
547
|
+
<li class="del"><del>bang</del></li>
|
548
|
+
<li class="ins"><ins>bang<strong>leize</strong></ins></li>
|
549
|
+
</ul>
|
550
|
+
</div>
|
551
|
+
DIFF
|
552
|
+
end
|
553
|
+
|
554
|
+
it "should correctly do inline hightlighting when default diff options are changed" do
|
555
|
+
original_options = ::Diffy::Diff.default_options
|
556
|
+
begin
|
557
|
+
::Diffy::Diff.default_options.merge!(:diff => '-U0')
|
558
|
+
|
559
|
+
s1 = "foo\nbar\nbang"
|
560
|
+
s2 = "foo\nbar\nbangleize"
|
561
|
+
expect(Diffy::Diff.new(s1,s2).to_s(:html)).to eq <<-DIFF
|
562
|
+
<div class="diff">
|
563
|
+
<ul>
|
564
|
+
<li class="del"><del>bang</del></li>
|
565
|
+
<li class="ins"><ins>bang<strong>leize</strong></ins></li>
|
566
|
+
</ul>
|
567
|
+
</div>
|
568
|
+
DIFF
|
569
|
+
ensure
|
570
|
+
::Diffy::Diff.default_options = original_options
|
571
|
+
end
|
572
|
+
end
|
573
|
+
end
|
574
|
+
|
575
|
+
it "should escape diffed html in html output" do
|
576
|
+
diff = Diffy::Diff.new("<script>alert('bar')</script>", "<script>alert('foo')</script>").to_s(:html)
|
577
|
+
expect(diff).to include('<script>')
|
578
|
+
expect(diff).not_to include('<script>')
|
579
|
+
end
|
580
|
+
|
581
|
+
it "should be easy to generate custom format" do
|
582
|
+
expect(Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").map do |line|
|
583
|
+
case line
|
584
|
+
when /^\+/ then "line #{line.chomp} added"
|
585
|
+
when /^-/ then "line #{line.chomp} removed"
|
586
|
+
end
|
587
|
+
end.compact.join).to eq("line +baz added")
|
588
|
+
end
|
589
|
+
|
590
|
+
it "should let you iterate over chunks instead of lines" do
|
591
|
+
expect(Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each_chunk.map do |chunk|
|
592
|
+
chunk
|
593
|
+
end).to eq([" foo\n bar\n", "+baz\n"])
|
594
|
+
end
|
595
|
+
|
596
|
+
it "should allow chaining enumerable methods" do
|
597
|
+
expect(Diffy::Diff.new("foo\nbar\n", "foo\nbar\nbaz\n").each.map do |line|
|
598
|
+
line
|
599
|
+
end).to eq([" foo\n", " bar\n", "+baz\n"])
|
600
|
+
end
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
604
|
+
describe Diffy::SplitDiff do
|
605
|
+
before do
|
606
|
+
::Diffy::Diff.default_options.merge!(:diff => '-U 10000')
|
607
|
+
end
|
608
|
+
|
609
|
+
it "should fail with invalid format" do
|
610
|
+
expected_fail = expect do
|
611
|
+
Diffy::SplitDiff.new("lorem\n", "ipsum\n", :format => :fail)
|
612
|
+
end
|
613
|
+
expected_fail.to raise_error(ArgumentError)
|
614
|
+
end
|
615
|
+
|
616
|
+
describe "#left" do
|
617
|
+
it "should only highlight deletions" do
|
618
|
+
string1 = "lorem\nipsum\ndolor\nsit amet\n"
|
619
|
+
string2 = "lorem\nipsumdolor\nsit amet\n"
|
620
|
+
expect(Diffy::SplitDiff.new(string1, string2).left).to eq <<-TEXT
|
621
|
+
lorem
|
622
|
+
-ipsum
|
623
|
+
-dolor
|
624
|
+
sit amet
|
625
|
+
TEXT
|
626
|
+
end
|
627
|
+
|
628
|
+
it "should also format left diff as html" do
|
629
|
+
string1 = "lorem\nipsum\ndolor\nsit amet\n"
|
630
|
+
string2 = "lorem\nipsumdolor\nsit amet\n"
|
631
|
+
expect(Diffy::SplitDiff.new(string1, string2, :format => :html).left).to eq <<-HTML
|
632
|
+
<div class="diff">
|
633
|
+
<ul>
|
634
|
+
<li class="unchanged"><span>lorem</span></li>
|
635
|
+
<li class="del"><del>ipsum<strong></strong></del></li>
|
636
|
+
<li class="del"><del><strong></strong>dolor</del></li>
|
637
|
+
<li class="unchanged"><span>sit amet</span></li>
|
638
|
+
</ul>
|
639
|
+
</div>
|
640
|
+
HTML
|
641
|
+
end
|
642
|
+
end
|
643
|
+
|
644
|
+
describe "#right" do
|
645
|
+
it "should only highlight insertions" do
|
646
|
+
string1 = "lorem\nipsum\ndolor\nsit amet\n"
|
647
|
+
string2 = "lorem\nipsumdolor\nsit amet\n"
|
648
|
+
expect(Diffy::SplitDiff.new(string1, string2).right).to eq <<-TEXT
|
649
|
+
lorem
|
650
|
+
+ipsumdolor
|
651
|
+
sit amet
|
652
|
+
TEXT
|
653
|
+
end
|
654
|
+
|
655
|
+
it "should also format right diff as html" do
|
656
|
+
string1 = "lorem\nipsum\ndolor\nsit amet\n"
|
657
|
+
string2 = "lorem\nipsumdolor\nsit amet\n"
|
658
|
+
expect(Diffy::SplitDiff.new(string1, string2, :format => :html).right).to eq <<-HTML
|
659
|
+
<div class="diff">
|
660
|
+
<ul>
|
661
|
+
<li class="unchanged"><span>lorem</span></li>
|
662
|
+
<li class="ins"><ins>ipsumdolor</ins></li>
|
663
|
+
<li class="unchanged"><span>sit amet</span></li>
|
664
|
+
</ul>
|
665
|
+
</div>
|
666
|
+
HTML
|
667
|
+
end
|
668
|
+
end
|
669
|
+
end
|
670
|
+
|
671
|
+
describe 'Diffy::CSS' do
|
672
|
+
it "should be some css" do
|
673
|
+
expect(Diffy::CSS).to include 'diff{overflow:auto;}'
|
674
|
+
end
|
675
|
+
end
|
676
|
+
|