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
@@ -1,8 +1,9 @@
1
1
  ---
2
2
  layout: default
3
3
  title: RSpec Matchers
4
- nav_order: 12
5
- parent: Basic Usage
4
+ parent: Interfaces
5
+ nav_order: 3
6
+ has_children: true
6
7
  ---
7
8
  = Canon RSpec matchers
8
9
  :toc:
@@ -14,9 +15,9 @@ This document describes how to use Canon's RSpec matchers for testing. Canon
14
15
  provides semantic comparison matchers that focus on content rather than
15
16
  formatting.
16
17
 
17
- For Ruby API usage, see link:RUBY_API[Ruby API documentation].
18
+ For Ruby API usage, see link:../ruby-api/[Ruby API documentation].
18
19
 
19
- For command-line usage, see link:CLI[CLI documentation].
20
+ For command-line usage, see link:../cli/[CLI documentation].
20
21
 
21
22
  == General
22
23
 
@@ -147,7 +148,7 @@ end
147
148
 
148
149
  Available profiles: `:strict`, `:rendered`, `:spec_friendly`, `:content_only`
149
150
 
150
- See link:MATCH_OPTIONS[Match options] for profile details.
151
+ See link:../../features/match-options/[Match options] for profile details.
151
152
  ====
152
153
 
153
154
  .Match dimension options
@@ -175,7 +176,7 @@ Canon::RSpecMatchers.configure do |config|
175
176
  end
176
177
  ----
177
178
 
178
- See link:MATCH_OPTIONS[Match options] for dimension reference.
179
+ See link:../../features/match-options/[Match options] for dimension reference.
179
180
  ====
180
181
 
181
182
  === Diff configuration
@@ -200,7 +201,7 @@ Canon::RSpecMatchers.configure do |config|
200
201
  end
201
202
  ----
202
203
 
203
- See link:MODES[Diff modes] for mode details.
204
+ See link:../../understanding/diff-modes/[Diff modes] for mode details.
204
205
  ====
205
206
 
206
207
  .Diff formatting
@@ -221,7 +222,7 @@ Canon::RSpecMatchers.configure do |config|
221
222
  end
222
223
  ----
223
224
 
224
- See link:DIFF_FORMATTING[Diff formatting] for options.
225
+ See link:../../features/diff-formatting/[Diff formatting] for options.
225
226
  ====
226
227
 
227
228
  === Complete configuration example
@@ -339,7 +340,7 @@ end
339
340
  ----
340
341
  ====
341
342
 
342
- == Verbose output
343
+ === Verbose output
343
344
 
344
345
  Use `verbose: true` to show detailed diff output on test failures.
345
346
 
@@ -371,14 +372,238 @@ end
371
372
  ----
372
373
  ====
373
374
 
375
+ === Display filtering
376
+
377
+ Use `.show_diffs()` to control which differences appear in failure output.
378
+
379
+ .Display filtering modes
380
+ [example]
381
+ ====
382
+ [source,ruby]
383
+ ----
384
+ RSpec.describe 'Display filtering' do
385
+ it 'shows all differences (default)' do
386
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml)
387
+ .show_diffs(:all)
388
+ end
389
+
390
+ it 'shows only normative differences' do
391
+ # Only show differences that affect equivalence
392
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml)
393
+ .show_diffs(:normative)
394
+ end
395
+
396
+ it 'shows only informative differences' do
397
+ # Only show differences that don't affect equivalence
398
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml,
399
+ match: { comments: :ignore }
400
+ ).show_diffs(:informative)
401
+ end
402
+ end
403
+ ----
404
+ ====
405
+
406
+ .Combining with match options
407
+ [example]
408
+ ====
409
+ [source,ruby]
410
+ ----
411
+ RSpec.describe 'Combined filtering' do
412
+ it 'ignores comments but shows only normative diffs' do
413
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml)
414
+ .with_options(comments: :ignore)
415
+ .show_diffs(:normative)
416
+ end
417
+
418
+ it 'uses spec_friendly profile with normative filtering' do
419
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml)
420
+ .with_profile(:spec_friendly)
421
+ .show_diffs(:normative)
422
+ end
423
+ end
424
+ ----
425
+ ====
426
+
427
+ IMPORTANT: Display filtering does NOT affect equivalence determination. It
428
+ only controls which differences appear in the failure output. Equivalence is
429
+ always based on normative differences only.
430
+
431
+ See link:../../features/diff-formatting/display-filtering.adoc[Display
432
+ filtering] for complete details.
433
+
434
+ == Diff algorithms
435
+
436
+ Canon supports two diff algorithms that can be selected based on your needs:
437
+
438
+ * **`:dom`** (default): Positional, DOM-based matching
439
+ * **`:semantic`**: Tree-based matching with operation detection
440
+
441
+ === DOM algorithm
442
+
443
+ The DOM algorithm performs positional matching and is the default behavior:
444
+
445
+ .DOM algorithm usage
446
+ [example]
447
+ ====
448
+ [source,ruby]
449
+ ----
450
+ RSpec.describe 'DOM algorithm' do
451
+ it 'uses positional matching by default' do
452
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml)
453
+ end
454
+
455
+ it 'explicitly specifies DOM algorithm' do
456
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml,
457
+ diff_algorithm: :dom,
458
+ verbose: true
459
+ )
460
+ end
461
+ end
462
+ ----
463
+ ====
464
+
465
+ === Semantic algorithm
466
+
467
+ The semantic algorithm uses tree-based matching and detects operations like
468
+ insert, delete, update, move, merge, and split:
469
+
470
+ .Semantic algorithm usage
471
+ [example]
472
+ ====
473
+ [source,ruby]
474
+ ----
475
+ RSpec.describe 'Semantic algorithm' do
476
+ it 'detects semantic operations' do
477
+ xml1 = '<root><a>1</a><b>2</b></root>'
478
+ xml2 = '<root><b>2</b><a>1</a><c>3</c></root>'
479
+
480
+ expect(xml1).to be_xml_equivalent_to(xml2,
481
+ diff_algorithm: :semantic,
482
+ verbose: true
483
+ )
484
+ end
485
+
486
+ it 'identifies element moves' do
487
+ html1 = '<div><p>First</p><p>Second</p></div>'
488
+ html2 = '<div><p>Second</p><p>First</p></div>'
489
+
490
+ expect(html1).to be_html_equivalent_to(html2,
491
+ diff_algorithm: :semantic,
492
+ verbose: true
493
+ )
494
+ end
495
+
496
+ it 'detects insertions and deletions' do
497
+ json1 = '{"users": [{"id": 1}, {"id": 2}]}'
498
+ json2 = '{"users": [{"id": 1}, {"id": 2}, {"id": 3}]}'
499
+
500
+ expect(json1).to be_json_equivalent_to(json2,
501
+ diff_algorithm: :semantic,
502
+ verbose: true
503
+ )
504
+ end
505
+ end
506
+ ----
507
+ ====
508
+
509
+ === Global algorithm configuration
510
+
511
+ Configure the diff algorithm globally:
512
+
513
+ .Global diff algorithm configuration
514
+ [example]
515
+ ====
516
+ [source,ruby]
517
+ ----
518
+ # spec_helper.rb
519
+ Canon::RSpecMatchers.configure do |config|
520
+ # Use semantic algorithm for XML by default
521
+ config.xml.diff.algorithm = :semantic
522
+
523
+ # Use DOM algorithm for HTML (default)
524
+ config.html.diff.algorithm = :dom
525
+
526
+ # Use semantic algorithm for JSON
527
+ config.json.diff.algorithm = :semantic
528
+ end
529
+ ----
530
+ ====
531
+
532
+ === Per-test algorithm override
533
+
534
+ Override the global algorithm configuration for specific tests:
535
+
536
+ .Per-test algorithm override
537
+ [example]
538
+ ====
539
+ [source,ruby]
540
+ ----
541
+ RSpec.describe 'Algorithm override' do
542
+ # Global config uses :semantic
543
+ # But this test uses :dom
544
+ it 'uses DOM algorithm for this specific test' do
545
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml,
546
+ diff_algorithm: :dom,
547
+ verbose: true
548
+ )
549
+ end
550
+
551
+ # Global config uses :dom
552
+ # But this test uses :semantic
553
+ it 'uses semantic algorithm to detect operations' do
554
+ expect(actual_html).to be_html_equivalent_to(expected_html,
555
+ diff_algorithm: :semantic,
556
+ verbose: true
557
+ )
558
+ end
559
+ end
560
+ ----
561
+ ====
562
+
563
+ === Combining algorithm with other options
564
+
565
+ The diff algorithm can be combined with match profiles and options:
566
+
567
+ .Algorithm with profiles and options
568
+ [example]
569
+ ----
570
+ RSpec.describe 'Combined configuration' do
571
+ it 'uses semantic algorithm with spec_friendly profile' do
572
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml,
573
+ diff_algorithm: :semantic,
574
+ verbose: true
575
+ )
576
+ .with_profile(:spec_friendly)
577
+ end
578
+
579
+ it 'uses semantic algorithm with custom match options' do
580
+ expect(actual_xml).to be_xml_equivalent_to(expected_xml,
581
+ diff_algorithm: :semantic,
582
+ verbose: true
583
+ )
584
+ .with_options(
585
+ structural_whitespace: :ignore,
586
+ comments: :ignore
587
+ )
588
+ end
589
+
590
+ it 'uses DOM algorithm with strict matching' do
591
+ expect(actual_html).to be_html_equivalent_to(expected_html,
592
+ diff_algorithm: :dom,
593
+ verbose: true
594
+ )
595
+ .with_profile(:strict)
596
+ end
597
+ end
598
+ ----
599
+ ====
600
+
374
601
  == Common patterns
375
602
 
376
603
  === Testing XML generation
377
604
 
378
605
  .XML generation tests
379
606
  [example]
380
- ====
381
- [source,ruby]
382
607
  ----
383
608
  RSpec.describe 'XML generation' do
384
609
  let(:expected_xml) do
@@ -414,8 +639,6 @@ end
414
639
 
415
640
  .HTML output tests
416
641
  [example]
417
- ====
418
- [source,ruby]
419
642
  ----
420
643
  RSpec.describe 'HTML generation' do
421
644
  let(:expected_html) do
@@ -462,8 +685,6 @@ end
462
685
 
463
686
  .JSON API tests
464
687
  [example]
465
- ====
466
- [source,ruby]
467
688
  ----
468
689
  RSpec.describe 'API responses' do
469
690
  let(:expected_response) do
@@ -498,8 +719,6 @@ end
498
719
 
499
720
  .Configuration file tests
500
721
  [example]
501
- ====
502
- [source,ruby]
503
722
  ----
504
723
  RSpec.describe 'Configuration files' do
505
724
  it 'generates correct YAML config' do
@@ -538,8 +757,6 @@ detail:
538
757
 
539
758
  .Debugging example
540
759
  [example]
541
- ====
542
- [source,ruby]
543
760
  ----
544
761
  it 'shows exactly what differs' do
545
762
  expect(actual).to be_xml_equivalent_to(expected, verbose: true)
@@ -553,14 +770,12 @@ The diff output will show:
553
770
  * Color-coded changes (red/green)
554
771
  * Whitespace visualization
555
772
  * Non-ASCII character warnings
556
- ====
773
+ ----
557
774
 
558
775
  === Temporarily disabling global config
559
776
 
560
777
  .Override global config
561
778
  [example]
562
- ====
563
- [source,ruby]
564
779
  ----
565
780
  it 'uses different config for this test' do
566
781
  # Global config uses spec_friendly, but we want strict here
@@ -572,14 +787,11 @@ it 'uses different config for this test' do
572
787
  )
573
788
  end
574
789
  ----
575
- ====
576
790
 
577
791
  === Checking what's being compared
578
792
 
579
793
  .Debug preprocessed content
580
794
  [example]
581
- ====
582
- [source,ruby]
583
795
  ----
584
796
  # In your test, temporarily add:
585
797
  result = Canon::Comparison.equivalent?(actual, expected, verbose: true)
@@ -594,12 +806,11 @@ puts result[:preprocessed][1]
594
806
  puts "Differences:"
595
807
  pp result[:differences]
596
808
  ----
597
- ====
598
809
 
599
810
  == See also
600
811
 
601
- * link:RUBY_API[Ruby API documentation]
602
- * link:CLI[Command-line interface]
603
- * link:MATCH_OPTIONS[Match options reference]
604
- * link:MODES[Diff modes]
605
- * link:DIFF_FORMATTING[Diff formatting options]
812
+ * link:../ruby-api/[Ruby API documentation]
813
+ * link:../cli/[Command-line interface]
814
+ * link:../../features/match-options/[Match options reference]
815
+ * link:../../understanding/diff-modes/[Diff modes]
816
+ * link:../../features/diff-formatting/[Diff formatting options]
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  layout: default
3
3
  title: Ruby API
4
- nav_order: 10
5
- parent: Basic Usage
6
- grand_parent: Documentation Index
4
+ parent: Interfaces
5
+ nav_order: 1
6
+ has_children: true
7
7
  ---
8
8
  = Canon Ruby API
9
9
  :toc:
@@ -14,9 +14,9 @@ grand_parent: Documentation Index
14
14
  This document describes how to use Canon from Ruby code. It covers formatting,
15
15
  parsing, and comparison APIs.
16
16
 
17
- For command-line usage, see link:CLI[CLI documentation].
17
+ For command-line usage, see link:../cli/[CLI documentation].
18
18
 
19
- For RSpec testing, see link:RSPEC[RSpec documentation].
19
+ For RSpec testing, see link:../rspec/[RSpec documentation].
20
20
 
21
21
  == General
22
22
 
@@ -188,7 +188,7 @@ The comparison uses depth-first traversal of DOM trees (XML/HTML) or object
188
188
  graphs (JSON/YAML), comparing nodes/values based on configurable match
189
189
  dimensions.
190
190
 
191
- See link:MATCH_OPTIONS[Match options] for details on match dimensions and
191
+ See link:../../features/match-options/[Match options] for details on match dimensions and
192
192
  profiles.
193
193
 
194
194
  === Basic comparison
@@ -210,7 +210,14 @@ Returns:
210
210
 
211
211
  * `true` if documents are semantically equivalent
212
212
  * `false` if documents differ
213
- * `Hash` with `:differences` and `:preprocessed` keys if `verbose: true`
213
+ * `ComparisonResult` object if `verbose: true`
214
+
215
+ Options:
216
+
217
+ * `diff_algorithm`: `:dom` (default) or `:semantic` - chooses the diff algorithm
218
+ * `verbose`: `true` or `false` - returns detailed results when true
219
+ * `match`: Hash of match dimension options
220
+ * `match_profile`: Symbol specifying a predefined profile
214
221
 
215
222
  .Basic comparison examples
216
223
  [example]
@@ -262,7 +269,7 @@ Canon::Comparison.equivalent?(obj1, obj2,
262
269
  )
263
270
  ----
264
271
 
265
- See link:MATCH_OPTIONS[Match options] for complete dimension reference.
272
+ See link:../../features/match-options/[Match options] for complete dimension reference.
266
273
 
267
274
  .Match option examples
268
275
  [example]
@@ -398,6 +405,103 @@ result = Canon::Comparison.equivalent?(xml1, xml2,
398
405
  ----
399
406
  ====
400
407
 
408
+ === Display filtering
409
+
410
+ Use the `show_diffs` parameter to control which differences appear in formatted
411
+ output.
412
+
413
+ Syntax:
414
+
415
+ [source,ruby]
416
+ ----
417
+ Canon::Comparison.equivalent?(obj1, obj2,
418
+ verbose: true,
419
+ show_diffs: :mode
420
+ )
421
+ ----
422
+
423
+ Where `mode` is one of:
424
+
425
+ `:all`:: Show all differences (default)
426
+ `:normative`:: Show only differences that affect equivalence
427
+ `:informative`:: Show only differences that don't affect equivalence
428
+
429
+ .Display filtering examples
430
+ [example]
431
+ ====
432
+ [source,ruby]
433
+ ----
434
+ # Show all differences (default)
435
+ result = Canon::Comparison.equivalent?(xml1, xml2,
436
+ verbose: true,
437
+ show_diffs: :all
438
+ )
439
+
440
+ # Show only normative differences
441
+ result = Canon::Comparison.equivalent?(xml1, xml2,
442
+ verbose: true,
443
+ match: { comments: :ignore },
444
+ show_diffs: :normative
445
+ )
446
+
447
+ # Show only informative differences
448
+ result = Canon::Comparison.equivalent?(xml1, xml2,
449
+ verbose: true,
450
+ match: { comments: :ignore },
451
+ show_diffs: :informative
452
+ )
453
+
454
+ # Use with DiffFormatter directly
455
+ formatter = Canon::DiffFormatter.new(
456
+ use_color: true,
457
+ mode: :by_object,
458
+ show_diffs: :normative
459
+ )
460
+ output = formatter.format(result, :xml)
461
+ ----
462
+ ====
463
+
464
+ IMPORTANT: Display filtering does NOT affect equivalence determination. It
465
+ only controls which differences appear in formatted output. Equivalence is
466
+ always based on normative differences only, regardless of the `show_diffs`
467
+ setting.
468
+
469
+ .Common use case: XML comments
470
+ [example]
471
+ ====
472
+ [source,ruby]
473
+ ----
474
+ xml1 = <<~XML
475
+ <root>
476
+ <!-- Old comment -->
477
+ <element>value1</element>
478
+ </root>
479
+ XML
480
+
481
+ xml2 = <<~XML
482
+ <root>
483
+ <!-- New comment -->
484
+ <element>value2</element>
485
+ </root>
486
+ XML
487
+
488
+ # With comments: :ignore and show_diffs: :normative
489
+ result = Canon::Comparison.equivalent?(xml1, xml2,
490
+ verbose: true,
491
+ match: { comments: :ignore },
492
+ show_diffs: :normative
493
+ )
494
+
495
+ # Result:
496
+ # - equivalent? => false (element value differs)
497
+ # - Diff output shows: only the element value change
498
+ # - Diff output hides: comment differences (informative)
499
+ ----
500
+ ====
501
+
502
+ See link:../../features/diff-formatting/display-filtering.adoc[Display
503
+ filtering] for complete details.
504
+
401
505
  === Format-specific comparators
402
506
 
403
507
  You can use format-specific comparator classes directly.
@@ -414,8 +518,6 @@ Canon::Comparison::YamlComparator.equivalent?(obj1, obj2, options)
414
518
 
415
519
  .Format-specific comparator examples
416
520
  [example]
417
- ====
418
- [source,ruby]
419
521
  ----
420
522
  # XML comparison with strict attribute order
421
523
  Canon::Comparison::XmlComparator.equivalent?(xml1, xml2,
@@ -467,12 +569,12 @@ end
467
569
  ----
468
570
  ====
469
571
 
470
- See link:INPUT_VALIDATION[Input validation] for details.
572
+ See link:../../features/input-validation/[Input validation] for details.
471
573
 
472
574
  == See also
473
575
 
474
- * link:CLI[Command-line interface]
475
- * link:RSPEC[RSpec matchers]
476
- * link:MATCH_OPTIONS[Match options reference]
477
- * link:FORMATS[Format support details]
478
- * link:INPUT_VALIDATION[Input validation]
576
+ * link:../cli/[Command-line interface]
577
+ * link:../rspec/[RSpec matchers]
578
+ * link:../../features/match-options/[Match options reference]
579
+ * link:../../understanding/formats/[Format support details]
580
+ * link:../../features/input-validation/[Input validation]
data/docs/lychee.toml ADDED
@@ -0,0 +1,65 @@
1
+ # Lychee Link Checker Configuration
2
+ # For Canon Documentation
3
+ # https://github.com/lycheeverse/lychee
4
+
5
+ # Cache results to avoid re-checking same URLs
6
+ cache = true
7
+ max_cache_age = "1d"
8
+
9
+ # Check both source files and built site
10
+ include_verbatim = true
11
+
12
+ # Recursively check all files
13
+ recursive = true
14
+
15
+ # File types to check
16
+ include = [
17
+ "_site/**/*.html"
18
+ ]
19
+
20
+ # Excluded paths
21
+ exclude = [
22
+ ".git",
23
+ ".github",
24
+ "node_modules",
25
+ "vendor",
26
+ ".bundle",
27
+ ".sass-cache",
28
+ ".jekyll-cache"
29
+ ]
30
+
31
+ # Link checking behavior
32
+ max_redirects = 10
33
+ max_retries = 3
34
+ timeout = 30
35
+
36
+ # Accept status codes
37
+ accept = [
38
+ "100..=103", # Informational
39
+ "200..=299", # Success
40
+ "429" # Too Many Requests (retry handled by max_retries)
41
+ ]
42
+
43
+ # User agent to identify ourselves
44
+ user_agent = "lychee/canon-docs-link-checker"
45
+
46
+ # Check HTTP, HTTPS, and file:// schemes
47
+ scheme = ["https", "http", "file"]
48
+
49
+ # Include file:// URLs for local link checking
50
+ include_file = true
51
+
52
+ # Handle different link types
53
+ include_mail = false # Don't check mailto: links
54
+
55
+ # Maximum concurrent requests
56
+ max_concurrency = 10
57
+
58
+ # Verbose output for debugging
59
+ verbose = "info"
60
+
61
+ # Require HTTPS where possible
62
+ require_https = false # Don't enforce
63
+
64
+ # Index files
65
+ index_files = ["index.html"]