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,390 @@
|
|
|
1
|
+
---
|
|
2
|
+
layout: default
|
|
3
|
+
title: Semantic Diff Report
|
|
4
|
+
parent: Advanced
|
|
5
|
+
nav_order: 2
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
:toc:
|
|
9
|
+
:toclevels: 3
|
|
10
|
+
|
|
11
|
+
== Purpose
|
|
12
|
+
|
|
13
|
+
The Semantic Diff Report provides dimension-specific, actionable details for each difference found during comparison. It focuses on **what changed** and **why it matters**, rather than just showing every changed line.
|
|
14
|
+
|
|
15
|
+
The report is automatically shown in verbose mode when differences exist, appearing before the detailed diff output.
|
|
16
|
+
|
|
17
|
+
== Key Features
|
|
18
|
+
|
|
19
|
+
* XPath locations for XML/HTML elements
|
|
20
|
+
* JSON path locations for JSON/YAML data
|
|
21
|
+
* Dimension-specific formatting optimized for each type of difference
|
|
22
|
+
* Colorized output for easy visual scanning
|
|
23
|
+
* Whitespace preservation detection for `<pre>`, `<code>`, etc.
|
|
24
|
+
* Actionable change summaries (e.g., "Added: +xmlns:v, +xmlns:o")
|
|
25
|
+
|
|
26
|
+
== Report Format
|
|
27
|
+
|
|
28
|
+
Each difference is displayed as a vertical section:
|
|
29
|
+
|
|
30
|
+
[source]
|
|
31
|
+
----
|
|
32
|
+
🔍 DIFFERENCE #1/3 [NORMATIVE]
|
|
33
|
+
──────────────────────────────────────────────────────────────────────
|
|
34
|
+
Dimension: attribute_presence
|
|
35
|
+
Location: /iso-standard/preface/foreword
|
|
36
|
+
|
|
37
|
+
⊖ Expected (File 1):
|
|
38
|
+
<foreword> with 3 attributes: displayorder, id, semx-id
|
|
39
|
+
|
|
40
|
+
⊕ Actual (File 2):
|
|
41
|
+
<foreword> with 2 attributes: displayorder, id
|
|
42
|
+
|
|
43
|
+
✨ Changes:
|
|
44
|
+
Removed: -semx-id
|
|
45
|
+
----
|
|
46
|
+
|
|
47
|
+
Where:
|
|
48
|
+
|
|
49
|
+
`STATUS`:: Either `[NORMATIVE]` (green) or `[INFORMATIVE]` (yellow)
|
|
50
|
+
`Dimension`:: The match dimension that detected this difference (magenta)
|
|
51
|
+
`Location`:: XPath for XML/HTML, JSON path for JSON/YAML (blue)
|
|
52
|
+
`Expected`:: What was in File 1 (red heading)
|
|
53
|
+
`Actual`:: What was in File 2 (green heading)
|
|
54
|
+
`Changes`:: Actionable summary (yellow)
|
|
55
|
+
|
|
56
|
+
== Color Scheme
|
|
57
|
+
|
|
58
|
+
* **Dimension name**: Magenta
|
|
59
|
+
* **XPath/JSON path**: Blue
|
|
60
|
+
* **Expected heading**: Red (bold)
|
|
61
|
+
* **Actual heading**: Green (bold)
|
|
62
|
+
* **Changes heading**: Yellow (bold)
|
|
63
|
+
* **Status [NORMATIVE]**: Green (bold)
|
|
64
|
+
* **Status [INFORMATIVE]**: Yellow (bold)
|
|
65
|
+
* **Added items**: Green (with `+` prefix)
|
|
66
|
+
* **Removed items**: Red (with `-` prefix)
|
|
67
|
+
* **Element names**: Magenta
|
|
68
|
+
* **Attribute names**: Cyan
|
|
69
|
+
|
|
70
|
+
== XML/HTML Dimensions
|
|
71
|
+
|
|
72
|
+
=== Attribute Presence
|
|
73
|
+
|
|
74
|
+
Shows when attributes are missing or extra.
|
|
75
|
+
|
|
76
|
+
.Example: Missing attribute
|
|
77
|
+
[example]
|
|
78
|
+
====
|
|
79
|
+
[source]
|
|
80
|
+
----
|
|
81
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
82
|
+
──────────────────────────────────────────────────────────────────────
|
|
83
|
+
Dimension: attribute_presence
|
|
84
|
+
Location: /html/body/div/div
|
|
85
|
+
|
|
86
|
+
⊖ Expected (File 1):
|
|
87
|
+
<div> with 2 attributes: class, id
|
|
88
|
+
|
|
89
|
+
⊕ Actual (File 2):
|
|
90
|
+
<div> with 1 attribute: id
|
|
91
|
+
|
|
92
|
+
✨ Changes:
|
|
93
|
+
Removed: -class
|
|
94
|
+
----
|
|
95
|
+
====
|
|
96
|
+
|
|
97
|
+
=== Attribute Values
|
|
98
|
+
|
|
99
|
+
Shows when an attribute value differs.
|
|
100
|
+
|
|
101
|
+
.Example: Whitespace difference
|
|
102
|
+
[example]
|
|
103
|
+
====
|
|
104
|
+
[source]
|
|
105
|
+
----
|
|
106
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
107
|
+
──────────────────────────────────────────────────────────────────────
|
|
108
|
+
Dimension: attribute_values
|
|
109
|
+
Location: /html/body/div[@id="main"]
|
|
110
|
+
|
|
111
|
+
⊖ Expected (File 1):
|
|
112
|
+
<div> class=" container fluid "
|
|
113
|
+
|
|
114
|
+
⊕ Actual (File 2):
|
|
115
|
+
<div> class="container fluid"
|
|
116
|
+
|
|
117
|
+
✨ Changes:
|
|
118
|
+
Whitespace normalization difference
|
|
119
|
+
----
|
|
120
|
+
====
|
|
121
|
+
|
|
122
|
+
=== Text Content
|
|
123
|
+
|
|
124
|
+
Shows when element text differs.
|
|
125
|
+
|
|
126
|
+
.Example: Text content change
|
|
127
|
+
[example]
|
|
128
|
+
====
|
|
129
|
+
[source]
|
|
130
|
+
----
|
|
131
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
132
|
+
──────────────────────────────────────────────────────────────────────
|
|
133
|
+
Dimension: text_content
|
|
134
|
+
Location: /html/body/div/table/tbody/tr/td/pre/text
|
|
135
|
+
|
|
136
|
+
⊖ Expected (File 1):
|
|
137
|
+
<text> "
|
|
138
|
+
puts \"Hello, world.\"
|
|
139
|
+
"
|
|
140
|
+
|
|
141
|
+
⊕ Actual (File 2):
|
|
142
|
+
<text> "puts \"Hello, world.\" "
|
|
143
|
+
|
|
144
|
+
✨ Changes:
|
|
145
|
+
⚠️ Whitespace preserved (inside <pre>, <code>, etc. - whitespace is significant)
|
|
146
|
+
----
|
|
147
|
+
====
|
|
148
|
+
|
|
149
|
+
The warning appears for text inside whitespace-preserving elements where Canon automatically switches to strict mode.
|
|
150
|
+
|
|
151
|
+
=== Structural Whitespace
|
|
152
|
+
|
|
153
|
+
Shows whitespace-only differences (usually informative).
|
|
154
|
+
|
|
155
|
+
.Example: Whitespace-only difference
|
|
156
|
+
[example]
|
|
157
|
+
====
|
|
158
|
+
[source]
|
|
159
|
+
----
|
|
160
|
+
🔍 DIFFERENCE #1/1 [INFORMATIVE]
|
|
161
|
+
──────────────────────────────────────────────────────────────────────
|
|
162
|
+
Dimension: structural_whitespace
|
|
163
|
+
Location: /root/section/p
|
|
164
|
+
|
|
165
|
+
⊖ Expected (File 1):
|
|
166
|
+
<p> "hello␣␣world"
|
|
167
|
+
|
|
168
|
+
⊕ Actual (File 2):
|
|
169
|
+
<p> "hello␣world"
|
|
170
|
+
|
|
171
|
+
✨ Changes:
|
|
172
|
+
Whitespace-only difference (informative)
|
|
173
|
+
----
|
|
174
|
+
====
|
|
175
|
+
|
|
176
|
+
=== Comments
|
|
177
|
+
|
|
178
|
+
Shows when comment content differs.
|
|
179
|
+
|
|
180
|
+
.Example: Comment difference
|
|
181
|
+
[example]
|
|
182
|
+
====
|
|
183
|
+
[source]
|
|
184
|
+
----
|
|
185
|
+
🔍 DIFFERENCE #1/1 [INFORMATIVE]
|
|
186
|
+
──────────────────────────────────────────────────────────────────────
|
|
187
|
+
Dimension: comments
|
|
188
|
+
Location: /html/head
|
|
189
|
+
|
|
190
|
+
⊖ Expected (File 1):
|
|
191
|
+
<!-- Original comment text -->
|
|
192
|
+
|
|
193
|
+
⊕ Actual (File 2):
|
|
194
|
+
<!-- Modified comment text -->
|
|
195
|
+
|
|
196
|
+
✨ Changes:
|
|
197
|
+
Comment content differs
|
|
198
|
+
----
|
|
199
|
+
====
|
|
200
|
+
|
|
201
|
+
== JSON/YAML Dimensions
|
|
202
|
+
|
|
203
|
+
JSON and YAML use path-based reporting:
|
|
204
|
+
|
|
205
|
+
=== Hash Key Differences
|
|
206
|
+
|
|
207
|
+
.Example: Missing key
|
|
208
|
+
[example]
|
|
209
|
+
====
|
|
210
|
+
[source]
|
|
211
|
+
----
|
|
212
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
213
|
+
──────────────────────────────────────────────────────────────────────
|
|
214
|
+
Dimension: hash_key
|
|
215
|
+
Location: user.email
|
|
216
|
+
|
|
217
|
+
⊖ Expected (File 1):
|
|
218
|
+
user.email = "alice@example.com"
|
|
219
|
+
|
|
220
|
+
⊕ Actual (File 2):
|
|
221
|
+
user.email = nil
|
|
222
|
+
|
|
223
|
+
✨ Changes:
|
|
224
|
+
Key missing
|
|
225
|
+
----
|
|
226
|
+
====
|
|
227
|
+
|
|
228
|
+
=== Primitive Value Differences
|
|
229
|
+
|
|
230
|
+
.Example: Value changed
|
|
231
|
+
[example]
|
|
232
|
+
====
|
|
233
|
+
[source]
|
|
234
|
+
----
|
|
235
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
236
|
+
──────────────────────────────────────────────────────────────────────
|
|
237
|
+
Dimension: primitive_value
|
|
238
|
+
Location: users[0].age
|
|
239
|
+
|
|
240
|
+
⊖ Expected (File 1):
|
|
241
|
+
users[0].age = 25
|
|
242
|
+
|
|
243
|
+
⊕ Actual (File 2):
|
|
244
|
+
users[0].age = 30
|
|
245
|
+
|
|
246
|
+
✨ Changes:
|
|
247
|
+
Value changed
|
|
248
|
+
----
|
|
249
|
+
====
|
|
250
|
+
|
|
251
|
+
=== Array Differences
|
|
252
|
+
|
|
253
|
+
.Example: Array length differs
|
|
254
|
+
[example]
|
|
255
|
+
====
|
|
256
|
+
[source]
|
|
257
|
+
----
|
|
258
|
+
🔍 DIFFERENCE #1/1 [NORMATIVE]
|
|
259
|
+
──────────────────────────────────────────────────────────────────────
|
|
260
|
+
Dimension: array_length
|
|
261
|
+
Location: items
|
|
262
|
+
|
|
263
|
+
⊖ Expected (File 1):
|
|
264
|
+
items = [...] (5 items)
|
|
265
|
+
|
|
266
|
+
⊕ Actual (File 2):
|
|
267
|
+
items = [...] (3 items)
|
|
268
|
+
|
|
269
|
+
✨ Changes:
|
|
270
|
+
Array length differs
|
|
271
|
+
----
|
|
272
|
+
====
|
|
273
|
+
|
|
274
|
+
== Special Features
|
|
275
|
+
|
|
276
|
+
=== XPath Location Extraction
|
|
277
|
+
|
|
278
|
+
For XML/HTML differences, the report extracts XPath with:
|
|
279
|
+
|
|
280
|
+
* Full path from root: `/html/body/div/section/p`
|
|
281
|
+
* Position predicates when multiple siblings: `/p[2]`, `/div[3]`
|
|
282
|
+
* Safe traversal with depth limits to prevent infinite loops
|
|
283
|
+
* Graceful error handling for circular references
|
|
284
|
+
|
|
285
|
+
=== Whitespace Preservation Detection
|
|
286
|
+
|
|
287
|
+
The report detects when text is inside whitespace-preserving HTML elements and shows a special warning:
|
|
288
|
+
|
|
289
|
+
[source]
|
|
290
|
+
----
|
|
291
|
+
✨ Changes: ⚠️ Whitespace preserved (inside <pre>, <code>, etc. - whitespace is significant)
|
|
292
|
+
----
|
|
293
|
+
|
|
294
|
+
Elements detected:
|
|
295
|
+
|
|
296
|
+
* `<pre>` - Preformatted text
|
|
297
|
+
* `<code>` - Code blocks
|
|
298
|
+
* `<textarea>` - Text input areas
|
|
299
|
+
* `<script>` - JavaScript code
|
|
300
|
+
* `<style>` - CSS style sheets
|
|
301
|
+
|
|
302
|
+
This helps developers understand why whitespace differences cause test failures.
|
|
303
|
+
|
|
304
|
+
=== Comprehensive Error Handling
|
|
305
|
+
|
|
306
|
+
The formatter includes multiple layers of error handling:
|
|
307
|
+
|
|
308
|
+
* Top-level rescue in formatting functions
|
|
309
|
+
* Safe XPath extraction with depth limits
|
|
310
|
+
* Safe parent traversal with document node checks
|
|
311
|
+
* Graceful fallbacks when node types are unexpected
|
|
312
|
+
|
|
313
|
+
This ensures the report never crashes, even with unusual DOM structures.
|
|
314
|
+
|
|
315
|
+
== Integration
|
|
316
|
+
|
|
317
|
+
The Semantic Diff Report is integrated at the `format_comparison_result()` level:
|
|
318
|
+
|
|
319
|
+
[source,ruby]
|
|
320
|
+
----
|
|
321
|
+
def format_comparison_result(comparison_result, expected, actual)
|
|
322
|
+
output = []
|
|
323
|
+
|
|
324
|
+
# 1. Algorithm name
|
|
325
|
+
output << "Algorithm: SEMANTIC TREE DIFF"
|
|
326
|
+
|
|
327
|
+
# 2. CANON VERBOSE tables (optional)
|
|
328
|
+
output << verbose_tables if ENV['CANON_VERBOSE'] == '1'
|
|
329
|
+
|
|
330
|
+
# 3. Semantic Diff Report (always if diffs exist)
|
|
331
|
+
if comparison_result.differences.any?
|
|
332
|
+
output << DiffDetailFormatter.format_report(differences)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# 4. Main diff output (always)
|
|
336
|
+
output << format(...)
|
|
337
|
+
|
|
338
|
+
output.compact.join("\n")
|
|
339
|
+
end
|
|
340
|
+
----
|
|
341
|
+
|
|
342
|
+
This ensures the Semantic Diff Report is part of the main output, not debug information.
|
|
343
|
+
|
|
344
|
+
== When It Appears
|
|
345
|
+
|
|
346
|
+
The Semantic Diff Report appears automatically when:
|
|
347
|
+
|
|
348
|
+
1. Comparison finds differences
|
|
349
|
+
2. Verbose mode is enabled (`verbose: true` or `--verbose`)
|
|
350
|
+
3. Files are not equivalent
|
|
351
|
+
|
|
352
|
+
It does **not** appear when:
|
|
353
|
+
|
|
354
|
+
* Files are equivalent
|
|
355
|
+
* Verbose mode is disabled
|
|
356
|
+
* No differences exist
|
|
357
|
+
|
|
358
|
+
== Practical Uses
|
|
359
|
+
|
|
360
|
+
=== Debugging Test Failures
|
|
361
|
+
|
|
362
|
+
When a test fails, the report immediately shows:
|
|
363
|
+
|
|
364
|
+
* Exactly which element changed
|
|
365
|
+
* What dimension detected the change
|
|
366
|
+
* Whether it's normative or informative
|
|
367
|
+
* Actionable summary of what to fix
|
|
368
|
+
|
|
369
|
+
=== Understanding Match Behavior
|
|
370
|
+
|
|
371
|
+
The report helps verify match options are working:
|
|
372
|
+
|
|
373
|
+
* Informative diffs show what's being ignored
|
|
374
|
+
* Normative diffs show what causes failures
|
|
375
|
+
* Dimension names clarify which rules apply
|
|
376
|
+
|
|
377
|
+
=== Code Review
|
|
378
|
+
|
|
379
|
+
During code review, the report provides:
|
|
380
|
+
|
|
381
|
+
* High-level summary of changes
|
|
382
|
+
* Location-based organization
|
|
383
|
+
* Clear separation of semantic vs formatting changes
|
|
384
|
+
|
|
385
|
+
== See Also
|
|
386
|
+
|
|
387
|
+
* link:diff-classification.html[Diff Classification] - Normative vs informative
|
|
388
|
+
* link:../features/diff-formatting/colors-and-symbols.html[Colors and Symbols] - Visual indicators
|
|
389
|
+
* link:verbose-mode-architecture.html[Verbose Mode] - Debug output details
|
|
390
|
+
* link:../understanding/comparison-pipeline.html[Comparison Pipeline] - How comparison works
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
nav_order:
|
|
5
|
-
parent: Advanced Topics
|
|
2
|
+
title: Verbose Mode Architecture
|
|
3
|
+
parent: Advanced
|
|
4
|
+
nav_order: 3
|
|
6
5
|
---
|
|
7
6
|
= Canon verbose mode guide
|
|
8
7
|
:toc:
|
|
9
8
|
:toclevels: 3
|
|
10
9
|
|
|
11
|
-
==
|
|
10
|
+
== Purpose
|
|
12
11
|
|
|
13
|
-
Canon provides a two-tier verbose output architecture for debugging
|
|
14
|
-
comparison failures:
|
|
12
|
+
Canon provides a two-tier verbose output architecture for debugging comparison failures. This document explains the output structure, when to use each tier, and implementation details.
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
actionable, dimension-specific details for each difference
|
|
18
|
-
* **CANON VERBOSE tables**: Extra detailed option tables shown only when
|
|
19
|
-
`CANON_VERBOSE=1` environment variable is set
|
|
14
|
+
== Overview
|
|
20
15
|
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
Canon's verbose mode enhances diff output with configuration tables and summaries:
|
|
17
|
+
|
|
18
|
+
* **Diffs**: Always shown when files differ (default behavior)
|
|
19
|
+
* **Configuration Tables**: Shown with `--verbose` flag or `CANON_VERBOSE=1`
|
|
20
|
+
* **Semantic Diff Report**: Always shown when differences exist in verbose mode
|
|
21
|
+
|
|
22
|
+
The `--verbose` flag adds diagnostic information, not gates diff display.
|
|
23
23
|
|
|
24
24
|
== Architecture
|
|
25
25
|
|
|
@@ -28,74 +28,71 @@ The output architecture follows a clear three-tier structure:
|
|
|
28
28
|
[source]
|
|
29
29
|
----
|
|
30
30
|
╔═════════════════════════════════════════════════════════════════════╗
|
|
31
|
-
║ CANON
|
|
31
|
+
║ CANON DIFF OUTPUT ARCHITECTURE ║
|
|
32
32
|
╚═════════════════════════════════════════════════════════════════════╝
|
|
33
33
|
|
|
34
|
-
When
|
|
34
|
+
When files differ:
|
|
35
35
|
|
|
36
36
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
37
|
-
│ TIER 1:
|
|
37
|
+
│ TIER 1: Configuration Tables (with --verbose flag) │
|
|
38
38
|
│ │
|
|
39
39
|
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
40
|
-
│ │ Match Options Table
|
|
40
|
+
│ │ Match Options Table (if CANON_VERBOSE=1) │ │
|
|
41
41
|
│ │ • Shows preprocessing behavior │ │
|
|
42
42
|
│ │ • Shows dimension behaviors (strict/normalize/ignore) │ │
|
|
43
43
|
│ │ • Explains what each setting means │ │
|
|
44
44
|
│ └────────────────────────────────────────────────────────────────┘ │
|
|
45
45
|
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
46
|
-
│ │ Formatter Options Table
|
|
46
|
+
│ │ Formatter Options Table (if CANON_VERBOSE=1) │ │
|
|
47
47
|
│ │ • Shows mode (by_line vs by_object) │ │
|
|
48
48
|
│ │ • Shows context_lines, diff_grouping_lines │ │
|
|
49
49
|
│ │ • Shows show_diffs filter setting │ │
|
|
50
50
|
│ └────────────────────────────────────────────────────────────────┘ │
|
|
51
51
|
│ ┌────────────────────────────────────────────────────────────────┐ │
|
|
52
|
-
│ │ Comparison Result Summary
|
|
52
|
+
│ │ Comparison Result Summary (if CANON_VERBOSE=1) │ │
|
|
53
53
|
│ │ • Equivalent? (YES/NO) │ │
|
|
54
|
-
│ │ • Normative/Informative/Total diff counts
|
|
54
|
+
│ │ • Normative/Informative/Total diff counts │ │
|
|
55
55
|
│ └────────────────────────────────────────────────────────────────┘ │
|
|
56
56
|
└─────────────────────────────────────────────────────────────────────┘
|
|
57
57
|
│
|
|
58
58
|
▼
|
|
59
59
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
60
|
-
│ TIER 2: Semantic Diff Report (
|
|
60
|
+
│ TIER 2: Semantic Diff Report (if --verbose and diffs exist) │
|
|
61
61
|
│ │
|
|
62
62
|
│ For each difference: │
|
|
63
63
|
│ • XPath location (e.g., /html/body/div/table/pre/text) │
|
|
64
64
|
│ • Dimension classification (attribute_presence, text_content) │
|
|
65
65
|
│ • Specific changes (Added: +xmlns:v, +xmlns:o) │
|
|
66
|
-
│ • Normative/Informative status
|
|
66
|
+
│ • Normative/Informative status │
|
|
67
67
|
│ • Dimension-specific formatting │
|
|
68
68
|
└─────────────────────────────────────────────────────────────────────┘
|
|
69
69
|
│
|
|
70
70
|
▼
|
|
71
71
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
72
|
-
│ TIER 3: Detailed Diff (ALWAYS)
|
|
72
|
+
│ TIER 3: Detailed Diff (ALWAYS when files differ) │
|
|
73
73
|
│ │
|
|
74
74
|
│ Either: │
|
|
75
|
-
│ • Line-by-line diff (for HTML, or with --
|
|
76
|
-
│ • Object tree diff (for XML/JSON/YAML
|
|
75
|
+
│ • Line-by-line diff (for HTML, or with --diff-mode by_line) │
|
|
76
|
+
│ • Object tree diff (for XML/JSON/YAML, or with --diff-mode │
|
|
77
|
+
│ by_object) │
|
|
77
78
|
└─────────────────────────────────────────────────────────────────────┘
|
|
78
79
|
----
|
|
79
80
|
|
|
80
81
|
=== Output flow
|
|
81
82
|
|
|
82
|
-
The `DiffFormatter.format_comparison_result()`
|
|
83
|
-
output:
|
|
83
|
+
The `DiffCommand` and `DiffFormatter.format_comparison_result()` orchestrate output:
|
|
84
84
|
|
|
85
|
-
.
|
|
86
|
-
.
|
|
87
|
-
.
|
|
85
|
+
. Always show diff when files differ (Tier 3)
|
|
86
|
+
. If `--verbose`: Add configuration tables (Tier 1 if CANON_VERBOSE=1)
|
|
87
|
+
. If `--verbose` and diffs exist: Add Semantic Diff Report (Tier 2)
|
|
88
88
|
|
|
89
89
|
== Semantic diff report
|
|
90
90
|
|
|
91
|
-
===
|
|
91
|
+
=== Purpose
|
|
92
92
|
|
|
93
|
-
The Semantic Diff Report is the core verbose output, always shown when
|
|
94
|
-
differences exist. It provides dimension-specific, actionable details for
|
|
95
|
-
each difference.
|
|
93
|
+
The Semantic Diff Report is the core verbose output, always shown when differences exist. It provides dimension-specific, actionable details for each difference.
|
|
96
94
|
|
|
97
|
-
Unlike the detailed diff (which shows every changed line), the Semantic
|
|
98
|
-
Diff Report shows a high-level summary of WHAT changed and WHY it matters.
|
|
95
|
+
Unlike the detailed diff (which shows every changed line), the Semantic Diff Report shows a high-level summary of WHAT changed and WHY it matters.
|
|
99
96
|
|
|
100
97
|
=== Output format
|
|
101
98
|
|
|
@@ -135,8 +132,7 @@ Each difference displays:
|
|
|
135
132
|
* **Location**: XPath for XML/HTML, path for JSON/YAML (colorized in blue)
|
|
136
133
|
* **Expected section**: What was in File 1 (red heading, bold)
|
|
137
134
|
* **Actual section**: What was in File 2 (green heading, bold)
|
|
138
|
-
* **Changes summary**: Actionable description of the difference (yellow,
|
|
139
|
-
bold)
|
|
135
|
+
* **Changes summary**: Actionable description of the difference (yellow, bold)
|
|
140
136
|
|
|
141
137
|
=== Dimension-specific formats
|
|
142
138
|
|
|
@@ -162,8 +158,7 @@ Shows:
|
|
|
162
158
|
|
|
163
159
|
* Element name (`<p>`)
|
|
164
160
|
* How many attributes each has
|
|
165
|
-
* Which attributes were added (green with `+` prefix) or removed (red with
|
|
166
|
-
`-` prefix)
|
|
161
|
+
* Which attributes were added (green with `+` prefix) or removed (red with `-` prefix)
|
|
167
162
|
|
|
168
163
|
==== Attribute value differences
|
|
169
164
|
|
|
@@ -187,8 +182,7 @@ Shows:
|
|
|
187
182
|
|
|
188
183
|
* Which specific attribute differs (highlighted in cyan)
|
|
189
184
|
* Exact values on both sides
|
|
190
|
-
* Analysis: "Whitespace difference only", "Whitespace normalization
|
|
191
|
-
difference", or "Value changed"
|
|
185
|
+
* Analysis: "Whitespace difference only", "Whitespace normalization difference", or "Value changed"
|
|
192
186
|
|
|
193
187
|
==== Text content differences
|
|
194
188
|
|
|
@@ -214,8 +208,7 @@ Location: /html/body/div/table/tbody/tr/td/pre/text
|
|
|
214
208
|
Shows:
|
|
215
209
|
|
|
216
210
|
* Text preview (truncated at 100 characters)
|
|
217
|
-
* Special warning if inside `<pre>`, `<code>`, `<textarea>`, `<script>`,
|
|
218
|
-
or `<style>` elements (where whitespace is significant)
|
|
211
|
+
* Special warning if inside `<pre>`, `<code>`, `<textarea>`, `<script>`, or `<style>` elements (where whitespace is significant)
|
|
219
212
|
|
|
220
213
|
==== Structural whitespace differences
|
|
221
214
|
|
|
@@ -260,10 +253,9 @@ Location: user.email
|
|
|
260
253
|
|
|
261
254
|
== CANON VERBOSE mode
|
|
262
255
|
|
|
263
|
-
===
|
|
256
|
+
=== Purpose
|
|
264
257
|
|
|
265
|
-
CANON VERBOSE mode adds detailed option tables BEFORE the Semantic Diff
|
|
266
|
-
Report. These tables help understand:
|
|
258
|
+
CANON VERBOSE mode adds detailed option tables BEFORE the Semantic Diff Report. These tables help understand:
|
|
267
259
|
|
|
268
260
|
* What match options are in effect
|
|
269
261
|
* How the diff formatter is configured
|
|
@@ -290,10 +282,10 @@ Shows preprocessing and dimension behaviors:
|
|
|
290
282
|
│ Dimension │ Behavior │ Meaning │
|
|
291
283
|
├────────────────────┼───────────┼────────────────────────────────────┤
|
|
292
284
|
│ preprocessing │ rendered │ As browser-rendered (compacted wh… │
|
|
293
|
-
│ text_content │ normalize │ Normalized then compared (normative
|
|
285
|
+
│ text_content │ normalize │ Normalized then compared (normative) │
|
|
294
286
|
│ structural_whit… │ ignore │ Differences IGNORED (informative) │
|
|
295
287
|
│ attribute_presence │ strict │ Must match exactly (normative) │
|
|
296
|
-
│ attribute_values │ normalize │ Normalized then compared (normative
|
|
288
|
+
│ attribute_values │ normalize │ Normalized then compared (normative) │
|
|
297
289
|
│ comments │ ignore │ Differences IGNORED (informative) │
|
|
298
290
|
╰────────────────────┴───────────┴────────────────────────────────────╯
|
|
299
291
|
----
|
|
@@ -309,10 +301,9 @@ Preprocessing behaviors:
|
|
|
309
301
|
|
|
310
302
|
Dimension behaviors:
|
|
311
303
|
|
|
312
|
-
* `:ignore` - Differences IGNORED (
|
|
304
|
+
* `:ignore` - Differences IGNORED (informative, won't fail test)
|
|
313
305
|
* `:strict` - Must match exactly (normative, will fail test)
|
|
314
|
-
* `:normalize` - Normalized then compared (normative if different after
|
|
315
|
-
normalization)
|
|
306
|
+
* `:normalize` - Normalized then compared (normative if different after normalization)
|
|
316
307
|
* `:strip` - Strip leading/trailing whitespace only
|
|
317
308
|
* `:compact` - Collapse whitespace runs to single space
|
|
318
309
|
|
|
@@ -328,7 +319,7 @@ Shows diff formatting settings:
|
|
|
328
319
|
│ Formatter Options │
|
|
329
320
|
├─────────────────────┬─────────┬────────────────────────────────────┤
|
|
330
321
|
│ Option │ Value │ Impact │
|
|
331
|
-
|
|
322
|
+
├─────────────────────┼─────────┼────────────────────────────────────┤
|
|
332
323
|
│ mode │ by_line │ Line-by-line diff │
|
|
333
324
|
│ context_lines │ 3 │ 3 lines of context around diffs │
|
|
334
325
|
│ show_diffs │ all │ Show all diffs (normative + informative) │
|
|
@@ -480,3 +471,10 @@ end
|
|
|
480
471
|
----
|
|
481
472
|
|
|
482
473
|
This ensures the correct output order and separation of concerns.
|
|
474
|
+
|
|
475
|
+
== See also
|
|
476
|
+
|
|
477
|
+
* link:../features/diff-formatting/[Diff Formatting] - Diff output customization
|
|
478
|
+
* link:../understanding/comparison-pipeline.adoc[Comparison Pipeline] - 4-layer architecture
|
|
479
|
+
* link:../interfaces/rspec/[RSpec Matchers] - Using verbose mode in tests
|
|
480
|
+
* link:../interfaces/cli/[CLI] - Command-line verbose mode
|