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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +163 -67
  3. data/README.adoc +400 -7
  4. data/docs/Gemfile +9 -0
  5. data/docs/INDEX.adoc +99 -182
  6. data/docs/_config.yml +100 -0
  7. data/docs/advanced/diff-classification.adoc +547 -0
  8. data/docs/advanced/diff-pipeline.adoc +358 -0
  9. data/docs/advanced/index.adoc +214 -0
  10. data/docs/advanced/semantic-diff-report.adoc +390 -0
  11. data/docs/{VERBOSE.adoc → advanced/verbose-mode-architecture.adoc} +51 -53
  12. data/docs/features/diff-formatting/algorithm-specific-output.adoc +533 -0
  13. data/docs/{CHARACTER_VISUALIZATION.adoc → features/diff-formatting/character-visualization.adoc} +23 -62
  14. data/docs/features/diff-formatting/colors-and-symbols.adoc +606 -0
  15. data/docs/features/diff-formatting/context-and-grouping.adoc +490 -0
  16. data/docs/features/diff-formatting/display-filtering.adoc +472 -0
  17. data/docs/features/diff-formatting/index.adoc +140 -0
  18. data/docs/features/environment-configuration/index.adoc +327 -0
  19. data/docs/features/environment-configuration/override-system.adoc +436 -0
  20. data/docs/features/environment-configuration/size-limits.adoc +273 -0
  21. data/docs/features/index.adoc +173 -0
  22. data/docs/features/input-validation/index.adoc +521 -0
  23. data/docs/features/match-options/algorithm-specific-behavior.adoc +365 -0
  24. data/docs/features/match-options/html-policies.adoc +312 -0
  25. data/docs/features/match-options/index.adoc +621 -0
  26. data/docs/getting-started/index.adoc +83 -0
  27. data/docs/getting-started/quick-start.adoc +76 -0
  28. data/docs/guides/choosing-configuration.adoc +689 -0
  29. data/docs/guides/index.adoc +181 -0
  30. data/docs/{CLI.adoc → interfaces/cli/index.adoc} +18 -13
  31. data/docs/interfaces/index.adoc +101 -0
  32. data/docs/{RSPEC.adoc → interfaces/rspec/index.adoc} +242 -31
  33. data/docs/{RUBY_API.adoc → interfaces/ruby-api/index.adoc} +118 -16
  34. data/docs/lychee.toml +65 -0
  35. data/docs/reference/cli-options.adoc +418 -0
  36. data/docs/reference/environment-variables.adoc +375 -0
  37. data/docs/reference/index.adoc +204 -0
  38. data/docs/reference/options-across-interfaces.adoc +417 -0
  39. data/docs/understanding/algorithms/dom-diff.adoc +389 -0
  40. data/docs/understanding/algorithms/index.adoc +314 -0
  41. data/docs/understanding/algorithms/semantic-tree-diff.adoc +533 -0
  42. data/docs/understanding/architecture.adoc +447 -0
  43. data/docs/understanding/comparison-pipeline.adoc +317 -0
  44. data/docs/understanding/formats/html.adoc +380 -0
  45. data/docs/understanding/formats/index.adoc +261 -0
  46. data/docs/understanding/formats/json.adoc +390 -0
  47. data/docs/understanding/formats/xml.adoc +366 -0
  48. data/docs/understanding/formats/yaml.adoc +504 -0
  49. data/docs/understanding/index.adoc +130 -0
  50. data/lib/canon/cli.rb +42 -1
  51. data/lib/canon/commands/diff_command.rb +108 -23
  52. data/lib/canon/comparison/compare_profile.rb +101 -0
  53. data/lib/canon/comparison/comparison_result.rb +41 -2
  54. data/lib/canon/comparison/html_comparator.rb +292 -71
  55. data/lib/canon/comparison/html_compare_profile.rb +117 -0
  56. data/lib/canon/comparison/match_options.rb +42 -4
  57. data/lib/canon/comparison/strategies/base_match_strategy.rb +99 -0
  58. data/lib/canon/comparison/strategies/match_strategy_factory.rb +74 -0
  59. data/lib/canon/comparison/strategies/semantic_tree_match_strategy.rb +220 -0
  60. data/lib/canon/comparison/xml_comparator.rb +695 -91
  61. data/lib/canon/comparison.rb +207 -2
  62. data/lib/canon/config/env_provider.rb +71 -0
  63. data/lib/canon/config/env_schema.rb +58 -0
  64. data/lib/canon/config/override_resolver.rb +55 -0
  65. data/lib/canon/config/type_converter.rb +59 -0
  66. data/lib/canon/config.rb +158 -29
  67. data/lib/canon/data_model.rb +29 -0
  68. data/lib/canon/diff/diff_classifier.rb +74 -14
  69. data/lib/canon/diff/diff_context_builder.rb +41 -0
  70. data/lib/canon/diff/diff_line.rb +18 -2
  71. data/lib/canon/diff/diff_node.rb +18 -3
  72. data/lib/canon/diff/diff_node_mapper.rb +71 -12
  73. data/lib/canon/diff/formatting_detector.rb +53 -0
  74. data/lib/canon/diff_formatter/by_line/base_formatter.rb +60 -5
  75. data/lib/canon/diff_formatter/by_line/html_formatter.rb +68 -16
  76. data/lib/canon/diff_formatter/by_line/json_formatter.rb +0 -37
  77. data/lib/canon/diff_formatter/by_line/simple_formatter.rb +0 -42
  78. data/lib/canon/diff_formatter/by_line/xml_formatter.rb +116 -31
  79. data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +0 -37
  80. data/lib/canon/diff_formatter/by_object/base_formatter.rb +126 -19
  81. data/lib/canon/diff_formatter/by_object/xml_formatter.rb +30 -1
  82. data/lib/canon/diff_formatter/debug_output.rb +7 -1
  83. data/lib/canon/diff_formatter/diff_detail_formatter.rb +674 -57
  84. data/lib/canon/diff_formatter/legend.rb +42 -0
  85. data/lib/canon/diff_formatter.rb +78 -9
  86. data/lib/canon/errors.rb +56 -0
  87. data/lib/canon/formatters/html_formatter_base.rb +35 -1
  88. data/lib/canon/formatters/json_formatter.rb +3 -0
  89. data/lib/canon/formatters/yaml_formatter.rb +3 -0
  90. data/lib/canon/html/data_model.rb +229 -0
  91. data/lib/canon/html.rb +9 -0
  92. data/lib/canon/options/cli_generator.rb +70 -0
  93. data/lib/canon/options/registry.rb +234 -0
  94. data/lib/canon/rspec_matchers.rb +34 -13
  95. data/lib/canon/tree_diff/adapters/html_adapter.rb +316 -0
  96. data/lib/canon/tree_diff/adapters/json_adapter.rb +204 -0
  97. data/lib/canon/tree_diff/adapters/xml_adapter.rb +285 -0
  98. data/lib/canon/tree_diff/adapters/yaml_adapter.rb +213 -0
  99. data/lib/canon/tree_diff/core/attribute_comparator.rb +84 -0
  100. data/lib/canon/tree_diff/core/matching.rb +241 -0
  101. data/lib/canon/tree_diff/core/node_signature.rb +164 -0
  102. data/lib/canon/tree_diff/core/node_weight.rb +135 -0
  103. data/lib/canon/tree_diff/core/tree_node.rb +450 -0
  104. data/lib/canon/tree_diff/matchers/hash_matcher.rb +258 -0
  105. data/lib/canon/tree_diff/matchers/similarity_matcher.rb +168 -0
  106. data/lib/canon/tree_diff/matchers/structural_propagator.rb +242 -0
  107. data/lib/canon/tree_diff/matchers/universal_matcher.rb +220 -0
  108. data/lib/canon/tree_diff/operation_converter.rb +631 -0
  109. data/lib/canon/tree_diff/operations/operation.rb +92 -0
  110. data/lib/canon/tree_diff/operations/operation_detector.rb +626 -0
  111. data/lib/canon/tree_diff/tree_diff_integrator.rb +140 -0
  112. data/lib/canon/tree_diff.rb +33 -0
  113. data/lib/canon/validators/json_validator.rb +3 -1
  114. data/lib/canon/validators/yaml_validator.rb +3 -1
  115. data/lib/canon/version.rb +1 -1
  116. data/lib/canon/xml/data_model.rb +22 -23
  117. data/lib/canon/xml/element_matcher.rb +128 -20
  118. data/lib/canon/xml/namespace_helper.rb +110 -0
  119. data/lib/canon.rb +3 -0
  120. metadata +81 -23
  121. data/_config.yml +0 -116
  122. data/docs/ADVANCED_TOPICS.adoc +0 -20
  123. data/docs/BASIC_USAGE.adoc +0 -16
  124. data/docs/CUSTOMIZING_BEHAVIOR.adoc +0 -19
  125. data/docs/DIFF_ARCHITECTURE.adoc +0 -435
  126. data/docs/DIFF_FORMATTING.adoc +0 -540
  127. data/docs/FORMATS.adoc +0 -447
  128. data/docs/INPUT_VALIDATION.adoc +0 -477
  129. data/docs/MATCH_ARCHITECTURE.adoc +0 -463
  130. data/docs/MATCH_OPTIONS.adoc +0 -719
  131. data/docs/MODES.adoc +0 -432
  132. data/docs/NORMATIVE_INFORMATIVE_DIFFS.adoc +0 -219
  133. data/docs/OPTIONS.adoc +0 -1387
  134. data/docs/PREPROCESSING.adoc +0 -491
  135. data/docs/SEMANTIC_DIFF_REPORT.adoc +0 -528
  136. 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
- layout: default
3
- title: Verbose Mode
4
- nav_order: 40
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
- == General
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
- * **Semantic Diff Report**: Always shown in verbose mode - provides
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
- This progressive disclosure ensures developers get useful information by
22
- default, with additional debugging details available when needed.
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 VERBOSE MODE OUTPUT ARCHITECTURE
31
+ ║ CANON DIFF OUTPUT ARCHITECTURE
32
32
  ╚═════════════════════════════════════════════════════════════════════╝
33
33
 
34
- When verbose: true is used:
34
+ When files differ:
35
35
 
36
36
  ┌─────────────────────────────────────────────────────────────────────┐
37
- │ TIER 1: CANON VERBOSE Tables (ONLY if CANON_VERBOSE=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 (ALWAYS if diffs exist)
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 --by-line flag)
76
- │ • Object tree diff (for XML/JSON/YAML by default)
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()` method orchestrates the
83
- output:
83
+ The `DiffCommand` and `DiffFormatter.format_comparison_result()` orchestrate output:
84
84
 
85
- . Check if `CANON_VERBOSE=1` Render option tables
86
- . Check if differences exist Render Semantic Diff Report
87
- . Always render detailed diff (by-line or by-object)
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
- === General
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
- === General
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 (innormative, won't fail test)
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