canon 0.3.42 → 0.3.44

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a54063c501419f65316ce159b9ff85c7179d49afc6a0c7d3d17f5adef2981a0
4
- data.tar.gz: f535a9131aed98326fe7c8fa13c70fe39f2913451b39a83a82d2df6ab636219c
3
+ metadata.gz: e7b141fefd0f254d40b0ba7621c7400d882f5a0bcee1fc2f96a51424ce4c7c36
4
+ data.tar.gz: '018e400f0949c85ca2db99aa362664e6434834b135e32efc891b9f4b1c794f46'
5
5
  SHA512:
6
- metadata.gz: 82f5cb1c13b63065112deb746b569e9abf902322c8cff3e94568a05db86f605872f739aa15ca0f82ccab425f92494dd5fcfc9f83ee2b99b4a8309c4c34533474
7
- data.tar.gz: 72002e2e958716c54fa353ffd6fffda94b98e7eeac8e05510af5fa92f4c576fe37c2f5c06fa9d44feae84ba8e9a698ededd8405504b49f28620cc29418f21f22
6
+ metadata.gz: 0d25eaf6dfa12649678fb9e770762fbf1ad51923d7da03b168aa36acbb11fe3242edb958069b9738bf097aa0c90188498b3408f1fd900589bc091394c578d394
7
+ data.tar.gz: e519ee287d5016becf20d31ad057d825d9c6118273305ce713f13c8c0429172283b576fe6a0c477a91cfbda92328b8a4d4f3491b1e6c34e69425d24ff7f12eb1
@@ -59,10 +59,121 @@ module Canon
59
59
  grouping_lines: @diff_grouping_lines,
60
60
  )
61
61
 
62
+ # #85/#86: DiffNodes the enricher could not locate were
63
+ # previously dropped silently — the absorption mechanism.
64
+ # Their serialized content renders as a trailing context so
65
+ # the change is always visible, without perturbing the
66
+ # located walk's line accounting.
67
+ append_unlocated_context(report)
68
+
62
69
  # Layer 6: Format the report
63
70
  format_report(report, doc1, doc2)
64
71
  end
65
72
 
73
+ # Trailing context for DiffNodes with no located char ranges
74
+ # (multiline reflowed text, relocated content): one removed
75
+ # DiffLine per serialized_before line, one added per
76
+ # serialized_after line. Nil positions render as blank line
77
+ # numbers.
78
+ def append_unlocated_context(report)
79
+ unlocated = @differences.select do |dn|
80
+ dn.char_ranges.nil? || dn.char_ranges.empty?
81
+ end
82
+ return if unlocated.empty?
83
+
84
+ unlocated = unlocated.reject do |dn|
85
+ (@show_diffs == :normative && !dn.normative?) ||
86
+ (@show_diffs == :informative && !dn.informative?)
87
+ end
88
+ return if unlocated.empty?
89
+
90
+ # Place each unlocated node's context after the report
91
+ # context containing its nearest preceding LOCATED node
92
+ # (@differences is comparator-walk order = document order),
93
+ # so the change reads in position instead of trailing.
94
+ unlocated.each do |dn|
95
+ context = Canon::Diff::DiffContext.new(
96
+ lines: unlocated_lines(dn),
97
+ )
98
+ anchor_index = context_index_after(report, preceding_located(dn))
99
+ report.contexts.insert(anchor_index, context)
100
+ end
101
+ end
102
+
103
+ # Mini-diff of one unlocated node's serialized sides: shared
104
+ # lines render as :unchanged context instead of remove-all +
105
+ # add-all. Blank line numbers throughout — no located position.
106
+ def unlocated_lines(diff_node)
107
+ before = diff_node.serialized_before&.split("\n") || []
108
+ after = diff_node.serialized_after&.split("\n") || []
109
+ fmt = diff_node.formatting?
110
+ lines = []
111
+ require "diff/lcs" unless defined?(::Diff::LCS)
112
+
113
+ ::Diff::LCS.sdiff(before, after).each do |change|
114
+ case change.action
115
+ when "="
116
+ lines << Canon::Diff::DiffLine.new(
117
+ line_number: nil, new_position: nil,
118
+ content: change.old_element, type: :unchanged,
119
+ diff_node: diff_node
120
+ )
121
+ when "-"
122
+ lines << Canon::Diff::DiffLine.new(
123
+ line_number: nil, new_position: nil,
124
+ content: change.old_element, type: :removed,
125
+ diff_node: diff_node, formatting: fmt
126
+ )
127
+ when "+"
128
+ lines << Canon::Diff::DiffLine.new(
129
+ line_number: nil, new_position: nil,
130
+ content: change.new_element, type: :added,
131
+ diff_node: diff_node, formatting: fmt
132
+ )
133
+ when "!"
134
+ lines << Canon::Diff::DiffLine.new(
135
+ line_number: nil, new_position: nil,
136
+ content: change.old_element, type: :removed,
137
+ diff_node: diff_node, formatting: fmt
138
+ )
139
+ lines << Canon::Diff::DiffLine.new(
140
+ line_number: nil, new_position: nil,
141
+ content: change.new_element, type: :added,
142
+ diff_node: diff_node, formatting: fmt
143
+ )
144
+ end
145
+ end
146
+ lines
147
+ end
148
+
149
+ # The nearest preceding node (in @differences walk order)
150
+ # that the enricher DID locate.
151
+ def preceding_located(diff_node)
152
+ index = @differences.index(diff_node)
153
+ return nil unless index
154
+
155
+ (index - 1).downto(0) do |i|
156
+ dn = @differences[i]
157
+ return dn if dn.char_ranges && !dn.char_ranges.empty?
158
+ end
159
+ nil
160
+ end
161
+
162
+ # Index into report.contexts for inserting an unlocated
163
+ # context: after the context holding the anchor node's lines,
164
+ # or at the front when the anchor is nil (nothing precedes).
165
+ def context_index_after(report, anchor_node)
166
+ return 0 if anchor_node.nil?
167
+
168
+ report.contexts.each_with_index do |context, idx|
169
+ has_anchor = context.lines.any? do |dl|
170
+ dl.diff_node&.equal?(anchor_node)
171
+ end
172
+ return idx + 1 if has_anchor
173
+ end
174
+ report.contexts.length
175
+ end
176
+
66
177
  # Format a DiffReport for display
67
178
  def format_report(report, doc1, doc2)
68
179
  return "" if report.contexts.empty?
@@ -100,12 +211,12 @@ module Canon
100
211
  context.lines.each do |diff_line|
101
212
  case diff_line.type
102
213
  when :unchanged
103
- old_num = diff_line.line_number + 1
104
- new_num = (diff_line.new_position || diff_line.line_number) + 1
214
+ old_num = diff_line.line_number&.+(1)
215
+ new_num = (diff_line.new_position || diff_line.line_number)&.+(1)
105
216
  output << format_unified_line(old_num, new_num, " ",
106
217
  diff_line.content)
107
218
  when :removed
108
- line_num = diff_line.line_number + 1
219
+ line_num = diff_line.line_number&.+(1)
109
220
  formatting = diff_line.formatting?
110
221
  informative = diff_line.informative?
111
222
 
@@ -147,7 +258,7 @@ module Canon
147
258
  theme_color(:removed, :content))
148
259
  end
149
260
  when :added
150
- line_num = (diff_line.new_position || diff_line.line_number) + 1
261
+ line_num = (diff_line.new_position || diff_line.line_number)&.+(1)
151
262
  formatting = diff_line.formatting?
152
263
  informative = diff_line.informative?
153
264
 
@@ -255,8 +366,8 @@ module Canon
255
366
  # Format a changed diff line using DiffCharRanges for character-level highlighting.
256
367
  # Reads pre-computed char ranges from the DiffLine — NO tokenization, NO LCS.
257
368
  def format_changed_line(diff_line, _lines1)
258
- old_line_num = diff_line.line_number + 1
259
- new_line_num = (diff_line.new_position || diff_line.line_number) + 1
369
+ old_line_num = diff_line.line_number&.+(1)
370
+ new_line_num = (diff_line.new_position || diff_line.line_number)&.+(1)
260
371
  formatting = diff_line.formatting?
261
372
  informative = diff_line.informative?
262
373
  old_content = diff_line.old_content || diff_line.content
data/lib/canon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canon
4
- VERSION = "0.3.42"
4
+ VERSION = "0.3.44"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.42
4
+ version: 0.3.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.