ruby2js 4.1.4 → 4.2.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.
@@ -69,16 +69,16 @@ module Ruby2JS
69
69
  left = rewrite(*left.children)
70
70
  end
71
71
 
72
- if right.type != :send
72
+ if right.type != :send or OPERATORS.flatten.include? right.children[1]
73
73
  s(:and, left, right)
74
74
  elsif conditionally_equals(left, right.children.first)
75
75
  # a && a.b => a&.b
76
- right.updated(:csend, [left, right.children.last])
76
+ right.updated(:csend, [left, *right.children[1..-1]])
77
77
  elsif conditionally_equals(left.children.last, right.children.first)
78
78
  # a && b && b.c => a && b&.c
79
79
  left.updated(:and, [left.children.first,
80
80
  left.children.last.updated(:csend,
81
- [left.children.last, right.children.last])])
81
+ [left.children.last, *right.children[1..-1]])])
82
82
  else
83
83
  s(:and, left, right)
84
84
  end
@@ -15,7 +15,7 @@ module Ruby2JS
15
15
  EXPRESSIONS = [ :array, :float, :hash, :int, :lvar, :nil, :send, :attr,
16
16
  :str, :sym, :dstr, :dsym, :cvar, :ivar, :zsuper, :super, :or, :and,
17
17
  :block, :const, :true, :false, :xnode, :taglit, :self,
18
- :op_asgn, :and_asgn, :or_asgn, :taglit, :gvar ]
18
+ :op_asgn, :and_asgn, :or_asgn, :taglit, :gvar, :csend ]
19
19
 
20
20
  handle :autoreturn do |*statements|
21
21
  return if statements == [nil]
@@ -17,8 +17,8 @@ module Ruby2JS
17
17
 
18
18
  LOGICAL = :and, :not, :or
19
19
  OPERATORS = [:[], :[]=], [:not, :!], [:**], [:*, :/, :%], [:+, :-],
20
- [:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=], [:==, :!=, :===, :"!=="],
21
- [:and, :or]
20
+ [:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=],
21
+ [:==, :!=, :===, :"!==", :=~, :!~], [:and, :or]
22
22
 
23
23
  INVERT_OP = {
24
24
  :< => :>=,
data/lib/ruby2js/demo.rb CHANGED
@@ -3,6 +3,34 @@ require 'ruby2js'
3
3
 
4
4
  module Ruby2JS
5
5
  module Demo
6
+ # convert {"[:foo, :Bar]" => "wee"} to {[:foo, :Bar] => "wee"}
7
+ def self.parse_stringified_symbol_keys(mapping_hash)
8
+ updated_mappings = {}
9
+
10
+ mapping_hash.each do |k, v|
11
+ next updated_mappings[k] = v unless k.is_a?(String) && k.start_with?("[:")
12
+
13
+ new_k = k.tr("[]", "").split(",").map! {|str| str.strip.delete_prefix(":").to_sym }.map(&:to_sym)
14
+ updated_mappings[new_k] = v
15
+ end
16
+
17
+ updated_mappings
18
+ end
19
+
20
+ # convert {"Foo" => "[:bar, :Baz]"} to {"Foo" => [:bar, :Baz]}
21
+ def self.parse_stringified_symbol_values(mapping_hash)
22
+ updated_mappings = {}
23
+
24
+ mapping_hash.each do |k, v|
25
+ next updated_mappings[k] = v unless v.is_a?(String) && v.start_with?("[:")
26
+
27
+ new_v = v.tr("[]", "").split(",").map! {|str| str.strip.delete_prefix(":").to_sym }.map(&:to_sym)
28
+ updated_mappings[k] = new_v
29
+ end
30
+
31
+ updated_mappings
32
+ end
33
+
6
34
  def self.parse_autoimports(mappings)
7
35
  autoimports = {}
8
36
 
@@ -7,7 +7,6 @@ module Ruby2JS
7
7
 
8
8
  def on_send(node)
9
9
  target, method, *args = node.children
10
- return super unless args.empty?
11
10
 
12
11
  if es2015 and method == :blank?
13
12
  create_or_update_import("blank$")
@@ -18,6 +17,15 @@ module Ruby2JS
18
17
  elsif es2015 and method == :presence
19
18
  create_or_update_import("presence$")
20
19
  process node.updated :send, [nil, "presence$", target]
20
+ elsif es2015 and method == :chomp
21
+ create_or_update_import("chomp$")
22
+ process node.updated :send, [nil, "chomp$", target, *args]
23
+ elsif es2015 and method == :delete_prefix
24
+ create_or_update_import("deletePrefix$")
25
+ process node.updated :send, [nil, "deletePrefix$", target, *args]
26
+ elsif es2015 and method == :delete_suffix
27
+ create_or_update_import("deleteSuffix$")
28
+ process node.updated :send, [nil, "deleteSuffix$", target, *args]
21
29
  else
22
30
  super
23
31
  end
@@ -69,7 +69,7 @@ module Ruby2JS
69
69
  def handle_generic_node(node, node_type)
70
70
  return node if node.type != node_type
71
71
 
72
- if node.children[0] =~ /_.*\w$/ and !ALLOWLIST.include?(node.children[0].to_s)
72
+ if node.children[0] =~ /_.*[?!\w]$/ and !ALLOWLIST.include?(node.children[0].to_s)
73
73
  S(node_type , camelCase(node.children[0]), *node.children[1..-1])
74
74
  else
75
75
  node
@@ -136,7 +136,7 @@ module Ruby2JS
136
136
  node = super
137
137
  return node if node.type != :defs
138
138
 
139
- if node.children[1] =~ /_.*\w$/
139
+ if node.children[1] =~ /_.*[?!\w]$/
140
140
  S(:defs , node.children[0],
141
141
  camelCase(node.children[1]), *node.children[2..-1])
142
142
  else
@@ -13,16 +13,30 @@ module Ruby2JS
13
13
  @esm_autoimports = options[:autoimports]
14
14
  @esm_defs = options[:defs] || {}
15
15
  @esm_explicit_tokens = Set.new
16
+ @esm_top = nil
17
+
18
+ # don't convert requires if Require filter is included
19
+ filters = options[:filters] || Filter::DEFAULTS
20
+ if \
21
+ defined? Ruby2JS::Filter::Require and
22
+ filters.include? Ruby2JS::Filter::Require
23
+ then
24
+ @esm_top = []
25
+ end
16
26
  end
17
27
 
18
28
  def process(node)
19
- return super unless @esm_autoexports
29
+ return super if @esm_top
20
30
 
21
31
  list = [node]
22
32
  while list.length == 1 and list.first.type == :begin
23
33
  list = list.first.children.dup
24
34
  end
25
35
 
36
+ @esm_top = list
37
+
38
+ return super unless @esm_autoexports
39
+
26
40
  replaced = []
27
41
  list.map! do |child|
28
42
  replacement = child
@@ -84,7 +98,7 @@ module Ruby2JS
84
98
  target, method, *args = node.children
85
99
  return super unless target.nil?
86
100
 
87
- if method == :import
101
+ if method == :import or (method == :require and @esm_top&.include? @ast)
88
102
  # don't do the conversion if the word import is followed by a paren
89
103
  if node.loc.respond_to? :selector
90
104
  selector = node.loc.selector
@@ -98,7 +112,7 @@ module Ruby2JS
98
112
  # => import "file.css"
99
113
  s(:import, args[0].children[0])
100
114
  elsif args.length == 1 and \
101
- args[0].type == :send and \
115
+ args[0].type == :send and \
102
116
  args[0].children[0].nil? and \
103
117
  args[0].children[2].type == :send and \
104
118
  args[0].children[2].children[0].nil? and \
@@ -152,17 +166,17 @@ module Ruby2JS
152
166
 
153
167
  values = @esm_defs[node.children.last]
154
168
 
155
- if values
156
- values = values.map {|value|
157
- if value.to_s.start_with? "@"
158
- [value.to_s[1..-1].to_sym, s(:self)]
159
- else
160
- [value.to_sym, s(:autobind, s(:self))]
161
- end
162
- }.to_h
163
-
164
- @namespace.defineProps values, [node.children.last]
165
- end
169
+ if values
170
+ values = values.map {|value|
171
+ if value.to_s.start_with? "@"
172
+ [value.to_s[1..-1].to_sym, s(:self)]
173
+ else
174
+ [value.to_sym, s(:autobind, s(:self))]
175
+ end
176
+ }.to_h
177
+
178
+ @namespace.defineProps values, [node.children.last]
179
+ end
166
180
  end
167
181
 
168
182
  super
@@ -341,7 +341,11 @@ module Ruby2JS
341
341
 
342
342
  elsif method == :last
343
343
  if node.children.length == 2
344
- process on_send S(:send, target, :[], s(:int, -1))
344
+ if es2022
345
+ process S(:send, target, :at, s(:int, -1))
346
+ else
347
+ process on_send S(:send, target, :[], s(:int, -1))
348
+ end
345
349
  elsif node.children.length == 3
346
350
  process S(:send, target, :slice,
347
351
  s(:send, s(:attr, target, :length), :-, node.children[2]),
@@ -358,8 +362,12 @@ module Ruby2JS
358
362
  # resolve negative literal indexes
359
363
  i = proc do |index|
360
364
  if index.type == :int and index.children.first < 0
361
- process S(:send, S(:attr, target, :length), :-,
362
- s(:int, -index.children.first))
365
+ if es2022
366
+ return process S(:send, target, :at, index)
367
+ else
368
+ process S(:send, S(:attr, target, :length), :-,
369
+ s(:int, -index.children.first))
370
+ end
363
371
  else
364
372
  index
365
373
  end
@@ -1,218 +1,2 @@
1
- require 'ruby2js'
2
-
3
- module Ruby2JS
4
- module Filter
5
- module LitElement
6
- include SEXP
7
- extend SEXP
8
-
9
- LITELEMENT_IMPORT = s(:import,
10
- [s(:pair, s(:sym, :from), s(:str, "lit-element"))],
11
- [s(:const, nil, :LitElement), s(:attr, nil, :css), s(:attr, nil, :html)])
12
-
13
- def initialize(node)
14
- super
15
- @le_props = nil
16
- end
17
-
18
- def on_ivar(node)
19
- return super unless @le_props&.include?(node.children.first)
20
- s(:attr, s(:self), node.children.first.to_s[1..-1])
21
- end
22
-
23
- def on_ivasgn(node)
24
- return super unless @le_props&.include?(node.children.first)
25
- return super unless node.children.length > 1
26
- s(:send, s(:self), node.children.first.to_s[1..-1]+'=',
27
- process(node.children[1]))
28
- end
29
-
30
- def on_op_asgn(node)
31
- return super unless node.children.first.type == :ivasgn
32
- var = node.children.first.children.first
33
- return super unless @le_props&.include?(var)
34
- super node.updated(nil, [s(:attr, s(:attr, nil, :this),
35
- var.to_s[1..-1]), *node.children[1..-1]])
36
- end
37
-
38
- def on_class(node)
39
- cname, inheritance, *body = node.children
40
- return super unless inheritance == s(:const, nil, :LitElement)
41
-
42
- @le_props = {}
43
- le_walk(node)
44
-
45
- prepend_list << LITELEMENT_IMPORT if modules_enabled?
46
-
47
- nodes = body.dup
48
- if nodes.length == 1 and nodes.first&.type == :begin
49
- nodes = nodes.first.children.dup
50
- end
51
-
52
- # insert/update static get properties() {}
53
- unless @le_props.empty?
54
- values = nodes.find_index {|child|
55
- child.type == :defs and child.children[0..1] == [s(:self), :properties]
56
- }
57
-
58
- if values == nil
59
- nodes.unshift s(:defp, s(:self), :properties, s(:args), s(:return,
60
- s(:hash, *@le_props.map {|name, type| s(:pair, s(:str, name.to_s[1..-1]),
61
- s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String))))})))
62
- elsif nodes[values].children[3].type == :hash
63
- le_props = @le_props.map {|name, type|
64
- [s(:sym, name.to_s[1..-1].to_sym),
65
- s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String)))]
66
- }.to_h.merge(
67
- nodes[values].children[3].children.map {|pair| pair.children}.to_h
68
- )
69
-
70
- nodes[values] = nodes[values].updated(nil,
71
- [*nodes[values].children[0..2], s(:hash,
72
- *le_props.map{|name, value| s(:pair, name, value)})])
73
- end
74
- end
75
-
76
- # render of a string is converted to a taglit :html
77
- render = nodes.find_index {|child|
78
- child&.type == :def and child.children.first == :render
79
- }
80
- if render and %i[str dstr].include?(nodes[render].children[2]&.type)
81
- nodes[render] = nodes[render].updated(:deff,
82
- [*nodes[render].children[0..1],
83
- s(:autoreturn, html_wrap(nodes[render].children[2]))])
84
- end
85
-
86
- # self.styles returning string is converted to a taglit :css
87
- styles = nodes.find_index {|child|
88
- child&.type == :defs and child.children[0..1] == [s(:self), :styles]
89
- }
90
- if styles and %i[str dstr].include?(nodes[styles].children[3]&.type)
91
- string = nodes[styles].children[3]
92
- string = s(:dstr, string) if string.type == :str
93
- children = string.children.dup
94
-
95
- while children.length > 1 and children.last.type == :str and
96
- children.last.children.last.strip == ''
97
- children.pop
98
- end
99
-
100
- if children.last.type == :str
101
- children << s(:str, children.pop.children.first.chomp)
102
- end
103
-
104
- nodes[styles] = nodes[styles].updated(nil,
105
- [*nodes[styles].children[0..2],
106
- s(:autoreturn, s(:taglit, s(:sym, :css),
107
- s(:dstr, *children)))])
108
- end
109
-
110
- # insert super calls into initializer
111
- initialize = nodes.find_index {|child|
112
- child&.type == :def and child.children.first == :initialize
113
- }
114
- if initialize and nodes[initialize].children.length == 3
115
- statements = nodes[initialize].children[2..-1]
116
-
117
- if statements.length == 1 and statements.first.type == :begin
118
- statements = statements.first.children
119
- end
120
-
121
- unless statements.any? {|statement| %i[super zuper].include? statement.type}
122
- nodes[initialize] = nodes[initialize].updated(nil,
123
- [*nodes[initialize].children[0..1],
124
- s(:begin, s(:zsuper), *statements)])
125
- end
126
- end
127
-
128
- props = @le_props.keys.map {|prop| [prop.to_sym, s(:self)]}.to_h
129
-
130
- nodes.unshift s(:defineProps, props)
131
-
132
- nodes.pop unless nodes.last
133
-
134
- node.updated(nil, [*node.children[0..1], s(:begin, *process_all(nodes))])
135
- ensure
136
- @le_props = nil
137
- end
138
-
139
- def html_wrap(node)
140
- if node.type == :str and node.children.first.strip.start_with? '<'
141
- s(:taglit, s(:sym, :html), s(:dstr, node))
142
- elsif node.type == :dstr
143
- prefix = ''
144
- node.children.each do |child|
145
- break unless child.type == :str
146
- prefix += child.children.first
147
- end
148
-
149
- return node unless prefix.strip.start_with? '<'
150
-
151
- children = node.children.map do |child|
152
- if child.type == :str
153
- child
154
- else
155
- html_wrap(child)
156
- end
157
- end
158
-
159
- while children.length > 1 and children.last.type == :str and
160
- children.last.children.last.strip == ''
161
- children.pop
162
- end
163
-
164
- if children.last.type == :str
165
- children << s(:str, children.pop.children.first.chomp)
166
- end
167
-
168
- s(:taglit, s(:sym, :html), node.updated(nil, children))
169
- elsif node.type == :begin
170
- node.updated(nil, node.children.map {|child| html_wrap(child)})
171
- elsif node.type == :if
172
- node.updated(nil, [node.children.first,
173
- *node.children[1..2].map {|child| html_wrap(child)}])
174
- elsif node.type == :block and
175
- node.children.first.children[1] == :map
176
- node.updated(nil, [*node.children[0..1],
177
- html_wrap(node.children[2])])
178
- else
179
- node
180
- end
181
- end
182
-
183
- # analyze ivar usage
184
- def le_walk(node)
185
- node.children.each do |child|
186
- next unless child.is_a? Parser::AST::Node
187
-
188
- if child.type == :ivar
189
- @le_props[child.children.first] ||= nil
190
- elsif child.type == :ivasgn || child.type == :op_asgn
191
- prop = child.children.first
192
- unless prop.is_a? Symbol
193
- prop = prop.children.first if prop.type == :ivasgn
194
- next unless prop.is_a? Symbol
195
- end
196
-
197
- @le_props[prop] = case child.children.last.type
198
- when :str, :dstr
199
- :String
200
- when :array
201
- :Array
202
- when :int, :float
203
- :Number
204
- when :true, :false
205
- :Boolean
206
- else
207
- @le_props[prop] || :Object
208
- end
209
- else
210
- le_walk(child)
211
- end
212
- end
213
- end
214
- end
215
-
216
- DEFAULTS.push LitElement
217
- end
218
- end
1
+ # for backwards compatibility
2
+ require_relative './lit'