canon 0.2.8 → 0.2.11
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/.rspec-opal +7 -0
- data/.rubocop_todo.yml +25 -73
- data/Rakefile +37 -0
- data/lib/canon/cache.rb +16 -27
- data/lib/canon/cli.rb +1 -1
- data/lib/canon/color_detector.rb +3 -5
- data/lib/canon/comparison/compare_profile.rb +1 -4
- data/lib/canon/comparison/dimensions/attribute_order_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/attribute_presence_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/attribute_values_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/comments_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/element_position_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/structural_whitespace_dimension.rb +2 -6
- data/lib/canon/comparison/dimensions/text_content_dimension.rb +3 -5
- data/lib/canon/comparison/format_detector.rb +29 -20
- data/lib/canon/comparison/html_comparator.rb +20 -29
- data/lib/canon/comparison/html_compare_profile.rb +3 -10
- data/lib/canon/comparison/html_parser.rb +1 -1
- data/lib/canon/comparison/json_comparator.rb +8 -0
- data/lib/canon/comparison/node_inspector.rb +117 -86
- data/lib/canon/comparison/strategies/semantic_tree_match_strategy.rb +6 -8
- data/lib/canon/comparison/whitespace_sensitivity.rb +55 -193
- data/lib/canon/comparison/xml_comparator/attribute_comparator.rb +19 -2
- data/lib/canon/comparison/xml_comparator/attribute_filter.rb +5 -10
- data/lib/canon/comparison/xml_comparator/child_comparison.rb +4 -4
- data/lib/canon/comparison/xml_comparator/diff_node_builder.rb +40 -8
- data/lib/canon/comparison/xml_comparator/namespace_comparator.rb +14 -28
- data/lib/canon/comparison/xml_comparator/node_parser.rb +14 -13
- data/lib/canon/comparison/xml_comparator/node_type_comparator.rb +30 -58
- data/lib/canon/comparison/xml_comparator.rb +63 -85
- data/lib/canon/comparison/xml_node_comparison.rb +15 -15
- data/lib/canon/comparison/yaml_comparator.rb +8 -0
- data/lib/canon/comparison.rb +24 -24
- data/lib/canon/config/profile_loader.rb +13 -13
- data/lib/canon/config.rb +29 -5
- data/lib/canon/diff/diff_classifier.rb +7 -41
- data/lib/canon/diff/diff_line.rb +1 -1
- data/lib/canon/diff/diff_line_builder.rb +2 -0
- data/lib/canon/diff/diff_node_enricher.rb +22 -24
- data/lib/canon/diff/diff_node_mapper.rb +10 -8
- data/lib/canon/diff/formatting_detector.rb +3 -2
- data/lib/canon/diff/node_serializer.rb +23 -30
- data/lib/canon/diff/path_builder.rb +24 -37
- data/lib/canon/diff/source_locator.rb +0 -3
- data/lib/canon/diff/xml_serialization_formatter.rb +8 -84
- data/lib/canon/diff_formatter/by_line/base_formatter.rb +7 -7
- data/lib/canon/diff_formatter/by_line/json_formatter.rb +1 -1
- data/lib/canon/diff_formatter/by_line/simple_formatter.rb +1 -1
- data/lib/canon/diff_formatter/by_line/xml_formatter.rb +2 -2
- data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +1 -1
- data/lib/canon/diff_formatter/by_line_formatter.rb +1 -1
- data/lib/canon/diff_formatter/by_object/base_formatter.rb +23 -17
- data/lib/canon/diff_formatter/by_object/xml_formatter.rb +127 -11
- data/lib/canon/diff_formatter/by_object_formatter.rb +2 -6
- data/lib/canon/diff_formatter/debug_output.rb +12 -24
- data/lib/canon/diff_formatter/diff_detail_formatter/color_helper.rb +2 -2
- data/lib/canon/diff_formatter/diff_detail_formatter/dimension_formatter.rb +3 -3
- data/lib/canon/diff_formatter/diff_detail_formatter/location_extractor.rb +26 -27
- data/lib/canon/diff_formatter/diff_detail_formatter/node_utils.rb +146 -318
- data/lib/canon/diff_formatter/diff_detail_formatter.rb +28 -20
- data/lib/canon/diff_formatter/legend.rb +2 -2
- data/lib/canon/diff_formatter/pretty_diff_formatter.rb +2 -2
- data/lib/canon/diff_formatter/theme.rb +4 -4
- data/lib/canon/diff_formatter.rb +17 -13
- data/lib/canon/formatters/html_formatter.rb +1 -1
- data/lib/canon/formatters/html_formatter_base.rb +1 -1
- data/lib/canon/formatters/xml_formatter.rb +7 -32
- data/lib/canon/html/data_model.rb +2 -2
- data/lib/canon/pretty_printer/html.rb +1 -1
- data/lib/canon/pretty_printer/xml.rb +16 -7
- data/lib/canon/pretty_printer/xml_normalized.rb +9 -3
- data/lib/canon/rspec_matchers.rb +2 -2
- data/lib/canon/tree_diff/adapters/html_adapter.rb +1 -1
- data/lib/canon/tree_diff/adapters/xml_adapter.rb +1 -1
- data/lib/canon/tree_diff/core/tree_node.rb +1 -3
- data/lib/canon/tree_diff/operation_converter.rb +7 -7
- data/lib/canon/tree_diff/operations/operation_detector.rb +4 -0
- data/lib/canon/validators/base_validator.rb +5 -8
- data/lib/canon/validators/html_validator.rb +3 -8
- data/lib/canon/validators/xml_validator.rb +3 -8
- data/lib/canon/version.rb +1 -1
- data/lib/canon/xml/data_model.rb +132 -138
- data/lib/canon/xml/namespace_helper.rb +5 -0
- data/lib/canon/xml/node.rb +2 -1
- data/lib/canon/xml/nodes/root_node.rb +4 -0
- data/lib/canon/xml/nodes/text_node.rb +6 -1
- data/lib/canon/xml/sax_builder.rb +5 -7
- data/lib/canon/xml/whitespace_normalizer.rb +2 -2
- data/lib/canon/xml_backend.rb +49 -0
- data/lib/canon/xml_parsing.rb +283 -0
- data/lib/canon.rb +3 -1
- data/lib/tasks/benchmark_runner.rb +1 -1
- data/lib/tasks/performance_helpers.rb +1 -1
- metadata +9 -6
|
@@ -283,22 +283,8 @@ module Canon
|
|
|
283
283
|
content = node.value.to_s
|
|
284
284
|
preview = content.length > 30 ? "#{content[0..27]}..." : content
|
|
285
285
|
"<!--#{preview}-->"
|
|
286
|
-
elsif node.
|
|
286
|
+
elsif Canon::XmlParsing.xml_node?(node) || node.is_a?(Canon::Xml::Node)
|
|
287
287
|
"<#{node.name}>"
|
|
288
|
-
elsif node.respond_to?(:content)
|
|
289
|
-
content = node.content.to_s
|
|
290
|
-
if content.length > 30
|
|
291
|
-
"\"#{content[0..27]}...\""
|
|
292
|
-
else
|
|
293
|
-
"\"#{content || ''}\""
|
|
294
|
-
end
|
|
295
|
-
elsif node.respond_to?(:text)
|
|
296
|
-
text = node.text.to_s
|
|
297
|
-
if text.length > 30
|
|
298
|
-
"\"#{text[0..27]}...\""
|
|
299
|
-
else
|
|
300
|
-
"\"#{text || ''}\""
|
|
301
|
-
end
|
|
302
288
|
else
|
|
303
289
|
node.class.name
|
|
304
290
|
end
|
|
@@ -311,14 +297,16 @@ module Canon
|
|
|
311
297
|
|
|
312
298
|
# For attribute differences, show which attributes differ
|
|
313
299
|
if diff.dimension == :attribute_whitespace &&
|
|
314
|
-
|
|
300
|
+
(Canon::XmlParsing.xml_node?(node1) || node1.is_a?(Canon::Xml::Node)) &&
|
|
301
|
+
(Canon::XmlParsing.xml_node?(node2) || node2.is_a?(Canon::Xml::Node))
|
|
315
302
|
attrs1 = format_attributes(node1)
|
|
316
303
|
attrs2 = format_attributes(node2)
|
|
317
304
|
return ["<#{node1.name}> #{attrs1}", "<#{node2.name}> #{attrs2}"]
|
|
318
305
|
end
|
|
319
306
|
|
|
320
307
|
# For element differences, show element names
|
|
321
|
-
if
|
|
308
|
+
if (Canon::XmlParsing.xml_node?(node1) || node1.is_a?(Canon::Xml::Node)) &&
|
|
309
|
+
(Canon::XmlParsing.xml_node?(node2) || node2.is_a?(Canon::Xml::Node))
|
|
322
310
|
if node1.name == node2.name
|
|
323
311
|
# Same element name, different content
|
|
324
312
|
end
|
|
@@ -340,7 +328,7 @@ module Canon
|
|
|
340
328
|
end
|
|
341
329
|
|
|
342
330
|
def format_attributes(node)
|
|
343
|
-
return "" unless node.
|
|
331
|
+
return "" unless Canon::XmlParsing.xml_node?(node) || node.is_a?(Canon::Xml::Node)
|
|
344
332
|
|
|
345
333
|
attrs = node.attributes
|
|
346
334
|
return "" if attrs.empty?
|
|
@@ -350,9 +338,9 @@ module Canon
|
|
|
350
338
|
name = if key.is_a?(String)
|
|
351
339
|
key
|
|
352
340
|
else
|
|
353
|
-
|
|
341
|
+
key.name
|
|
354
342
|
end
|
|
355
|
-
value = val.
|
|
343
|
+
value = val.is_a?(String) ? val : val.value
|
|
356
344
|
"#{name}=\"#{value}\""
|
|
357
345
|
end.sort
|
|
358
346
|
|
|
@@ -365,10 +353,10 @@ module Canon
|
|
|
365
353
|
end
|
|
366
354
|
|
|
367
355
|
def get_node_content(node)
|
|
368
|
-
if
|
|
369
|
-
node.
|
|
370
|
-
elsif node.
|
|
371
|
-
node.
|
|
356
|
+
if Canon::XmlParsing.xml_node?(node)
|
|
357
|
+
Canon::XmlParsing.text_content(node).to_s
|
|
358
|
+
elsif node.is_a?(Canon::Xml::Node)
|
|
359
|
+
node.text_content.to_s
|
|
372
360
|
else
|
|
373
361
|
""
|
|
374
362
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "rainbow"
|
|
3
|
+
require "rainbow" unless RUBY_ENGINE == "opal"
|
|
4
4
|
|
|
5
5
|
module Canon
|
|
6
6
|
class DiffFormatter
|
|
@@ -19,7 +19,7 @@ module Canon
|
|
|
19
19
|
def self.colorize(text, color, use_color, bold: false)
|
|
20
20
|
return text unless use_color
|
|
21
21
|
|
|
22
|
-
presenter = Rainbow(text).
|
|
22
|
+
presenter = Rainbow(text).public_send(color)
|
|
23
23
|
presenter = presenter.bright if bold
|
|
24
24
|
presenter.to_s
|
|
25
25
|
end
|
|
@@ -707,7 +707,7 @@ expand_difference: false)
|
|
|
707
707
|
# @param diff [DiffNode, Hash] Difference node
|
|
708
708
|
# @return [Symbol] Dimension
|
|
709
709
|
def self.extract_dimension(diff)
|
|
710
|
-
if diff.
|
|
710
|
+
if diff.is_a?(Canon::Diff::DiffNode)
|
|
711
711
|
diff.dimension
|
|
712
712
|
elsif diff.is_a?(Hash)
|
|
713
713
|
diff[:dimension] || diff[:diff_code] || :unknown
|
|
@@ -721,7 +721,7 @@ expand_difference: false)
|
|
|
721
721
|
# @param diff [DiffNode, Hash] Difference node
|
|
722
722
|
# @return [Object] Node1
|
|
723
723
|
def self.extract_node1(diff)
|
|
724
|
-
if diff.
|
|
724
|
+
if diff.is_a?(Canon::Diff::DiffNode)
|
|
725
725
|
diff.node1
|
|
726
726
|
elsif diff.is_a?(Hash)
|
|
727
727
|
diff[:node1]
|
|
@@ -733,7 +733,7 @@ expand_difference: false)
|
|
|
733
733
|
# @param diff [DiffNode, Hash] Difference node
|
|
734
734
|
# @return [Object] Node2
|
|
735
735
|
def self.extract_node2(diff)
|
|
736
|
-
if diff.
|
|
736
|
+
if diff.is_a?(Canon::Diff::DiffNode)
|
|
737
737
|
diff.node2
|
|
738
738
|
elsif diff.is_a?(Hash)
|
|
739
739
|
diff[:node2]
|
|
@@ -17,12 +17,12 @@ module Canon
|
|
|
17
17
|
return "" unless diff
|
|
18
18
|
|
|
19
19
|
# Prefer pre-computed path if available (populated by MetadataEnricher)
|
|
20
|
-
if diff.
|
|
21
|
-
return
|
|
20
|
+
if diff.is_a?(Canon::Diff::DiffNode) && diff.path && !diff.path.empty?
|
|
21
|
+
return diff.path
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
# Fall back to extracting from nodes
|
|
25
|
-
node = if diff.
|
|
25
|
+
node = if diff.is_a?(Canon::Diff::DiffNode)
|
|
26
26
|
diff.node1 || diff.node2
|
|
27
27
|
elsif diff.is_a?(Hash)
|
|
28
28
|
diff[:node1] || diff[:node2]
|
|
@@ -30,8 +30,7 @@ module Canon
|
|
|
30
30
|
|
|
31
31
|
return "" unless node
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
xpath.empty? ? "" : "Location: #{xpath}"
|
|
33
|
+
extract_xpath(node)
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
# Extract XPath from a node
|
|
@@ -66,24 +65,26 @@ module Canon
|
|
|
66
65
|
current = node
|
|
67
66
|
|
|
68
67
|
while current
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
name = case current
|
|
69
|
+
when Canon::Xml::Node, Nokogiri::XML::Node
|
|
70
|
+
current.name
|
|
71
|
+
else
|
|
72
|
+
break
|
|
73
|
+
end
|
|
72
74
|
break if name.nil? || name.empty?
|
|
73
75
|
|
|
74
|
-
# Calculate position among siblings
|
|
75
76
|
index = calculate_sibling_index(current, name)
|
|
76
77
|
parts.unshift("#{name}[#{index}]")
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
current = case current
|
|
80
|
+
when Canon::Xml::Node, Nokogiri::XML::Node
|
|
80
81
|
current.parent
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
else
|
|
83
|
+
break
|
|
83
84
|
end
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
break if current.is_a?(Nokogiri::XML::Document) ||
|
|
87
|
+
current.is_a?(Canon::Xml::Nodes::RootNode)
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
parts.empty? ? "" : "/#{parts.join('/')}"
|
|
@@ -95,24 +96,22 @@ module Canon
|
|
|
95
96
|
# @param name [String] Node name
|
|
96
97
|
# @return [Integer] 1-based index
|
|
97
98
|
def self.calculate_sibling_index(node, name)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
parent = if node.respond_to?(:parent)
|
|
99
|
+
parent = case node
|
|
100
|
+
when Canon::Xml::Node, Nokogiri::XML::Node
|
|
101
101
|
node.parent
|
|
102
|
-
elsif node.respond_to?(:parent_node)
|
|
103
|
-
node.parent_node
|
|
104
102
|
end
|
|
105
103
|
|
|
106
104
|
return 1 unless parent
|
|
107
105
|
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
siblings = case parent
|
|
107
|
+
when Canon::Xml::Node, Nokogiri::XML::Node
|
|
110
108
|
parent.children.select do |n|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
109
|
+
case n
|
|
110
|
+
when Canon::Xml::Node, Nokogiri::XML::Node
|
|
111
|
+
n.name == name
|
|
112
|
+
else
|
|
113
|
+
false
|
|
114
|
+
end
|
|
116
115
|
end
|
|
117
116
|
else
|
|
118
117
|
[node]
|