ruby2js 3.1.0 → 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -10
- data/lib/ruby2js.rb +15 -2
- data/lib/ruby2js/converter.rb +11 -3
- data/lib/ruby2js/converter/args.rb +1 -1
- data/lib/ruby2js/converter/block.rb +2 -2
- data/lib/ruby2js/converter/class.rb +2 -2
- data/lib/ruby2js/converter/class2.rb +38 -9
- data/lib/ruby2js/converter/cvar.rb +1 -1
- data/lib/ruby2js/converter/cvasgn.rb +1 -1
- data/lib/ruby2js/converter/def.rb +2 -2
- data/lib/ruby2js/converter/for.rb +8 -1
- data/lib/ruby2js/converter/hash.rb +3 -3
- data/lib/ruby2js/converter/if.rb +13 -2
- data/lib/ruby2js/converter/import.rb +38 -0
- data/lib/ruby2js/converter/logical.rb +46 -1
- data/lib/ruby2js/converter/opasgn.rb +5 -2
- data/lib/ruby2js/converter/regexp.rb +27 -2
- data/lib/ruby2js/converter/return.rb +1 -1
- data/lib/ruby2js/converter/send.rb +53 -27
- data/lib/ruby2js/converter/super.rb +15 -9
- data/lib/ruby2js/converter/xnode.rb +89 -0
- data/lib/ruby2js/es2021.rb +5 -0
- data/lib/ruby2js/es2021/strict.rb +3 -0
- data/lib/ruby2js/filter.rb +1 -0
- data/lib/ruby2js/filter/cjs.rb +2 -2
- data/lib/ruby2js/filter/esm.rb +72 -0
- data/lib/ruby2js/filter/functions.rb +191 -41
- data/lib/ruby2js/filter/matchAll.rb +49 -0
- data/lib/ruby2js/filter/node.rb +18 -10
- data/lib/ruby2js/filter/nokogiri.rb +13 -13
- data/lib/ruby2js/filter/react.rb +190 -30
- data/lib/ruby2js/filter/require.rb +1 -4
- data/lib/ruby2js/filter/rubyjs.rb +4 -4
- data/lib/ruby2js/filter/vue.rb +45 -17
- data/lib/ruby2js/filter/wunderbar.rb +63 -0
- data/lib/ruby2js/serializer.rb +25 -11
- data/lib/ruby2js/version.rb +2 -2
- data/ruby2js.gemspec +2 -11
- metadata +24 -4
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ruby2js'
|
2
|
+
|
3
|
+
module Ruby2JS
|
4
|
+
module Filter
|
5
|
+
module MatchAll
|
6
|
+
include SEXP
|
7
|
+
|
8
|
+
# ensure matchAll is before Functions in the filter list
|
9
|
+
def self.reorder(filters)
|
10
|
+
if \
|
11
|
+
defined? Ruby2JS::Filter::Functions and
|
12
|
+
filters.include? Ruby2JS::Filter::Functions
|
13
|
+
then
|
14
|
+
filters = filters.dup
|
15
|
+
matchAll = filters.delete(Ruby2JS::Filter::MatchAll)
|
16
|
+
filters.insert filters.index(Ruby2JS::Filter::Functions), matchAll
|
17
|
+
else
|
18
|
+
filters
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_block(node)
|
23
|
+
return super if es2020
|
24
|
+
|
25
|
+
# only process each/forEach blocks
|
26
|
+
call = node.children.first
|
27
|
+
return super unless
|
28
|
+
[:each, :forEach].include? call.children[1] and
|
29
|
+
call.children.first.type == :send and
|
30
|
+
node.children[1].children.length == 1
|
31
|
+
|
32
|
+
# only process matchAll requests with simple expressions
|
33
|
+
call = call.children.first
|
34
|
+
return super unless
|
35
|
+
call.children[1] == :matchAll and
|
36
|
+
call.children[2].type == :send and
|
37
|
+
call.children[2].children.first == nil and
|
38
|
+
call.children[2].children.length == 2
|
39
|
+
|
40
|
+
process s(:while,
|
41
|
+
s(:lvasgn, node.children[1].children[0].children[0],
|
42
|
+
s(:send, call.children[2], :exec, call.children.first)),
|
43
|
+
node.children[2])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
DEFAULTS.push MatchAll
|
48
|
+
end
|
49
|
+
end
|
data/lib/ruby2js/filter/node.rb
CHANGED
@@ -56,7 +56,7 @@ module Ruby2JS
|
|
56
56
|
s(:hash, s(:pair, s(:sym, :stdio), s(:str, 'inherit'))))
|
57
57
|
end
|
58
58
|
|
59
|
-
elsif
|
59
|
+
elsif \
|
60
60
|
method == :require and args.length == 1 and
|
61
61
|
args.first.type == :str and
|
62
62
|
%w(fileutils tmpdir).include? args.first.children.first
|
@@ -67,7 +67,7 @@ module Ruby2JS
|
|
67
67
|
super
|
68
68
|
end
|
69
69
|
|
70
|
-
elsif
|
70
|
+
elsif \
|
71
71
|
[:File, :IO].include? target.children.last and
|
72
72
|
target.type == :const and target.children.first == nil
|
73
73
|
then
|
@@ -99,7 +99,7 @@ module Ruby2JS
|
|
99
99
|
@node_setup << :fs
|
100
100
|
S(:send, s(:attr, nil, :fs), :renameSync, *process_all(args))
|
101
101
|
|
102
|
-
elsif
|
102
|
+
elsif \
|
103
103
|
[:chmod, :lchmod].include? method and
|
104
104
|
args.length > 1 and args.first.type == :int
|
105
105
|
then
|
@@ -110,7 +110,7 @@ module Ruby2JS
|
|
110
110
|
s(:octal, *args.first.children))
|
111
111
|
})
|
112
112
|
|
113
|
-
elsif
|
113
|
+
elsif \
|
114
114
|
[:chown, :lchown].include? method and args.length > 2 and
|
115
115
|
args[0].type == :int and args[1].type == :int
|
116
116
|
then
|
@@ -148,7 +148,7 @@ module Ruby2JS
|
|
148
148
|
super
|
149
149
|
end
|
150
150
|
|
151
|
-
elsif
|
151
|
+
elsif \
|
152
152
|
target.children.last == :FileUtils and
|
153
153
|
target.type == :const and target.children.first == nil
|
154
154
|
then
|
@@ -201,7 +201,7 @@ module Ruby2JS
|
|
201
201
|
s(:send, s(:attr, nil, :fs), :unlinkSync, process(file))
|
202
202
|
})
|
203
203
|
|
204
|
-
elsif
|
204
|
+
elsif \
|
205
205
|
method == :chmod and args.length == 2 and args.first.type == :int
|
206
206
|
then
|
207
207
|
@node_setup << :fs
|
@@ -211,7 +211,7 @@ module Ruby2JS
|
|
211
211
|
s(:octal, *args.first.children))
|
212
212
|
})
|
213
213
|
|
214
|
-
elsif
|
214
|
+
elsif \
|
215
215
|
method == :chown and args.length == 3 and
|
216
216
|
args[0].type == :int and args[1].type == :int
|
217
217
|
then
|
@@ -233,7 +233,7 @@ module Ruby2JS
|
|
233
233
|
super
|
234
234
|
end
|
235
235
|
|
236
|
-
elsif
|
236
|
+
elsif \
|
237
237
|
target.type == :const and target.children.first == nil and
|
238
238
|
target.children.last == :Dir
|
239
239
|
then
|
@@ -274,7 +274,7 @@ module Ruby2JS
|
|
274
274
|
call = node.children.first
|
275
275
|
target, method, *args = call.children
|
276
276
|
|
277
|
-
if
|
277
|
+
if \
|
278
278
|
method == :chdir and args.length == 1 and
|
279
279
|
target.children.last == :Dir and
|
280
280
|
target.type == :const and target.children.first == nil
|
@@ -324,7 +324,15 @@ module Ruby2JS
|
|
324
324
|
children = node.children.dup
|
325
325
|
command = children.shift
|
326
326
|
while children.length > 0
|
327
|
-
|
327
|
+
child = children.shift
|
328
|
+
if \
|
329
|
+
child.type == :begin and child.children.length == 1 and
|
330
|
+
child.children.first.type == :send and
|
331
|
+
child.children.first.children.first == nil
|
332
|
+
then
|
333
|
+
child = child.children.first
|
334
|
+
end
|
335
|
+
command = s(:send, command, :+, child)
|
328
336
|
end
|
329
337
|
|
330
338
|
s(:send, s(:attr, nil, :child_process), :execSync, command,
|
@@ -36,7 +36,7 @@ module Ruby2JS
|
|
36
36
|
return super if excluded?(method)
|
37
37
|
|
38
38
|
if target == nil
|
39
|
-
if
|
39
|
+
if \
|
40
40
|
method == :require and args.length == 1 and
|
41
41
|
args.first.type == :str and
|
42
42
|
%w(nokogiri nokogumbo).include? args.first.children.first
|
@@ -47,7 +47,7 @@ module Ruby2JS
|
|
47
47
|
super
|
48
48
|
end
|
49
49
|
|
50
|
-
elsif
|
50
|
+
elsif \
|
51
51
|
[:HTML, :HTML5].include? method and
|
52
52
|
target == s(:const, nil, :Nokogiri)
|
53
53
|
then
|
@@ -55,7 +55,7 @@ module Ruby2JS
|
|
55
55
|
S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
|
56
56
|
*process_all(args)), :window), :document)
|
57
57
|
|
58
|
-
elsif
|
58
|
+
elsif \
|
59
59
|
method == :parse and
|
60
60
|
target.type == :const and
|
61
61
|
target.children.first == s(:const, nil, :Nokogiri) and
|
@@ -65,13 +65,13 @@ module Ruby2JS
|
|
65
65
|
S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
|
66
66
|
*process_all(args)), :window), :document)
|
67
67
|
|
68
|
-
elsif
|
68
|
+
elsif \
|
69
69
|
method == :at and
|
70
70
|
args.length == 1 and args.first.type == :str
|
71
71
|
then
|
72
72
|
S(:send, target, :querySelector, process(args.first))
|
73
73
|
|
74
|
-
elsif
|
74
|
+
elsif \
|
75
75
|
method == :search and
|
76
76
|
args.length == 1 and args.first.type == :str
|
77
77
|
then
|
@@ -98,25 +98,25 @@ module Ruby2JS
|
|
98
98
|
elsif method === :to_html and args.length == 0
|
99
99
|
S(:attr, target, :outerHTML)
|
100
100
|
|
101
|
-
elsif
|
101
|
+
elsif \
|
102
102
|
[:attr, :get_attribute].include? method and
|
103
103
|
args.length == 1 and args.first.type == :str
|
104
104
|
then
|
105
105
|
S(:send, target, :getAttribute, process(args.first))
|
106
106
|
|
107
|
-
elsif
|
107
|
+
elsif \
|
108
108
|
[:key?, :has_attribute].include? method and
|
109
109
|
args.length == 1 and args.first.type == :str
|
110
110
|
then
|
111
111
|
S(:send, target, :hasAttribute, process(args.first))
|
112
112
|
|
113
|
-
elsif
|
113
|
+
elsif \
|
114
114
|
method == :set_attribute and
|
115
115
|
args.length == 2 and args.first.type == :str
|
116
116
|
then
|
117
117
|
S(:send, target, :setAttribute, *process_all(args))
|
118
118
|
|
119
|
-
elsif
|
119
|
+
elsif \
|
120
120
|
method == :attribute and
|
121
121
|
args.length == 1 and args.first.type == :str
|
122
122
|
then
|
@@ -128,7 +128,7 @@ module Ruby2JS
|
|
128
128
|
elsif method == :attribute_nodes and args.length == 0
|
129
129
|
S(:attr, target, :attributes)
|
130
130
|
|
131
|
-
elsif
|
131
|
+
elsif \
|
132
132
|
method == :new and args.length == 2 and
|
133
133
|
target == s(:const, s(:const, s(:const, nil, :Nokogiri), :XML), :Node)
|
134
134
|
then
|
@@ -172,14 +172,14 @@ module Ruby2JS
|
|
172
172
|
elsif method == :add_child and args.length == 1
|
173
173
|
S(:send, target, :appendChild, process(args.first))
|
174
174
|
|
175
|
-
elsif
|
175
|
+
elsif \
|
176
176
|
[:add_next_sibling, :next=, :after].include? method and
|
177
177
|
args.length == 1
|
178
178
|
then
|
179
179
|
S(:send, s(:attr, target, :parentNode), :insertBefore,
|
180
180
|
process(args.first), s(:attr, target, :nextSibling))
|
181
181
|
|
182
|
-
elsif
|
182
|
+
elsif \
|
183
183
|
[:add_previous_sibling, :previous=, :before].include? method and
|
184
184
|
args.length == 1
|
185
185
|
then
|
@@ -199,7 +199,7 @@ module Ruby2JS
|
|
199
199
|
elsif method == :previous_element and args.length == 0
|
200
200
|
S(:attr, target, :previousElement)
|
201
201
|
|
202
|
-
elsif
|
202
|
+
elsif \
|
203
203
|
[:previous, :previous_sibling].include? method and args.length == 0
|
204
204
|
then
|
205
205
|
S(:attr, target, :previousSibling)
|
data/lib/ruby2js/filter/react.rb
CHANGED
@@ -68,12 +68,31 @@ module Ruby2JS
|
|
68
68
|
@reactApply = nil
|
69
69
|
@reactBlock = nil
|
70
70
|
@reactClass = nil
|
71
|
+
@react_props = []
|
72
|
+
@react_methods = []
|
73
|
+
@react_filter_functions = false
|
74
|
+
@jsx = false
|
71
75
|
super
|
72
76
|
end
|
73
77
|
|
74
78
|
def options=(options)
|
75
79
|
super
|
76
80
|
@react = true if options[:react]
|
81
|
+
filters = options[:filters] || Filter::DEFAULTS
|
82
|
+
|
83
|
+
if \
|
84
|
+
defined? Ruby2JS::Filter::Functions and
|
85
|
+
filters.include? Ruby2JS::Filter::Functions
|
86
|
+
then
|
87
|
+
@react_filter_functions = true
|
88
|
+
end
|
89
|
+
|
90
|
+
if \
|
91
|
+
defined? Ruby2JS::Filter::Wunderbar and
|
92
|
+
filters.include? Ruby2JS::Filter::Wunderbar
|
93
|
+
then
|
94
|
+
@jsx = true
|
95
|
+
end
|
77
96
|
end
|
78
97
|
|
79
98
|
# Example conversion
|
@@ -85,7 +104,9 @@ module Ruby2JS
|
|
85
104
|
def on_class(node)
|
86
105
|
cname, inheritance, *body = node.children
|
87
106
|
return super unless cname.children.first == nil
|
88
|
-
return super unless inheritance == s(:const, nil, :React)
|
107
|
+
return super unless inheritance == s(:const, nil, :React) or
|
108
|
+
inheritance == s(:const, nil, :Vue) or
|
109
|
+
inheritance == s(:send, s(:const, nil, :React), :Component)
|
89
110
|
|
90
111
|
# traverse down to actual list of class statements
|
91
112
|
if body.length == 1
|
@@ -106,18 +127,25 @@ module Ruby2JS
|
|
106
127
|
react, @react = @react, true
|
107
128
|
reactClass, @reactClass = @reactClass, true
|
108
129
|
|
109
|
-
|
110
|
-
|
111
|
-
|
130
|
+
pairs = []
|
131
|
+
|
132
|
+
unless es2015
|
133
|
+
# automatically capture the displayName for the class
|
134
|
+
pairs << s(:pair, s(:sym, :displayName),
|
135
|
+
s(:str, cname.children.last.to_s))
|
136
|
+
end
|
112
137
|
|
113
138
|
# collect static properties/functions
|
114
139
|
statics = []
|
115
140
|
body.select {|child| child.type == :defs}.each do |child|
|
116
141
|
_parent, mname, args, *block = child.children
|
117
|
-
if
|
142
|
+
if es2015
|
143
|
+
block = [s(:autoreturn, *block)] unless child.is_method?
|
144
|
+
pairs << s(:defs, s(:self), mname, args, *block)
|
145
|
+
elsif child.is_method?
|
118
146
|
statics << s(:pair, s(:sym, mname), process(child.updated(:block,
|
119
147
|
[s(:send, nil, :proc), args, s(:autoreturn, *block)])))
|
120
|
-
elsif
|
148
|
+
elsif \
|
121
149
|
block.length == 1 and
|
122
150
|
Converter::EXPRESSIONS.include? block.first.type
|
123
151
|
then
|
@@ -128,6 +156,25 @@ module Ruby2JS
|
|
128
156
|
end
|
129
157
|
end
|
130
158
|
|
159
|
+
# collect instance methods (including getters and setters)
|
160
|
+
@react_props = []
|
161
|
+
@react_methods = []
|
162
|
+
body.each do |statement|
|
163
|
+
if statement.type == :def
|
164
|
+
method = statement.children.first
|
165
|
+
unless method == :initialize
|
166
|
+
if method.to_s.end_with? '='
|
167
|
+
method = method.to_s[0..-2].to_sym
|
168
|
+
@react_props << method unless @react_props.include? method
|
169
|
+
elsif statement.is_method?
|
170
|
+
@react_methods << method unless @react_methods.include? method
|
171
|
+
else
|
172
|
+
@react_props << method unless @react_props.include? method
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
131
178
|
# append statics (if any)
|
132
179
|
unless statics.empty?
|
133
180
|
pairs << s(:pair, s(:sym, :statics), s(:hash, *statics))
|
@@ -135,7 +182,8 @@ module Ruby2JS
|
|
135
182
|
|
136
183
|
# create a default getInitialState method if there is no such method
|
137
184
|
# and there are references to instance variables.
|
138
|
-
if
|
185
|
+
if \
|
186
|
+
not es2015 and
|
139
187
|
not body.any? do |child|
|
140
188
|
child.type == :def and
|
141
189
|
[:getInitialState, :initialize].include? child.children.first
|
@@ -162,7 +210,7 @@ module Ruby2JS
|
|
162
210
|
(@reactIvars[:pre] + @reactIvars[:post]).uniq
|
163
211
|
|
164
212
|
if mname == :initialize
|
165
|
-
mname = :getInitialState
|
213
|
+
mname = es2015 ? :initialize : :getInitialState
|
166
214
|
|
167
215
|
# extract real list of statements
|
168
216
|
if block.length == 1
|
@@ -193,7 +241,9 @@ module Ruby2JS
|
|
193
241
|
anode.children.first.to_s[1..-1]), anode.children.last)})
|
194
242
|
|
195
243
|
# modify block to build and/or return state
|
196
|
-
if
|
244
|
+
if mname == :initialize
|
245
|
+
block.unshift(s(:send, s(:self), :state=, state))
|
246
|
+
elsif block.empty?
|
197
247
|
block = [s(:return, state)]
|
198
248
|
else
|
199
249
|
block.unshift(s(:send, s(:self), :state=, state))
|
@@ -201,13 +251,30 @@ module Ruby2JS
|
|
201
251
|
end
|
202
252
|
|
203
253
|
elsif mname == :render
|
204
|
-
if
|
205
|
-
|
254
|
+
if \
|
255
|
+
block.length != 1 or not block.last or
|
206
256
|
not [:send, :block].include? block.last.type
|
207
257
|
then
|
208
|
-
|
209
|
-
|
210
|
-
|
258
|
+
if @jsx
|
259
|
+
while block.length == 1 and block.first.type == :begin
|
260
|
+
block = block.first.children.dup
|
261
|
+
end
|
262
|
+
|
263
|
+
# gather non-element emitting statements in the front
|
264
|
+
prolog = []
|
265
|
+
while not block.empty? and
|
266
|
+
react_wunderbar_free([block.first]) do
|
267
|
+
prolog << process(block.shift)
|
268
|
+
end
|
269
|
+
|
270
|
+
# wrap multi-line blocks with an empty element
|
271
|
+
block = [*prolog, s(:return,
|
272
|
+
s(:xnode, '', *process_all(block)))]
|
273
|
+
else
|
274
|
+
# wrap multi-line blocks with a 'span' element
|
275
|
+
block = [s(:return,
|
276
|
+
s(:block, s(:send, nil, :_span), s(:args), *block))]
|
277
|
+
end
|
211
278
|
end
|
212
279
|
|
213
280
|
elsif mname == :componentWillReceiveProps
|
@@ -227,12 +294,17 @@ module Ruby2JS
|
|
227
294
|
|
228
295
|
# add method to class
|
229
296
|
type = (child.is_method? ? :begin : :autoreturn)
|
297
|
+
type = :begin if mname == :initialize
|
230
298
|
if block.length == 1 and Parser::AST::Node === block.first
|
231
299
|
type = :begin if block.first.type == :return
|
232
300
|
end
|
233
301
|
|
234
|
-
|
235
|
-
|
302
|
+
if es2015
|
303
|
+
pairs << s(:def, mname, args, process(s(type, *block)))
|
304
|
+
else
|
305
|
+
pairs << s(:pair, s(:sym, mname), child.updated(:block,
|
306
|
+
[s(:send, nil, :proc), args, process(s(type, *block))]))
|
307
|
+
end
|
236
308
|
|
237
309
|
# retain comment
|
238
310
|
unless @comments[child].empty?
|
@@ -245,18 +317,61 @@ module Ruby2JS
|
|
245
317
|
@reactMethod = nil
|
246
318
|
end
|
247
319
|
|
248
|
-
|
249
|
-
|
250
|
-
|
320
|
+
if es2015
|
321
|
+
# emit a class that extends React.Component
|
322
|
+
node.updated(:class, [s(:const, nil, cname.children.last),
|
323
|
+
s(:attr, s(:const, nil, :React), :Component), *pairs])
|
324
|
+
else
|
325
|
+
# emit a createClass statement
|
326
|
+
node.updated(:casgn, [nil, cname.children.last,
|
327
|
+
s(:send, s(:const, nil, :React), :createClass, s(:hash, *pairs))])
|
328
|
+
end
|
251
329
|
end
|
252
330
|
|
253
331
|
def on_send(node)
|
332
|
+
# convert Vue.utile.defineReactive to class fields or assignments
|
333
|
+
if node.children.first == s(:send, s(:const, nil, :Vue), :util)
|
334
|
+
if node.children[1] == :defineReactive
|
335
|
+
if node.children[2].type == :cvar
|
336
|
+
return process s(:cvasgn, node.children[2].children.first,
|
337
|
+
node.children[3])
|
338
|
+
elsif node.children[2].type == :send
|
339
|
+
assign = node.children[2]
|
340
|
+
return assign.updated(nil, [assign.children[0],
|
341
|
+
assign.children[1].to_s + '=', node.children[3]])
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
# calls to methods (including getters) defined in this class
|
347
|
+
if node.children[0]==nil and Symbol === node.children[1]
|
348
|
+
if node.is_method?
|
349
|
+
if @react_methods.include? node.children[1]
|
350
|
+
# calls to methods defined in this class
|
351
|
+
return node.updated nil, [s(:self), node.children[1],
|
352
|
+
*process_all(node.children[2..-1])]
|
353
|
+
end
|
354
|
+
else
|
355
|
+
if @react_props.include? node.children[1]
|
356
|
+
# access to properties defined in this class
|
357
|
+
return node.updated nil, [s(:self), node.children[1],
|
358
|
+
*process_all(node.children[2..-1])]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
if node.children.first == s(:const, nil, :Vue)
|
364
|
+
node = node.updated(nil, [s(:const, nil, :React),
|
365
|
+
*node.children[1..-1]])
|
366
|
+
end
|
367
|
+
|
254
368
|
if not @react
|
255
369
|
# enable React filtering within React class method calls or
|
256
370
|
# React component calls
|
257
|
-
if
|
371
|
+
if \
|
258
372
|
node.children.first == s(:const, nil, :React)
|
259
373
|
then
|
374
|
+
|
260
375
|
begin
|
261
376
|
react, @react = @react, true
|
262
377
|
return on_send(node)
|
@@ -278,7 +393,7 @@ module Ruby2JS
|
|
278
393
|
process(node.children[2])
|
279
394
|
end
|
280
395
|
|
281
|
-
elsif
|
396
|
+
elsif \
|
282
397
|
@reactApply and node.children[1] == :createElement and
|
283
398
|
node.children[0] == s(:const, nil, :React)
|
284
399
|
then
|
@@ -286,7 +401,7 @@ module Ruby2JS
|
|
286
401
|
s(:send, s(:gvar, :$_), :push, s(:send, *node.children[0..1],
|
287
402
|
*process_all(node.children[2..-1])))
|
288
403
|
|
289
|
-
elsif node.children[0] == nil and node.children[1] =~ /^_\w/
|
404
|
+
elsif !@jsx and node.children[0] == nil and node.children[1] =~ /^_\w/
|
290
405
|
# map method calls starting with an underscore to React calls
|
291
406
|
# to create an element.
|
292
407
|
#
|
@@ -344,7 +459,7 @@ module Ruby2JS
|
|
344
459
|
expr = expr.children.first
|
345
460
|
end
|
346
461
|
|
347
|
-
if
|
462
|
+
if \
|
348
463
|
expr.type == :if and expr.children[1] and
|
349
464
|
expr.children[1].type == :str
|
350
465
|
then
|
@@ -468,6 +583,8 @@ module Ruby2JS
|
|
468
583
|
# explicit call to React.createElement
|
469
584
|
next true if arg.children[1] == :createElement and
|
470
585
|
arg.children[0] == s(:const, nil, :React)
|
586
|
+
next true if arg.children[1] == :createElement and
|
587
|
+
arg.children[0] == s(:const, nil, :Vue)
|
471
588
|
|
472
589
|
# wunderbar style call
|
473
590
|
arg = arg.children.first if arg.type == :block
|
@@ -669,7 +786,7 @@ module Ruby2JS
|
|
669
786
|
super
|
670
787
|
end
|
671
788
|
|
672
|
-
elsif
|
789
|
+
elsif \
|
673
790
|
node.children[0] and node.children[0].type == :self and
|
674
791
|
node.children.length == 2 and
|
675
792
|
node.children[1] == :componentWillReceiveProps
|
@@ -686,7 +803,7 @@ module Ruby2JS
|
|
686
803
|
if not @react
|
687
804
|
# enable React filtering within React class method calls or
|
688
805
|
# React component calls
|
689
|
-
if
|
806
|
+
if \
|
690
807
|
node.children.first == s(:const, nil, :React)
|
691
808
|
then
|
692
809
|
begin
|
@@ -713,7 +830,7 @@ module Ruby2JS
|
|
713
830
|
#
|
714
831
|
# Base Ruby2JS processing will convert the 'splat' to 'apply'
|
715
832
|
child = node.children.first
|
716
|
-
if
|
833
|
+
if \
|
717
834
|
child.children[1] == :createElement and
|
718
835
|
child.children[0] == s(:const, nil, :React)
|
719
836
|
then
|
@@ -743,7 +860,7 @@ module Ruby2JS
|
|
743
860
|
end
|
744
861
|
|
745
862
|
# wunderbar style calls
|
746
|
-
if child.children[0] == nil and child.children[1] =~ /^_\w/
|
863
|
+
if !@jsx and child.children[0] == nil and child.children[1] =~ /^_\w/
|
747
864
|
if node.children[1].children.empty?
|
748
865
|
# append block as a standalone proc
|
749
866
|
block = s(:block, s(:send, nil, :proc), s(:args),
|
@@ -875,6 +992,49 @@ module Ruby2JS
|
|
875
992
|
s(:attr, @reactProps, node.children.first.to_s[2..-1])
|
876
993
|
end
|
877
994
|
|
995
|
+
# is this a "wunderbar" style call or createElement?
|
996
|
+
def react_element?(node)
|
997
|
+
return false unless node
|
998
|
+
|
999
|
+
forEach = [:forEach]
|
1000
|
+
forEach << :each if @react_filter_functions
|
1001
|
+
|
1002
|
+
return true if node.type == :block and
|
1003
|
+
forEach.include? node.children.first.children.last and
|
1004
|
+
react_element?(node.children.last)
|
1005
|
+
|
1006
|
+
# explicit call to React.createElement
|
1007
|
+
return true if node.children[1] == :createElement and
|
1008
|
+
node.children[0] == s(:const, nil, :React)
|
1009
|
+
|
1010
|
+
# explicit call to Vue.createElement
|
1011
|
+
return true if node.children[1] == :createElement and
|
1012
|
+
node.children[0] == s(:const, nil, :Vue)
|
1013
|
+
|
1014
|
+
# wunderbar style call
|
1015
|
+
node = node.children.first if node.type == :block
|
1016
|
+
while node.type == :send and node.children.first != nil
|
1017
|
+
node = node.children.first
|
1018
|
+
end
|
1019
|
+
node.type == :send and node.children[1].to_s.start_with? '_'
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
# ensure that there are no "wunderbar" or "createElement" calls in
|
1023
|
+
# a set of statements.
|
1024
|
+
def react_wunderbar_free(nodes)
|
1025
|
+
nodes.each do |node|
|
1026
|
+
if Parser::AST::Node === node
|
1027
|
+
return false if react_element?(node)
|
1028
|
+
|
1029
|
+
# recurse
|
1030
|
+
return false unless react_wunderbar_free(node.children)
|
1031
|
+
end
|
1032
|
+
end
|
1033
|
+
|
1034
|
+
# no problems found
|
1035
|
+
return true
|
1036
|
+
end
|
1037
|
+
|
878
1038
|
# analyze ivar usage
|
879
1039
|
def react_walk(node)
|
880
1040
|
# ignore hash values which are blocks (most typically, event handlers)
|
@@ -920,7 +1080,7 @@ module Ruby2JS
|
|
920
1080
|
end
|
921
1081
|
|
922
1082
|
when :send
|
923
|
-
if
|
1083
|
+
if \
|
924
1084
|
child and child.type == :self and node.children.length == 2 and
|
925
1085
|
node.children[1] == :componentWillReceiveProps
|
926
1086
|
then
|
@@ -933,7 +1093,7 @@ module Ruby2JS
|
|
933
1093
|
# Ruby 'desugars' -> to lambda, and Ruby2JS presumes that lambdas
|
934
1094
|
# return a value.
|
935
1095
|
def on_pair(node)
|
936
|
-
if
|
1096
|
+
if \
|
937
1097
|
node.children[1].type == :block and
|
938
1098
|
node.children[1].children[0] == s(:send, nil, :lambda)
|
939
1099
|
then
|
@@ -949,7 +1109,7 @@ module Ruby2JS
|
|
949
1109
|
def on_begin(node)
|
950
1110
|
node = super
|
951
1111
|
(node.children.length-2).downto(0) do |i|
|
952
|
-
if
|
1112
|
+
if \
|
953
1113
|
node.children[i].type == :send and
|
954
1114
|
node.children[i].children[0] and
|
955
1115
|
node.children[i].children[0].type == :self and
|