dommy 0.8.0 → 0.9.0
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/README.md +3 -3
- data/lib/dommy/animation.rb +4 -0
- data/lib/dommy/attr.rb +11 -5
- data/lib/dommy/backend/makiri_adapter.rb +330 -0
- data/lib/dommy/backend.rb +114 -33
- data/lib/dommy/blob.rb +2 -0
- data/lib/dommy/bridge.rb +11 -0
- data/lib/dommy/browser.rb +217 -0
- data/lib/dommy/compression_streams.rb +4 -0
- data/lib/dommy/crypto.rb +4 -0
- data/lib/dommy/css.rb +487 -50
- data/lib/dommy/custom_elements.rb +2 -2
- data/lib/dommy/data_transfer.rb +2 -0
- data/lib/dommy/data_uri.rb +35 -0
- data/lib/dommy/deferred_response.rb +59 -0
- data/lib/dommy/document.rb +386 -228
- data/lib/dommy/dom_exception.rb +2 -0
- data/lib/dommy/dom_parser.rb +7 -17
- data/lib/dommy/element.rb +502 -155
- data/lib/dommy/event.rb +240 -9
- data/lib/dommy/fetch.rb +152 -34
- data/lib/dommy/form_data.rb +2 -0
- data/lib/dommy/history.rb +2 -0
- data/lib/dommy/html_canvas_element.rb +230 -0
- data/lib/dommy/html_collection.rb +5 -6
- data/lib/dommy/html_elements.rb +304 -27
- data/lib/dommy/interaction/debug.rb +35 -0
- data/lib/dommy/interaction/dom_summary.rb +131 -0
- data/lib/dommy/interaction/driver.rb +244 -0
- data/lib/dommy/interaction/event_synthesis.rb +56 -0
- data/lib/dommy/interaction/field_interactor.rb +117 -0
- data/lib/dommy/interaction/form_submission.rb +268 -0
- data/lib/dommy/interaction/locator.rb +158 -0
- data/lib/dommy/interaction/role_query.rb +58 -0
- data/lib/dommy/interaction.rb +32 -0
- data/lib/dommy/internal/accessibility_tree.rb +215 -0
- data/lib/dommy/internal/accessible_description.rb +38 -0
- data/lib/dommy/internal/accessible_name.rb +301 -0
- data/lib/dommy/internal/aria_role.rb +252 -0
- data/lib/dommy/internal/aria_snapshot.rb +64 -0
- data/lib/dommy/internal/aria_state.rb +151 -0
- data/lib/dommy/internal/css/calc.rb +242 -0
- data/lib/dommy/internal/css/cascade.rb +430 -0
- data/lib/dommy/internal/css/color.rb +381 -0
- data/lib/dommy/internal/css/computed_style_declaration.rb +130 -0
- data/lib/dommy/internal/css/counters.rb +227 -0
- data/lib/dommy/internal/css/custom_properties.rb +183 -0
- data/lib/dommy/internal/css/media_query.rb +302 -0
- data/lib/dommy/internal/css/parser.rb +265 -0
- data/lib/dommy/internal/css/property_registry.rb +512 -0
- data/lib/dommy/internal/css/rule_index.rb +494 -0
- data/lib/dommy/internal/css/supports.rb +158 -0
- data/lib/dommy/internal/css/ua_stylesheet.rb +53 -0
- data/lib/dommy/internal/css_pseudo_handlers.rb +283 -42
- data/lib/dommy/internal/css_rule_text.rb +160 -0
- data/lib/dommy/internal/dom_matching.rb +80 -9
- data/lib/dommy/internal/element_matching.rb +109 -0
- data/lib/dommy/internal/global_functions.rb +33 -0
- data/lib/dommy/internal/mutation_coordinator.rb +95 -4
- data/lib/dommy/internal/namespaces.rb +49 -5
- data/lib/dommy/internal/node_wrapper_cache.rb +163 -26
- data/lib/dommy/internal/parent_node.rb +82 -5
- data/lib/dommy/internal/selector_ast.rb +124 -0
- data/lib/dommy/internal/selector_index.rb +146 -0
- data/lib/dommy/internal/selector_matcher.rb +756 -0
- data/lib/dommy/internal/selector_parser.rb +283 -131
- data/lib/dommy/internal/shadow_root_registry.rb +9 -2
- data/lib/dommy/internal/template_content_registry.rb +26 -18
- data/lib/dommy/internal/xml_serialization.rb +344 -0
- data/lib/dommy/intersection_observer.rb +2 -0
- data/lib/dommy/js/bridge_conformance.rb +80 -0
- data/lib/dommy/js/constructor_resolver.rb +44 -0
- data/lib/dommy/js/custom_element_bridge.rb +90 -0
- data/lib/dommy/js/dom_interfaces.rb +162 -0
- data/lib/dommy/js/handle_table.rb +60 -0
- data/lib/dommy/js/host_bridge.rb +517 -0
- data/lib/dommy/js/host_runtime.js +1495 -0
- data/lib/dommy/js/import_map.rb +58 -0
- data/lib/dommy/js/marshaller.rb +240 -0
- data/lib/dommy/js/module_loader.rb +99 -0
- data/lib/dommy/js/observable_runtime.js +742 -0
- data/lib/dommy/js/runtime.rb +115 -0
- data/lib/dommy/js/script_boot.rb +221 -0
- data/lib/dommy/js/wire_tags.rb +62 -0
- data/lib/dommy/location.rb +2 -0
- data/lib/dommy/media_query_list.rb +50 -14
- data/lib/dommy/message_channel.rb +22 -6
- data/lib/dommy/minitest/assertions.rb +27 -0
- data/lib/dommy/mutation_observer.rb +89 -4
- data/lib/dommy/navigator.rb +34 -2
- data/lib/dommy/node.rb +24 -14
- data/lib/dommy/notification.rb +2 -0
- data/lib/dommy/parser.rb +1 -1
- data/lib/dommy/performance.rb +21 -1
- data/lib/dommy/promise.rb +94 -10
- data/lib/dommy/range.rb +173 -31
- data/lib/dommy/resources.rb +178 -0
- data/lib/dommy/rspec/capy_style_matchers.rb +126 -0
- data/lib/dommy/scheduler.rb +149 -13
- data/lib/dommy/screen.rb +91 -0
- data/lib/dommy/shadow_root.rb +76 -13
- data/lib/dommy/storage.rb +2 -1
- data/lib/dommy/streams.rb +6 -0
- data/lib/dommy/text_codec.rb +7 -1
- data/lib/dommy/tree_walker.rb +33 -10
- data/lib/dommy/url.rb +13 -1
- data/lib/dommy/version.rb +1 -1
- data/lib/dommy/window.rb +199 -11
- data/lib/dommy/worker.rb +8 -4
- data/lib/dommy/xml_http_request.rb +47 -6
- data/lib/dommy.rb +36 -1
- metadata +96 -10
- data/lib/dommy/backend/nokogiri_adapter.rb +0 -127
- data/lib/dommy/backend/nokolexbor_adapter.rb +0 -117
metadata
CHANGED
|
@@ -1,18 +1,52 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dommy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- takahashim
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
-
dependencies:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: makiri
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.5.1
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '1.0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: 0.5.1
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '1.0'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: base64
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '0'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
description: 'A pure Ruby DOM polyfill built on Makiri, inspired by happy-dom and
|
|
47
|
+
jsdom. It gives Ruby tests a browser style DOM with events, MutationObserver, Custom
|
|
48
|
+
Elements, Shadow DOM, the File API, timers, and Storage, without requiring a real
|
|
49
|
+
browser.
|
|
16
50
|
|
|
17
51
|
'
|
|
18
52
|
email:
|
|
@@ -26,12 +60,12 @@ files:
|
|
|
26
60
|
- lib/dommy/animation.rb
|
|
27
61
|
- lib/dommy/attr.rb
|
|
28
62
|
- lib/dommy/backend.rb
|
|
29
|
-
- lib/dommy/backend/
|
|
30
|
-
- lib/dommy/backend/nokolexbor_adapter.rb
|
|
63
|
+
- lib/dommy/backend/makiri_adapter.rb
|
|
31
64
|
- lib/dommy/blob.rb
|
|
32
65
|
- lib/dommy/bridge.rb
|
|
33
66
|
- lib/dommy/bridge/constructor_registry.rb
|
|
34
67
|
- lib/dommy/bridge/methods.rb
|
|
68
|
+
- lib/dommy/browser.rb
|
|
35
69
|
- lib/dommy/callable_invoker.rb
|
|
36
70
|
- lib/dommy/compression_streams.rb
|
|
37
71
|
- lib/dommy/cookie_store.rb
|
|
@@ -39,6 +73,8 @@ files:
|
|
|
39
73
|
- lib/dommy/css.rb
|
|
40
74
|
- lib/dommy/custom_elements.rb
|
|
41
75
|
- lib/dommy/data_transfer.rb
|
|
76
|
+
- lib/dommy/data_uri.rb
|
|
77
|
+
- lib/dommy/deferred_response.rb
|
|
42
78
|
- lib/dommy/document.rb
|
|
43
79
|
- lib/dommy/dom_exception.rb
|
|
44
80
|
- lib/dommy/dom_parser.rb
|
|
@@ -49,11 +85,41 @@ files:
|
|
|
49
85
|
- lib/dommy/file_reader.rb
|
|
50
86
|
- lib/dommy/form_data.rb
|
|
51
87
|
- lib/dommy/history.rb
|
|
88
|
+
- lib/dommy/html_canvas_element.rb
|
|
52
89
|
- lib/dommy/html_collection.rb
|
|
53
90
|
- lib/dommy/html_elements.rb
|
|
91
|
+
- lib/dommy/interaction.rb
|
|
92
|
+
- lib/dommy/interaction/debug.rb
|
|
93
|
+
- lib/dommy/interaction/dom_summary.rb
|
|
94
|
+
- lib/dommy/interaction/driver.rb
|
|
95
|
+
- lib/dommy/interaction/event_synthesis.rb
|
|
96
|
+
- lib/dommy/interaction/field_interactor.rb
|
|
97
|
+
- lib/dommy/interaction/form_submission.rb
|
|
98
|
+
- lib/dommy/interaction/locator.rb
|
|
99
|
+
- lib/dommy/interaction/role_query.rb
|
|
100
|
+
- lib/dommy/internal/accessibility_tree.rb
|
|
101
|
+
- lib/dommy/internal/accessible_description.rb
|
|
102
|
+
- lib/dommy/internal/accessible_name.rb
|
|
103
|
+
- lib/dommy/internal/aria_role.rb
|
|
104
|
+
- lib/dommy/internal/aria_snapshot.rb
|
|
105
|
+
- lib/dommy/internal/aria_state.rb
|
|
54
106
|
- lib/dommy/internal/cookie_jar.rb
|
|
107
|
+
- lib/dommy/internal/css/calc.rb
|
|
108
|
+
- lib/dommy/internal/css/cascade.rb
|
|
109
|
+
- lib/dommy/internal/css/color.rb
|
|
110
|
+
- lib/dommy/internal/css/computed_style_declaration.rb
|
|
111
|
+
- lib/dommy/internal/css/counters.rb
|
|
112
|
+
- lib/dommy/internal/css/custom_properties.rb
|
|
113
|
+
- lib/dommy/internal/css/media_query.rb
|
|
114
|
+
- lib/dommy/internal/css/parser.rb
|
|
115
|
+
- lib/dommy/internal/css/property_registry.rb
|
|
116
|
+
- lib/dommy/internal/css/rule_index.rb
|
|
117
|
+
- lib/dommy/internal/css/supports.rb
|
|
118
|
+
- lib/dommy/internal/css/ua_stylesheet.rb
|
|
55
119
|
- lib/dommy/internal/css_pseudo_handlers.rb
|
|
120
|
+
- lib/dommy/internal/css_rule_text.rb
|
|
56
121
|
- lib/dommy/internal/dom_matching.rb
|
|
122
|
+
- lib/dommy/internal/element_matching.rb
|
|
57
123
|
- lib/dommy/internal/global_functions.rb
|
|
58
124
|
- lib/dommy/internal/idna.rb
|
|
59
125
|
- lib/dommy/internal/idna_data.rb
|
|
@@ -71,11 +137,29 @@ files:
|
|
|
71
137
|
- lib/dommy/internal/range_text_serializer.rb
|
|
72
138
|
- lib/dommy/internal/reflected_attributes.rb
|
|
73
139
|
- lib/dommy/internal/scope_resolution.rb
|
|
140
|
+
- lib/dommy/internal/selector_ast.rb
|
|
141
|
+
- lib/dommy/internal/selector_index.rb
|
|
142
|
+
- lib/dommy/internal/selector_matcher.rb
|
|
74
143
|
- lib/dommy/internal/selector_parser.rb
|
|
75
144
|
- lib/dommy/internal/shadow_root_registry.rb
|
|
76
145
|
- lib/dommy/internal/template_content_registry.rb
|
|
77
146
|
- lib/dommy/internal/url_parser.rb
|
|
147
|
+
- lib/dommy/internal/xml_serialization.rb
|
|
78
148
|
- lib/dommy/intersection_observer.rb
|
|
149
|
+
- lib/dommy/js/bridge_conformance.rb
|
|
150
|
+
- lib/dommy/js/constructor_resolver.rb
|
|
151
|
+
- lib/dommy/js/custom_element_bridge.rb
|
|
152
|
+
- lib/dommy/js/dom_interfaces.rb
|
|
153
|
+
- lib/dommy/js/handle_table.rb
|
|
154
|
+
- lib/dommy/js/host_bridge.rb
|
|
155
|
+
- lib/dommy/js/host_runtime.js
|
|
156
|
+
- lib/dommy/js/import_map.rb
|
|
157
|
+
- lib/dommy/js/marshaller.rb
|
|
158
|
+
- lib/dommy/js/module_loader.rb
|
|
159
|
+
- lib/dommy/js/observable_runtime.js
|
|
160
|
+
- lib/dommy/js/runtime.rb
|
|
161
|
+
- lib/dommy/js/script_boot.rb
|
|
162
|
+
- lib/dommy/js/wire_tags.rb
|
|
79
163
|
- lib/dommy/location.rb
|
|
80
164
|
- lib/dommy/media_query_list.rb
|
|
81
165
|
- lib/dommy/message_channel.rb
|
|
@@ -91,10 +175,12 @@ files:
|
|
|
91
175
|
- lib/dommy/promise.rb
|
|
92
176
|
- lib/dommy/range.rb
|
|
93
177
|
- lib/dommy/resize_observer.rb
|
|
178
|
+
- lib/dommy/resources.rb
|
|
94
179
|
- lib/dommy/rspec.rb
|
|
95
180
|
- lib/dommy/rspec/capy_style_matchers.rb
|
|
96
181
|
- lib/dommy/rspec/matchers.rb
|
|
97
182
|
- lib/dommy/scheduler.rb
|
|
183
|
+
- lib/dommy/screen.rb
|
|
98
184
|
- lib/dommy/shadow_root.rb
|
|
99
185
|
- lib/dommy/storage.rb
|
|
100
186
|
- lib/dommy/streams.rb
|
|
@@ -128,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
128
214
|
- !ruby/object:Gem::Version
|
|
129
215
|
version: '0'
|
|
130
216
|
requirements: []
|
|
131
|
-
rubygems_version: 3.6.
|
|
217
|
+
rubygems_version: 3.6.9
|
|
132
218
|
specification_version: 4
|
|
133
219
|
summary: happy-dom-style DOM polyfill in pure Ruby
|
|
134
220
|
test_files: []
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "nokogiri"
|
|
4
|
-
|
|
5
|
-
module Dommy
|
|
6
|
-
module Backend
|
|
7
|
-
# Nokogiri (libxml2-based) backend. Mature, full XML namespace
|
|
8
|
-
# support. Default backend.
|
|
9
|
-
module Nokogiri
|
|
10
|
-
# Class references for `is_a?` / type-checking from Dommy internals.
|
|
11
|
-
Element = ::Nokogiri::XML::Element
|
|
12
|
-
Document = ::Nokogiri::XML::Document
|
|
13
|
-
Text = ::Nokogiri::XML::Text
|
|
14
|
-
Comment = ::Nokogiri::XML::Comment
|
|
15
|
-
DocumentFragment = ::Nokogiri::XML::DocumentFragment
|
|
16
|
-
Node = ::Nokogiri::XML::Node
|
|
17
|
-
|
|
18
|
-
module_function
|
|
19
|
-
|
|
20
|
-
def parse(html)
|
|
21
|
-
::Nokogiri::HTML5(html.to_s, max_errors: 0)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Parse an XML string into an XML document (DOMParser "text/xml" etc.).
|
|
25
|
-
def parse_xml(xml)
|
|
26
|
-
::Nokogiri::XML(xml.to_s)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def fragment(html, owner_doc:)
|
|
30
|
-
# owner_doc is unused by Nokogiri — the fragment carries its
|
|
31
|
-
# own document. The Parser layer copies nodes into the target.
|
|
32
|
-
::Nokogiri::HTML5.fragment(html.to_s, max_errors: 0)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def create_element(name, doc)
|
|
36
|
-
::Nokogiri::XML::Node.new(name, doc)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def create_text(content, doc)
|
|
40
|
-
::Nokogiri::XML::Text.new(content, doc)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def create_comment(content, doc)
|
|
44
|
-
::Nokogiri::XML::Comment.new(doc, content)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def create_cdata(content, doc)
|
|
48
|
-
::Nokogiri::XML::CDATA.new(doc, content.to_s)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def cdata_class = ::Nokogiri::XML::CDATA
|
|
52
|
-
|
|
53
|
-
def namespace_of(node)
|
|
54
|
-
node.namespace
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def add_namespace_definition(node, prefix, href)
|
|
58
|
-
node.add_namespace_definition(prefix, href)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# ----- Namespaced attributes -----
|
|
62
|
-
|
|
63
|
-
def get_attribute_ns(node, namespace, local_name)
|
|
64
|
-
find_attr_ns(node, namespace, local_name)&.value
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def has_attribute_ns?(node, namespace, local_name)
|
|
68
|
-
!find_attr_ns(node, namespace, local_name).nil?
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def set_attribute_ns(node, namespace, prefix, local_name, qualified_name, value)
|
|
72
|
-
# WHATWG "set an attribute value": when an attribute with this
|
|
73
|
-
# (namespace, localName) already exists, only its value changes —
|
|
74
|
-
# the existing prefix/qualified name is preserved, not replaced by
|
|
75
|
-
# the one in this call.
|
|
76
|
-
existing = find_attr_ns(node, namespace, local_name)
|
|
77
|
-
if existing
|
|
78
|
-
existing.value = value.to_s
|
|
79
|
-
return value.to_s
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
if namespace.nil? || namespace.to_s.empty?
|
|
83
|
-
node[qualified_name] = value.to_s
|
|
84
|
-
return value.to_s
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Defining the namespace before the qualified-name assignment lets
|
|
88
|
-
# libxml2 bind the prefix to it (verified behavior). Reuse an existing
|
|
89
|
-
# matching definition so repeated sets don't pile up declarations.
|
|
90
|
-
node.namespace_definitions.find { |d| d.href == namespace.to_s && d.prefix == prefix } ||
|
|
91
|
-
node.add_namespace_definition(prefix, namespace.to_s)
|
|
92
|
-
node[qualified_name] = value.to_s
|
|
93
|
-
value.to_s
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
def remove_attribute_ns(node, namespace, local_name)
|
|
97
|
-
find_attr_ns(node, namespace, local_name)&.remove
|
|
98
|
-
nil
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def attribute_ns_info(attr_node)
|
|
102
|
-
ns = attr_node.namespace
|
|
103
|
-
{
|
|
104
|
-
namespace_uri: ns&.href,
|
|
105
|
-
prefix: ns&.prefix,
|
|
106
|
-
local_name: attr_node.name,
|
|
107
|
-
qualified_name: ns&.prefix ? "#{ns.prefix}:#{attr_node.name}" : attr_node.name,
|
|
108
|
-
value: attr_node.value,
|
|
109
|
-
}
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def attribute_nodes(node)
|
|
113
|
-
node.attribute_nodes
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# Finds the attribute node matching (namespace, localName). A null
|
|
117
|
-
# namespace matches only the un-namespaced attribute of that local name.
|
|
118
|
-
def find_attr_ns(node, namespace, local_name)
|
|
119
|
-
if namespace.nil? || namespace.to_s.empty?
|
|
120
|
-
node.attribute_nodes.find { |a| a.namespace.nil? && a.name == local_name.to_s }
|
|
121
|
-
else
|
|
122
|
-
node.attribute_with_ns(local_name.to_s, namespace.to_s)
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "nokolexbor"
|
|
4
|
-
|
|
5
|
-
module Dommy
|
|
6
|
-
module Backend
|
|
7
|
-
# Nokolexbor (Lexbor-based) backend. 3-7× faster CSS selectors,
|
|
8
|
-
# 6× faster HTML5 parsing. HTML-only — XML namespaces are not
|
|
9
|
-
# tracked, so SVG detection falls back to ancestor walking.
|
|
10
|
-
module Nokolexbor
|
|
11
|
-
# Class references for `is_a?` / type-checking.
|
|
12
|
-
Element = ::Nokolexbor::Element
|
|
13
|
-
Document = ::Nokolexbor::Document
|
|
14
|
-
Text = ::Nokolexbor::Text
|
|
15
|
-
Comment = ::Nokolexbor::Comment
|
|
16
|
-
DocumentFragment = ::Nokolexbor::DocumentFragment
|
|
17
|
-
Node = ::Nokolexbor::Node
|
|
18
|
-
|
|
19
|
-
# Fake "namespace" wrapper returned for nodes inside <svg> subtrees.
|
|
20
|
-
# Provides the same `href` API that Nokogiri's Namespace object has,
|
|
21
|
-
# so calling code can treat them uniformly.
|
|
22
|
-
SvgNamespace = Struct.new(:href) do
|
|
23
|
-
def initialize
|
|
24
|
-
super("http://www.w3.org/2000/svg")
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
SVG_NAMESPACE = SvgNamespace.new.freeze
|
|
29
|
-
|
|
30
|
-
module_function
|
|
31
|
-
|
|
32
|
-
def parse(html)
|
|
33
|
-
::Nokolexbor.parse(html.to_s)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def fragment(html, owner_doc:)
|
|
37
|
-
::Nokolexbor::DocumentFragment.parse(html.to_s)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def create_element(name, doc)
|
|
41
|
-
::Nokolexbor::Node.new(name, doc)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def create_text(content, doc)
|
|
45
|
-
::Nokolexbor::Text.new(content, doc)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def create_comment(content, doc)
|
|
49
|
-
# Nokolexbor's argument order is (content, doc).
|
|
50
|
-
::Nokolexbor::Comment.new(content, doc)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
# Nokolexbor doesn't track XML namespaces. We synthesize one for
|
|
54
|
-
# SVG by walking ancestors — necessary so `element_class_for`
|
|
55
|
-
# routes SVG tags to their specialized classes.
|
|
56
|
-
def namespace_of(node)
|
|
57
|
-
return nil unless node.respond_to?(:name)
|
|
58
|
-
|
|
59
|
-
in_svg_subtree?(node) ? SVG_NAMESPACE : nil
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def add_namespace_definition(_node, _prefix, _href)
|
|
63
|
-
# No-op: Nokolexbor doesn't support XML namespaces.
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# ----- Namespaced attributes (degraded) -----
|
|
67
|
-
# Nokolexbor has no namespace model, so *AttributeNS collapses to the
|
|
68
|
-
# qualified name in the null namespace. Fine for HTML (all attributes are
|
|
69
|
-
# null-namespace); foreign-content (SVG/MathML) fidelity is lost.
|
|
70
|
-
|
|
71
|
-
def get_attribute_ns(node, _namespace, local_name)
|
|
72
|
-
node[local_name.to_s]
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def has_attribute_ns?(node, _namespace, local_name)
|
|
76
|
-
node.key?(local_name.to_s)
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def set_attribute_ns(node, _namespace, _prefix, _local_name, qualified_name, value)
|
|
80
|
-
node[qualified_name] = value.to_s
|
|
81
|
-
value.to_s
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def remove_attribute_ns(node, _namespace, local_name)
|
|
85
|
-
node.remove_attribute(local_name.to_s) if node.key?(local_name.to_s)
|
|
86
|
-
nil
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def attribute_ns_info(attr_node)
|
|
90
|
-
{
|
|
91
|
-
namespace_uri: nil,
|
|
92
|
-
prefix: nil,
|
|
93
|
-
local_name: attr_node.name,
|
|
94
|
-
qualified_name: attr_node.name,
|
|
95
|
-
value: attr_node.value,
|
|
96
|
-
}
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def attribute_nodes(node)
|
|
100
|
-
node.attribute_nodes
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
# Internal helper — visible to allow testing.
|
|
104
|
-
def in_svg_subtree?(node)
|
|
105
|
-
return true if node.name.to_s.downcase == "svg"
|
|
106
|
-
|
|
107
|
-
current = node.parent
|
|
108
|
-
while current
|
|
109
|
-
return true if current.respond_to?(:name) && current.name.to_s.downcase == "svg"
|
|
110
|
-
current = current.respond_to?(:parent) ? current.parent : nil
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
false
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|