stimulus-rails 0.1.4 → 0.2.0

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