diff_json 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 500b28225357427a86dabd6853d94896a4efcaccb9e6f9e8153d2b93535ce183
4
- data.tar.gz: de6dae135cebc7bb440239bf40a990c53c1849fc0fd0d2e26f867b083b231050
3
+ metadata.gz: 381de4c98d550d810fa415cc9a9259b746cae5323dc10b90e00f1b58ef9590a0
4
+ data.tar.gz: '068496e04aaacf8c3d595535be66864d478faa40efccf09e265c23b853589346'
5
5
  SHA512:
6
- metadata.gz: 8200a8a6996d6ab68ba6544d27172fd22e712aef12f9b6d62570084ca54e416cd495a4f13a73145532530609420b97540b80dbd89c772d95470df08d6dd80b75
7
- data.tar.gz: 912663025aa950e5ded31559b2d3106592e58a44f23129421ed11320302e11caa2b274335ac03d7da2f67757fde3e6d03138bc8b420457370b2dc0fc8169d853
6
+ metadata.gz: 1a3c0d1c5575e1f2dbe544cc7af9bad83cefecd17df789b3783311fa84ed64dc6996f874a7e8b00448bb309628ba3cab0062b8b3a76ae4e1d7399cc569da738b
7
+ data.tar.gz: a437d87e79ceceee111f1e7f0f2845e1e26622492d9dc639f0b599f55b57b390e53dfe2526cf4d64cd24d365fd61de277266d1586a3677d5b2bceb614b22b2f6
@@ -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
- :old => [],
27
- :new => []
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(@diff, **output_opts)
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
- @calculated = true
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
- only_path_prefix = only_path.gsub(/\*/, '')
395
- only_path_wildcard = only_path.gsub(/[^\*]/, '')
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
- except_path_prefix = except_path.gsub(/\*/, '')
424
- except_path_wildcard = except_path.gsub(/[^\*]/, '') || ''
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 output
15
- return @output
17
+ def full
18
+ return @output[:full_diff][:full]
16
19
  end
17
20
 
18
21
  def left
19
- return @output[:left] if @opts[:split]
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[:right] if @opts[:split]
26
+ return @output[:full_diff][:right]
27
+ end
26
28
 
27
- raise 'Method `#right` is only available for split output'
29
+ def sub_diffs
30
+ return @output[:sub_diffs]
28
31
  end
29
32
 
30
33
  private
31
34
 
32
35
  def calculate
33
- if @opts[:split]
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
- (0..(@diff[:old].length - 1)).each do |i|
40
- @output[:left] += "<tr class=\"diff-json-view-line\">\n"
41
- @output[:left] += "<td class=\"diff-json-view-line-operator\">#{@diff[:old][i][0].gsub(/\s/, '&nbsp;')}</td>\n"
42
- @output[:left] += "<td class=\"diff-json-view-line-content #{content_highlight_class(:left, @diff[:old][i][0])}\">#{@diff[:old][i][1].gsub(/\s/, '&nbsp;')}</td>\n"
43
- @output[:left] += "</tr>\n"
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/, '&nbsp;')}</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/, '&nbsp;')}</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
- @output[:left] += "</table>\n"
51
- @output[:right] += "</table>\n"
52
- else
53
- @output = "<table id=\"#{@opts[:table_id_prefix]}_full\" class=\"diff-json-view\">\n"
47
+ def table_markup(table_id_prefix, lines)
48
+ markup = {
49
+ :full => "",
50
+ :left => "",
51
+ :right => ""
52
+ }
54
53
 
55
- (0..(@diff[:old].length - 1)).each do |i|
56
- @output += "<tr class=\"diff-json-view-line\">\n"
57
- @output += "<td class=\"diff-json-view-line-operator\">#{@diff[:old][i][0].gsub(/\s/, '&nbsp;')}</td>\n"
58
- @output += "<td class=\"diff-json-view-line-content #{content_highlight_class(:left, @diff[:old][i][0])}\">#{@diff[:old][i][1].gsub(/\s/, '&nbsp;')}</td>\n"
59
- @output += "<td class=\"diff-json-view-line-operator\">#{@diff[:new][i][0].gsub(/\s/, '&nbsp;')}</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/, '&nbsp;')}</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
- @output += "</table>\n"
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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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/, '&nbsp;')}</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 nil
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.1
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-13 00:00:00.000000000 Z
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