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.
@@ -0,0 +1,290 @@
1
+ require 'ruby2js'
2
+
3
+ module Ruby2JS
4
+ module Filter
5
+ module Lit
6
+ include SEXP
7
+ extend SEXP
8
+
9
+ LITELEMENT_IMPORT = s(:import,
10
+ [s(:pair, s(:sym, :from), s(:str, "lit"))],
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
+ process 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
+
27
+ process s(:send, s(:self), node.children.first.to_s[1..-1]+'=',
28
+ process(node.children[1]))
29
+ end
30
+
31
+ def on_op_asgn(node)
32
+ return super unless node.children.first.type == :ivasgn
33
+ var = node.children.first.children.first
34
+ return super unless @le_props&.include?(var)
35
+ super node.updated(nil, [s(:attr, s(:attr, nil, :this),
36
+ var.to_s[1..-1]), *node.children[1..-1]])
37
+ end
38
+
39
+ def on_class(node)
40
+ class_name, inheritance, *body = node.children
41
+ return super unless inheritance == s(:const, nil, :LitElement)
42
+
43
+ @le_props = {}
44
+ le_walk(node)
45
+
46
+ prepend_list << LITELEMENT_IMPORT if modules_enabled?
47
+
48
+ nodes = body.dup
49
+ if nodes.length == 1 and nodes.first&.type == :begin
50
+ nodes = nodes.first.children.dup
51
+ end
52
+
53
+ # insert/update static get properties() {}
54
+ unless @le_props.empty?
55
+ values = nodes.find_index {|child|
56
+ (child.type == :defs and child.children[0..1] == [s(:self), :properties]) or
57
+ (child.type == :send and child.children[0..1] == [s(:self), :properties=])
58
+ }
59
+
60
+ if values == nil
61
+ if es2022
62
+ nodes.unshift process(s(:casgn, nil, :properties,
63
+ s(:hash, *@le_props.map {|name, type| s(:pair, s(:sym, name.to_s[1..-1]),
64
+ s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String))))})))
65
+ else
66
+ nodes.unshift process(s(:defp, s(:self), :properties, s(:args), s(:return,
67
+ s(:hash, *@le_props.map {|name, type| s(:pair, s(:sym, name.to_s[1..-1]),
68
+ s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String))))}))))
69
+ end
70
+ elsif nodes[values].children.last.type == :hash
71
+ le_props = @le_props.map {|name, type|
72
+ [s(:sym, name.to_s[1..-1].to_sym),
73
+ s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String)))]
74
+ }.to_h.merge(
75
+ nodes[values].children.last.children.map {|pair| pair.children}.to_h
76
+ )
77
+
78
+ nodes[values] = nodes[values].updated(nil,
79
+ [*nodes[values].children[0..-2], s(:hash,
80
+ *le_props.map{|name, value| s(:pair, name, value)})])
81
+ end
82
+ end
83
+
84
+ # customElement is converted to customElements.define
85
+ customElement = nodes.find_index {|child|
86
+ child&.type == :send and (child.children[0..1] == [nil, :customElement] || child.children[0..1] == [nil, :custom_element])
87
+ }
88
+ if customElement and nodes[customElement].children.length == 3
89
+ nodes[customElement] = nodes[customElement].updated(nil,
90
+ [s(:attr, nil, :customElements), :define,
91
+ nodes[customElement].children.last, class_name])
92
+ end
93
+
94
+ # render of a string is converted to a taglit :html
95
+ render = nodes.find_index {|child|
96
+ child&.type == :def and child.children.first == :render
97
+ }
98
+ if render and %i[str dstr begin if block].include?(nodes[render].children[2]&.type)
99
+ nodes[render] = nodes[render].updated(:deff,
100
+ [*nodes[render].children[0..1],
101
+ s(:autoreturn, html_wrap(nodes[render].children[2]))])
102
+ end
103
+
104
+ # self.styles returning string is converted to a taglit :css
105
+ styles = nodes.find_index {|child|
106
+ (child&.type == :ivasgn and child.children[0] == :@styles) or
107
+ (child&.type == :defs and child.children[0..1] == [s(:self), :styles]) or
108
+ (child&.type == :send and child.children[0..1] == [s(:self), :styles=])
109
+ }
110
+ if styles and %i[str dstr].include?(nodes[styles].children.last&.type)
111
+ string = nodes[styles].children.last
112
+ string = s(:dstr, string) if string.type == :str
113
+ children = string.children.dup
114
+
115
+ while children.length > 1 and children.last.type == :str and
116
+ children.last.children.last.strip == ''
117
+ children.pop
118
+ end
119
+
120
+ if children.last.type == :str
121
+ children << s(:str, children.pop.children.first.chomp)
122
+ end
123
+
124
+ if es2022
125
+ nodes[styles] = nodes[styles].updated(:casgn,
126
+ [nil, :styles, s(:taglit, s(:sym, :css),
127
+ s(:dstr, *children))])
128
+ else
129
+ nodes[styles] = nodes[styles].updated(:defp,
130
+ [s(:self), :styles, s(:args),
131
+ s(:autoreturn, s(:taglit, s(:sym, :css),
132
+ s(:dstr, *children)))])
133
+ end
134
+ end
135
+
136
+ # insert super calls into initializer
137
+ initialize = nodes.find_index {|child|
138
+ child&.type == :def and child.children.first == :initialize
139
+ }
140
+ if initialize and nodes[initialize].children.length == 3
141
+ statements = nodes[initialize].children[2..-1]
142
+
143
+ if statements.length == 1 and statements.first.type == :begin
144
+ statements = statements.first.children
145
+ end
146
+
147
+ unless statements.any? {|statement| %i[super zuper].include? statement.type}
148
+ nodes[initialize] = nodes[initialize].updated(nil,
149
+ [*nodes[initialize].children[0..1],
150
+ s(:begin, s(:zsuper), *statements)])
151
+ end
152
+ end
153
+
154
+ # props/methods inherited from LitElement
155
+ props = {
156
+ hasUpdated: s(:self),
157
+ performUpdate: s(:autobind, s(:self)),
158
+ renderRoot: s(:self),
159
+ requestUpdate: s(:autobind, s(:self)),
160
+ shadowRoot: s(:self),
161
+ updateComplete: s(:self),
162
+ }
163
+
164
+ # local props
165
+ props.merge! @le_props.keys.map {|prop| [prop.to_sym, s(:self)]}.to_h
166
+
167
+ nodes.unshift s(:defineProps, props)
168
+
169
+ nodes.pop unless nodes.last
170
+
171
+ node.updated(nil, [*node.children[0..1], s(:begin, *process_all(nodes))])
172
+ ensure
173
+ @le_props = nil
174
+ end
175
+
176
+ def html_wrap(node)
177
+ return node unless node.is_a?(Parser::AST::Node)
178
+
179
+ if node.type == :str and node.children.first.strip.start_with? '<'
180
+ s(:taglit, s(:sym, :html), s(:dstr, node))
181
+ elsif node.type == :dstr
182
+ prefix = ''
183
+ node.children.each do |child|
184
+ break unless child.type == :str
185
+ prefix += child.children.first
186
+ end
187
+
188
+ return node unless prefix.strip.start_with? '<'
189
+
190
+ children = node.children.map do |child|
191
+ if child.type == :str
192
+ child
193
+ else
194
+ html_wrap(child)
195
+ end
196
+ end
197
+
198
+ while children.length > 1 and children.last.type == :str and
199
+ children.last.children.last.strip == ''
200
+ children.pop
201
+ end
202
+
203
+ if children.last.type == :str
204
+ children << s(:str, children.pop.children.first.chomp)
205
+ end
206
+
207
+ s(:taglit, s(:sym, :html), node.updated(nil, children))
208
+ elsif node.type == :begin
209
+ node.updated(nil, node.children.map {|child| html_wrap(child)})
210
+ elsif node.type == :if
211
+ node.updated(nil, [node.children.first,
212
+ *node.children[1..2].map {|child| html_wrap(child)}])
213
+ elsif node.type == :block and
214
+ node.children.first.children[1] == :map
215
+ node.updated(nil, [*node.children[0..1],
216
+ html_wrap(node.children[2])])
217
+ else
218
+ node
219
+ end
220
+ end
221
+
222
+ def on_def(node)
223
+ node = super
224
+ return node if [:constructor, :initialize].include?(node.children.first)
225
+
226
+ children = node.children[1..-1]
227
+
228
+ node.updated nil, [node.children[0], children.first,
229
+ *(children[1..-1].map {|child| html_wrap(child) })]
230
+ end
231
+
232
+ # analyze ivar usage
233
+ def le_walk(node)
234
+ node.children.each do |child|
235
+ next unless child.is_a? Parser::AST::Node
236
+
237
+ if child.type == :ivar
238
+ next if child.children.first.to_s.start_with?("@_")
239
+
240
+ @le_props[child.children.first] ||= nil
241
+ elsif child.type == :ivasgn || child.type == :op_asgn
242
+ prop = child.children.first
243
+ unless prop.is_a? Symbol
244
+ prop = prop.children.first if prop.type == :ivasgn
245
+ next unless prop.is_a? Symbol
246
+ end
247
+
248
+ next if prop.to_s.start_with?("@_")
249
+
250
+ @le_props[prop] = case child.children.last.type
251
+ when :str, :dstr
252
+ :String
253
+ when :array
254
+ :Array
255
+ when :int, :float
256
+ :Number
257
+ when :true, :false
258
+ :Boolean
259
+ else
260
+ @le_props[prop] || :Object
261
+ end
262
+ else
263
+ le_walk(child)
264
+ end
265
+ end
266
+ end
267
+
268
+ def on_send(node)
269
+ target, method, *args = node.children
270
+
271
+ return super if target
272
+ return super unless %i{query queryAll queryAsync}.include? method
273
+ return super unless args.length == 1
274
+
275
+ result = s(:csend, s(:attr, s(:self), :renderRoot),
276
+ (method == :query ? 'querySelector' : 'querySelectorAll'),
277
+ args.first)
278
+
279
+ if method == :queryAsync
280
+ result = s(:block, s(:send, s(:attr, s(:self), :updateComplete),
281
+ :then), s(:args), result)
282
+ end
283
+
284
+ result
285
+ end
286
+ end
287
+
288
+ DEFAULTS.push Lit
289
+ end
290
+ end
@@ -41,9 +41,16 @@ module Ruby2JS
41
41
  #
42
42
  def self.genAttrs
43
43
  unless RUBY_ENGINE == 'opal'
44
- require 'nokogumbo'
45
- page = 'https://facebook.github.io/react/docs/tags-and-attributes.html'
46
- doc = Nokogiri::HTML5.get(page)
44
+ require 'nokogiri'
45
+ require 'uri'
46
+ require 'net/http'
47
+
48
+ page = 'https://reactjs.org/docs/dom-elements.html'
49
+ uri = URI.parse(page)
50
+ http = Net::HTTP.new(uri.host, uri.port)
51
+ http.use_ssl = true
52
+ data = http.get(uri.request_uri).body
53
+ doc = Nokogiri::HTML5::Document.parse(data)
47
54
 
48
55
  # delete contents of page prior to the list of supported attributes
49
56
  attrs = doc.at('a[name=supported-attributes]')
@@ -51,7 +58,7 @@ module Ruby2JS
51
58
  attrs.previous_sibling.remove while attrs and attrs.previous_sibling
52
59
 
53
60
  # extract attribute names with uppercase chars from code and format
54
- attrs = doc.search('code').map(&:text).join(' ')
61
+ attrs = doc.search('div[data-language=text] pre code').map(&:text).join(' ')
55
62
  attrs = attrs.split(/\s+/).grep(/[A-Z]/).sort.uniq.join(' ')
56
63
  puts "ReactAttrs = %w(#{attrs})".gsub(/(.{1,72})(\s+|\Z)/, "\\1\n")
57
64
  end
@@ -1492,7 +1499,13 @@ module Ruby2JS
1492
1499
  source = Ruby2JS.jsx2_rb(source)
1493
1500
  ast = Ruby2JS.parse(source).first
1494
1501
  ast = s(:block, s(:send, nil, :_), s(:args), ast) if ast.type == :begin
1495
- process ast
1502
+
1503
+ begin
1504
+ react, @react = @react, @react || :react
1505
+ process ast
1506
+ ensure
1507
+ @react = react
1508
+ end
1496
1509
  end
1497
1510
  end
1498
1511
 
@@ -9,12 +9,12 @@ module Ruby2JS
9
9
 
10
10
  STIMULUS_IMPORT = s(:import,
11
11
  [s(:pair, s(:sym, :as), s(:const, nil, :Stimulus)),
12
- s(:pair, s(:sym, :from), s(:str, "stimulus"))],
12
+ s(:pair, s(:sym, :from), s(:str, "@hotwired/stimulus"))],
13
13
  s(:str, '*'))
14
14
 
15
15
  STIMULUS_IMPORT_SKYPACK = s(:import,
16
16
  [s(:pair, s(:sym, :as), s(:const, nil, :Stimulus)),
17
- s(:pair, s(:sym, :from), s(:str, "https://cdn.skypack.dev/stimulus"))],
17
+ s(:pair, s(:sym, :from), s(:str, "https://cdn.skypack.dev/@hotwired/stimulus"))],
18
18
  s(:str, '*'))
19
19
 
20
20
  def initialize(*args)
@@ -18,6 +18,12 @@ module Ruby2JS
18
18
  else
19
19
  super
20
20
  end
21
+ elsif [:take, :drop].include? method and node.is_method?
22
+ process S(:send, s(:lvar, :_), method, node.children[0], node.children[2])
23
+ elsif method == :each_slice and node.is_method?
24
+ process S(:send, s(:lvar, :_), :chunk, node.children[0], node.children[2])
25
+ elsif [:min, :max].include? method and node.children.length == 2
26
+ process S(:send, s(:lvar, :_), method, node.children[0])
21
27
  elsif method == :sample and node.children.length <= 3
22
28
  process S(:send, s(:lvar, :_), :sample, node.children[0],
23
29
  *node.children[2..-1])
@@ -62,14 +68,14 @@ module Ruby2JS
62
68
  elsif method == :reduce
63
69
  if node.children.length == 3 and node.children[2].type == :sym
64
70
  # input: a.reduce(:+)
65
- # output: _.reduce(_.rest(a),
71
+ # output: _.reduce(_.rest(a),
66
72
  # proc {|memo, item| return memo+item},
67
73
  # a[0])
68
- process S(:send, s(:lvar, :_), :reduce,
74
+ process S(:send, s(:lvar, :_), :reduce,
69
75
  s(:send, s(:lvar, :_), :rest, node.children.first),
70
- s(:block, s(:send, nil, :proc),
76
+ s(:block, s(:send, nil, :proc),
71
77
  s(:args, s(:arg, :memo), s(:arg, :item)),
72
- s(:autoreturn, s(:send, s(:lvar, :memo),
78
+ s(:autoreturn, s(:send, s(:lvar, :memo),
73
79
  node.children[2].children.first, s(:lvar, :item)))),
74
80
  s(:send, node.children.first, :[], s(:int, 0)))
75
81
  elsif node.children.last.type == :block_pass
@@ -79,9 +85,9 @@ module Ruby2JS
79
85
  # input: a.reduce(n, :+)
80
86
  # output: _.reduce(a, proc {|memo, item| return memo+item}, n)
81
87
  process S(:send, s(:lvar, :_), :reduce, node.children.first,
82
- s(:block, s(:send, nil, :proc),
88
+ s(:block, s(:send, nil, :proc),
83
89
  s(:args, s(:arg, :memo), s(:arg, :item)),
84
- s(:autoreturn, s(:send, s(:lvar, :memo),
90
+ s(:autoreturn, s(:send, s(:lvar, :memo),
85
91
  node.children[3].children.first, s(:lvar, :item)))),
86
92
  node.children[2])
87
93
  else
@@ -93,8 +99,8 @@ module Ruby2JS
93
99
  # input: a.compact!
94
100
  # output: a.splice(0, a.length, *a.compact)
95
101
  target = node.children.first
96
- process S(:send, target, :splice, s(:int, 0),
97
- s(:attr, target, :length), s(:splat, s(:send, target,
102
+ process S(:send, target, :splice, s(:int, 0),
103
+ s(:attr, target, :length), s(:splat, s(:send, target,
98
104
  :"#{method.to_s[0..-2]}", *node.children[2..-1])))
99
105
  else
100
106
  super
@@ -111,14 +117,14 @@ module Ruby2JS
111
117
  # output: _.sortBy {return expression}
112
118
  method = method.to_s.sub(/\_by$/,'By').to_sym
113
119
  process S(:block, s(:send, s(:lvar, :_), method,
114
- call.children.first), node.children[1],
120
+ call.children.first), node.children[1],
115
121
  s(:autoreturn, node.children[2]))
116
122
  elsif [:find, :reject].include? method
117
123
  if call.children.length == 2
118
124
  # input: a.find {|item| item > 0}
119
125
  # output: _.find(a) {|item| return item > 0}
120
- process S(:block, s(:send, s(:lvar, :_), method,
121
- call.children.first), node.children[1],
126
+ process S(:block, s(:send, s(:lvar, :_), method,
127
+ call.children.first), node.children[1],
122
128
  s(:autoreturn, node.children[2]))
123
129
  else
124
130
  super
@@ -127,25 +133,25 @@ module Ruby2JS
127
133
  elsif method == :times and call.children.length == 2
128
134
  # input: 5.times {|i| console.log i}
129
135
  # output: _.find(5) {|i| console.log(i)}
130
- process S(:block, s(:send, s(:lvar, :_), method,
136
+ process S(:block, s(:send, s(:lvar, :_), method,
131
137
  call.children.first), node.children[1], node.children[2])
132
138
 
133
139
  elsif method == :reduce
134
140
  if call.children.length == 2
135
141
  # input: a.reduce {|memo, item| memo+item}
136
- # output: _.reduce(_.rest(a),
142
+ # output: _.reduce(_.rest(a),
137
143
  # proc {|memo, item| return memo+item},
138
144
  # a[0])
139
- process S(:call, s(:lvar, :_), :reduce,
145
+ process S(:call, s(:lvar, :_), :reduce,
140
146
  s(:send, s(:lvar, :_), :rest, call.children.first),
141
- s(:block, s(:send, nil, :proc),
147
+ s(:block, s(:send, nil, :proc),
142
148
  node.children[1], s(:autoreturn, node.children[2])),
143
149
  s(:send, call.children.first, :[], s(:int, 0)))
144
150
  elsif call.children.length == 3
145
151
  # input: a.reduce(n) {|memo, item| memo+item}
146
152
  # output: _.reduce(a, proc {|memo, item| return memo+item}, n)
147
153
  process S(:call, s(:lvar, :_), :reduce, call.children.first,
148
- s(:block, s(:send, nil, :proc),
154
+ s(:block, s(:send, nil, :proc),
149
155
  node.children[1], s(:autoreturn, node.children[2])),
150
156
  call.children[2])
151
157
  end
@@ -155,7 +161,7 @@ module Ruby2JS
155
161
  # output: a.splice(0, a.length, *a.map {expression})
156
162
  method = :"#{method.to_s[0..-2]}"
157
163
  target = call.children.first
158
- process S(:call, target, :splice, s(:splat, s(:send, s(:array,
164
+ process S(:call, target, :splice, s(:splat, s(:send, s(:array,
159
165
  s(:int, 0), s(:attr, target, :length)), :concat,
160
166
  s(:block, s(:send, target, method, *call.children[2..-1]),
161
167
  *node.children[1..-1]))))
@@ -1,8 +1,8 @@
1
1
  module Ruby2JS
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
- MINOR = 1
5
- TINY = 4
4
+ MINOR = 2
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,5 +1,5 @@
1
- @ruby2js_options = {filters: ['lit-element']}
2
- @yarn_add='lit-element'
1
+ @ruby2js_options = {filters: ['lit']}
2
+ @yarn_add='lit'
3
3
  eval IO.read "#{__dir__}/webpacker.rb"
4
4
 
5
5
  directory File.expand_path("app/javascript/elements", __dir__),
@@ -0,0 +1,44 @@
1
+ # install rollup plugin
2
+ run "yarn add @ruby2js/rollup-plugin"
3
+
4
+ # configure rollup for ruby2js with stimulus filters
5
+ insert_into_file Rails.root.join("rollup.config.js").to_s,
6
+ "import ruby2js from '@ruby2js/rollup-plugin';\n",
7
+ after: /import resolve from .*\n/
8
+
9
+ insert_into_file Rails.root.join("rollup.config.js").to_s,
10
+ <<-CONFIG, after: "resolve()\n"
11
+ ,ruby2js({
12
+ eslevel: 2020,
13
+ autoexports: 'default',
14
+ filters: ['stimulus', 'esm', 'functions']
15
+ })
16
+ CONFIG
17
+
18
+ # monkey patch stimulus:manifest:update to find .rb.js controllers too.
19
+ # See https://github.com/hotwired/stimulus-rails/issues/76
20
+ append_to_file Rails.root.join('config/application.rb').to_s,
21
+ "\n" + <<~'CONFIG'
22
+ require 'stimulus/manifest'
23
+
24
+ module Stimulus::Manifest
25
+ def import_and_register_controller(controllers_path, controller_path)
26
+ controller_path = controller_path.relative_path_from(controllers_path).to_s
27
+ module_path = controller_path.split('.').first
28
+ controller_class_name = module_path.camelize.gsub(/::/, "__")
29
+ tag_name = module_path.remove(/_controller/).gsub(/_/, "-").gsub(/\//, "--")
30
+
31
+ <<~JS
32
+
33
+ import #{controller_class_name} from "./#{controller_path}"
34
+ application.register("#{tag_name}", #{controller_class_name})
35
+ JS
36
+ end
37
+
38
+ def extract_controllers_from(directory)
39
+ (directory.children.select { |e| e.to_s =~ /_controller\.js(\.\w+)?$/ } +
40
+ directory.children.select(&:directory?).collect { |d| extract_controllers_from(d) }
41
+ ).flatten.sort
42
+ end
43
+ end
44
+ CONFIG
@@ -1,32 +1,25 @@
1
1
  create_file Rails.root.join('config/initializers/ruby2js.rb').to_s,
2
2
  <<~CONFIG
3
- require 'ruby2js/filter/esm'
4
- require 'ruby2js/filter/functions'
5
- require 'ruby2js/filter/stimulus'
3
+ require 'stimulus/manifest'
6
4
 
7
- Ruby2JS::SprocketsTransformer.options = {
8
- autoexports: :default,
9
- eslevel: 2020
10
- }
5
+ module Stimulus::Manifest
6
+ def import_and_register_controller(controllers_path, controller_path)
7
+ controller_path = controller_path.relative_path_from(controllers_path).to_s
8
+ module_path = controller_path.split('.').first
9
+ controller_class_name = module_path.camelize.gsub(/::/, "__")
10
+ tag_name = module_path.remove(/_controller/).gsub(/_/, "-").gsub(/\//, "--")
11
11
 
12
- require 'stimulus/importmap_helper'
12
+ <<~JS
13
13
 
14
- module Stimulus::ImportmapHelper
15
- def find_javascript_files_in_tree(path)
16
- exts = {'.js' => '.js', '.jsm' => '.jsm'}.merge(
17
- Sprockets.mime_exts.map {|key, value|
18
- next unless Sprockets.transformers[value]["application/javascript"]
19
- [key, '.js']
20
- }.compact.to_h)
21
-
22
- Dir[path.join('**/*')].map {|file|
23
- file_ext, web_ext = Sprockets::PathUtils.match_path_extname(file, exts)
24
- next unless file_ext
25
-
26
- next unless File.file? file
14
+ import #{controller_class_name} from "./#{controller_path}"
15
+ application.register("#{tag_name}", #{controller_class_name})
16
+ JS
17
+ end
27
18
 
28
- Pathname.new(file.chomp(file_ext) + web_ext)
29
- }.compact
19
+ def extract_controllers_from(directory)
20
+ (directory.children.select { |e| e.to_s =~ /_controller\.js(\.\w+)?$/ } +
21
+ directory.children.select(&:directory?).collect { |d| extract_controllers_from(d) }
22
+ ).flatten.sort
30
23
  end
31
24
  end
32
25
  CONFIG
@@ -3,3 +3,6 @@ eval IO.read "#{__dir__}/webpacker.rb"
3
3
 
4
4
  insert_into_file Rails.root.join("app/javascript/controllers/index.js").to_s,
5
5
  '(\\.rb)?', after: '_controller\\.js'
6
+
7
+ insert_into_file Rails.root.join("app/javascript/packs/application.js").to_s,
8
+ "import \"../controllers\"\n", after: "import \"channels\"\n"
@@ -1,4 +1,6 @@
1
- Thor::Actions::WARNINGS[:unchanged_no_flag] = 'unchanged'
1
+ if defined? Thor
2
+ Thor::Actions::WARNINGS[:unchanged_no_flag] = 'unchanged'
3
+ end
2
4
 
3
5
  def template(location)
4
6
  system "#{RbConfig.ruby} #{Rails.root.join("bin")}/rails app:template " +
@@ -9,7 +11,7 @@ namespace :ruby2js do
9
11
  namespace :install do
10
12
  desc "Install Ruby2JS with LitElement support"
11
13
  task :litelement do
12
- template 'install/litelement.rb'
14
+ template 'install/lit-webpacker.rb'
13
15
  end
14
16
 
15
17
  desc "Install Ruby2JS with Preact support"
@@ -24,9 +26,9 @@ namespace :ruby2js do
24
26
  end
25
27
 
26
28
  namespace :stimulus do
27
- desc "Install Ruby2JS with Stimulus Sprockets support"
28
- task :sprockets => :"stimulus:install:asset_pipeline" do
29
- template 'install/stimulus-sprockets.rb'
29
+ desc "Install Ruby2JS with Stimulus Rollup support"
30
+ task :rollup do
31
+ template 'install/stimulus-rollup.rb'
30
32
  end
31
33
 
32
34
  desc "Install Ruby2JS with Stimulus Webpacker support"
@@ -34,6 +36,18 @@ namespace :ruby2js do
34
36
  template 'install/stimulus-webpacker.rb'
35
37
  end
36
38
  end
39
+
40
+ namespace :lit do
41
+ desc "Install Ruby2JS with Lit Rollup support"
42
+ task :rollup do
43
+ template 'install/lit-rollup.rb'
44
+ end
45
+
46
+ desc "Install Ruby2JS with Lit Webpacker support"
47
+ task :webpacker do
48
+ template 'install/lit-webpacker.rb'
49
+ end
50
+ end
37
51
  end
38
52
  end
39
53
 
data/ruby2js.gemspec CHANGED
@@ -12,12 +12,14 @@ Gem::Specification.new do |s|
12
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
- s.files = %w(ruby2js.gemspec README.md) + Dir.glob("{lib}/**/*")
15
+ s.files = %w(ruby2js.gemspec README.md bin/ruby2js demo/ruby2js.rb) + Dir.glob("{lib}/**/*")
16
16
  s.homepage = "http://github.com/rubys/ruby2js".freeze
17
17
  s.licenses = ["MIT".freeze]
18
18
  s.required_ruby_version = Gem::Requirement.new(">= 2.3".freeze)
19
19
  s.summary = "Minimal yet extensible Ruby to JavaScript conversion.".freeze
20
20
 
21
+ s.executables << 'ruby2js'
22
+
21
23
  s.add_dependency('parser')
22
24
  s.add_dependency('regexp_parser', '~> 2.1.1')
23
25
  end