Class: Canon::TreeDiff::OperationConverter

Inherits:
Object
  • Object
show all
Defined in:
lib/canon/tree_diff/operation_converter.rb

Overview

Converts TreeDiff Operations to DiffNodes for integration with Canon’s existing diff pipeline.

This class bridges the semantic tree diff system with Canon’s DOM-based diff architecture by mapping operations to match dimensions and creating DiffNode objects that can be processed by the standard diff formatter.

Examples:

Convert operations to diff nodes

converter = OperationConverter.new(format: :xml, match_options: opts)
diff_nodes = converter.convert(operations)

Constant Summary collapse

OPERATION_TO_DIMENSION =

Mapping from operation types to match dimensions

{
  insert: :element_structure,
  delete: :element_structure,
  update: :text_content, # Default, refined based on what changed
  move: :element_position,
  merge: :element_structure,
  split: :element_structure,
  upgrade: :element_hierarchy,
  downgrade: :element_hierarchy,
}.freeze
METADATA_ELEMENTS =

Metadata/presentation elements that should be treated as informative These elements don’t affect semantic equivalence

%w[
  semx fmt-concept fmt-name fmt-title fmt-xref fmt-eref
  fmt-termref fmt-element-name fmt-link autonum
  meta link base title style script
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format:, match_options: {}) ⇒ OperationConverter

Initialize converter

Parameters:

  • format (Symbol)

    Document format (:xml, :html, :json, :yaml)

  • match_options (Hash) (defaults to: {})

    Match options for determining normative/informative



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
# File 'lib/canon/tree_diff/operation_converter.rb', line 51

def initialize(format:, match_options: {})
  @format = format

  # Resolve match options using format-specific module
  match_opts_hash = case format
                    when :xml, :html, :html4, :html5
                      Canon::Comparison::MatchOptions::Xml.resolve(
                        format: format,
                        match: match_options,
                      )
                    when :json
                      Canon::Comparison::MatchOptions::Json.resolve(
                        format: format,
                        match: match_options,
                      )
                    when :yaml
                      Canon::Comparison::MatchOptions::Yaml.resolve(
                        format: format,
                        match: match_options,
                      )
                    else
                      raise ArgumentError, "Unknown format: #{format}"
                    end

  # Wrap in ResolvedMatchOptions
  @match_options = Canon::Comparison::ResolvedMatchOptions.new(
    match_opts_hash,
    format: format,
  )
end

Instance Attribute Details

#formatObject (readonly)

Returns the value of attribute format.



45
46
47
# File 'lib/canon/tree_diff/operation_converter.rb', line 45

def format
  @format
end

#match_optionsObject (readonly)

Returns the value of attribute match_options.



45
46
47
# File 'lib/canon/tree_diff/operation_converter.rb', line 45

def match_options
  @match_options
end

Instance Method Details

#convert(operations) ⇒ Array<DiffNode>

Convert array of Operations to array of DiffNodes

Parameters:

  • operations (Array<Operation>)

    Operations to convert

Returns:

  • (Array<DiffNode>)

    Converted diff nodes



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/canon/tree_diff/operation_converter.rb', line 86

def convert(operations)
  diff_nodes = operations.flat_map do |operation|
    convert_operation(operation)
  end

  # Post-process to detect attribute-order-only differences
  OperationConverterHelpers::PostProcessor.detect_attribute_order_diffs(
    diff_nodes,
    ->(dimension) { determine_normative(dimension) },
  )
end