require 'sprockets'
require 'sprockets/helpers/version'
require 'sprockets/helpers/base_path'
require 'sprockets/helpers/asset_path'
require 'sprockets/helpers/file_path'
require 'sprockets/helpers/manifest_path'
require 'uri'
module Sprockets
module Helpers
class << self
# Indicates whenever we are using Sprockets 3.x.
attr_accessor :are_using_sprockets_3
# Link to assets from a dedicated server.
attr_accessor :asset_host
# When true, the asset paths will return digest paths.
attr_accessor :digest
# When true, expand assets.
attr_accessor :expand
# When true, force debug mode
# :debug => true equals
# :expand => true
# :digest => false
# :manifest => false
attr_accessor :debug
# Set the Sprockets environment to search for assets.
# This defaults to the context's #environment method.
attr_accessor :environment
# The manifest file used for lookup
attr_accessor :manifest
# The base URL the Sprocket environment is mapped to.
# This defaults to '/assets'.
def prefix
@prefix ||= '/assets'
@prefix.is_a?(Array) ? "/#{@prefix.first}" : @prefix
end
attr_writer :prefix
# Customize the protocol when using asset hosts.
# If the value is :relative, A relative protocol ('//')
# will be used.
def protocol
@protocol ||= 'http://'
end
attr_writer :protocol
# The path to the public directory, where the assets
# not managed by Sprockets will be located.
# Defaults to './public'
def public_path
@public_path ||= './public'
end
attr_writer :public_path
# The default options for each asset path method. This is where you
# can change your default directories for the fallback directory.
def default_path_options
@default_path_options ||= {
:audio_path => { :dir => 'audios' },
:font_path => { :dir => 'fonts' },
:image_path => { :dir => 'images' },
:javascript_path => { :dir => 'javascripts', :ext => 'js' },
:stylesheet_path => { :dir => 'stylesheets', :ext => 'css' },
:video_path => { :dir => 'videos' }
}
end
attr_writer :default_path_options
# Convience method for configuring Sprockets::Helpers.
def configure
yield self
end
# Hack to ensure methods from Sprockets::Helpers override the
# methods of Sprockets::Context when included.
def append_features(context) # :nodoc:
context.class_eval do
context_methods = context.instance_methods(false)
Helpers.public_instance_methods.each do |method|
remove_method(method) if context_methods.include?(method)
end
end
super(context)
end
end
# We are checking here to skip this at runtime
@are_using_sprockets_3 = Gem::Version.new(Sprockets::VERSION) >= Gem::Version.new('3.0')
# Returns the path to an asset either in the Sprockets environment
# or the public directory. External URIs are untouched.
#
# ==== Options
#
# * :ext - The extension to append if the source does not have one.
# * :dir - The directory to prepend if the file is in the public directory.
# * :digest - Wether or not use the digest paths for assets. Set Sprockets::Helpers.digest for global configuration.
# * :prefix - Use a custom prefix for the Sprockets environment. Set Sprockets::Helpers.prefix for global configuration.
# * :body - Adds a ?body=1 flag that tells Sprockets to return only the body of the asset.
#
# ==== Examples
#
# For files within Sprockets:
#
# asset_path 'xmlhr.js' # => '/assets/xmlhr.js'
# asset_path 'xmlhr', :ext => 'js' # => '/assets/xmlhr.js'
# asset_path 'xmlhr.js', :digest => true # => '/assets/xmlhr-27a8f1f96afd8d4c67a59eb9447f45bd.js'
# asset_path 'xmlhr.js', :prefix => '/themes' # => '/themes/xmlhr.js'
#
# For files outside of Sprockets:
#
# asset_path 'xmlhr' # => '/xmlhr'
# asset_path 'xmlhr', :ext => 'js' # => '/xmlhr.js'
# asset_path 'dir/xmlhr.js', :dir => 'javascripts' # => '/javascripts/dir/xmlhr.js'
# asset_path '/dir/xmlhr.js', :dir => 'javascripts' # => '/dir/xmlhr.js'
# asset_path 'http://www.example.com/js/xmlhr' # => 'http://www.example.com/js/xmlhr'
# asset_path 'http://www.example.com/js/xmlhr.js' # => 'http://www.example.com/js/xmlhr.js'
#
def asset_path(source, options = {})
uri = URI.parse(source)
return source if uri.absolute?
options[:prefix] = Sprockets::Helpers.prefix unless options[:prefix]
if Helpers.debug || options[:debug]
options[:manifest] = false
options[:digest] = false
options[:asset_host] = false
end
source_ext = File.extname(source)
if options[:ext] && source_ext != ".#{options[:ext]}"
uri.path << ".#{options[:ext]}"
end
path = find_asset_path(uri, source, options)
if options[:expand] && path.respond_to?(:to_a)
path.to_a
else
path.to_s
end
end
alias_method :path_to_asset, :asset_path
def asset_tag(source, options = {}, &block)
raise ::ArgumentError, 'block missing' unless block
options = { :expand => !!Helpers.debug || !!Helpers.expand, :debug => Helpers.debug }.merge(options)
path = asset_path(source, options)
output = if options[:expand] && path.respond_to?(:map)
"\n\n" + path.map(&block).join("\n")
else
yield path
end
output = output.html_safe if output.respond_to?(:html_safe)
output
end
def javascript_tag(source, options = {})
options = Helpers.default_path_options[:javascript_path].merge(options)
asset_tag(source, options) do |path|
%Q()
end
end
def stylesheet_tag(source, options = {})
media = options.delete(:media)
media_attr = media.nil? ? nil : " media=\"#{media}\""
options = Helpers.default_path_options[:stylesheet_path].merge(options)
asset_tag(source, options) do |path|
%Q()
end
end
# Computes the path to a audio asset either in the Sprockets environment
# or the public directory. External URIs are untouched.
#
# ==== Examples
#
# With files within Sprockets:
#
# audio_path 'audio.mp3' # => '/assets/audio.mp3'
# audio_path 'subfolder/audio.mp3' # => '/assets/subfolder/audio.mp3'
# audio_path '/subfolder/audio.mp3' # => '/assets/subfolder/audio.mp3'
#
# With files outside of Sprockets:
#
# audio_path 'audio' # => '/audios/audio'
# audio_path 'audio.mp3' # => '/audios/audio.mp3'
# audio_path 'subfolder/audio.mp3' # => '/audios/subfolder/audio.mp3'
# audio_path '/subfolder/audio.mp3 # => '/subfolder/audio.mp3'
# audio_path 'http://www.example.com/img/audio.mp3' # => 'http://www.example.com/img/audio.mp3'
#
def audio_path(source, options = {})
asset_path source, Helpers.default_path_options[:audio_path].merge(options)
end
alias_method :path_to_audio, :audio_path
# Computes the path to a font asset either in the Sprockets environment
# or the public directory. External URIs are untouched.
#
# ==== Examples
#
# With files within Sprockets:
#
# font_path 'font.ttf' # => '/assets/font.ttf'
# font_path 'subfolder/font.ttf' # => '/assets/subfolder/font.ttf'
# font_path '/subfolder/font.ttf' # => '/assets/subfolder/font.ttf'
#
# With files outside of Sprockets:
#
# font_path 'font' # => '/fonts/font'
# font_path 'font.ttf' # => '/fonts/font.ttf'
# font_path 'subfolder/font.ttf' # => '/fonts/subfolder/font.ttf'
# font_path '/subfolder/font.ttf # => '/subfolder/font.ttf'
# font_path 'http://www.example.com/img/font.ttf' # => 'http://www.example.com/img/font.ttf'
#
def font_path(source, options = {})
asset_path source, Helpers.default_path_options[:font_path].merge(options)
end
alias_method :path_to_font, :font_path
# Computes the path to an image asset either in the Sprockets environment
# or the public directory. External URIs are untouched.
#
# ==== Examples
#
# With files within Sprockets:
#
# image_path 'edit.png' # => '/assets/edit.png'
# image_path 'icons/edit.png' # => '/assets/icons/edit.png'
# image_path '/icons/edit.png' # => '/assets/icons/edit.png'
#
# With files outside of Sprockets:
#
# image_path 'edit' # => '/images/edit'
# image_path 'edit.png' # => '/images/edit.png'
# image_path 'icons/edit.png' # => '/images/icons/edit.png'
# image_path '/icons/edit.png' # => '/icons/edit.png'
# image_path 'http://www.example.com/img/edit.png' # => 'http://www.example.com/img/edit.png'
#
def image_path(source, options = {})
asset_path source, Helpers.default_path_options[:image_path].merge(options)
end
alias_method :path_to_image, :image_path
# Computes the path to a javascript asset either in the Sprockets
# environment or the public directory. If the +source+ filename has no extension,
# .js will be appended. External URIs are untouched.
#
# ==== Examples
#
# For files within Sprockets:
#
# javascript_path 'xmlhr' # => '/assets/xmlhr.js'
# javascript_path 'dir/xmlhr.js' # => '/assets/dir/xmlhr.js'
# javascript_path '/dir/xmlhr' # => '/assets/dir/xmlhr.js'
#
# For files outside of Sprockets:
#
# javascript_path 'xmlhr' # => '/javascripts/xmlhr.js'
# javascript_path 'dir/xmlhr.js' # => '/javascripts/dir/xmlhr.js'
# javascript_path '/dir/xmlhr' # => '/dir/xmlhr.js'
# javascript_path 'http://www.example.com/js/xmlhr' # => 'http://www.example.com/js/xmlhr'
# javascript_path 'http://www.example.com/js/xmlhr.js' # => 'http://www.example.com/js/xmlhr.js'
#
def javascript_path(source, options = {})
asset_path source, Helpers.default_path_options[:javascript_path].merge(options)
end
alias_method :path_to_javascript, :javascript_path
# Computes the path to a stylesheet asset either in the Sprockets
# environment or the public directory. If the +source+ filename has no extension,
# .css will be appended. External URIs are untouched.
#
# ==== Examples
#
# For files within Sprockets:
#
# stylesheet_path 'style' # => '/assets/style.css'
# stylesheet_path 'dir/style.css' # => '/assets/dir/style.css'
# stylesheet_path '/dir/style.css' # => '/assets/dir/style.css'
#
# For files outside of Sprockets:
#
# stylesheet_path 'style' # => '/stylesheets/style.css'
# stylesheet_path 'dir/style.css' # => '/stylesheets/dir/style.css'
# stylesheet_path '/dir/style.css' # => '/dir/style.css'
# stylesheet_path 'http://www.example.com/css/style' # => 'http://www.example.com/css/style'
# stylesheet_path 'http://www.example.com/css/style.css' # => 'http://www.example.com/css/style.css'
#
def stylesheet_path(source, options = {})
asset_path source, Helpers.default_path_options[:stylesheet_path].merge(options)
end
alias_method :path_to_stylesheet, :stylesheet_path
# Computes the path to a video asset either in the Sprockets environment
# or the public directory. External URIs are untouched.
#
# ==== Examples
#
# With files within Sprockets:
#
# video_path 'video.mp4' # => '/assets/video.mp4'
# video_path 'subfolder/video.mp4' # => '/assets/subfolder/video.mp4'
# video_path '/subfolder/video.mp4' # => '/assets/subfolder/video.mp4'
#
# With files outside of Sprockets:
#
# video_path 'video' # => '/videos/video'
# video_path 'video.mp4' # => '/videos/video.mp4'
# video_path 'subfolder/video.mp4' # => '/videos/subfolder/video.mp4'
# video_path '/subfolder/video.mp4 # => '/subfolder/video.mp4'
# video_path 'http://www.example.com/img/video.mp4' # => 'http://www.example.com/img/video.mp4'
#
def video_path(source, options = {})
asset_path source, Helpers.default_path_options[:video_path].merge(options)
end
alias_method :path_to_video, :video_path
protected
# Returns the Sprockets environment #asset_path uses to search for
# assets. This can be overridden for more control, if necessary.
# Defaults to Sprockets::Helpers.environment or the envrionment
# returned by #environment.
def assets_environment
Helpers.environment || environment
end
def find_asset_path(uri, source, options = {})
if Helpers.manifest && options[:manifest] != false
manifest_path = Helpers.manifest.assets[uri.path]
return Helpers::ManifestPath.new(uri, manifest_path, options) if manifest_path
end
if Sprockets::Helpers.are_using_sprockets_3
resolved = assets_environment.resolve(uri.path)
if resolved
return Helpers::AssetPath.new(uri, assets_environment[uri.path], options)
else
return Helpers::FilePath.new(uri, options)
end
else
assets_environment.resolve(uri.path) do |path|
return Helpers::AssetPath.new(uri, assets_environment[path], options)
end
return Helpers::FilePath.new(uri, options)
end
end
end
class Context
include Helpers
end
end