Module: Canon::Comparison::MatchOptions

Defined in:
lib/canon/comparison/match_options.rb,
lib/canon/comparison/match_options/xml_resolver.rb,
lib/canon/comparison/match_options/base_resolver.rb,
lib/canon/comparison/match_options/json_resolver.rb,
lib/canon/comparison/match_options/yaml_resolver.rb

Overview

Module containing match option utilities and format-specific modules

Defined Under Namespace

Modules: Json, Xml, Yaml Classes: BaseResolver, JsonResolver, XmlResolver, YamlResolver

Constant Summary collapse

PREPROCESSING_OPTIONS =

Preprocessing options - what to do before comparison

%i[none c14n normalize format rendered].freeze
MATCH_BEHAVIORS =

Matching behaviors (deprecated - use per-dimension validation instead) This universal constant is kept for backward compatibility but should not be used for validation. Use BaseResolver.dimension_behaviors instead. Note: :strip and :compact are only valid for attribute_values dimension.

%i[strict strip compact normalize ignore].freeze
ASCII_WHITESPACE_ONLY =

Fast form of normalize_text(text).empty?, called per text node by node_excluded?. Pure-ASCII whitespace (the common case — pretty-print indentation) matches a plain class with no intermediate strings and no \p{} property (Opal's JS regexes do not honor \pSpace); a pure-ASCII miss is conclusively non-whitespace; only non-ASCII text falls back to normalize_text's exact Unicode semantics. NUL is included because String#strip strips nulls too.

/\A[ \t\r\n\v\f\x00]*\z/
ASCII_ONLY =
/\A[\x00-\x7f]*\z/

Class Method Summary collapse

Class Method Details

.match_text?(text1, text2, behavior, whitespace_type: :strict) ⇒ Boolean

Apply match behavior to text comparison

Parameters:

  • text1 (String)

    First text

  • text2 (String)

    Second text

  • behavior (Symbol)

    Match behavior (:strict, :normalize, :ignore)

  • whitespace_type (Symbol) (defaults to: :strict)

    Whitespace type handling (:strict, :normalize)

Returns:

  • (Boolean)

    true if texts match according to behavior



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/canon/comparison/match_options.rb', line 68

def match_text?(text1, text2, behavior, whitespace_type: :strict)
  case behavior
  when :strict
    text1 == text2
  when :normalize
    # Identical strings normalize identically — skip the two
    # gsub+strip chains.
    return true if text1 == text2

    if whitespace_type == :normalize
      normalize_text(text1) == normalize_text(text2)
    else
      normalize_text_preserving_type(text1) == normalize_text_preserving_type(text2)
    end
  when :ignore
    true
  else
    raise Canon::Error, "Unknown match behavior: #{behavior}"
  end
end

.normalize_text(text) ⇒ Object

Normalize text by collapsing whitespace and trimming Mimics HTML whitespace collapsing



91
92
93
94
95
96
97
# File 'lib/canon/comparison/match_options.rb', line 91

def normalize_text(text)
  return "" if text.nil?

  text.to_s
    .gsub(/[\p{Space} ]+/, " ") # Collapse all whitespace to single space
    .strip # Remove leading/trailing whitespace
end

.normalize_text_preserving_type(text) ⇒ Object

Normalize text preserving Unicode whitespace type distinctions.



127
128
129
130
131
132
133
# File 'lib/canon/comparison/match_options.rb', line 127

def normalize_text_preserving_type(text)
  return "" if text.nil?

  text.to_s
    .gsub(/[ \t\r\n\f\v]+/, " ") # Collapse only ASCII whitespace
    .strip
end

.process_attribute_value(value, behavior) ⇒ Object

Process attribute value according to match behavior



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/canon/comparison/match_options.rb', line 136

def process_attribute_value(value, behavior)
  case behavior
  when :strict
    value.to_s
  when :strip
    value.to_s.strip
  when :compact
    value.to_s.gsub(/[\p{Space} ]+/, " ")
  when :normalize
    normalize_text(value)
  when :ignore
    ""
  else
    raise Canon::Error, "Unknown attribute value behavior: #{behavior}"
  end
end

.whitespace_only?(text) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/canon/comparison/match_options.rb', line 110

def whitespace_only?(text)
  text = text.to_s
  return true if text.empty?
  return true if text.match?(ASCII_WHITESPACE_ONLY)
  # A pure-ASCII string that failed the class contains an ASCII
  # non-whitespace character, which survives both the collapse
  # and the strip — conclusively not whitespace-only, with no
  # intermediate strings. Only non-ASCII text (NBSP, U+3000,
  # ...) needs normalize_text's exact Unicode semantics — and
  # no \p{} classes appear in the fast paths, which Opal's JS
  # regexes would not honor anyway.
  return false if text.match?(ASCII_ONLY)

  normalize_text(text).empty?
end