opal-rails 2.0.4 → 3.0.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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +39 -4
  3. data/.gitignore +2 -0
  4. data/Appraisals +20 -21
  5. data/CHANGELOG.md +30 -0
  6. data/Gemfile +2 -2
  7. data/PORTING.md +140 -0
  8. data/README.md +150 -87
  9. data/Rakefile +16 -2
  10. data/app/helpers/opal_helper.rb +9 -28
  11. data/bin/sandbox +3 -2
  12. data/bin/sandbox-setup +2 -0
  13. data/gemfiles/{rails_7_0_opal_1_0.gemfile → rails_7_0_opal_1_8.gemfile} +2 -2
  14. data/gemfiles/{rails_7_0_opal_1_3.gemfile → rails_7_0_opal_master.gemfile} +2 -2
  15. data/gemfiles/{rails_6_0_opal_1_0.gemfile → rails_8_0_opal_1_8.gemfile} +3 -3
  16. data/gemfiles/rails_8_0_opal_master.gemfile +10 -0
  17. data/gemfiles/{rails_6_1_opal_1_0.gemfile → rails_8_1_opal_1_8.gemfile} +3 -3
  18. data/gemfiles/rails_8_1_opal_master.gemfile +10 -0
  19. data/lib/generators/opal/assets/assets_generator.rb +11 -1
  20. data/lib/generators/opal/assets/templates/{javascript.js.rb → asset.rb.tt} +3 -6
  21. data/lib/generators/opal/install/install_generator.rb +160 -9
  22. data/lib/generators/opal/install/templates/{application.js.rb → application.rb} +4 -4
  23. data/lib/generators/opal/install/templates/dev.tt +8 -0
  24. data/lib/generators/opal/install/templates/{initializer.rb → initializer.rb.tt} +8 -0
  25. data/lib/opal/rails/builder_runner.rb +126 -0
  26. data/lib/opal/rails/engine.rb +11 -9
  27. data/lib/opal/rails/entrypoints_resolver.rb +81 -0
  28. data/lib/opal/rails/errors.rb +11 -0
  29. data/lib/opal/rails/file_watcher.rb +58 -0
  30. data/lib/opal/rails/haml6_filter.rb +6 -6
  31. data/lib/opal/rails/haml_filter.rb +3 -6
  32. data/lib/opal/rails/legacy_upgrade_warning.rb +95 -0
  33. data/lib/opal/rails/outputs_manifest.rb +82 -0
  34. data/lib/opal/rails/path_setup.rb +28 -0
  35. data/lib/opal/rails/task_hooks.rb +49 -0
  36. data/lib/opal/rails/version.rb +1 -1
  37. data/lib/opal/rails/watch_runner.rb +173 -0
  38. data/lib/opal/rails.rb +7 -0
  39. data/lib/tasks/opal.rake +48 -0
  40. data/opal-rails.gemspec +23 -14
  41. data/spec/end_to_end/full_lifecycle_spec.rb +377 -0
  42. data/spec/helpers/opal_helper_spec.rb +27 -34
  43. data/spec/integration/source_map_spec.rb +6 -8
  44. data/spec/opal/assets_generator_spec.rb +31 -0
  45. data/spec/opal/install_generator_spec.rb +140 -0
  46. data/spec/opal/rails/build_task_spec.rb +116 -0
  47. data/spec/opal/rails/builder_runner_spec.rb +151 -0
  48. data/spec/opal/rails/clobber_task_spec.rb +55 -0
  49. data/spec/opal/rails/entrypoints_resolver_spec.rb +50 -0
  50. data/spec/opal/rails/haml_filter_spec.rb +41 -0
  51. data/spec/opal/rails/legacy_upgrade_warning_spec.rb +94 -0
  52. data/spec/opal/rails/outputs_manifest_spec.rb +44 -0
  53. data/spec/opal/rails/path_setup_spec.rb +71 -0
  54. data/spec/opal/rails/task_hooks_spec.rb +61 -0
  55. data/spec/opal/rails/watch_runner_spec.rb +283 -0
  56. data/spec/opal/rails/watch_task_spec.rb +23 -0
  57. data/spec/spec_helper.rb +16 -7
  58. data/spec/support/browser_support_spec.rb +36 -0
  59. data/spec/support/capybara.rb +61 -0
  60. data/spec/support/reset_assets_cache.rb +9 -1
  61. data/spec/support/test_app.rb +23 -2
  62. data/test_apps/app/application_controller.rb +23 -32
  63. data/test_apps/app/assets/builds/.keep +0 -0
  64. data/test_apps/app/assets/config/manifest.js +3 -1
  65. data/test_apps/app/assets/images/.keep +0 -0
  66. data/test_apps/app/opal/application.rb +5 -0
  67. data/test_apps/app/{assets/javascripts/source_map_example.js.rb → opal/source_map_example.rb} +1 -2
  68. data/test_apps/app/opal/with_assignments.js.rb +8 -0
  69. data/test_apps/rails.rb +19 -5
  70. metadata +196 -50
  71. data/gemfiles/rails_6_0_opal_1_1.gemfile +0 -9
  72. data/gemfiles/rails_6_0_opal_1_3.gemfile +0 -10
  73. data/gemfiles/rails_6_0_opal_1_7.gemfile +0 -10
  74. data/gemfiles/rails_6_1_opal_1_1.gemfile +0 -9
  75. data/gemfiles/rails_6_1_opal_1_3.gemfile +0 -10
  76. data/gemfiles/rails_6_1_opal_1_7.gemfile +0 -10
  77. data/gemfiles/rails_7_0_opal_1_7.gemfile +0 -10
  78. data/lib/opal/rails/haml5_filter.rb +0 -28
  79. data/test_apps/app/assets/javascripts/application.js.rb +0 -7
  80. data/test_apps/app/assets/javascripts/bar.rb +0 -3
  81. data/test_apps/app/assets/javascripts/foo.js.rb +0 -3
data/README.md CHANGED
@@ -8,12 +8,7 @@
8
8
 
9
9
  _Rails bindings for [Opal](http://opalrb.com). ([Changelog](https://github.com/opal/opal-rails/blob/master/CHANGELOG.md))_
10
10
 
11
- ### Looking for Webpack support? 👀
12
-
13
- If you want to integrate Opal via Webpack please refer to [opal-webpack-loader](https://github.com/isomorfeus/opal-webpack-loader#installation) installation instructions.
14
-
15
- ℹ️ Webpack and ES6 modules are not yet officially supported, but we're working on it thanks to the awesome work done in _opal-webpack-loader_.
16
-
11
+ If you are upgrading an existing app, see [`PORTING.md`](PORTING.md) for a focused 2.x -> 3.x migration guide.
17
12
 
18
13
  ## Installation
19
14
 
@@ -23,12 +18,35 @@ In your `Gemfile`
23
18
  gem 'opal-rails'
24
19
  ```
25
20
 
26
- Run `opal:install` Rails generator to add `app/assets/javascript` to your asset-pipeline manifest in `app/assets/config/manifest.js`:
21
+ `opal-rails` is tested against Rails 7.0, 8.0, and 8.1 with Opal 1.8 and Opal master (`2.0dev`) on Ruby 3.2 and 4.0. It requires Opal 1.7.0+ for the builder/watch dependency APIs it uses. Rails 6.x is no longer supported, Rails 7.1/7.2 do not have dedicated appraisal coverage, and Rails 8 requires Ruby 3.2+.
22
+
23
+ Run the `opal:install` Rails generator to create a build-based Opal setup:
27
24
 
28
25
  ```
29
26
  bin/rails g opal:install
30
27
  ```
31
28
 
29
+ The generator now creates:
30
+
31
+ - `app/opal/application.rb` for greenfield apps, or reuses `app/assets/opal` when migrating an older layout
32
+ - `config/initializers/opal.rb` with build-oriented defaults
33
+ - `app/assets/builds/.keep`
34
+ - a `Procfile.dev` entry for `opal: bin/rails opal:watch`
35
+ - a `bin/dev` launcher when the app does not already have one
36
+ - for Sprockets apps, `app/assets/config/manifest.js` links for `app/assets/builds`
37
+ - for Sprockets test environments, `config.assets.debug = true` in `config/environments/test.rb` so rebuilt assets win over stale checked-in digests
38
+
39
+ For already-installed 2.x apps, do not treat `bin/rails g opal:install` as a drop-in migration step. Follow [`PORTING.md`](PORTING.md) instead, and pin `opal-rails` to the `2.0` series until you are ready to port the app deliberately.
40
+
41
+ `bin/dev` is a small Foreman launcher for `Procfile.dev`; the generated script installs the `foreman` gem if it is missing and then starts both Rails and `opal:watch` together.
42
+
43
+ If the generator finds an existing multi-entrypoint Opal source root, it keeps that layout intact, configures `config.opal.entrypoints = :all`, and avoids inserting a default `javascript_include_tag "application"` when no `application.rb` entrypoint exists.
44
+
45
+ If the host app already has a non-Opal `application.js`, the generator keeps `app/opal/application.rb` as the source file but configures the built logical asset name as `opal` so the two pipelines do not collide.
46
+
47
+ It no longer depends on `opal-sprockets` or a Sprockets-specific helper loader at runtime.
48
+ The `opal:assets` generator now writes plain `.rb` files into the active Opal source root instead of generating `app/assets/javascripts/*.js.rb` files.
49
+
32
50
 
33
51
  ### Configuration
34
52
 
@@ -51,6 +69,99 @@ end
51
69
 
52
70
  Check out the full list of the available configuration options at: [lib/opal/config.rb](https://github.com/opal/opal/blob/master/lib/opal/config.rb).
53
71
 
72
+ ### Build-based assets
73
+
74
+ `opal-rails` now also exposes an explicit build task for modern Rails-style asset generation.
75
+
76
+ The host Rails app is still responsible for choosing an asset server such as Propshaft or Sprockets to serve the built files from `app/assets/builds`.
77
+
78
+ Current build-oriented config keys are:
79
+
80
+ ```ruby
81
+ Rails.application.configure do
82
+ config.opal.source_path = Rails.root.join('app/opal')
83
+ config.opal.entrypoints_path = config.opal.source_path
84
+ config.opal.build_path = Rails.root.join('app/assets/builds')
85
+ config.opal.entrypoints = { 'application' => 'application.rb' }
86
+ config.opal.append_paths = []
87
+ config.opal.use_gems = []
88
+ end
89
+ ```
90
+
91
+ For mixed-stack apps that already use another `application.js`, use an explicit logical name for the Opal output instead of colliding with the existing asset:
92
+
93
+ ```ruby
94
+ Rails.application.configure do
95
+ config.opal.source_path = Rails.root.join('app/opal')
96
+ config.opal.entrypoints_path = config.opal.source_path
97
+ config.opal.entrypoints = { 'opal' => 'application.rb' }
98
+ end
99
+ ```
100
+
101
+ With that in place, you can build Opal entrypoints into browser-ready assets with:
102
+
103
+ ```bash
104
+ bin/rails opal:build
105
+ ```
106
+
107
+ `opal-rails` also hooks `opal:build` into `assets:precompile` automatically, and into `test:prepare` / `spec:prepare` when those tasks exist in the host app.
108
+
109
+ And clean only Opal-owned build outputs with:
110
+
111
+ ```bash
112
+ bin/rails opal:clobber
113
+ ```
114
+
115
+ To rebuild entrypoints while you develop, run:
116
+
117
+ ```bash
118
+ bin/rails opal:watch
119
+ ```
120
+
121
+ This writes `*.js` outputs, optional `*.js.map` files, and an Opal-owned manifest into `app/assets/builds`.
122
+
123
+ `opal:clobber` uses that manifest to remove only Opal-tracked outputs, leaving unrelated assets in `app/assets/builds` alone.
124
+
125
+ `opal:watch` uses the `listen` gem, tracks Opal/core and app dependency files, rebuilds affected entrypoints for known file changes, and falls back to a full rebuild when files are added or removed.
126
+
127
+ Any directories listed in `config.opal.append_paths` are also part of that watch scope, so shared templates or support files can trigger rebuilds too.
128
+
129
+ Include the built entrypoint in your layout with the normal Rails helper:
130
+
131
+ ```erb
132
+ <%= javascript_include_tag "application", "data-turbo-track": "reload" %>
133
+ ```
134
+
135
+ Boot code should live in the built Opal entrypoint itself rather than in a helper-side loader shim.
136
+
137
+ If you are migrating an app that already keeps frontend Ruby under `app/assets/opal`, set `config.opal.source_path` and `config.opal.entrypoints_path` to that directory instead. If your asset server would otherwise expose raw files from that directory, exclude it in the host app configuration yourself. For example, Propshaft apps can add `config.assets.excluded_paths << Rails.root.join('app/assets/opal')`. Apps using the default `app/opal` layout do not need this.
138
+
139
+ For the default `app/opal` layout, `opal-rails` also ignores that source root in Rails autoloaders so frontend Opal files are not treated as application constants.
140
+
141
+ If you want one built asset per top-level Opal file, you can opt into bulk entrypoint discovery:
142
+
143
+ ```ruby
144
+ Rails.application.configure do
145
+ config.opal.source_path = Rails.root.join('app/assets/opal')
146
+ config.opal.entrypoints_path = config.opal.source_path
147
+ config.opal.entrypoints = :all
148
+ end
149
+ ```
150
+
151
+ In `:all` mode, `opal-rails` compiles each top-level `*.rb` file in `entrypoints_path` to a same-name asset in `app/assets/builds`, ignores nested support files, and prunes stale Opal-owned outputs when an entrypoint file disappears.
152
+
153
+ The install generator will choose that `:all` configuration automatically for migration-friendly layouts that already have multiple top-level Opal entrypoints.
154
+
155
+ If you want to generate a controller-specific Opal file, use:
156
+
157
+ ```bash
158
+ bin/rails g opal:assets dashboard
159
+ ```
160
+
161
+ This now creates `app/opal/dashboard.rb` by default, or `app/assets/opal/dashboard.rb` for migration-friendly layouts.
162
+
163
+ The bundled test app and integration suite prebuild assets from `app/opal` into `app/assets/builds` instead of relying on `app/assets/javascripts/*.js.rb` request-time compilation.
164
+
54
165
  #### For template assigns
55
166
 
56
167
  You may optionally add configuration for rendering assigns when using the template handler from actions:
@@ -80,7 +191,7 @@ This example assumes Rails 7 and having followed the [Installation](#installatio
80
191
 
81
192
  1- Delete `app/javascript/application.js`
82
193
 
83
- 2- Enable the following lines in the generated `app/assets/javascript/application.js.rb` below `require "opal"`:
194
+ 2- Enable the following lines in the generated `app/opal/application.rb` below `require "opal"`:
84
195
 
85
196
  ```ruby
86
197
  puts "hello world!"
@@ -96,9 +207,11 @@ end
96
207
 
97
208
  5- Clear `app/views/welcomes/index.html.erb` (empty its content)
98
209
 
99
- 6- Run `rails s`
210
+ 6- Run `bin/rails opal:build`
211
+
212
+ 7- Run `rails s`
100
213
 
101
- 7- Visit `http://localhost:3000/welcomes`
214
+ 8- Visit `http://localhost:3000/welcomes`
102
215
 
103
216
  In the browser webpage, you should see:
104
217
 
@@ -106,79 +219,22 @@ In the browser webpage, you should see:
106
219
 
107
220
  Also, you should see `hello world!` in the browser console.
108
221
 
109
- #### Rails 5 example
222
+ #### Migrating older Sprockets-style apps
110
223
 
111
- This example assumes Rails 5.
224
+ Older `opal-rails` apps often used `app/assets/javascripts/application.js.rb`, `manifest.js`, and request-time Sprockets compilation.
112
225
 
113
- 1. Rename `app/assets/javascripts/application.js` to `app/assets/javascripts/application.js.rb`
114
- 2. Replace the Sprockets directives with plain requires
226
+ See [`PORTING.md`](PORTING.md) for the full 2.x -> 3.x checklist.
115
227
 
116
- ```ruby
117
- # Require the opal runtime and core library
118
- require 'opal'
228
+ The build-first migration path is:
119
229
 
120
- # For Rails 5.1 and above, otherwise use 'opal_ujs'
121
- require 'rails_ujs'
230
+ 1. move the Opal entrypoint to `app/opal/application.rb` or keep `app/assets/opal/application.rb` for migration-friendly layouts;
231
+ 2. configure `config.opal.source_path`, `config.opal.entrypoints_path`, and `config.opal.entrypoints` in `config/initializers/opal.rb`;
232
+ 3. build with `bin/rails opal:build` and watch with `bin/rails opal:watch`;
233
+ 4. include the built asset with the normal `javascript_include_tag` helper.
122
234
 
123
- # Require of JS libraries will be forwarded to sprockets as is
124
- require 'turbolinks'
235
+ The documented path no longer relies on Sprockets directives such as `require_tree` or on helper-level Opal loader injection.
125
236
 
126
- # a Ruby equivalent of the require_tree Sprockets directive is available
127
- require_tree '.'
128
-
129
- puts "hello world!"
130
- ```
131
-
132
- #### A more extensive Rails 5 example
133
-
134
- ```ruby
135
- require 'opal'
136
- require 'opal_ujs'
137
- require 'turbolinks'
138
- require_tree '.' # a Ruby equivalent of the require_tree Sprockets directive is available
139
-
140
- # ---- YOUR FANCY RUBY CODE HERE ----
141
- #
142
- # Examples:
143
-
144
- # == Print something in the browser's console
145
- puts "Hello world!"
146
- pp hello: :world
147
- require 'console'
148
- $console.log %w[Hello world!]
149
-
150
- # == Use Native to wrap native JS objects, $$ is preconfigured to wrap `window`
151
- require 'native'
152
- $$.alert "Hello world!"
153
-
154
- # == Do some DOM manipulation with jQuery
155
- require 'opal-jquery'
156
- Document.ready? do
157
- Element.find('body').html = '<h1>Hello world!</h1>'
158
- end
159
-
160
- # == Or access the DOM api directly
161
- $$[:document].addEventListener(:DOMContentLoaded, -> {
162
- $$[:document].querySelector('body')[:innerHTML] = '<h1>Hello world!</h1>'
163
- })
164
-
165
- ```
166
-
167
-
168
- ### Using Sprockets directives and `application.js`
169
-
170
- If you want to use `application.js` (instead of `application.js.rb`) and keep using Sprockets directives, you'll need to load the Opal files you require via Sprockets manually, e.g.:
171
-
172
- ```js
173
- //= require opal
174
- //= require rails_ujs
175
- //= require turbolinks
176
- //= require_tree .
177
- //= require app
178
-
179
- Opal.require('opal');
180
- Opal.require('app');
181
- ```
237
+ If the host app itself still uses Sprockets during migration, it can keep the minimal manifest entries needed to serve the built files, but `opal-rails` itself no longer requires `opal-sprockets` to compile or boot Opal assets.
182
238
 
183
239
 
184
240
  ### As a template
@@ -209,7 +265,7 @@ post.find('.comments').html = comments_html
209
265
 
210
266
  By default `opal-rails`, will NOT forward any instance and local variable you'll pass to the template.
211
267
 
212
- This behavior can be enabled by setting `Rails.application.config.opal.assigns_in_templates` to `true` in `config/initializers/assets.rb`:
268
+ This behavior can be enabled by setting `Rails.application.config.opal.assigns_in_templates` to `true` in `config/initializers/opal.rb`:
213
269
 
214
270
  ```ruby
215
271
  Rails.application.configure do
@@ -223,7 +279,7 @@ end
223
279
 
224
280
  ### As a Haml filter (optional)
225
281
 
226
- Of course you need to require `haml-rails` separately since its presence is not assumed
282
+ Require `haml-rails` separately if you want to use Haml. `opal-rails` supports the optional `:opal` Haml filter on Haml 6 and newer only!
227
283
 
228
284
  ```haml
229
285
  -# app/views/posts/show.html.haml
@@ -267,7 +323,7 @@ _Upcoming as `opal-minitest-rails`_
267
323
 
268
324
  ### Shared templates
269
325
 
270
- As long as the templates are inside the Sprockets/Opal load path, then you should be able to just require them.
326
+ As long as the templates are inside an Opal load path, you should be able to require them.
271
327
 
272
328
  Let's say we have this template `app/views/shared/test.haml`:
273
329
 
@@ -277,17 +333,17 @@ Let's say we have this template `app/views/shared/test.haml`:
277
333
  = @bar
278
334
  ```
279
335
 
280
- We need to make sure Opal can see and compile that template. So we need to add the path to sprockets:
336
+ We need to make sure Opal can see and compile that template. Add the path to `config.opal.append_paths`:
281
337
 
282
338
  ```ruby
283
339
  # config/initializers/opal.rb
284
- Rails.application.config.assets.paths << Rails.root.join('app', 'views', 'shared').to_s
340
+ Rails.application.config.opal.append_paths << Rails.root.join('app', 'views', 'shared')
285
341
  ```
286
342
 
287
343
  Now, somewhere in `application.rb` you need to require that template, and you can just run it through `Template`:
288
344
 
289
345
  ```ruby
290
- # app/assets/javascripts/application.rb
346
+ # app/opal/application.rb
291
347
  require 'opal'
292
348
  require 'opal-haml'
293
349
  require 'test'
@@ -302,14 +358,16 @@ template.render(self)
302
358
 
303
359
  ### Using Ruby gems from Opal
304
360
 
305
- Just use `Opal.use_gem` in your asset initializer (`config/initializers/assets.rb`).
361
+ Add gems to the Opal load path from `config/initializers/opal.rb`.
306
362
 
307
363
  Example:
308
364
 
309
365
  ```ruby
310
- Opal.use_gem 'cannonbol'
366
+ Rails.application.config.opal.use_gems << 'cannonbol'
311
367
  ```
312
368
 
369
+ Both `opal:build` and `opal:watch` apply `config.opal.use_gems` and `config.opal.append_paths` when creating builders, so the same load-path behavior is used in direct builds, watch-mode rebuilds, and precompile hooks.
370
+
313
371
 
314
372
  ## Contributing
315
373
 
@@ -320,6 +378,10 @@ bin/setup
320
378
  bin/rake
321
379
  ```
322
380
 
381
+ `bin/rake` now runs the non-JS and browser-driven specs in separate RSpec phases so each browser pass starts from a fresh process.
382
+
383
+ Browser-driven specs auto-detect a usable local Chrome/Chromium binary, including Fedora's headless Chromium shell path when it is installed but not on `PATH`, and only skip when no supported browser binary can be found.
384
+
323
385
  Inspect the test app:
324
386
 
325
387
  ```
@@ -330,8 +392,9 @@ bin/rackup
330
392
  Tinker with a sandbox app:
331
393
 
332
394
  ```
333
- bin/sandbox # will re-create the app
334
- bin/rails s # will start the sandbox app server
395
+ bin/sandbox # re-creates the app, installs opal-rails, and runs an initial opal:build
396
+ bin/rails s # starts the sandbox app server
397
+ # or run bin/rails opal:watch in another shell while you edit Opal source files
335
398
  # visit localhost:3000
336
399
  ```
337
400
 
data/Rakefile CHANGED
@@ -10,6 +10,20 @@ Bundler::GemHelper.install_tasks
10
10
  # TEST
11
11
 
12
12
  require 'rspec/core/rake_task'
13
- RSpec::Core::RakeTask.new :rspec
14
13
 
15
- task :default => :rspec
14
+ RSpec::Core::RakeTask.new('spec:non_js') do |task|
15
+ task.rspec_opts = '--tag ~js --tag ~e2e'
16
+ end
17
+
18
+ RSpec::Core::RakeTask.new('spec:js') do |task|
19
+ task.rspec_opts = '--tag js'
20
+ end
21
+
22
+ RSpec::Core::RakeTask.new('spec:e2e') do |task|
23
+ task.rspec_opts = '--tag e2e'
24
+ end
25
+
26
+ task spec: ['spec:non_js', 'spec:js']
27
+ task rspec: :spec
28
+
29
+ task default: :spec
@@ -1,34 +1,15 @@
1
- require 'opal/sprockets'
2
-
3
1
  module OpalHelper
4
- def opal_tag(opal_code = nil, &block)
5
- opal_code ||= capture(&block)
2
+ def opal_tag(opal_code_or_options = nil, html_options = {}, &block)
3
+ if block_given?
4
+ html_options = opal_code_or_options if opal_code_or_options.is_a?(Hash)
5
+ opal_code_or_options = capture(&block)
6
+ end
7
+
6
8
  compiler_options = Opal::Config.compiler_options.merge(requirable: false)
7
- compiler = Opal::Compiler.new(opal_code, compiler_options)
9
+ compiler = Opal::Compiler.new(opal_code_or_options, compiler_options)
8
10
  js_code = compiler.compile
9
- javascript_tag js_code
10
- end
11
-
12
- def javascript_include_tag(*sources)
13
- options = sources.extract_options!.symbolize_keys
14
- debug = options[:debug] != false
15
- skip_loader = options.delete(:skip_opal_loader)
16
- force_opal_loader_tag = options.delete(:force_opal_loader_tag) || debug
17
-
18
- return super(*sources, options) if skip_loader && !force_opal_loader_tag
19
-
20
- script_tags = "".html_safe
21
- sources.each do |source|
22
- load_asset_code = Opal::Sprockets.load_asset(source)
23
- loading_code = "if(window.Opal && Opal.modules[#{source.to_json}]){#{load_asset_code}}"
24
-
25
- if force_opal_loader_tag
26
- script_tags << super(source, options)
27
- script_tags << "\n".html_safe + javascript_tag(loading_code)
28
- else
29
- script_tags << super(source, options.merge(onload: loading_code))
30
- end
11
+ javascript_tag html_options do
12
+ js_code.html_safe
31
13
  end
32
- script_tags
33
14
  end
34
15
  end
data/bin/sandbox CHANGED
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
+ set -euo pipefail
4
+ IFS=$'\n\t'
5
+
3
6
  gem_name="$(ruby -rpathname -e"puts Pathname(ARGV.first).join('../..').expand_path.glob('*.gemspec').first.basename('.gemspec')" -- $0)"
4
7
 
5
8
  # Stay away from the bundler env of the containing extension.
@@ -28,7 +31,6 @@ gem '$gem_name', path: '..'
28
31
  RUBY
29
32
 
30
33
  unbundled bundle install --gemfile Gemfile
31
- unbundled bin/rails webpacker:install
32
34
 
33
35
 
34
36
  cd .. # Back to the project root.
@@ -36,4 +38,3 @@ bin/sandbox-setup # Run any custom setup.
36
38
 
37
39
  echo
38
40
  echo "🚀 Sandbox app successfully created for $gem_name!"
39
-
data/bin/sandbox-setup CHANGED
@@ -12,3 +12,5 @@ root.join('config/routes.rb').write <<~RUBY
12
12
  root to: "home#index"
13
13
  end
14
14
  RUBY
15
+
16
+ system 'bin/rails opal:build'
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "net-smtp"
6
6
  gem "rails", "~> 7.0.0"
7
- gem "opal", "~> 1.0.0"
8
- gem "opal-sprockets"
7
+ gem "sqlite3", "~> 1.4"
8
+ gem "opal", "~> 1.8.0"
9
9
 
10
10
  gemspec path: "../"
@@ -4,7 +4,7 @@ source "https://rubygems.org"
4
4
 
5
5
  gem "net-smtp"
6
6
  gem "rails", "~> 7.0.0"
7
- gem "opal", "~> 1.3.0"
8
- gem "opal-sprockets"
7
+ gem "sqlite3", "~> 1.4"
8
+ gem "opal", git: "https://github.com/opal/opal.git", branch: :master
9
9
 
10
10
  gemspec path: "../"
@@ -3,8 +3,8 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "net-smtp"
6
- gem "rails", "~> 6.0.0"
7
- gem "opal", "~> 1.0.0"
8
- gem "opal-sprockets"
6
+ gem "rails", "~> 8.0.0"
7
+ gem "sqlite3", ">= 2.1"
8
+ gem "opal", "~> 1.8.0"
9
9
 
10
10
  gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "net-smtp"
6
+ gem "rails", "~> 8.0.0"
7
+ gem "sqlite3", ">= 2.1"
8
+ gem "opal", git: "https://github.com/opal/opal.git", branch: :master
9
+
10
+ gemspec path: "../"
@@ -3,8 +3,8 @@
3
3
  source "https://rubygems.org"
4
4
 
5
5
  gem "net-smtp"
6
- gem "rails", "~> 6.1.0"
7
- gem "opal", "~> 1.0.0"
8
- gem "opal-sprockets"
6
+ gem "rails", "~> 8.1.0"
7
+ gem "sqlite3", ">= 2.1"
8
+ gem "opal", "~> 1.8.0"
9
9
 
10
10
  gemspec path: "../"
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "net-smtp"
6
+ gem "rails", "~> 8.1.0"
7
+ gem "sqlite3", ">= 2.1"
8
+ gem "opal", git: "https://github.com/opal/opal.git", branch: :master
9
+
10
+ gemspec path: "../"
@@ -2,6 +2,16 @@ class Opal::AssetsGenerator < ::Rails::Generators::NamedBase
2
2
  source_root File.expand_path('templates', __dir__)
3
3
 
4
4
  def copy_opal
5
- template 'javascript.js.rb', File.join('app/assets/javascripts', class_path, "#{file_name}.js.rb")
5
+ template 'asset.rb.tt', File.join(opal_source_path, class_path, "#{file_name}.rb")
6
+ end
7
+
8
+ private
9
+
10
+ def opal_source_path
11
+ destination_directory_exist?('app/assets/opal') ? 'app/assets/opal' : 'app/opal'
12
+ end
13
+
14
+ def destination_directory_exist?(relative_path)
15
+ File.directory?(File.join(destination_root, relative_path))
6
16
  end
7
17
  end
@@ -1,7 +1,5 @@
1
- # Place all the behaviors and hooks related to the matching controller here.
2
- # All this logic will automatically be available in application.js.
3
- # You can use Opal in this file: http://opalrb.com/
4
- #
1
+ # Place controller-specific Opal code here.
2
+ # Require this file from `app/opal/application.rb` or another configured entrypoint.
5
3
  #
6
4
  # Here's an example view class for your controller:
7
5
  #
@@ -25,7 +23,6 @@ class <%= class_name %>View
25
23
  puts "Hello! (You just clicked on a link: #{event.current_target.text})"
26
24
  end
27
25
 
28
-
29
26
  private
30
27
 
31
28
  attr_reader :selector, :element
@@ -37,7 +34,7 @@ class <%= class_name %>View
37
34
  # Element.find("#{@selector} #{selector}")
38
35
  # end
39
36
 
40
- # Register events on document to save memory and be friends to Turbolinks
37
+ # Register events on document so page-level handlers stay centralized.
41
38
  def on(event, selector = nil, &block)
42
39
  Element[`document`].on(event, selector, &block)
43
40
  end