canon 0.1.6 → 0.1.7
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/.rubocop_todo.yml +163 -67
- data/README.adoc +400 -7
- data/docs/Gemfile +9 -0
- data/docs/INDEX.adoc +99 -182
- data/docs/_config.yml +100 -0
- data/docs/advanced/diff-classification.adoc +547 -0
- data/docs/advanced/diff-pipeline.adoc +358 -0
- data/docs/advanced/index.adoc +214 -0
- data/docs/advanced/semantic-diff-report.adoc +390 -0
- data/docs/{VERBOSE.adoc → advanced/verbose-mode-architecture.adoc} +51 -53
- data/docs/features/diff-formatting/algorithm-specific-output.adoc +533 -0
- data/docs/{CHARACTER_VISUALIZATION.adoc → features/diff-formatting/character-visualization.adoc} +23 -62
- data/docs/features/diff-formatting/colors-and-symbols.adoc +606 -0
- data/docs/features/diff-formatting/context-and-grouping.adoc +490 -0
- data/docs/features/diff-formatting/display-filtering.adoc +472 -0
- data/docs/features/diff-formatting/index.adoc +140 -0
- data/docs/features/environment-configuration/index.adoc +327 -0
- data/docs/features/environment-configuration/override-system.adoc +436 -0
- data/docs/features/environment-configuration/size-limits.adoc +273 -0
- data/docs/features/index.adoc +173 -0
- data/docs/features/input-validation/index.adoc +521 -0
- data/docs/features/match-options/algorithm-specific-behavior.adoc +365 -0
- data/docs/features/match-options/html-policies.adoc +312 -0
- data/docs/features/match-options/index.adoc +621 -0
- data/docs/getting-started/index.adoc +83 -0
- data/docs/getting-started/quick-start.adoc +76 -0
- data/docs/guides/choosing-configuration.adoc +689 -0
- data/docs/guides/index.adoc +181 -0
- data/docs/{CLI.adoc → interfaces/cli/index.adoc} +18 -13
- data/docs/interfaces/index.adoc +101 -0
- data/docs/{RSPEC.adoc → interfaces/rspec/index.adoc} +242 -31
- data/docs/{RUBY_API.adoc → interfaces/ruby-api/index.adoc} +118 -16
- data/docs/lychee.toml +65 -0
- data/docs/reference/cli-options.adoc +418 -0
- data/docs/reference/environment-variables.adoc +375 -0
- data/docs/reference/index.adoc +204 -0
- data/docs/reference/options-across-interfaces.adoc +417 -0
- data/docs/understanding/algorithms/dom-diff.adoc +389 -0
- data/docs/understanding/algorithms/index.adoc +314 -0
- data/docs/understanding/algorithms/semantic-tree-diff.adoc +533 -0
- data/docs/understanding/architecture.adoc +447 -0
- data/docs/understanding/comparison-pipeline.adoc +317 -0
- data/docs/understanding/formats/html.adoc +380 -0
- data/docs/understanding/formats/index.adoc +261 -0
- data/docs/understanding/formats/json.adoc +390 -0
- data/docs/understanding/formats/xml.adoc +366 -0
- data/docs/understanding/formats/yaml.adoc +504 -0
- data/docs/understanding/index.adoc +130 -0
- data/lib/canon/cli.rb +42 -1
- data/lib/canon/commands/diff_command.rb +108 -23
- data/lib/canon/comparison/compare_profile.rb +101 -0
- data/lib/canon/comparison/comparison_result.rb +41 -2
- data/lib/canon/comparison/html_comparator.rb +292 -71
- data/lib/canon/comparison/html_compare_profile.rb +117 -0
- data/lib/canon/comparison/match_options.rb +42 -4
- data/lib/canon/comparison/strategies/base_match_strategy.rb +99 -0
- data/lib/canon/comparison/strategies/match_strategy_factory.rb +74 -0
- data/lib/canon/comparison/strategies/semantic_tree_match_strategy.rb +220 -0
- data/lib/canon/comparison/xml_comparator.rb +695 -91
- data/lib/canon/comparison.rb +207 -2
- data/lib/canon/config/env_provider.rb +71 -0
- data/lib/canon/config/env_schema.rb +58 -0
- data/lib/canon/config/override_resolver.rb +55 -0
- data/lib/canon/config/type_converter.rb +59 -0
- data/lib/canon/config.rb +158 -29
- data/lib/canon/data_model.rb +29 -0
- data/lib/canon/diff/diff_classifier.rb +74 -14
- data/lib/canon/diff/diff_context_builder.rb +41 -0
- data/lib/canon/diff/diff_line.rb +18 -2
- data/lib/canon/diff/diff_node.rb +18 -3
- data/lib/canon/diff/diff_node_mapper.rb +71 -12
- data/lib/canon/diff/formatting_detector.rb +53 -0
- data/lib/canon/diff_formatter/by_line/base_formatter.rb +60 -5
- data/lib/canon/diff_formatter/by_line/html_formatter.rb +68 -16
- data/lib/canon/diff_formatter/by_line/json_formatter.rb +0 -37
- data/lib/canon/diff_formatter/by_line/simple_formatter.rb +0 -42
- data/lib/canon/diff_formatter/by_line/xml_formatter.rb +116 -31
- data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +0 -37
- data/lib/canon/diff_formatter/by_object/base_formatter.rb +126 -19
- data/lib/canon/diff_formatter/by_object/xml_formatter.rb +30 -1
- data/lib/canon/diff_formatter/debug_output.rb +7 -1
- data/lib/canon/diff_formatter/diff_detail_formatter.rb +674 -57
- data/lib/canon/diff_formatter/legend.rb +42 -0
- data/lib/canon/diff_formatter.rb +78 -9
- data/lib/canon/errors.rb +56 -0
- data/lib/canon/formatters/html_formatter_base.rb +35 -1
- data/lib/canon/formatters/json_formatter.rb +3 -0
- data/lib/canon/formatters/yaml_formatter.rb +3 -0
- data/lib/canon/html/data_model.rb +229 -0
- data/lib/canon/html.rb +9 -0
- data/lib/canon/options/cli_generator.rb +70 -0
- data/lib/canon/options/registry.rb +234 -0
- data/lib/canon/rspec_matchers.rb +34 -13
- data/lib/canon/tree_diff/adapters/html_adapter.rb +316 -0
- data/lib/canon/tree_diff/adapters/json_adapter.rb +204 -0
- data/lib/canon/tree_diff/adapters/xml_adapter.rb +285 -0
- data/lib/canon/tree_diff/adapters/yaml_adapter.rb +213 -0
- data/lib/canon/tree_diff/core/attribute_comparator.rb +84 -0
- data/lib/canon/tree_diff/core/matching.rb +241 -0
- data/lib/canon/tree_diff/core/node_signature.rb +164 -0
- data/lib/canon/tree_diff/core/node_weight.rb +135 -0
- data/lib/canon/tree_diff/core/tree_node.rb +450 -0
- data/lib/canon/tree_diff/matchers/hash_matcher.rb +258 -0
- data/lib/canon/tree_diff/matchers/similarity_matcher.rb +168 -0
- data/lib/canon/tree_diff/matchers/structural_propagator.rb +242 -0
- data/lib/canon/tree_diff/matchers/universal_matcher.rb +220 -0
- data/lib/canon/tree_diff/operation_converter.rb +631 -0
- data/lib/canon/tree_diff/operations/operation.rb +92 -0
- data/lib/canon/tree_diff/operations/operation_detector.rb +626 -0
- data/lib/canon/tree_diff/tree_diff_integrator.rb +140 -0
- data/lib/canon/tree_diff.rb +33 -0
- data/lib/canon/validators/json_validator.rb +3 -1
- data/lib/canon/validators/yaml_validator.rb +3 -1
- data/lib/canon/version.rb +1 -1
- data/lib/canon/xml/data_model.rb +22 -23
- data/lib/canon/xml/element_matcher.rb +128 -20
- data/lib/canon/xml/namespace_helper.rb +110 -0
- data/lib/canon.rb +3 -0
- metadata +81 -23
- data/_config.yml +0 -116
- data/docs/ADVANCED_TOPICS.adoc +0 -20
- data/docs/BASIC_USAGE.adoc +0 -16
- data/docs/CUSTOMIZING_BEHAVIOR.adoc +0 -19
- data/docs/DIFF_ARCHITECTURE.adoc +0 -435
- data/docs/DIFF_FORMATTING.adoc +0 -540
- data/docs/FORMATS.adoc +0 -447
- data/docs/INPUT_VALIDATION.adoc +0 -477
- data/docs/MATCH_ARCHITECTURE.adoc +0 -463
- data/docs/MATCH_OPTIONS.adoc +0 -719
- data/docs/MODES.adoc +0 -432
- data/docs/NORMATIVE_INFORMATIVE_DIFFS.adoc +0 -219
- data/docs/OPTIONS.adoc +0 -1387
- data/docs/PREPROCESSING.adoc +0 -491
- data/docs/SEMANTIC_DIFF_REPORT.adoc +0 -528
- data/docs/UNDERSTANDING_CANON.adoc +0 -17
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
= Display filtering
|
|
2
|
+
:toc:
|
|
3
|
+
|
|
4
|
+
== General
|
|
5
|
+
|
|
6
|
+
The `show_diffs` parameter controls which differences appear in diff output
|
|
7
|
+
while maintaining correct equivalence determination.
|
|
8
|
+
|
|
9
|
+
This feature allows you to filter diff display based on whether differences are
|
|
10
|
+
normative (affect equivalence) or informative (don't affect equivalence).
|
|
11
|
+
|
|
12
|
+
== Purpose
|
|
13
|
+
|
|
14
|
+
When comparing documents with both normative and informative differences, you
|
|
15
|
+
may want to:
|
|
16
|
+
|
|
17
|
+
* **Show only normative differences**: Focus on changes that make documents
|
|
18
|
+
non-equivalent
|
|
19
|
+
* **Show only informative differences**: View differences that don't affect
|
|
20
|
+
equivalence (e.g., comments when set to `:ignore`)
|
|
21
|
+
* **Show all differences**: See both types (default behavior)
|
|
22
|
+
|
|
23
|
+
=== Common use case: XML comments
|
|
24
|
+
|
|
25
|
+
When comparing XML with `comments: :ignore`, comment differences are classified
|
|
26
|
+
as informative (they don't affect equivalence). Using `show_diffs: :normative`
|
|
27
|
+
hides these comment diffs while showing only structural/content differences.
|
|
28
|
+
|
|
29
|
+
[example]
|
|
30
|
+
====
|
|
31
|
+
[source,ruby]
|
|
32
|
+
----
|
|
33
|
+
xml1 = <<~XML
|
|
34
|
+
<root>
|
|
35
|
+
<!-- Old comment -->
|
|
36
|
+
<element>value1</element>
|
|
37
|
+
</root>
|
|
38
|
+
XML
|
|
39
|
+
|
|
40
|
+
xml2 = <<~XML
|
|
41
|
+
<root>
|
|
42
|
+
<!-- New comment -->
|
|
43
|
+
<element>value2</element>
|
|
44
|
+
</root>
|
|
45
|
+
XML
|
|
46
|
+
|
|
47
|
+
# With comments: :ignore and show_diffs: :normative
|
|
48
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
49
|
+
verbose: true,
|
|
50
|
+
match: { comments: :ignore },
|
|
51
|
+
show_diffs: :normative
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Result:
|
|
55
|
+
# - equivalent? => false (element value differs)
|
|
56
|
+
# - Diff output shows: only the element value change
|
|
57
|
+
# - Diff output hides: comment differences (informative)
|
|
58
|
+
----
|
|
59
|
+
====
|
|
60
|
+
|
|
61
|
+
== Filtering modes
|
|
62
|
+
|
|
63
|
+
The `show_diffs` parameter accepts three values:
|
|
64
|
+
|
|
65
|
+
=== All differences (`:all`)
|
|
66
|
+
|
|
67
|
+
**Default mode**. Shows both normative and informative differences.
|
|
68
|
+
|
|
69
|
+
[source,ruby]
|
|
70
|
+
----
|
|
71
|
+
Canon::Comparison.equivalent?(doc1, doc2,
|
|
72
|
+
verbose: true,
|
|
73
|
+
show_diffs: :all # or omit (default)
|
|
74
|
+
)
|
|
75
|
+
----
|
|
76
|
+
|
|
77
|
+
Use when:
|
|
78
|
+
|
|
79
|
+
* You want to see every difference
|
|
80
|
+
* Debugging to understand all changes
|
|
81
|
+
* Initial comparison to assess document similarity
|
|
82
|
+
|
|
83
|
+
=== Normative differences only (`:normative`)
|
|
84
|
+
|
|
85
|
+
Shows only differences that affect equivalence.
|
|
86
|
+
|
|
87
|
+
[source,ruby]
|
|
88
|
+
----
|
|
89
|
+
Canon::Comparison.equivalent?(doc1, doc2,
|
|
90
|
+
verbose: true,
|
|
91
|
+
show_diffs: :normative
|
|
92
|
+
)
|
|
93
|
+
----
|
|
94
|
+
|
|
95
|
+
Use when:
|
|
96
|
+
|
|
97
|
+
* Focusing on changes that make documents non-equivalent
|
|
98
|
+
* Hiding informative diffs (e.g., comments when ignored)
|
|
99
|
+
* Clean output for CI/CD pipelines
|
|
100
|
+
* Reviewing semantic changes only
|
|
101
|
+
|
|
102
|
+
=== Informative differences only (`:informative`)
|
|
103
|
+
|
|
104
|
+
Shows only differences that don't affect equivalence.
|
|
105
|
+
|
|
106
|
+
[source,ruby]
|
|
107
|
+
----
|
|
108
|
+
Canon::Comparison.equivalent?(doc1, doc2,
|
|
109
|
+
verbose: true,
|
|
110
|
+
show_diffs: :informative
|
|
111
|
+
)
|
|
112
|
+
----
|
|
113
|
+
|
|
114
|
+
Use when:
|
|
115
|
+
|
|
116
|
+
* Reviewing non-semantic changes
|
|
117
|
+
* Checking comment differences
|
|
118
|
+
* Auditing metadata changes
|
|
119
|
+
* Verifying ignored dimensions are truly informative
|
|
120
|
+
|
|
121
|
+
== Visual distinction: Informative vs normative diffs
|
|
122
|
+
|
|
123
|
+
Canon visually distinguishes informative from normative diffs using different symbols and colors:
|
|
124
|
+
|
|
125
|
+
=== Normative diffs (affect equivalence)
|
|
126
|
+
|
|
127
|
+
* **Symbols**: `-` (red) for deletions, `+` (green) for additions
|
|
128
|
+
* **Colors**: Red for removed lines, green for added lines
|
|
129
|
+
* **Meaning**: These differences cause documents to be non-equivalent
|
|
130
|
+
|
|
131
|
+
[example]
|
|
132
|
+
====
|
|
133
|
+
[source]
|
|
134
|
+
----
|
|
135
|
+
4| -| <item>Old</item> # Red - (normative deletion)
|
|
136
|
+
| 5+| <item>New</item> # Green + (normative addition)
|
|
137
|
+
----
|
|
138
|
+
====
|
|
139
|
+
|
|
140
|
+
=== Informative diffs (don't affect equivalence)
|
|
141
|
+
|
|
142
|
+
* **Symbol**: `~` (tilde) in cyan/blue
|
|
143
|
+
* **Color**: Cyan (blue) for both removed and added content
|
|
144
|
+
* **Meaning**: These differences are ignored based on match options
|
|
145
|
+
|
|
146
|
+
[example]
|
|
147
|
+
====
|
|
148
|
+
[source]
|
|
149
|
+
----
|
|
150
|
+
4| ~| <!-- Old comment --> # Cyan ~ (informative)
|
|
151
|
+
| 5~| <!-- New comment --> # Cyan ~ (informative)
|
|
152
|
+
----
|
|
153
|
+
====
|
|
154
|
+
|
|
155
|
+
This visual distinction makes it immediately clear which diffs affect equivalence and which are informational only.
|
|
156
|
+
|
|
157
|
+
.Common scenario: Attribute order with spec_friendly profile
|
|
158
|
+
[example]
|
|
159
|
+
====
|
|
160
|
+
When using the `spec_friendly` profile, attribute order is informative:
|
|
161
|
+
|
|
162
|
+
[source]
|
|
163
|
+
----
|
|
164
|
+
4| ~| <el attr2="b" attr1="a"/> # Cyan ~ (informative)
|
|
165
|
+
| 5~| <el attr1="a" attr2="b"/> # Cyan ~ (informative)
|
|
166
|
+
----
|
|
167
|
+
|
|
168
|
+
The cyan color and `~` symbol indicate this differs does not affect equivalence in the `spec_friendly` profile.
|
|
169
|
+
====
|
|
170
|
+
|
|
171
|
+
== Usage examples
|
|
172
|
+
|
|
173
|
+
=== Ruby API
|
|
174
|
+
|
|
175
|
+
[source,ruby]
|
|
176
|
+
----
|
|
177
|
+
require 'canon/comparison'
|
|
178
|
+
|
|
179
|
+
# Show all differences
|
|
180
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
181
|
+
verbose: true,
|
|
182
|
+
match: { comments: :ignore },
|
|
183
|
+
show_diffs: :all
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Show only normative differences
|
|
187
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
188
|
+
verbose: true,
|
|
189
|
+
match: { comments: :ignore },
|
|
190
|
+
show_diffs: :normative
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Show only informative differences
|
|
194
|
+
result = Canon::Comparison.equivalent?(xml1, xml2,
|
|
195
|
+
verbose: true,
|
|
196
|
+
match: { comments: :ignore },
|
|
197
|
+
show_diffs: :informative
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Access via DiffFormatter directly
|
|
201
|
+
formatter = Canon::DiffFormatter.new(
|
|
202
|
+
use_color: true,
|
|
203
|
+
mode: :by_object,
|
|
204
|
+
show_diffs: :normative
|
|
205
|
+
)
|
|
206
|
+
output = formatter.format(result, :xml)
|
|
207
|
+
----
|
|
208
|
+
|
|
209
|
+
=== Command-line interface
|
|
210
|
+
|
|
211
|
+
[source,bash]
|
|
212
|
+
----
|
|
213
|
+
# Show all differences (default)
|
|
214
|
+
$ canon diff file1.xml file2.xml
|
|
215
|
+
|
|
216
|
+
# Show only normative differences
|
|
217
|
+
$ canon diff file1.xml file2.xml --show-diffs normative
|
|
218
|
+
|
|
219
|
+
# Show only informative differences
|
|
220
|
+
$ canon diff file1.xml file2.xml --show-diffs informative
|
|
221
|
+
|
|
222
|
+
# Combined with match options
|
|
223
|
+
$ canon diff file1.xml file2.xml \
|
|
224
|
+
--comments ignore \
|
|
225
|
+
--show-diffs normative
|
|
226
|
+
----
|
|
227
|
+
|
|
228
|
+
=== RSpec matchers
|
|
229
|
+
|
|
230
|
+
[source,ruby]
|
|
231
|
+
----
|
|
232
|
+
require 'canon/rspec_matchers'
|
|
233
|
+
|
|
234
|
+
RSpec.describe 'XML comparison' do
|
|
235
|
+
it 'matches equivalent documents' do
|
|
236
|
+
# Show all differences on failure
|
|
237
|
+
expect(actual).to be_xml_equivalent_to(expected)
|
|
238
|
+
.show_diffs(:all)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it 'shows only normative differences' do
|
|
242
|
+
expect(actual).to be_xml_equivalent_to(expected,
|
|
243
|
+
match: { comments: :ignore }
|
|
244
|
+
).show_diffs(:normative)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it 'shows only informative differences' do
|
|
248
|
+
expect(actual).to be_xml_equivalent_to(expected,
|
|
249
|
+
match: { comments: :ignore }
|
|
250
|
+
).show_diffs(:informative)
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
----
|
|
254
|
+
|
|
255
|
+
=== Configuration
|
|
256
|
+
|
|
257
|
+
Set default for all comparisons:
|
|
258
|
+
|
|
259
|
+
[source,ruby]
|
|
260
|
+
----
|
|
261
|
+
Canon::Config.configure do |config|
|
|
262
|
+
config.xml.diff.show_diffs = :normative
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Now all XML comparisons use normative-only by default
|
|
266
|
+
result = Canon::Comparison.equivalent?(xml1, xml2, verbose: true)
|
|
267
|
+
----
|
|
268
|
+
|
|
269
|
+
== Relationship to equivalence
|
|
270
|
+
|
|
271
|
+
IMPORTANT: Display filtering does NOT affect equivalence determination.
|
|
272
|
+
Equivalence is always based on normative differences only, regardless of the
|
|
273
|
+
`show_diffs` setting.
|
|
274
|
+
|
|
275
|
+
[source,ruby]
|
|
276
|
+
----
|
|
277
|
+
xml1 = "<root><!-- Comment A --><el>value</el></root>"
|
|
278
|
+
xml2 = "<root><!-- Comment B --><el>value</el></root>"
|
|
279
|
+
|
|
280
|
+
# All three produce the same equivalence result
|
|
281
|
+
result_all = Canon::Comparison.equivalent?(xml1, xml2,
|
|
282
|
+
verbose: true,
|
|
283
|
+
match: { comments: :ignore },
|
|
284
|
+
show_diffs: :all
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
result_normative = Canon::Comparison.equivalent?(xml1, xml2,
|
|
288
|
+
verbose: true,
|
|
289
|
+
match: { comments: :ignore },
|
|
290
|
+
show_diffs: :normative
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
result_informative = Canon::Comparison.equivalent?(xml1, xml2,
|
|
294
|
+
verbose: true,
|
|
295
|
+
match: { comments: :ignore },
|
|
296
|
+
show_diffs: :informative
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# All return true (only comment diffs, which are informative)
|
|
300
|
+
result_all.equivalent? # => true
|
|
301
|
+
result_normative.equivalent? # => true
|
|
302
|
+
result_informative.equivalent? # => true
|
|
303
|
+
|
|
304
|
+
# Only diff output differs:
|
|
305
|
+
# - result_all: shows comment diffs
|
|
306
|
+
# - result_normative: hides comment diffs
|
|
307
|
+
# - result_informative: shows comment diffs
|
|
308
|
+
----
|
|
309
|
+
|
|
310
|
+
== How it works
|
|
311
|
+
|
|
312
|
+
The filtering operates at the display layer:
|
|
313
|
+
|
|
314
|
+
. **Comparison phase**: All differences are detected and classified as
|
|
315
|
+
normative or informative based on match options
|
|
316
|
+
. **Equivalence determination**: Only normative differences affect the
|
|
317
|
+
equivalence result
|
|
318
|
+
. **Display phase**: The `show_diffs` parameter filters which differences
|
|
319
|
+
appear in formatted output
|
|
320
|
+
|
|
321
|
+
.Diff pipeline with display filtering
|
|
322
|
+
[source]
|
|
323
|
+
----
|
|
324
|
+
Input Documents
|
|
325
|
+
│
|
|
326
|
+
▼
|
|
327
|
+
Preprocessing (optional)
|
|
328
|
+
│
|
|
329
|
+
▼
|
|
330
|
+
Semantic Matching
|
|
331
|
+
│
|
|
332
|
+
▼
|
|
333
|
+
Diff Detection & Classification
|
|
334
|
+
│
|
|
335
|
+
├──► Normative DiffNodes
|
|
336
|
+
│
|
|
337
|
+
└──► Informative DiffNodes
|
|
338
|
+
│
|
|
339
|
+
▼
|
|
340
|
+
Equivalence Determination
|
|
341
|
+
(based on normative diffs only)
|
|
342
|
+
│
|
|
343
|
+
▼
|
|
344
|
+
Display Filtering ◄── show_diffs parameter
|
|
345
|
+
(filter which diffs to show)
|
|
346
|
+
│
|
|
347
|
+
▼
|
|
348
|
+
Formatted Output
|
|
349
|
+
----
|
|
350
|
+
|
|
351
|
+
== Match dimensions and informativeness
|
|
352
|
+
|
|
353
|
+
Different match dimension settings affect which diffs are normative vs
|
|
354
|
+
informative:
|
|
355
|
+
|
|
356
|
+
[cols="2,1,3"]
|
|
357
|
+
|===
|
|
358
|
+
|Dimension |Setting |Diff Classification
|
|
359
|
+
|
|
360
|
+
|`comments`
|
|
361
|
+
|`:strict`
|
|
362
|
+
|Normative (affects equivalence)
|
|
363
|
+
|
|
364
|
+
|`comments`
|
|
365
|
+
|`:ignore`
|
|
366
|
+
|Informative (doesn't affect equivalence)
|
|
367
|
+
|
|
368
|
+
|`text_content`
|
|
369
|
+
|`:strict`
|
|
370
|
+
|Normative
|
|
371
|
+
|
|
372
|
+
|`text_content`
|
|
373
|
+
|`:normalize`
|
|
374
|
+
|Normative (but normalized first)
|
|
375
|
+
|
|
376
|
+
|`structural_whitespace`
|
|
377
|
+
|`:strict`
|
|
378
|
+
|Normative
|
|
379
|
+
|
|
380
|
+
|`structural_whitespace`
|
|
381
|
+
|`:ignore`
|
|
382
|
+
|Informative
|
|
383
|
+
|
|
384
|
+
|`attribute_whitespace`
|
|
385
|
+
|`:strict`
|
|
386
|
+
|Normative
|
|
387
|
+
|
|
388
|
+
|`attribute_whitespace`
|
|
389
|
+
|`:normalize`
|
|
390
|
+
|Normative (but normalized first)
|
|
391
|
+
|
|
392
|
+
|`attribute_order`
|
|
393
|
+
|`:strict`
|
|
394
|
+
|Normative
|
|
395
|
+
|
|
396
|
+
|`attribute_order`
|
|
397
|
+
|`:ignore`
|
|
398
|
+
|Informative
|
|
399
|
+
|
|
400
|
+
|`key_order`
|
|
401
|
+
|`:strict`
|
|
402
|
+
|Normative (JSON/YAML)
|
|
403
|
+
|
|
404
|
+
|`key_order`
|
|
405
|
+
|`:ignore`
|
|
406
|
+
|Informative (JSON/YAML)
|
|
407
|
+
|===
|
|
408
|
+
|
|
409
|
+
== Best practices
|
|
410
|
+
|
|
411
|
+
=== In test suites
|
|
412
|
+
|
|
413
|
+
Use `show_diffs: :normative` to reduce noise in test failures:
|
|
414
|
+
|
|
415
|
+
[source,ruby]
|
|
416
|
+
----
|
|
417
|
+
Canon::Config.configure do |config|
|
|
418
|
+
config.xml.match.profile = :spec_friendly
|
|
419
|
+
config.xml.diff.show_diffs = :normative
|
|
420
|
+
end
|
|
421
|
+
----
|
|
422
|
+
|
|
423
|
+
=== In CI/CD pipelines
|
|
424
|
+
|
|
425
|
+
Use `show_diffs: :normative` for cleaner output:
|
|
426
|
+
|
|
427
|
+
[source,bash]
|
|
428
|
+
----
|
|
429
|
+
#!/bin/bash
|
|
430
|
+
canon diff expected.xml actual.xml \
|
|
431
|
+
--match-profile spec_friendly \
|
|
432
|
+
--show-diffs normative
|
|
433
|
+
----
|
|
434
|
+
|
|
435
|
+
=== During development
|
|
436
|
+
|
|
437
|
+
Use `show_diffs: :all` to see everything while debugging:
|
|
438
|
+
|
|
439
|
+
[source,ruby]
|
|
440
|
+
----
|
|
441
|
+
result = Canon::Comparison.equivalent?(doc1, doc2,
|
|
442
|
+
verbose: true,
|
|
443
|
+
show_diffs: :all
|
|
444
|
+
)
|
|
445
|
+
----
|
|
446
|
+
|
|
447
|
+
=== For auditing
|
|
448
|
+
|
|
449
|
+
Use `show_diffs: :informative` to verify ignored dimensions don't have
|
|
450
|
+
unexpected changes:
|
|
451
|
+
|
|
452
|
+
[source,ruby]
|
|
453
|
+
----
|
|
454
|
+
result = Canon::Comparison.equivalent?(doc1, doc2,
|
|
455
|
+
verbose: true,
|
|
456
|
+
match: { comments: :ignore },
|
|
457
|
+
show_diffs: :informative
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
# Review comment changes that were ignored for equivalence
|
|
461
|
+
puts result.differences.count # Number of informative diffs
|
|
462
|
+
----
|
|
463
|
+
|
|
464
|
+
== See also
|
|
465
|
+
|
|
466
|
+
* link:../match-options/index.adoc[Match options] - Configure match dimensions
|
|
467
|
+
* link:colors-and-symbols.adoc[Colors and symbols] - Understanding diff
|
|
468
|
+
visualization
|
|
469
|
+
* link:../../../understanding/algorithms/index.adoc[Diff algorithms] -
|
|
470
|
+
Algorithm-specific behavior
|
|
471
|
+
* link:../../../advanced/diff-classification.adoc[Diff classification] -
|
|
472
|
+
Normative vs informative classification
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Diff Formatting
|
|
3
|
+
parent: Features
|
|
4
|
+
nav_order: 2
|
|
5
|
+
has_children: true
|
|
6
|
+
---
|
|
7
|
+
= Diff formatting
|
|
8
|
+
:toc:
|
|
9
|
+
:toclevels: 2
|
|
10
|
+
|
|
11
|
+
== Purpose
|
|
12
|
+
|
|
13
|
+
Canon provides extensive options for customizing diff output to make
|
|
14
|
+
differences clear, actionable, and easy to understand.
|
|
15
|
+
|
|
16
|
+
This section covers all aspects of diff output formatting, from basic color
|
|
17
|
+
schemes to advanced filtering options.
|
|
18
|
+
|
|
19
|
+
== Features overview
|
|
20
|
+
|
|
21
|
+
Canon's diff formatting includes:
|
|
22
|
+
|
|
23
|
+
* **Display filtering**: Control which differences appear in output based on
|
|
24
|
+
whether they affect equivalence
|
|
25
|
+
* **Colors and symbols**: Visual indicators for different types of changes
|
|
26
|
+
* **Character visualization**: Make invisible characters visible
|
|
27
|
+
* **Context and grouping**: Control how much surrounding context to show
|
|
28
|
+
* **Algorithm-specific output**: Different output styles for different diff
|
|
29
|
+
algorithms
|
|
30
|
+
|
|
31
|
+
== Available formatting options
|
|
32
|
+
|
|
33
|
+
=== Display filtering
|
|
34
|
+
|
|
35
|
+
Filter which differences appear in output while maintaining correct equivalence
|
|
36
|
+
determination.
|
|
37
|
+
|
|
38
|
+
* Show all differences (default)
|
|
39
|
+
* Show only normative differences (affect equivalence)
|
|
40
|
+
* Show only informative differences (don't affect equivalence)
|
|
41
|
+
|
|
42
|
+
See link:display-filtering.adoc[Display filtering] for complete details.
|
|
43
|
+
|
|
44
|
+
=== Colors and symbols
|
|
45
|
+
|
|
46
|
+
Canon uses color-coded output to distinguish different types of changes:
|
|
47
|
+
|
|
48
|
+
* Red: Normative deletions
|
|
49
|
+
* Green: Normative additions
|
|
50
|
+
* Yellow: Normative structural changes
|
|
51
|
+
* Cyan: Informative differences
|
|
52
|
+
|
|
53
|
+
See link:colors-and-symbols.adoc[Colors and symbols] for details.
|
|
54
|
+
|
|
55
|
+
=== Character visualization
|
|
56
|
+
|
|
57
|
+
Make invisible characters visible in diff output:
|
|
58
|
+
|
|
59
|
+
* Whitespace visualization (spaces, tabs, newlines)
|
|
60
|
+
* Non-ASCII character detection
|
|
61
|
+
* CJK-safe Unicode symbols
|
|
62
|
+
|
|
63
|
+
See link:character-visualization.adoc[Character visualization] for details.
|
|
64
|
+
|
|
65
|
+
=== Context and grouping
|
|
66
|
+
|
|
67
|
+
Control how much surrounding context to show:
|
|
68
|
+
|
|
69
|
+
* Context lines: Number of unchanged lines around changes
|
|
70
|
+
* Grouping: Combine nearby changes into single blocks
|
|
71
|
+
|
|
72
|
+
See link:context-and-grouping.adoc[Context and grouping] for details.
|
|
73
|
+
|
|
74
|
+
=== Algorithm-specific output
|
|
75
|
+
|
|
76
|
+
Different diff algorithms produce different output styles:
|
|
77
|
+
|
|
78
|
+
* DOM diff: Line-by-line or by-object output
|
|
79
|
+
* Semantic tree diff: Operation-based output with tree structure
|
|
80
|
+
|
|
81
|
+
See link:algorithm-specific-output.adoc[Algorithm-specific output] for details.
|
|
82
|
+
|
|
83
|
+
== Common use cases
|
|
84
|
+
|
|
85
|
+
=== Testing
|
|
86
|
+
|
|
87
|
+
Focus on actionable differences by filtering informative diffs:
|
|
88
|
+
|
|
89
|
+
[source,ruby]
|
|
90
|
+
----
|
|
91
|
+
Canon::Config.configure do |config|
|
|
92
|
+
config.xml.diff.show_diffs = :normative
|
|
93
|
+
config.xml.diff.use_color = true
|
|
94
|
+
end
|
|
95
|
+
----
|
|
96
|
+
|
|
97
|
+
=== Debugging
|
|
98
|
+
|
|
99
|
+
See all differences with maximum context:
|
|
100
|
+
|
|
101
|
+
[source,ruby]
|
|
102
|
+
----
|
|
103
|
+
result = Canon::Comparison.equivalent?(doc1, doc2,
|
|
104
|
+
verbose: true,
|
|
105
|
+
show_diffs: :all
|
|
106
|
+
)
|
|
107
|
+
----
|
|
108
|
+
|
|
109
|
+
=== CI/CD pipelines
|
|
110
|
+
|
|
111
|
+
Clean, focused output for automated testing:
|
|
112
|
+
|
|
113
|
+
[source,bash]
|
|
114
|
+
----
|
|
115
|
+
canon diff expected.xml actual.xml \
|
|
116
|
+
--show-diffs normative \
|
|
117
|
+
--no-color
|
|
118
|
+
----
|
|
119
|
+
|
|
120
|
+
== Configuration
|
|
121
|
+
|
|
122
|
+
Diff formatting can be configured:
|
|
123
|
+
|
|
124
|
+
* Globally via `Canon::Config.configure`
|
|
125
|
+
* Per-format (XML, HTML, JSON, YAML)
|
|
126
|
+
* Per-operation via method parameters
|
|
127
|
+
|
|
128
|
+
See link:../../reference/cli-options.adoc[CLI options] and
|
|
129
|
+
link:../../interfaces/ruby-api/index.adoc[Ruby API] for configuration details.
|
|
130
|
+
|
|
131
|
+
== See also
|
|
132
|
+
|
|
133
|
+
* link:../../understanding/comparison-pipeline.adoc[Comparison pipeline] -
|
|
134
|
+
Understanding the diff generation process
|
|
135
|
+
* link:../match-options/index.adoc[Match options] - Controlling what gets
|
|
136
|
+
compared
|
|
137
|
+
* link:../../advanced/diff-classification.adoc[Diff classification] -
|
|
138
|
+
Normative vs informative differences
|
|
139
|
+
* link:../../interfaces/cli/index.adoc[CLI interface] - Command-line usage
|
|
140
|
+
* link:../../interfaces/ruby-api/index.adoc[Ruby API] - Programmatic usage
|