opal-browser 0.2.0.beta1 → 0.3.2
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 +5 -5
- data/.github/workflows/build.yml +95 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +17 -3
- data/LICENSE +2 -1
- data/README.md +183 -52
- data/Rakefile +29 -1
- data/config.ru +20 -3
- data/docs/polyfills.md +24 -0
- data/examples/2048/Gemfile +6 -0
- data/examples/2048/README.md +13 -0
- data/examples/2048/app/application.rb +169 -0
- data/examples/2048/config.ru +9 -0
- data/examples/canvas/Gemfile +6 -0
- data/examples/canvas/README.md +9 -0
- data/examples/canvas/app/application.rb +55 -0
- data/examples/canvas/config.ru +9 -0
- data/examples/component/Gemfile +6 -0
- data/examples/component/README.md +10 -0
- data/examples/component/app/application.rb +66 -0
- data/examples/component/config.ru +9 -0
- data/examples/integrations/README.md +24 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/Gemfile +6 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/README.md +16 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/app/application.rb +6 -0
- data/examples/integrations/dynamic-rack-opal-sprockets-server/config.ru +9 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/.gitignore +1 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/Gemfile +7 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/README.md +22 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/Rakefile +4 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/app/application.rb +6 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/app.rb +32 -0
- data/examples/integrations/dynamic-roda-roda-sprockets/config.ru +3 -0
- data/examples/integrations/dynamic-roda-tilt/.gitignore +1 -0
- data/examples/integrations/dynamic-roda-tilt/Gemfile +8 -0
- data/examples/integrations/dynamic-roda-tilt/README.md +17 -0
- data/examples/integrations/dynamic-roda-tilt/Rakefile +6 -0
- data/examples/integrations/dynamic-roda-tilt/app/application.rb +6 -0
- data/examples/integrations/dynamic-roda-tilt/app.rb +50 -0
- data/examples/integrations/dynamic-roda-tilt/config.ru +3 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/Gemfile +7 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/README.md +16 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/app/application.rb +6 -0
- data/examples/integrations/dynamic-sinatra-opal-sprockets-server/config.ru +29 -0
- data/examples/integrations/static-bash/.gitignore +2 -0
- data/examples/integrations/static-bash/Gemfile +3 -0
- data/examples/integrations/static-bash/README.md +8 -0
- data/examples/integrations/static-bash/app/application.rb +6 -0
- data/examples/integrations/static-bash/build.sh +4 -0
- data/examples/integrations/static-bash/index.html +10 -0
- data/examples/integrations/static-bash-opal-parser/.gitignore +3 -0
- data/examples/integrations/static-bash-opal-parser/Gemfile +3 -0
- data/examples/integrations/static-bash-opal-parser/README.md +10 -0
- data/examples/integrations/static-bash-opal-parser/build.sh +4 -0
- data/examples/integrations/static-bash-opal-parser/index.html +19 -0
- data/examples/integrations/static-rake/.gitignore +1 -0
- data/examples/integrations/static-rake/Gemfile +4 -0
- data/examples/integrations/static-rake/README.md +7 -0
- data/examples/integrations/static-rake/Rakefile +10 -0
- data/examples/integrations/static-rake/app/application.rb +6 -0
- data/examples/integrations/static-rake/index.html +9 -0
- data/examples/integrations/static-rake-guard/.gitignore +1 -0
- data/examples/integrations/static-rake-guard/Gemfile +6 -0
- data/examples/integrations/static-rake-guard/Guardfile +3 -0
- data/examples/integrations/static-rake-guard/README.md +10 -0
- data/examples/integrations/static-rake-guard/Rakefile +10 -0
- data/examples/integrations/static-rake-guard/app/application.rb +6 -0
- data/examples/integrations/static-rake-guard/index.html +9 -0
- data/examples/svg/.gitignore +1 -0
- data/examples/svg/Gemfile +4 -0
- data/examples/svg/README.md +7 -0
- data/examples/svg/Rakefile +10 -0
- data/examples/svg/app/application.rb +11 -0
- data/examples/svg/index.html +17 -0
- data/examples/svg/index.svg +6 -0
- data/index.html.erb +8 -6
- data/lib/opal-browser.rb +1 -0
- data/opal/browser/animation_frame.rb +26 -1
- data/opal/browser/audio/node.rb +121 -0
- data/opal/browser/audio/param_schedule.rb +43 -0
- data/opal/browser/audio.rb +66 -0
- data/opal/browser/blob.rb +94 -0
- data/opal/browser/canvas/data.rb +1 -11
- data/opal/browser/canvas/gradient.rb +1 -11
- data/opal/browser/canvas/style.rb +3 -11
- data/opal/browser/canvas/text.rb +1 -11
- data/opal/browser/canvas.rb +17 -13
- data/opal/browser/console.rb +3 -1
- data/opal/browser/cookies.rb +78 -42
- data/opal/browser/crypto.rb +79 -0
- data/opal/browser/css/declaration.rb +1 -1
- data/opal/browser/css/rule.rb +1 -1
- data/opal/browser/css/style_sheet.rb +2 -2
- data/opal/browser/css.rb +23 -7
- data/opal/browser/database/sql.rb +193 -0
- data/opal/browser/delay.rb +41 -7
- data/opal/browser/dom/attribute.rb +13 -12
- data/opal/browser/dom/builder.rb +31 -17
- data/opal/browser/dom/document.rb +174 -42
- data/opal/browser/dom/document_fragment.rb +18 -0
- data/opal/browser/dom/document_or_shadow_root.rb +19 -0
- data/opal/browser/dom/element/attributes.rb +111 -0
- data/opal/browser/dom/element/button.rb +31 -0
- data/opal/browser/dom/element/custom.rb +177 -0
- data/opal/browser/dom/element/data.rb +82 -0
- data/opal/browser/dom/element/editable.rb +47 -0
- data/opal/browser/dom/element/form.rb +38 -0
- data/opal/browser/dom/element/iframe.rb +37 -0
- data/opal/browser/dom/element/image.rb +2 -0
- data/opal/browser/dom/element/input.rb +48 -1
- data/opal/browser/dom/element/media.rb +17 -0
- data/opal/browser/dom/element/offset.rb +5 -0
- data/opal/browser/dom/element/position.rb +11 -2
- data/opal/browser/dom/element/scroll.rb +123 -24
- data/opal/browser/dom/element/select.rb +42 -0
- data/opal/browser/dom/element/size.rb +17 -0
- data/opal/browser/dom/element/template.rb +11 -0
- data/opal/browser/dom/element/textarea.rb +26 -0
- data/opal/browser/dom/element.rb +468 -238
- data/opal/browser/dom/mutation_observer.rb +4 -4
- data/opal/browser/dom/node.rb +142 -60
- data/opal/browser/dom/node_set.rb +73 -44
- data/opal/browser/dom/shadow_root.rb +12 -0
- data/opal/browser/dom/text.rb +2 -2
- data/opal/browser/dom.rb +40 -16
- data/opal/browser/effects.rb +180 -3
- data/opal/browser/event/all.rb +26 -0
- data/opal/browser/{dom/event → event}/animation.rb +4 -2
- data/opal/browser/{dom/event → event}/audio_processing.rb +4 -2
- data/opal/browser/{dom/event → event}/base.rb +98 -9
- data/opal/browser/{dom/event → event}/before_unload.rb +4 -2
- data/opal/browser/{dom/event → event}/clipboard.rb +11 -2
- data/opal/browser/{dom/event → event}/close.rb +4 -2
- data/opal/browser/{dom/event → event}/composition.rb +4 -2
- data/opal/browser/{dom/event → event}/custom.rb +3 -3
- data/opal/browser/event/data_transfer.rb +95 -0
- data/opal/browser/{dom/event → event}/device_light.rb +4 -2
- data/opal/browser/{dom/event → event}/device_motion.rb +4 -2
- data/opal/browser/{dom/event → event}/device_orientation.rb +4 -2
- data/opal/browser/{dom/event → event}/device_proximity.rb +4 -2
- data/opal/browser/{dom/event → event}/drag.rb +11 -7
- data/opal/browser/{dom/event → event}/focus.rb +4 -2
- data/opal/browser/{dom/event → event}/gamepad.rb +5 -3
- data/opal/browser/{dom/event → event}/hash_change.rb +4 -2
- data/opal/browser/{dom/event → event}/keyboard.rb +16 -3
- data/opal/browser/{dom/event → event}/message.rb +4 -2
- data/opal/browser/{dom/event → event}/mouse.rb +12 -8
- data/opal/browser/{dom/event → event}/page_transition.rb +4 -2
- data/opal/browser/{dom/event → event}/pop_state.rb +4 -2
- data/opal/browser/{dom/event → event}/progress.rb +4 -2
- data/opal/browser/{dom/event → event}/sensor.rb +4 -2
- data/opal/browser/{dom/event → event}/storage.rb +4 -2
- data/opal/browser/{dom/event → event}/touch.rb +4 -2
- data/opal/browser/{dom/event → event}/ui.rb +2 -2
- data/opal/browser/{dom/event → event}/wheel.rb +4 -2
- data/opal/browser/event.rb +163 -0
- data/opal/browser/event_source.rb +2 -2
- data/opal/browser/form_data.rb +225 -0
- data/opal/browser/history.rb +4 -8
- data/opal/browser/http/binary.rb +1 -0
- data/opal/browser/http/headers.rb +16 -2
- data/opal/browser/http/request.rb +46 -48
- data/opal/browser/http/response.rb +5 -1
- data/opal/browser/http.rb +25 -2
- data/opal/browser/immediate.rb +9 -5
- data/opal/browser/interval.rb +34 -11
- data/opal/browser/location.rb +7 -1
- data/opal/browser/navigator.rb +127 -7
- data/opal/browser/polyfill/visual_viewport.rb +216 -0
- data/opal/browser/screen.rb +3 -3
- data/opal/browser/setup/base.rb +6 -0
- data/opal/browser/setup/full.rb +13 -0
- data/opal/browser/setup/large.rb +17 -0
- data/opal/browser/setup/mini.rb +8 -0
- data/opal/browser/setup/traditional.rb +10 -0
- data/opal/browser/socket.rb +8 -4
- data/opal/browser/storage.rb +53 -35
- data/opal/browser/support.rb +72 -5
- data/opal/browser/utils.rb +94 -14
- data/opal/browser/version.rb +1 -1
- data/opal/browser/visual_viewport.rb +39 -0
- data/opal/browser/window/size.rb +31 -3
- data/opal/browser/window/view.rb +15 -0
- data/opal/browser/window.rb +46 -25
- data/opal/browser.rb +1 -10
- data/opal/opal-browser.rb +1 -0
- data/opal-browser.gemspec +3 -3
- data/spec/database/sql_spec.rb +139 -0
- data/spec/delay_spec.rb +41 -0
- data/spec/dom/attribute_spec.rb +49 -0
- data/spec/dom/builder_spec.rb +25 -8
- data/spec/dom/document_spec.rb +22 -0
- data/spec/dom/element/attributes_spec.rb +52 -0
- data/spec/dom/element/custom_spec.rb +106 -0
- data/spec/dom/element/subclass_spec.rb +144 -0
- data/spec/dom/element_spec.rb +181 -4
- data/spec/dom/mutation_observer_spec.rb +12 -8
- data/spec/dom/node_set_spec.rb +44 -0
- data/spec/dom/node_spec.rb +48 -0
- data/spec/dom_spec.rb +8 -0
- data/spec/event_source_spec.rb +15 -12
- data/spec/{dom/event_spec.rb → event_spec.rb} +44 -15
- data/spec/history_spec.rb +23 -19
- data/spec/http_spec.rb +19 -31
- data/spec/immediate_spec.rb +5 -4
- data/spec/interval_spec.rb +59 -0
- data/spec/native_cached_wrapper_spec.rb +46 -0
- data/spec/runner.rb +62 -69
- data/spec/socket_spec.rb +16 -12
- data/spec/spec_helper.rb +2 -5
- data/spec/spec_helper_promise.rb.erb +25 -0
- data/spec/storage_spec.rb +1 -1
- metadata +172 -50
- data/.travis.yml +0 -60
- data/opal/browser/dom/event.rb +0 -253
- data/opal/browser/http/parameters.rb +0 -8
- data/opal/browser/window/scroll.rb +0 -59
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
module Browser
|
|
2
|
+
|
|
3
|
+
class Blob
|
|
4
|
+
include NativeCachedWrapper
|
|
5
|
+
|
|
6
|
+
# Create a new blob from anything that Blob API supports
|
|
7
|
+
def self.create(from, options={})
|
|
8
|
+
new(`new Blob(#{Native.convert(from)}, #{options.to_n})`)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# @!attribute [r] size
|
|
12
|
+
# @return [Integer] blob size in bytes
|
|
13
|
+
def size
|
|
14
|
+
`#@native.size`
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @!attribute [r] type
|
|
18
|
+
# @return [String] blob mime type
|
|
19
|
+
def type
|
|
20
|
+
`#@native.type`
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Convert a blob to a UTF-8 encoded string.
|
|
24
|
+
#
|
|
25
|
+
# If block is given it will be called with a parameter once we receive
|
|
26
|
+
# the text. Otherwise return a {Promise} which will resolve once we
|
|
27
|
+
# receive it.
|
|
28
|
+
def text(&block)
|
|
29
|
+
promise = nil
|
|
30
|
+
unless block_given?
|
|
31
|
+
promise = Promise.new
|
|
32
|
+
block = proc { |i| promise.resolve(i) }
|
|
33
|
+
end
|
|
34
|
+
`#@native.text().then(#{block.to_n})`
|
|
35
|
+
promise
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# {Buffer} view into the blob
|
|
39
|
+
#
|
|
40
|
+
# If block is given it will be called with a parameter once we receive
|
|
41
|
+
# the buffer. Otherwise return a {Promise} which will resolve once we
|
|
42
|
+
# receive it.
|
|
43
|
+
def buffer
|
|
44
|
+
promise = nil
|
|
45
|
+
unless block_given?
|
|
46
|
+
promise = Promise.new
|
|
47
|
+
block = proc { |i| promise.resolve(i) }
|
|
48
|
+
end
|
|
49
|
+
resblock = proc { |i| block.call(Buffer.new(i)) }
|
|
50
|
+
`#@native.arrayBuffer().then(#{resblock.to_n})`
|
|
51
|
+
promise
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Create a new blob by slicing this blob
|
|
55
|
+
def slice(start, finish=nil)
|
|
56
|
+
Blob.new(`#@native.slice(#{start}, #{finish})`)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Convert a blob to an URL that can be used to reference this blob in DOM
|
|
60
|
+
# eg. display some multimedia
|
|
61
|
+
def to_url(window=$window)
|
|
62
|
+
`#{window.to_n}.URL.createObjectURL(#@native)`
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Rename a blob and return a {File} with a new name.
|
|
66
|
+
#
|
|
67
|
+
# @return [File] a renamed blob
|
|
68
|
+
def rename(new_filename)
|
|
69
|
+
File.create([self], new_filename, type: type,
|
|
70
|
+
lastModified: respond_to?(:last_modified) ?
|
|
71
|
+
last_modified : Time.now)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class File < Blob
|
|
76
|
+
# Create a new file from anything that File API supports
|
|
77
|
+
def self.create(from, name, options={})
|
|
78
|
+
new(`new File(#{Native.convert(from)}, #{name}, #{options.to_n})`)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @!attribute [r] last_modified
|
|
82
|
+
# @return [Time] last modified date of this file
|
|
83
|
+
def last_modified
|
|
84
|
+
Time.at(`#@native.lastModified`/1000.0)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @!attribute [r] name
|
|
88
|
+
# @return [String] filename
|
|
89
|
+
def name
|
|
90
|
+
`#@native.name`
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
end
|
data/opal/browser/canvas/data.rb
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
3
|
-
# Version 2, December 2004
|
|
4
|
-
#
|
|
5
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
6
|
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
7
|
-
#
|
|
8
|
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
9
|
-
#++
|
|
10
|
-
|
|
11
1
|
module Browser; class Canvas
|
|
12
2
|
|
|
13
3
|
class Data
|
|
@@ -27,7 +17,7 @@ class Data
|
|
|
27
17
|
data
|
|
28
18
|
end
|
|
29
19
|
|
|
30
|
-
include Native
|
|
20
|
+
include Native::Wrapper
|
|
31
21
|
|
|
32
22
|
attr_reader :x, :y, :width, :height
|
|
33
23
|
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
3
|
-
# Version 2, December 2004
|
|
4
|
-
#
|
|
5
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
6
|
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
7
|
-
#
|
|
8
|
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
9
|
-
#++
|
|
10
|
-
|
|
11
1
|
module Browser; class Canvas
|
|
12
2
|
|
|
13
3
|
class Gradient
|
|
14
|
-
include Native
|
|
4
|
+
include Native::Wrapper
|
|
15
5
|
|
|
16
6
|
attr_reader :context
|
|
17
7
|
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
3
|
-
# Version 2, December 2004
|
|
4
|
-
#
|
|
5
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
6
|
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
7
|
-
#
|
|
8
|
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
9
|
-
#++
|
|
10
|
-
|
|
11
1
|
module Browser; class Canvas
|
|
12
2
|
|
|
13
3
|
class StyleObject
|
|
14
|
-
include Native
|
|
4
|
+
include Native::Wrapper
|
|
15
5
|
|
|
16
6
|
attr_reader :context
|
|
17
7
|
|
|
@@ -66,10 +56,12 @@ class Style < StyleObject
|
|
|
66
56
|
|
|
67
57
|
def smooth!
|
|
68
58
|
`#@native.mozImageSmoothingEnabled = #{@smooth = true}`
|
|
59
|
+
`#@native.imageSmoothingEnabled = #{@smooth = true}`
|
|
69
60
|
end
|
|
70
61
|
|
|
71
62
|
def no_smooth!
|
|
72
63
|
`#@native.mozImageSmoothingEnabled = #{@smooth = false}`
|
|
64
|
+
`#@native.imageSmoothingEnabled = #{@smooth = false}`
|
|
73
65
|
end
|
|
74
66
|
end
|
|
75
67
|
|
data/opal/browser/canvas/text.rb
CHANGED
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
3
|
-
# Version 2, December 2004
|
|
4
|
-
#
|
|
5
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
6
|
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
7
|
-
#
|
|
8
|
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
9
|
-
#++
|
|
10
|
-
|
|
11
1
|
module Browser; class Canvas
|
|
12
2
|
|
|
13
3
|
class Text
|
|
14
|
-
include Native
|
|
4
|
+
include Native::Wrapper
|
|
15
5
|
|
|
16
6
|
attr_reader :context
|
|
17
7
|
|
data/opal/browser/canvas.rb
CHANGED
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
#--
|
|
2
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
3
|
-
# Version 2, December 2004
|
|
4
|
-
#
|
|
5
|
-
# DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
|
6
|
-
# TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
|
7
|
-
#
|
|
8
|
-
# 0. You just DO WHAT THE FUCK YOU WANT TO.
|
|
9
|
-
#++
|
|
10
|
-
|
|
11
|
-
require 'promise'
|
|
12
|
-
|
|
13
1
|
require 'browser/canvas/style'
|
|
14
2
|
require 'browser/canvas/text'
|
|
15
3
|
require 'browser/canvas/data'
|
|
@@ -18,7 +6,7 @@ require 'browser/canvas/gradient'
|
|
|
18
6
|
module Browser
|
|
19
7
|
|
|
20
8
|
class Canvas
|
|
21
|
-
include Native
|
|
9
|
+
include Native::Wrapper
|
|
22
10
|
|
|
23
11
|
attr_reader :element, :style, :text
|
|
24
12
|
|
|
@@ -69,6 +57,14 @@ class Canvas
|
|
|
69
57
|
@element[:height].to_i
|
|
70
58
|
end
|
|
71
59
|
|
|
60
|
+
def width=(new_width)
|
|
61
|
+
@element[:width] = new_width.to_i
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def height=(new_height)
|
|
65
|
+
@element[:height] = new_height.to_i
|
|
66
|
+
end
|
|
67
|
+
|
|
72
68
|
def append_to(parent)
|
|
73
69
|
@element.append_to(parent)
|
|
74
70
|
end
|
|
@@ -322,6 +318,14 @@ class Canvas
|
|
|
322
318
|
def to_data(type = undefined)
|
|
323
319
|
`#{@element.to_n}.toDataUrl(type)`
|
|
324
320
|
end
|
|
321
|
+
|
|
322
|
+
def to_dom(*)
|
|
323
|
+
@element
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def on(*args, &block); @element.on(*args, &block); end
|
|
327
|
+
def one(*args, &block); @element.one(*args, &block); end
|
|
328
|
+
def off(*args, &block); @element.off(*args, &block); end
|
|
325
329
|
end
|
|
326
330
|
|
|
327
331
|
Browser::DOM::Builder.for Canvas do |b, item|
|
data/opal/browser/console.rb
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
warn "`console' has been moved to Opal's stdlib, please `require 'console'` instead." if RUBY_ENGINE_VERSION.to_f >= 0.9
|
|
2
|
+
|
|
1
3
|
module Browser
|
|
2
4
|
|
|
3
5
|
# Manipulate the browser console.
|
|
4
6
|
#
|
|
5
7
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/console
|
|
6
8
|
class Console
|
|
7
|
-
include
|
|
9
|
+
include Browser::NativeCachedWrapper
|
|
8
10
|
|
|
9
11
|
# Clear the console.
|
|
10
12
|
def clear
|
data/opal/browser/cookies.rb
CHANGED
|
@@ -1,14 +1,28 @@
|
|
|
1
|
-
require 'stringio'
|
|
2
|
-
|
|
3
1
|
module Browser
|
|
4
2
|
|
|
5
3
|
# Allows manipulation of browser cookies.
|
|
6
4
|
#
|
|
7
5
|
# @see https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
#
|
|
9
|
+
# cookies = $document.cookies
|
|
10
|
+
# cookies["my-cookie"] = "monster"
|
|
11
|
+
# cookies.delete("my-cookie")
|
|
12
|
+
#
|
|
13
|
+
# By default, cookies are stored JSON-encoded. You can supply a `raw:` option
|
|
14
|
+
# whenever you need to access/write the cookies in a raw way, eg.
|
|
15
|
+
#
|
|
16
|
+
# cookies["my-other-cookie", raw: true] = 123
|
|
17
|
+
#
|
|
18
|
+
# You can also set this option while referencing $document.cookies, eg.
|
|
19
|
+
#
|
|
20
|
+
# cookies = $document.cookies(raw: true)
|
|
21
|
+
# cookies["my-other-cookie"] = 123
|
|
8
22
|
class Cookies
|
|
9
23
|
# Default cookie options.
|
|
10
24
|
DEFAULT = {
|
|
11
|
-
expires: Time.now +
|
|
25
|
+
expires: Time.now + 60 * 60 * 24,
|
|
12
26
|
secure: false
|
|
13
27
|
}
|
|
14
28
|
|
|
@@ -19,66 +33,83 @@ class Cookies
|
|
|
19
33
|
# Create a new {Cookies} wrapper.
|
|
20
34
|
#
|
|
21
35
|
# @param document [native] the native document object
|
|
22
|
-
|
|
36
|
+
# @param options [Hash] the default cookie options
|
|
37
|
+
def initialize(document, options = {})
|
|
23
38
|
@document = document
|
|
24
|
-
@options = DEFAULT.
|
|
39
|
+
@options = DEFAULT.merge(options)
|
|
25
40
|
end
|
|
26
41
|
|
|
27
42
|
# Access the cookie with the given name.
|
|
28
43
|
#
|
|
29
44
|
# @param name [String] the name of the cookie
|
|
45
|
+
# @param options [Hash] the options for the cookie
|
|
46
|
+
#
|
|
47
|
+
# @option options [Boolean] :raw get a raw cookie value, don't encode it with JSON
|
|
30
48
|
#
|
|
31
49
|
# @return [Object]
|
|
32
|
-
def [](name)
|
|
33
|
-
|
|
50
|
+
def [](name, options = {})
|
|
51
|
+
options = @options.merge(options)
|
|
52
|
+
|
|
53
|
+
matches = `#@document.cookie`.scan(/#{Regexp.escape(FormData.encode(name))}=([^;]*)/)
|
|
34
54
|
|
|
35
55
|
return if matches.empty?
|
|
36
56
|
|
|
37
|
-
result = matches.map
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
result = matches.flatten.map do |value|
|
|
58
|
+
if options[:raw]
|
|
59
|
+
FormData.decode(value)
|
|
60
|
+
else
|
|
61
|
+
JSON.parse(FormData.decode(value))
|
|
62
|
+
end
|
|
63
|
+
end
|
|
40
64
|
|
|
41
65
|
result.length == 1 ? result.first : result
|
|
42
66
|
end
|
|
43
67
|
|
|
44
68
|
# Set a cookie.
|
|
45
69
|
#
|
|
46
|
-
# Options
|
|
47
|
-
# -------
|
|
48
|
-
# + **max_age** - the max age of the cookie in seconds
|
|
49
|
-
# + **expires** - the expire date as {Time}
|
|
50
|
-
# + **path** - the path where the cookie is valid on
|
|
51
|
-
# + **domain** - the domain where the cookie is valid on
|
|
52
|
-
# + **secure** - whether the cookie is secure or not
|
|
53
|
-
#
|
|
54
70
|
# @param name [String] the name of the cookie
|
|
55
71
|
# @param value [Object] the data to set
|
|
56
72
|
# @param options [Hash] the options for the cookie
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
#
|
|
74
|
+
# @option options [Boolean] :raw don't encode a value with JSON
|
|
75
|
+
# @option options [Integer] :max_age the max age of the cookie in seconds
|
|
76
|
+
# @option options [Time] :expires the expire date
|
|
77
|
+
# @option options [String] :path the path the cookie is valid on
|
|
78
|
+
# @option options [String] :domain the domain the cookie is valid on
|
|
79
|
+
# @option options [Boolean] :secure whether the cookie is secure or not
|
|
80
|
+
def []=(name, options = {}, value)
|
|
81
|
+
options = @options.merge(options)
|
|
82
|
+
if options[:raw]
|
|
83
|
+
string = value.to_s
|
|
84
|
+
else
|
|
85
|
+
string = JSON.dump(value)
|
|
86
|
+
end
|
|
87
|
+
encoded_value = encode(name, string, options)
|
|
88
|
+
`#@document.cookie = #{encoded_value}`
|
|
59
89
|
end
|
|
60
90
|
|
|
61
91
|
# Delete a cookie.
|
|
62
92
|
#
|
|
63
93
|
# @param name [String] the name of the cookie
|
|
64
|
-
def delete(name)
|
|
94
|
+
def delete(name, _options = {})
|
|
65
95
|
`#@document.cookie = #{encode name, '', expires: Time.now}`
|
|
66
96
|
end
|
|
67
97
|
|
|
68
98
|
# @!attribute [r] keys
|
|
69
99
|
# @return [Array<String>] all the cookie names
|
|
70
|
-
def keys
|
|
71
|
-
Array(`#@document.cookie.split(/; /)`).map
|
|
100
|
+
def keys(_options = {})
|
|
101
|
+
Array(`#@document.cookie.split(/; /)`).map do |cookie|
|
|
72
102
|
cookie.split(/\s*=\s*/).first
|
|
73
|
-
|
|
103
|
+
end
|
|
74
104
|
end
|
|
75
105
|
|
|
76
106
|
# @!attribute [r] values
|
|
77
107
|
# @return [Array] all the cookie values
|
|
78
|
-
def values
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
def values(options = {})
|
|
109
|
+
options = @options.merge(options)
|
|
110
|
+
keys.map do |key|
|
|
111
|
+
self[key, options]
|
|
112
|
+
end
|
|
82
113
|
end
|
|
83
114
|
|
|
84
115
|
# Enumerate the cookies.
|
|
@@ -86,13 +117,18 @@ class Cookies
|
|
|
86
117
|
# @yieldparam key [String] the name of the cookie
|
|
87
118
|
# @yieldparam value [String] the value of the cookie
|
|
88
119
|
#
|
|
120
|
+
# @param options [Hash] the options for the cookie
|
|
121
|
+
#
|
|
122
|
+
# @option options [Boolean] :raw don't encode a value with JSON
|
|
123
|
+
#
|
|
89
124
|
# @return [self]
|
|
90
|
-
def each(&block)
|
|
91
|
-
return enum_for :each unless block
|
|
125
|
+
def each(options = {}, &block)
|
|
126
|
+
return enum_for :each, options unless block
|
|
127
|
+
options = @options.merge(options)
|
|
92
128
|
|
|
93
|
-
keys.each
|
|
94
|
-
yield key, self[key]
|
|
95
|
-
|
|
129
|
+
keys.each do |key|
|
|
130
|
+
yield key, self[key, options]
|
|
131
|
+
end
|
|
96
132
|
|
|
97
133
|
self
|
|
98
134
|
end
|
|
@@ -100,35 +136,35 @@ class Cookies
|
|
|
100
136
|
# Delete all the cookies
|
|
101
137
|
#
|
|
102
138
|
# @return [self]
|
|
103
|
-
def clear
|
|
104
|
-
keys.each
|
|
139
|
+
def clear(_options = {})
|
|
140
|
+
keys.each do |key|
|
|
105
141
|
delete key
|
|
106
|
-
|
|
142
|
+
end
|
|
107
143
|
|
|
108
144
|
self
|
|
109
145
|
end
|
|
110
146
|
|
|
111
147
|
protected
|
|
112
148
|
def encode(key, value, options = {})
|
|
113
|
-
io =
|
|
149
|
+
io = []
|
|
114
150
|
|
|
115
|
-
io << key
|
|
151
|
+
io << FormData.encode(key) << ?= << FormData.encode(value) << '; '
|
|
116
152
|
|
|
117
153
|
io << 'max-age=' << options[:max_age] << '; ' if options[:max_age]
|
|
118
|
-
io << 'expires=' << options[:expires].
|
|
154
|
+
io << 'expires=' << options[:expires].utc << '; ' if options[:expires]
|
|
119
155
|
io << 'path=' << options[:path] << '; ' if options[:path]
|
|
120
156
|
io << 'domain=' << options[:domain] << '; ' if options[:domain]
|
|
121
157
|
io << 'secure' if options[:secure]
|
|
122
158
|
|
|
123
|
-
io.
|
|
159
|
+
io.join
|
|
124
160
|
end
|
|
125
161
|
end
|
|
126
162
|
|
|
127
163
|
class DOM::Document < DOM::Element
|
|
128
164
|
# @!attribute [r] cookies
|
|
129
165
|
# @return [Cookies] the cookies for the document
|
|
130
|
-
def cookies
|
|
131
|
-
Cookies.new(@native) if defined?(`#@native.cookie`)
|
|
166
|
+
def cookies(options = {})
|
|
167
|
+
Cookies.new(@native, options) if defined?(`#@native.cookie`)
|
|
132
168
|
end
|
|
133
169
|
end
|
|
134
170
|
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Browser
|
|
2
|
+
|
|
3
|
+
# Implements (parts of) the web crypto interface
|
|
4
|
+
#
|
|
5
|
+
# https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API
|
|
6
|
+
class Crypto
|
|
7
|
+
include NativeCachedWrapper
|
|
8
|
+
|
|
9
|
+
class Digest
|
|
10
|
+
def initialize(buf)
|
|
11
|
+
@buffer = Buffer.new(buf)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :buffer
|
|
15
|
+
|
|
16
|
+
# Convert a digest to a hexadecimal string
|
|
17
|
+
def to_hex
|
|
18
|
+
buffer.to_a.map { |i| "%02x" % i }.join
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Convert a digest to a binary string
|
|
22
|
+
def to_s
|
|
23
|
+
buffer.to_a.map { |i| "%c" % i }.join
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Convert a digest to a Base64-encoded string
|
|
27
|
+
#
|
|
28
|
+
# You will need to `require "base64"`
|
|
29
|
+
def to_b64
|
|
30
|
+
Base64.strict_encode64(to_s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Convert a digest to a urlsafe Base64-encoded string
|
|
34
|
+
#
|
|
35
|
+
# You will need to `require "base64"`
|
|
36
|
+
def to_u64(padding: false)
|
|
37
|
+
Base64.urlsafe_encode64(to_s, padding: padding)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Compute a cryptographic digest of data (a Buffer). If block is given,
|
|
42
|
+
# it will call a block, otherwise it will return a Promise that will
|
|
43
|
+
# return once a digest is computed.
|
|
44
|
+
#
|
|
45
|
+
# Allowed values for algo: SHA-1, SHA-256 (default), SHA-368, SHA-512.
|
|
46
|
+
#
|
|
47
|
+
# The block/promise will be given an argument of type {Digest} which can
|
|
48
|
+
# be used to format a digest.
|
|
49
|
+
#
|
|
50
|
+
# Example:
|
|
51
|
+
# ```
|
|
52
|
+
# Browser::Blob.new(['test']).buffer.then { |b|
|
|
53
|
+
# $window.crypto.digest(b)
|
|
54
|
+
# }.then { |d|
|
|
55
|
+
# puts d.to_hex
|
|
56
|
+
# }
|
|
57
|
+
# ```
|
|
58
|
+
def digest data, algo = 'SHA-256', &block
|
|
59
|
+
promise = nil
|
|
60
|
+
unless block_given?
|
|
61
|
+
promise = Promise.new
|
|
62
|
+
block = proc { |i| promise.resolve(i) }
|
|
63
|
+
end
|
|
64
|
+
resblock = proc { |i| block.call(Digest.new(i)) }
|
|
65
|
+
|
|
66
|
+
`#@native.subtle.digest(algo, #{Native.convert(data)}).then(#{resblock.to_n})`
|
|
67
|
+
promise
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class Window
|
|
72
|
+
# @!attribute [r] crypto
|
|
73
|
+
# @return [Crypto] the crypto interface of this window
|
|
74
|
+
def crypto
|
|
75
|
+
@crypto ||= Crypto.new(`#@native.crypto`)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
end
|
data/opal/browser/css/rule.rb
CHANGED
data/opal/browser/css.rb
CHANGED
|
@@ -4,19 +4,35 @@ require 'browser/css/rule'
|
|
|
4
4
|
require 'browser/css/rule/style'
|
|
5
5
|
|
|
6
6
|
module Kernel
|
|
7
|
-
#
|
|
8
|
-
# {Browser::CSS::Builder} DSL.
|
|
7
|
+
# @overload CSS(document = $document, &block)
|
|
9
8
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
# Create a `<style>` element from a {Paggio::CSS} DSL.
|
|
10
|
+
#
|
|
11
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
12
|
+
# we intend to use
|
|
13
|
+
#
|
|
14
|
+
# @return [Browser::DOM::Element] the created `<style>` element
|
|
15
|
+
#
|
|
16
|
+
# @overload CSS(string, document = $document)
|
|
17
|
+
#
|
|
18
|
+
# Create a `<style>` element from a string.
|
|
19
|
+
#
|
|
20
|
+
# @param document [Browser::DOM::Document] the document instance
|
|
21
|
+
# we intend to use
|
|
22
|
+
#
|
|
23
|
+
# @return [Browser::DOM::Element] the created `<style>` element
|
|
24
|
+
def CSS(*args, &block)
|
|
25
|
+
document = if args.length > 1 || block_given?
|
|
26
|
+
args.pop
|
|
27
|
+
end || $document
|
|
28
|
+
|
|
29
|
+
style = document.create_element(:style)
|
|
14
30
|
style[:type] = 'text/css'
|
|
15
31
|
|
|
16
32
|
if block
|
|
17
33
|
style.inner_text = Paggio.css(&block)
|
|
18
34
|
else
|
|
19
|
-
style.inner_text =
|
|
35
|
+
style.inner_text = args.join("")
|
|
20
36
|
end
|
|
21
37
|
|
|
22
38
|
style
|