lib/hanami/assets.rb in hanami-assets-1.3.5 vs lib/hanami/assets.rb in hanami-assets-2.1.0.beta2
- old
+ new
@@ -1,175 +1,93 @@
# frozen_string_literal: true
-require "hanami/utils/class_attribute"
+require "json"
+require "zeitwerk"
# Hanami
#
# @since 0.1.0
module Hanami
# Assets management for Ruby web applications
#
# @since 0.1.0
- module Assets
- # Base error for Hanami::Assets
- #
- # All the errors defined in this framework MUST inherit from it.
- #
- # @since 0.1.0
- class Error < ::StandardError
+ class Assets
+ # @since 2.1.0
+ # @api private
+ def self.gem_loader
+ @gem_loader ||= Zeitwerk::Loader.new.tap do |loader|
+ root = File.expand_path("..", __dir__)
+ loader.tag = "hanami-assets"
+ loader.push_dir(root)
+ loader.ignore(
+ "#{root}/hanami-assets.rb",
+ "#{root}/hanami/assets/version.rb",
+ "#{root}/hanami/assets/errors.rb"
+ )
+ loader.inflector = Zeitwerk::GemInflector.new("#{root}/hanami-assets.rb")
+ end
end
- require "hanami/assets/version"
- require "hanami/assets/configuration"
- require "hanami/assets/config/global_sources"
- require "hanami/assets/helpers"
+ gem_loader.setup
+ require_relative "assets/version"
+ require_relative "assets/errors"
- include Utils::ClassAttribute
-
- # Configuration
- #
- # @since 0.1.0
+ # @since 2.1.0
# @api private
- class_attribute :configuration
- self.configuration = Configuration.new
+ SEPARATOR = "/"
+ private_constant :SEPARATOR
- # Configure framework
- #
- # @param blk [Proc] configuration code block
- #
- # @return self
- #
- # @since 0.1.0
- #
- # @see Hanami::Assets::Configuration
- def self.configure(&blk)
- configuration.instance_eval(&blk)
- self
- end
+ attr_reader :config
- # Prepare assets for deploys
- #
- # @since 0.1.0
- def self.deploy
- require "hanami/assets/precompiler"
- require "hanami/assets/bundler"
-
- Precompiler.new(configuration, duplicates).run
- Bundler.new(configuration, duplicates).run
+ # @since 2.1.0
+ # @api public
+ def initialize(config:)
+ @config = config
end
- # Precompile assets
- #
- # @since 0.4.0
- def self.precompile(configurations)
- require "hanami/assets/precompiler"
- require "hanami/assets/bundler"
+ # @since 2.1.0
+ # @api public
+ def [](path)
+ asset_attrs = manifest
+ .fetch(path) { raise AssetMissingError.new(path) }
+ .transform_keys(&:to_sym)
+ .tap { |attrs|
+ # The `url` attribute we receive from the manifest is actually a path; rename it as such
+ # so our `Asset` attributes make more sense on their own.
+ attrs[:path] = attrs.delete(:url)
+ }
- Precompiler.new(configuration, configurations).run
- Bundler.new(configuration, configurations).run
+ Asset.new(
+ **asset_attrs,
+ base_url: config.base_url
+ )
end
- # Preload the framework
- #
- # This MUST be used in production mode
- #
- # @since 0.1.0
- #
- # @example Direct Invocation
- # require 'hanami/assets'
- #
- # Hanami::Assets.load!
- #
- # @example Load Via Configuration Block
- # require 'hanami/assets'
- #
- # Hanami::Assets.configure do
- # # ...
- # end.load!
- def self.load!
- configuration.load!
+ # @since 2.1.0
+ # @api public
+ def subresource_integrity?
+ config.subresource_integrity.any?
end
- # Global assets sources
- #
- # This is designed for third party integration gems with frontend frameworks
- # like Bootstrap, Ember.js or React.
- #
- # Developers can maintain gems that ship static assets for these frameworks
- # and make them available to Hanami::Assets.
- #
- # @return [Hanami::Assets::Config::GlobalSources]
- #
- # @since 0.1.0
- #
- # @example Ember.js Integration
- # # lib/hanami/emberjs.rb (third party gem)
- # require 'hanami/assets'
- #
- # Hanami::Assets.sources << '/path/to/emberjs/assets'
- def self.sources
- synchronize do
- @@sources ||= Config::GlobalSources.new # rubocop:disable Style/ClassVars
- end
+ # @since 2.1.0
+ # @api public
+ def crossorigin?(source_path)
+ config.crossorigin?(source_path)
end
- # Duplicate the framework and generate modules for the target application
- #
- # @param _mod [Module] the Ruby namespace of the application
- # @param blk [Proc] an optional block to configure the framework
- #
- # @return [Module] a copy of Hanami::Assets
- #
- # @since 0.1.0
- #
- # @see Hanami::Assets#dupe
- # @see Hanami::Assets::Configuration
- def self.duplicate(_mod, &blk)
- dupe.tap do |duplicated|
- duplicated.configure(&blk) if block_given?
- duplicates << duplicated
- end
- end
+ private
- # Duplicate Hanami::Assets in order to create a new separated instance
- # of the framework.
- #
- # The new instance of the framework will be completely decoupled from the
- # original. It will inherit the configuration, but all the changes that
- # happen after the duplication, won't be reflected on the other copies.
- #
- # @return [Module] a copy of Hanami::Assets
- #
- # @since 0.1.0
- # @api private
- def self.dupe
- dup.tap do |duplicated|
- duplicated.configuration = configuration.duplicate
- end
- end
+ def manifest
+ return @manifest if instance_variable_defined?(:@manifest)
- # Keep track of duplicated frameworks
- #
- # @return [Array] a collection of duplicated frameworks
- #
- # @since 0.1.0
- # @api private
- #
- # @see Hanami::Assets#duplicate
- # @see Hanami::Assets#dupe
- def self.duplicates
- synchronize do
- @@duplicates ||= [] # rubocop:disable Style/ClassVars
+ unless config.manifest_path
+ raise ConfigError, "no manifest_path configured"
end
- end
- class << self
- private
-
- # @since 0.1.0
- # @api private
- def synchronize(&blk)
- Mutex.new.synchronize(&blk)
+ unless File.exist?(config.manifest_path)
+ raise ManifestMissingError.new(config.manifest_path)
end
+
+ @manifest = JSON.parse(File.read(config.manifest_path))
end
end
end