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
data/Gemfile CHANGED
@@ -27,3 +27,9 @@ gem "tempfile"
27
27
 
28
28
  # Needed by get_process_mem on Windows
29
29
  gem "sys-proctable" if Gem.win_platform?
30
+
31
+ group :opal do
32
+ gem "opal", "~> 1.8"
33
+ gem "opal-rspec", "~> 1.0"
34
+ gem "opal-sprockets"
35
+ end
data/Rakefile CHANGED
@@ -5,11 +5,43 @@ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
+ begin
9
+ require "opal/rspec/rake_task"
10
+
11
+ # REXML is a bundled gem since Ruby 3.4; its source must be on Opal's
12
+ # global load path so the compiler can follow `require "rexml/document"`.
13
+ # Opal-compatible overrides go first so they shadow the gem originals.
14
+ if defined?(Opal)
15
+ Opal.append_path File.expand_path("lib/compat/opal", __dir__)
16
+ rexml_lib = $LOAD_PATH.find do |p|
17
+ File.exist?(File.join(p, "rexml", "document.rb"))
18
+ end
19
+ Opal.append_path rexml_lib if rexml_lib
20
+ end
21
+ rescue LoadError
22
+ # Opal not available or incompatible with current Ruby version
23
+ end
24
+
8
25
  require "rubocop/rake_task"
9
26
 
10
27
  RuboCop::RakeTask.new
11
28
 
12
29
  namespace :spec do
30
+ if defined?(Opal::RSpec::RakeTask)
31
+ desc "Run Opal (JavaScript) tests"
32
+ Opal::RSpec::RakeTask.new(:opal) do |server, runner|
33
+ server.append_path "lib"
34
+ server.append_path "spec"
35
+
36
+ runner.default_path = "spec"
37
+ runner.requires = %w[rexml_compat rexml/document rexml/xpath
38
+ moxml/adapter/rexml spec_helper support/opal]
39
+ runner.files = Dir.glob("spec/moxml/*opal*_spec.rb") +
40
+ Dir.glob("spec/moxml/native_attachment/opal_spec.rb") +
41
+ Dir.glob("spec/moxml/adapter/shared_examples/*.rb")
42
+ end
43
+ end
44
+
13
45
  desc "Validate XML fixtures are well-formed (requires xmllint)"
14
46
  task :validate_fixtures do
15
47
  fixtures = Dir.glob("spec/fixtures/**/*.xml")
@@ -106,4 +138,42 @@ namespace :benchmark do
106
138
  end
107
139
  end
108
140
 
141
+ namespace :opal do
142
+ desc "Regenerate entity data for Opal from w3c_entities.json"
143
+ task :generate_entity_data do
144
+ require "json"
145
+
146
+ source = File.join(__dir__, "data", "w3c_entities.json")
147
+ target = File.join(__dir__, "lib", "moxml", "entity_registry_opal_data.rb")
148
+
149
+ data = JSON.parse(File.read(source))
150
+ chars = data["characters"]
151
+
152
+ lines = []
153
+ lines << "# frozen_string_literal: true"
154
+ lines << "#"
155
+ lines << "# Auto-generated entity data for Opal runtime."
156
+ lines << "# Source: data/w3c_entities.json (#{chars.size} entities)"
157
+ lines << "# Regenerate with: rake opal:generate_entity_data"
158
+ lines << ""
159
+ lines << "module Moxml"
160
+ lines << " class EntityRegistry"
161
+ lines << " OPAL_ENTITY_DATA = {"
162
+ chars.each do |name, char|
163
+ codepoint = if char.start_with?("\\u")
164
+ char.unicode_normalize(:nfc)[2..].to_i(16)
165
+ else
166
+ char.ord
167
+ end
168
+ lines << " #{name.inspect} => #{codepoint},"
169
+ end
170
+ lines << " }.freeze"
171
+ lines << " end"
172
+ lines << "end"
173
+
174
+ File.write(target, "#{lines.join("\n")}\n")
175
+ puts "Generated #{target} (#{chars.size} entities, #{lines.size} lines)"
176
+ end
177
+ end
178
+
109
179
  task default: %i[spec rubocop]
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rexml/xmltokens"
4
+
5
+ module REXML
6
+ module Namespace
7
+ attr_reader :name, :expanded_name
8
+ attr_accessor :prefix
9
+
10
+ include XMLTokens
11
+
12
+ NAME_WITHOUT_NAMESPACE = /^#{NCNAME_STR}$/
13
+ NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
14
+
15
+ def name=(name)
16
+ @expanded_name = name
17
+ if name.match?(NAME_WITHOUT_NAMESPACE)
18
+ @prefix = ""
19
+ @namespace = ""
20
+ @name = name
21
+ elsif name =~ NAMESPLIT
22
+ if $1
23
+ @prefix = $1
24
+ else
25
+ @prefix = ""
26
+ @namespace = ""
27
+ end
28
+ @name = $2
29
+ elsif name == ""
30
+ @prefix = nil
31
+ @namespace = nil
32
+ @name = nil
33
+ else
34
+ message = "name must be \#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: "
35
+ message += "<#{name.inspect}>"
36
+ raise ArgumentError, message
37
+ end
38
+ end
39
+
40
+ def has_name?(other, ns = nil)
41
+ if ns
42
+ namespace == ns and name == other
43
+ elsif other.include? ":"
44
+ fully_expanded_name == other
45
+ else
46
+ name == other
47
+ end
48
+ end
49
+
50
+ alias :local_name :name
51
+
52
+ def fully_expanded_name
53
+ ns = prefix
54
+ return "#{ns}:#@name" if ns.size.positive?
55
+
56
+ @name
57
+ end
58
+ end
59
+ end