Class: Hanami::Assets

Inherits:
Object
  • Object
show all
Defined in:
lib/hanami/sprockets.rb,
lib/hanami/sprockets/cli.rb,
lib/hanami/sprockets/asset.rb,
lib/hanami/sprockets/config.rb,
lib/hanami/sprockets/errors.rb,
lib/hanami/sprockets/helpers.rb,
lib/hanami/sprockets/version.rb,
lib/hanami/sprockets/base_url.rb,
lib/hanami/sprockets/middleware.rb

Overview

Assets management for Ruby web applications using Sprockets

Since:

  • 0.1.0

Defined Under Namespace

Modules: Helpers Classes: Asset, AssetMissingError, BaseUrl, CLI, Config, Error, ManifestMissingError, Middleware

Constant Summary collapse

VERSION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0

"0.2.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:, root:) ⇒ Assets

Returns a new instance of Assets.

Since:

  • 0.1.0



71
72
73
74
75
# File 'lib/hanami/sprockets.rb', line 71

def initialize(config:, root:)
  @config = config
  @root = Pathname(root)
  @environment = setup_sprockets_environment
end

Instance Attribute Details

#configObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0



59
60
61
# File 'lib/hanami/sprockets.rb', line 59

def config
  @config
end

#environmentObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0



67
68
69
# File 'lib/hanami/sprockets.rb', line 67

def environment
  @environment
end

#rootObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0



63
64
65
# File 'lib/hanami/sprockets.rb', line 63

def root
  @root
end

Class Method Details

.gem_loaderObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Since:

  • 0.1.0



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/hanami/sprockets.rb', line 17

def self.gem_loader
  @gem_loader ||= Zeitwerk::Loader.new.tap do |loader|
    root = File.expand_path("..", __dir__)
    loader.tag = "hanami-sprockets"
    loader.push_dir(root)
    loader.ignore(
      "#{root}/hanami-sprockets.rb",
      "#{root}/hanami/sprockets/version.rb",
      "#{root}/hanami/sprockets/errors.rb",
      "#{root}/hanami/sprockets/cli.rb",
      "#{root}/hanami/cli"
    )
    loader.enable_reloading if loader.respond_to?(:enable_reloading)
    loader.inflector = Zeitwerk::GemInflector.new("#{root}/hanami-sprockets.rb")
  end
end

.public_assets_dir(slice) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the directory (under ‘public/assets/`) to be used for storing a slice’s compiled assets.

This is shared logic used by both Hanami (for the assets provider) and Hanami::CLI (for the assets commands).

Since:

  • 0.1.0



51
52
53
54
55
# File 'lib/hanami/sprockets.rb', line 51

def self.public_assets_dir(slice)
  return nil if slice.app.eql?(slice)

  slice.slice_name.to_s.split("/").map { |name| "_#{name}" }.join("/")
end

Instance Method Details

#[](path) ⇒ Hanami::Sprockets::Asset

Returns the asset at the given path.

Returns:

  • (Hanami::Sprockets::Asset)

    the asset

Raises:

  • AssetMissingError if no asset can be found at the path

Since:

  • 0.1.0



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/hanami/sprockets.rb', line 85

def [](path)
  # Find the asset using Sprockets
  sprockets_asset = environment.find_asset(path)

  raise AssetMissingError.new(path) unless sprockets_asset

  # Generate the asset path - use digest_path for fingerprinting in production
  asset_path = if config.digest
    "#{config.path_prefix}/#{sprockets_asset.digest_path}"
  else
    "#{config.path_prefix}/#{sprockets_asset.logical_path}"
  end

  # Create our Asset wrapper
  Asset.new(
    path: asset_path,
    base_url: config.base_url,
    sri: calculate_sri(sprockets_asset),
    logical_path: sprockets_asset.logical_path,
    digest_path: sprockets_asset.digest_path,
    content_type: sprockets_asset.content_type,
    source: sprockets_asset.source
  )
end

#clear_cache!Object

Clear the cache (useful in development)

Since:

  • 0.1.0



199
200
201
# File 'lib/hanami/sprockets.rb', line 199

def clear_cache!
  @environment = setup_sprockets_environment
end

#crossorigin?(source_path) ⇒ Boolean

Returns true if the given source path is a cross-origin request.

Returns:

  • (Boolean)

Since:

  • 0.1.0



126
127
128
# File 'lib/hanami/sprockets.rb', line 126

def crossorigin?(source_path)
  config.crossorigin?(source_path)
end

#logical_pathsObject

Get all logical paths (useful for debugging)

Since:

  • 0.1.0



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/hanami/sprockets.rb', line 171

def logical_paths
  paths = []
  # Walk through all load paths and find assets
  environment.paths.each do |load_path|
    next unless Dir.exist?(load_path)

    Dir.glob("**/*", base: load_path).each do |file|
      full_path = File.join(load_path, file)
      next unless File.file?(full_path)
      next if File.basename(file).start_with?(".")

      # Try to find it as an asset to see if Sprockets can handle it
      begin
        if environment.find_asset(file)
          paths << file
        end
      rescue
        # Skip files that cause errors
      end
    end
  end

  paths.uniq.sort
end

#precompile(target_dir = nil, &block) ⇒ Object

Precompile assets (for production)

Since:

  • 0.1.0



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/hanami/sprockets.rb', line 134

def precompile(target_dir = nil, &block)
  target_dir ||= root.join("public", "assets")
  target_dir = Pathname(target_dir)
  target_dir.mkpath

  manifest = ::Sprockets::Manifest.new(environment, target_dir, "manifest.json")

  # Precompile configured assets - compile by explicit names first
  ['app.css', 'app.js'].each do |asset|
    begin
      manifest.compile(asset)
      block&.call(asset) if block
    rescue Sprockets::FileNotFound
      # Asset doesn't exist, skip it
    end
  end

  # Then process configured precompile patterns
  config.precompile.each do |asset|
    begin
      manifest.compile(asset)
      block&.call(asset) if block
    rescue Sprockets::FileNotFound
      # Asset doesn't exist, skip it
    end
  end

  # Write the manifest file
  File.write(File.join(target_dir, "manifest.json"), JSON.pretty_generate(manifest.assets))

  manifest
end

#subresource_integrity?Boolean

Returns true if subresource integrity is configured.

Returns:

  • (Boolean)

Since:

  • 0.1.0



116
117
118
# File 'lib/hanami/sprockets.rb', line 116

def subresource_integrity?
  config.subresource_integrity.any?
end