dommy 0.5.0 → 0.7.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 +31 -13
- data/lib/dommy/animation.rb +288 -0
- data/lib/dommy/attr.rb +23 -11
- data/lib/dommy/backend/nokogiri_adapter.rb +51 -0
- data/lib/dommy/backend/nokolexbor_adapter.rb +80 -0
- data/lib/dommy/backend.rb +129 -0
- data/lib/dommy/blob.rb +2 -2
- data/lib/dommy/compression_streams.rb +147 -0
- data/lib/dommy/cookie_store.rb +128 -0
- data/lib/dommy/crypto.rb +396 -0
- data/lib/dommy/css.rb +7 -7
- data/lib/dommy/custom_elements.rb +6 -6
- data/lib/dommy/document.rb +190 -32
- data/lib/dommy/dom_parser.rb +5 -4
- data/lib/dommy/element.rb +356 -53
- data/lib/dommy/event.rb +431 -25
- data/lib/dommy/event_source.rb +131 -0
- data/lib/dommy/fetch.rb +76 -6
- data/lib/dommy/file_reader.rb +176 -0
- data/lib/dommy/form_data.rb +1 -3
- data/lib/dommy/history.rb +82 -0
- data/lib/dommy/html_collection.rb +4 -4
- data/lib/dommy/html_elements.rb +130 -67
- data/lib/dommy/internal/cookie_jar.rb +2 -0
- data/lib/dommy/internal/css_pseudo_handlers.rb +28 -0
- data/lib/dommy/internal/dom_matching.rb +4 -4
- data/lib/dommy/internal/idna.rb +443 -0
- data/lib/dommy/internal/idna_data.rb +10379 -0
- data/lib/dommy/internal/ipv4_parser.rb +78 -0
- data/lib/dommy/internal/node_traversal.rb +1 -1
- data/lib/dommy/internal/node_wrapper_cache.rb +23 -12
- data/lib/dommy/internal/observable_callback.rb +25 -0
- data/lib/dommy/internal/punycode.rb +202 -0
- data/lib/dommy/internal/range_text_serializer.rb +72 -0
- data/lib/dommy/internal/reflected_attributes.rb +45 -0
- data/lib/dommy/internal/template_content_registry.rb +6 -6
- data/lib/dommy/intersection_observer.rb +82 -0
- data/lib/dommy/{router.rb → location.rb} +8 -142
- data/lib/dommy/media_query_list.rb +118 -0
- data/lib/dommy/message_channel.rb +249 -0
- data/lib/dommy/{observer.rb → mutation_observer.rb} +21 -11
- data/lib/dommy/navigator.rb +365 -5
- data/lib/dommy/node.rb +12 -0
- data/lib/dommy/notification.rb +89 -0
- data/lib/dommy/parser.rb +13 -13
- data/lib/dommy/performance.rb +146 -0
- data/lib/dommy/performance_observer.rb +55 -0
- data/lib/dommy/range.rb +597 -0
- data/lib/dommy/resize_observer.rb +53 -0
- data/lib/dommy/shadow_root.rb +10 -8
- data/lib/dommy/streams.rb +386 -0
- data/lib/dommy/svg_elements.rb +3863 -0
- data/lib/dommy/text_codec.rb +175 -0
- data/lib/dommy/tree_walker.rb +21 -21
- data/lib/dommy/url.rb +274 -29
- data/lib/dommy/url_pattern.rb +144 -0
- data/lib/dommy/version.rb +1 -1
- data/lib/dommy/web_socket.rb +209 -0
- data/lib/dommy/window.rb +369 -0
- data/lib/dommy/worker.rb +143 -0
- data/lib/dommy/xml_http_request.rb +438 -0
- data/lib/dommy.rb +43 -5
- metadata +44 -29
- data/lib/dommy/world.rb +0 -209
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Dommy
|
|
4
|
+
# `TextEncoder` — encodes a String into UTF-8 bytes.
|
|
5
|
+
# Per spec, only "utf-8" encoding is supported.
|
|
6
|
+
#
|
|
7
|
+
# Spec: https://encoding.spec.whatwg.org/#textencoder
|
|
8
|
+
class TextEncoder
|
|
9
|
+
def encoding
|
|
10
|
+
"utf-8"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# encode(string) → Array<Integer> (bytes).
|
|
14
|
+
# Browsers return a Uint8Array; Dommy returns the equivalent Ruby
|
|
15
|
+
# byte array since there is no typed-array layer.
|
|
16
|
+
def encode(input = "")
|
|
17
|
+
input.to_s.encode(Encoding::UTF_8).bytes
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def __js_get__(key)
|
|
21
|
+
key == "encoding" ? encoding : nil
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def __js_call__(method, args)
|
|
25
|
+
case method
|
|
26
|
+
when "encode"
|
|
27
|
+
encode(args[0])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# `TextDecoder` — decodes bytes into a String. Supports utf-8,
|
|
33
|
+
# utf-16, utf-16le, utf-16be, iso-8859-1 (best-effort).
|
|
34
|
+
#
|
|
35
|
+
# Spec: https://encoding.spec.whatwg.org/#textdecoder
|
|
36
|
+
class TextDecoder
|
|
37
|
+
def initialize(label = "utf-8", _options = nil)
|
|
38
|
+
@encoding = normalize_encoding(label.to_s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def encoding
|
|
42
|
+
@encoding
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# decode(bytes) → String. Accepts Array<Integer> (byte values),
|
|
46
|
+
# a binary String, or anything responding to to_a/bytes.
|
|
47
|
+
def decode(input = nil, _options = nil)
|
|
48
|
+
return "" if input.nil?
|
|
49
|
+
|
|
50
|
+
bytes = case input
|
|
51
|
+
when String
|
|
52
|
+
input.b
|
|
53
|
+
when Array
|
|
54
|
+
input.pack("C*")
|
|
55
|
+
else
|
|
56
|
+
input.respond_to?(:to_a) ? input.to_a.pack("C*") : input.to_s
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
bytes.force_encoding(ruby_encoding).encode(Encoding::UTF_8, invalid: :replace, undef: :replace)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def __js_get__(key)
|
|
63
|
+
key == "encoding" ? encoding : nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def __js_call__(method, args)
|
|
67
|
+
case method
|
|
68
|
+
when "decode"
|
|
69
|
+
decode(args[0], args[1])
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def normalize_encoding(label)
|
|
76
|
+
l = label.downcase.strip
|
|
77
|
+
case l
|
|
78
|
+
when "utf-8", "utf8"
|
|
79
|
+
"utf-8"
|
|
80
|
+
when "utf-16", "utf-16le"
|
|
81
|
+
"utf-16le"
|
|
82
|
+
when "utf-16be"
|
|
83
|
+
"utf-16be"
|
|
84
|
+
when "iso-8859-1", "latin1"
|
|
85
|
+
"iso-8859-1"
|
|
86
|
+
else
|
|
87
|
+
"utf-8"
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def ruby_encoding
|
|
92
|
+
case @encoding
|
|
93
|
+
when "utf-8"
|
|
94
|
+
Encoding::UTF_8
|
|
95
|
+
when "utf-16le"
|
|
96
|
+
Encoding::UTF_16LE
|
|
97
|
+
when "utf-16be"
|
|
98
|
+
Encoding::UTF_16BE
|
|
99
|
+
when "iso-8859-1"
|
|
100
|
+
Encoding::ISO_8859_1
|
|
101
|
+
else
|
|
102
|
+
Encoding::UTF_8
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# `TextEncoderStream` — Stream-shaped wrapper over `TextEncoder`.
|
|
108
|
+
# `write(string)` flushes UTF-8 bytes downstream.
|
|
109
|
+
class TextEncoderStream
|
|
110
|
+
attr_reader :readable, :writable
|
|
111
|
+
|
|
112
|
+
def initialize(window)
|
|
113
|
+
encoder = TextEncoder.new
|
|
114
|
+
@readable = ReadableStream.new(window)
|
|
115
|
+
controller = TransformStreamDefaultController.new(@readable)
|
|
116
|
+
|
|
117
|
+
@writable = WritableStream.new(
|
|
118
|
+
window,
|
|
119
|
+
{
|
|
120
|
+
"write" => proc { |chunk| controller.enqueue(encoder.encode(chunk)) },
|
|
121
|
+
"close" => proc { @readable.__internal_close__ },
|
|
122
|
+
"abort" => proc { |r| @readable.__internal_error__(r) }
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def encoding
|
|
128
|
+
"utf-8"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def __js_get__(key)
|
|
132
|
+
case key
|
|
133
|
+
when "readable"
|
|
134
|
+
@readable
|
|
135
|
+
when "writable"
|
|
136
|
+
@writable
|
|
137
|
+
when "encoding"
|
|
138
|
+
encoding
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# `TextDecoderStream` — Stream-shaped wrapper over `TextDecoder`.
|
|
144
|
+
# `write(bytes)` flushes decoded strings downstream.
|
|
145
|
+
class TextDecoderStream
|
|
146
|
+
attr_reader :readable, :writable, :encoding
|
|
147
|
+
|
|
148
|
+
def initialize(window, label = "utf-8", _options = nil)
|
|
149
|
+
decoder = TextDecoder.new(label)
|
|
150
|
+
@encoding = decoder.encoding
|
|
151
|
+
@readable = ReadableStream.new(window)
|
|
152
|
+
controller = TransformStreamDefaultController.new(@readable)
|
|
153
|
+
|
|
154
|
+
@writable = WritableStream.new(
|
|
155
|
+
window,
|
|
156
|
+
{
|
|
157
|
+
"write" => proc { |chunk| controller.enqueue(decoder.decode(chunk)) },
|
|
158
|
+
"close" => proc { @readable.__internal_close__ },
|
|
159
|
+
"abort" => proc { |r| @readable.__internal_error__(r) }
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def __js_get__(key)
|
|
165
|
+
case key
|
|
166
|
+
when "readable"
|
|
167
|
+
@readable
|
|
168
|
+
when "writable"
|
|
169
|
+
@writable
|
|
170
|
+
when "encoding"
|
|
171
|
+
@encoding
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
data/lib/dommy/tree_walker.rb
CHANGED
|
@@ -45,9 +45,11 @@ module Dommy
|
|
|
45
45
|
# tree rooted at `root` and filter by `whatToShow` + an optional
|
|
46
46
|
# filter callable (or object with `acceptNode`).
|
|
47
47
|
module TreeTraversalCore
|
|
48
|
+
private
|
|
49
|
+
|
|
48
50
|
# Returns FILTER_ACCEPT / FILTER_REJECT / FILTER_SKIP for the
|
|
49
51
|
# given wrapped node.
|
|
50
|
-
def
|
|
52
|
+
def accept(node)
|
|
51
53
|
return NodeFilter::FILTER_REJECT unless node
|
|
52
54
|
return NodeFilter::FILTER_SKIP if (NodeFilter.bitmask_for(node) & @what_to_show) == 0
|
|
53
55
|
|
|
@@ -55,8 +57,6 @@ module Dommy
|
|
|
55
57
|
result || NodeFilter::FILTER_ACCEPT
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
private
|
|
59
|
-
|
|
60
60
|
def invoke_filter(node)
|
|
61
61
|
return NodeFilter::FILTER_ACCEPT if @filter.nil?
|
|
62
62
|
|
|
@@ -92,7 +92,7 @@ module Dommy
|
|
|
92
92
|
def next_node
|
|
93
93
|
node = first_descendant_or_following(@current_node)
|
|
94
94
|
while node
|
|
95
|
-
verdict =
|
|
95
|
+
verdict = accept(node)
|
|
96
96
|
if verdict == NodeFilter::FILTER_ACCEPT
|
|
97
97
|
@current_node = node
|
|
98
98
|
return node
|
|
@@ -109,7 +109,7 @@ module Dommy
|
|
|
109
109
|
def previous_node
|
|
110
110
|
node = preceding(@current_node)
|
|
111
111
|
while node && node != @root
|
|
112
|
-
verdict =
|
|
112
|
+
verdict = accept(node)
|
|
113
113
|
if verdict == NodeFilter::FILTER_ACCEPT
|
|
114
114
|
@current_node = node
|
|
115
115
|
return node
|
|
@@ -124,7 +124,7 @@ module Dommy
|
|
|
124
124
|
def parent_node
|
|
125
125
|
node = wrapped_parent(@current_node)
|
|
126
126
|
while node && reachable_from_root?(node)
|
|
127
|
-
return @current_node = node if
|
|
127
|
+
return @current_node = node if accept(node) == NodeFilter::FILTER_ACCEPT
|
|
128
128
|
|
|
129
129
|
node = wrapped_parent(node)
|
|
130
130
|
end
|
|
@@ -192,7 +192,7 @@ module Dommy
|
|
|
192
192
|
def walk_siblings(start, direction)
|
|
193
193
|
node = start
|
|
194
194
|
while node
|
|
195
|
-
v =
|
|
195
|
+
v = accept(node)
|
|
196
196
|
return @current_node = node if v == NodeFilter::FILTER_ACCEPT
|
|
197
197
|
|
|
198
198
|
node = (v == NodeFilter::FILTER_REJECT) ? nil : send(direction, node)
|
|
@@ -246,30 +246,30 @@ module Dommy
|
|
|
246
246
|
end
|
|
247
247
|
|
|
248
248
|
def wrapped_parent(node)
|
|
249
|
-
parent_nk = node.respond_to?(:
|
|
250
|
-
return nil unless parent_nk && !parent_nk.is_a?(
|
|
249
|
+
parent_nk = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.parent : nil
|
|
250
|
+
return nil unless parent_nk && !parent_nk.is_a?(Backend.document_class)
|
|
251
251
|
|
|
252
252
|
doc = node.instance_variable_get(:@document) || (@root.respond_to?(:document) ? @root.document : @root)
|
|
253
253
|
doc.wrap_node(parent_nk)
|
|
254
254
|
end
|
|
255
255
|
|
|
256
256
|
def first_wrapped_child(node)
|
|
257
|
-
child_nk = node.respond_to?(:
|
|
257
|
+
child_nk = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.children.first : nil
|
|
258
258
|
child_nk && document_for(node).wrap_node(child_nk)
|
|
259
259
|
end
|
|
260
260
|
|
|
261
261
|
def last_wrapped_child(node)
|
|
262
|
-
child_nk = node.respond_to?(:
|
|
262
|
+
child_nk = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.children.last : nil
|
|
263
263
|
child_nk && document_for(node).wrap_node(child_nk)
|
|
264
264
|
end
|
|
265
265
|
|
|
266
266
|
def next_sibling_wrapped(node)
|
|
267
|
-
n = node.respond_to?(:
|
|
267
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.next : nil
|
|
268
268
|
n && document_for(node).wrap_node(n)
|
|
269
269
|
end
|
|
270
270
|
|
|
271
271
|
def previous_sibling_wrapped(node)
|
|
272
|
-
n = node.respond_to?(:
|
|
272
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.previous : nil
|
|
273
273
|
n && document_for(node).wrap_node(n)
|
|
274
274
|
end
|
|
275
275
|
|
|
@@ -306,7 +306,7 @@ module Dommy
|
|
|
306
306
|
|
|
307
307
|
@reference_node = node
|
|
308
308
|
@pointer_before_reference = false
|
|
309
|
-
return node if
|
|
309
|
+
return node if accept(node) == NodeFilter::FILTER_ACCEPT
|
|
310
310
|
end
|
|
311
311
|
end
|
|
312
312
|
|
|
@@ -322,7 +322,7 @@ module Dommy
|
|
|
322
322
|
|
|
323
323
|
@reference_node = node
|
|
324
324
|
@pointer_before_reference = true
|
|
325
|
-
return node if
|
|
325
|
+
return node if accept(node) == NodeFilter::FILTER_ACCEPT
|
|
326
326
|
end
|
|
327
327
|
end
|
|
328
328
|
|
|
@@ -392,28 +392,28 @@ module Dommy
|
|
|
392
392
|
end
|
|
393
393
|
|
|
394
394
|
def first_child_node(node)
|
|
395
|
-
n = node.respond_to?(:
|
|
395
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.children.first : nil
|
|
396
396
|
n && document_for(node).wrap_node(n)
|
|
397
397
|
end
|
|
398
398
|
|
|
399
399
|
def last_child_node(node)
|
|
400
|
-
n = node.respond_to?(:
|
|
400
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.children.last : nil
|
|
401
401
|
n && document_for(node).wrap_node(n)
|
|
402
402
|
end
|
|
403
403
|
|
|
404
404
|
def next_sibling_node(node)
|
|
405
|
-
n = node.respond_to?(:
|
|
405
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.next : nil
|
|
406
406
|
n && document_for(node).wrap_node(n)
|
|
407
407
|
end
|
|
408
408
|
|
|
409
409
|
def previous_sibling_node(node)
|
|
410
|
-
n = node.respond_to?(:
|
|
410
|
+
n = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.previous : nil
|
|
411
411
|
n && document_for(node).wrap_node(n)
|
|
412
412
|
end
|
|
413
413
|
|
|
414
414
|
def parent_node_of(node)
|
|
415
|
-
parent_nk = node.respond_to?(:
|
|
416
|
-
return nil unless parent_nk && !parent_nk.is_a?(
|
|
415
|
+
parent_nk = node.respond_to?(:__dommy_backend_node__) ? node.__dommy_backend_node__.parent : nil
|
|
416
|
+
return nil unless parent_nk && !parent_nk.is_a?(Backend.document_class)
|
|
417
417
|
|
|
418
418
|
document_for(node).wrap_node(parent_nk)
|
|
419
419
|
end
|