canon 0.3.52 → 0.3.54

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: e699f814a8d0944cf2cef44825a9d417302adf157a7672ee3d94974a372b8ade
4
- data.tar.gz: ef0e376d61027009a26ba783cb71ab5bedf0efc947cfea7a2b465d5504b32597
3
+ metadata.gz: c8094be0b06c7cd2a74e5e5fa4085f2a3ac654c54ed9ec106fcfa930490d4d11
4
+ data.tar.gz: 71c81085b65c0648b059a9d6a4d12663d71867b2f032f42e6ed95df2c38fcb26
5
5
  SHA512:
6
- metadata.gz: d0ef1400915d857311938307896e5e276bf3fb56088f98716218d2d92d82429f0b5864f4e24ce35eb0a99d249ed04c862b948de6483269df9cd21879845827d2
7
- data.tar.gz: 5d95e02de1d7eb031a15f41a5705414cebd8360fc9bbaec0b1f90a34b1fb0689d504c3c5f258b3de7b66d91951b2889e2ad5dbc1d75d3485eb6d5f15e8588114
6
+ metadata.gz: 2a2401a1455182a4c4dc9b553fdbc51f6d63b4a9153ecf99f248bbf42fe43ac2f1ee801df0e22e52aebd1d4bfbecd0409e39d35e4fa02f440de7c674ccb44777
7
+ data.tar.gz: 894d3d399acd98b30c8dbd6da4fcce1915f12355347e5df6f77373c37fc7a9d7a2cfd21bbafbe53617d4ab6eb0e37a0820091ce61850554da25b5741a25945e1
@@ -5,12 +5,14 @@ module Canon
5
5
  # Encapsulates the result of a comparison operation
6
6
  # Provides methods to query equivalence based on normative diffs
7
7
  class ComparisonResult
8
- attr_reader :differences, :preprocessed_strings, :format, :html_version,
9
- :match_options, :algorithm, :original_strings,
8
+ attr_reader :differences, :format, :html_version,
9
+ :match_options, :algorithm,
10
10
  :parse_errors_expected, :parse_errors_received
11
11
 
12
12
  # @param differences [Array<DiffNode>] Array of difference nodes
13
- # @param preprocessed_strings [Array<String, String>] Pre-processed content for display
13
+ # @param preprocessed_strings [Array<String, String>, Proc] Pre-processed
14
+ # content for display, or a Proc returning the Array (materialized on
15
+ # first read)
14
16
  # @param format [Symbol] Format type (:xml, :html, :json, :yaml)
15
17
  # @param html_version [Symbol, nil] HTML version (:html4 or :html5) for HTML format only
16
18
  # @param match_options [Hash, nil] Resolved match options used for comparison
@@ -23,7 +25,7 @@ html_version: nil, match_options: nil, algorithm: :dom, original_strings: nil,
23
25
  parse_errors_expected: nil, parse_errors_received: nil)
24
26
  @differences = differences
25
27
  @preprocessed_strings = preprocessed_strings
26
- @original_strings = original_strings || preprocessed_strings
28
+ @original_strings = original_strings
27
29
  @format = format
28
30
  @html_version = html_version
29
31
  @match_options = match_options
@@ -32,6 +34,28 @@ parse_errors_expected: nil, parse_errors_received: nil)
32
34
  @parse_errors_received = Array(parse_errors_received)
33
35
  end
34
36
 
37
+ # Display strings for the compared inputs. When the comparator
38
+ # supplied a builder Proc (the display strings require serializing
39
+ # both parsed documents), materialization is deferred to the first
40
+ # read: by_object consumers never pay it, by_line and preprocessed
41
+ # display trigger it exactly once.
42
+ #
43
+ # @return [Array<String, String>]
44
+ def preprocessed_strings
45
+ unless @preprocessed_strings.is_a?(Array)
46
+ @preprocessed_strings = @preprocessed_strings.call
47
+ end
48
+ @preprocessed_strings
49
+ end
50
+
51
+ # Unprocessed input strings; falls back to the preprocessed pair
52
+ # when the comparator did not provide originals.
53
+ #
54
+ # @return [Array<String, String>]
55
+ def original_strings
56
+ @original_strings || preprocessed_strings
57
+ end
58
+
35
59
  # Whether either side reported parse errors. Used by the diff
36
60
  # formatter to decide whether to render the parse-error banner.
37
61
  #
@@ -147,8 +171,8 @@ show_diffs: :all, diff_mode: :separate, legacy_terminal: false)
147
171
  formatter.format(
148
172
  self,
149
173
  @format,
150
- doc1: @preprocessed_strings[0],
151
- doc2: @preprocessed_strings[1],
174
+ doc1: preprocessed_strings[0],
175
+ doc2: preprocessed_strings[1],
152
176
  html_version: @html_version,
153
177
  )
154
178
  end
@@ -131,8 +131,10 @@ module Canon
131
131
  if opts[:verbose]
132
132
  ComparisonResult.new(
133
133
  differences: differences,
134
- preprocessed_strings: [serialize_for_display(node1),
135
- serialize_for_display(node2)],
134
+ preprocessed_strings: lambda do
135
+ [serialize_for_display(node1),
136
+ serialize_for_display(node2)]
137
+ end,
136
138
  original_strings: [original_str1, original_str2],
137
139
  format: :html,
138
140
  html_version: html_version,
@@ -44,12 +44,16 @@ module Canon
44
44
  differences, "")
45
45
 
46
46
  if opts[:verbose]
47
- json_str1 = obj1.is_a?(String) ? obj1 : JSON.pretty_generate(obj1)
48
- json_str2 = obj2.is_a?(String) ? obj2 : JSON.pretty_generate(obj2)
47
+ preprocessed = lambda do
48
+ [
49
+ obj1.is_a?(String) ? obj1 : JSON.pretty_generate(obj1),
50
+ obj2.is_a?(String) ? obj2 : JSON.pretty_generate(obj2),
51
+ ]
52
+ end
49
53
 
50
54
  ComparisonResult.new(
51
55
  differences: differences,
52
- preprocessed_strings: [json_str1, json_str2],
56
+ preprocessed_strings: preprocessed,
53
57
  format: :json,
54
58
  match_options: match_opts_hash,
55
59
  )
@@ -131,11 +131,14 @@ module Canon
131
131
 
132
132
  if opts[:verbose]
133
133
  # Serialize parsed nodes for consistent formatting
134
- # This ensures both sides formatted identically, showing only real differences
135
- preprocessed = [
136
- serialize_node(node1).gsub("><", ">\n<"),
137
- serialize_node(node2).gsub("><", ">\n<"),
138
- ]
134
+ # This ensures both sides formatted identically, showing only real
135
+ # differences. Deferred: by_object consumers never read these.
136
+ preprocessed = lambda do
137
+ [
138
+ serialize_node(node1).gsub("><", ">\n<"),
139
+ serialize_node(node2).gsub("><", ">\n<"),
140
+ ]
141
+ end
139
142
 
140
143
  ComparisonResult.new(
141
144
  differences: differences,
@@ -181,16 +184,16 @@ module Canon
181
184
  def build_trivial_equivalent_result(n1, n2, opts)
182
185
  return true unless opts[:verbose]
183
186
 
184
- # Parse nodes for verbose display
185
- preserve_whitespace = true
186
- node1 = parse_node(n1, :none,
187
- preserve_whitespace: preserve_whitespace)
188
- node2 = parse_node(n2, :none,
189
- preserve_whitespace: preserve_whitespace)
190
- preprocessed = [
191
- serialize_node(node1).gsub("><", ">\n<"),
192
- serialize_node(node2).gsub("><", ">\n<"),
193
- ]
187
+ # Parse nodes for verbose display — deferred with the strings:
188
+ # nothing but the display pair ever reads them.
189
+ preprocessed = lambda do
190
+ [
191
+ serialize_node(parse_node(n1, :none,
192
+ preserve_whitespace: true)).gsub("><", ">\n<"),
193
+ serialize_node(parse_node(n2, :none,
194
+ preserve_whitespace: true)).gsub("><", ">\n<"),
195
+ ]
196
+ end
194
197
  original1 = n1.is_a?(String) ? n1 : serialize_node(n1)
195
198
  original2 = n2.is_a?(String) ? n2 : serialize_node(n2)
196
199
 
@@ -69,13 +69,17 @@ module Canon
69
69
  differences, "")
70
70
 
71
71
  if opts[:verbose]
72
- # Format YAML for display
73
- yaml_str1 = obj1.is_a?(String) ? obj1 : Canon::YamlParsing.dump(obj1)
74
- yaml_str2 = obj2.is_a?(String) ? obj2 : Canon::YamlParsing.dump(obj2)
72
+ # Format YAML for display — deferred until first read
73
+ preprocessed = lambda do
74
+ [
75
+ obj1.is_a?(String) ? obj1 : Canon::YamlParsing.dump(obj1),
76
+ obj2.is_a?(String) ? obj2 : Canon::YamlParsing.dump(obj2),
77
+ ]
78
+ end
75
79
 
76
80
  ComparisonResult.new(
77
81
  differences: differences,
78
- preprocessed_strings: [yaml_str1, yaml_str2],
82
+ preprocessed_strings: preprocessed,
79
83
  format: :yaml,
80
84
  match_options: match_opts_hash,
81
85
  )
@@ -407,11 +407,11 @@ module Canon
407
407
 
408
408
  # CRITICAL: Use strategy's preprocess_for_display to ensure proper
409
409
  # line-breaking. This matches DOM diff preprocessing pattern
410
- # (xml_comparator.rb:106-109).
410
+ # (xml_comparator.rb). Deferred via the lazy ComparisonResult seam:
411
+ # by_object consumers never pay the serialization.
411
412
  strategy = Comparison::Strategies::SemanticTreeMatchStrategy.new(
412
413
  format: format1, match_options: match_options_only,
413
414
  )
414
- str1, str2 = strategy.preprocess_for_display(doc1, doc2)
415
415
 
416
416
  # Store tree diff data in match_options for access via result.
417
417
  enhanced_match_options = match_opts_hash.merge(
@@ -423,7 +423,7 @@ module Canon
423
423
  # Create ComparisonResult for unified handling.
424
424
  result = Canon::Comparison::ComparisonResult.new(
425
425
  differences: diff_nodes,
426
- preprocessed_strings: [str1, str2],
426
+ preprocessed_strings: -> { strategy.preprocess_for_display(doc1, doc2) },
427
427
  original_strings: [original_str1, original_str2],
428
428
  format: format1,
429
429
  html_version: %i[html4 html5].include?(format1) ? format1 : nil,
@@ -62,12 +62,14 @@ module Canon
62
62
  # @param element [Canon::Xml::Nodes::ElementNode] Element to serialize
63
63
  # @return [String] Serialized element
64
64
  def self.serialize_element_node(element)
65
- # Build opening tag with attributes
65
+ # Mutating build: no intermediate per attribute (one child
66
+ # string per element via map+join below is the remaining
67
+ # necessary product).
66
68
  tag = "<#{element.name}"
67
69
 
68
70
  # Add attributes
69
71
  element.sorted_attribute_nodes.each do |attr|
70
- tag += " #{attr.name}=\"#{attr.value}\""
72
+ tag << " " << attr.name << '="' << attr.value << '"'
71
73
  end
72
74
 
73
75
  # Check if element has children
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.52"
4
+ VERSION = "0.3.54"
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.52
4
+ version: 0.3.54
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.