ruby2js 3.3.5 → 3.5.2

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: 290afa338befd02c8b83d54b13032a5e2d59c8a9cb96f2c413042d069c2614f8
4
- data.tar.gz: ed8506fa6b7dfbdcec3c59f6496a4cae822b18e597fb7030a10ae403d8b7c942
3
+ metadata.gz: 8995ca731fa2bedb5306084bca13f70aa01c269a3b3ac9b6c0ace540a0d58fae
4
+ data.tar.gz: 71c6cbb010ddf18f67623307c469f1ce4f55c4938c33a9e3172161f71819de87
5
5
  SHA512:
6
- metadata.gz: 3bfe229a4ac6718d7a79cc41d2ef8b014ac49c4f73366791ffb2b2487b1661dc9a74d91672f866464ba00b83dcbae464b4d1ce0f602aa37fef7c59cd0c2865be
7
- data.tar.gz: 9a2a2c7feb84284009900ece1a605922de023fb3173158799fb889cfd0d4ac6ff12d10cfbafa062e8cb133024ee58be204d0abc8fd7ef76d0b8fc20714069346
6
+ metadata.gz: b51e4838e7180248ffb00debab0758049dcc6a989bcc4b9e1087fb7112ac1a8142507c96e21309b23c3b69d987065e9d7fafb91dd0a7d8961b25f125fafc3788
7
+ data.tar.gz: fe7b943fc51b4f1685b5cc7020c969101d7a9aa17834bc6a8af746fdbe9472f9cc55960ef464f8dcfc10125598d6966a8cf38322ce432ec88e6dd787a49158ac
data/README.md CHANGED
@@ -5,6 +5,7 @@ Minimal yet extensible Ruby to JavaScript conversion.
5
5
 
6
6
  [![Build Status](https://travis-ci.org/rubys/ruby2js.svg)](https://travis-ci.org/rubys/ruby2js)
7
7
  [![Gem Version](https://badge.fury.io/rb/ruby2js.svg)](https://badge.fury.io/rb/ruby2js)
8
+ [![Gitter](https://badges.gitter.im/ruby2js/community.svg)](https://gitter.im/ruby2js/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
8
9
 
9
10
  Description
10
11
  ---
@@ -80,6 +81,12 @@ require 'ruby2js/filter/functions'
80
81
  puts Ruby2JS.convert('"2A".to_i(16)')
81
82
  ```
82
83
 
84
+ Host variable substitution:
85
+
86
+ ```ruby
87
+ puts Ruby2JS.convert("@name", ivars: {:@name => "Joe"})
88
+ ```
89
+
83
90
  Enable ES2015 support:
84
91
 
85
92
  ```ruby
@@ -104,6 +111,13 @@ Emit nullish coalescing operators:
104
111
  puts Ruby2JS.convert('a || 1', or: :nullish)
105
112
  ```
106
113
 
114
+ Emit underscored private fields (allowing subclass access):
115
+
116
+ ```ruby
117
+ puts Ruby2JS.convert('class C; def initialize; @f=1; end; end',
118
+ eslevel: 2020, underscored_private: true)
119
+ ```
120
+
107
121
  With [ExecJS](https://github.com/sstephenson/execjs):
108
122
  ```ruby
109
123
  require 'ruby2js/execjs'
@@ -193,7 +207,7 @@ Integrations
193
207
 
194
208
  While this is a low level library suitable for DIY integration, one of the
195
209
  obvious uses of a tool that produces JavaScript is by web servers. Ruby2JS
196
- includes three such integrations:
210
+ includes several integrations:
197
211
 
198
212
  * [CGI](https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/cgi.rb)
199
213
  * [Sinatra](https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/sinatra.rb)
@@ -204,6 +218,9 @@ As you might expect, CGI is a bit sluggish. By contrast, Sinatra and Rails
204
218
  are quite speedy as the bulk of the time is spent on the initial load of the
205
219
  required libraries.
206
220
 
221
+ For easy integration with Webpack (and Webpacker in Rails 5+), you can use the
222
+ [rb2js-loader](https://github.com/whitefusionhq/rb2js-loader) plugin.
223
+
207
224
  Filters
208
225
  ---
209
226
 
@@ -226,8 +243,10 @@ the script.
226
243
 
227
244
  * <a id="functions" href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/functions.rb">functions</a>
228
245
 
246
+ * `.abs` becomes `Math.abs()`
229
247
  * `.all?` becomes `.every`
230
248
  * `.any?` becomes `.some`
249
+ * `.ceil` becomes `Math.ceil()`
231
250
  * `.chr` becomes `fromCharCode`
232
251
  * `.clear` becomes `.length = 0`
233
252
  * `.delete` becomes `delete target[arg]`
@@ -242,6 +261,7 @@ the script.
242
261
  * `.find_index` becomes `findIndex`
243
262
  * `.first` becomes `[0]`
244
263
  * `.first(n)` becomes `.slice(0, n)`
264
+ * `.floor` becomes `Math.floor()`
245
265
  * `.gsub` becomes `replace(//g)`
246
266
  * `.include?` becomes `.indexOf() != -1`
247
267
  * `.inspect` becomes `JSON.stringify()`
@@ -270,10 +290,12 @@ the script.
270
290
  * `(b...a).to_a` becomes `Array.apply(null, {length: (a-b)}).map(Function.call, Number).map(function (idx) { return idx+b })`
271
291
  * `.strip` becomes `.trim`
272
292
  * `.sub` becomes `.replace`
293
+ * `.tap {|n| n}` becomes `(function(n) {n; return n})(...)`
273
294
  * `.to_f` becomes `parseFloat`
274
295
  * `.to_i` becomes `parseInt`
275
296
  * `.to_s` becomes `.to_String`
276
297
  * `.upcase` becomes `.toUpperCase`
298
+ * `.yield_self {|n| n}` becomes `(function(n) {return n})(...)`
277
299
  * `[-n]` becomes `[*.length-n]` for literal values of `n`
278
300
  * `[n...m]` becomes `.slice(n,m)`
279
301
  * `[n..m]` becomes `.slice(n,m+1)`
@@ -297,12 +319,78 @@ the script.
297
319
  of `Error` instead; and default constructors will be provided
298
320
  * `loop do...end` will be replaced with `while (true) {...}`
299
321
  * `raise Exception.new(...)` will be replaced with `throw new Error(...)`
322
+ * `block_given?` will check for the presence of optional argument `_implicitBlockYield` which is a function made accessible through the use of `yield` in a method body.
300
323
 
301
324
  Additionally, there is one mapping that will only be done if explicitly
302
- <a href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter.rb">included</a>:
325
+ included (pass `include: :class` as a `convert` option to enable):
303
326
 
304
327
  * `.class` becomes `.constructor`
305
328
 
329
+ * <a id="tagged_templates" href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/tagged_templates.rb">tagged_templates</a>
330
+
331
+ Allows you to turn certain method calls with a string argument into tagged
332
+ template literals. By default it supports html and css, so you can write
333
+ `html "<div>#{1+2}</div>"` which converts to `` html`<div>${1+2}</div>` ``.
334
+ Works nicely with squiggly heredocs for multi-line templates as well. If you
335
+ need to configure the tag names yourself, pass a `template_literal_tags`
336
+ option to `convert` with an array of tag name symbols.
337
+
338
+ Note: these conversions are only done if eslevel >= 2015
339
+
340
+ * <a href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/esm.rb">esm</a>
341
+
342
+ Provides conversion of import and export statements for use with modern ES builders like Webpack.
343
+
344
+ Examples:
345
+
346
+ **import**
347
+
348
+ ```ruby
349
+ import "./index.scss"
350
+ # => import "./index.scss"
351
+
352
+ import Something from "./lib/something"
353
+ # => import Something from "./lib/something"
354
+
355
+ import Something, "./lib/something"
356
+ # => import Something from "./lib/something"
357
+
358
+ import [ LitElement, html, css ], from: "lit-element"
359
+ # => import { LitElement, html, css } from "lit-element"
360
+
361
+ import React, from: "react"
362
+ # => import React from "react"
363
+
364
+ import React, as: "*", from: "react"
365
+ # => import React as * from "react"
366
+ ```
367
+
368
+ **export**
369
+
370
+ ```ruby
371
+ export hash = { ab: 123 }
372
+ # => export const hash = {ab: 123};
373
+
374
+ export func = ->(x) { x * 10 }
375
+ # => export const func = x => x * 10;
376
+
377
+ export def multiply(x, y)
378
+ return x * y
379
+ end
380
+ # => export function multiply(x, y) {
381
+ # return x * y
382
+ # }
383
+
384
+ export default class MyClass
385
+ end
386
+ # => export default class MyClass {
387
+ # };
388
+
389
+ # or final export statement:
390
+ export [ one, two, default: three ]
391
+ # => export { one, two, three as default }
392
+ ```
393
+
306
394
  * <a id="node" href="https://github.com/rubys/ruby2js/blob/master/spec/node_spec.rb">node</a>
307
395
 
308
396
  * `` `command` `` becomes `child_process.execSync("command", {encoding: "utf8"})`
@@ -388,68 +476,6 @@ the script.
388
476
  * `text` becomes `textContent`
389
477
  * `to_html` becomes `outerHTML`
390
478
 
391
- * <a id="rubyjs" href="https://github.com/rubys/ruby2js/blob/master/spec/rubyjs_spec.rb">rubyjs</a>
392
- * `.at()` becomes `_a.at()`
393
- * `.between?()` becomes `R().between()`
394
- * `.capitalize()` becomes `_s.capitalize()`
395
- * `.center()` becomes `_s.center()`
396
- * `.chomp()` becomes `_s.chomp()`
397
- * `.collect_concat()` becomes `_e.collect_concat()`
398
- * `.compact()` becomes `_a.compact()`
399
- * `.compact!()` becomes `_a.compact_bang()`
400
- * `.count()` becomes `_e.count()`
401
- * `.cycle()` becomes `_e.cycle()`
402
- * `.delete_at()` becomes `_a.delete_at()`
403
- * `.delete_if()` becomes `_a.delete_if()`
404
- * `.drop_while()` becomes `_e.drop_while()`
405
- * `.each_index()` becomes `_e.each_index()`
406
- * `.each_slice()` becomes `_e.each_slice()`
407
- * `.each_with_index()` becomes `_e.each_with_index()`
408
- * `.each_with_object()` becomes `_e.each_with_object()`
409
- * `.find_all()` becomes `_e.find_all()`
410
- * `.find()` becomes `_e.find()`
411
- * `.flat_map()` becomes `_e.flat_map()`
412
- * `.flatten()` becomes `_a.flatten()`
413
- * `.grep()` becomes `_e.grep()`
414
- * `.group_by()` becomes `_e.group_by()`
415
- * `.inject()` becomes `_e.inject()`
416
- * `.insert()` becomes `_a.insert()`
417
- * `.keep_if()` becomes `_a.keep_if()`
418
- * `.ljust()` becomes `_s.ljust()`
419
- * `.lstrip()` becomes `_s.lstrip()`
420
- * `.map()` becomes `_e.map()`
421
- * `.max_by()` becomes `_e.max_by()`
422
- * `.min_by()` becomes `_e.min_by()`
423
- * `.one?()` becomes `_e.one()`
424
- * `.partition()` becomes `_e.partition()`
425
- * `.reject()` becomes `_e.reject()`
426
- * `.reverse()` becomes `_a.reverse()`
427
- * `.reverse!()` becomes `_a.reverse_bang()`
428
- * `.reverse_each()` becomes `_e.reverse_each()`
429
- * `.rindex()` becomes `_s.rindex()`
430
- * `.rjust()` becomes `_s.rjust()`
431
- * `.rotate()` becomes `_a.rotate()`
432
- * `.rotate!()` becomes `_a.rotate_bang()`
433
- * `.rstrip()` becomes `_s.rstrip()`
434
- * `.scan()` becomes `_s.scan()`
435
- * `.select()` becomes `_a.select()`
436
- * `.shift()` becomes `_a.shift()`
437
- * `.shuffle()` becomes `_a.shuffle()`
438
- * `.shuffle!()` becomes `_a.shuffle_bang()`
439
- * `.slice()` becomes `_a.slice()`
440
- * `.slice!()` becomes `_a.slice_bang()`
441
- * `.sort_by()` becomes `_e.sort_by()`
442
- * `.strftime()` becomes `_t.strftime()`
443
- * `.swapcase()` becomes `_s.swapcase()`
444
- * `.take_while()` becomes `_e.take_while(`)
445
- * `.transpose()` becomes `_a.transpose()`
446
- * `.tr()` becomes `_s.tr()`
447
- * `.union()` becomes `_a.union()`
448
- * `.uniq()` becomes `_a.uniq()`
449
- * `.uniq!()` becomes `_a.uniq_bang()`
450
- * `<=>` becomes `R.Comparable.cmp()`
451
- * `(n..m)` becomes `R.Range.new()`
452
-
453
479
  * <a id="underscore" href="https://github.com/rubys/ruby2js/blob/master/spec/underscore.rb">underscore</a>
454
480
 
455
481
  * `.clone()` becomes `_.clone()`
@@ -605,6 +631,14 @@ conversions are made by the `functions` filter:
605
631
  * `.entries()` becomes `Object.entries()`
606
632
  * `.each_pair {}` becomes `for (let [key, value] of Object.entries()) {}'
607
633
 
634
+ async support:
635
+
636
+ * `async def` becomes `async function`
637
+ * `async lambda` becomes `async =>`
638
+ * `async proc` becomes `async =>`
639
+ * `async ->` becomes `async =>`
640
+ * `foo bar, async do...end` becomes `foo(bar, async () => {})`
641
+
608
642
  ES2018 support
609
643
  ---
610
644
 
@@ -677,7 +711,7 @@ License
677
711
 
678
712
  (The MIT License)
679
713
 
680
- Copyright (c) 2009, 2013 Macario Ortega, Sam Ruby
714
+ Copyright (c) 2009, 2020 Macario Ortega, Sam Ruby, Jared White
681
715
 
682
716
  Permission is hereby granted, free of charge, to any person obtaining
683
717
  a copy of this software and associated documentation files (the
@@ -17,6 +17,7 @@ module Ruby2JS
17
17
 
18
18
  @@eslevel_default = 2009 # ecmascript 5
19
19
  @@strict_default = false
20
+ @@module_default = nil
20
21
 
21
22
  def self.eslevel_default
22
23
  @@eslevel_default
@@ -34,6 +35,14 @@ module Ruby2JS
34
35
  @@strict_default = level
35
36
  end
36
37
 
38
+ def self.module_default
39
+ @@module_default
40
+ end
41
+
42
+ def self.module_default=(module_type)
43
+ @@module_default = module_type
44
+ end
45
+
37
46
  module Filter
38
47
  DEFAULTS = []
39
48
 
@@ -52,10 +61,14 @@ module Ruby2JS
52
61
  include Ruby2JS::Filter
53
62
  BINARY_OPERATORS = Converter::OPERATORS[2..-1].flatten
54
63
 
64
+ attr_accessor :prepend_list
65
+
55
66
  def initialize(comments)
56
67
  @comments = comments
57
68
  @ast = nil
58
69
  @exclude_methods = []
70
+ @esm = false
71
+ @prepend_list = Set.new
59
72
  end
60
73
 
61
74
  def options=(options)
@@ -134,6 +147,7 @@ module Ruby2JS
134
147
  def on_xnode(node); end
135
148
  def on_export(node); end
136
149
  def on_import(node); end
150
+ def on_taglit(node); end
137
151
 
138
152
  # provide a method so filters can call 'super'
139
153
  def on_sym(node); node; end
@@ -160,6 +174,7 @@ module Ruby2JS
160
174
  def self.convert(source, options={})
161
175
  options[:eslevel] ||= @@eslevel_default
162
176
  options[:strict] = @@strict_default if options[:strict] == nil
177
+ options[:module] ||= @@module_default || :esm
163
178
 
164
179
  if Proc === source
165
180
  file,line = source.source_location
@@ -191,6 +206,11 @@ module Ruby2JS
191
206
 
192
207
  filter.options = options
193
208
  ast = filter.process(ast)
209
+
210
+ if filter.prepend_list
211
+ prepend = filter.prepend_list.sort_by {|ast| ast.type == :import ? 0 : 1}
212
+ ast = Parser::AST::Node.new(:begin, [*prepend, ast])
213
+ end
194
214
  end
195
215
 
196
216
  ruby2js = Ruby2JS::Converter.new(ast, comments)
@@ -201,6 +221,8 @@ module Ruby2JS
201
221
  ruby2js.strict = options[:strict]
202
222
  ruby2js.comparison = options[:comparison] || :equality
203
223
  ruby2js.or = options[:or] || :logical
224
+ ruby2js.module_type = options[:module] || :esm
225
+ ruby2js.underscored_private = (options[:eslevel] < 2020) || options[:underscored_private]
204
226
  if ruby2js.binding and not ruby2js.ivars
205
227
  ruby2js.ivars = ruby2js.binding.eval \
206
228
  'Hash[instance_variables.map {|var| [var, instance_variable_get(var)]}]'
@@ -3,9 +3,11 @@ require 'ruby2js/serializer'
3
3
  module Ruby2JS
4
4
  class Error < NotImplementedError
5
5
  def initialize(message, ast)
6
- message += ' at ' + ast.loc.expression.source_buffer.name.to_s
7
- message += ':' + ast.loc.expression.line.inspect
8
- message += ':' + ast.loc.expression.column.to_s
6
+ if ast.loc
7
+ message += ' at ' + ast.loc.expression.source_buffer.name.to_s
8
+ message += ':' + ast.loc.expression.line.inspect
9
+ message += ':' + ast.loc.expression.column.to_s
10
+ end
9
11
  super(message)
10
12
  end
11
13
  end
@@ -63,6 +65,7 @@ module Ruby2JS
63
65
  @strict = false
64
66
  @comparison = :equality
65
67
  @or = :logical
68
+ @underscored_private = true
66
69
  end
67
70
 
68
71
  def width=(width)
@@ -127,7 +130,7 @@ module Ruby2JS
127
130
  Parser::AST::Node.new(type, args)
128
131
  end
129
132
 
130
- attr_accessor :strict, :eslevel, :comparison, :or
133
+ attr_accessor :strict, :eslevel, :module_type, :comparison, :or, :underscored_private
131
134
 
132
135
  def es2015
133
136
  @eslevel >= 2015
@@ -332,6 +335,7 @@ require 'ruby2js/converter/self'
332
335
  require 'ruby2js/converter/send'
333
336
  require 'ruby2js/converter/super'
334
337
  require 'ruby2js/converter/sym'
338
+ require 'ruby2js/converter/taglit'
335
339
  require 'ruby2js/converter/undef'
336
340
  require 'ruby2js/converter/until'
337
341
  require 'ruby2js/converter/untilpost'
@@ -341,3 +345,4 @@ require 'ruby2js/converter/while'
341
345
  require 'ruby2js/converter/whilepost'
342
346
  require 'ruby2js/converter/xstr'
343
347
  require 'ruby2js/converter/xnode'
348
+ require 'ruby2js/converter/yield'
@@ -9,6 +9,11 @@ module Ruby2JS
9
9
 
10
10
  handle :block do |call, args, block|
11
11
 
12
+ if es2017 and call.children.last == s(:send, nil, :async)
13
+ return parse call.updated(nil, [*call.children[0..-2],
14
+ s(:send, nil, :async, s(:block, s(:send, nil, :proc), args, block))])
15
+ end
16
+
12
17
  if \
13
18
  @state == :statement and args.children.length == 1 and
14
19
  call.children.first and call.children.first.type == :begin and
@@ -49,7 +49,7 @@ module Ruby2JS
49
49
  end
50
50
 
51
51
  # private variable declarations
52
- if es2020
52
+ unless underscored_private
53
53
  ivars = Set.new
54
54
  cvars = Set.new
55
55
 
@@ -202,7 +202,7 @@ module Ruby2JS
202
202
  end
203
203
 
204
204
  elsif m.type == :send and m.children.first == nil
205
- p = es2020 ? '#' : '_'
205
+ p = underscored_private ? '_' : '#'
206
206
 
207
207
  if m.children[1] == :attr_accessor
208
208
  m.children[2..-1].each_with_index do |child_sym, index2|
@@ -236,7 +236,7 @@ module Ruby2JS
236
236
  end
237
237
 
238
238
  else
239
- if m.type == :cvasgn and es2020
239
+ if m.type == :cvasgn and !underscored_private
240
240
  put 'static #$'; put m.children[0].to_s[2..-1]; put ' = '
241
241
  parse m.children[1]
242
242
  else
@@ -288,6 +288,12 @@ module Ruby2JS
288
288
  [name, innerclass_name.children[1]])
289
289
  end
290
290
  parse m.updated(nil, [innerclass_name, *m.children[1..-1]])
291
+ elsif m.type == :send && (m.children[0].nil? || m.children[0].type == :self)
292
+ if m.children[0].nil?
293
+ parse m.updated(:send, [@class_name, *m.children[1..-1]])
294
+ else
295
+ parse m.updated(:send, [@class_name, *m.children[1..-1]])
296
+ end
291
297
  else
292
298
  parse m, :statement
293
299
  end
@@ -4,7 +4,7 @@ module Ruby2JS
4
4
  # (cvar :@@a)
5
5
 
6
6
  handle :cvar do |var|
7
- prefix = es2020 ? '#$' : '_'
7
+ prefix = underscored_private ? '_' : '#$'
8
8
 
9
9
  @class_name ||= nil
10
10
  if @class_name
@@ -7,7 +7,7 @@ module Ruby2JS
7
7
  handle :cvasgn do |var, expression=nil|
8
8
  multi_assign_declarations if @state == :statement
9
9
 
10
- prefix = es2020 ? '#$' : '_'
10
+ prefix = underscored_private ? '_' : '#$'
11
11
 
12
12
  if @class_name
13
13
  parse @class_name