ydiffy 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|