ruby2js 3.5.3 → 4.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -665
  3. data/lib/ruby2js.rb +60 -15
  4. data/lib/ruby2js/converter.rb +39 -3
  5. data/lib/ruby2js/converter/args.rb +6 -1
  6. data/lib/ruby2js/converter/assign.rb +159 -0
  7. data/lib/ruby2js/converter/begin.rb +7 -2
  8. data/lib/ruby2js/converter/case.rb +7 -2
  9. data/lib/ruby2js/converter/class.rb +80 -21
  10. data/lib/ruby2js/converter/class2.rb +107 -33
  11. data/lib/ruby2js/converter/def.rb +7 -3
  12. data/lib/ruby2js/converter/dstr.rb +8 -3
  13. data/lib/ruby2js/converter/for.rb +1 -1
  14. data/lib/ruby2js/converter/hash.rb +28 -6
  15. data/lib/ruby2js/converter/hide.rb +13 -0
  16. data/lib/ruby2js/converter/if.rb +10 -2
  17. data/lib/ruby2js/converter/import.rb +19 -4
  18. data/lib/ruby2js/converter/kwbegin.rb +9 -2
  19. data/lib/ruby2js/converter/literal.rb +14 -2
  20. data/lib/ruby2js/converter/logical.rb +1 -1
  21. data/lib/ruby2js/converter/module.rb +41 -4
  22. data/lib/ruby2js/converter/next.rb +10 -2
  23. data/lib/ruby2js/converter/opasgn.rb +8 -0
  24. data/lib/ruby2js/converter/redo.rb +14 -0
  25. data/lib/ruby2js/converter/return.rb +2 -1
  26. data/lib/ruby2js/converter/send.rb +73 -8
  27. data/lib/ruby2js/converter/vasgn.rb +5 -0
  28. data/lib/ruby2js/converter/while.rb +1 -1
  29. data/lib/ruby2js/converter/whilepost.rb +1 -1
  30. data/lib/ruby2js/converter/xstr.rb +2 -3
  31. data/lib/ruby2js/demo.rb +53 -0
  32. data/lib/ruby2js/es2022.rb +5 -0
  33. data/lib/ruby2js/es2022/strict.rb +3 -0
  34. data/lib/ruby2js/filter.rb +9 -1
  35. data/lib/ruby2js/filter/active_functions.rb +44 -0
  36. data/lib/ruby2js/filter/camelCase.rb +6 -3
  37. data/lib/ruby2js/filter/cjs.rb +2 -0
  38. data/lib/ruby2js/filter/esm.rb +118 -26
  39. data/lib/ruby2js/filter/functions.rb +137 -109
  40. data/lib/ruby2js/filter/{wunderbar.rb → jsx.rb} +29 -7
  41. data/lib/ruby2js/filter/node.rb +58 -14
  42. data/lib/ruby2js/filter/nokogiri.rb +12 -12
  43. data/lib/ruby2js/filter/react.rb +182 -57
  44. data/lib/ruby2js/filter/require.rb +102 -11
  45. data/lib/ruby2js/filter/return.rb +13 -1
  46. data/lib/ruby2js/filter/stimulus.rb +187 -0
  47. data/lib/ruby2js/jsx.rb +309 -0
  48. data/lib/ruby2js/namespace.rb +75 -0
  49. data/lib/ruby2js/serializer.rb +19 -12
  50. data/lib/ruby2js/sprockets.rb +40 -0
  51. data/lib/ruby2js/version.rb +3 -3
  52. data/ruby2js.gemspec +2 -2
  53. metadata +23 -13
  54. data/lib/ruby2js/filter/esm_migration.rb +0 -72
  55. data/lib/ruby2js/rails.rb +0 -63
@@ -0,0 +1,75 @@
1
+ # Instances of this class keep track of both classes and modules that we have
2
+ # seen before, as well as the methods and properties that are defined in each.
3
+ #
4
+ # Use cases this enables:
5
+ #
6
+ # * detection of "open" classes and modules, i.e., redefining a class or
7
+ # module that was previously declared in order to add or modify methods
8
+ # or properties.
9
+ #
10
+ # * knowing when to prefix method or property access with `this.` and
11
+ # when to add `.bind(this)` for methods and properties that were defined
12
+ # outside of this class.
13
+ #
14
+ module Ruby2JS
15
+ class Namespace
16
+ def initialize
17
+ @active = [] # current scope
18
+ @seen = {} # history of all definitions seen previously
19
+ end
20
+
21
+ # convert an AST name which is represented as a set of nested
22
+ # s(:const, # ...) into an array of symbols that represent
23
+ # the relative path.
24
+ def resolve(token, result = [])
25
+ return [] unless token&.type == :const
26
+ resolve(token.children.first, result)
27
+ result.push(token.children.last)
28
+ end
29
+
30
+ # return the active scope as a flat array of symbols
31
+ def active
32
+ @active.flatten.compact
33
+ end
34
+
35
+ # enter a new scope, which may be a nested subscope. Mark the new scope
36
+ # as seen, and return any previous definition that may have been seen
37
+ # before.
38
+ def enter(name)
39
+ @active.push resolve(name)
40
+ previous = @seen[active]
41
+ @seen[active] ||= {}
42
+ previous
43
+ end
44
+
45
+ # return the set of known properties (and methods) for either the current
46
+ # scope or a named subscope.
47
+ def getOwnProps(name = nil)
48
+ @seen[active + resolve(name)]&.dup || {}
49
+ end
50
+
51
+ # add new props (and methods) to the current scope.
52
+ def defineProps(props, namespace=active)
53
+ @seen[namespace] ||= {}
54
+ @seen[namespace].merge! props || {}
55
+ end
56
+
57
+ # find a named scope which may be relative to any point in the ancestry of
58
+ # the current scope. Return the properties for that scope.
59
+ def find(name)
60
+ name = resolve(name)
61
+ prefix = active
62
+ while prefix.pop
63
+ result = @seen[prefix + name]
64
+ return result if result
65
+ end
66
+ {}
67
+ end
68
+
69
+ # leave a given scope. Note that the scope may be compound (e.g., M::N),
70
+ # and if so, it will pop the entire resolved name.
71
+ def leave()
72
+ @active.pop
73
+ end
74
+ end
75
+ end
@@ -42,6 +42,7 @@ module Ruby2JS
42
42
 
43
43
  class Serializer
44
44
  attr_reader :timestamps
45
+ attr_accessor :file_name
45
46
 
46
47
  def initialize
47
48
  @sep = '; '
@@ -56,6 +57,7 @@ module Ruby2JS
56
57
  @timestamps = {}
57
58
 
58
59
  @ast = nil
60
+ @file_name = ''
59
61
  end
60
62
 
61
63
  def timestamp(file)
@@ -301,11 +303,11 @@ module Ruby2JS
301
303
  def vlq(*mark)
302
304
  if @mark[0] == mark[0]
303
305
  return if @mark[-3..-1] == mark[-3..-1]
304
- @mappings << ',' unless @mappings == ''
306
+ @mappings += ',' unless @mappings == ''
305
307
  end
306
308
 
307
309
  while @mark[0] < mark[0]
308
- @mappings << ';'
310
+ @mappings += ';'
309
311
  @mark[0] += 1
310
312
  @mark[1] = 0
311
313
  end
@@ -320,16 +322,21 @@ module Ruby2JS
320
322
  data = diff << 1
321
323
  end
322
324
 
323
- encoded = ''
324
-
325
- begin
326
- digit = data & 0b11111
327
- data >>= 5
328
- digit |= 0b100000 if data > 0
329
- encoded << BASE64[digit]
330
- end while data > 0
325
+ if data <= 0b11111
326
+ # workaround https://github.com/opal/opal/issues/575
327
+ encoded = BASE64[data]
328
+ else
329
+ encoded = ''
330
+
331
+ begin
332
+ digit = data & 0b11111
333
+ data >>= 5
334
+ digit |= 0b100000 if data > 0
335
+ encoded += BASE64[digit]
336
+ end while data > 0
337
+ end
331
338
 
332
- @mappings << encoded
339
+ @mappings += encoded
333
340
  end
334
341
  end
335
342
 
@@ -363,7 +370,7 @@ module Ruby2JS
363
370
 
364
371
  @sourcemap = {
365
372
  version: 3,
366
- file: @ast.loc.expression.source_buffer.name,
373
+ file: @file_name,
367
374
  sources: sources.map(&:name),
368
375
  mappings: @mappings
369
376
  }
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/source_map_utils'
3
+ require 'ruby2js'
4
+ require 'ruby2js/version'
5
+
6
+ module Ruby2JS
7
+ module SprocketsTransformer
8
+ include Sprockets
9
+ VERSION = '1'
10
+
11
+ @@options = {}
12
+
13
+ def self.options=(options)
14
+ @@options = options
15
+ end
16
+
17
+ def self.cache_key
18
+ @cache_key ||= "#{name}:#{Ruby2JS::VERSION::STRING}:#{VERSION}".freeze
19
+ end
20
+
21
+ def self.call(input)
22
+ data = input[:data]
23
+
24
+ js, map = input[:cache].fetch([self.cache_key, data]) do
25
+ result = Ruby2JS.convert(data, {**@@options, file: input[:filename]})
26
+ [result.to_s, result.sourcemap.transform_keys {|key| key.to_s}]
27
+ end
28
+
29
+ map = SourceMapUtils.format_source_map(map, input)
30
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
31
+
32
+ { data: js, map: map }
33
+ end
34
+ end
35
+ end
36
+
37
+ Sprockets.register_mime_type 'application/ruby', extensions: ['.rb', '.js.rb']
38
+
39
+ Sprockets.register_transformer 'application/ruby', 'application/javascript',
40
+ Ruby2JS::SprocketsTransformer
@@ -1,8 +1,8 @@
1
1
  module Ruby2JS
2
2
  module VERSION #:nodoc:
3
- MAJOR = 3
4
- MINOR = 5
5
- TINY = 3
3
+ MAJOR = 4
4
+ MINOR = 0
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/ruby2js.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
11
11
  s.require_paths = ["lib".freeze]
12
- s.authors = ["Sam Ruby".freeze]
12
+ s.authors = ["Sam Ruby".freeze, "Jared White".freeze]
13
13
  s.description = " The base package maps Ruby syntax to JavaScript semantics.\n Filters may be provided to add Ruby-specific or framework specific\n behavior.\n".freeze
14
14
  s.email = "rubys@intertwingly.net".freeze
15
15
  s.files = %w(ruby2js.gemspec README.md) + Dir.glob("{lib}/**/*")
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.summary = "Minimal yet extensible Ruby to JavaScript conversion.".freeze
20
20
 
21
21
  s.add_dependency('parser')
22
- s.add_dependency('regexp_parser')
22
+ s.add_dependency('regexp_parser', '~> 2.1.1')
23
23
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2js
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.3
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
- autorequire:
8
+ - Jared White
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2020-11-24 00:00:00.000000000 Z
12
+ date: 2021-03-03 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: parser
@@ -28,16 +29,16 @@ dependencies:
28
29
  name: regexp_parser
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - ">="
32
+ - - "~>"
32
33
  - !ruby/object:Gem::Version
33
- version: '0'
34
+ version: 2.1.1
34
35
  type: :runtime
35
36
  prerelease: false
36
37
  version_requirements: !ruby/object:Gem::Requirement
37
38
  requirements:
38
- - - ">="
39
+ - - "~>"
39
40
  - !ruby/object:Gem::Version
40
- version: '0'
41
+ version: 2.1.1
41
42
  description: |2
42
43
  The base package maps Ruby syntax to JavaScript semantics.
43
44
  Filters may be provided to add Ruby-specific or framework specific
@@ -54,6 +55,7 @@ files:
54
55
  - lib/ruby2js/converter/arg.rb
55
56
  - lib/ruby2js/converter/args.rb
56
57
  - lib/ruby2js/converter/array.rb
58
+ - lib/ruby2js/converter/assign.rb
57
59
  - lib/ruby2js/converter/begin.rb
58
60
  - lib/ruby2js/converter/block.rb
59
61
  - lib/ruby2js/converter/blockpass.rb
@@ -73,6 +75,7 @@ files:
73
75
  - lib/ruby2js/converter/fileline.rb
74
76
  - lib/ruby2js/converter/for.rb
75
77
  - lib/ruby2js/converter/hash.rb
78
+ - lib/ruby2js/converter/hide.rb
76
79
  - lib/ruby2js/converter/if.rb
77
80
  - lib/ruby2js/converter/import.rb
78
81
  - lib/ruby2js/converter/in.rb
@@ -88,6 +91,7 @@ files:
88
91
  - lib/ruby2js/converter/nthref.rb
89
92
  - lib/ruby2js/converter/opasgn.rb
90
93
  - lib/ruby2js/converter/prototype.rb
94
+ - lib/ruby2js/converter/redo.rb
91
95
  - lib/ruby2js/converter/regexp.rb
92
96
  - lib/ruby2js/converter/return.rb
93
97
  - lib/ruby2js/converter/self.rb
@@ -105,6 +109,7 @@ files:
105
109
  - lib/ruby2js/converter/xnode.rb
106
110
  - lib/ruby2js/converter/xstr.rb
107
111
  - lib/ruby2js/converter/yield.rb
112
+ - lib/ruby2js/demo.rb
108
113
  - lib/ruby2js/es2015.rb
109
114
  - lib/ruby2js/es2015/strict.rb
110
115
  - lib/ruby2js/es2016.rb
@@ -119,14 +124,17 @@ files:
119
124
  - lib/ruby2js/es2020/strict.rb
120
125
  - lib/ruby2js/es2021.rb
121
126
  - lib/ruby2js/es2021/strict.rb
127
+ - lib/ruby2js/es2022.rb
128
+ - lib/ruby2js/es2022/strict.rb
122
129
  - lib/ruby2js/execjs.rb
123
130
  - lib/ruby2js/filter.rb
131
+ - lib/ruby2js/filter/active_functions.rb
124
132
  - lib/ruby2js/filter/camelCase.rb
125
133
  - lib/ruby2js/filter/cjs.rb
126
134
  - lib/ruby2js/filter/esm.rb
127
- - lib/ruby2js/filter/esm_migration.rb
128
135
  - lib/ruby2js/filter/functions.rb
129
136
  - lib/ruby2js/filter/jquery.rb
137
+ - lib/ruby2js/filter/jsx.rb
130
138
  - lib/ruby2js/filter/matchAll.rb
131
139
  - lib/ruby2js/filter/minitest-jasmine.rb
132
140
  - lib/ruby2js/filter/node.rb
@@ -135,14 +143,16 @@ files:
135
143
  - lib/ruby2js/filter/require.rb
136
144
  - lib/ruby2js/filter/return.rb
137
145
  - lib/ruby2js/filter/securerandom.rb
146
+ - lib/ruby2js/filter/stimulus.rb
138
147
  - lib/ruby2js/filter/tagged_templates.rb
139
148
  - lib/ruby2js/filter/underscore.rb
140
149
  - lib/ruby2js/filter/vue.rb
141
- - lib/ruby2js/filter/wunderbar.rb
142
150
  - lib/ruby2js/haml.rb
143
- - lib/ruby2js/rails.rb
151
+ - lib/ruby2js/jsx.rb
152
+ - lib/ruby2js/namespace.rb
144
153
  - lib/ruby2js/serializer.rb
145
154
  - lib/ruby2js/sinatra.rb
155
+ - lib/ruby2js/sprockets.rb
146
156
  - lib/ruby2js/strict.rb
147
157
  - lib/ruby2js/version.rb
148
158
  - ruby2js.gemspec
@@ -150,7 +160,7 @@ homepage: http://github.com/rubys/ruby2js
150
160
  licenses:
151
161
  - MIT
152
162
  metadata: {}
153
- post_install_message:
163
+ post_install_message:
154
164
  rdoc_options: []
155
165
  require_paths:
156
166
  - lib
@@ -165,8 +175,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
165
175
  - !ruby/object:Gem::Version
166
176
  version: '0'
167
177
  requirements: []
168
- rubygems_version: 3.2.0.rc.1
169
- signing_key:
178
+ rubygems_version: 3.1.2
179
+ signing_key:
170
180
  specification_version: 4
171
181
  summary: Minimal yet extensible Ruby to JavaScript conversion.
172
182
  test_files: []
@@ -1,72 +0,0 @@
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
data/lib/ruby2js/rails.rb DELETED
@@ -1,63 +0,0 @@
1
- # Example usage:
2
- #
3
- # $ echo "gem 'ruby2js', require: 'ruby2js/rails'" >> Gemfile
4
- # $ bundle update
5
- # $ rails generate controller Say hello
6
- # $ echo 'alert "Hello world!"' > app/views/say/hello.js.rb
7
- # $ rails server
8
- # $ curl http://localhost:3000/say/hello.js
9
- #
10
- # Using an optional filter:
11
- #
12
- # $ echo 'require "ruby2js/filter/functions"' > config/initializers/ruby2js.rb
13
- #
14
- # Asset Pipeline:
15
- #
16
- # Ruby2JS registers ".rb.js" extension.
17
- # You can add "ruby_thing.js.rb" to your app/javascript folder
18
- # and '= require ruby_thing' from other js sources.
19
- #
20
- # (options are not yet supported, but by requiring the appropriate files
21
- # as shown above, you can configure proejct wide.)
22
- require 'ruby2js'
23
-
24
- module Ruby2JS
25
- module Rails
26
- class Template
27
- cattr_accessor :default_format
28
- self.default_format = Mime[:js]
29
- def self.call(template, source)
30
- "Ruby2JS.convert(#{template.source.inspect}, file: source).to_s"
31
- end
32
- end
33
-
34
- ActiveSupport.on_load(:action_view) do
35
- ActionView::Template.register_template_handler :rb, Template
36
- end
37
-
38
- class SprocketProcessor
39
- def initialize(file = nil)
40
- @file = file
41
- end
42
- def render(context , _)
43
- context = context.instance_eval { binding } unless context.is_a? Binding
44
- Ruby2JS.convert(File.read(@file), binding: context).to_s
45
- end
46
- end
47
-
48
- class Engine < ::Rails::Engine
49
- engine_name "ruby2js"
50
-
51
- config.app_generators.javascripts true
52
- config.app_generators.javascript_engine :rb
53
-
54
- config.assets.configure do |env|
55
- env.register_mime_type 'text/ruby', extensions: ['.js.rb', '.rb']
56
- env.register_transformer 'text/ruby', 'text/javascript', SprocketProcessor
57
- env.register_preprocessor 'text/javascript', SprocketProcessor
58
- end
59
- end
60
-
61
- end
62
-
63
- end