svg_conform 0.2.1 → 0.2.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 136c672fbb6005495a240d2d8b7f30000fae008cd16fff6bfe51a74e7dbe2262
4
- data.tar.gz: 679452859b709b2e9ef78916918ea9e58040ebfb382291b8c6543b9062a5ee09
3
+ metadata.gz: b84a6929a5ff16f9cbe74d86c862a15487f5d76276972975cbd0ac9a99d027d9
4
+ data.tar.gz: ff3df290c1ce16e466f5a43527b664bb19a29af8ae80c7b8332dee172bb0c11f
5
5
  SHA512:
6
- metadata.gz: 26a32728202834b61e892d78ef87bb6bae0030e768414985cfe0bfa208da9fa21828035fe6f247225c6cd37a299dff6fe91863c70137c528d7e24a9aade3250e
7
- data.tar.gz: 47b4ba1d348244438817269403a2b5b09019687024849e691ff6fe4dcbb9d4fed1a322f132758af38f8ba1310fb0666cc5d9dbaeef93192a8edaf19df66bb1c9
6
+ metadata.gz: b7e28c31a41dd1b98b3ac98f7a97185a153d78b6303002b578a6540d7e53ffc3243777ec408feca823d4dd4395c4831630e1aed2562e64d6c4cf2595ee33baa6
7
+ data.tar.gz: 5c67c533db3ba7261c2a10998c2cd34bff00521ea43ae125fe369d5a7bea14cc3771662b8a545bba5a0f2eb427b9b25ab7fe2d35d23825e8242f40744d5f638f
@@ -1,12 +1,9 @@
1
- # Auto-generated by Cimas: Do not edit it manually!
2
- # See https://github.com/metanorma/cimas
1
+ # Trusted publishing (OIDC) release — matches lutaml-model/.github/workflows/release.yml.
2
+ # metanorma/ci switches to OIDC when the rubygems-api-key secret is omitted;
3
+ # each gem must be registered for trusted publishing on rubygems.org
4
+ # (owner=claricle, workflow=release.yml).
3
5
  name: release
4
6
 
5
- permissions:
6
- contents: write
7
- packages: write
8
- id-token: write
9
-
10
7
  on:
11
8
  workflow_dispatch:
12
9
  inputs:
@@ -18,11 +15,18 @@ on:
18
15
  repository_dispatch:
19
16
  types: [ do-release ]
20
17
 
18
+ # Least-privilege ceiling for the called rubygems-release.yml: its release job
19
+ # needs contents:write (git tag push) and id-token:write (OIDC Trusted Publishing).
20
+ permissions:
21
+ contents: write
22
+ id-token: write
23
+
24
+ concurrency:
25
+ group: release
26
+ cancel-in-progress: false
27
+
21
28
  jobs:
22
29
  release:
23
30
  uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
24
31
  with:
25
32
  next_version: ${{ github.event.inputs.next_version }}
26
- secrets:
27
- rubygems-api-key: ${{ secrets.CLARICLE_CI_RUBYGEMS_API_KEY }}
28
- pat_token: ${{ secrets.GITHUB_TOKEN }}
data/CLAUDE.md CHANGED
@@ -97,7 +97,7 @@ Profiles support `import` to inherit from other profiles (e.g., `metanorma` impo
97
97
 
98
98
  The `Validator` accepts multiple input types and always uses SAX:
99
99
  - String (XML content) → parsed directly with SAX
100
- - Moxml/Nokogiri documents → serialized once, then SAX validated
100
+ - Moxml/leptris documents → serialized once, then SAX validated
101
101
  - Document/Element objects → same serialization approach
102
102
 
103
103
  This ensures memory safety for large files regardless of input type.
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gemspec
8
8
  gem "canon", "~>0.1.10"
9
9
  gem "lutaml-model", github: "lutaml/lutaml-model", branch: "main"
10
10
  gem "moxml", github: "lutaml/moxml", branch: "main"
11
+ gem "leptris", "~> 1.9.362"
11
12
  gem "openssl", "~> 3.0"
12
13
  gem "rake"
13
14
  gem "rspec"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "moxml"
4
- require "nokogiri" if defined?(Nokogiri)
4
+ require "leptris" if defined?(Leptris)
5
5
 
6
6
  module SvgConform
7
7
  # Wrapper around Moxml document for SVG validation
@@ -29,7 +29,7 @@ module SvgConform
29
29
  new(content)
30
30
  end
31
31
 
32
- # Create Document from an already-parsed node (Nokogiri or Moxml)
32
+ # Create Document from an already-parsed node (leptris or Moxml)
33
33
  # Avoids re-parsing when input is already a DOM object
34
34
  def self.from_node(node)
35
35
  doc = allocate
@@ -42,15 +42,15 @@ module SvgConform
42
42
  doc.instance_variable_set(:@content, nil) # Don't store XML string
43
43
  doc.instance_variable_set(:@moxml_document,
44
44
  node.is_a?(Moxml::Document) ? node : wrap_moxml_element(node))
45
- elsif defined?(Nokogiri) && node.is_a?(Nokogiri::XML::Node)
46
- # Nokogiri node - must serialize to convert to Moxml
45
+ elsif defined?(Leptris) && node.is_a?(Leptris::XML::Node)
46
+ # leptris node - must serialize to convert to Moxml
47
47
  # This is unavoidable due to different DOM implementations
48
48
  xml_string = node.to_xml
49
49
  doc.instance_variable_set(:@content, xml_string)
50
50
  doc.send(:parse_document)
51
51
  else
52
52
  raise ArgumentError,
53
- "Invalid input type: #{node.class}. Expected Moxml or Nokogiri DOM node."
53
+ "Invalid input type: #{node.class}. Expected Moxml or leptris DOM node."
54
54
  end
55
55
 
56
56
  doc
@@ -72,8 +72,11 @@ module SvgConform
72
72
  end
73
73
 
74
74
  def xpath(path, namespaces = {})
75
- cache_key = [path, namespaces].hash
76
- @xpath_cache[cache_key] ||= @moxml_document.xpath(path, namespaces)
75
+ # No memoization: cached node sets go stale the moment any
76
+ # remediation mutates the tree, and validation then reads
77
+ # pre-remediation state (watch: style promotions silently
78
+ # "not applied" on revalidation).
79
+ @moxml_document.xpath(path, namespaces)
77
80
  end
78
81
 
79
82
  def traverse(&)
@@ -110,7 +113,7 @@ module SvgConform
110
113
 
111
114
  def remove_namespace_declarations(xml, prefixes)
112
115
  # Remove xmlns:prefix="uri" declarations from the XML string
113
- # This works around Moxml/Nokogiri's inability to remove namespace declarations
116
+ # This works around Moxml's inability to remove namespace declarations
114
117
  prefixes.reduce(xml) do |result, prefix|
115
118
  # Match xmlns:prefix="..." with various quote styles and surrounding whitespace
116
119
  # The pattern matches: xmlns:prefix="uri" or xmlns:prefix='uri'
@@ -237,8 +240,12 @@ module SvgConform
237
240
 
238
241
  def parse_document
239
242
  begin
240
- # Create a Moxml context and parse the document
241
- context = Moxml.new
243
+ # Create a Moxml context and parse the document. The DOM is
244
+ # pinned to the Nokogiri adapter: the leptris adapter segfaults
245
+ # natively in attribute traversal on path-heavy SVGs
246
+ # (leptris#1712), and this gem's remediation passes are exactly
247
+ # that workload.
248
+ context = Moxml.new(:nokogiri)
242
249
  @moxml_document = context.parse(@content)
243
250
  rescue StandardError => e
244
251
  raise ParseError, "Failed to parse SVG document: #{e.message}"
@@ -20,7 +20,7 @@ module SvgConform
20
20
  return nil unless node.respond_to?(:name) && node.name
21
21
 
22
22
  # Use native.object_id as cache key since wrapper object_id changes
23
- # across traverses but underlying Nokogiri node identity is stable
23
+ # across traverses but underlying leptris node identity is stable
24
24
  native_id = node.native.object_id
25
25
  @cache[native_id] ||= compute_and_cache_path(node)
26
26
  end
@@ -107,7 +107,7 @@ module SvgConform
107
107
 
108
108
  # Count this node's position among siblings with same name
109
109
  # Use native.object_id comparison since wrapper objects differ
110
- # across traverses but underlying Nokogiri nodes are stable
110
+ # across traverses but underlying leptris nodes are stable
111
111
  position = 0
112
112
  native_id = node.native.object_id
113
113
  parent.children.each do |child|
@@ -28,7 +28,7 @@ module SvgConform
28
28
  # This is the main validation method called for each node that passes
29
29
  # the should_check_node? filter during DOM-based validation.
30
30
  #
31
- # @param node [Moxml::Node, Nokogiri::XML::Node] The node to validate
31
+ # @param node [Moxml::Node, Leptris::XML::Node] The node to validate
32
32
  # @param context [ValidationContext] The validation context for reporting errors
33
33
  # @return [void]
34
34
  # @raise [NotImplementedError] If not implemented by subclass
@@ -143,7 +143,7 @@ module SvgConform
143
143
  #
144
144
  # Override this to add additional filtering logic.
145
145
  #
146
- # @param node [Moxml::Node, Nokogiri::XML::Node, ElementProxy] The node to check
146
+ # @param node [Moxml::Node, Leptris::XML::Node, ElementProxy] The node to check
147
147
  # @param context [ValidationContext, nil] The validation context (may be nil in some cases)
148
148
  # @return [Boolean] true if the node should be validated
149
149
  def should_check_node?(node, context = nil)
@@ -57,7 +57,18 @@ module SvgConform
57
57
  # @param name [String] attribute name
58
58
  # @return [Boolean] true if successful
59
59
  def remove_attribute(node, name)
60
- if node.respond_to?(:remove_attribute)
60
+ if node.respond_to?(:attributes)
61
+ # Remove via the attribute wrapper: node-level remove_attribute is
62
+ # a silent no-op for namespace-prefixed names (moxml#378), while
63
+ # the wrapper's #remove works on every adapter.
64
+ attr = Array(node.attributes).find do |a|
65
+ a.respond_to?(:name) && a.name == name && a.respond_to?(:remove)
66
+ end
67
+ return false unless attr
68
+
69
+ attr.remove
70
+ true
71
+ elsif node.respond_to?(:remove_attribute)
61
72
  node.remove_attribute(name)
62
73
  true
63
74
  elsif node.respond_to?(:[]=) && node.respond_to?(:[])
@@ -132,7 +132,7 @@ module SvgConform
132
132
  ValidationResult.new(document, self, context)
133
133
  elsif document.respond_to?(:to_xml)
134
134
  # For other document objects, serialize and use SAX for safety
135
- # (This handles Nokogiri/Moxml documents that aren't wrapped in Document)
135
+ # (This handles leptris/Moxml documents that aren't wrapped in Document)
136
136
  content = document.to_xml
137
137
  sax_doc = SaxDocument.from_content(content)
138
138
  sax_doc.validate_with_profile(self)
@@ -21,7 +21,10 @@ module SvgConform
21
21
  attribute :element_count, :integer, default: 0
22
22
  attribute :max_depth, :integer, default: 0
23
23
 
24
- after_initialize { freeze }
24
+ def initialize(**args)
25
+ super(args)
26
+ freeze
27
+ end
25
28
 
26
29
  # Value equality
27
30
  def ==(other)
@@ -30,7 +30,10 @@ module SvgConform
30
30
  attribute :non_remediable, :integer, default: 0
31
31
 
32
32
  # Ensure immutability after initialization
33
- after_initialize { freeze }
33
+ def initialize(**args)
34
+ super(args)
35
+ freeze
36
+ end
34
37
 
35
38
  # Value equality
36
39
  def ==(other)
@@ -23,7 +23,10 @@ module SvgConform
23
23
  attribute :has_clip_paths, :boolean, default: false
24
24
  attribute :has_external_refs, :boolean, default: false
25
25
 
26
- after_initialize { freeze }
26
+ def initialize(**args)
27
+ super(args)
28
+ freeze
29
+ end
27
30
 
28
31
  # Value equality
29
32
  def ==(other)
@@ -34,7 +34,10 @@ module SvgConform
34
34
  attribute :content_health, :symbol
35
35
  attribute :size_category, :symbol
36
36
 
37
- after_initialize { freeze }
37
+ def initialize(**args)
38
+ super(args)
39
+ freeze
40
+ end
38
41
 
39
42
  # Value equality
40
43
  def ==(other)
@@ -18,7 +18,10 @@ module SvgConform
18
18
 
19
19
  LEVELS = %i[excellent good fair poor critical].freeze
20
20
 
21
- after_initialize { freeze }
21
+ def initialize(**args)
22
+ super(args)
23
+ freeze
24
+ end
22
25
 
23
26
  # Value equality
24
27
  def ==(other)
@@ -32,7 +32,7 @@ module SvgConform
32
32
  end
33
33
 
34
34
  # Second pass: remove unused namespace declarations
35
- # Nokogiri/libxml2 cannot remove namespace declarations via DOM,
35
+ # Moxml adapters cannot remove namespace declarations via DOM,
36
36
  # so we use string manipulation + reparse
37
37
  if removed_namespaces.any? || disallowed_namespaces.any?
38
38
  changes.concat(remove_namespace_declarations(document,
@@ -51,7 +51,7 @@ module SvgConform
51
51
  attributes_to_remove = []
52
52
 
53
53
  if node.respond_to?(:attribute_nodes)
54
- # Use attribute_nodes if available (Nokogiri style)
54
+ # Use attribute_nodes if available (nokogiri-compatible API style)
55
55
  node.attribute_nodes.each do |attr|
56
56
  namespace_uri = attr.namespace&.href
57
57
  next unless namespace_uri
@@ -82,7 +82,9 @@ module SvgConform
82
82
  # Array case
83
83
  attributes.each do |attr|
84
84
  if should_remove_moxml_attribute?(attr, node, removed_namespaces)
85
- attr_name = attr.respond_to?(:name) ? attr.name : attr.to_s
85
+ local_name = attr.respond_to?(:name) ? attr.name : attr.to_s
86
+ ns_prefix = attr.respond_to?(:namespace) && attr.namespace.respond_to?(:prefix) ? attr.namespace.prefix : nil
87
+ attr_name = ns_prefix && !ns_prefix.empty? ? "#{ns_prefix}:#{local_name}" : local_name
86
88
  attributes_to_remove << attr_name
87
89
  end
88
90
  end
@@ -132,7 +134,7 @@ module SvgConform
132
134
 
133
135
  # Reparse the document to update the internal DOM
134
136
  # This is necessary because namespace declarations cannot be removed
135
- # from the DOM directly in Nokogiri/libxml2
137
+ # from the DOM directly in moxml adapters
136
138
  if changes.any?
137
139
  context = Moxml.new
138
140
  new_moxml_doc = context.parse(xml_str)
@@ -59,7 +59,10 @@ module SvgConform
59
59
 
60
60
  node.attributes.each do |attr_name, attr_value|
61
61
  # Handle both string keys and Moxml::Attribute objects
62
- name_str = attr_name.respond_to?(:name) ? attr_name.name : attr_name.to_s
62
+ local_name = attr_name.respond_to?(:name) ? attr_name.name : attr_name.to_s
63
+ # Include namespace prefix for namespaced attributes (e.g. "custom:id")
64
+ ns_prefix = attr_name.respond_to?(:namespace) && attr_name.namespace.respond_to?(:prefix) ? attr_name.namespace.prefix : nil
65
+ name_str = ns_prefix && !ns_prefix.empty? ? "#{ns_prefix}:#{local_name}" : local_name
63
66
 
64
67
  # For root SVG element, remove xmlns declarations for disallowed namespaces
65
68
  if remove_declarations && node.name == "svg" && name_str.start_with?("xmlns:")
@@ -107,7 +110,7 @@ module SvgConform
107
110
  end
108
111
 
109
112
  # Clean up unused namespace declarations
110
- # Note: Moxml/Nokogiri don't support removing namespace declarations directly,
113
+ # Note: Moxml doesn't support removing namespace declarations directly,
111
114
  # so we mark the document for post-processing during serialization
112
115
  cleanup_unused_namespace_declarations(document)
113
116
 
@@ -73,6 +73,11 @@ module SvgConform
73
73
  map "allow_rdf_metadata", to: :allow_rdf_metadata
74
74
  end
75
75
 
76
+ def initialize(**args)
77
+ super(args)
78
+ after_initialize
79
+ end
80
+
76
81
  def after_initialize
77
82
  build_element_config_index if element_configs&.any?
78
83
  end
@@ -33,7 +33,7 @@ module SvgConform
33
33
 
34
34
  # Try to get attributes using different methods depending on what's available
35
35
  if node.respond_to?(:attribute_nodes)
36
- # Use attribute_nodes if available (Nokogiri style)
36
+ # Use attribute_nodes if available (nokogiri-compatible API style)
37
37
  check_attribute_nodes(node, context)
38
38
  elsif node.respond_to?(:attributes)
39
39
  # Fallback to attributes method (Moxml style)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "leptris"
4
4
  require_relative "sax_validation_handler"
5
5
 
6
6
  module SvgConform
@@ -26,7 +26,7 @@ module SvgConform
26
26
  # Validate using SAX streaming parser
27
27
  def validate_with_profile(profile)
28
28
  handler = SaxValidationHandler.new(profile)
29
- parser = Nokogiri::XML::SAX::Parser.new(handler)
29
+ parser = Leptris::XML::SAX::Parser.new(handler)
30
30
 
31
31
  begin
32
32
  parser.parse(@content)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "leptris"
4
4
  require_relative "element_proxy"
5
5
  require_relative "validation_context"
6
6
  require_relative "validation/error_tracker"
@@ -38,7 +38,7 @@ module SvgConform
38
38
  # - Each validation creates a fresh SaxValidationHandler with fresh ValidationContext
39
39
  # - ValidationContext creates fresh State instances for deferred requirements
40
40
  # - No state pollution occurs across validations
41
- class SaxValidationHandler < Nokogiri::XML::SAX::Document
41
+ class SaxValidationHandler < Leptris::XML::SAX::Document
42
42
  attr_reader :result, :context
43
43
 
44
44
  def initialize(profile)
@@ -134,8 +134,8 @@ module SvgConform
134
134
  end
135
135
 
136
136
  # SAX Event: Parse error
137
- def error(error_message)
138
- @parse_errors << error_message
137
+ def error(message, _line = 0, _column = 0)
138
+ @parse_errors << message
139
139
  end
140
140
 
141
141
  # SAX Event: Warning
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nokogiri"
3
+ require "leptris"
4
4
 
5
5
  module SvgConform
6
6
  # Semantic comparison engine for comparing validation results and remediated content
@@ -553,8 +553,8 @@ repair_mode = false, _mixed_mode = false)
553
553
  def self.parse_svg_safely(content)
554
554
  return nil if content.nil? || content.strip.empty?
555
555
 
556
- Nokogiri::XML(content, &:strict)
557
- rescue Nokogiri::XML::SyntaxError
556
+ Leptris::XML.parse(content)
557
+ rescue Leptris::XML::ParseError
558
558
  nil
559
559
  end
560
560
 
@@ -35,7 +35,7 @@ module SvgConform
35
35
  # Accepts:
36
36
  # - String (XML content) → uses SAX for efficient parsing
37
37
  # - Moxml::Document or Moxml::Element → serializes once, then SAX validates
38
- # - Nokogiri::XML::Document or Nokogiri::XML::Element → serializes once, then SAX validates
38
+ # - leptris::XML::Document or leptris::XML::Element → serializes once, then SAX validates
39
39
  # - Any adapter document object (Ox, Oga, REXML, LibXML) → serializes once, then SAX validates
40
40
  #
41
41
  # IMPORTANT: Always uses SAX validation to safely handle large SVG files.
@@ -110,8 +110,8 @@ module SvgConform
110
110
  return input.to_xml
111
111
  end
112
112
 
113
- # Check for Nokogiri document or element
114
- if defined?(Nokogiri) && input.is_a?(Nokogiri::XML::Node)
113
+ # Check for leptris document or element
114
+ if defined?(Leptris) && input.is_a?(Leptris::XML::Node)
115
115
  return input.to_xml
116
116
  end
117
117
 
@@ -123,7 +123,7 @@ module SvgConform
123
123
  # If we can't convert, raise an error
124
124
  raise ArgumentError,
125
125
  "Invalid input type: #{input.class}. " \
126
- "Expected String, Moxml document, Nokogiri document, or adapter document object. " \
126
+ "Expected String, Moxml document, leptris document, or adapter document object. " \
127
127
  "Input must respond to #to_xml or be a valid XML string."
128
128
  end
129
129
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SvgConform
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.3"
5
5
  end
data/lib/svg_conform.rb CHANGED
@@ -4,7 +4,7 @@ require "lutaml/model"
4
4
 
5
5
  # Configure Lutaml::Model adapters
6
6
  Lutaml::Model::Config.configure do |config|
7
- config.xml_adapter_type = :nokogiri
7
+ config.xml_adapter_type = :leptris
8
8
  config.json_adapter_type = :standard_json
9
9
  config.yaml_adapter_type = :standard_yaml
10
10
  end
@@ -34,7 +34,7 @@ RSpec.describe "IdReferenceRequirement" do
34
34
 
35
35
  # Verify first validation caught the error
36
36
  expect(result1.errors.map(&:message)).to include(
37
- match(/Reference to undefined ID 'missing_id'/),
37
+ include("Reference to undefined ID 'missing_id'"),
38
38
  )
39
39
 
40
40
  # Second validation: SVG without reference errors
@@ -68,7 +68,7 @@ RSpec.describe "IdReferenceRequirement" do
68
68
  if i.even?
69
69
  # Should have error (svg_with_error)
70
70
  expect(result.errors.map(&:message)).to include(
71
- match(/Reference to undefined ID 'missing_id'/),
71
+ include("Reference to undefined ID 'missing_id'"),
72
72
  )
73
73
  else
74
74
  # Should NOT have error about missing_id (svg_without_error)
@@ -66,19 +66,19 @@ RSpec.describe SvgConform::Validator do
66
66
  end
67
67
  end
68
68
 
69
- context "with Nokogiri input (metanorm use case)" do
70
- it "validates Nokogiri::XML::Document" do
71
- nokogiri_doc = Nokogiri::XML(simple_svg)
69
+ context "with leptris input (metanorm use case)" do
70
+ it "validates a leptris document" do
71
+ leptris_doc = Leptris::XML.parse(simple_svg)
72
72
 
73
- result = validator.validate(nokogiri_doc, profile: :metanorma)
73
+ result = validator.validate(leptris_doc, profile: :metanorma)
74
74
 
75
75
  expect(result).to be_a(SvgConform::ValidationResult)
76
76
  expect(result.valid?).to be true
77
77
  end
78
78
 
79
- it "validates Nokogiri::XML::Element" do
80
- nokogiri_doc = Nokogiri::XML(simple_svg)
81
- svg_element = nokogiri_doc.root
79
+ it "validates a leptris element" do
80
+ leptris_doc = Leptris::XML.parse(simple_svg)
81
+ svg_element = leptris_doc.root
82
82
 
83
83
  # This is the metanorma use case - passing element directly
84
84
  result = validator.validate(svg_element, profile: :metanorma)
@@ -87,9 +87,9 @@ RSpec.describe SvgConform::Validator do
87
87
  expect(result.valid?).to be true
88
88
  end
89
89
 
90
- it "serializes Nokogiri element once for SAX validation" do
91
- nokogiri_doc = Nokogiri::XML(simple_svg)
92
- svg_element = nokogiri_doc.root
90
+ it "serializes leptris element once for SAX validation" do
91
+ leptris_doc = Leptris::XML.parse(simple_svg)
92
+ svg_element = leptris_doc.root
93
93
 
94
94
  # Should call to_xml once for SAX validation
95
95
  # (SAX mode is memory-safe for large SVGs)
@@ -126,9 +126,9 @@ RSpec.describe SvgConform::Validator do
126
126
  SVG
127
127
  end
128
128
 
129
- it "builds reference manifest from Nokogiri element" do
130
- nokogiri_doc = Nokogiri::XML(svg_with_refs)
131
- svg_element = nokogiri_doc.root
129
+ it "builds reference manifest from leptris element" do
130
+ leptris_doc = Leptris::XML.parse(svg_with_refs)
131
+ svg_element = leptris_doc.root
132
132
 
133
133
  result = validator.validate(svg_element, profile: :metanorma)
134
134
 
@@ -159,8 +159,8 @@ RSpec.describe SvgConform::Validator do
159
159
  end
160
160
 
161
161
  it "applies remediation when using document object input" do
162
- nokogiri_doc = Nokogiri::XML(invalid_svg)
163
- svg_element = nokogiri_doc.root
162
+ leptris_doc = Leptris::XML.parse(invalid_svg)
163
+ svg_element = leptris_doc.root
164
164
 
165
165
  result = validator.validate(svg_element, profile: :svg_1_2_rfc, fix: true)
166
166
 
@@ -341,7 +341,7 @@ RSpec.describe "SvgCheck Compatibility" do
341
341
 
342
342
  def parse_xml(xml_content)
343
343
  # Simple XML parsing check
344
- require "nokogiri"
345
- Nokogiri::XML(xml_content, &:strict)
344
+ require "leptris"
345
+ Leptris::XML.parse(xml_content)
346
346
  end
347
347
  end
data/svg_conform.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.require_paths = ["lib"]
31
31
 
32
32
  spec.add_dependency "lutaml-model", "~> 0.8.0"
33
- spec.add_dependency "moxml", "~> 0.1", ">= 0.1.10"
33
+ spec.add_dependency "moxml", "~> 0.5"
34
34
  spec.add_dependency "rainbow"
35
35
  spec.add_dependency "table_tennis"
36
36
  spec.add_dependency "thor"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svg_conform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-04-11 00:00:00.000000000 Z
11
+ date: 2026-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -30,20 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.1'
34
- - - ">="
35
- - !ruby/object:Gem::Version
36
- version: 0.1.10
33
+ version: '0.5'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
38
  - - "~>"
42
39
  - !ruby/object:Gem::Version
43
- version: '0.1'
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: 0.1.10
40
+ version: '0.5'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: rainbow
49
43
  requirement: !ruby/object:Gem::Requirement