ruby2js 4.1.4 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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