moxml 0.1.23 → 0.1.25
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 +4 -4
- data/.github/workflows/docs.yml +1 -1
- data/.github/workflows/opal.yml +18 -1
- data/.github/workflows/rake.yml +32 -3
- data/.github/workflows/round-trip.yml +72 -9
- data/.gitmodules +6 -0
- data/.rubocop_todo.yml +2 -0
- data/Gemfile +9 -1
- data/README.adoc +124 -0
- data/Rakefile +117 -5
- data/lib/compat/opal/moxml_boot.rb +57 -0
- data/lib/moxml/adapter/base.rb +5 -5
- data/lib/moxml/adapter/customized_libxml/cdata.rb +0 -2
- data/lib/moxml/adapter/customized_libxml/comment.rb +0 -2
- data/lib/moxml/adapter/customized_libxml/element.rb +3 -5
- data/lib/moxml/adapter/customized_libxml/node.rb +2 -2
- data/lib/moxml/adapter/customized_libxml/processing_instruction.rb +0 -2
- data/lib/moxml/adapter/customized_libxml/text.rb +0 -2
- data/lib/moxml/adapter/customized_rexml/formatter.rb +3 -4
- data/lib/moxml/adapter/headed_ox.rb +1 -5
- data/lib/moxml/adapter/libxml.rb +12 -10
- data/lib/moxml/adapter/nokogiri.rb +4 -2
- data/lib/moxml/adapter/oga.rb +10 -10
- data/lib/moxml/adapter/ox.rb +29 -16
- data/lib/moxml/adapter/rexml.rb +5 -6
- data/lib/moxml/adapter.rb +17 -7
- data/lib/moxml/attribute.rb +5 -2
- data/lib/moxml/config.rb +2 -1
- data/lib/moxml/context.rb +8 -8
- data/lib/moxml/declaration.rb +2 -7
- data/lib/moxml/document.rb +0 -11
- data/lib/moxml/document_builder.rb +12 -8
- data/lib/moxml/element.rb +4 -4
- data/lib/moxml/node.rb +37 -14
- data/lib/moxml/node_set.rb +2 -4
- data/lib/moxml/sax/block_handler.rb +0 -2
- data/lib/moxml/sax/element_handler.rb +0 -2
- data/lib/moxml/sax/namespace_splitter.rb +5 -4
- data/lib/moxml/sax.rb +4 -25
- data/lib/moxml/version.rb +1 -1
- data/lib/moxml/xml_utils.rb +1 -3
- data/lib/moxml/xpath/compiler.rb +1 -49
- data/lib/moxml/xpath/conversion.rb +7 -6
- data/lib/moxml/xpath/ruby/generator.rb +12 -19
- data/lib/moxml/xpath/ruby/node.rb +1 -9
- data/lib/moxml/xpath.rb +6 -14
- data/lib/moxml.rb +67 -20
- data/moxml.gemspec +1 -1
- data/spec/moxml/adapter/platform_spec.rb +64 -46
- data/spec/moxml/attribute_spec.rb +16 -0
- data/spec/moxml/context_spec.rb +14 -0
- data/spec/moxml/moxml_spec.rb +13 -0
- data/spec/moxml/node_spec.rb +58 -0
- data/spec/moxml/opal_oga_adapter_spec.rb +14 -0
- data/spec/moxml/opal_oga_features_spec.rb +212 -0
- data/spec/moxml/opal_oga_smoke_spec.rb +35 -0
- data/spec/moxml/xpath/functions/node_functions_spec.rb +1 -1
- data/spec/moxml/xpath/ruby/node_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ed30996109d8cfb8057f216677cba8ca3cd3856287c38b6a7edab3251ebb2064
|
|
4
|
+
data.tar.gz: f93d7c13863ef9d437e40403e4a48434ed1e1c5530ea2424cdeff710740243a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b09c144a268507bb02a16a4c6ba7caf6d1a2fa003718a6fa0960a8b68ba03a09584a66fb9475b1c23cd2d79071f1cc8c313200749f997d317aa90e61fba3811
|
|
7
|
+
data.tar.gz: 6389858a232d82faad5f6bbfd22d4828801c7a6d45a55a2a0f08d28c44647a588b52d2106649d408777453b571815b40c191f48c374cc49b648c58ad2be1e835
|
data/.github/workflows/docs.yml
CHANGED
data/.github/workflows/opal.yml
CHANGED
|
@@ -21,16 +21,33 @@ jobs:
|
|
|
21
21
|
uses: ruby/setup-ruby@v1
|
|
22
22
|
with:
|
|
23
23
|
ruby-version: "3.4"
|
|
24
|
-
bundler-cache
|
|
24
|
+
# NOTE: bundler-cache is disabled because the path-source oga
|
|
25
|
+
# and ruby-ll forks need ragel + ruby-ll outputs generated
|
|
26
|
+
# (rake vendor:prepare) before their C extensions can compile.
|
|
27
|
+
bundler-cache: false
|
|
25
28
|
|
|
26
29
|
- name: Set up Node.js
|
|
27
30
|
uses: actions/setup-node@v4
|
|
28
31
|
with:
|
|
29
32
|
node-version: "18"
|
|
30
33
|
|
|
34
|
+
- name: Install ragel
|
|
35
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
36
|
+
|
|
37
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
38
|
+
run: gem install ruby-ll --no-document
|
|
39
|
+
|
|
40
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
41
|
+
# Run before `bundle install`: the path-source oga/ruby-ll forks
|
|
42
|
+
# gitignore their generated .rb/.c files (parser.rb, lexer.rb,
|
|
43
|
+
# ext/c/lexer.c). bundle install compiles the C extensions via
|
|
44
|
+
# each fork's extconf.rb, which requires ext/c/lexer.c to exist.
|
|
45
|
+
run: rake vendor:prepare
|
|
46
|
+
|
|
31
47
|
- name: Install Opal dependencies
|
|
32
48
|
run: |
|
|
33
49
|
npm list -g opal-compiler || npm install -g opal-compiler
|
|
50
|
+
bundle install
|
|
34
51
|
bundle exec rake opal:generate_entity_data
|
|
35
52
|
|
|
36
53
|
- name: Run Opal tests
|
data/.github/workflows/rake.yml
CHANGED
|
@@ -13,14 +13,43 @@ jobs:
|
|
|
13
13
|
rake:
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
with:
|
|
18
|
+
submodules: "recursive"
|
|
19
|
+
|
|
20
|
+
- name: Set up Ruby
|
|
21
|
+
uses: ruby/setup-ruby@v1
|
|
18
22
|
with:
|
|
19
23
|
ruby-version: "3.3"
|
|
20
|
-
bundler-cache
|
|
24
|
+
# bundler-cache is disabled because the path-source oga
|
|
25
|
+
# and ruby-ll forks need ragel + ruby-ll outputs generated
|
|
26
|
+
# (rake vendor:prepare) before their C extensions can compile.
|
|
27
|
+
bundler-cache: false
|
|
28
|
+
|
|
29
|
+
- name: Install ragel
|
|
30
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
31
|
+
|
|
32
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
33
|
+
run: gem install ruby-ll --no-document
|
|
34
|
+
|
|
35
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
36
|
+
# Run before `bundle install`: the path-source oga/ruby-ll forks
|
|
37
|
+
# gitignore their generated .rb/.c files (parser.rb, lexer.rb,
|
|
38
|
+
# ext/c/lexer.c). bundle install compiles the C extensions via
|
|
39
|
+
# each fork's extconf.rb, which requires ext/c/lexer.c to exist.
|
|
40
|
+
run: rake vendor:prepare
|
|
41
|
+
|
|
21
42
|
- name: Install dependencies
|
|
22
43
|
run: bundle install
|
|
44
|
+
|
|
45
|
+
- name: Compile liboga / libll native extensions
|
|
46
|
+
# Bundler does not reliably build path-source gems' native
|
|
47
|
+
# extensions; compile them explicitly so `require "oga"` (which
|
|
48
|
+
# requires libll) resolves under CRuby.
|
|
49
|
+
run: rake vendor:compile
|
|
50
|
+
|
|
23
51
|
- name: Run fast tests (unit + adapter + integration)
|
|
24
52
|
run: bundle exec rake spec:fast
|
|
53
|
+
|
|
25
54
|
- name: Run rubocop
|
|
26
55
|
run: bundle exec rubocop
|
|
@@ -19,11 +19,34 @@ jobs:
|
|
|
19
19
|
ruby: [ "3.1", "3.2", "3.3", "3.4", "4.0" ]
|
|
20
20
|
category: [ metanorma, rfcxml, niso-jats ]
|
|
21
21
|
steps:
|
|
22
|
-
- uses: actions/checkout@
|
|
23
|
-
|
|
22
|
+
- uses: actions/checkout@v6
|
|
23
|
+
with:
|
|
24
|
+
submodules: "recursive"
|
|
25
|
+
|
|
26
|
+
- name: Set up Ruby
|
|
27
|
+
uses: ruby/setup-ruby@v1
|
|
24
28
|
with:
|
|
25
29
|
ruby-version: ${{ matrix.ruby }}
|
|
26
|
-
bundler-cache
|
|
30
|
+
# bundler-cache is disabled because the path-source oga
|
|
31
|
+
# and ruby-ll forks need ragel + ruby-ll outputs generated
|
|
32
|
+
# (rake vendor:prepare) before their C extensions can compile.
|
|
33
|
+
bundler-cache: false
|
|
34
|
+
|
|
35
|
+
- name: Install ragel
|
|
36
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
37
|
+
|
|
38
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
39
|
+
run: gem install ruby-ll --no-document
|
|
40
|
+
|
|
41
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
42
|
+
run: rake vendor:prepare
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: bundle install
|
|
46
|
+
|
|
47
|
+
- name: Compile liboga / libll native extensions
|
|
48
|
+
run: rake vendor:compile
|
|
49
|
+
|
|
27
50
|
- name: Run round-trip tests (${{ matrix.category }})
|
|
28
51
|
run: bundle exec rspec spec/consistency/ --tag round_trip --tag fixture_category:${{ matrix.category }}
|
|
29
52
|
env:
|
|
@@ -39,11 +62,31 @@ jobs:
|
|
|
39
62
|
ruby: [ "3.3", "4.0" ]
|
|
40
63
|
category: [ metanorma, rfcxml, niso-jats ]
|
|
41
64
|
steps:
|
|
42
|
-
- uses: actions/checkout@
|
|
43
|
-
|
|
65
|
+
- uses: actions/checkout@v6
|
|
66
|
+
with:
|
|
67
|
+
submodules: "recursive"
|
|
68
|
+
|
|
69
|
+
- name: Set up Ruby
|
|
70
|
+
uses: ruby/setup-ruby@v1
|
|
44
71
|
with:
|
|
45
72
|
ruby-version: ${{ matrix.ruby }}
|
|
46
|
-
bundler-cache:
|
|
73
|
+
bundler-cache: false
|
|
74
|
+
|
|
75
|
+
- name: Install ragel
|
|
76
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
77
|
+
|
|
78
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
79
|
+
run: gem install ruby-ll --no-document
|
|
80
|
+
|
|
81
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
82
|
+
run: rake vendor:prepare
|
|
83
|
+
|
|
84
|
+
- name: Install dependencies
|
|
85
|
+
run: bundle install
|
|
86
|
+
|
|
87
|
+
- name: Compile liboga / libll native extensions
|
|
88
|
+
run: rake vendor:compile
|
|
89
|
+
|
|
47
90
|
- name: Run Nokogiri × Ox round-trip tests (${{ matrix.category }})
|
|
48
91
|
run: bundle exec rspec spec/consistency/ --tag round_trip --tag fixture_category:${{ matrix.category }}
|
|
49
92
|
env:
|
|
@@ -61,11 +104,31 @@ jobs:
|
|
|
61
104
|
ruby: [ "3.3", "4.0" ]
|
|
62
105
|
category: [ metanorma, rfcxml, niso-jats ]
|
|
63
106
|
steps:
|
|
64
|
-
- uses: actions/checkout@
|
|
65
|
-
|
|
107
|
+
- uses: actions/checkout@v6
|
|
108
|
+
with:
|
|
109
|
+
submodules: "recursive"
|
|
110
|
+
|
|
111
|
+
- name: Set up Ruby
|
|
112
|
+
uses: ruby/setup-ruby@v1
|
|
66
113
|
with:
|
|
67
114
|
ruby-version: ${{ matrix.ruby }}
|
|
68
|
-
bundler-cache:
|
|
115
|
+
bundler-cache: false
|
|
116
|
+
|
|
117
|
+
- name: Install ragel
|
|
118
|
+
run: sudo apt-get update && sudo apt-get install -y ragel
|
|
119
|
+
|
|
120
|
+
- name: Install ruby-ll (for rake vendor:prepare)
|
|
121
|
+
run: gem install ruby-ll --no-document
|
|
122
|
+
|
|
123
|
+
- name: Generate ragel / ruby-ll outputs in vendored forks
|
|
124
|
+
run: rake vendor:prepare
|
|
125
|
+
|
|
126
|
+
- name: Install dependencies
|
|
127
|
+
run: bundle install
|
|
128
|
+
|
|
129
|
+
- name: Compile liboga / libll native extensions
|
|
130
|
+
run: rake vendor:compile
|
|
131
|
+
|
|
69
132
|
- name: Run Nokogiri × REXML round-trip tests (${{ matrix.category }})
|
|
70
133
|
run: bundle exec rspec spec/consistency/ --tag round_trip --tag fixture_category:${{ matrix.category }}
|
|
71
134
|
env:
|
data/.gitmodules
ADDED
data/.rubocop_todo.yml
CHANGED
|
@@ -675,6 +675,8 @@ RSpec/SpecFilePathFormat:
|
|
|
675
675
|
- '**/spec/routing/**/*'
|
|
676
676
|
- 'spec/moxml/node_type_map_spec.rb'
|
|
677
677
|
- 'spec/moxml/opal_rexml_adapter_spec.rb'
|
|
678
|
+
- 'spec/moxml/opal_oga_adapter_spec.rb'
|
|
679
|
+
- 'spec/moxml/adapter/platform_spec.rb'
|
|
678
680
|
- 'spec/moxml/xpath/ast/node_spec.rb'
|
|
679
681
|
- 'spec/moxml/xpath/cache_spec.rb'
|
|
680
682
|
- 'spec/moxml/xpath/compiler_spec.rb'
|
data/Gemfile
CHANGED
|
@@ -11,11 +11,19 @@ gem "benchmark-ips"
|
|
|
11
11
|
gem "get_process_mem"
|
|
12
12
|
gem "libxml-ruby", "~> 5.0"
|
|
13
13
|
gem "nokogiri", "~> 1.18"
|
|
14
|
-
gem "oga", "~> 3.4"
|
|
15
14
|
gem "openssl", "~> 3.0"
|
|
16
15
|
gem "ox", "~> 2.14"
|
|
17
16
|
gem "rake"
|
|
18
17
|
gem "rexml"
|
|
18
|
+
|
|
19
|
+
# Opal-compatible forks of oga and ruby-ll. The forks add pure-Ruby lexer
|
|
20
|
+
# and driver fallbacks (under ext/pureruby/) plus an Opal-aware conditional
|
|
21
|
+
# in lib/oga.rb / lib/ll/setup.rb that selects the pure-Ruby implementation
|
|
22
|
+
# when RUBY_PLATFORM == 'opal'. Under CRuby/JRuby the forks behave
|
|
23
|
+
# identically to upstream (the conditional falls through to liboga/libll).
|
|
24
|
+
gem "oga", path: "vendor/opal-oga"
|
|
25
|
+
gem "ruby-ll", path: "vendor/opal-ruby-ll"
|
|
26
|
+
|
|
19
27
|
gem "rspec"
|
|
20
28
|
gem "rubocop"
|
|
21
29
|
gem "rubocop-performance"
|
data/README.adoc
CHANGED
|
@@ -889,6 +889,130 @@ performance optimization, and testing strategies, see
|
|
|
889
889
|
link:docs/_pages/best-practices.adoc[Best Practices Guide].
|
|
890
890
|
|
|
891
891
|
|
|
892
|
+
== Running under Opal (JavaScript)
|
|
893
|
+
|
|
894
|
+
Opal compiles Ruby to JavaScript and cannot load C extensions. To run
|
|
895
|
+
Moxml on Opal you need three things: an adapter with no native code, a
|
|
896
|
+
XML library fork that exposes pure-Ruby fallbacks for its lexer and
|
|
897
|
+
parser driver, and an Opal build that puts those pure-Ruby
|
|
898
|
+
implementations on the load path.
|
|
899
|
+
|
|
900
|
+
=== Default adapter under Opal
|
|
901
|
+
|
|
902
|
+
Under `RUBY_ENGINE == "opal"`, Moxml's default adapter is `:oga` (see
|
|
903
|
+
<<Default adapter selection>>). Oga is a pure-Ruby XML parser; under
|
|
904
|
+
standard CRuby its lexer and parsers are accelerated by the `liboga`
|
|
905
|
+
and `libll` C extensions. Those extensions cannot be compiled into
|
|
906
|
+
JavaScript, so on Opal they are replaced by the pure-Ruby fallbacks
|
|
907
|
+
shipped in `ext/pureruby/` of the Opal-compatible forks below.
|
|
908
|
+
|
|
909
|
+
The REXML adapter is also available on Opal (`Moxml.new(:rexml)`) but
|
|
910
|
+
relies on a number of compatibility shims because REXML uses Ruby
|
|
911
|
+
regular-expression features (the `/n` flag, `\u{...}` codepoint
|
|
912
|
+
escapes, inline flag groups) and String APIs that do not all transpile
|
|
913
|
+
to JavaScript today. `:oga` is the recommended path for new Opal
|
|
914
|
+
projects.
|
|
915
|
+
|
|
916
|
+
=== Required XML library forks
|
|
917
|
+
|
|
918
|
+
Upstream https://github.com/yorickpeterse/oga[oga] and
|
|
919
|
+
https://github.com/yorickpeterse/ruby-ll[ruby-ll] do not currently
|
|
920
|
+
ship Opal-compatible fallbacks. Moxml vendors the following forks:
|
|
921
|
+
|
|
922
|
+
* https://github.com/lutaml/opal-oga[lutaml/opal-oga] — oga with an
|
|
923
|
+
`ext/pureruby/oga/native/lexer.rb` fallback that fires when
|
|
924
|
+
`RUBY_PLATFORM == 'opal'`. Under CRuby/JRuby the fork behaves
|
|
925
|
+
identically to upstream oga.
|
|
926
|
+
* https://github.com/lutaml/opal-ruby-ll[lutaml/opal-ruby-ll] —
|
|
927
|
+
ruby-ll with `ext/pureruby/ll/native/{driver,driver_config}.rb`
|
|
928
|
+
fallbacks selected by the same conditional in `lib/ll/setup.rb`.
|
|
929
|
+
|
|
930
|
+
Both forks are vendored as submodules under `vendor/opal-oga` and
|
|
931
|
+
`vendor/opal-ruby-ll` in the Moxml repository. Moxml's own `Gemfile`
|
|
932
|
+
references them via `path:` source so that any consumer of Moxml under
|
|
933
|
+
Opal resolves to the same fork commits Moxml was tested against.
|
|
934
|
+
|
|
935
|
+
=== Wiring the forks in a downstream Gemfile
|
|
936
|
+
|
|
937
|
+
Downstream libraries that run on Opal (for example
|
|
938
|
+
https://github.com/plurimath/plurimath-js[plurimath-js]) must also use
|
|
939
|
+
the Opal-compatible forks rather than upstream `oga` and `ruby-ll`.
|
|
940
|
+
Wire them as `path:` or `git:` sources so the fork's
|
|
941
|
+
`RUBY_PLATFORM == 'opal'` conditional can fire:
|
|
942
|
+
|
|
943
|
+
[source,ruby]
|
|
944
|
+
----
|
|
945
|
+
# In your downstream gem's Gemfile (or gemspec)
|
|
946
|
+
gem "moxml", "~> 0.1.24" # provides the :oga adapter
|
|
947
|
+
gem "oga", git: "https://github.com/lutaml/opal-oga.git",
|
|
948
|
+
ref: "<commit-sha-moxml-tests-against>"
|
|
949
|
+
gem "ruby-ll", git: "https://github.com/lutaml/opal-ruby-ll.git",
|
|
950
|
+
ref: "<commit-sha-moxml-tests-against>"
|
|
951
|
+
----
|
|
952
|
+
|
|
953
|
+
Pin the `ref:` to the submodule commits Moxml ships in
|
|
954
|
+
`vendor/opal-oga` and `vendor/opal-ruby-ll` (recorded in
|
|
955
|
+
`.gitmodules`) so your fork and Moxml's fork stay in lockstep. If you
|
|
956
|
+
prefer to vendor the forks yourself, replace the `git:` source with
|
|
957
|
+
`path: "vendor/opal-oga"` and `path: "vendor/opal-ruby-ll"` after
|
|
958
|
+
copying them in.
|
|
959
|
+
|
|
960
|
+
=== Opal build configuration
|
|
961
|
+
|
|
962
|
+
Under Opal, the forks' `lib/` directory is on the load path (via the
|
|
963
|
+
gem), but the pure-Ruby implementations live under `ext/pureruby/`.
|
|
964
|
+
That directory must be added to Opal's load path so the
|
|
965
|
+
`if RUBY_PLATFORM == 'opal'` branch in `lib/oga.rb` and
|
|
966
|
+
`lib/ll/setup.rb` resolves to the pure-Ruby files instead of trying to
|
|
967
|
+
load the C extension.
|
|
968
|
+
|
|
969
|
+
For consumers using https://github.com/opal/opal[Opal] directly:
|
|
970
|
+
|
|
971
|
+
[source,ruby]
|
|
972
|
+
----
|
|
973
|
+
require "opal"
|
|
974
|
+
|
|
975
|
+
# Opal path: put both lib/ and ext/pureruby/ on the load path so the
|
|
976
|
+
# fork's conditional requires resolve to the pure-Ruby fallback.
|
|
977
|
+
%w[opal-oga opal-ruby-ll].each do |fork|
|
|
978
|
+
Opal.append_path File.expand_path("vendor/#{fork}/lib", __dir__)
|
|
979
|
+
Opal.append_path File.expand_path("vendor/#{fork}/ext/pureruby", __dir__)
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
# Moxml's Opal boot file (lib/compat/opal/moxml_boot.rb) explicitly
|
|
983
|
+
# requires every module that would normally be autoloaded under CRuby.
|
|
984
|
+
require "moxml_boot"
|
|
985
|
+
----
|
|
986
|
+
|
|
987
|
+
For consumers using https://github.com/opal/opal-compiler[Opal via
|
|
988
|
+
Sprockets/Webpack], the equivalent is to add both `lib/` and
|
|
989
|
+
`ext/pureruby/` from each fork to the Opal `paths` array.
|
|
990
|
+
|
|
991
|
+
=== Verifying the Opal build
|
|
992
|
+
|
|
993
|
+
Moxml's own Opal test suite exercises the wiring described above. To
|
|
994
|
+
reproduce:
|
|
995
|
+
|
|
996
|
+
[source,shell]
|
|
997
|
+
----
|
|
998
|
+
# One-time setup: install ragel + ruby-ll so the forks' gitignored
|
|
999
|
+
# generated lexer/parser sources can be produced.
|
|
1000
|
+
gem install ruby-ll --no-document
|
|
1001
|
+
# (Install ragel via your package manager, e.g. apt-get install ragel
|
|
1002
|
+
# or brew install ragel.)
|
|
1003
|
+
|
|
1004
|
+
# Generate the gitignored outputs in the vendored forks.
|
|
1005
|
+
bundle exec rake vendor:prepare
|
|
1006
|
+
|
|
1007
|
+
# Run the Opal (JavaScript) test suite.
|
|
1008
|
+
bundle exec rake spec:opal
|
|
1009
|
+
----
|
|
1010
|
+
|
|
1011
|
+
Reference implementation: https://github.com/plurimath/plurimath-js[plurimath-js]
|
|
1012
|
+
is the canonical downstream consumer; its `Rakefile` and `env/` wrapper
|
|
1013
|
+
scripts show the full pattern end-to-end.
|
|
1014
|
+
|
|
1015
|
+
|
|
892
1016
|
== Specific adapter limitations
|
|
893
1017
|
|
|
894
1018
|
=== Ox adapter
|
data/Rakefile
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
|
-
require "rspec/core/rake_task"
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
# vendor:prepare must be runnable before `bundle install` (CI runs it
|
|
6
|
+
# first so the path-source oga/ruby-ll forks' gitignored lexer/parser
|
|
7
|
+
# outputs exist before their extconf.rb runs). Guard the rspec/opal
|
|
8
|
+
# requires so the file loads with only `rake` + `bundler` available.
|
|
9
|
+
begin
|
|
10
|
+
require "rspec/core/rake_task"
|
|
11
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
12
|
+
rescue LoadError
|
|
13
|
+
end
|
|
7
14
|
|
|
8
15
|
begin
|
|
9
16
|
require "opal/rspec/rake_task"
|
|
@@ -17,15 +24,110 @@ begin
|
|
|
17
24
|
File.exist?(File.join(p, "rexml", "document.rb"))
|
|
18
25
|
end
|
|
19
26
|
Opal.append_path rexml_lib if rexml_lib
|
|
27
|
+
|
|
28
|
+
# The Opal-compatible oga and ruby-ll forks (vendored as submodules)
|
|
29
|
+
# expose pure-Ruby implementations under ext/pureruby/. Their top-level
|
|
30
|
+
# lib/oga.rb and lib/ll/setup.rb conditionally require them when
|
|
31
|
+
# RUBY_PLATFORM == 'opal'. Both lib/ and ext/pureruby/ must be on
|
|
32
|
+
# Opal's load path so the conditional resolves correctly.
|
|
33
|
+
%w[opal-oga opal-ruby-ll].each do |fork_name|
|
|
34
|
+
fork_path = File.expand_path("vendor/#{fork_name}", __dir__)
|
|
35
|
+
Opal.append_path File.join(fork_path, "lib")
|
|
36
|
+
Opal.append_path File.join(fork_path, "ext/pureruby")
|
|
37
|
+
end
|
|
20
38
|
end
|
|
21
39
|
rescue LoadError
|
|
22
40
|
# Opal not available or incompatible with current Ruby version
|
|
23
41
|
end
|
|
24
42
|
|
|
25
|
-
|
|
43
|
+
begin
|
|
44
|
+
require "rubocop/rake_task"
|
|
45
|
+
RuboCop::RakeTask.new
|
|
46
|
+
rescue LoadError
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Regenerate the ragel / ruby-ll outputs that the Opal-compatible forks
|
|
50
|
+
# (vendored as submodules under vendor/) gitignore. The forks ship the
|
|
51
|
+
# grammar sources (.rl / .rll) but not the generated .rb / .c, since
|
|
52
|
+
# those are large and version-controllable upstream. Both ragel and
|
|
53
|
+
# ruby-ll must be on PATH; the upstream ruby-ll gem is sufficient for
|
|
54
|
+
# generation (the fork is only needed at runtime).
|
|
55
|
+
namespace :vendor do
|
|
56
|
+
desc "Generate ragel / ruby-ll outputs in vendored opal-oga and opal-ruby-ll"
|
|
57
|
+
task :prepare do
|
|
58
|
+
require "fileutils"
|
|
59
|
+
|
|
60
|
+
oga = File.expand_path("vendor/opal-oga", __dir__)
|
|
61
|
+
ruby_ll = File.expand_path("vendor/opal-ruby-ll", __dir__)
|
|
62
|
+
|
|
63
|
+
generators = [
|
|
64
|
+
# oga: ruby-ll grammar → Ruby parser
|
|
65
|
+
["ruby-ll #{oga}/lib/oga/xml/parser.rll -o #{oga}/lib/oga/xml/parser.rb",
|
|
66
|
+
"#{oga}/lib/oga/xml/parser.rb",
|
|
67
|
+
"#{oga}/lib/oga/xml/parser.rll"],
|
|
68
|
+
["ruby-ll #{oga}/lib/oga/xpath/parser.rll -o #{oga}/lib/oga/xpath/parser.rb",
|
|
69
|
+
"#{oga}/lib/oga/xpath/parser.rb",
|
|
70
|
+
"#{oga}/lib/oga/xpath/parser.rll"],
|
|
71
|
+
["ruby-ll #{oga}/lib/oga/css/parser.rll -o #{oga}/lib/oga/css/parser.rb",
|
|
72
|
+
"#{oga}/lib/oga/css/parser.rb",
|
|
73
|
+
"#{oga}/lib/oga/css/parser.rll"],
|
|
74
|
+
# oga: ragel Ruby lexer
|
|
75
|
+
["ragel -R -F1 #{oga}/lib/oga/xpath/lexer.rl -o #{oga}/lib/oga/xpath/lexer.rb",
|
|
76
|
+
"#{oga}/lib/oga/xpath/lexer.rb",
|
|
77
|
+
"#{oga}/lib/oga/xpath/lexer.rl"],
|
|
78
|
+
["ragel -R -F1 #{oga}/lib/oga/css/lexer.rl -o #{oga}/lib/oga/css/lexer.rb",
|
|
79
|
+
"#{oga}/lib/oga/css/lexer.rb",
|
|
80
|
+
"#{oga}/lib/oga/css/lexer.rl"],
|
|
81
|
+
# oga: ragel C lexer for liboga
|
|
82
|
+
["ragel -C -I #{oga}/ext/ragel -G2 #{oga}/ext/c/lexer.rl -o #{oga}/ext/c/lexer.c",
|
|
83
|
+
"#{oga}/ext/c/lexer.c",
|
|
84
|
+
"#{oga}/ext/c/lexer.rl"],
|
|
85
|
+
# ruby-ll: ruby-ll grammar → Ruby parser
|
|
86
|
+
["ruby-ll #{ruby_ll}/lib/ll/parser.rll -o #{ruby_ll}/lib/ll/parser.rb --no-requires",
|
|
87
|
+
"#{ruby_ll}/lib/ll/parser.rb",
|
|
88
|
+
"#{ruby_ll}/lib/ll/parser.rll"],
|
|
89
|
+
]
|
|
26
90
|
|
|
27
|
-
|
|
91
|
+
generators.each do |cmd, output, source|
|
|
92
|
+
if File.exist?(output) && File.mtime(output) >= File.mtime(source)
|
|
93
|
+
next
|
|
94
|
+
end
|
|
28
95
|
|
|
96
|
+
FileUtils.mkdir_p(File.dirname(output))
|
|
97
|
+
sh cmd
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Bundler does not reliably compile native extensions for path-source
|
|
102
|
+
# gems. Build liboga/libll explicitly so `require "oga"` resolves.
|
|
103
|
+
desc "Compile liboga / libll native extensions for vendored forks"
|
|
104
|
+
task :compile do
|
|
105
|
+
require "fileutils"
|
|
106
|
+
require "rbconfig"
|
|
107
|
+
|
|
108
|
+
dlext = RbConfig::CONFIG["DLEXT"]
|
|
109
|
+
|
|
110
|
+
{
|
|
111
|
+
"vendor/opal-ruby-ll" => "libll",
|
|
112
|
+
"vendor/opal-oga" => "liboga",
|
|
113
|
+
}.each do |fork_path, ext_name|
|
|
114
|
+
abs_fork = File.expand_path(fork_path, __dir__)
|
|
115
|
+
lib_bundle = File.join(abs_fork, "lib", "#{ext_name}.#{dlext}")
|
|
116
|
+
ext_dir = File.join(abs_fork, "ext", "c")
|
|
117
|
+
extconf = File.join(ext_dir, "extconf.rb")
|
|
118
|
+
lib_dir = File.join(abs_fork, "lib")
|
|
119
|
+
next if File.exist?(lib_bundle)
|
|
120
|
+
|
|
121
|
+
Dir.chdir(ext_dir) do
|
|
122
|
+
sh "ruby #{extconf}"
|
|
123
|
+
sh "make"
|
|
124
|
+
FileUtils.cp("#{ext_name}.#{dlext}", lib_dir)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
if defined?(RSpec)
|
|
29
131
|
namespace :spec do
|
|
30
132
|
if defined?(Opal::RSpec::RakeTask)
|
|
31
133
|
desc "Run Opal (JavaScript) tests"
|
|
@@ -34,12 +136,21 @@ namespace :spec do
|
|
|
34
136
|
server.append_path "spec"
|
|
35
137
|
|
|
36
138
|
runner.default_path = "spec"
|
|
139
|
+
# `oga` and `ll/setup` must be required before moxml_boot so that
|
|
140
|
+
# the forks' Opal-aware conditional requires fire (lib/oga.rb calls
|
|
141
|
+
# `require 'oga/native/lexer'` when RUBY_PLATFORM == 'opal'; that
|
|
142
|
+
# resolves against vendor/opal-oga/ext/pureruby/, which the global
|
|
143
|
+
# Opal.append_path calls above add to the load path).
|
|
37
144
|
runner.requires = %w[rexml_compat rexml/document rexml/xpath
|
|
38
|
-
|
|
145
|
+
oga ll/setup
|
|
146
|
+
moxml_boot spec_helper support/opal]
|
|
39
147
|
runner.files = Dir.glob("spec/moxml/*opal*_spec.rb") +
|
|
40
148
|
Dir.glob("spec/moxml/native_attachment/opal_spec.rb") +
|
|
41
149
|
Dir.glob("spec/moxml/adapter/shared_examples/*.rb")
|
|
42
150
|
end
|
|
151
|
+
|
|
152
|
+
desc "Alias for spec:opal that also runs vendor:prepare"
|
|
153
|
+
task opal: "vendor:prepare"
|
|
43
154
|
end
|
|
44
155
|
|
|
45
156
|
desc "Validate XML fixtures are well-formed (requires xmllint)"
|
|
@@ -124,6 +235,7 @@ namespace :spec do
|
|
|
124
235
|
task all: %i[unit adapter integration consistency examples
|
|
125
236
|
performance]
|
|
126
237
|
end
|
|
238
|
+
end
|
|
127
239
|
|
|
128
240
|
namespace :benchmark do
|
|
129
241
|
desc "Run XPath performance benchmarks"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Opal doesn't support Ruby autoload. This file explicitly requires
|
|
4
|
+
# all Moxml modules that would normally be lazy-loaded via autoload
|
|
5
|
+
# in lib/moxml.rb. Loaded by the Opal Rakefile before spec_helper.
|
|
6
|
+
|
|
7
|
+
require "moxml/version"
|
|
8
|
+
require "moxml/error"
|
|
9
|
+
require "moxml/native_attachment"
|
|
10
|
+
require "moxml/native_attachment/opal"
|
|
11
|
+
require "moxml/xml_utils"
|
|
12
|
+
require "moxml/xml_utils/encoder"
|
|
13
|
+
require "moxml/node"
|
|
14
|
+
require "moxml/node_set"
|
|
15
|
+
require "moxml/document"
|
|
16
|
+
require "moxml/element"
|
|
17
|
+
require "moxml/attribute"
|
|
18
|
+
require "moxml/text"
|
|
19
|
+
require "moxml/cdata"
|
|
20
|
+
require "moxml/comment"
|
|
21
|
+
require "moxml/processing_instruction"
|
|
22
|
+
require "moxml/declaration"
|
|
23
|
+
require "moxml/namespace"
|
|
24
|
+
require "moxml/doctype"
|
|
25
|
+
require "moxml/entity_reference"
|
|
26
|
+
require "moxml/entity_registry"
|
|
27
|
+
require "moxml/adapter"
|
|
28
|
+
require "moxml/adapter/base"
|
|
29
|
+
require "moxml/adapter/customized_rexml"
|
|
30
|
+
require "moxml/adapter/customized_rexml/entity_reference"
|
|
31
|
+
require "moxml/adapter/customized_rexml/formatter"
|
|
32
|
+
require "moxml/sax"
|
|
33
|
+
require "moxml/sax/handler"
|
|
34
|
+
require "moxml/sax/element_handler"
|
|
35
|
+
require "moxml/sax/block_handler"
|
|
36
|
+
require "moxml/sax/namespace_splitter"
|
|
37
|
+
require "moxml/adapter/rexml"
|
|
38
|
+
require "moxml/adapter/customized_oga"
|
|
39
|
+
require "moxml/adapter/customized_oga/xml_declaration"
|
|
40
|
+
require "moxml/adapter/customized_oga/xml_generator"
|
|
41
|
+
require "moxml/adapter/oga"
|
|
42
|
+
require "moxml/document_builder"
|
|
43
|
+
require "moxml/builder"
|
|
44
|
+
require "moxml/context"
|
|
45
|
+
require "moxml/config"
|
|
46
|
+
require "moxml/xpath"
|
|
47
|
+
require "moxml/xpath/engine"
|
|
48
|
+
require "moxml/xpath/context"
|
|
49
|
+
require "moxml/xpath/conversion"
|
|
50
|
+
require "moxml/xpath/cache"
|
|
51
|
+
require "moxml/xpath/lexer"
|
|
52
|
+
require "moxml/xpath/parser"
|
|
53
|
+
require "moxml/xpath/compiler"
|
|
54
|
+
require "moxml/xpath/errors"
|
|
55
|
+
require "moxml/xpath/ast/node"
|
|
56
|
+
require "moxml/xpath/ruby/node"
|
|
57
|
+
require "moxml/xpath/ruby/generator"
|
data/lib/moxml/adapter/base.rb
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "../xml_utils"
|
|
4
|
-
require_relative "../document_builder"
|
|
5
|
-
|
|
6
3
|
module Moxml
|
|
7
4
|
module Adapter
|
|
8
5
|
class Base
|
|
@@ -104,8 +101,7 @@ module Moxml
|
|
|
104
101
|
#
|
|
105
102
|
# @return [Boolean] true if SAX parsing is supported
|
|
106
103
|
def sax_supported?
|
|
107
|
-
|
|
108
|
-
method(:sax_parse).owner != Moxml::Adapter::Base.singleton_class
|
|
104
|
+
method(:sax_parse).owner != Moxml::Adapter::Base.singleton_class
|
|
109
105
|
end
|
|
110
106
|
|
|
111
107
|
def create_document(_native_doc = nil)
|
|
@@ -212,6 +208,10 @@ namespace_validation_mode: :strict)
|
|
|
212
208
|
wrapper.has_xml_declaration
|
|
213
209
|
end
|
|
214
210
|
|
|
211
|
+
# Clear the declaration state from the native document.
|
|
212
|
+
# Called when a Declaration node is removed from a document.
|
|
213
|
+
def remove_declaration(_native_doc); end
|
|
214
|
+
|
|
215
215
|
# Return the actual native node after an add_child operation.
|
|
216
216
|
# Override for adapters where node identity may change (e.g., LibXML doc.root=).
|
|
217
217
|
def actual_native(child_native, _parent_native)
|