From 0a0e5c85a9921deb2a29cd33e1f2932ba79ba483 Mon Sep 17 00:00:00 2001 From: Bruno Prieto Date: Wed, 15 May 2024 22:25:30 -0400 Subject: [PATCH] Add an option to only pick assets from app/assets/stylesheets using stylesheet_link_tag :app --- lib/propshaft/helper.rb | 38 ++++++++++++++----- lib/propshaft/load_path.rb | 5 +++ test/dummy/app/helpers/application_helper.rb | 5 +++ .../app/views/layouts/application.html.erb | 2 +- test/dummy/config/application.rb | 1 + test/dummy/vendor/stylesheets/library.css | 0 test/propshaft_integration_test.rb | 10 +++++ 7 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 test/dummy/app/helpers/application_helper.rb create mode 100644 test/dummy/vendor/stylesheets/library.css diff --git a/lib/propshaft/helper.rb b/lib/propshaft/helper.rb index 66e8d25..f014079 100644 --- a/lib/propshaft/helper.rb +++ b/lib/propshaft/helper.rb @@ -4,22 +4,40 @@ def compute_asset_path(path, options = {}) Rails.application.assets.resolver.resolve(path) || raise(MissingAssetError.new(path)) end - # Add an option to call `stylesheet_link_tag` with `:all` to include every css file found on the load path. + # Add an option to call `stylesheet_link_tag` with + # `:all` to include every css file found on the load path or + # `:app` to include every css file found on `app/assets/stylesheets`. def stylesheet_link_tag(*sources, **options) - if sources.first == :all + case sources.first + when :all super(*all_stylesheets_paths, **options) + when :app + super(*app_stylesheets_paths, **options) else super end end - # Returns a sorted and unique array of logical paths for all stylesheets in the load path. - def all_stylesheets_paths - Rails.application.assets.load_path - .assets(content_types: [ Mime::EXTENSION_LOOKUP["css"] ]) - .collect { |css| css.logical_path.to_s } - .sort - .uniq - end + private + def all_stylesheets_paths + stylesheets_paths_for(Rails.application.assets.load_path) + end + + def app_stylesheets_paths + stylesheets_paths_for( + Rails.application.assets.load_path.dup.tap do |load_path| + load_path.paths = [ File.join(Rails.root, "app", "assets", "stylesheets") ] + end + ) + end + + # Returns a sorted and unique array of logical paths for a stylesheets load path. + def stylesheets_paths_for(load_path) + load_path + .assets(content_types: [ Mime::EXTENSION_LOOKUP["css"] ]) + .collect { |css| css.logical_path.to_s } + .sort + .uniq + end end end diff --git a/lib/propshaft/load_path.rb b/lib/propshaft/load_path.rb index 6abdbe2..b2813a9 100644 --- a/lib/propshaft/load_path.rb +++ b/lib/propshaft/load_path.rb @@ -7,6 +7,11 @@ def initialize(paths = [], compilers:, version: nil) @paths, @compilers, @version = dedup(paths), compilers, version end + def paths=(paths) + @paths = dedup(paths) + clear_cache + end + def find(asset_name) assets_by_path[asset_name] end diff --git a/test/dummy/app/helpers/application_helper.rb b/test/dummy/app/helpers/application_helper.rb new file mode 100644 index 0000000..9c42136 --- /dev/null +++ b/test/dummy/app/helpers/application_helper.rb @@ -0,0 +1,5 @@ +module ApplicationHelper + def app_stylesheets? + params[:stylesheets] == "app" + end +end diff --git a/test/dummy/app/views/layouts/application.html.erb b/test/dummy/app/views/layouts/application.html.erb index c412d08..d2ed29a 100644 --- a/test/dummy/app/views/layouts/application.html.erb +++ b/test/dummy/app/views/layouts/application.html.erb @@ -5,7 +5,7 @@ <%= csrf_meta_tags %> <%= csp_meta_tag %> - <%= stylesheet_link_tag :all, data: { custom_attribute: true } %> + <%= stylesheet_link_tag(app_stylesheets? ? :app : :all, data: { custom_attribute: true }) %> diff --git a/test/dummy/config/application.rb b/test/dummy/config/application.rb index fb160a1..9a01256 100644 --- a/test/dummy/config/application.rb +++ b/test/dummy/config/application.rb @@ -31,5 +31,6 @@ class Application < Rails::Application # # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") + config.assets.paths << File.join(Rails.root, "vendor", "stylesheets") end end diff --git a/test/dummy/vendor/stylesheets/library.css b/test/dummy/vendor/stylesheets/library.css new file mode 100644 index 0000000..e69de29 diff --git a/test/propshaft_integration_test.rb b/test/propshaft_integration_test.rb index 554303d..e605576 100644 --- a/test/propshaft_integration_test.rb +++ b/test/propshaft_integration_test.rb @@ -8,10 +8,20 @@ class PropshaftIntegrationTest < ActionDispatch::IntegrationTest assert_select 'link[href="/assets/hello_world-4137140a.css"][data-custom-attribute="true"]' assert_select 'link[href="/assets/goodbye-b1dc9940.css"][data-custom-attribute="true"]' + assert_select 'link[href="/assets/library-356a192b.css"][data-custom-attribute="true"]' assert_select 'script[src="/assets/hello_world-888761f8.js"]' end + test "using stylesheet_link_tag :app option should only resolve assets contained in app/assets/stylesheets" do + get sample_load_real_assets_url(stylesheets: :app) + + assert_response :success + assert_select 'link[href="/assets/hello_world-4137140a.css"][data-custom-attribute="true"]' + assert_select 'link[href="/assets/goodbye-b1dc9940.css"][data-custom-attribute="true"]' + assert_select 'link[href="/assets/library-356a192b.css"][data-custom-attribute="true"]', 0 + end + test "should raise an exception when resolving nonexistent assets" do exception = assert_raises ActionView::Template::Error do get sample_load_nonexistent_assets_url