module Sprockets::Rails::Helper

def self.extended(obj)

def self.extended(obj)
  obj.singleton_class.class_eval do
    attr_accessor(*VIEW_ACCESSORS)
    remove_method :assets_environment
    def assets_environment
      if env = @assets_environment
        @assets_environment = env.cached
      else
        nil
      end
    end
  end
end

def self.included(klass)

def self.included(klass)
  klass.class_attribute(*VIEW_ACCESSORS)
  klass.class_eval do
    remove_method :assets_environment
    def assets_environment
      if instance_variable_defined?(:@assets_environment)
        @assets_environment = @assets_environment.cached
      elsif env = self.class.assets_environment
        @assets_environment = env.cached
      else
        nil
      end
    end
  end
end

def asset_digest_path(path, options = {})

Returns String path or nil if no asset was found.

options - Hash options
path - String path

Expand asset path to digested form.
def asset_digest_path(path, options = {})
  resolve_asset do |resolver|
    resolver.digest_path path, options[:debug]
  end
end

def asset_integrity(path, options = {})

Returns String integrity attribute or nil if no asset was found.

options - Hash options
path - String path

Experimental: Get integrity for asset path.
def asset_integrity(path, options = {})
  path = path_with_extname(path, options)
  resolve_asset do |resolver|
    resolver.integrity path
  end
end

def asset_resolver_strategies

List of resolvers in `config.assets.resolve_with` order.
def asset_resolver_strategies
  @asset_resolver_strategies ||=
    Array(resolve_assets_with).map do |name|
      HelperAssetResolvers[name].new(self)
    end
end

def assets_environment

def assets_environment
  if instance_variable_defined?(:@assets_environment)
    @assets_environment = @assets_environment.cached
  elsif env = self.class.assets_environment
    @assets_environment = env.cached
  else
    nil
  end
end

def assets_environment

def assets_environment
  if env = @assets_environment
    @assets_environment = env.cached
  else
    nil
  end
end

def compute_asset_path(path, options = {})

to use the asset pipeline.
Writes over the built in ActionView::Helpers::AssetUrlHelper#compute_asset_path
def compute_asset_path(path, options = {})
  debug = options[:debug]
  if asset_path = resolve_asset_path(path, debug)
    File.join(assets_prefix || "/", legacy_debug_path(asset_path, debug))
  else
    message =  "The asset #{ path.inspect } is not present in the asset pipeline.\n"
    raise AssetNotFound, message unless unknown_asset_fallback
    if respond_to?(:public_compute_asset_path)
      message << "Falling back to an asset that may be in the public folder.\n"
      message << "This behavior is deprecated and will be removed.\n"
      message << "To bypass the asset pipeline and preserve this behavior,\n"
      message << "use the `skip_pipeline: true` option.\n"
      Sprockets::Rails.deprecator.warn(message, caller_locations)
    end
    super
  end
end

def compute_integrity?(options)

it's boolean-ish.
doesn't bleed into the tag attributes, but also check its value if
That means we have to delete the shortcut boolean option so it
options hash is also passed through as literal tag attributes.
we want to include or omit the subresource integrity hash, but the
This is awkward: `integrity` is a boolean option indicating whether
def compute_integrity?(options)
  if secure_subresource_integrity_context?
    case options['integrity']
    when nil, false, true
      options.delete('integrity') == true
    end
  else
    options.delete 'integrity'
    false
  end
end

def javascript_include_tag(*sources)

Eventually will be deprecated and replaced by source maps.

Override javascript tag helper to provide debugging support.
def javascript_include_tag(*sources)
  options = sources.extract_options!.stringify_keys
  integrity = compute_integrity?(options)
  if options["debug"] != false && request_debug_assets?
    sources.map { |source|
      if asset = lookup_debug_asset(source, type: :javascript)
        if asset.respond_to?(:to_a)
          asset.to_a.map do |a|
            super(path_to_javascript(a.logical_path, debug: true), options)
          end
        else
          super(path_to_javascript(asset.logical_path, debug: true), options)
        end
      else
        super(source, options)
      end
    }.flatten.uniq.join("\n").html_safe
  else
    sources.map { |source|
      options = options.merge('integrity' => asset_integrity(source, type: :javascript)) if integrity
      super source, options
    }.join("\n").html_safe
  end
end

def legacy_debug_path(path, debug)

Append ?body=1 if debug is on and we're on old Sprockets.
def legacy_debug_path(path, debug)
  if debug && !using_sprockets4?
    "#{path}?body=1"
  else
    path
  end
end

def lookup_debug_asset(path, options = {})

eventually be removed w/ Sprockets 3.x.
Internal method to support multifile debugging. Will
def lookup_debug_asset(path, options = {})
  path = path_with_extname(path, options)
  resolve_asset do |resolver|
    resolver.find_debug_asset path
  end
end

def path_with_extname(path, options)

compute_asset_extname is in AV::Helpers::AssetUrlHelper
def path_with_extname(path, options)
  path = path.to_s
  "#{path}#{compute_asset_extname(path, options)}"
end

def request_debug_assets?

and replaced by source maps in Sprockets 3.x.
Enable split asset debugging. Eventually will be deprecated
def request_debug_assets?
  debug_assets || (defined?(controller) && controller && params[:debug_assets])
rescue # FIXME: what exactly are we rescuing?
  false
end

def resolve_asset

Try each asset resolver and return the first non-nil result.
def resolve_asset
  asset_resolver_strategies.detect do |resolver|
    if result = yield(resolver)
      break result
    end
  end
end

def resolve_asset_path(path, allow_non_precompiled = false) #:nodoc:

:nodoc:
Returns nil if it's an asset we don't know about.
Resolve the asset path against the Sprockets manifest or environment.
def resolve_asset_path(path, allow_non_precompiled = false) #:nodoc:
  resolve_asset do |resolver|
    resolver.asset_path path, digest_assets, allow_non_precompiled
  end
end

def secure_subresource_integrity_context?

http://www.w3.org/TR/SRI/#non-secure-contexts-remain-non-secure
Only serve integrity metadata for HTTPS requests:
def secure_subresource_integrity_context?
  respond_to?(:request) && self.request && (self.request.local? || self.request.ssl?)
end

def stylesheet_link_tag(*sources)

Eventually will be deprecated and replaced by source maps.

Override stylesheet tag helper to provide debugging support.
def stylesheet_link_tag(*sources)
  options = sources.extract_options!.stringify_keys
  integrity = compute_integrity?(options)
  if options["debug"] != false && request_debug_assets?
    sources.map { |source|
      if asset = lookup_debug_asset(source, type: :stylesheet)
        if asset.respond_to?(:to_a)
          asset.to_a.map do |a|
            super(path_to_stylesheet(a.logical_path, debug: true), options)
          end
        else
          super(path_to_stylesheet(asset.logical_path, debug: true), options)
        end
      else
        super(source, options)
      end
    }.flatten.uniq.join("\n").html_safe
  else
    sources.map { |source|
      options = options.merge('integrity' => asset_integrity(source, type: :stylesheet)) if integrity
      super source, options
    }.join("\n").html_safe
  end
end