Module: Canon::DiffFormatter::DiffDetailFormatter

Defined in:
lib/canon/diff_formatter/diff_detail_formatter.rb

Overview

Formats dimension-specific detail for individual differences Provides actionable, colorized output showing exactly what changed

Constant Summary collapse

ANSI_ESCAPE =
/\e\[[0-9;]*m/
COMPACT_DETAIL_MAX =
30

Class Method Summary collapse

Class Method Details

.format_report(differences, use_color: true, show_diffs: :all, compact_semantic_report: false, expand_difference: false) ⇒ String

Format all differences as a semantic diff report

Parameters:

  • differences (Array<DiffNode>)

    Array of differences

  • use_color (Boolean) (defaults to: true)

    Whether to use colors

  • show_diffs (Symbol) (defaults to: :all)

    Filter: :all (default), :normative, :informative

  • compact_semantic_report (Boolean) (defaults to: false)

    When true, serialize element nodes as compact XML (e.g. <strong>Annex</strong>) instead of the verbose node_info description (e.g. “name: strong namespace_uri: …”)

Returns:

  • (String)

    Formatted semantic diff report



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/canon/diff_formatter/diff_detail_formatter.rb', line 30

def format_report(differences, use_color: true, show_diffs: :all,
                  compact_semantic_report: false,
                  expand_difference: false)
  return "" if differences.empty?

  # Group differences by normative status
  normative = differences.select do |diff|
    diff.respond_to?(:normative?) ? diff.normative? : true
  end
  informative = differences.select do |diff|
    diff.respond_to?(:normative?) && !diff.normative?
  end

  # Apply show_diffs filter — same semantics as the line-diff filter
  show_normative   = show_diffs != :informative
  show_informative = show_diffs != :normative

  output = []
  output << ""
  output << colorize("=" * 70, :cyan, use_color, bold: true)
  output << colorize(
    "  SEMANTIC DIFF REPORT (#{differences.length} #{differences.length == 1 ? 'difference' : 'differences'})", :cyan, use_color, bold: true
  )
  output << colorize("=" * 70, :cyan, use_color, bold: true)

  # Show normative differences first
  if normative.any? && show_normative
    output << ""
    output << colorize(
      "┌─ NORMATIVE DIFFERENCES (#{normative.length}) ─┐", :green, use_color, bold: true
    )

    normative.each_with_index do |diff, i|
      output << ""
      output << format_single_diff(diff, i + 1, normative.length,
                                   use_color, section: "NORMATIVE",
                                              compact: compact_semantic_report,
                                              expand_difference: expand_difference)
    end
  end

  # Show informative differences second
  if informative.any? && show_informative
    output << ""
    output << ""
    output << colorize(
      "┌─ INFORMATIVE DIFFERENCES (#{informative.length}) ─┐", :yellow, use_color, bold: true
    )

    informative.each_with_index do |diff, i|
      output << ""
      output << format_single_diff(diff, i + 1, informative.length,
                                   use_color, section: "INFORMATIVE",
                                              compact: compact_semantic_report,
                                              expand_difference: expand_difference)
    end
  end

  output << ""
  output << colorize("=" * 70, :cyan, use_color, bold: true)
  output << ""

  output.join("\n")
end