moxml 0.1.20 → 0.1.22

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/opal.yml +37 -0
  3. data/.rspec-opal +5 -0
  4. data/Gemfile +6 -0
  5. data/Rakefile +67 -0
  6. data/lib/compat/opal/rexml/namespace.rb +56 -0
  7. data/lib/compat/opal/rexml/parsers/baseparser.rb +952 -0
  8. data/lib/compat/opal/rexml/source.rb +213 -0
  9. data/lib/compat/opal/rexml/text.rb +418 -0
  10. data/lib/compat/opal/rexml/xmltokens.rb +45 -0
  11. data/lib/compat/opal/rexml_compat.rb +76 -0
  12. data/lib/moxml/adapter/base.rb +5 -0
  13. data/lib/moxml/adapter/customized_libxml/node.rb +3 -0
  14. data/lib/moxml/adapter/customized_libxml/text.rb +6 -1
  15. data/lib/moxml/adapter/customized_rexml/formatter.rb +11 -10
  16. data/lib/moxml/adapter/headed_ox.rb +2 -6
  17. data/lib/moxml/adapter/libxml/entity_ref_registry.rb +105 -0
  18. data/lib/moxml/adapter/libxml/entity_restorer.rb +92 -0
  19. data/lib/moxml/adapter/libxml.rb +386 -382
  20. data/lib/moxml/adapter/nokogiri.rb +7 -18
  21. data/lib/moxml/adapter/oga.rb +4 -22
  22. data/lib/moxml/adapter/ox.rb +8 -23
  23. data/lib/moxml/adapter/rexml.rb +29 -33
  24. data/lib/moxml/adapter.rb +38 -8
  25. data/lib/moxml/config.rb +1 -1
  26. data/lib/moxml/entity_registry.rb +36 -31
  27. data/lib/moxml/entity_registry_opal_data.rb +2137 -0
  28. data/lib/moxml/node.rb +19 -26
  29. data/lib/moxml/sax/namespace_splitter.rb +54 -0
  30. data/lib/moxml/version.rb +1 -1
  31. data/lib/moxml/xml_utils.rb +9 -1
  32. data/spec/consistency/adapter_parity_spec.rb +1 -1
  33. data/spec/integration/all_adapters_spec.rb +1 -1
  34. data/spec/integration/w3c_namespace_spec.rb +1 -1
  35. data/spec/moxml/adapter/libxml_internals_spec.rb +167 -0
  36. data/spec/moxml/adapter/ox_spec.rb +8 -0
  37. data/spec/moxml/adapter/platform_spec.rb +69 -0
  38. data/spec/moxml/adapter/shared_examples/adapter_contract.rb +0 -6
  39. data/spec/moxml/entity_registry_spec.rb +10 -0
  40. data/spec/moxml/native_attachment/opal_spec.rb +39 -2
  41. data/spec/moxml/node_type_map_spec.rb +43 -0
  42. data/spec/moxml/opal_rexml_adapter_spec.rb +14 -0
  43. data/spec/moxml/opal_smoke_spec.rb +61 -0
  44. data/spec/moxml/sax/namespace_splitter_spec.rb +67 -0
  45. data/spec/moxml/text_spec.rb +1 -1
  46. data/spec/performance/benchmark_spec.rb +1 -1
  47. data/spec/spec_helper.rb +32 -13
  48. data/spec/support/opal.rb +16 -0
  49. metadata +21 -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
@@ -30,7 +30,7 @@ RSpec.shared_examples "Performance Examples" do
30
30
  rexml: { parser: 0, serializer: 5 },
31
31
  ox: { parser: 2, serializer: 1000 },
32
32
  headed_ox: { parser: 2, serializer: 1000 },
33
- libxml: { parser: 2, serializer: 3 },
33
+ libxml: { parser: 500, serializer: 60 },
34
34
  }
35
35
  end
36
36
 
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.20
4
+ version: 0.1.22
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-03 00:00:00.000000000 Z
11
+ date: 2026-05-25 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
@@ -121,6 +129,8 @@ files:
121
129
  - lib/moxml/adapter/customized_rexml/formatter.rb
122
130
  - lib/moxml/adapter/headed_ox.rb
123
131
  - lib/moxml/adapter/libxml.rb
132
+ - lib/moxml/adapter/libxml/entity_ref_registry.rb
133
+ - lib/moxml/adapter/libxml/entity_restorer.rb
124
134
  - lib/moxml/adapter/nokogiri.rb
125
135
  - lib/moxml/adapter/oga.rb
126
136
  - lib/moxml/adapter/ox.rb
@@ -138,6 +148,7 @@ files:
138
148
  - lib/moxml/element.rb
139
149
  - lib/moxml/entity_reference.rb
140
150
  - lib/moxml/entity_registry.rb
151
+ - lib/moxml/entity_registry_opal_data.rb
141
152
  - lib/moxml/error.rb
142
153
  - lib/moxml/namespace.rb
143
154
  - lib/moxml/native_attachment.rb
@@ -150,6 +161,7 @@ files:
150
161
  - lib/moxml/sax/block_handler.rb
151
162
  - lib/moxml/sax/element_handler.rb
152
163
  - lib/moxml/sax/handler.rb
164
+ - lib/moxml/sax/namespace_splitter.rb
153
165
  - lib/moxml/text.rb
154
166
  - lib/moxml/version.rb
155
167
  - lib/moxml/xml_utils.rb
@@ -297,10 +309,12 @@ files:
297
309
  - spec/moxml/adapter/base_spec.rb
298
310
  - spec/moxml/adapter/entity_restoration_spec.rb
299
311
  - spec/moxml/adapter/headed_ox_spec.rb
312
+ - spec/moxml/adapter/libxml_internals_spec.rb
300
313
  - spec/moxml/adapter/libxml_spec.rb
301
314
  - spec/moxml/adapter/nokogiri_spec.rb
302
315
  - spec/moxml/adapter/oga_spec.rb
303
316
  - spec/moxml/adapter/ox_spec.rb
317
+ - spec/moxml/adapter/platform_spec.rb
304
318
  - spec/moxml/adapter/rexml_spec.rb
305
319
  - spec/moxml/adapter/shared_examples/.gitkeep
306
320
  - spec/moxml/adapter/shared_examples/adapter_contract.rb
@@ -335,7 +349,11 @@ files:
335
349
  - spec/moxml/node_set_cache_spec.rb
336
350
  - spec/moxml/node_set_spec.rb
337
351
  - spec/moxml/node_spec.rb
352
+ - spec/moxml/node_type_map_spec.rb
353
+ - spec/moxml/opal_rexml_adapter_spec.rb
354
+ - spec/moxml/opal_smoke_spec.rb
338
355
  - spec/moxml/processing_instruction_spec.rb
356
+ - spec/moxml/sax/namespace_splitter_spec.rb
339
357
  - spec/moxml/sax_spec.rb
340
358
  - spec/moxml/text_spec.rb
341
359
  - spec/moxml/version_spec.rb
@@ -369,6 +387,7 @@ files:
369
387
  - spec/performance/xpath_benchmark_spec.rb
370
388
  - spec/spec_helper.rb
371
389
  - spec/support/allocation_helper.rb
390
+ - spec/support/opal.rb
372
391
  - spec/support/w3c_namespace_helpers.rb
373
392
  - spec/support/xml_matchers.rb
374
393
  - spec/unit/rexml_isolated_test.rb