opal-vite 0.3.13 → 0.3.15
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/lib/opal/vite/compiler.rb +20 -1
- data/lib/opal/vite/version.rb +1 -1
- data/lib/opal-vite.rb +4 -2
- data/opal/opal_vite/compat/opal_stimulus.rb +168 -0
- data/opal/opal_vite/concerns/v1/action_cable_helpers.rb +1 -1
- data/opal/opal_vite/concerns/v1/base64_helpers.rb +10 -8
- data/opal/opal_vite/concerns/v1/react_helpers.rb +4 -1
- data/opal/opal_vite/concerns/v1/stimulus_helpers.rb +24 -4
- data/opal/opal_vite/concerns/v1/storable.rb +1 -1
- data/opal/opal_vite/concerns/v1/turbo_helpers.rb +7 -1
- data/opal/opal_vite/concerns/v1/uri_helpers.rb +4 -4
- data/opal/opal_vite/concerns/v1/vue_helpers.rb +4 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ff5610634e2852d6053397650789a4873d1dfa2faf891c634503849531a0a0c
|
|
4
|
+
data.tar.gz: f8169727ae99fb3faa4f9bd75e48786b667b1ad2c4cd261a985b411c60bbea6c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 485d95f570220009668240c82cf363dbf092b743601045b78820c1b0628f041d4b1bda86393eaac16156261cd794190d062392f2303af0338b89646658f3c62c
|
|
7
|
+
data.tar.gz: e2970ff1eaaa5828ccc128f564aab1a1ce8b628300d480731aae8f6eaee6df094c2253940914b39049ebc5424efd188c316bfed4af0bba3a90c1fdc42e8d7d44
|
data/lib/opal/vite/compiler.rb
CHANGED
|
@@ -12,6 +12,10 @@ module Opal
|
|
|
12
12
|
@config = options[:config] || Opal::Vite.config
|
|
13
13
|
@include_concerns = options.fetch(:include_concerns, true)
|
|
14
14
|
@stubs = options.fetch(:stubs, [])
|
|
15
|
+
# When true, Opal's corelib is treated as already loaded and left out
|
|
16
|
+
# of the output. The Vite plugin then imports the shared runtime
|
|
17
|
+
# (`/@opal-runtime`) instead, so corelib is only loaded once.
|
|
18
|
+
@external_runtime = options.fetch(:external_runtime, false)
|
|
15
19
|
end
|
|
16
20
|
|
|
17
21
|
# Compile Ruby source code to JavaScript
|
|
@@ -20,6 +24,7 @@ module Opal
|
|
|
20
24
|
begin
|
|
21
25
|
# Use Opal::Builder and add the file's directory to load paths
|
|
22
26
|
builder = Opal::Builder.new(stubs: @stubs)
|
|
27
|
+
builder.prerequired = self.class.runtime_requires if @external_runtime
|
|
23
28
|
|
|
24
29
|
# Add the directory containing the file to load paths
|
|
25
30
|
# This allows require statements to work relative to the file
|
|
@@ -68,10 +73,24 @@ module Opal
|
|
|
68
73
|
end
|
|
69
74
|
|
|
70
75
|
# Get the Opal runtime code
|
|
76
|
+
#
|
|
77
|
+
# The runtime's entry file (opal.rb) is not registered as a requirable
|
|
78
|
+
# module, so mark it as loaded explicitly. Otherwise `require 'opal'` in
|
|
79
|
+
# a bundle compiled with external_runtime raises LoadError at runtime.
|
|
71
80
|
def self.runtime_code
|
|
72
81
|
builder = Opal::Builder.new
|
|
73
82
|
builder.build('opal')
|
|
74
|
-
builder.to_s
|
|
83
|
+
"#{builder.to_s}\nOpal.loaded([\"opal\"]);\n"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Logical require paths that are part of runtime_code (opal itself and
|
|
87
|
+
# the corelib files it pulls in).
|
|
88
|
+
def self.runtime_requires
|
|
89
|
+
@runtime_requires ||= begin
|
|
90
|
+
builder = Opal::Builder.new
|
|
91
|
+
builder.build('opal')
|
|
92
|
+
['opal', *builder.already_processed.to_a].freeze
|
|
93
|
+
end
|
|
75
94
|
end
|
|
76
95
|
|
|
77
96
|
private
|
data/lib/opal/vite/version.rb
CHANGED
data/lib/opal-vite.rb
CHANGED
|
@@ -32,12 +32,14 @@ module Opal
|
|
|
32
32
|
# @param include_concerns [Boolean] Whether to include built-in concerns
|
|
33
33
|
# @param source_map [Boolean] Whether to generate source maps
|
|
34
34
|
# @param stubs [Array<String>] List of modules to stub (return empty implementations)
|
|
35
|
-
|
|
35
|
+
# @param external_runtime [Boolean] Leave Opal's corelib out of the output
|
|
36
|
+
# (the caller loads it separately, e.g. via the `/@opal-runtime` module)
|
|
37
|
+
def compile_for_vite(file_path, include_concerns: true, source_map: true, stubs: [], external_runtime: false)
|
|
36
38
|
# Temporarily override source map setting if specified
|
|
37
39
|
original_source_map = config.source_map_enabled
|
|
38
40
|
config.source_map_enabled = source_map
|
|
39
41
|
|
|
40
|
-
compiler = Compiler.new(include_concerns: include_concerns, stubs: stubs)
|
|
42
|
+
compiler = Compiler.new(include_concerns: include_concerns, stubs: stubs, external_runtime: external_runtime)
|
|
41
43
|
result = compiler.compile_file(file_path)
|
|
42
44
|
|
|
43
45
|
# Output JSON to stdout for the Vite plugin to consume
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# backtick_javascript: true
|
|
2
|
+
#
|
|
3
|
+
# Fixes for opal_stimulus (0.2.x) accessors that look up the wrong
|
|
4
|
+
# JavaScript property for multi-word names.
|
|
5
|
+
#
|
|
6
|
+
# opal_stimulus builds names such as "hasSoundButtonTarget" with
|
|
7
|
+
# String#capitalize, which lowercases the rest of the word ("hasSoundbuttonTarget"),
|
|
8
|
+
# and passes snake_case value names straight to Stimulus. As a result:
|
|
9
|
+
#
|
|
10
|
+
# - has_*_target / has_*_outlet / has_*_class always return undefined for
|
|
11
|
+
# multi-word names
|
|
12
|
+
# - multi-word values read and write the wrong property, use the wrong
|
|
13
|
+
# data attribute, and never fire *_value_changed
|
|
14
|
+
# - dashed outlet names (e.g. "user-status") read the wrong property and never
|
|
15
|
+
# fire *_outlet_connected / *_outlet_disconnected
|
|
16
|
+
#
|
|
17
|
+
# Usage (after opal_stimulus, before defining controllers):
|
|
18
|
+
#
|
|
19
|
+
# require 'opal_stimulus/stimulus_controller'
|
|
20
|
+
# require 'opal_vite/compat/opal_stimulus'
|
|
21
|
+
#
|
|
22
|
+
# Values declared as `self.values = { latest_paid: :number }` then map to
|
|
23
|
+
# Stimulus' latestPaidValue / data-<controller>-latest-paid-value, as they
|
|
24
|
+
# would in a JavaScript controller.
|
|
25
|
+
require 'opal_stimulus/stimulus_controller'
|
|
26
|
+
|
|
27
|
+
module OpalVite
|
|
28
|
+
module Compat
|
|
29
|
+
module OpalStimulus
|
|
30
|
+
# "soundButton" -> "SoundButton" (String#capitalize gives "Soundbutton")
|
|
31
|
+
def self.upcase_first(name)
|
|
32
|
+
str = name.to_s
|
|
33
|
+
str.empty? ? str : str[0].upcase + str[1..-1]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Stimulus' camelize: "latest_paid" / "user-status" -> "latestPaid" / "userStatus"
|
|
37
|
+
def self.camelize(name)
|
|
38
|
+
name.to_s.gsub(/[_-]([a-z0-9])/) { $1.upcase }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Stimulus' namespaceCamelize for outlet names ("admin--user-status" -> "adminUserStatus")
|
|
42
|
+
def self.namespace_camelize(name)
|
|
43
|
+
camelize(name.to_s.gsub('--', '-').gsub('__', '_'))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
module ClassMethods
|
|
47
|
+
def targets=(targets = [])
|
|
48
|
+
super
|
|
49
|
+
|
|
50
|
+
targets.each do |target|
|
|
51
|
+
has_prop = "has#{OpalStimulus.upcase_first(target)}Target"
|
|
52
|
+
define_method("has_#{to_ruby_name(target)}_target") do
|
|
53
|
+
`this[#{has_prop}]`
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def outlets=(outlets = [])
|
|
59
|
+
super
|
|
60
|
+
|
|
61
|
+
outlets.each do |outlet|
|
|
62
|
+
ruby_name = to_ruby_name(outlet).tr('-', '_')
|
|
63
|
+
js_name = OpalStimulus.namespace_camelize(outlet)
|
|
64
|
+
outlet_prop = "#{js_name}Outlet"
|
|
65
|
+
outlets_prop = "#{js_name}Outlets"
|
|
66
|
+
has_prop = "has#{OpalStimulus.upcase_first(js_name)}Outlet"
|
|
67
|
+
|
|
68
|
+
define_method("#{ruby_name}_outlet") do
|
|
69
|
+
`this[#{outlet_prop}]`
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
define_method("#{ruby_name}_outlets") do
|
|
73
|
+
`this[#{outlets_prop}]`
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
define_method("has_#{ruby_name}_outlet") do
|
|
77
|
+
`this[#{has_prop}]`
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Stimulus calls the camelized callbacks; forward them to Ruby.
|
|
81
|
+
["connected", "disconnected"].each do |event|
|
|
82
|
+
snake_case_callback = "#{ruby_name}_outlet_#{event}"
|
|
83
|
+
camel_case_callback = "#{js_name}Outlet#{OpalStimulus.upcase_first(event)}"
|
|
84
|
+
%x{
|
|
85
|
+
#{stimulus_controller}.prototype[#{camel_case_callback}] = function(outlet, element) {
|
|
86
|
+
if (this['$respond_to?'] && this['$respond_to?'](#{snake_case_callback})) {
|
|
87
|
+
return this['$' + #{snake_case_callback}](outlet, element);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Stimulus uses the class key as-is for xxxClass / xxxClasses, so only
|
|
96
|
+
# the has_ accessor needs fixing.
|
|
97
|
+
def classes=(class_names = [])
|
|
98
|
+
super
|
|
99
|
+
|
|
100
|
+
class_names.each do |class_name|
|
|
101
|
+
has_prop = "has#{OpalStimulus.upcase_first(class_name)}Class"
|
|
102
|
+
define_method("has_#{to_ruby_name(class_name)}_class") do
|
|
103
|
+
`this[#{has_prop}]`
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Replaces (does not wrap) the original: the original registers
|
|
109
|
+
# snake_case keys with Stimulus, which changes the data attribute
|
|
110
|
+
# name, so it cannot be fixed after the fact.
|
|
111
|
+
def values=(values_hash = {})
|
|
112
|
+
js_values = {}
|
|
113
|
+
|
|
114
|
+
values_hash.each do |name, type|
|
|
115
|
+
ruby_name = to_ruby_name(name)
|
|
116
|
+
js_name = OpalStimulus.camelize(ruby_name)
|
|
117
|
+
|
|
118
|
+
js_type = case type
|
|
119
|
+
when :string then `String`
|
|
120
|
+
when :number then `Number`
|
|
121
|
+
when :boolean then `Boolean`
|
|
122
|
+
when :array then `Array`
|
|
123
|
+
when :object then `Object`
|
|
124
|
+
else
|
|
125
|
+
raise ArgumentError,
|
|
126
|
+
"Unsupported value type: #{type}, please use :string, :number, :boolean, :array, or :object"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
js_values[js_name] = js_type
|
|
130
|
+
|
|
131
|
+
value_prop = "#{js_name}Value"
|
|
132
|
+
has_prop = "has#{OpalStimulus.upcase_first(js_name)}Value"
|
|
133
|
+
|
|
134
|
+
define_method("#{ruby_name}_value") do
|
|
135
|
+
Native(`this[#{value_prop}]`)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
define_method("#{ruby_name}_value=") do |value|
|
|
139
|
+
Native(`this[#{value_prop}] = #{value}`)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
define_method("has_#{ruby_name}") do
|
|
143
|
+
`this[#{has_prop}]`
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
snake_case_changed = "#{ruby_name}_value_changed"
|
|
147
|
+
camel_case_changed = "#{js_name}ValueChanged"
|
|
148
|
+
%x{
|
|
149
|
+
#{stimulus_controller}.prototype[#{camel_case_changed}] = function(value, previousValue) {
|
|
150
|
+
if (#{type == :object}) {
|
|
151
|
+
value = JSON.stringify(value)
|
|
152
|
+
previousValue = JSON.stringify(previousValue)
|
|
153
|
+
}
|
|
154
|
+
if (this['$respond_to?'] && this['$respond_to?'](#{snake_case_changed})) {
|
|
155
|
+
return this['$' + #{snake_case_changed}](value, previousValue);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
`#{stimulus_controller}.values = #{js_values.to_n}`
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
StimulusController.singleton_class.prepend(OpalVite::Compat::OpalStimulus::ClassMethods)
|
|
@@ -29,7 +29,7 @@ module OpalVite
|
|
|
29
29
|
# @return [String] Base64 encoded string
|
|
30
30
|
def base64_encode(str)
|
|
31
31
|
`btoa(#{str})`
|
|
32
|
-
rescue
|
|
32
|
+
rescue Exception
|
|
33
33
|
nil
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -38,7 +38,7 @@ module OpalVite
|
|
|
38
38
|
# @return [String] Decoded string
|
|
39
39
|
def base64_decode(str)
|
|
40
40
|
`atob(#{str})`
|
|
41
|
-
rescue
|
|
41
|
+
rescue Exception
|
|
42
42
|
nil
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -81,7 +81,7 @@ module OpalVite
|
|
|
81
81
|
def base64_encode_unicode(str)
|
|
82
82
|
# Convert to UTF-8 bytes, then encode
|
|
83
83
|
`btoa(unescape(encodeURIComponent(#{str})))`
|
|
84
|
-
rescue
|
|
84
|
+
rescue Exception
|
|
85
85
|
nil
|
|
86
86
|
end
|
|
87
87
|
|
|
@@ -90,7 +90,7 @@ module OpalVite
|
|
|
90
90
|
# @return [String] Decoded Unicode string
|
|
91
91
|
def base64_decode_unicode(str)
|
|
92
92
|
`decodeURIComponent(escape(atob(#{str})))`
|
|
93
|
-
rescue
|
|
93
|
+
rescue Exception
|
|
94
94
|
nil
|
|
95
95
|
end
|
|
96
96
|
|
|
@@ -108,7 +108,7 @@ module OpalVite
|
|
|
108
108
|
}
|
|
109
109
|
return btoa(binary);
|
|
110
110
|
`
|
|
111
|
-
rescue
|
|
111
|
+
rescue Exception
|
|
112
112
|
nil
|
|
113
113
|
end
|
|
114
114
|
|
|
@@ -124,7 +124,7 @@ module OpalVite
|
|
|
124
124
|
}
|
|
125
125
|
return bytes;
|
|
126
126
|
`
|
|
127
|
-
rescue
|
|
127
|
+
rescue Exception
|
|
128
128
|
nil
|
|
129
129
|
end
|
|
130
130
|
|
|
@@ -202,7 +202,7 @@ module OpalVite
|
|
|
202
202
|
return nil unless payload_json
|
|
203
203
|
|
|
204
204
|
`JSON.parse(#{payload_json})`
|
|
205
|
-
rescue
|
|
205
|
+
rescue Exception
|
|
206
206
|
nil
|
|
207
207
|
end
|
|
208
208
|
|
|
@@ -264,7 +264,9 @@ module OpalVite
|
|
|
264
264
|
|
|
265
265
|
len = str.length
|
|
266
266
|
padding = str.end_with?('==') ? 2 : (str.end_with?('=') ? 1 : 0)
|
|
267
|
-
|
|
267
|
+
# Use integer division: in Opal `len * 3 / 4` is JS float division, so
|
|
268
|
+
# unpadded/URL-safe input (len % 4 == 2 or 3) would yield e.g. 16.5.
|
|
269
|
+
((len * 3) / 4).floor - padding
|
|
268
270
|
end
|
|
269
271
|
end
|
|
270
272
|
end
|
|
@@ -275,7 +275,10 @@ module OpalVite
|
|
|
275
275
|
|
|
276
276
|
# Stringify to JSON
|
|
277
277
|
def to_json(object)
|
|
278
|
-
|
|
278
|
+
# Convert Ruby Hash/Array to a native JS value first; passing a raw
|
|
279
|
+
# Opal Hash to JSON.stringify serializes to "{}" (silent data loss).
|
|
280
|
+
native = object.respond_to?(:to_n) ? object.to_n : object
|
|
281
|
+
`JSON.stringify(#{native})`
|
|
279
282
|
end
|
|
280
283
|
|
|
281
284
|
# ===================
|
|
@@ -857,11 +857,12 @@ module OpalVite
|
|
|
857
857
|
end
|
|
858
858
|
|
|
859
859
|
# Call a method on a JavaScript object
|
|
860
|
-
# @param obj [
|
|
860
|
+
# @param obj [Object] JavaScript object (raw, Native or JS::Proxy)
|
|
861
861
|
# @param method [Symbol, String] Method name
|
|
862
862
|
# @param args [Array] Arguments to pass
|
|
863
863
|
# @return [Native] Method return value
|
|
864
864
|
def js_call_on(obj, method, *args)
|
|
865
|
+
obj = to_native_element(obj)
|
|
865
866
|
if args.empty?
|
|
866
867
|
`#{obj}[#{method.to_s}]()`
|
|
867
868
|
else
|
|
@@ -871,21 +872,40 @@ module OpalVite
|
|
|
871
872
|
end
|
|
872
873
|
|
|
873
874
|
# Get a property from a JavaScript object
|
|
874
|
-
#
|
|
875
|
+
#
|
|
876
|
+
# Unlike calling the property as a method on a JS::Proxy (e.g. the
|
|
877
|
+
# elements opal_stimulus' `*_target` methods return), a missing property
|
|
878
|
+
# does not raise NoMethodError; you get JavaScript's undefined.
|
|
879
|
+
#
|
|
880
|
+
# @param obj [Object] JavaScript object (raw, Native or JS::Proxy)
|
|
875
881
|
# @param prop [Symbol, String] Property name
|
|
876
|
-
# @return [
|
|
882
|
+
# @return [Object] Raw property value (may be undefined)
|
|
877
883
|
def js_get(obj, prop)
|
|
884
|
+
obj = to_native_element(obj)
|
|
878
885
|
`#{obj}[#{prop.to_s}]`
|
|
879
886
|
end
|
|
880
887
|
|
|
881
888
|
# Set a property on a JavaScript object
|
|
882
|
-
# @param obj [
|
|
889
|
+
# @param obj [Object] JavaScript object (raw, Native or JS::Proxy)
|
|
883
890
|
# @param prop [Symbol, String] Property name
|
|
884
891
|
# @param value [Object] Value to set
|
|
885
892
|
def js_set(obj, prop, value)
|
|
893
|
+
obj = to_native_element(obj)
|
|
886
894
|
`#{obj}[#{prop.to_s}] = #{value}`
|
|
887
895
|
end
|
|
888
896
|
|
|
897
|
+
# Read a data-* attribute through element.dataset
|
|
898
|
+
# @param element [Object] DOM element (raw, Native or JS::Proxy)
|
|
899
|
+
# @param key [Symbol, String] Attribute name without "data-", in
|
|
900
|
+
# snake_case or camelCase (:confirm_message and :confirmMessage both
|
|
901
|
+
# read data-confirm-message)
|
|
902
|
+
# @return [String, nil] The attribute value, or nil when it is absent
|
|
903
|
+
def dataset_value(element, key)
|
|
904
|
+
el = to_native_element(element)
|
|
905
|
+
name = camelize(key, false)
|
|
906
|
+
`(#{el}.dataset[#{name}] == null) ? nil : #{el}.dataset[#{name}]`
|
|
907
|
+
end
|
|
908
|
+
|
|
889
909
|
# ===== JSON Methods =====
|
|
890
910
|
|
|
891
911
|
# Parse JSON string to JavaScript object
|
|
@@ -356,7 +356,13 @@ module OpalVite
|
|
|
356
356
|
# source = turbo_stream_from("/notifications/stream")
|
|
357
357
|
# # Turbo will automatically process incoming streams
|
|
358
358
|
def turbo_stream_from(url)
|
|
359
|
-
|
|
359
|
+
# Keep a reference to the EventSource and return it: connectStreamSource
|
|
360
|
+
# returns undefined, so returning its result would make the documented
|
|
361
|
+
# `turbo_stream_disconnect(source)` call `undefined.close()` and leak
|
|
362
|
+
# the SSE connection.
|
|
363
|
+
source = `new EventSource(#{url})`
|
|
364
|
+
`window.Turbo.connectStreamSource(#{source})`
|
|
365
|
+
source
|
|
360
366
|
end
|
|
361
367
|
|
|
362
368
|
# Disconnect a Turbo Stream SSE source
|
|
@@ -27,7 +27,7 @@ module OpalVite
|
|
|
27
27
|
# @return [Native] JavaScript URL object
|
|
28
28
|
def parse_url(url_string)
|
|
29
29
|
`new URL(#{url_string})`
|
|
30
|
-
rescue
|
|
30
|
+
rescue Exception
|
|
31
31
|
nil
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -37,7 +37,7 @@ module OpalVite
|
|
|
37
37
|
# @return [Native] JavaScript URL object
|
|
38
38
|
def parse_url_with_base(url_string, base)
|
|
39
39
|
`new URL(#{url_string}, #{base})`
|
|
40
|
-
rescue
|
|
40
|
+
rescue Exception
|
|
41
41
|
nil
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -225,7 +225,7 @@ module OpalVite
|
|
|
225
225
|
# @return [String] Decoded string
|
|
226
226
|
def decode_uri_component(str)
|
|
227
227
|
`decodeURIComponent(#{str})`
|
|
228
|
-
rescue
|
|
228
|
+
rescue Exception
|
|
229
229
|
str
|
|
230
230
|
end
|
|
231
231
|
|
|
@@ -241,7 +241,7 @@ module OpalVite
|
|
|
241
241
|
# @return [String] Decoded URI
|
|
242
242
|
def decode_uri(str)
|
|
243
243
|
`decodeURI(#{str})`
|
|
244
|
-
rescue
|
|
244
|
+
rescue Exception
|
|
245
245
|
str
|
|
246
246
|
end
|
|
247
247
|
|
|
@@ -315,7 +315,10 @@ module OpalVite
|
|
|
315
315
|
|
|
316
316
|
# Stringify to JSON
|
|
317
317
|
def to_json_string(object)
|
|
318
|
-
|
|
318
|
+
# Convert Ruby Hash/Array to a native JS value first; passing a raw
|
|
319
|
+
# Opal Hash to JSON.stringify serializes to "{}" (silent data loss).
|
|
320
|
+
native = object.respond_to?(:to_n) ? object.to_n : object
|
|
321
|
+
`JSON.stringify(#{native})`
|
|
319
322
|
end
|
|
320
323
|
|
|
321
324
|
# ===================
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: opal-vite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.15
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- stofu1234
|
|
@@ -112,6 +112,7 @@ files:
|
|
|
112
112
|
- lib/opal/vite/testing/stable_helpers.rb
|
|
113
113
|
- lib/opal/vite/version.rb
|
|
114
114
|
- opal/opal_vite.rb
|
|
115
|
+
- opal/opal_vite/compat/opal_stimulus.rb
|
|
115
116
|
- opal/opal_vite/concerns.rb
|
|
116
117
|
- opal/opal_vite/concerns/dom_helpers.rb
|
|
117
118
|
- opal/opal_vite/concerns/js_proxy_ex.rb
|