Class: Hanami::Assets

Inherits:
Object
  • Object
show all
Defined in:
lib/hanami/sprockets.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, 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.1.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



69
70
71
72
73
# File 'lib/hanami/sprockets.rb', line 69

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



57
58
59
# File 'lib/hanami/sprockets.rb', line 57

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



65
66
67
# File 'lib/hanami/sprockets.rb', line 65

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



61
62
63
# File 'lib/hanami/sprockets.rb', line 61

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
# 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"
    )
    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



49
50
51
52
53
# File 'lib/hanami/sprockets.rb', line 49

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



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

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



197
198
199
# File 'lib/hanami/sprockets.rb', line 197

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



124
125
126
# File 'lib/hanami/sprockets.rb', line 124

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

#logical_pathsObject

Get all logical paths (useful for debugging)

Since:

  • 0.1.0



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

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



132
133
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
# File 'lib/hanami/sprockets.rb', line 132

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



114
115
116
# File 'lib/hanami/sprockets.rb', line 114

def subresource_integrity?
  config.subresource_integrity.any?
end