From 4e6f189c83bbc5a821451f44ebc11fbff57fc0ad Mon Sep 17 00:00:00 2001 From: Thomas von Deyen Date: Wed, 22 May 2024 19:33:17 +0200 Subject: [PATCH] Allow to add to Alchemy's importmap from Rails application Rails applications are technically engines, but not really. For example the `engine_name` is the `config/application.rb` modularized class name. Which makes it not nice for this interface from an app developers perspective. Let's make the interface more explicit by using a options hash with readable keys. Rails.application.config.before_initialize do Alchemy.admin_importmaps.add({ importmap_path: Rails.application.root.join("config/alchemy/importmap.rb"), source_paths: [ Rails.application.root.join("app/javascript/components/product_select.js") ], name: "product_select" }) end --- app/views/layouts/alchemy/admin.html.erb | 6 ++-- config/{alchemy => }/importmap.rb | 2 +- lib/alchemy.rb | 23 ++++++++++---- lib/alchemy/engine.rb | 14 ++++----- spec/libraries/alchemy_spec.rb | 38 ++++++++++++++++++++++++ 5 files changed, 65 insertions(+), 18 deletions(-) rename config/{alchemy => }/importmap.rb (84%) create mode 100644 spec/libraries/alchemy_spec.rb diff --git a/app/views/layouts/alchemy/admin.html.erb b/app/views/layouts/alchemy/admin.html.erb index 5c724600b4..5cb2ab7fbc 100644 --- a/app/views/layouts/alchemy/admin.html.erb +++ b/app/views/layouts/alchemy/admin.html.erb @@ -21,11 +21,9 @@ <%= render 'alchemy/admin/partials/routes' %> <%= javascript_include_tag('alchemy/admin/all', 'data-turbo-track' => true) %> <%= javascript_importmap_tags("alchemy_admin", importmap: Alchemy.importmap) %> - <% if Alchemy.admin_js_imports.any? %> + <% Alchemy.admin_js_imports.each do |path| %> <% end %> <%= yield :javascript_includes %> diff --git a/config/alchemy/importmap.rb b/config/importmap.rb similarity index 84% rename from config/alchemy/importmap.rb rename to config/importmap.rb index e74429a2f8..545eae6504 100644 --- a/config/alchemy/importmap.rb +++ b/config/importmap.rb @@ -9,4 +9,4 @@ pin "tinymce", to: "tinymce.min.js", preload: true pin "alchemy_admin", to: "alchemy_admin.js", preload: true -pin_all_from File.expand_path("../../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin", preload: true +pin_all_from File.expand_path("../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin", preload: true diff --git a/lib/alchemy.rb b/lib/alchemy.rb index 47a87845fc..58176d01fa 100644 --- a/lib/alchemy.rb +++ b/lib/alchemy.rb @@ -62,7 +62,7 @@ def self.admin_js_imports=(sources) @_admin_js_imports = Set[sources] end - # Additional importmaps from engines to be included in the Alchemy admin UI + # Additional importmaps to be included in the Alchemy admin UI # # Be sure to also pin modules with +Alchemy.importmap+. # @@ -76,13 +76,26 @@ def self.admin_js_imports=(sources) # # # lib/alchemy/solidus/engine.rb # initializer "alchemy_solidus.assets", before: "alchemy.importmap" do |app| - # Alchemy.engine_importmaps.add(Engine) + # Alchemy.admin_importmaps.add({ + # importmap_path: root.join("config/importmap.rb"), + # source_paths: [ + # root.join("app/javascript") + # ], + # name: "alchemy_solidus" + # }) # app.config.assets.precompile << "alchemy_solidus/manifest.js" # end # - # @return [Set] - def self.engine_importmaps - @_engine_importmaps ||= Set.new([Alchemy::Engine]) + # @return [Set] + def self.admin_importmaps + @_admin_importmaps ||= Set.new([{ + importmap_path: Engine.root.join("config/importmap.rb"), + source_paths: [ + Engine.root.join("app/javascript"), + Engine.root.join("vendor/javascript") + ], + name: "alchemy_admin" + }]) end # Define page publish targets diff --git a/lib/alchemy/engine.rb b/lib/alchemy/engine.rb index 14c04903f9..afb256c625 100644 --- a/lib/alchemy/engine.rb +++ b/lib/alchemy/engine.rb @@ -23,14 +23,12 @@ class Engine < Rails::Engine initializer "alchemy.importmap" do |app| watch_paths = [] - Alchemy.engine_importmaps.each do |engine| - Alchemy.importmap.draw engine.root.join("config/alchemy", "importmap.rb") - package_path = engine.root.join("app/javascript") - watch_paths << package_path - vendor_packages_path = engine.root.join("vendor/javascript") - app.config.assets.paths += [package_path, vendor_packages_path] - if engine.engine_name != "alchemy" - Alchemy.admin_js_imports.add(engine.engine_name) + Alchemy.admin_importmaps.each do |admin_import| + Alchemy.importmap.draw admin_import[:importmap_path] + watch_paths += admin_import[:source_paths] + app.config.assets.paths += admin_import[:source_paths] + if admin_import[:name] != "alchemy_admin" + Alchemy.admin_js_imports.add(admin_import[:name]) end end diff --git a/spec/libraries/alchemy_spec.rb b/spec/libraries/alchemy_spec.rb new file mode 100644 index 0000000000..ff3d2f6abb --- /dev/null +++ b/spec/libraries/alchemy_spec.rb @@ -0,0 +1,38 @@ +require "rails_helper" + +RSpec.describe Alchemy do + describe ".admin_importmaps" do + subject { Alchemy.admin_importmaps } + + it "returns a Set of admin importmaps" do + is_expected.to be_a(Set) + end + + it "includes alchemy_admin importmap" do + expect(subject.first).to eq({ + importmap_path: Alchemy::Engine.root.join("config/importmap.rb"), + name: "alchemy_admin", + source_paths: [ + Alchemy::Engine.root.join("app/javascript"), + Alchemy::Engine.root.join("vendor/javascript") + ] + }) + end + + context "with additional importmaps" do + before do + Alchemy.admin_importmaps.add({ + importmap_path: Rails.root.join("config/importmap.rb"), + name: "additional_importmap", + source_paths: [Rails.root.join("app/javascript")] + }) + end + + it "adds additional importmap to admin imports" do + initializer = Alchemy::Engine.initializers.find { _1.name == "alchemy.importmap" } + expect(Alchemy.admin_js_imports).to receive(:add).with("additional_importmap") + initializer.run(Rails.application) + end + end + end +end