ruby2js 3.3.3 → 3.5.0
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/README.md +90 -65
- data/lib/ruby2js.rb +3 -0
- data/lib/ruby2js/converter.rb +4 -1
- data/lib/ruby2js/converter/block.rb +5 -0
- data/lib/ruby2js/converter/class2.rb +9 -3
- data/lib/ruby2js/converter/cvar.rb +1 -1
- data/lib/ruby2js/converter/cvasgn.rb +1 -1
- data/lib/ruby2js/converter/def.rb +16 -0
- data/lib/ruby2js/converter/dstr.rb +1 -1
- data/lib/ruby2js/converter/hash.rb +12 -2
- data/lib/ruby2js/converter/import.rb +78 -10
- data/lib/ruby2js/converter/ivar.rb +3 -3
- data/lib/ruby2js/converter/ivasgn.rb +1 -1
- data/lib/ruby2js/converter/logical.rb +1 -1
- data/lib/ruby2js/converter/return.rb +3 -1
- data/lib/ruby2js/converter/taglit.rb +13 -0
- data/lib/ruby2js/converter/yield.rb +12 -0
- data/lib/ruby2js/filter/camelCase.rb +78 -35
- data/lib/ruby2js/filter/esm.rb +44 -49
- data/lib/ruby2js/filter/esm_migration.rb +72 -0
- data/lib/ruby2js/filter/functions.rb +15 -1
- data/lib/ruby2js/filter/node.rb +10 -3
- data/lib/ruby2js/filter/nokogiri.rb +7 -3
- data/lib/ruby2js/filter/require.rb +0 -2
- data/lib/ruby2js/filter/return.rb +7 -3
- data/lib/ruby2js/filter/tagged_templates.rb +40 -0
- data/lib/ruby2js/serializer.rb +1 -1
- data/lib/ruby2js/version.rb +2 -2
- data/ruby2js.gemspec +1 -1
- metadata +11 -8
- data/lib/ruby2js/filter/rubyjs.rb +0 -112
@@ -6,10 +6,10 @@ module Ruby2JS
|
|
6
6
|
handle :ivar do |var|
|
7
7
|
if self.ivars and self.ivars.include? var
|
8
8
|
parse s(:hostvalue, self.ivars[var])
|
9
|
-
elsif
|
10
|
-
parse s(:attr, s(:self), var.to_s.sub('@', '#'))
|
11
|
-
else
|
9
|
+
elsif underscored_private
|
12
10
|
parse s(:attr, s(:self), var.to_s.sub('@', '_'))
|
11
|
+
else
|
12
|
+
parse s(:attr, s(:self), var.to_s.sub('@', '#'))
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -7,7 +7,7 @@ module Ruby2JS
|
|
7
7
|
handle :ivasgn do |var, expression=nil|
|
8
8
|
multi_assign_declarations if @state == :statement
|
9
9
|
|
10
|
-
put "#{ var.to_s.sub('@', 'this.' + (
|
10
|
+
put "#{ var.to_s.sub('@', 'this.' + (underscored_private ? '_' : '#')) }"
|
11
11
|
if expression
|
12
12
|
put " = "; parse expression
|
13
13
|
end
|
@@ -89,7 +89,7 @@ module Ruby2JS
|
|
89
89
|
def conditionally_equals(left, right)
|
90
90
|
if left == right
|
91
91
|
true
|
92
|
-
elsif !left or !right or left.type != :csend or right.type != :send
|
92
|
+
elsif !left.respond_to?(:type) or !left or !right or left.type != :csend or right.type != :send
|
93
93
|
false
|
94
94
|
else
|
95
95
|
conditionally_equals(left.children.first, right.children.first) &&
|
@@ -14,7 +14,7 @@ module Ruby2JS
|
|
14
14
|
|
15
15
|
EXPRESSIONS = [ :array, :float, :hash, :int, :lvar, :nil, :send, :attr,
|
16
16
|
:str, :sym, :dstr, :dsym, :cvar, :ivar, :zsuper, :super, :or, :and,
|
17
|
-
:block, :const, :true, :false, :xnode ]
|
17
|
+
:block, :const, :true, :false, :xnode, :taglit, :self ]
|
18
18
|
|
19
19
|
handle :autoreturn do |*statements|
|
20
20
|
return if statements == [nil]
|
@@ -55,6 +55,8 @@ module Ruby2JS
|
|
55
55
|
node = block.pop
|
56
56
|
children = node.children.dup
|
57
57
|
(1...children.length).each do |i|
|
58
|
+
next if children[i].nil? # case statements without else clause end with nil
|
59
|
+
|
58
60
|
if children[i].type == :when
|
59
61
|
gchildren = children[i].children.dup
|
60
62
|
if !gchildren.empty? and EXPRESSIONS.include? gchildren.last.type
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'ruby2js'
|
2
2
|
|
3
|
+
# Note care is taken to run all the filters first before camelCasing.
|
4
|
+
# This ensures that Ruby methods like each_pair can be mapped to
|
5
|
+
# JavaScript before camelcasing.
|
6
|
+
|
3
7
|
module Ruby2JS
|
4
8
|
module Filter
|
5
9
|
module CamelCase
|
@@ -9,75 +13,114 @@ module Ruby2JS
|
|
9
13
|
attr_accessor
|
10
14
|
}
|
11
15
|
|
16
|
+
CAPS_EXCEPTIONS = {
|
17
|
+
"innerHtml" => "innerHTML",
|
18
|
+
"innerHtml=" => "innerHTML=",
|
19
|
+
"outerHtml" => "outerHTML",
|
20
|
+
"outerHtml=" => "outerHTML=",
|
21
|
+
"encodeUri" => "encodeURI",
|
22
|
+
"encodeUriComponent" => "encodeURIComponent",
|
23
|
+
"decodeUri" => "decodeURI",
|
24
|
+
"decodeUriComponent" => "decodeURIComponent"
|
25
|
+
}
|
26
|
+
|
12
27
|
def camelCase(symbol)
|
13
|
-
symbol.
|
28
|
+
should_symbolize = symbol.is_a?(Symbol)
|
29
|
+
symbol = symbol
|
30
|
+
.to_s
|
31
|
+
.gsub(/(?!^)_[a-z0-9]/) {|match| match[1].upcase}
|
32
|
+
.gsub(/^(.*)$/) {|match| CAPS_EXCEPTIONS[match] || match }
|
33
|
+
should_symbolize ? symbol.to_sym : symbol
|
14
34
|
end
|
15
35
|
|
16
36
|
def on_send(node)
|
37
|
+
node = super
|
38
|
+
return node unless [:send, :csend, :attr].include? node.type
|
39
|
+
|
17
40
|
if node.children[0] == nil and WHITELIST.include? node.children[1].to_s
|
18
|
-
|
19
|
-
elsif node.children[
|
20
|
-
|
41
|
+
node
|
42
|
+
elsif node.children[0] && [:ivar, :cvar].include?(node.children[0].type)
|
43
|
+
S(node.type, s(node.children[0].type, camelCase(node.children[0].children[0])),
|
44
|
+
camelCase(node.children[1]), *node.children[2..-1])
|
45
|
+
elsif node.children[1] =~ /_.*\w[=!?]?$/
|
46
|
+
S(node.type, node.children[0],
|
21
47
|
camelCase(node.children[1]), *node.children[2..-1])
|
22
48
|
else
|
23
|
-
|
49
|
+
node
|
24
50
|
end
|
25
51
|
end
|
52
|
+
|
53
|
+
def on_csend(node)
|
54
|
+
on_send(node)
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_attr(node)
|
58
|
+
on_send(node)
|
59
|
+
end
|
60
|
+
|
61
|
+
def handle_generic_node(node, node_type)
|
62
|
+
return node if node.type != node_type
|
26
63
|
|
27
|
-
def on_def(node)
|
28
64
|
if node.children[0] =~ /_.*\w$/
|
29
|
-
|
65
|
+
S(node_type , camelCase(node.children[0]), *node.children[1..-1])
|
30
66
|
else
|
31
|
-
|
67
|
+
node
|
32
68
|
end
|
33
69
|
end
|
34
70
|
|
71
|
+
def on_def(node)
|
72
|
+
handle_generic_node(super, :def)
|
73
|
+
end
|
74
|
+
|
35
75
|
def on_optarg(node)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
76
|
+
handle_generic_node(super, :optarg)
|
77
|
+
end
|
78
|
+
|
79
|
+
def on_kwoptarg(node)
|
80
|
+
handle_generic_node(super, :kwoptarg)
|
41
81
|
end
|
42
82
|
|
43
83
|
def on_lvar(node)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
84
|
+
handle_generic_node(super, :lvar)
|
85
|
+
end
|
86
|
+
|
87
|
+
def on_ivar(node)
|
88
|
+
handle_generic_node(super, :ivar)
|
89
|
+
end
|
90
|
+
|
91
|
+
def on_cvar(node)
|
92
|
+
handle_generic_node(super, :cvar)
|
49
93
|
end
|
50
94
|
|
51
95
|
def on_arg(node)
|
52
|
-
|
53
|
-
super S(:arg , camelCase(node.children[0]), *node.children[1..-1])
|
54
|
-
else
|
55
|
-
super
|
56
|
-
end
|
96
|
+
handle_generic_node(super, :arg)
|
57
97
|
end
|
58
98
|
|
59
99
|
def on_lvasgn(node)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
100
|
+
handle_generic_node(super, :lvasgn)
|
101
|
+
end
|
102
|
+
|
103
|
+
def on_ivasgn(node)
|
104
|
+
handle_generic_node(super, :ivasgn)
|
105
|
+
end
|
106
|
+
|
107
|
+
def on_cvasgn(node)
|
108
|
+
handle_generic_node(super, :cvasgn)
|
65
109
|
end
|
66
110
|
|
67
111
|
def on_sym(node)
|
68
|
-
|
69
|
-
super S(:sym , camelCase(node.children[0]), *node.children[1..-1])
|
70
|
-
else
|
71
|
-
super
|
72
|
-
end
|
112
|
+
handle_generic_node(super, :sym)
|
73
113
|
end
|
74
114
|
|
75
115
|
def on_defs(node)
|
116
|
+
node = super
|
117
|
+
return node if node.type != :defs
|
118
|
+
|
76
119
|
if node.children[1] =~ /_.*\w$/
|
77
|
-
|
120
|
+
S(:defs , node.children[0],
|
78
121
|
camelCase(node.children[1]), *node.children[2..-1])
|
79
122
|
else
|
80
|
-
|
123
|
+
node
|
81
124
|
end
|
82
125
|
end
|
83
126
|
end
|
data/lib/ruby2js/filter/esm.rb
CHANGED
@@ -6,63 +6,58 @@ module Ruby2JS
|
|
6
6
|
include SEXP
|
7
7
|
|
8
8
|
def initialize(*args)
|
9
|
-
@esm_include = nil
|
10
9
|
super
|
10
|
+
@esm = true # signal for other filters
|
11
11
|
end
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
|
16
|
-
@esm_exclude = Set.new
|
17
|
-
@esm_export = nil
|
18
|
-
result = super
|
13
|
+
def on_send(node)
|
14
|
+
target, method, *args = node.children
|
15
|
+
return super unless target.nil?
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
list = inventory.map do |name|
|
28
|
-
if name == "React" and defined? Ruby2JS::Filter::React
|
29
|
-
s(:import, "#{name.downcase}", s(:const, nil, name))
|
30
|
-
elsif not %w(JSON Object).include? name
|
31
|
-
s(:import, "./#{name.downcase}.js", s(:const, nil, name))
|
32
|
-
end
|
17
|
+
if method == :import
|
18
|
+
# don't do the conversion if the word import is followed by a paren
|
19
|
+
if node.loc.respond_to? :selector
|
20
|
+
selector = node.loc.selector
|
21
|
+
if selector and selector.source_buffer
|
22
|
+
return super if selector.source_buffer.source[selector.end_pos] == '('
|
23
|
+
end
|
33
24
|
end
|
34
25
|
|
35
|
-
|
26
|
+
if args[0].type == :str
|
27
|
+
# import "file.css"
|
28
|
+
# => import "file.css"
|
29
|
+
s(:import, args[0].children[0])
|
30
|
+
elsif args.length == 1 and \
|
31
|
+
args[0].type == :send and \
|
32
|
+
args[0].children[0].nil? and \
|
33
|
+
args[0].children[2].type == :send and \
|
34
|
+
args[0].children[2].children[0].nil? and \
|
35
|
+
args[0].children[2].children[1] == :from and \
|
36
|
+
args[0].children[2].children[2].type == :str
|
37
|
+
# import name from "file.js"
|
38
|
+
# => import name from "file.js"
|
39
|
+
s(:import,
|
40
|
+
[args[0].children[2].children[2].children[0]],
|
41
|
+
process(s(:attr, nil, args[0].children[1])))
|
36
42
|
|
37
|
-
|
38
|
-
|
43
|
+
else
|
44
|
+
# import Stuff, "file.js"
|
45
|
+
# => import Stuff from "file.js"
|
46
|
+
# import Stuff, from: "file.js"
|
47
|
+
# => import Stuff from "file.js"
|
48
|
+
# import Stuff, as: "*", from: "file.js"
|
49
|
+
# => import Stuff as * from "file.js"
|
50
|
+
# import [ Some, Stuff ], from: "file.js"
|
51
|
+
# => import { Some, Stuff } from "file.js"
|
52
|
+
imports = (args[0].type == :const || args[0].type == :send) ?
|
53
|
+
process(args[0]) :
|
54
|
+
process_all(args[0].children)
|
55
|
+
s(:import, args[1].children, imports) unless args[1].nil?
|
39
56
|
end
|
40
|
-
|
41
|
-
s(:
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# gather constants
|
46
|
-
def esm_walk(node)
|
47
|
-
# extract ivars and cvars
|
48
|
-
if node.type == :const and node.children.first == nil
|
49
|
-
@esm_include << node.children.last.to_s
|
50
|
-
elsif node.type == :xnode
|
51
|
-
name = node.children.first
|
52
|
-
@esm_include << name unless name.empty? or name =~ /^[a-z]/
|
53
|
-
elsif node.type == :casgn and node.children.first == nil
|
54
|
-
@esm_exclude << node.children[1].to_s
|
55
|
-
elsif node.type == :class and node.children.first.type == :const
|
56
|
-
if node.children.first.children.first == nil
|
57
|
-
name = node.children.first.children.last.to_s
|
58
|
-
@esm_exclude << name
|
59
|
-
@esm_export ||= name
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# recurse
|
64
|
-
node.children.each do |child|
|
65
|
-
esm_walk(child) if Parser::AST::Node === child
|
57
|
+
elsif method == :export
|
58
|
+
s(:export, *process_all(args))
|
59
|
+
else
|
60
|
+
super
|
66
61
|
end
|
67
62
|
end
|
68
63
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'ruby2js'
|
2
|
+
|
3
|
+
module Ruby2JS
|
4
|
+
module Filter
|
5
|
+
module ESMMigration
|
6
|
+
include SEXP
|
7
|
+
|
8
|
+
def initialize(*args)
|
9
|
+
@esm_include = nil
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def process(node)
|
14
|
+
return super if @esm_include
|
15
|
+
@esm_include = Set.new
|
16
|
+
@esm_exclude = Set.new
|
17
|
+
@esm_export = nil
|
18
|
+
result = super
|
19
|
+
|
20
|
+
esm_walk(result)
|
21
|
+
|
22
|
+
inventory = (@esm_include - @esm_exclude).to_a.sort
|
23
|
+
|
24
|
+
if inventory.empty? and not @esm_export
|
25
|
+
result
|
26
|
+
else
|
27
|
+
list = inventory.map do |name|
|
28
|
+
if name == "React" and defined? Ruby2JS::Filter::React
|
29
|
+
s(:import, "#{name.downcase}", s(:const, nil, name))
|
30
|
+
elsif not %w(JSON Object).include? name
|
31
|
+
s(:import, "./#{name.downcase}.js", s(:const, nil, name))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
list.push result
|
36
|
+
|
37
|
+
if @esm_export
|
38
|
+
list.push s(:export, :default, s(:const, nil, @esm_export))
|
39
|
+
end
|
40
|
+
|
41
|
+
s(:begin, *list.compact)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# gather constants
|
46
|
+
def esm_walk(node)
|
47
|
+
# extract ivars and cvars
|
48
|
+
if node.type == :const and node.children.first == nil
|
49
|
+
@esm_include << node.children.last.to_s
|
50
|
+
elsif node.type == :xnode
|
51
|
+
name = node.children.first
|
52
|
+
@esm_include << name unless name.empty? or name =~ /^[a-z]/
|
53
|
+
elsif node.type == :casgn and node.children.first == nil
|
54
|
+
@esm_exclude << node.children[1].to_s
|
55
|
+
elsif node.type == :class and node.children.first.type == :const
|
56
|
+
if node.children.first.children.first == nil
|
57
|
+
name = node.children.first.children.last.to_s
|
58
|
+
@esm_exclude << name
|
59
|
+
@esm_export ||= name
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# recurse
|
64
|
+
node.children.each do |child|
|
65
|
+
esm_walk(child) if Parser::AST::Node === child
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
DEFAULTS.push ESMMigration
|
71
|
+
end
|
72
|
+
end
|
@@ -528,6 +528,9 @@ module Ruby2JS
|
|
528
528
|
elsif method == :new and target == s(:const, nil, :Exception)
|
529
529
|
process S(:send, s(:const, nil, :Error), :new, *args)
|
530
530
|
|
531
|
+
elsif method == :block_given? and target == nil and args.length == 0
|
532
|
+
process process s(:lvar, "_implicitBlockYield")
|
533
|
+
|
531
534
|
else
|
532
535
|
super
|
533
536
|
end
|
@@ -538,7 +541,7 @@ module Ruby2JS
|
|
538
541
|
method = call.children[1]
|
539
542
|
return super if excluded?(method)
|
540
543
|
|
541
|
-
if [:setInterval, :setTimeout].include? method
|
544
|
+
if [:setInterval, :setTimeout, :set_interval, :set_timeout].include? method
|
542
545
|
return super unless call.children.first == nil
|
543
546
|
block = process s(:block, s(:send, nil, :proc), *node.children[1..-1])
|
544
547
|
on_send call.updated nil, [*call.children[0..1], block,
|
@@ -703,6 +706,17 @@ module Ruby2JS
|
|
703
706
|
process call.updated(nil, [*call.children, s(:block,
|
704
707
|
s(:send, nil, :proc), *node.children[1..-1])])
|
705
708
|
|
709
|
+
elsif method == :yield_self and call.children.length == 2
|
710
|
+
process node.updated(:send, [s(:block, s(:send, nil, :proc),
|
711
|
+
node.children[1], s(:autoreturn, node.children[2])),
|
712
|
+
:[], call.children[0]])
|
713
|
+
|
714
|
+
elsif method == :tap and call.children.length == 2
|
715
|
+
process node.updated(:send, [s(:block, s(:send, nil, :proc),
|
716
|
+
node.children[1], s(:begin, node.children[2],
|
717
|
+
s(:return, s(:lvar, node.children[1].children[0].children[0])))),
|
718
|
+
:[], call.children[0]])
|
719
|
+
|
706
720
|
else
|
707
721
|
super
|
708
722
|
end
|