moxml 0.1.21 → 0.1.23

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/opal.yml +37 -0
  3. data/.gitignore +1 -0
  4. data/.rspec-opal +5 -0
  5. data/.rubocop.yml +1 -0
  6. data/.rubocop_todo.yml +680 -110
  7. data/Gemfile +6 -0
  8. data/Rakefile +70 -0
  9. data/lib/compat/opal/rexml/namespace.rb +59 -0
  10. data/lib/compat/opal/rexml/parsers/baseparser.rb +1016 -0
  11. data/lib/compat/opal/rexml/source.rb +214 -0
  12. data/lib/compat/opal/rexml/text.rb +426 -0
  13. data/lib/compat/opal/rexml/xmltokens.rb +45 -0
  14. data/lib/compat/opal/rexml_compat.rb +77 -0
  15. data/lib/moxml/adapter/customized_oga/xml_declaration.rb +8 -1
  16. data/lib/moxml/adapter/customized_rexml/formatter.rb +11 -10
  17. data/lib/moxml/adapter/headed_ox.rb +2 -6
  18. data/lib/moxml/adapter/libxml/entity_ref_registry.rb +4 -2
  19. data/lib/moxml/adapter/libxml/entity_restorer.rb +3 -1
  20. data/lib/moxml/adapter/libxml.rb +22 -24
  21. data/lib/moxml/adapter/nokogiri.rb +24 -33
  22. data/lib/moxml/adapter/oga.rb +47 -84
  23. data/lib/moxml/adapter/ox.rb +43 -41
  24. data/lib/moxml/adapter/rexml.rb +29 -33
  25. data/lib/moxml/adapter.rb +38 -8
  26. data/lib/moxml/config.rb +16 -3
  27. data/lib/moxml/document.rb +2 -8
  28. data/lib/moxml/entity_registry.rb +40 -31
  29. data/lib/moxml/entity_registry_opal_data.rb +2138 -0
  30. data/lib/moxml/node.rb +27 -26
  31. data/lib/moxml/sax/namespace_splitter.rb +54 -0
  32. data/lib/moxml/version.rb +1 -1
  33. data/lib/moxml/xml_utils.rb +10 -1
  34. data/lib/moxml.rb +7 -0
  35. data/spec/consistency/adapter_parity_spec.rb +1 -1
  36. data/spec/integration/all_adapters_spec.rb +2 -1
  37. data/spec/integration/shared_examples/line_ending_behavior.rb +56 -0
  38. data/spec/integration/w3c_namespace_spec.rb +1 -1
  39. data/spec/moxml/adapter/libxml_internals_spec.rb +4 -2
  40. data/spec/moxml/adapter/ox_spec.rb +8 -0
  41. data/spec/moxml/adapter/platform_spec.rb +70 -0
  42. data/spec/moxml/adapter/shared_examples/adapter_contract.rb +0 -6
  43. data/spec/moxml/config_spec.rb +33 -0
  44. data/spec/moxml/entity_registry_spec.rb +10 -0
  45. data/spec/moxml/native_attachment/opal_spec.rb +39 -2
  46. data/spec/moxml/node_type_map_spec.rb +43 -0
  47. data/spec/moxml/opal_rexml_adapter_spec.rb +14 -0
  48. data/spec/moxml/opal_smoke_spec.rb +61 -0
  49. data/spec/moxml/sax/namespace_splitter_spec.rb +67 -0
  50. data/spec/moxml/text_spec.rb +1 -1
  51. data/spec/spec_helper.rb +32 -13
  52. data/spec/support/opal.rb +16 -0
  53. metadata +19 -2
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Moxml::SAX::NamespaceSplitter do
6
+ let(:bridge_class) do
7
+ Class.new do
8
+ include Moxml::SAX::NamespaceSplitter
9
+
10
+ attr_reader :last_attrs, :last_ns
11
+
12
+ def split(attributes)
13
+ @last_attrs, @last_ns = split_attributes_and_namespaces(attributes)
14
+ end
15
+ end
16
+ end
17
+
18
+ let(:splitter) { bridge_class.new }
19
+
20
+ describe "#split_attributes_and_namespaces" do
21
+ it "splits hash attributes into attrs and namespaces" do
22
+ attrs, ns = splitter.split({
23
+ "xmlns" => "http://default.ns",
24
+ "xmlns:foo" => "http://foo.ns",
25
+ "id" => "123",
26
+ "class" => "bar",
27
+ })
28
+
29
+ expect(attrs).to eq("id" => "123", "class" => "bar")
30
+ expect(ns).to eq(nil => "http://default.ns", "foo" => "http://foo.ns")
31
+ end
32
+
33
+ it "splits array-of-pairs attributes" do
34
+ attrs, ns = splitter.split([
35
+ ["xmlns:prefix", "http://example.com"],
36
+ ["name", "value"],
37
+ ])
38
+
39
+ expect(attrs).to eq("name" => "value")
40
+ expect(ns).to eq("prefix" => "http://example.com")
41
+ end
42
+
43
+ it "returns empty hashes when all attributes are namespaces" do
44
+ attrs, ns = splitter.split({ "xmlns" => "http://default.ns" })
45
+ expect(attrs).to be_empty
46
+ expect(ns).to eq(nil => "http://default.ns")
47
+ end
48
+
49
+ it "returns empty hashes when there are no namespaces" do
50
+ attrs, ns = splitter.split({ "id" => "1", "name" => "test" })
51
+ expect(attrs).to eq("id" => "1", "name" => "test")
52
+ expect(ns).to be_empty
53
+ end
54
+
55
+ it "handles nil attributes" do
56
+ attrs, ns = splitter.split(nil)
57
+ expect(attrs).to be_empty
58
+ expect(ns).to be_empty
59
+ end
60
+
61
+ it "handles empty hash" do
62
+ attrs, ns = splitter.split({})
63
+ expect(attrs).to be_empty
64
+ expect(ns).to be_empty
65
+ end
66
+ end
67
+ end
@@ -34,7 +34,7 @@ RSpec.describe Moxml::Text do
34
34
  end
35
35
 
36
36
  it "is consistent across adapters" do
37
- Moxml::Adapter::AVALIABLE_ADAPTERS.each do |adapter_name|
37
+ Moxml::Adapter::AVAILABLE_ADAPTERS.each do |adapter_name|
38
38
  ctx = Moxml.new(adapter_name)
39
39
  d = ctx.parse("<root>hello world</root>")
40
40
  text = d.root.children.first
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # SimpleCov must be loaded before application code
4
- if ENV.fetch("COVERAGE", nil) == "true"
4
+ if ENV.fetch("COVERAGE", nil) == "true" && RUBY_ENGINE != "opal"
5
5
  require "simplecov"
6
6
 
7
7
  SimpleCov.start do
@@ -25,20 +25,25 @@ if ENV.fetch("COVERAGE", nil) == "true"
25
25
  end
26
26
 
27
27
  require "moxml"
28
- require "nokogiri"
28
+ require "nokogiri" unless RUBY_ENGINE == "opal"
29
29
 
30
- # Load shared examples from new locations
31
- Dir[File.expand_path("integration/shared_examples/**/*.rb",
32
- __dir__)].each do |f|
33
- require f
34
- end
35
- Dir[File.expand_path("moxml/adapter/shared_examples/**/*.rb",
36
- __dir__)].each do |f|
37
- require f
30
+ unless RUBY_ENGINE == "opal"
31
+ # Load shared examples from new locations
32
+ Dir[File.expand_path("integration/shared_examples/**/*.rb",
33
+ __dir__)].each do |f|
34
+ require f
35
+ end
36
+ Dir[File.expand_path("moxml/adapter/shared_examples/**/*.rb",
37
+ __dir__)].each do |f|
38
+ require f
39
+ end
38
40
  end
39
41
  Dir[File.expand_path("support/**/*.rb", __dir__)].each { |f| require f }
40
- Dir[File.expand_path("performance/*.rb", __dir__)].each { |f| require f }
41
- Dir[File.expand_path("examples/*.rb", __dir__)].each { |f| require f }
42
+
43
+ unless RUBY_ENGINE == "opal"
44
+ Dir[File.expand_path("performance/*.rb", __dir__)].each { |f| require f }
45
+ Dir[File.expand_path("examples/*.rb", __dir__)].each { |f| require f }
46
+ end
42
47
 
43
48
  # Clear XPath caches immediately to ensure fresh compilation
44
49
  # This is critical when code changes affect compiled XPath expressions
@@ -78,12 +83,26 @@ RSpec.configure do |config|
78
83
  # Configure to skip examples unless explicitly run
79
84
  config.filter_run_excluding examples: true unless ENV["RUN_EXAMPLES"]
80
85
 
86
+ # Under Opal, exclude specs that require native-only adapters or filesystem
87
+ if RUBY_ENGINE == "opal"
88
+ config.filter_run_excluding(
89
+ :native_adapter,
90
+ :native_fs,
91
+ :subprocess,
92
+ :xpath_native,
93
+ :performance,
94
+ :examples,
95
+ :consistency,
96
+ )
97
+ end
98
+
81
99
  config.order = :random
82
100
  Kernel.srand config.seed
83
101
  end
84
102
 
85
103
  Moxml.configure do |config|
86
- config.adapter = :nokogiri
104
+ config.adapter = RUBY_ENGINE == "opal" ? :rexml : :nokogiri
87
105
  config.strict_parsing = true
88
106
  config.default_encoding = "UTF-8"
107
+ config.entity_load_mode = :optional if RUBY_ENGINE == "opal"
89
108
  end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Opal runtime patches for moxml specs.
4
+ #
5
+ # Moxml already handles Opal-specific behavior internally
6
+ # (NativeAttachment::Opal, Config::OPAL_DEFAULT_ADAPTER, EntityRegistry::OPAL_ENTITY_DATA).
7
+ # This file is loaded only under Opal for any additional test-environment patches.
8
+
9
+ # Under Opal, moxml uses REXML adapter (Opal reimplements strscan/stringio
10
+ # in its stdlib, enabling REXML to compile to JavaScript).
11
+ Moxml.configure do |config|
12
+ config.adapter = :rexml
13
+ config.strict_parsing = false
14
+ config.default_encoding = "UTF-8"
15
+ config.entity_load_mode = :optional
16
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moxml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.21
4
+ version: 0.1.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-25 00:00:00.000000000 Z
11
+ date: 2026-06-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Moxml is a unified XML manipulation library that provides a common API
@@ -23,11 +23,13 @@ files:
23
23
  - ".github/workflows/dependent-repos.json"
24
24
  - ".github/workflows/dependent-tests.yml"
25
25
  - ".github/workflows/docs.yml"
26
+ - ".github/workflows/opal.yml"
26
27
  - ".github/workflows/rake.yml"
27
28
  - ".github/workflows/release.yml"
28
29
  - ".github/workflows/round-trip.yml"
29
30
  - ".gitignore"
30
31
  - ".rspec"
32
+ - ".rspec-opal"
31
33
  - ".rubocop.yml"
32
34
  - ".rubocop_todo.yml"
33
35
  - Gemfile
@@ -96,6 +98,12 @@ files:
96
98
  - examples/web_scraper/README.md
97
99
  - examples/web_scraper/example_page.html
98
100
  - examples/web_scraper/web_scraper.rb
101
+ - lib/compat/opal/rexml/namespace.rb
102
+ - lib/compat/opal/rexml/parsers/baseparser.rb
103
+ - lib/compat/opal/rexml/source.rb
104
+ - lib/compat/opal/rexml/text.rb
105
+ - lib/compat/opal/rexml/xmltokens.rb
106
+ - lib/compat/opal/rexml_compat.rb
99
107
  - lib/moxml.rb
100
108
  - lib/moxml/adapter.rb
101
109
  - lib/moxml/adapter/base.rb
@@ -140,6 +148,7 @@ files:
140
148
  - lib/moxml/element.rb
141
149
  - lib/moxml/entity_reference.rb
142
150
  - lib/moxml/entity_registry.rb
151
+ - lib/moxml/entity_registry_opal_data.rb
143
152
  - lib/moxml/error.rb
144
153
  - lib/moxml/namespace.rb
145
154
  - lib/moxml/native_attachment.rb
@@ -152,6 +161,7 @@ files:
152
161
  - lib/moxml/sax/block_handler.rb
153
162
  - lib/moxml/sax/element_handler.rb
154
163
  - lib/moxml/sax/handler.rb
164
+ - lib/moxml/sax/namespace_splitter.rb
155
165
  - lib/moxml/text.rb
156
166
  - lib/moxml/version.rb
157
167
  - lib/moxml/xml_utils.rb
@@ -277,6 +287,7 @@ files:
277
287
  - spec/integration/shared_examples/high_level/context_behavior.rb
278
288
  - spec/integration/shared_examples/high_level/document_builder_behavior.rb
279
289
  - spec/integration/shared_examples/integration_workflows.rb
290
+ - spec/integration/shared_examples/line_ending_behavior.rb
280
291
  - spec/integration/shared_examples/node_wrappers/.gitkeep
281
292
  - spec/integration/shared_examples/node_wrappers/attribute_behavior.rb
282
293
  - spec/integration/shared_examples/node_wrappers/cdata_behavior.rb
@@ -304,6 +315,7 @@ files:
304
315
  - spec/moxml/adapter/nokogiri_spec.rb
305
316
  - spec/moxml/adapter/oga_spec.rb
306
317
  - spec/moxml/adapter/ox_spec.rb
318
+ - spec/moxml/adapter/platform_spec.rb
307
319
  - spec/moxml/adapter/rexml_spec.rb
308
320
  - spec/moxml/adapter/shared_examples/.gitkeep
309
321
  - spec/moxml/adapter/shared_examples/adapter_contract.rb
@@ -338,7 +350,11 @@ files:
338
350
  - spec/moxml/node_set_cache_spec.rb
339
351
  - spec/moxml/node_set_spec.rb
340
352
  - spec/moxml/node_spec.rb
353
+ - spec/moxml/node_type_map_spec.rb
354
+ - spec/moxml/opal_rexml_adapter_spec.rb
355
+ - spec/moxml/opal_smoke_spec.rb
341
356
  - spec/moxml/processing_instruction_spec.rb
357
+ - spec/moxml/sax/namespace_splitter_spec.rb
342
358
  - spec/moxml/sax_spec.rb
343
359
  - spec/moxml/text_spec.rb
344
360
  - spec/moxml/version_spec.rb
@@ -372,6 +388,7 @@ files:
372
388
  - spec/performance/xpath_benchmark_spec.rb
373
389
  - spec/spec_helper.rb
374
390
  - spec/support/allocation_helper.rb
391
+ - spec/support/opal.rb
375
392
  - spec/support/w3c_namespace_helpers.rb
376
393
  - spec/support/xml_matchers.rb
377
394
  - spec/unit/rexml_isolated_test.rb