canon 0.2.8 → 0.2.9

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec-opal +7 -0
  3. data/.rubocop_todo.yml +14 -71
  4. data/Rakefile +17 -0
  5. data/lib/canon/cli.rb +1 -1
  6. data/lib/canon/color_detector.rb +3 -5
  7. data/lib/canon/comparison/compare_profile.rb +1 -4
  8. data/lib/canon/comparison/dimensions/attribute_order_dimension.rb +2 -6
  9. data/lib/canon/comparison/dimensions/attribute_presence_dimension.rb +2 -6
  10. data/lib/canon/comparison/dimensions/attribute_values_dimension.rb +2 -6
  11. data/lib/canon/comparison/dimensions/comments_dimension.rb +2 -6
  12. data/lib/canon/comparison/dimensions/element_position_dimension.rb +2 -6
  13. data/lib/canon/comparison/dimensions/structural_whitespace_dimension.rb +2 -6
  14. data/lib/canon/comparison/dimensions/text_content_dimension.rb +3 -5
  15. data/lib/canon/comparison/format_detector.rb +29 -20
  16. data/lib/canon/comparison/html_comparator.rb +18 -29
  17. data/lib/canon/comparison/html_compare_profile.rb +3 -10
  18. data/lib/canon/comparison/html_parser.rb +1 -1
  19. data/lib/canon/comparison/json_comparator.rb +8 -0
  20. data/lib/canon/comparison/node_inspector.rb +146 -80
  21. data/lib/canon/comparison/strategies/semantic_tree_match_strategy.rb +6 -8
  22. data/lib/canon/comparison/whitespace_sensitivity.rb +55 -193
  23. data/lib/canon/comparison/xml_comparator/attribute_filter.rb +5 -10
  24. data/lib/canon/comparison/xml_comparator/child_comparison.rb +4 -4
  25. data/lib/canon/comparison/xml_comparator/diff_node_builder.rb +10 -8
  26. data/lib/canon/comparison/xml_comparator/namespace_comparator.rb +14 -28
  27. data/lib/canon/comparison/xml_comparator/node_parser.rb +12 -11
  28. data/lib/canon/comparison/xml_comparator/node_type_comparator.rb +30 -58
  29. data/lib/canon/comparison/xml_comparator.rb +61 -83
  30. data/lib/canon/comparison/xml_node_comparison.rb +15 -15
  31. data/lib/canon/comparison/yaml_comparator.rb +8 -0
  32. data/lib/canon/comparison.rb +23 -23
  33. data/lib/canon/config/profile_loader.rb +13 -13
  34. data/lib/canon/config.rb +29 -5
  35. data/lib/canon/diff/diff_classifier.rb +7 -41
  36. data/lib/canon/diff/diff_line.rb +1 -1
  37. data/lib/canon/diff/diff_node_enricher.rb +22 -24
  38. data/lib/canon/diff/node_serializer.rb +23 -30
  39. data/lib/canon/diff/path_builder.rb +24 -37
  40. data/lib/canon/diff/source_locator.rb +0 -3
  41. data/lib/canon/diff/xml_serialization_formatter.rb +8 -81
  42. data/lib/canon/diff_formatter/by_line/base_formatter.rb +7 -7
  43. data/lib/canon/diff_formatter/by_line/json_formatter.rb +1 -1
  44. data/lib/canon/diff_formatter/by_line/simple_formatter.rb +1 -1
  45. data/lib/canon/diff_formatter/by_line/xml_formatter.rb +2 -2
  46. data/lib/canon/diff_formatter/by_line/yaml_formatter.rb +1 -1
  47. data/lib/canon/diff_formatter/by_line_formatter.rb +1 -1
  48. data/lib/canon/diff_formatter/by_object/base_formatter.rb +11 -15
  49. data/lib/canon/diff_formatter/by_object/xml_formatter.rb +8 -10
  50. data/lib/canon/diff_formatter/by_object_formatter.rb +1 -1
  51. data/lib/canon/diff_formatter/debug_output.rb +12 -24
  52. data/lib/canon/diff_formatter/diff_detail_formatter/color_helper.rb +2 -2
  53. data/lib/canon/diff_formatter/diff_detail_formatter/node_utils.rb +146 -318
  54. data/lib/canon/diff_formatter/diff_detail_formatter.rb +28 -20
  55. data/lib/canon/diff_formatter/legend.rb +2 -2
  56. data/lib/canon/diff_formatter/pretty_diff_formatter.rb +2 -2
  57. data/lib/canon/diff_formatter/theme.rb +4 -4
  58. data/lib/canon/diff_formatter.rb +2 -2
  59. data/lib/canon/formatters/html_formatter.rb +1 -1
  60. data/lib/canon/formatters/html_formatter_base.rb +1 -1
  61. data/lib/canon/formatters/xml_formatter.rb +7 -32
  62. data/lib/canon/html/data_model.rb +1 -1
  63. data/lib/canon/pretty_printer/html.rb +1 -1
  64. data/lib/canon/pretty_printer/xml.rb +16 -7
  65. data/lib/canon/pretty_printer/xml_normalized.rb +9 -3
  66. data/lib/canon/rspec_matchers.rb +2 -2
  67. data/lib/canon/tree_diff/adapters/html_adapter.rb +1 -1
  68. data/lib/canon/tree_diff/adapters/xml_adapter.rb +1 -1
  69. data/lib/canon/tree_diff/core/tree_node.rb +1 -3
  70. data/lib/canon/validators/html_validator.rb +1 -1
  71. data/lib/canon/validators/xml_validator.rb +1 -1
  72. data/lib/canon/version.rb +1 -1
  73. data/lib/canon/xml/data_model.rb +131 -137
  74. data/lib/canon/xml/namespace_helper.rb +5 -0
  75. data/lib/canon/xml/node.rb +2 -1
  76. data/lib/canon/xml/nodes/root_node.rb +4 -0
  77. data/lib/canon/xml/nodes/text_node.rb +6 -1
  78. data/lib/canon/xml/sax_builder.rb +4 -6
  79. data/lib/canon/xml_backend.rb +49 -0
  80. data/lib/canon/xml_parsing.rb +271 -0
  81. data/lib/canon.rb +3 -1
  82. data/lib/tasks/benchmark_runner.rb +1 -1
  83. data/lib/tasks/performance_helpers.rb +1 -1
  84. metadata +5 -2
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "unicode/name"
3
+ require "unicode/name" unless RUBY_ENGINE == "opal"
4
4
 
5
5
  module Canon
6
6
  class DiffFormatter
@@ -175,7 +175,7 @@ module Canon
175
175
 
176
176
  require "rainbow"
177
177
  presenter = Rainbow(text)
178
- colors.each { |c| presenter = presenter.send(c) }
178
+ colors.each { |c| presenter = presenter.public_send(c) }
179
179
  presenter.to_s
180
180
  end
181
181
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "paint"
4
- require "diff/lcs"
3
+ require "paint" unless RUBY_ENGINE == "opal"
4
+ require "diff/lcs" unless RUBY_ENGINE == "opal"
5
5
 
6
6
  module Canon
7
7
  class DiffFormatter
@@ -797,19 +797,19 @@ _invalid_values)
797
797
  return env_theme if env_theme
798
798
 
799
799
  # Check config theme_inheritance (custom theme with base + overrides)
800
- if @config.respond_to?(:xml) && @config.xml.diff.respond_to?(:theme_inheritance)
800
+ if @config.is_a?(Canon::Config)
801
801
  inheritance = @config.xml.diff.theme_inheritance
802
802
  return resolve_inheritance_theme(inheritance) if inheritance
803
803
  end
804
804
 
805
805
  # Check config custom_theme (full custom theme hash)
806
- if @config.respond_to?(:xml) && @config.xml.diff.respond_to?(:custom_theme)
806
+ if @config.is_a?(Canon::Config)
807
807
  custom = @config.xml.diff.custom_theme
808
808
  return custom if custom.is_a?(Hash) && !custom.empty?
809
809
  end
810
810
 
811
811
  # Check config theme name
812
- if @config.respond_to?(:xml) && @config.xml.diff.respond_to?(:theme)
812
+ if @config.is_a?(Canon::Config)
813
813
  theme_name = @config.xml.diff.theme
814
814
  return Theme[theme_name] if Theme.include?(theme_name)
815
815
  end
@@ -826,7 +826,7 @@ _invalid_values)
826
826
  return env_name if env_name && Theme.include?(env_name)
827
827
 
828
828
  # Check config
829
- if @config.respond_to?(:xml) && @config.xml.diff.respond_to?(:theme)
829
+ if @config.is_a?(Canon::Config)
830
830
  theme_name = @config.xml.diff.theme
831
831
  return theme_name if Theme.include?(theme_name)
832
832
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "paint"
3
+ require "paint" unless RUBY_ENGINE == "opal"
4
4
  require "yaml"
5
5
  require_relative "comparison"
6
6
  require_relative "diff/diff_block"
@@ -326,7 +326,7 @@ module Canon
326
326
  return pretty_diff_formatter.format(d1, d2, format: format)
327
327
  end
328
328
 
329
- no_diffs = if differences.respond_to?(:equivalent?)
329
+ no_diffs = if differences.is_a?(Canon::Comparison::ComparisonResult)
330
330
  differences.equivalent?
331
331
  else
332
332
  differences.empty?
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require_relative "html_formatter_base"
5
5
  require_relative "../pretty_printer/html"
6
6
  require_relative "../validators/html_validator"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
 
5
5
  module Canon
6
6
  module Formatters
@@ -1,39 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
+ require_relative "../xml_backend"
4
5
  require_relative "../xml/c14n"
5
6
  require_relative "../pretty_printer/xml"
6
7
  require_relative "../validators/xml_validator"
7
8
 
8
9
  module Canon
9
10
  module Formatters
10
- # XML formatter using Canonical XML 1.1 or pretty printing
11
- #
12
- # Use this class for formatting XML documents for display or storage.
13
- # For semantic comparison of XML documents, use Canon::Comparison instead.
14
- #
15
- # == XML Declaration Handling
16
- #
17
- # - Pretty printing (default): Preserves XML declaration
18
- # - Canonicalization: Removes XML declaration (per W3C C14N 1.1 spec)
19
- #
20
- # == Usage
21
- #
22
- # # Pretty print (preserves declaration)
23
- # Canon.format_xml(xml)
24
- #
25
- # # Canonicalize (removes declaration)
26
- # Canon.format(xml, :xml, pretty: false)
27
- #
28
- # For comparison, use:
29
- # Canon::Comparison.equivalent?(xml1, xml2, format: :xml)
30
- #
31
11
  class XmlFormatter
32
- # Format XML with pretty printing by default
33
- # @param xml [String] XML document to format
34
- # @param pretty [Boolean] Whether to pretty print (default: true)
35
- # @param indent [Integer] Number of spaces for indentation (default: 2)
36
- # @return [String] Formatted XML
37
12
  def self.format(xml, pretty: true, indent: 2)
38
13
  if pretty
39
14
  Canon::PrettyPrinter::Xml.new(indent: indent).format(xml)
@@ -42,13 +17,13 @@ module Canon
42
17
  end
43
18
  end
44
19
 
45
- # Parse XML into a Nokogiri document
46
- # @param xml [String] XML document to parse
47
- # @return [Nokogiri::XML::Document] Parsed XML document
48
20
  def self.parse(xml)
49
- # Validate before parsing
50
21
  Canon::Validators::XmlValidator.validate!(xml)
51
- Nokogiri::XML(xml)
22
+ if XmlBackend.nokogiri?
23
+ Nokogiri::XML(xml)
24
+ else
25
+ XmlParsing.parse(xml)
26
+ end
52
27
  end
53
28
  end
54
29
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require_relative "../data_model"
5
5
  require_relative "../xml/nodes/root_node"
6
6
  require_relative "../xml/nodes/element_node"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require "stringio"
5
5
  require_relative "html_void_elements"
6
6
 
@@ -1,29 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
 
5
5
  module Canon
6
6
  module PrettyPrinter
7
- # Pretty printer for XML with consistent indentation
8
7
  class Xml
9
8
  def initialize(indent: 2, indent_type: "space")
10
9
  @indent = indent.to_i
11
10
  @indent_type = indent_type
12
11
  end
13
12
 
14
- # Pretty print XML with consistent indentation
15
13
  def format(xml_string)
16
- doc = Nokogiri::XML(xml_string, &:noblanks)
14
+ if Canon::XmlBackend.nokogiri?
15
+ nokogiri_format(xml_string)
16
+ else
17
+ moxml_format(xml_string)
18
+ end
19
+ end
17
20
 
18
- # Use Nokogiri's built-in pretty printing
21
+ private
22
+
23
+ def nokogiri_format(xml_string)
24
+ doc = Nokogiri::XML(xml_string, &:noblanks)
19
25
  if @indent_type == "tab"
20
- # For tabs, use indent_text parameter
21
26
  doc.to_xml(indent: 1, indent_text: "\t", encoding: "UTF-8")
22
27
  else
23
- # For spaces, use indent parameter
24
28
  doc.to_xml(indent: @indent, encoding: "UTF-8")
25
29
  end
26
30
  end
31
+
32
+ def moxml_format(xml_string)
33
+ doc = Canon::XmlParsing.parse(xml_string)
34
+ doc.to_xml
35
+ end
27
36
  end
28
37
  end
29
38
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require_relative "html_void_elements"
5
5
 
6
6
  module Canon
@@ -154,7 +154,13 @@ module Canon
154
154
  # @return [String] Serialized XML, one node per line, with content
155
155
  # whitespace visualized at line boundaries
156
156
  def format(xml_string)
157
- doc = @html_mode ? Nokogiri::HTML5(xml_string) : Nokogiri::XML(xml_string)
157
+ doc = if Canon::XmlBackend.moxml?
158
+ Canon::XmlParsing.parse(xml_string)
159
+ elsif @html_mode
160
+ Nokogiri::HTML5(xml_string)
161
+ else
162
+ Nokogiri::XML(xml_string)
163
+ end
158
164
  lines = []
159
165
 
160
166
  if !@html_mode && doc.version
@@ -183,7 +189,7 @@ module Canon
183
189
  # @return [Symbol] :strict, :normalize, or :drop
184
190
  def classify_whitespace(element)
185
191
  current = element
186
- while current && !current.is_a?(Nokogiri::XML::Document)
192
+ while current && !Canon::XmlParsing.document?(current)
187
193
  name = current.name.to_s
188
194
  return :drop if @insens_ws.include?(name)
189
195
  return :strict if @strict_ws.include?(name)
@@ -177,7 +177,7 @@ module Canon
177
177
  config_format = normalize_format_for_config(@format)
178
178
 
179
179
  # Only access config if format is supported
180
- if Canon::Config.instance.respond_to?(config_format)
180
+ if %i[xml html json yaml string].include?(config_format)
181
181
  format_config = Canon::Config.instance.public_send(config_format)
182
182
  if format_config.match.profile
183
183
  opts[:global_profile] =
@@ -375,7 +375,7 @@ module Canon
375
375
  diff_algorithm: diff_algorithm)
376
376
  end
377
377
 
378
- if defined?(::RSpec) && ::RSpec.respond_to?(:configure)
378
+ if defined?(::RSpec.configure)
379
379
  RSpec.configure do |config|
380
380
  config.include(Canon::RSpecMatchers)
381
381
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
 
5
5
  module Canon
6
6
  module TreeDiff
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
 
5
5
  module Canon
6
6
  module TreeDiff
@@ -437,15 +437,13 @@ module Canon
437
437
 
438
438
  alias to_s inspect
439
439
 
440
- private
441
-
442
440
  # Invalidate cached computations
443
441
  def invalidate_cache
444
442
  @signature = nil
445
443
  @weight = nil
446
444
 
447
445
  # Propagate upward
448
- parent&.send(:invalidate_cache)
446
+ parent&.invalidate_cache
449
447
  end
450
448
  end
451
449
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require_relative "base_validator"
5
5
 
6
6
  module Canon
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "nokogiri" unless RUBY_ENGINE == "opal"
4
4
  require_relative "base_validator"
5
5
 
6
6
  module Canon
data/lib/canon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canon
4
- VERSION = "0.2.8"
4
+ VERSION = "0.2.9"
5
5
  end