ruby2js 4.0.5 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6728e4201e77b477a9203551b57de3f23b36077f6012061233d4b072d92886b9
4
- data.tar.gz: 7d5e6ef7aa5b9add1477b3cc642cc55714a657f7f962dbb6dd7af6688d45cfb0
3
+ metadata.gz: 46b6cba0b33ebf62cb966def9b680eda35f5e84ff0c3adaea058fc2aae242269
4
+ data.tar.gz: 6c5843992eccd24e8460b16f805eab16701d70d85e8ef4dcaffee948243666c0
5
5
  SHA512:
6
- metadata.gz: 321dc88308946ff626914ceb87fa93f93bec4f5cde0b660cab75d7df46b52f9ca63da830e7fab4f070b989586ef468b3cdf9d8f682f64b44ee06fef9df5230f7
7
- data.tar.gz: 22f5161f0bc03c294fbfd3f32be407030fea293985e1eff4c7d0fc464bd57aaa6a3cfc70e1bf9ed13e9bbb0dbbac9f394b860e76df52ae236b494accd86c840b
6
+ metadata.gz: 6910f39474f2c22c321b91ad742ab10f7fff08bc5408e53f9b4d0cdee4f4fead414519a1b31bf7e6f781dc31da71fbda55bc747132c0d78e8eeb62a8693ca419
7
+ data.tar.gz: 07b1ddbff32682c2ea3fa65570e40f97907eea4765d00ea4b7921bca5156f83f8f855178ab13ed3fc70b9edb8035fc801cdb4031c6f8176e044699099ac7dccd
@@ -36,7 +36,8 @@ module Ruby2JS
36
36
  end
37
37
 
38
38
  if inheritance
39
- init = s(:def, :initialize, s(:args), s(:super))
39
+ parent = @namespace.find(inheritance)&.[](:constructor)
40
+ init = s(:def, :initialize, parent || s(:args), s(:zsuper))
40
41
  else
41
42
  init = s(:def, :initialize, s(:args), nil)
42
43
  end
@@ -58,7 +59,7 @@ module Ruby2JS
58
59
  m = m.updated(:def, m.children[1..-1])
59
60
  end
60
61
 
61
- node = if m.type == :def
62
+ node = if m.type == :def or m.type == :defm
62
63
  if m.children.first == :initialize and !visible[:initialize]
63
64
  # constructor: remove from body and overwrite init function
64
65
  init = m
@@ -313,7 +314,7 @@ module Ruby2JS
313
314
  # prepend constructor
314
315
  if init
315
316
  constructor = init.updated(:constructor, [name, *init.children[1..-1]])
316
- @comments[constructor] = @comments[init] unless @comments[init].empty?
317
+ visible[:constructor] = init.children[1]
317
318
 
318
319
  if @ast.type == :class_extend or extend
319
320
  if es2015
@@ -329,6 +330,7 @@ module Ruby2JS
329
330
  end
330
331
  end
331
332
 
333
+ @comments[constructor] = @comments[init] unless @comments[init].empty?
332
334
  body.unshift constructor
333
335
  end
334
336
 
@@ -349,7 +351,7 @@ module Ruby2JS
349
351
  self.ivars = ivars
350
352
  @class_name = class_name
351
353
  @class_parent = class_parent
352
- @rbstack.pop
354
+ @namespace.defineProps @rbstack.pop
353
355
  @namespace.leave unless @ast.type == :class_module
354
356
  end
355
357
  end
@@ -99,7 +99,6 @@ module Ruby2JS
99
99
  end
100
100
  walk[@ast]
101
101
 
102
- # process leading initializers in constructor
103
102
  while constructor.length == 1 and constructor.first.type == :begin
104
103
  constructor = constructor.first.children.dup
105
104
  end
@@ -116,6 +115,7 @@ module Ruby2JS
116
115
  put 'static #$' + cvar.to_s[2..-1]
117
116
  end
118
117
 
118
+ # process leading initializers in constructor
119
119
  while constructor.length > 0 and constructor.first.type == :ivasgn
120
120
  put(index == 0 ? @nl : @sep)
121
121
  index += 1
@@ -227,14 +227,19 @@ module Ruby2JS
227
227
  if before.type == :regexp
228
228
  before = before.updated(:regexp, [*before.children[0...-1],
229
229
  s(:regopt, :g, *before.children.last)])
230
- elsif before.type == :str
230
+ elsif before.type == :str and not es2021
231
231
  before = before.updated(:regexp,
232
232
  [s(:str, Regexp.escape(before.children.first)), s(:regopt, :g)])
233
233
  end
234
234
  if after.type == :str
235
235
  after = s(:str, after.children.first.gsub(/\\(\d)/, "$\\1"))
236
236
  end
237
- process node.updated nil, [target, :replace, before, after]
237
+
238
+ if es2021
239
+ process node.updated nil, [target, :replaceAll, before, after]
240
+ else
241
+ process node.updated nil, [target, :replace, before, after]
242
+ end
238
243
 
239
244
  elsif method == :ord and args.length == 0
240
245
  if target.type == :str
@@ -767,10 +772,10 @@ module Ruby2JS
767
772
  body.any? {|statement| statement.type == :def and
768
773
  statement.children.first == :initialize}
769
774
  then
770
- body.unshift S(:def, :initialize, s(:args, s(:arg, :message)),
771
- s(:begin, S(:send, s(:self), :message=, s(:lvar, :message)),
772
- S(:send, s(:self), :name=, s(:sym, name.children[1])),
773
- S(:send, s(:self), :stack=, s(:send, s(:send, nil, :Error,
775
+ body.unshift s(:def, :initialize, s(:args, s(:arg, :message)),
776
+ s(:begin, s(:send, s(:self), :message=, s(:lvar, :message)),
777
+ s(:send, s(:self), :name=, s(:sym, name.children[1])),
778
+ s(:send, s(:self), :stack=, s(:attr, s(:send, nil, :Error,
774
779
  s(:lvar, :message)), :stack))))
775
780
  end
776
781
 
@@ -27,7 +27,11 @@ module Ruby2JS
27
27
 
28
28
  REACT_IMPORTS = {
29
29
  React: s(:import, ['react'], s(:attr, nil, :React)),
30
- ReactDOM: s(:import, ['react-dom'], s(:attr, nil, :ReactDOM))
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, '*'))
31
35
  }
32
36
 
33
37
  # the following command can be used to generate ReactAttrs:
@@ -75,7 +79,12 @@ module Ruby2JS
75
79
 
76
80
  ReactAttrMap = Hash[ReactAttrs.map {|name| [name.downcase, name]}]
77
81
  ReactAttrMap['for'] = 'htmlFor'
78
- ReactFragment = :'_React.Fragment'
82
+
83
+ PreactAttrMap = {
84
+ htmlFor: 'for',
85
+ onDoubleClick: 'onDblClick',
86
+ tabIndex: 'tabindex'
87
+ }
79
88
 
80
89
  def initialize(*args)
81
90
  @react = nil
@@ -118,12 +127,23 @@ module Ruby2JS
118
127
  def on_class(node)
119
128
  cname, inheritance, *body = node.children
120
129
  return super unless cname.children.first == nil
121
- return super unless inheritance == s(:const, nil, :React) or
122
- inheritance == s(:const, nil, :Vue) or
130
+
131
+ if inheritance == s(:const, nil, :React) or
123
132
  inheritance == s(:const, s(:const, nil, :React), :Component) or
124
133
  inheritance == s(:send, s(:const, nil, :React), :Component)
125
134
 
126
- prepend_list << REACT_IMPORTS[:React] if modules_enabled?
135
+ react = :React
136
+ prepend_list << REACT_IMPORTS[:React] if modules_enabled?
137
+
138
+ elsif inheritance == s(:const, nil, :Preact) or
139
+ inheritance == s(:const, s(:const, nil, :Preact), :Component) or
140
+ inheritance == s(:send, s(:const, nil, :Preact), :Component)
141
+
142
+ react = :Preact
143
+ prepend_list << REACT_IMPORTS[:Preact] if modules_enabled?
144
+ else
145
+ return super
146
+ end
127
147
 
128
148
  # traverse down to actual list of class statements
129
149
  if body.length == 1
@@ -141,12 +161,14 @@ module Ruby2JS
141
161
  end
142
162
 
143
163
  begin
144
- react, @react = @react, true
164
+ react, @react = @react, react
145
165
  reactClass, @reactClass = @reactClass, true
146
166
 
147
167
  pairs = []
148
168
 
149
- unless es2015
169
+ createClass = (@react == :React and not es2015)
170
+
171
+ if createClass
150
172
  # automatically capture the displayName for the class
151
173
  pairs << s(:pair, s(:sym, :displayName),
152
174
  s(:str, cname.children.last.to_s))
@@ -156,9 +178,8 @@ module Ruby2JS
156
178
  statics = []
157
179
  body.select {|child| child.type == :defs}.each do |child|
158
180
  _parent, mname, args, *block = child.children
159
- if es2015
160
- block = [s(:autoreturn, *block)] unless child.is_method?
161
- pairs << s(:defs, s(:self), mname, args, *block)
181
+ if not createClass
182
+ pairs << child
162
183
  elsif child.is_method?
163
184
  statics << s(:pair, s(:sym, mname), process(child.updated(:block,
164
185
  [s(:send, nil, :proc), args, s(:autoreturn, *block)])))
@@ -212,7 +233,7 @@ module Ruby2JS
212
233
  scan_events[node.children]
213
234
  end
214
235
  end
215
- scan_events[body] unless es2015
236
+ scan_events[body] if createClass
216
237
 
217
238
  # append statics (if any)
218
239
  unless statics.empty?
@@ -230,7 +251,7 @@ module Ruby2JS
230
251
  then
231
252
  @reactIvars = {pre: [], post: [], asgn: [], ref: [], cond: []}
232
253
  react_walk(node)
233
- if not es2015 and not @reactIvars.values.flatten.empty?
254
+ if createClass and not @reactIvars.values.flatten.empty?
234
255
  body = [s(:def, :getInitialState, s(:args),
235
256
  s(:return, s(:hash))), *body]
236
257
  elsif not needs_binding.empty? or not @reactIvars.values.flatten.empty?
@@ -251,7 +272,7 @@ module Ruby2JS
251
272
  (@reactIvars[:pre] + @reactIvars[:post]).uniq
252
273
 
253
274
  if mname == :initialize
254
- mname = es2015 ? :initialize : :getInitialState
275
+ mname = createClass ? :getInitialState : :initialize
255
276
 
256
277
  # extract real list of statements
257
278
  if block.length == 1
@@ -333,7 +354,7 @@ module Ruby2JS
333
354
  else
334
355
  # wrap multi-line blocks with a React Fragment
335
356
  block = [s(:return,
336
- s(:block, s(:send, nil, ReactFragment), s(:args), *block))]
357
+ s(:block, s(:send, nil, :"_#{@react}.Fragment"), s(:args), *block))]
337
358
  end
338
359
  end
339
360
 
@@ -359,14 +380,14 @@ module Ruby2JS
359
380
  type = :begin if block.first.type == :return
360
381
  end
361
382
 
362
- if es2015
383
+ if createClass
384
+ pairs << s(:pair, s(:sym, mname), child.updated(:block,
385
+ [s(:send, nil, :proc), args, process(s(type, *block))]))
386
+ else
363
387
  pairs << child.updated(
364
388
  ReactLifecycle.include?(mname.to_s) ? :defm : :def,
365
389
  [mname, args, process(s(type, *block))]
366
390
  )
367
- else
368
- pairs << s(:pair, s(:sym, mname), child.updated(:block,
369
- [s(:send, nil, :proc), args, process(s(type, *block))]))
370
391
  end
371
392
 
372
393
  # retain comment
@@ -374,38 +395,24 @@ module Ruby2JS
374
395
  @comments[pairs.last] = @comments[child]
375
396
  end
376
397
  end
398
+
399
+ if createClass
400
+ # emit a createClass statement
401
+ node.updated(:casgn, [nil, cname.children.last,
402
+ s(:send, s(:const, nil, :React), :createClass, s(:hash, *pairs))])
403
+ else
404
+ # emit a class that extends React.Component
405
+ node.updated(:class, [s(:const, nil, cname.children.last),
406
+ s(:attr, s(:const, nil, @react), :Component), *pairs])
407
+ end
377
408
  ensure
378
409
  @react = react
379
410
  @reactClass = reactClass
380
411
  @reactMethod = nil
381
412
  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
413
  end
393
414
 
394
415
  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
416
  # calls to methods (including getters) defined in this class
410
417
  if node.children[0]==nil and Symbol === node.children[1]
411
418
  if node.is_method?
@@ -423,16 +430,12 @@ module Ruby2JS
423
430
  end
424
431
  end
425
432
 
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
433
  if not @react
432
434
  # enable React filtering within React class method calls or
433
435
  # React component calls
434
436
  if \
435
437
  node.children.first == s(:const, nil, :React) or
438
+ node.children.first == s(:const, nil, :Preact) or
436
439
  node.children.first == s(:const, nil, :ReactDOM)
437
440
  then
438
441
  if modules_enabled?
@@ -440,7 +443,8 @@ module Ruby2JS
440
443
  end
441
444
 
442
445
  begin
443
- react, @react = @react, true
446
+ react = @react
447
+ @react = (node.children.first.children.last == :Preact ? :Preact : :React)
444
448
  return on_send(node)
445
449
  ensure
446
450
  @react = react
@@ -461,13 +465,26 @@ module Ruby2JS
461
465
  end
462
466
 
463
467
  elsif \
464
- @reactApply and node.children[1] == :createElement and
465
- node.children[0] == s(:const, nil, :React)
468
+ (@reactApply and node.children[1] == :createElement and
469
+ node.children[0] == s(:const, nil, :React)) or
470
+ (@reactApply and node.children[1] == :h and
471
+ node.children[0] == s(:const, nil, :Preact))
466
472
  then
467
473
  # push results of explicit calls to React.createElement
468
474
  s(:send, s(:gvar, :$_), :push, s(:send, *node.children[0..1],
469
475
  *process_all(node.children[2..-1])))
470
476
 
477
+ elsif \
478
+ @react == :Preact and node.children[1] == :h and node.children[0] == nil
479
+ then
480
+ if @reactApply
481
+ # push results of explicit calls to Preact.h
482
+ s(:send, s(:gvar, :$_), :push, s(:send, s(:const, nil, :Preact), :h,
483
+ *process_all(node.children[2..-1])))
484
+ else
485
+ node.updated(nil, [s(:const, nil, :Preact), :h, *process_all(node.children[2..-1])])
486
+ end
487
+
471
488
  elsif !@jsx and node.children[0] == nil and node.children[1] =~ /^_\w/
472
489
  # map method calls starting with an underscore to React calls
473
490
  # to create an element.
@@ -549,7 +566,12 @@ module Ruby2JS
549
566
  else
550
567
  value = s(:str, values.join(' '))
551
568
  end
552
- pairs.unshift s(:pair, s(:sym, :className), value)
569
+
570
+ if @react == :Preact
571
+ pairs.unshift s(:pair, s(:sym, :class), value)
572
+ else
573
+ pairs.unshift s(:pair, s(:sym, :className), value)
574
+ end
553
575
  end
554
576
 
555
577
  # support controlled form components
@@ -559,13 +581,28 @@ module Ruby2JS
559
581
  ['value', :value].include? pair.children.first.children.first
560
582
  end
561
583
 
562
- # search for the presence of a 'onChange' attribute
584
+ event = (@react == :Preact ? :onInput : :onChange)
585
+
586
+
587
+ # search for the presence of a onInput/onChange attribute
563
588
  onChange = pairs.find_index do |pair|
564
- ['onChange', :onChange].include? pair.children.first.children[0]
589
+ pair.children.first.children[0].to_s == event.to_s
590
+ end
591
+
592
+ if event == :onInput and not onChange
593
+ # search for the presence of a 'onChange' attribute
594
+ onChange = pairs.find_index do |pair|
595
+ pair.children.first.children[0].to_s == 'onChange'
596
+ end
597
+
598
+ if onChange
599
+ pairs[onChange] = s(:pair, s(:sym, event),
600
+ pairs[onChange].children.last)
601
+ end
565
602
  end
566
603
 
567
604
  if value and pairs[value].children.last.type == :ivar and !onChange
568
- pairs << s(:pair, s(:sym, :onChange),
605
+ pairs << s(:pair, s(:sym, event),
569
606
  s(:block, s(:send, nil, :proc), s(:args, s(:arg, :event)),
570
607
  s(:ivasgn, pairs[value].children.last.children.first,
571
608
  s(:attr, s(:attr, s(:lvar, :event), :target), :value))))
@@ -578,7 +615,7 @@ module Ruby2JS
578
615
  end
579
616
 
580
617
  if checked and pairs[checked].children.last.type == :ivar
581
- pairs << s(:pair, s(:sym, :onChange),
618
+ pairs << s(:pair, s(:sym, event),
582
619
  s(:block, s(:send, nil, :proc), s(:args),
583
620
  s(:ivasgn, pairs[checked].children.last.children.first,
584
621
  s(:send, pairs[checked].children.last, :!))))
@@ -586,13 +623,25 @@ module Ruby2JS
586
623
  end
587
624
  end
588
625
 
589
- # replace attribute names with case-sensitive javascript properties
590
- pairs.each_with_index do |pair, index|
591
- next if pair.type == :kwsplat
592
- name = pair.children.first.children.first.downcase
593
- if ReactAttrMap[name] and name.to_s != ReactAttrMap[name]
594
- pairs[index] = pairs[index].updated(nil,
595
- [s(:str, ReactAttrMap[name]), pairs[index].children.last])
626
+ if @react == :Preact
627
+ # replace selected Reactisms with native HTML
628
+ pairs.each_with_index do |pair, index|
629
+ next if pair.type == :kwsplat
630
+ name = pair.children.first.children.first.to_sym
631
+ if PreactAttrMap[name]
632
+ pairs[index] = pairs[index].updated(nil,
633
+ [s(:str, PreactAttrMap[name]), pairs[index].children.last])
634
+ end
635
+ end
636
+ else
637
+ # replace attribute names with case-sensitive javascript properties
638
+ pairs.each_with_index do |pair, index|
639
+ next if pair.type == :kwsplat
640
+ name = pair.children.first.children.first.downcase
641
+ if ReactAttrMap[name] and name.to_s != ReactAttrMap[name]
642
+ pairs[index] = pairs[index].updated(nil,
643
+ [s(:str, ReactAttrMap[name]), pairs[index].children.last])
644
+ end
596
645
  end
597
646
  end
598
647
 
@@ -654,8 +703,14 @@ module Ruby2JS
654
703
  # explicit call to React.createElement
655
704
  next true if arg.children[1] == :createElement and
656
705
  arg.children[0] == s(:const, nil, :React)
657
- next true if arg.children[1] == :createElement and
658
- arg.children[0] == s(:const, nil, :Vue)
706
+
707
+ # explicit call to Preact.h
708
+ next true if arg.children[1] == :h and
709
+ arg.children[0] == s(:const, nil, :Preact)
710
+
711
+ # explicit call to h
712
+ next true if arg.children[1] == :h and
713
+ arg.children[0] == nil
659
714
 
660
715
  # JSX
661
716
  next true if arg.type == :xstr
@@ -717,8 +772,13 @@ module Ruby2JS
717
772
  params.pop if params.last == s(:nil)
718
773
 
719
774
  # construct element using params
720
- element = node.updated(:send, [s(:const, nil, :React),
721
- :createElement, *params])
775
+ if @react == :Preact
776
+ element = node.updated(:send, [s(:const, nil, :Preact),
777
+ :h, *params])
778
+ else
779
+ element = node.updated(:send, [s(:const, nil, :React),
780
+ :createElement, *params])
781
+ end
722
782
 
723
783
  if @reactApply
724
784
  # if apply is set, emit code that pushes result
@@ -846,8 +906,13 @@ module Ruby2JS
846
906
  while node != child
847
907
  if node.children[1] !~ /!$/
848
908
  # convert method name to hash {className: name} pair
849
- pair = s(:pair, s(:sym, :className),
850
- s(:str, node.children[1].to_s.gsub('_','-')))
909
+ if @react == :Preact
910
+ pair = s(:pair, s(:sym, :class),
911
+ s(:str, node.children[1].to_s.gsub('_','-')))
912
+ else
913
+ pair = s(:pair, s(:sym, :className),
914
+ s(:str, node.children[1].to_s.gsub('_','-')))
915
+ end
851
916
  else
852
917
  # convert method name to hash {id: name} pair
853
918
  pair = s(:pair, s(:sym, :id),
@@ -917,8 +982,11 @@ module Ruby2JS
917
982
  # Base Ruby2JS processing will convert the 'splat' to 'apply'
918
983
  child = node.children.first
919
984
  if \
920
- child.children[1] == :createElement and
921
- child.children[0] == s(:const, nil, :React)
985
+ (child.children[1] == :createElement and
986
+ child.children[0] == s(:const, nil, :React)) or
987
+ (child.children[1] == :h and
988
+ (child.children[0] == s(:const, nil, :Preact) or
989
+ child.children[0] == nil))
922
990
  then
923
991
  begin
924
992
  reactApply, @reactApply = @reactApply, true
@@ -931,11 +999,13 @@ module Ruby2JS
931
999
  @reactApply = reactApply
932
1000
  end
933
1001
 
1002
+ target = child.children[0] || s(:const, nil, :Preact)
1003
+
934
1004
  if reactApply
935
1005
  return child.updated(:send, [s(:gvar, :$_), :push,
936
- s(:send, *child.children[0..1], *params)])
1006
+ s(:send, target, child.children[1], *params)])
937
1007
  else
938
- return child.updated(:send, [*child.children[0..1], *params])
1008
+ return child.updated(:send, [target, child.children[1], *params])
939
1009
  end
940
1010
  end
941
1011
 
@@ -952,7 +1022,7 @@ module Ruby2JS
952
1022
  block = s(:block, s(:send, nil, :proc), s(:args),
953
1023
  *node.children[2..-1])
954
1024
  return on_send node.children.first.updated(:send,
955
- [nil, ReactFragment, block])
1025
+ [nil, :"_#{@react}.Fragment", block])
956
1026
 
957
1027
  elsif !@jsx and child.children[0] == nil and child.children[1] =~ /^_\w/
958
1028
  if node.children[1].children.empty?
@@ -1020,7 +1090,7 @@ module Ruby2JS
1020
1090
  ivar = node.children.first.to_s
1021
1091
  if @reactBlock
1022
1092
  return s(:send, s(:self), :setState, s(:hash, s(:pair,
1023
- s(:lvar, ivar[1..-1]), process(s(:lvasgn, "$#{ivar[1..-1]}",
1093
+ s(:str, ivar[1..-1]), process(s(:lvasgn, "$#{ivar[1..-1]}",
1024
1094
  *node.children[1..-1])))))
1025
1095
  else
1026
1096
  return s(:lvasgn, "$#{ivar[1..-1]}",
@@ -1075,7 +1145,7 @@ module Ruby2JS
1075
1145
  if @reactMethod and @reactIvars[:capture].include? var
1076
1146
  if @reactBlock
1077
1147
  s(:send, s(:self), :setState, s(:hash, s(:pair,
1078
- s(:lvar, var[1..-1]), process(s(node.type,
1148
+ s(:str, var[1..-1]), process(s(node.type,
1079
1149
  s(:lvasgn, "$#{var[1..-1]}"), *node.children[1..-1])))))
1080
1150
  else
1081
1151
  process s(node.type, s(:lvasgn, "$#{var[1..-1]}"),
@@ -1118,9 +1188,13 @@ module Ruby2JS
1118
1188
  return true if node.children[1] == :createElement and
1119
1189
  node.children[0] == s(:const, nil, :React)
1120
1190
 
1121
- # explicit call to Vue.createElement
1122
- return true if node.children[1] == :createElement and
1123
- node.children[0] == s(:const, nil, :Vue)
1191
+ # explicit call to Preact.h
1192
+ return true if node.children[1] == :h and
1193
+ node.children[0] == s(:const, nil, :Preact)
1194
+
1195
+ # explicit call to h
1196
+ return true if node.children[1] == :h and
1197
+ node.children[0] == nil
1124
1198
  end
1125
1199
 
1126
1200
  # wunderbar style call
@@ -1280,7 +1354,7 @@ module Ruby2JS
1280
1354
  # update ivars that are set and later referenced
1281
1355
  unless @reactIvars[:post].empty?
1282
1356
  updates = @reactIvars[:post].uniq.sort.reverse.map do |ivar|
1283
- s(:pair, s(:lvar, ivar.to_s[1..-1]),
1357
+ s(:pair, s(:str, ivar.to_s[1..-1]),
1284
1358
  s(:lvar, "$#{ivar.to_s[1..-1]}"))
1285
1359
  end
1286
1360
  update = s(:send, s(:self), :setState, s(:hash, *updates))
@@ -1,8 +1,8 @@
1
1
  module Ruby2JS
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
- MINOR = 0
5
- TINY = 5
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -0,0 +1,20 @@
1
+ const { environment } = require('@rails/webpacker')
2
+
3
+ module.exports = {
4
+ test: /\.js\.rb$/,
5
+ use: [
6
+ {
7
+ loader: "babel-loader",
8
+ options: environment.loaders.get('babel').use[0].options
9
+ },
10
+
11
+ {
12
+ loader: "@ruby2js/webpack-loader",
13
+ options: {
14
+ autoexports: "default",
15
+ eslevel: 2021,
16
+ filters: ["esm", "functions"]
17
+ }
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,3 @@
1
+ @ruby2js_options = {filters: ['react']}
2
+ @yarn_add='preact'
3
+ eval IO.read "#{__dir__}/webpacker.rb"
@@ -27,40 +27,25 @@ insert_into_file Rails.root.join("config/webpacker.yml").to_s,
27
27
  # install webpack loader
28
28
  run "yarn add @ruby2js/webpack-loader #{@yarn_add}"
29
29
 
30
+ target = Rails.root.join("config/webpack/loaders/ruby2js.js").to_s
31
+
30
32
  # default config
31
- config = <<~CONFIG
32
- // Insert rb2js loader at the end of list
33
- environment.loaders.append('rb2js', {
34
- test: /\.js\.rb$/,
35
- use: [
36
- {
37
- loader: "babel-loader",
38
- options: environment.loaders.get('babel').use[0].options
39
- },
33
+ if not File.exist? target
34
+ # may be called via eval, or directly. Resolve source either way.
35
+ source_paths.unshift __dir__
36
+ source_paths.unshift File.dirname(caller.first)
37
+ directory "config/webpack/loaders", File.dirname(target)
38
+ end
40
39
 
41
- {
42
- loader: "@ruby2js/webpack-loader",
43
- options: {
44
- autoexports: "default",
45
- eslevel: 2021,
46
- filters: ["esm", "functions"]
47
- }
48
- },
49
- ]
50
- })
51
- CONFIG
40
+ # load config
41
+ insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
42
+ "environment.loaders.prepend('ruby2js', require('./loaders/ruby2js'))\n"
52
43
 
53
44
  # read current configuration
54
- target = Rails.root.join("config/webpack/environment.js").to_s
55
45
  before = IO.read(target)
56
46
 
57
- # extract indentation and options either from the current configuration or the
58
- # default configuration.
59
- if before.include? '@ruby2js/webpack-loader'
60
- match = /^(\s*)options: (\{.*?\n\1\})/m.match(before)
61
- else
62
- match = /^(\s*)options: (\{.*?\n\1\})/m.match(config)
63
- end
47
+ # extract indentation and options
48
+ match = /^(\s*)options: (\{.*?\n\1\})/m.match(before)
64
49
 
65
50
  # evaluate base options. Here it is handy that Ruby's syntax for hashes is
66
51
  # fairly close to JavaScript's object literals. May run into problems in the
@@ -90,8 +75,6 @@ replacement = Ruby2JS.convert(merged.inspect + "\n").to_s.
90
75
  gsub(/^/, match[1]).strip
91
76
 
92
77
  # Update configuration
93
- if before.include? '@ruby2js/webpack-loader'
78
+ unless before.include? replacement
94
79
  gsub_file target, match[2].to_s, replacement
95
- else
96
- append_to_file target, "\n" + config.sub(match[2], replacement)
97
80
  end
@@ -12,6 +12,11 @@ namespace :ruby2js do
12
12
  template 'install/litelement.rb'
13
13
  end
14
14
 
15
+ desc "Install Ruby2JS with Preact support"
16
+ task :preact do
17
+ template 'install/preact.rb'
18
+ end
19
+
15
20
  desc "Install Ruby2JS with React support"
16
21
  task :react do
17
22
  template 'install/react.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2js
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.5
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-03-11 00:00:00.000000000 Z
12
+ date: 2021-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parser
@@ -159,7 +159,9 @@ files:
159
159
  - lib/ruby2js/version.rb
160
160
  - lib/tasks/README.md
161
161
  - lib/tasks/install/app/javascript/elements/index.js
162
+ - lib/tasks/install/config/webpack/loaders/ruby2js.js
162
163
  - lib/tasks/install/litelement.rb
164
+ - lib/tasks/install/preact.rb
163
165
  - lib/tasks/install/react.rb
164
166
  - lib/tasks/install/stimulus-sprockets.rb
165
167
  - lib/tasks/install/stimulus-webpacker.rb