ruby2js 3.5.3 → 4.0.2

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.
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