ruby2js 4.0.2 → 4.1.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 +0 -1
- data/lib/ruby2js.rb +1 -1
- data/lib/ruby2js/converter.rb +1 -0
- data/lib/ruby2js/converter/class.rb +7 -5
- data/lib/ruby2js/converter/class2.rb +4 -4
- data/lib/ruby2js/converter/def.rb +7 -1
- data/lib/ruby2js/converter/dstr.rb +3 -1
- data/lib/ruby2js/converter/return.rb +1 -1
- data/lib/ruby2js/converter/send.rb +1 -0
- data/lib/ruby2js/converter/taglit.rb +13 -2
- data/lib/ruby2js/filter/cjs.rb +100 -2
- data/lib/ruby2js/filter/functions.rb +11 -6
- data/lib/ruby2js/filter/lit-element.rb +218 -0
- data/lib/ruby2js/filter/react.rb +276 -88
- data/lib/ruby2js/filter/tagged_templates.rb +4 -2
- data/lib/ruby2js/rails.rb +10 -0
- data/lib/ruby2js/version.rb +2 -2
- data/lib/tasks/README.md +4 -0
- data/lib/tasks/install/app/javascript/elements/index.js +2 -0
- data/lib/tasks/install/config/webpack/loaders/ruby2js.js +20 -0
- data/lib/tasks/install/litelement.rb +9 -0
- data/lib/tasks/install/preact.rb +3 -0
- data/lib/tasks/install/react.rb +2 -0
- data/lib/tasks/install/stimulus-sprockets.rb +32 -0
- data/lib/tasks/install/stimulus-webpacker.rb +5 -0
- data/lib/tasks/install/webpacker.rb +80 -0
- data/lib/tasks/nodetest.js +47 -0
- data/lib/tasks/ruby2js_tasks.rake +47 -0
- metadata +15 -2
data/lib/ruby2js/filter/react.rb
CHANGED
@@ -26,8 +26,13 @@ module Ruby2JS
|
|
26
26
|
extend SEXP
|
27
27
|
|
28
28
|
REACT_IMPORTS = {
|
29
|
-
React: s(:import, ['
|
30
|
-
ReactDOM: s(:import, ['
|
29
|
+
React: s(:import, ['react'], s(:attr, nil, :React)),
|
30
|
+
ReactDOM: s(:import, ['react-dom'], s(:attr, nil, :ReactDOM)),
|
31
|
+
Preact: s(:import,
|
32
|
+
[s(:pair, s(:sym, :as), s(:const, nil, :Preact)),
|
33
|
+
s(:pair, s(:sym, :from), s(:str, "preact"))],
|
34
|
+
s(:str, '*')),
|
35
|
+
PreactHook: s(:import, ["preact/hooks"], [s(:attr, nil, :useState)])
|
31
36
|
}
|
32
37
|
|
33
38
|
# the following command can be used to generate ReactAttrs:
|
@@ -71,17 +76,23 @@ module Ruby2JS
|
|
71
76
|
|
72
77
|
ReactLifecycle = %w(render componentDidMount shouldComponentUpdate
|
73
78
|
getShapshotBeforeUpdate componentDidUpdate componentWillUnmount
|
74
|
-
componentDidCatch)
|
79
|
+
componentDidCatch componentWillReceiveProps)
|
75
80
|
|
76
81
|
ReactAttrMap = Hash[ReactAttrs.map {|name| [name.downcase, name]}]
|
77
82
|
ReactAttrMap['for'] = 'htmlFor'
|
78
|
-
|
83
|
+
|
84
|
+
PreactAttrMap = {
|
85
|
+
htmlFor: 'for',
|
86
|
+
onDoubleClick: 'onDblClick',
|
87
|
+
tabIndex: 'tabindex'
|
88
|
+
}
|
79
89
|
|
80
90
|
def initialize(*args)
|
81
91
|
@react = nil
|
82
92
|
@reactApply = nil
|
83
93
|
@reactBlock = nil
|
84
94
|
@reactClass = nil
|
95
|
+
@reactMethod = nil
|
85
96
|
@react_props = []
|
86
97
|
@react_methods = []
|
87
98
|
@react_filter_functions = false
|
@@ -118,12 +129,23 @@ module Ruby2JS
|
|
118
129
|
def on_class(node)
|
119
130
|
cname, inheritance, *body = node.children
|
120
131
|
return super unless cname.children.first == nil
|
121
|
-
|
122
|
-
|
132
|
+
|
133
|
+
if inheritance == s(:const, nil, :React) or
|
123
134
|
inheritance == s(:const, s(:const, nil, :React), :Component) or
|
124
135
|
inheritance == s(:send, s(:const, nil, :React), :Component)
|
125
136
|
|
126
|
-
|
137
|
+
react = :React
|
138
|
+
prepend_list << REACT_IMPORTS[:React] if modules_enabled?
|
139
|
+
|
140
|
+
elsif inheritance == s(:const, nil, :Preact) or
|
141
|
+
inheritance == s(:const, s(:const, nil, :Preact), :Component) or
|
142
|
+
inheritance == s(:send, s(:const, nil, :Preact), :Component)
|
143
|
+
|
144
|
+
react = :Preact
|
145
|
+
prepend_list << REACT_IMPORTS[:Preact] if modules_enabled?
|
146
|
+
else
|
147
|
+
return super
|
148
|
+
end
|
127
149
|
|
128
150
|
# traverse down to actual list of class statements
|
129
151
|
if body.length == 1
|
@@ -141,12 +163,14 @@ module Ruby2JS
|
|
141
163
|
end
|
142
164
|
|
143
165
|
begin
|
144
|
-
react, @react = @react,
|
166
|
+
react, @react = @react, react
|
145
167
|
reactClass, @reactClass = @reactClass, true
|
146
168
|
|
147
169
|
pairs = []
|
148
170
|
|
149
|
-
|
171
|
+
createClass = (@react == :React and not es2015)
|
172
|
+
|
173
|
+
if createClass
|
150
174
|
# automatically capture the displayName for the class
|
151
175
|
pairs << s(:pair, s(:sym, :displayName),
|
152
176
|
s(:str, cname.children.last.to_s))
|
@@ -156,12 +180,11 @@ module Ruby2JS
|
|
156
180
|
statics = []
|
157
181
|
body.select {|child| child.type == :defs}.each do |child|
|
158
182
|
_parent, mname, args, *block = child.children
|
159
|
-
if
|
160
|
-
|
161
|
-
pairs << s(:defs, s(:self), mname, args, *block)
|
183
|
+
if not createClass
|
184
|
+
pairs << child
|
162
185
|
elsif child.is_method?
|
163
|
-
statics << s(:pair, s(:sym, mname),
|
164
|
-
[s(:send, nil, :proc), args, s(:autoreturn, *block)]))
|
186
|
+
statics << s(:pair, s(:sym, mname), child.updated(:block,
|
187
|
+
[s(:send, nil, :proc), args, s(:autoreturn, *block)]))
|
165
188
|
elsif \
|
166
189
|
block.length == 1 and
|
167
190
|
Converter::EXPRESSIONS.include? block.first.type
|
@@ -212,13 +235,53 @@ module Ruby2JS
|
|
212
235
|
scan_events[node.children]
|
213
236
|
end
|
214
237
|
end
|
215
|
-
scan_events[body]
|
238
|
+
scan_events[body] if createClass
|
216
239
|
|
217
240
|
# append statics (if any)
|
218
241
|
unless statics.empty?
|
219
242
|
pairs << s(:pair, s(:sym, :statics), s(:hash, *statics))
|
220
243
|
end
|
221
244
|
|
245
|
+
# determine if this class can be emitted as a hook
|
246
|
+
hook = (es2015 and inheritance.children.first == nil)
|
247
|
+
hookinit = nil
|
248
|
+
useState = []
|
249
|
+
body.each_with_index do |statement, index|
|
250
|
+
if statement.type == :def
|
251
|
+
method = statement.children.first
|
252
|
+
if method == :initialize
|
253
|
+
children = statement.children[2..-1]
|
254
|
+
children.pop unless children.last
|
255
|
+
while children.length == 1 and children.first.type == :begin
|
256
|
+
children = children.first.children
|
257
|
+
end
|
258
|
+
hookinit = index if children.any? {|child| child.type != :ivasgn}
|
259
|
+
elsif method == :render
|
260
|
+
nil
|
261
|
+
elsif ReactLifecycle.include? method.to_s
|
262
|
+
hook = false
|
263
|
+
elsif not statement.is_method?
|
264
|
+
hook = false
|
265
|
+
elsif method.to_s.end_with? '='
|
266
|
+
hook = false
|
267
|
+
end
|
268
|
+
elsif statement.type == :defs
|
269
|
+
hook = false
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
if hook
|
274
|
+
@reactClass = :hook
|
275
|
+
@react_props = []
|
276
|
+
@react_methods = []
|
277
|
+
|
278
|
+
if hookinit
|
279
|
+
body = body.dup
|
280
|
+
hookinit = body.delete_at(hookinit)
|
281
|
+
pairs.unshift process hookinit.children[2]
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
222
285
|
# create a default getInitialState method if there is no such method
|
223
286
|
# and there are either references to instance variables or there are
|
224
287
|
# methods that need to be bound.
|
@@ -230,7 +293,13 @@ module Ruby2JS
|
|
230
293
|
then
|
231
294
|
@reactIvars = {pre: [], post: [], asgn: [], ref: [], cond: []}
|
232
295
|
react_walk(node)
|
233
|
-
|
296
|
+
|
297
|
+
if hook
|
298
|
+
react_walk(hookinit) if hookinit
|
299
|
+
useState = (@reactIvars[:asgn] + @reactIvars[:ref]).uniq
|
300
|
+
end
|
301
|
+
|
302
|
+
if createClass and not @reactIvars.values.flatten.empty?
|
234
303
|
body = [s(:def, :getInitialState, s(:args),
|
235
304
|
s(:return, s(:hash))), *body]
|
236
305
|
elsif not needs_binding.empty? or not @reactIvars.values.flatten.empty?
|
@@ -242,16 +311,21 @@ module Ruby2JS
|
|
242
311
|
body.select {|child| child.type == :def}.each do |child|
|
243
312
|
mname, args, *block = child.children
|
244
313
|
@reactMethod = mname
|
245
|
-
|
314
|
+
|
315
|
+
if @reactClass == :hook
|
316
|
+
@reactProps = s(:lvar, :"prop$")
|
317
|
+
else
|
318
|
+
@reactProps = child.updated(:attr, [s(:self), :props])
|
319
|
+
end
|
246
320
|
|
247
321
|
# analyze ivar usage
|
248
322
|
@reactIvars = {pre: [], post: [], asgn: [], ref: [], cond: []}
|
249
323
|
react_walk(child) unless mname == :initialize
|
250
|
-
@reactIvars[:capture] =
|
251
|
-
|
324
|
+
@reactIvars[:capture] = (@reactIvars[:pre] + @reactIvars[:post]).uniq
|
325
|
+
@reactIvars[:pre] = @reactIvars[:post] = [] if @reactClass == :hook
|
252
326
|
|
253
327
|
if mname == :initialize
|
254
|
-
mname =
|
328
|
+
mname = createClass ? :getInitialState : :initialize
|
255
329
|
|
256
330
|
# extract real list of statements
|
257
331
|
if block.length == 1
|
@@ -333,7 +407,7 @@ module Ruby2JS
|
|
333
407
|
else
|
334
408
|
# wrap multi-line blocks with a React Fragment
|
335
409
|
block = [s(:return,
|
336
|
-
s(:block, s(:send, nil,
|
410
|
+
s(:block, s(:send, nil, :"_#{@react}.Fragment"), s(:args), *block))]
|
337
411
|
end
|
338
412
|
end
|
339
413
|
|
@@ -359,14 +433,14 @@ module Ruby2JS
|
|
359
433
|
type = :begin if block.first.type == :return
|
360
434
|
end
|
361
435
|
|
362
|
-
if
|
436
|
+
if createClass
|
437
|
+
pairs << s(:pair, s(:sym, mname), child.updated(:block,
|
438
|
+
[s(:send, nil, :proc), args, process(s(type, *block))]))
|
439
|
+
else
|
363
440
|
pairs << child.updated(
|
364
441
|
ReactLifecycle.include?(mname.to_s) ? :defm : :def,
|
365
442
|
[mname, args, process(s(type, *block))]
|
366
443
|
)
|
367
|
-
else
|
368
|
-
pairs << s(:pair, s(:sym, mname), child.updated(:block,
|
369
|
-
[s(:send, nil, :proc), args, process(s(type, *block))]))
|
370
444
|
end
|
371
445
|
|
372
446
|
# retain comment
|
@@ -374,38 +448,70 @@ module Ruby2JS
|
|
374
448
|
@comments[pairs.last] = @comments[child]
|
375
449
|
end
|
376
450
|
end
|
451
|
+
|
452
|
+
if createClass
|
453
|
+
# emit a createClass statement
|
454
|
+
node.updated(:casgn, [nil, cname.children.last,
|
455
|
+
s(:send, s(:const, nil, :React), :createClass, s(:hash, *pairs))])
|
456
|
+
elsif hook
|
457
|
+
initialize = pairs.find_index {|node| node.type == :def and node.children.first == :initialize}
|
458
|
+
|
459
|
+
hash = {}
|
460
|
+
if initialize
|
461
|
+
hash = pairs.delete_at(initialize)
|
462
|
+
hash = hash.children.last while %i(def begin send).include? hash&.type
|
463
|
+
hash = s(:hash) unless hash&.type == :hash
|
464
|
+
hash = hash.children.map {|pair|
|
465
|
+
[pair.children.first.children.first, pair.children.last]
|
466
|
+
}.to_h
|
467
|
+
end
|
468
|
+
|
469
|
+
useState.each do |symbol|
|
470
|
+
hash[symbol.to_s[1..-1]] ||= s(:nil)
|
471
|
+
end
|
472
|
+
|
473
|
+
hash.sort.reverse.each do |var, value|
|
474
|
+
if @react == :Preact
|
475
|
+
hooker = nil
|
476
|
+
prepend_list << REACT_IMPORTS[:PreactHook] if modules_enabled?
|
477
|
+
else
|
478
|
+
hooker = s(:const, nil, :React)
|
479
|
+
end
|
480
|
+
|
481
|
+
setter = 'set' + var[0].upcase + var[1..-1]
|
482
|
+
pairs.unshift(s(:masgn, s(:mlhs, s(:lvasgn, var),
|
483
|
+
s(:lvasgn, setter)), s(:send, hooker, :useState, value)))
|
484
|
+
end
|
485
|
+
|
486
|
+
render = pairs.find_index {|node| node.type == :defm and node.children.first == :render}
|
487
|
+
if render
|
488
|
+
render = pairs.delete_at(render)
|
489
|
+
pairs.push s(:autoreturn, render.children.last)
|
490
|
+
end
|
491
|
+
|
492
|
+
has_cvar = lambda {|list|
|
493
|
+
list.any? {|node|
|
494
|
+
next unless Parser::AST::Node === node
|
495
|
+
return true if node.type == :cvar
|
496
|
+
has_cvar.call(node.children)
|
497
|
+
}
|
498
|
+
}
|
499
|
+
args = has_cvar[node.children] ? s(:args, s(:arg, 'prop$')) : s(:args)
|
500
|
+
|
501
|
+
node.updated(:def, [cname.children.last, args, s(:begin, *pairs)])
|
502
|
+
else
|
503
|
+
# emit a class that extends React.Component
|
504
|
+
node.updated(:class, [s(:const, nil, cname.children.last),
|
505
|
+
s(:attr, s(:const, nil, @react), :Component), *pairs])
|
506
|
+
end
|
377
507
|
ensure
|
378
508
|
@react = react
|
379
509
|
@reactClass = reactClass
|
380
510
|
@reactMethod = nil
|
381
511
|
end
|
382
|
-
|
383
|
-
if es2015
|
384
|
-
# emit a class that extends React.Component
|
385
|
-
node.updated(:class, [s(:const, nil, cname.children.last),
|
386
|
-
s(:attr, s(:const, nil, :React), :Component), *pairs])
|
387
|
-
else
|
388
|
-
# emit a createClass statement
|
389
|
-
node.updated(:casgn, [nil, cname.children.last,
|
390
|
-
s(:send, s(:const, nil, :React), :createClass, s(:hash, *pairs))])
|
391
|
-
end
|
392
512
|
end
|
393
513
|
|
394
514
|
def on_send(node)
|
395
|
-
# convert Vue.utile.defineReactive to class fields or assignments
|
396
|
-
if node.children.first == s(:send, s(:const, nil, :Vue), :util)
|
397
|
-
if node.children[1] == :defineReactive
|
398
|
-
if node.children[2].type == :cvar
|
399
|
-
return process s(:cvasgn, node.children[2].children.first,
|
400
|
-
node.children[3])
|
401
|
-
elsif node.children[2].type == :send
|
402
|
-
assign = node.children[2]
|
403
|
-
return assign.updated(nil, [assign.children[0],
|
404
|
-
assign.children[1].to_s + '=', node.children[3]])
|
405
|
-
end
|
406
|
-
end
|
407
|
-
end
|
408
|
-
|
409
515
|
# calls to methods (including getters) defined in this class
|
410
516
|
if node.children[0]==nil and Symbol === node.children[1]
|
411
517
|
if node.is_method?
|
@@ -423,16 +529,12 @@ module Ruby2JS
|
|
423
529
|
end
|
424
530
|
end
|
425
531
|
|
426
|
-
if node.children.first == s(:const, nil, :Vue)
|
427
|
-
node = node.updated(nil, [s(:const, nil, :React),
|
428
|
-
*node.children[1..-1]])
|
429
|
-
end
|
430
|
-
|
431
532
|
if not @react
|
432
533
|
# enable React filtering within React class method calls or
|
433
534
|
# React component calls
|
434
535
|
if \
|
435
536
|
node.children.first == s(:const, nil, :React) or
|
537
|
+
node.children.first == s(:const, nil, :Preact) or
|
436
538
|
node.children.first == s(:const, nil, :ReactDOM)
|
437
539
|
then
|
438
540
|
if modules_enabled?
|
@@ -440,7 +542,8 @@ module Ruby2JS
|
|
440
542
|
end
|
441
543
|
|
442
544
|
begin
|
443
|
-
react
|
545
|
+
react = @react
|
546
|
+
@react = (node.children.first.children.last == :Preact ? :Preact : :React)
|
444
547
|
return on_send(node)
|
445
548
|
ensure
|
446
549
|
@react = react
|
@@ -461,13 +564,26 @@ module Ruby2JS
|
|
461
564
|
end
|
462
565
|
|
463
566
|
elsif \
|
464
|
-
@reactApply and node.children[1] == :createElement and
|
465
|
-
node.children[0] == s(:const, nil, :React)
|
567
|
+
(@reactApply and node.children[1] == :createElement and
|
568
|
+
node.children[0] == s(:const, nil, :React)) or
|
569
|
+
(@reactApply and node.children[1] == :h and
|
570
|
+
node.children[0] == s(:const, nil, :Preact))
|
466
571
|
then
|
467
572
|
# push results of explicit calls to React.createElement
|
468
573
|
s(:send, s(:gvar, :$_), :push, s(:send, *node.children[0..1],
|
469
574
|
*process_all(node.children[2..-1])))
|
470
575
|
|
576
|
+
elsif \
|
577
|
+
@react == :Preact and node.children[1] == :h and node.children[0] == nil
|
578
|
+
then
|
579
|
+
if @reactApply
|
580
|
+
# push results of explicit calls to Preact.h
|
581
|
+
s(:send, s(:gvar, :$_), :push, s(:send, s(:const, nil, :Preact), :h,
|
582
|
+
*process_all(node.children[2..-1])))
|
583
|
+
else
|
584
|
+
node.updated(nil, [s(:const, nil, :Preact), :h, *process_all(node.children[2..-1])])
|
585
|
+
end
|
586
|
+
|
471
587
|
elsif !@jsx and node.children[0] == nil and node.children[1] =~ /^_\w/
|
472
588
|
# map method calls starting with an underscore to React calls
|
473
589
|
# to create an element.
|
@@ -549,7 +665,12 @@ module Ruby2JS
|
|
549
665
|
else
|
550
666
|
value = s(:str, values.join(' '))
|
551
667
|
end
|
552
|
-
|
668
|
+
|
669
|
+
if @react == :Preact
|
670
|
+
pairs.unshift s(:pair, s(:sym, :class), value)
|
671
|
+
else
|
672
|
+
pairs.unshift s(:pair, s(:sym, :className), value)
|
673
|
+
end
|
553
674
|
end
|
554
675
|
|
555
676
|
# support controlled form components
|
@@ -559,13 +680,28 @@ module Ruby2JS
|
|
559
680
|
['value', :value].include? pair.children.first.children.first
|
560
681
|
end
|
561
682
|
|
562
|
-
|
683
|
+
event = (@react == :Preact ? :onInput : :onChange)
|
684
|
+
|
685
|
+
|
686
|
+
# search for the presence of a onInput/onChange attribute
|
563
687
|
onChange = pairs.find_index do |pair|
|
564
|
-
|
688
|
+
pair.children.first.children[0].to_s == event.to_s
|
689
|
+
end
|
690
|
+
|
691
|
+
if event == :onInput and not onChange
|
692
|
+
# search for the presence of a 'onChange' attribute
|
693
|
+
onChange = pairs.find_index do |pair|
|
694
|
+
pair.children.first.children[0].to_s == 'onChange'
|
695
|
+
end
|
696
|
+
|
697
|
+
if onChange
|
698
|
+
pairs[onChange] = s(:pair, s(:sym, event),
|
699
|
+
pairs[onChange].children.last)
|
700
|
+
end
|
565
701
|
end
|
566
702
|
|
567
703
|
if value and pairs[value].children.last.type == :ivar and !onChange
|
568
|
-
pairs << s(:pair, s(:sym,
|
704
|
+
pairs << s(:pair, s(:sym, event),
|
569
705
|
s(:block, s(:send, nil, :proc), s(:args, s(:arg, :event)),
|
570
706
|
s(:ivasgn, pairs[value].children.last.children.first,
|
571
707
|
s(:attr, s(:attr, s(:lvar, :event), :target), :value))))
|
@@ -578,7 +714,7 @@ module Ruby2JS
|
|
578
714
|
end
|
579
715
|
|
580
716
|
if checked and pairs[checked].children.last.type == :ivar
|
581
|
-
pairs << s(:pair, s(:sym,
|
717
|
+
pairs << s(:pair, s(:sym, event),
|
582
718
|
s(:block, s(:send, nil, :proc), s(:args),
|
583
719
|
s(:ivasgn, pairs[checked].children.last.children.first,
|
584
720
|
s(:send, pairs[checked].children.last, :!))))
|
@@ -586,13 +722,25 @@ module Ruby2JS
|
|
586
722
|
end
|
587
723
|
end
|
588
724
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
[
|
725
|
+
if @react == :Preact
|
726
|
+
# replace selected Reactisms with native HTML
|
727
|
+
pairs.each_with_index do |pair, index|
|
728
|
+
next if pair.type == :kwsplat
|
729
|
+
name = pair.children.first.children.first.to_sym
|
730
|
+
if PreactAttrMap[name]
|
731
|
+
pairs[index] = pairs[index].updated(nil,
|
732
|
+
[s(:str, PreactAttrMap[name]), pairs[index].children.last])
|
733
|
+
end
|
734
|
+
end
|
735
|
+
else
|
736
|
+
# replace attribute names with case-sensitive javascript properties
|
737
|
+
pairs.each_with_index do |pair, index|
|
738
|
+
next if pair.type == :kwsplat
|
739
|
+
name = pair.children.first.children.first.downcase
|
740
|
+
if ReactAttrMap[name] and name.to_s != ReactAttrMap[name]
|
741
|
+
pairs[index] = pairs[index].updated(nil,
|
742
|
+
[s(:str, ReactAttrMap[name]), pairs[index].children.last])
|
743
|
+
end
|
596
744
|
end
|
597
745
|
end
|
598
746
|
|
@@ -654,8 +802,14 @@ module Ruby2JS
|
|
654
802
|
# explicit call to React.createElement
|
655
803
|
next true if arg.children[1] == :createElement and
|
656
804
|
arg.children[0] == s(:const, nil, :React)
|
657
|
-
|
658
|
-
|
805
|
+
|
806
|
+
# explicit call to Preact.h
|
807
|
+
next true if arg.children[1] == :h and
|
808
|
+
arg.children[0] == s(:const, nil, :Preact)
|
809
|
+
|
810
|
+
# explicit call to h
|
811
|
+
next true if arg.children[1] == :h and
|
812
|
+
arg.children[0] == nil
|
659
813
|
|
660
814
|
# JSX
|
661
815
|
next true if arg.type == :xstr
|
@@ -717,8 +871,13 @@ module Ruby2JS
|
|
717
871
|
params.pop if params.last == s(:nil)
|
718
872
|
|
719
873
|
# construct element using params
|
720
|
-
|
721
|
-
:
|
874
|
+
if @react == :Preact
|
875
|
+
element = node.updated(:send, [s(:const, nil, :Preact),
|
876
|
+
:h, *params])
|
877
|
+
else
|
878
|
+
element = node.updated(:send, [s(:const, nil, :React),
|
879
|
+
:createElement, *params])
|
880
|
+
end
|
722
881
|
|
723
882
|
if @reactApply
|
724
883
|
# if apply is set, emit code that pushes result
|
@@ -846,8 +1005,13 @@ module Ruby2JS
|
|
846
1005
|
while node != child
|
847
1006
|
if node.children[1] !~ /!$/
|
848
1007
|
# convert method name to hash {className: name} pair
|
849
|
-
|
850
|
-
s(:
|
1008
|
+
if @react == :Preact
|
1009
|
+
pair = s(:pair, s(:sym, :class),
|
1010
|
+
s(:str, node.children[1].to_s.gsub('_','-')))
|
1011
|
+
else
|
1012
|
+
pair = s(:pair, s(:sym, :className),
|
1013
|
+
s(:str, node.children[1].to_s.gsub('_','-')))
|
1014
|
+
end
|
851
1015
|
else
|
852
1016
|
# convert method name to hash {id: name} pair
|
853
1017
|
pair = s(:pair, s(:sym, :id),
|
@@ -917,8 +1081,11 @@ module Ruby2JS
|
|
917
1081
|
# Base Ruby2JS processing will convert the 'splat' to 'apply'
|
918
1082
|
child = node.children.first
|
919
1083
|
if \
|
920
|
-
child.children[1] == :createElement and
|
921
|
-
child.children[0] == s(:const, nil, :React)
|
1084
|
+
(child.children[1] == :createElement and
|
1085
|
+
child.children[0] == s(:const, nil, :React)) or
|
1086
|
+
(child.children[1] == :h and
|
1087
|
+
(child.children[0] == s(:const, nil, :Preact) or
|
1088
|
+
child.children[0] == nil))
|
922
1089
|
then
|
923
1090
|
begin
|
924
1091
|
reactApply, @reactApply = @reactApply, true
|
@@ -931,11 +1098,13 @@ module Ruby2JS
|
|
931
1098
|
@reactApply = reactApply
|
932
1099
|
end
|
933
1100
|
|
1101
|
+
target = child.children[0] || s(:const, nil, :Preact)
|
1102
|
+
|
934
1103
|
if reactApply
|
935
1104
|
return child.updated(:send, [s(:gvar, :$_), :push,
|
936
|
-
s(:send,
|
1105
|
+
s(:send, target, child.children[1], *params)])
|
937
1106
|
else
|
938
|
-
return child.updated(:send, [
|
1107
|
+
return child.updated(:send, [target, child.children[1], *params])
|
939
1108
|
end
|
940
1109
|
end
|
941
1110
|
|
@@ -952,7 +1121,7 @@ module Ruby2JS
|
|
952
1121
|
block = s(:block, s(:send, nil, :proc), s(:args),
|
953
1122
|
*node.children[2..-1])
|
954
1123
|
return on_send node.children.first.updated(:send,
|
955
|
-
[nil,
|
1124
|
+
[nil, :"_#{@react}.Fragment", block])
|
956
1125
|
|
957
1126
|
elsif !@jsx and child.children[0] == nil and child.children[1] =~ /^_\w/
|
958
1127
|
if node.children[1].children.empty?
|
@@ -998,13 +1167,17 @@ module Ruby2JS
|
|
998
1167
|
# convert global variables to refs
|
999
1168
|
def on_gvar(node)
|
1000
1169
|
return super unless @reactClass
|
1170
|
+
return super if @reactClass == :hook
|
1001
1171
|
s(:attr, s(:attr, s(:self), :refs), node.children.first.to_s[1..-1])
|
1002
1172
|
end
|
1003
1173
|
|
1004
1174
|
# convert instance variables to state
|
1005
1175
|
def on_ivar(node)
|
1006
1176
|
return super unless @reactClass
|
1007
|
-
|
1177
|
+
|
1178
|
+
if @reactClass == :hook
|
1179
|
+
node.updated(:lvar, [node.children.first.to_s[1..-1]])
|
1180
|
+
elsif @reactMethod and @reactIvars[:capture].include? node.children.first
|
1008
1181
|
node.updated(:lvar, ["$#{node.children.first[1..-1]}"])
|
1009
1182
|
else
|
1010
1183
|
node.updated(:attr, [s(:attr, s(:self), :state),
|
@@ -1016,11 +1189,17 @@ module Ruby2JS
|
|
1016
1189
|
def on_ivasgn(node)
|
1017
1190
|
return super unless @react
|
1018
1191
|
|
1192
|
+
if @reactClass == :hook
|
1193
|
+
var = node.children.first.to_s[1..-1]
|
1194
|
+
return node.updated(:send, [nil, 'set' + var[0].upcase + var[1..-1],
|
1195
|
+
process(node.children.last)])
|
1196
|
+
end
|
1197
|
+
|
1019
1198
|
if @reactMethod and @reactIvars[:capture].include? node.children.first
|
1020
1199
|
ivar = node.children.first.to_s
|
1021
1200
|
if @reactBlock
|
1022
1201
|
return s(:send, s(:self), :setState, s(:hash, s(:pair,
|
1023
|
-
s(:
|
1202
|
+
s(:str, ivar[1..-1]), process(s(:lvasgn, "$#{ivar[1..-1]}",
|
1024
1203
|
*node.children[1..-1])))))
|
1025
1204
|
else
|
1026
1205
|
return s(:lvasgn, "$#{ivar[1..-1]}",
|
@@ -1072,10 +1251,14 @@ module Ruby2JS
|
|
1072
1251
|
return super unless @react
|
1073
1252
|
return super unless node.children.first.type == :ivasgn
|
1074
1253
|
var = node.children.first.children.first
|
1075
|
-
if @
|
1254
|
+
if @reactClass == :hook
|
1255
|
+
var = node.children.first.children.first.to_s[1..-1]
|
1256
|
+
node.updated(:send, [nil, 'set' + var[0].upcase + var[1..-1],
|
1257
|
+
s(:send, s(:lvar, var), *node.children[1..-1])])
|
1258
|
+
elsif @reactMethod and @reactIvars[:capture].include? var
|
1076
1259
|
if @reactBlock
|
1077
1260
|
s(:send, s(:self), :setState, s(:hash, s(:pair,
|
1078
|
-
s(:
|
1261
|
+
s(:str, var[1..-1]), process(s(node.type,
|
1079
1262
|
s(:lvasgn, "$#{var[1..-1]}"), *node.children[1..-1])))))
|
1080
1263
|
else
|
1081
1264
|
process s(node.type, s(:lvasgn, "$#{var[1..-1]}"),
|
@@ -1118,9 +1301,13 @@ module Ruby2JS
|
|
1118
1301
|
return true if node.children[1] == :createElement and
|
1119
1302
|
node.children[0] == s(:const, nil, :React)
|
1120
1303
|
|
1121
|
-
# explicit call to
|
1122
|
-
return true if node.children[1] == :
|
1123
|
-
node.children[0] == s(:const, nil, :
|
1304
|
+
# explicit call to Preact.h
|
1305
|
+
return true if node.children[1] == :h and
|
1306
|
+
node.children[0] == s(:const, nil, :Preact)
|
1307
|
+
|
1308
|
+
# explicit call to h
|
1309
|
+
return true if node.children[1] == :h and
|
1310
|
+
node.children[0] == nil
|
1124
1311
|
end
|
1125
1312
|
|
1126
1313
|
# wunderbar style call
|
@@ -1256,6 +1443,7 @@ module Ruby2JS
|
|
1256
1443
|
@reactIvars = {pre: [], post: [], asgn: [], ref: [], cond: []}
|
1257
1444
|
react_walk(node.children.last)
|
1258
1445
|
@reactIvars[:capture] = (@reactIvars[:pre] + @reactIvars[:post]).uniq
|
1446
|
+
@reactIvars[:pre] = @reactIvars[:post] = [] if @reactClass == :hook
|
1259
1447
|
node = super
|
1260
1448
|
block = react_process_ivars([node.children.last.dup])
|
1261
1449
|
node.updated(nil, [*node.children[0..-2], s(:begin, *block)])
|
@@ -1280,7 +1468,7 @@ module Ruby2JS
|
|
1280
1468
|
# update ivars that are set and later referenced
|
1281
1469
|
unless @reactIvars[:post].empty?
|
1282
1470
|
updates = @reactIvars[:post].uniq.sort.reverse.map do |ivar|
|
1283
|
-
s(:pair, s(:
|
1471
|
+
s(:pair, s(:str, ivar.to_s[1..-1]),
|
1284
1472
|
s(:lvar, "$#{ivar.to_s[1..-1]}"))
|
1285
1473
|
end
|
1286
1474
|
update = s(:send, s(:self), :setState, s(:hash, *updates))
|