stimulus-rails 0.1.3 → 0.2.3

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: 0ccf391e30e2e3ec0f91bdc894bba78582341c77dc33917dc094863f95767172
4
- data.tar.gz: ac90fc101aabdf0e027bd281e69ab5d709116dc8d7a8200c258198d932534aeb
3
+ metadata.gz: 294b1fb5168db9b241b1a7f5e05d9bbcea2dc384c55ca0b2b1cef1731ec71c1e
4
+ data.tar.gz: 1f29da6aa09938993859dc7c362509d9bc3b2cab1fd7259dda9a1c2fde9eb7ab
5
5
  SHA512:
6
- metadata.gz: 1ff414d0de6993b78d077961f136d7f2cf72a5966a698ad0713698e96a14c40c70d46ca6c95cd575e14a3dfb044e0ac05dd784db268201b17fc067ab923ab5d1
7
- data.tar.gz: 7f8f2e9a41e88ec03fdc936fadacaa109dd10890e6797cdd6d7b2484dc3eb746c31ee9d1fa07265ad5cf3e3ab87b40dd42efcddc87044eaa29ee897344ada441
6
+ metadata.gz: 78242453a57877148c68f4250cc8eb9a29f10e064512aee668c56a2b4f8ab71eb8448ae4a62e30af075f559469166b6da91df143ac46ba06a2e5a1af0facbb5c
7
+ data.tar.gz: 004f62719a205a64f1f76d44501960100583e3af56c8f9c32a1a6f71aca4c23a5b39d3a8d0c898d77761c609032feb81c463ee3766ac633ba04690d96c8e7780
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
- 4. Ensure JavaScript is included in your `app/config/manifest.js` file for compilation.
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,52 @@
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, type } of mutationsList) {
39
+ switch (type) {
40
+ case "attributes": {
41
+ if (attributeName == controllerAttribute && target.getAttribute(controllerAttribute)) {
42
+ extractControllerNamesFrom(target).forEach(loadController)
43
+ }
44
+ }
45
+ case "childList": {
46
+ autoloadControllersWithin(target)
47
+ }
48
+ }
49
+ }
50
+ }).observe(document, { attributeFilter: [controllerAttribute], subtree: true, childList: true })
20
51
 
21
- window.addEventListener("turbo:load", autoload)
52
+ 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,9 @@
1
+ // Load all the controllers within this directory and all subdirectories.
2
+ // Controller files must be named *_controller.js.
3
+
4
+ import { Application } from "stimulus"
5
+ import { definitionsFromContext } from "stimulus/webpack-helpers"
6
+
7
+ const application = Application.start()
8
+ const context = require.context("controllers", true, /_controller\.js$/)
9
+ application.load(definitionsFromContext(context))
@@ -0,0 +1 @@
1
+ import "controllers"
@@ -2,7 +2,7 @@ say "Copying Stimulus JavaScript"
2
2
  directory "#{__dir__}/app/assets/javascripts", "app/assets/javascripts"
3
3
  empty_directory_with_keep_file "app/assets/javascripts/libraries"
4
4
 
5
- say "Add app/javascripts to asset pipeline manifest"
5
+ say "Add app/assets/javascripts to asset pipeline manifest"
6
6
  append_to_file Rails.root.join("app/assets/config/manifest.js").to_s, "//= link_tree ../javascripts\n"
7
7
 
8
8
  APPLICATION_LAYOUT_PATH = Rails.root.join("app/views/layouts/application.html.erb")
@@ -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"
@@ -1,14 +1,15 @@
1
1
  module Stimulus::ImportmapHelper
2
2
  def importmap_list_with_stimulus_from(*paths)
3
- [ %("stimulus": "#{asset_path("stimulus/libraries/stimulus")}"), importmap_list_from(*paths) ].join(",\n")
3
+ [ %("stimulus": "#{asset_path("stimulus/libraries/stimulus")}"), importmap_list_from(*paths) ].reject(&:blank?).join(",\n")
4
4
  end
5
5
 
6
6
  def importmap_list_from(*paths)
7
7
  Array(paths).flat_map do |path|
8
- if (absolute_path = Rails.root.join(path)).exist?
9
- absolute_path.children.collect do |module_filename|
10
- module_name = importmap_module_name_from(module_filename)
11
- module_path = asset_path("#{absolute_path.basename.to_s}/#{module_filename.basename}")
8
+ if (absolute_path = absolute_root_of(path)).exist?
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))
12
13
 
13
14
  %("#{module_name}": "#{module_path}")
14
15
  end
@@ -19,6 +20,14 @@ module Stimulus::ImportmapHelper
19
20
  private
20
21
  # Strip off the extension and any versioning data for an absolute module name.
21
22
  def importmap_module_name_from(filename)
22
- 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?)
28
+ end
29
+
30
+ def absolute_root_of(path)
31
+ (pathname = Pathname.new(path)).absolute? ? pathname : Rails.root.join(path)
23
32
  end
24
33
  end
@@ -1,3 +1,3 @@
1
1
  module Stimulus
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.3"
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,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stimulus-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
8
8
  - Javan Mahkmali
9
9
  - David Heinemeier Hansson
10
- autorequire:
10
+ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-01-15 00:00:00.000000000 Z
13
+ date: 2021-02-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -26,7 +26,7 @@ dependencies:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
28
  version: 6.0.0
29
- description:
29
+ description:
30
30
  email: david@loudthinking.com
31
31
  executables: []
32
32
  extensions: []
@@ -40,12 +40,14 @@ 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
46
+ - lib/install/app/assets/javascripts/controllers/index.js
47
47
  - lib/install/app/assets/javascripts/importmap.json.erb
48
- - lib/install/stimulus.rb
48
+ - lib/install/application.js
49
+ - lib/install/stimulus_with_asset_pipeline.rb
50
+ - lib/install/stimulus_with_webpacker.rb
49
51
  - lib/stimulus-rails.rb
50
52
  - lib/stimulus/engine.rb
51
53
  - lib/stimulus/importmap_helper.rb
@@ -57,7 +59,7 @@ licenses:
57
59
  metadata:
58
60
  homepage_uri: https://stimulus.hotwire.dev
59
61
  source_code_uri: https://github.com/hotwired/stimulus-rails
60
- post_install_message:
62
+ post_install_message:
61
63
  rdoc_options: []
62
64
  require_paths:
63
65
  - lib
@@ -73,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
75
  version: '0'
74
76
  requirements: []
75
77
  rubygems_version: 3.1.2
76
- signing_key:
78
+ signing_key:
77
79
  specification_version: 4
78
80
  summary: A modest JavaScript framework for the HTML you already have.
79
81
  test_files: []
@@ -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()