stimulus-rails 0.1.4 → 0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 723e63c957d1d8a4ab833a4edb197f2379d4604ee68b7587e8bb85560f568ecb
4
- data.tar.gz: efe60efa445d404fdf3faf067223eb6ff187d4d41665cc7c78129b54abb94632
3
+ metadata.gz: 4ea2a08da4eec91fdf57c9aedd06922f70d7d3a5393e02a5ae53ec56e0412e84
4
+ data.tar.gz: ec8badcb14e076a0a85a27a6b7dd8fa704de2ac767e38ab2f7b23c63c9a5c777
5
5
  SHA512:
6
- metadata.gz: f8ea0462b55efd12f2cee6c70fd08a4efeafbb2840deb91fcfb3e2dba7fd7e2c014ec0f1a5b0c5f9906aa997a26fa7db1cb21620412d86faab0b7078226399c7
7
- data.tar.gz: 51300cbb38d24cbd24acc9a835e97bd744702325e18396af174e2c3601597319574860e0c318373c632951e9e81f605c0cecd18d0fb63ded358fbb9d538cd0ee
6
+ metadata.gz: 67387237ccb78c6a38702f83ba544aad12b2b3b95aa89895c945ba6bcada75894e302c11871528bf3f120be2a9717d69c16c221fc21cd4007c1bca32182279fb
7
+ data.tar.gz: bd46dcadb94da2b2a1228c0817a0b590ff0ec9eaaf2fd68c669609e522d7d2e7f0a86b5cf5b29a383e1d119b02880d1b48075e355fcee4a2b40c5133bff8cf80
data/README.md CHANGED
@@ -12,13 +12,19 @@ If you want to use Stimulus with a bundler, you should use [Webpacker](https://g
12
12
  2. Run `./bin/bundle install`.
13
13
  3. Run `./bin/rails stimulus:install`
14
14
 
15
- The last command will:
15
+ If using the asset pipeline to manage JavaScript, the last command will:
16
16
 
17
- 1. Create an example controller in `app/assets/javascripts/controllers/hello_controller.js`
17
+ 1. Create an example controller in `app/assets/javascripts/controllers/hello_controller.js`.
18
18
  2. Append the include tags to the `<head>` of your `app/views/layouts/application.html.erb`.
19
19
  3. Initialize your `importmap.json` in `app/assets/javascripts/importmap.json.erb`.
20
20
  4. Ensure JavaScript is included in your `app/assets/config/manifest.js` file for compilation.
21
21
 
22
+ If using Webpacker to manage JavaScript, the last command will:
23
+
24
+ 1. Import the controllers directory in the application pack.
25
+ 2. Create a controllers directory at `app/javascripts/controllers`.
26
+ 3. Create an example controller in `app/javascripts/controllers/hello_controller.js`.
27
+ 4. Install the Stimulus NPM package.
22
28
 
23
29
  ## Usage
24
30
 
@@ -1,21 +1,45 @@
1
1
  import { Application } from "stimulus"
2
2
 
3
3
  const application = Application.start()
4
+ const { controllerAttribute } = application.schema
5
+ const registeredControllers = {}
4
6
 
5
- function autoload() {
6
- Array.from(document.querySelectorAll('[data-controller]')).forEach((element) => {
7
- const controllerNames = element.attributes["data-controller"].value.split(" ")
7
+ function autoloadControllersWithin(element) {
8
+ queryControllerNamesWithin(element).forEach(loadController)
9
+ }
10
+
11
+ function queryControllerNamesWithin(element) {
12
+ return Array.from(element.querySelectorAll(`[${controllerAttribute}]`)).map(extractControllerNamesFrom).flat()
13
+ }
14
+
15
+ function extractControllerNamesFrom(element) {
16
+ return element.getAttribute(controllerAttribute).split(/\s+/).filter(content => content.length)
17
+ }
8
18
 
9
- controllerNames.forEach((controllerName) => {
10
- let controllerFilename = `${controllerName}_controller`
19
+ function loadController(name) {
20
+ import(controllerFilename(name))
21
+ .then(module => registerController(name, module))
22
+ .catch(error => console.log(`Failed to autoload controller: ${name}`, error))
23
+ }
11
24
 
12
- import(controllerFilename).then((controllerModule) => {
13
- application.register(controllerName, controllerModule.default)
14
- }).catch(error => console.log(`Failed to autoload controller: ${controllerName}`))
15
- })
16
- })
25
+ function controllerFilename(name) {
26
+ return `${name.replace(/--/g, "/").replace(/-/g, "_")}_controller`
17
27
  }
18
28
 
19
- autoload()
29
+ function registerController(name, module) {
30
+ if (name in registeredControllers) return
31
+
32
+ application.register(name, module.default)
33
+ registeredControllers[name] = true
34
+ }
35
+
36
+
37
+ new MutationObserver((mutationsList) => {
38
+ for (const { attributeName, target } of mutationsList) {
39
+ if (attributeName == controllerAttribute && target.hasAttribute(controllerAttribute)) {
40
+ autoloadControllersWithin(target)
41
+ }
42
+ }
43
+ }).observe(document.body, { attributeFilter: [controllerAttribute], subtree: true, childList: true })
20
44
 
21
- window.addEventListener("turbo:load", autoload)
45
+ autoloadControllersWithin(document)
@@ -1,10 +1,10 @@
1
1
  module Stimulus::StimulusHelper
2
2
  def stimulus_include_tags
3
- [
3
+ safe_join [
4
4
  javascript_include_tag("stimulus/libraries/es-module-shims", type: "module"),
5
5
  tag.script(type: "importmap-shim", src: asset_path("importmap.json")),
6
6
  javascript_include_tag("stimulus/libraries/stimulus", type: "module-shim"),
7
7
  javascript_include_tag("stimulus/loaders/autoloader", type: "module-shim")
8
- ].join("\n").html_safe
8
+ ], "\n"
9
9
  end
10
10
  end
@@ -0,0 +1 @@
1
+ import "controllers"
@@ -0,0 +1,10 @@
1
+ say "Appending Stimulus setup code to #{Webpacker.config.source_entry_path}/application.js"
2
+ append_to_file "#{Webpacker.config.source_entry_path}/application.js" do
3
+ "\n" + open("#{__dir__}/application.js").read
4
+ end
5
+
6
+ say "Creating controllers directory"
7
+ directory "#{__dir__}/app/assets/javascripts/controllers", "#{Webpacker.config.source_path}/controllers"
8
+
9
+ say "Installing all Stimulus dependencies"
10
+ run "yarn add stimulus"
@@ -6,11 +6,10 @@ module Stimulus::ImportmapHelper
6
6
  def importmap_list_from(*paths)
7
7
  Array(paths).flat_map do |path|
8
8
  if (absolute_path = Rails.root.join(path)).exist?
9
- absolute_path.children.collect do |module_filename|
10
- next unless module_filename.extname =~ /js(m)?$/
11
-
12
- module_name = importmap_module_name_from(module_filename)
13
- module_path = asset_path("#{absolute_path.basename.to_s}/#{module_filename.basename}")
9
+ find_javascript_files_in_tree(absolute_path).collect do |filename|
10
+ module_filename = filename.relative_path_from(absolute_path)
11
+ module_name = importmap_module_name_from(module_filename)
12
+ module_path = asset_path(absolute_path.basename.join(module_filename))
14
13
 
15
14
  %("#{module_name}": "#{module_path}")
16
15
  end
@@ -21,6 +20,10 @@ module Stimulus::ImportmapHelper
21
20
  private
22
21
  # Strip off the extension and any versioning data for an absolute module name.
23
22
  def importmap_module_name_from(filename)
24
- filename.basename.to_s.remove(filename.extname).split("@").first
23
+ filename.to_s.remove(filename.extname).split("@").first
24
+ end
25
+
26
+ def find_javascript_files_in_tree(path)
27
+ Dir[path.join("**/*.js{,m}")].collect { |file| Pathname.new(file) }.select(&:file?)
25
28
  end
26
29
  end
@@ -1,3 +1,3 @@
1
1
  module Stimulus
2
- VERSION = "0.1.4"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -1,6 +1,24 @@
1
+ def run_stimulus_install_template(path) system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}" end
2
+
1
3
  namespace :stimulus do
2
4
  desc "Install Stimulus into the app"
3
5
  task :install do
4
- system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/stimulus.rb", __dir__)}"
6
+ if defined?(Webpacker::Engine)
7
+ Rake::Task["stimulus:install:webpacker"].invoke
8
+ else
9
+ Rake::Task["stimulus:install:asset_pipeline"].invoke
10
+ end
11
+ end
12
+
13
+ namespace :install do
14
+ desc "Install Stimulus on the app with the asset pipeline"
15
+ task :asset_pipeline do
16
+ run_stimulus_install_template "stimulus_with_asset_pipeline"
17
+ end
18
+
19
+ desc "Install Stimulus on the app with webpacker"
20
+ task :webpacker do
21
+ run_stimulus_install_template "stimulus_with_webpacker"
22
+ end
5
23
  end
6
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-01-15 00:00:00.000000000 Z
13
+ date: 2021-01-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -40,12 +40,13 @@ files:
40
40
  - app/assets/javascripts/stimulus/libraries/stimulus.js
41
41
  - app/assets/javascripts/stimulus/libraries/stimulus@2.js
42
42
  - app/assets/javascripts/stimulus/loaders/autoloader.js
43
- - app/assets/javascripts/stimulus/loaders/preloader.js.erb
44
43
  - app/assets/javascripts/stimulus/manifest.js
45
44
  - app/helpers/stimulus/stimulus_helper.rb
46
45
  - lib/install/app/assets/javascripts/controllers/hello_controller.js
47
46
  - lib/install/app/assets/javascripts/importmap.json.erb
48
- - lib/install/stimulus.rb
47
+ - lib/install/application.js
48
+ - lib/install/stimulus_with_asset_pipeline.rb
49
+ - lib/install/stimulus_with_webpacker.rb
49
50
  - lib/stimulus-rails.rb
50
51
  - lib/stimulus/engine.rb
51
52
  - lib/stimulus/importmap_helper.rb
@@ -1,20 +0,0 @@
1
- // Experimental: Not currently exposed.
2
- import { Application } from "stimulus"
3
-
4
- const application = Application.start()
5
-
6
- async function preloadControllers() {
7
- const imports = await fetch("<%= asset_path "importmap.json" %>").then(r => r.json()).then(json => json.imports)
8
-
9
- for (const name in imports) {
10
- if (name.startsWith("controllers/")) {
11
- let controllerName = name.replace(/controllers\//, "").replace("_controller", "")
12
-
13
- import(imports[name]).then((module) => {
14
- application.register(controllerName, module.default)
15
- }).catch(error => console.log(error))
16
- }
17
- }
18
- }
19
-
20
- preloadControllers()