Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support cross slice assets #1372

Merged
merged 4 commits into from
Feb 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 9 additions & 8 deletions lib/hanami/helpers/assets_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ module AssetsHelper
# name of the algorithm, then a hyphen, then the hash value of the file.
# If more than one algorithm is used, they"ll be separated by a space.
#
# @param source_paths [Array<String>] one or more assets by name or absolute URL
# @param source_paths [Array<String, #url>] one or more assets by name or absolute URL
#
# @return [Hanami::View::HTML::SafeString] the markup
#
Expand Down Expand Up @@ -189,7 +189,7 @@ def javascript_tag(*source_paths, **options)
# name of the algorithm, then a hyphen, then the hashed value of the file.
# If more than one algorithm is used, they"ll be separated by a space.
#
# @param source_paths [Array<String>] one or more assets by name or absolute URL
# @param source_paths [Array<String, #url>] one or more assets by name or absolute URL
#
# @return [Hanami::View::HTML::SafeString] the markup
#
Expand Down Expand Up @@ -282,7 +282,7 @@ def stylesheet_tag(*source_paths, **options)
# If the "CDN mode" is on, the `src` is an absolute URL of the
# application CDN.
#
# @param source [String] asset name or absolute URL
# @param source [String, #url] asset name, absolute URL, or asset object
# @param options [Hash] HTML 5 attributes
#
# @return [Hanami::View::HTML::SafeString] the markup
Expand Down Expand Up @@ -353,7 +353,7 @@ def image_tag(source, options = {})
# If the "CDN mode" is on, the `href` is an absolute URL of the
# application CDN.
#
# @param source [String] asset name
# @param source [String, #url] asset name or asset object
# @param options [Hash] HTML 5 attributes
#
# @return [Hanami::View::HTML::SafeString] the markup
Expand Down Expand Up @@ -424,7 +424,7 @@ def favicon_tag(source = DEFAULT_FAVICON, options = {})
# If the "CDN mode" is on, the `src` is an absolute URL of the
# application CDN.
#
# @param source [String] asset name or absolute URL
# @param source [String, #url] asset name, absolute URL or asset object
# @param options [Hash] HTML 5 attributes
#
# @return [Hanami::View::HTML::SafeString] the markup
Expand Down Expand Up @@ -526,7 +526,7 @@ def video_tag(source = nil, options = {}, &blk)
# If the "CDN mode" is on, the `src` is an absolute URL of the
# application CDN.
#
# @param source [String] asset name or absolute URL
# @param source [String, #url] asset name, absolute URL or asset object
# @param options [Hash] HTML 5 attributes
#
# @return [Hanami::View::HTML::SafeString] the markup
Expand Down Expand Up @@ -626,7 +626,7 @@ def audio_tag(source = nil, options = {}, &blk)
#
# If CDN mode is on, it returns the absolute URL of the asset.
#
# @param source_path [String] the asset name
# @param source_path [String, #url] the asset name or asset object
#
# @return [String] the asset path
#
Expand Down Expand Up @@ -666,6 +666,7 @@ def audio_tag(source = nil, options = {}, &blk)
#
# # "https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
def asset_url(source_path)
return source_path.url if source_path.respond_to?(:url)
return source_path if _absolute_url?(source_path)

_context.assets[source_path].url
Expand All @@ -684,7 +685,7 @@ def _safe_tags(*source_paths, &blk)
# @since 2.1.0
# @api private
def _typed_path(source, ext)
source = "#{source}#{ext}" if _append_extension?(source, ext)
source = "#{source}#{ext}" if source.is_a?(String) && _append_extension?(source, ext)
asset_url(source)
end

Expand Down
130 changes: 130 additions & 0 deletions spec/integration/assets/cross_slice_assets_helpers_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# frozen_string_literal: true

require "rack/test"
require "stringio"

RSpec.describe "Cross-slice assets via helpers", :app_integration do
include Rack::Test::Methods
let(:app) { Hanami.app }
let(:root) { make_tmp_directory }

before do
with_directory(root) do
write "config/app.rb", <<~RUBY
module TestApp
class App < Hanami::App
config.logger.stream = StringIO.new
end
end
RUBY

write "config/slices/admin.rb", <<~RUBY
module Admin
class Slice < Hanami::Slice
# TODO: we should update `import` to make importing from the app nicer
# TODO: this test failed when I tried doing `as: "app"` (string instead of symbol); fix this in dry-system
import keys: ["assets"], from: Hanami.app.container, as: :app
end
end
RUBY

write "config/assets.js", <<~JS
import * as assets from "hanami-assets";
await assets.run();
JS

write "package.json", <<~JSON
{
"type": "module"
}
JSON

write "app/view.rb", <<~RUBY
# auto_register: false

require "hanami/view"

module TestApp
class View < Hanami::View
config.layout = nil
end
end
RUBY

write "app/assets/js/app.ts", <<~TS
import "../css/app.css";

console.log("Hello from index.ts");
TS

write "app/assets/css/app.css", <<~CSS
.btn {
background: #f00;
}
CSS

write "slices/admin/assets/js/app.ts", <<~TS
import "../css/app.css";

console.log("Hello from admin's index.ts");
TS

write "slices/admin/assets/css/app.css", <<~CSS
.btn {
background: #f00;
}
CSS

write "slices/admin/view.rb", <<~RUBY
# auto_register: false

module Admin
class View < TestApp::View
end
end
RUBY

write "slices/admin/views/posts/show.rb", <<~RUBY
module Admin
module Views
module Posts
class Show < Admin::View
end
end
end
end
RUBY

write "slices/admin/views/context.rb", <<~RUBY
# auto_register: false

require "hanami/view"

module Admin
module Views
class Context < Hanami::View::Context
include Deps[app_assets: "app.assets"]
end
end
end
RUBY

write "slices/admin/templates/posts/show.html.erb", <<~ERB
<%= stylesheet_tag(app_assets["app.css"]) %>
<%= javascript_tag(app_assets["app.js"]) %>
ERB

before_prepare if respond_to?(:before_prepare)
require "hanami/prepare"
end
end

specify "assets are available in helpers and in `assets` component" do
compile_assets!

output = Admin::Slice["views.posts.show"].call.to_s

expect(output).to match(%r{<link href="/assets/app-[A-Z0-9]{8}.css" type="text/css" rel="stylesheet">})
expect(output).to match(%r{<script src="/assets/app-[A-Z0-9]{8}.js" type="text/javascript"></script>})
end
end
11 changes: 11 additions & 0 deletions spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,15 @@ def before_prepare
end
end
end

context "given an asset object" do
it "returns the URL for the asset" do
asset = Hanami::Assets::Asset.new(
path: "/foo/bar.js",
base_url: Hanami.app.config.assets.base_url
)

expect(asset_url(asset)).to eq "/foo/bar.js"
end
end
end