ruby2js 3.3.4 → 3.5.1
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 +96 -65
- data/lib/ruby2js.rb +3 -0
- data/lib/ruby2js/converter.rb +9 -4
- 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 +9 -2
- data/lib/ruby2js/converter/import.rb +78 -10
- data/lib/ruby2js/converter/ivar.rb +13 -5
- 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/fast-deep-equal.rb +23 -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 +8 -4
- data/lib/ruby2js/filter/rubyjs.rb +0 -112
@@ -6,18 +6,26 @@ 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
|
|
16
16
|
handle :hostvalue do |value|
|
17
17
|
case value
|
18
18
|
when Hash
|
19
|
-
parse s(:hash, *value.map {|key, hvalue|
|
20
|
-
|
19
|
+
parse s(:hash, *value.map {|key, hvalue|
|
20
|
+
case key
|
21
|
+
when String
|
22
|
+
s(:pair, s(:str, key), s(:hostvalue, hvalue))
|
23
|
+
when Symbol
|
24
|
+
s(:pair, s(:sym, key), s(:hostvalue, hvalue))
|
25
|
+
else
|
26
|
+
s(:pair, s(:hostvalue, key), s(:hostvalue, hvalue))
|
27
|
+
end
|
28
|
+
})
|
21
29
|
when Array
|
22
30
|
parse s(:array, *value.map {|hvalue| s(:hostvalue, hvalue)})
|
23
31
|
when String
|
@@ -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
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'ruby2js'
|
2
|
+
|
3
|
+
module Ruby2JS
|
4
|
+
module Filter
|
5
|
+
module Fast_Deep_Equal
|
6
|
+
include SEXP
|
7
|
+
|
8
|
+
SCALAR = [ :float, :int, :nil, :str ]
|
9
|
+
|
10
|
+
def on_send(node)
|
11
|
+
return super unless node.children.length == 3
|
12
|
+
left, method, right = node.children
|
13
|
+
return super unless method == :==
|
14
|
+
return super if SCALAR.include? left.type
|
15
|
+
return super if SCALAR.include? right.type
|
16
|
+
|
17
|
+
node.updated nil, [nil, :$eq, left, right]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
DEFAULTS.push Fast_Deep_Equal
|
22
|
+
end
|
23
|
+
end
|