diff_json 0.0.1 → 0.1.0
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 +4 -4
- data/lib/diff_json/diff.rb +86 -39
- data/lib/diff_json/html_output.rb +54 -36
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 381de4c98d550d810fa415cc9a9259b746cae5323dc10b90e00f1b58ef9590a0
|
4
|
+
data.tar.gz: '068496e04aaacf8c3d595535be66864d478faa40efccf09e265c23b853589346'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a3c0d1c5575e1f2dbe544cc7af9bad83cefecd17df789b3783311fa84ed64dc6996f874a7e8b00448bb309628ba3cab0062b8b3a76ae4e1d7399cc569da738b
|
7
|
+
data.tar.gz: a437d87e79ceceee111f1e7f0f2845e1e26622492d9dc639f0b599f55b57b390e53dfe2526cf4d64cd24d365fd61de277266d1586a3677d5b2bceb614b22b2f6
|
data/lib/diff_json/diff.rb
CHANGED
@@ -5,11 +5,12 @@ module DiffJson
|
|
5
5
|
@new_json = new_json
|
6
6
|
@opts = {
|
7
7
|
:debug => false,
|
8
|
-
:ignore_object_keys => [],
|
9
8
|
:diff_count_filter => {
|
10
9
|
:only => ['$**'],
|
11
10
|
:except => []
|
12
|
-
}
|
11
|
+
},
|
12
|
+
:ignore_object_keys => [],
|
13
|
+
:generate_object_sub_diffs => {}
|
13
14
|
}.merge(opts)
|
14
15
|
@filtered = @opts[:diff_count_filter] != {
|
15
16
|
:only => ['$**'],
|
@@ -23,15 +24,26 @@ module DiffJson
|
|
23
24
|
:delete => 0,
|
24
25
|
:move => 0
|
25
26
|
},
|
26
|
-
:
|
27
|
-
|
27
|
+
:full_diff => {
|
28
|
+
:old => [],
|
29
|
+
:new => []
|
30
|
+
},
|
31
|
+
:sub_diffs => {}
|
28
32
|
}
|
29
33
|
|
30
34
|
calculate
|
31
35
|
end
|
32
36
|
|
33
37
|
def diff
|
34
|
-
return @diff
|
38
|
+
return @diff[:full_diff]
|
39
|
+
end
|
40
|
+
|
41
|
+
def sub_diffs
|
42
|
+
return @diff[:sub_diffs]
|
43
|
+
end
|
44
|
+
|
45
|
+
def change_count(operation = :all)
|
46
|
+
return @diff[:count][operation] || 0
|
35
47
|
end
|
36
48
|
|
37
49
|
def retrieve_output(output_type = :stdout, **output_opts)
|
@@ -39,7 +51,7 @@ module DiffJson
|
|
39
51
|
when :stdout
|
40
52
|
when :file
|
41
53
|
when :html
|
42
|
-
html_output = HtmlOutput.new(
|
54
|
+
html_output = HtmlOutput.new(self, **output_opts)
|
43
55
|
return html_output
|
44
56
|
end
|
45
57
|
end
|
@@ -47,8 +59,17 @@ module DiffJson
|
|
47
59
|
private
|
48
60
|
|
49
61
|
def calculate
|
50
|
-
@diff[:old], @diff[:new] = compare_elements(@old_json, @new_json)
|
51
|
-
|
62
|
+
@diff[:full_diff][:old], @diff[:full_diff][:new] = compare_elements(@old_json, @new_json)
|
63
|
+
|
64
|
+
@diff[:sub_diffs].each do |key, sub_diffs|
|
65
|
+
sub_diffs.each do |value, diff|
|
66
|
+
diff[:old] = [] unless diff.key?(:old)
|
67
|
+
diff[:new] = [] unless diff.key?(:new)
|
68
|
+
diff[:old].delete_if{|line| line == [' ', '']}
|
69
|
+
diff[:new].delete_if{|line| line == [' ', '']}
|
70
|
+
diff[:old], diff[:new] = add_blank_lines(diff[:old], diff[:new])
|
71
|
+
end
|
72
|
+
end
|
52
73
|
end
|
53
74
|
|
54
75
|
def compare_elements(old_element, new_element, indent_step = 0, path = '$')
|
@@ -244,6 +265,9 @@ module DiffJson
|
|
244
265
|
|
245
266
|
old_item_lines, new_item_lines = add_blank_lines(old_item_lines, new_item_lines)
|
246
267
|
|
268
|
+
add_object_sub_diff_if_required(item_path, old_item, old_item_lines) if old_item.is_a?(Hash) and old_operator == '-'
|
269
|
+
add_object_sub_diff_if_required(item_path, new_item, new_item_lines, :new) if new_item.is_a?(Hash) and new_operator == '+'
|
270
|
+
|
247
271
|
old_array_lines += old_item_lines
|
248
272
|
new_array_lines += new_item_lines
|
249
273
|
end
|
@@ -271,7 +295,7 @@ module DiffJson
|
|
271
295
|
debug("PROCESS KEY #{k}")
|
272
296
|
|
273
297
|
item_path = "#{base_path}{#{k}}"
|
274
|
-
key_string = "#{k}: "
|
298
|
+
key_string = "#{JSON.pretty_generate(k, max_nesting: false, quirks_mode: true)}: "
|
275
299
|
old_item_lines, new_item_lines = [], []
|
276
300
|
last_loop = (k == keys['all'].last)
|
277
301
|
|
@@ -326,6 +350,9 @@ module DiffJson
|
|
326
350
|
old_object_lines << [' ', "#{indentation(indent_step)}}"]
|
327
351
|
new_object_lines << [' ', "#{indentation(indent_step)}}"]
|
328
352
|
|
353
|
+
add_object_sub_diff_if_required(base_path, old_object, old_object_lines)
|
354
|
+
add_object_sub_diff_if_required(base_path, new_object, new_object_lines, :new)
|
355
|
+
|
329
356
|
return old_object_lines, new_object_lines
|
330
357
|
end
|
331
358
|
|
@@ -388,28 +415,19 @@ module DiffJson
|
|
388
415
|
# Any path prefixes in `only` that match?
|
389
416
|
if (
|
390
417
|
@opts[:diff_count_filter].key?(:only) and
|
391
|
-
@opts[:diff_count_filter][:only].is_a?(Array)
|
418
|
+
@opts[:diff_count_filter][:only].is_a?(Array) and
|
419
|
+
!@opts[:diff_count_filter][:only].empty?
|
392
420
|
)
|
393
421
|
@opts[:diff_count_filter][:only].each do |only_path|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
if path.include?(only_path_prefix)
|
398
|
-
path_remainder = path.gsub(only_path_prefix, '').split(/(\]\[|\]\{|\}\[|\}\{)/)
|
399
|
-
|
400
|
-
if (
|
401
|
-
(path_remainder.length == 0 and only_path_wildcard.length == 0) or
|
402
|
-
(path_remainder.length == 1 and only_path_wildcard.length > 0) or
|
403
|
-
(path_remainder.length > 1 and only_path_wildcard.length > 1)
|
404
|
-
)
|
405
|
-
do_count = true
|
406
|
-
break
|
407
|
-
end
|
422
|
+
unless ['none', 'lower'].include?(path_inclusion(path, only_path))
|
423
|
+
do_count = true
|
424
|
+
break
|
408
425
|
else
|
409
426
|
next
|
410
427
|
end
|
411
428
|
end
|
412
429
|
else
|
430
|
+
# If :only is empty or non-existent, count everything
|
413
431
|
do_count = true
|
414
432
|
end
|
415
433
|
|
@@ -417,23 +435,13 @@ module DiffJson
|
|
417
435
|
if (
|
418
436
|
do_count and
|
419
437
|
@opts[:diff_count_filter].key?(:except) and
|
420
|
-
@opts[:diff_count_filter][:except].is_a?(Array)
|
438
|
+
@opts[:diff_count_filter][:except].is_a?(Array) and
|
439
|
+
!@opts[:diff_count_filter][:except].empty?
|
421
440
|
)
|
422
441
|
@opts[:diff_count_filter][:except].each do |except_path|
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
if path.include?(except_path_prefix)
|
427
|
-
path_remainder = path.gsub(except_path_prefix, '').split(/(\]\[|\]\{|\}\[|\}\{)/)
|
428
|
-
|
429
|
-
if (
|
430
|
-
(path_remainder.length == 0 and except_path_wildcard.length == 0) or
|
431
|
-
(path_remainder.length == 1 and except_path_wildcard.length > 0) or
|
432
|
-
(path_remainder.length > 1 and except_path_wildcard.length > 1)
|
433
|
-
)
|
434
|
-
do_count = false
|
435
|
-
break
|
436
|
-
end
|
442
|
+
unless ['none', 'lower'].include?(path_inclusion(path, except_path))
|
443
|
+
do_count = false
|
444
|
+
break
|
437
445
|
else
|
438
446
|
next
|
439
447
|
end
|
@@ -452,9 +460,48 @@ module DiffJson
|
|
452
460
|
)
|
453
461
|
end
|
454
462
|
|
463
|
+
debug("Post-operation, #{do_count}")
|
464
|
+
|
455
465
|
@diff[:count][:all] += 1 if do_count
|
456
466
|
@diff[:count][operation] += 1 if do_count
|
457
467
|
end
|
458
468
|
end
|
469
|
+
|
470
|
+
def path_inclusion(current_path, check_path)
|
471
|
+
check_path_base = check_path.gsub(/\*/, '')
|
472
|
+
check_path_wildcard = check_path.gsub(/[^\*]/, '') || ''
|
473
|
+
check = 'lower'
|
474
|
+
|
475
|
+
if current_path == check_path_base
|
476
|
+
check = 'exact' if check_path_wildcard == ''
|
477
|
+
check = 'lower'
|
478
|
+
elsif current_path.include?(check_path_base)
|
479
|
+
current_path_remainder = current_path.gsub(check_path_base, '')
|
480
|
+
current_path_remainder_steps = current_path_remainder.split(/(\]\[|\]\{|\}\[|\}\{)/)
|
481
|
+
|
482
|
+
check = 'level' if (current_path_remainder_steps.length == 1 and check_path_wildcard == '*')
|
483
|
+
check = 'recurse' if (current_path_remainder_steps.length > 0 and check_path_wildcard == '**')
|
484
|
+
else
|
485
|
+
check = 'none'
|
486
|
+
end
|
487
|
+
|
488
|
+
return check
|
489
|
+
end
|
490
|
+
|
491
|
+
def add_object_sub_diff_if_required(object_path, object, lines, side = :old)
|
492
|
+
if (
|
493
|
+
@opts.key?(:generate_object_sub_diffs) and
|
494
|
+
@opts[:generate_object_sub_diffs].is_a?(Hash) and
|
495
|
+
!@opts[:generate_object_sub_diffs].empty?
|
496
|
+
)
|
497
|
+
@opts[:generate_object_sub_diffs].each do |k,v|
|
498
|
+
unless ['none', 'lower'].include?(path_inclusion(object_path, k))
|
499
|
+
@diff[:sub_diffs][v] = {} unless @diff[:sub_diffs].key?(v)
|
500
|
+
@diff[:sub_diffs][v][object[v]] = {} unless @diff[:sub_diffs][v].key?(object[v])
|
501
|
+
@diff[:sub_diffs][v][object[v]][side] = lines if object.key?(v)
|
502
|
+
end
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
459
506
|
end
|
460
507
|
end
|
@@ -4,65 +4,83 @@ module DiffJson
|
|
4
4
|
def initialize(diff, **opts)
|
5
5
|
@diff = diff
|
6
6
|
@opts = {
|
7
|
-
:split => false,
|
8
7
|
:table_id_prefix => 'diff_json_view_0'
|
9
8
|
}.merge(opts)
|
9
|
+
@output = {
|
10
|
+
:full_diff => {},
|
11
|
+
:sub_diffs => {}
|
12
|
+
}
|
10
13
|
|
11
14
|
calculate
|
12
15
|
end
|
13
16
|
|
14
|
-
def
|
15
|
-
return @output
|
17
|
+
def full
|
18
|
+
return @output[:full_diff][:full]
|
16
19
|
end
|
17
20
|
|
18
21
|
def left
|
19
|
-
return @output[:
|
20
|
-
|
21
|
-
raise 'Method `#left` is only available for split output'
|
22
|
+
return @output[:full_diff][:left]
|
22
23
|
end
|
23
24
|
|
24
25
|
def right
|
25
|
-
return @output[:
|
26
|
+
return @output[:full_diff][:right]
|
27
|
+
end
|
26
28
|
|
27
|
-
|
29
|
+
def sub_diffs
|
30
|
+
return @output[:sub_diffs]
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
31
34
|
|
32
35
|
def calculate
|
33
|
-
|
34
|
-
@output = {
|
35
|
-
:left => "<table id=\"#{@opts[:table_id_prefix]}_left\" class=\"diff-json-split-view-left\">\n",
|
36
|
-
:right => "<table id=\"#{@opts[:table_id_prefix]}_right\" class=\"diff-json-split-view-right\">\n"
|
37
|
-
}
|
36
|
+
@output[:full_diff] = table_markup(@opts[:table_id_prefix], @diff.diff)
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@output[:
|
44
|
-
@output[:right] += "<tr class=\"diff-json-view-line\">\n"
|
45
|
-
@output[:right] += "<td class=\"diff-json-view-line-operator\">#{@diff[:new][i][0].gsub(/\s/, ' ')}</td>\n"
|
46
|
-
@output[:right] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:right, @diff[:new][i][0])}\">#{@diff[:new][i][1].gsub(/\s/, ' ')}</td>\n"
|
47
|
-
@output[:right] += "</tr>\n"
|
38
|
+
@diff.sub_diffs.each do |key, sub_diffs|
|
39
|
+
sub_diffs.each do |value, diff|
|
40
|
+
sub_key = "#{key}::#{value}"
|
41
|
+
table_key = "#{key}_#{value}"
|
42
|
+
@output[:sub_diffs][sub_key] = table_markup("#{@opts[:table_id_prefix]}_sub_diff_#{table_key}", diff)
|
48
43
|
end
|
44
|
+
end
|
45
|
+
end
|
49
46
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
def table_markup(table_id_prefix, lines)
|
48
|
+
markup = {
|
49
|
+
:full => "",
|
50
|
+
:left => "",
|
51
|
+
:right => ""
|
52
|
+
}
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@output += "<td class=\"diff-json-view-line-content #{content_highlight_class(:left, @diff[:old][i][0])}\">#{@diff[:old][i][1].gsub(/\s/, ' ')}</td>\n"
|
59
|
-
@output += "<td class=\"diff-json-view-line-operator\">#{@diff[:new][i][0].gsub(/\s/, ' ')}</td>\n"
|
60
|
-
@output += "<td class=\"diff-json-view-line-content #{content_highlight_class(:right, @diff[:new][i][0])}\">#{@diff[:new][i][1].gsub(/\s/, ' ')}</td>\n"
|
61
|
-
@output += "</tr>\n"
|
62
|
-
end
|
54
|
+
markup[:full] = "<table id=\"#{table_id_prefix}_full\" class=\"diff-json-full-view\">\n"
|
55
|
+
markup[:left] = "<table id=\"#{table_id_prefix}_left\" class=\"diff-json-split-view-left\">\n"
|
56
|
+
markup[:right] = "<table id=\"#{table_id_prefix}_right\" class=\"diff-json-split-view-right\">\n"
|
63
57
|
|
64
|
-
|
58
|
+
(0..(lines[:old].length - 1)).each do |i|
|
59
|
+
# Full, combined table output
|
60
|
+
markup[:full] += "<tr class=\"diff-json-view-line\">\n"
|
61
|
+
markup[:full] += "<td class=\"diff-json-view-line-operator\">#{lines[:old][i][0].gsub(/\s/, ' ')}</td>\n"
|
62
|
+
markup[:full] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:left, lines[:old][i][0])}\">#{lines[:old][i][1].gsub(/\s/, ' ')}</td>\n"
|
63
|
+
markup[:full] += "<td class=\"diff-json-view-column-break\"></td>\n"
|
64
|
+
markup[:full] += "<td class=\"diff-json-view-line-operator\">#{lines[:new][i][0].gsub(/\s/, ' ')}</td>\n"
|
65
|
+
markup[:full] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:right, lines[:new][i][0])}\">#{lines[:new][i][1].gsub(/\s/, ' ')}</td>\n"
|
66
|
+
markup[:full] += "</tr>\n"
|
67
|
+
# Split, left side output
|
68
|
+
markup[:left] += "<tr class=\"diff-json-view-line\">\n"
|
69
|
+
markup[:left] += "<td class=\"diff-json-view-line-operator\">#{lines[:old][i][0].gsub(/\s/, ' ')}</td>\n"
|
70
|
+
markup[:left] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:left, lines[:old][i][0])}\">#{lines[:old][i][1].gsub(/\s/, ' ')}</td>\n"
|
71
|
+
markup[:left] += "</tr>\n"
|
72
|
+
# Split, right side output
|
73
|
+
markup[:right] += "<tr class=\"diff-json-view-line\">\n"
|
74
|
+
markup[:right] += "<td class=\"diff-json-view-line-operator\">#{lines[:new][i][0].gsub(/\s/, ' ')}</td>\n"
|
75
|
+
markup[:right] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:right, lines[:new][i][0])}\">#{lines[:new][i][1].gsub(/\s/, ' ')}</td>\n"
|
76
|
+
markup[:right] += "</tr>\n"
|
65
77
|
end
|
78
|
+
|
79
|
+
markup[:full] += "</table>\n"
|
80
|
+
markup[:left] += "</table>\n"
|
81
|
+
markup[:right] += "</table>\n"
|
82
|
+
|
83
|
+
return markup
|
66
84
|
end
|
67
85
|
|
68
86
|
def content_highlight_class(side, operator)
|
@@ -73,7 +91,7 @@ module DiffJson
|
|
73
91
|
elsif operator == 'M'
|
74
92
|
return side == :left ? 'diff-json-content-del' : 'diff-json-content-ins'
|
75
93
|
else
|
76
|
-
return
|
94
|
+
return ''
|
77
95
|
end
|
78
96
|
end
|
79
97
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diff_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh MacLachlan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Diffs two JSON objects and returns a left/right diff view, similar to
|
14
14
|
the command line `diff` utility
|