module Sprockets::Resolve
def parse_accept_options(mime_type, explicit_type)
[["*/*", 1.0]]
[["application/javascript", 1.0]]
Returns Array of Array
that matches the given explicit_type will be accepted.
When called with an explicit_type and a mime_type, only a mime_type
- explicit_type - String, optional. e.g. "application/javascript"
- mime_type - String, optional. e.g. "text/html"
Internal: Converts mimetype into accept Array
def parse_accept_options(mime_type, explicit_type) if mime_type return [[mime_type, 1.0]] if explicit_type.nil? return [[mime_type, 1.0]] if HTTPUtils.parse_q_values(explicit_type).any? { |accept, _| HTTPUtils.match_mime_type?(mime_type, accept) } return [] end accepts = HTTPUtils.parse_q_values(explicit_type) accepts << ['*/*'.freeze, 1.0] if accepts.empty? return accepts end
def resolve(path, load_paths: config[:paths], accept: nil, pipeline: nil, base_path: nil)
# => "file:///path/to/app/javascripts/application.coffee?type=application/javascript"
resolve("application", accept: "application/javascript")
format extension.
An accept content type can be given if the logical path doesn't have a
# => "file:///path/to/app/javascripts/application.js?type=application/javascript"
resolve("application.js")
environment's load paths.
Public: Find Asset URI for given a logical path by searching the
def resolve(path, load_paths: config[:paths], accept: nil, pipeline: nil, base_path: nil) paths = load_paths if valid_asset_uri?(path) uri, deps = resolve_asset_uri(path) elsif absolute_path?(path) filename, type, deps = resolve_absolute_path(paths, path, accept) elsif relative_path?(path) filename, type, path_pipeline, deps, index_alias = resolve_relative_path(paths, path, base_path, accept) else filename, type, path_pipeline, deps, index_alias = resolve_logical_path(paths, path, accept) end if filename uri = build_asset_uri(filename, type: type, pipeline: pipeline || path_pipeline, index_alias: index_alias) end return uri, deps end
def resolve!(path, **kargs)
Public: Same as resolve() but raises a FileNotFound exception instead of
def resolve!(path, **kargs) uri, deps = resolve(path, **kargs) unless uri message = String.new("couldn't find file '#{path}'") if relative_path?(path) && kargs[:base_path] load_path, _ = paths_split(config[:paths], kargs[:base_path]) message << " under '#{load_path}'" end message << " with type '#{kargs[:accept]}'" if kargs[:accept] load_paths = kargs[:load_paths] || config[:paths] message << "\nChecked in these paths: \n #{ load_paths.join("\n ") }" raise FileNotFound, message end return uri, deps end
def resolve_absolute_path(paths, filename, accept)
e.g. "application/javascript" or "text/css, */*"
mime types that we are looking for. Can be nil.
accept - String. A Quality value incoded set of
e.g. "/Users/schneems/sprockets/test/fixtures/asset/application.js"
filename - String containing absolute path to a file including extension.
paths - Array of Strings.
Internal: Finds a file in a set of given paths
def resolve_absolute_path(paths, filename, accept) deps = Set.new filename = File.expand_path(filename) # Ensure path is under load paths return nil, nil, deps unless PathUtils.paths_split(paths, filename) _, mime_type = PathUtils.match_path_extname(filename, config[:mime_exts]) type = resolve_transform_type(mime_type, accept) return nil, nil, deps if accept && !type return nil, nil, deps unless file?(filename) deps << URIUtils.build_file_digest_uri(filename) return filename, type, deps end
def resolve_alternates(load_path, logical_name)
def resolve_alternates(load_path, logical_name) return [], Set.new end
def resolve_alts_under_path(load_path, logical_name, mime_exts)
def resolve_alts_under_path(load_path, logical_name, mime_exts) filenames, deps = self.resolve_alternates(load_path, logical_name) filenames.map! do |fn| _, mime_type = PathUtils.match_path_extname(fn, mime_exts) { filename: fn, type: mime_type } end return filenames, deps end
def resolve_asset_uri(uri)
e.g. "file:///Users/schneems/sprockets/test/fixtures/default/gallery.js?type=application/javascript"
file.
uri - String. Contains file:// scheme, absolute path to
Internal: Finds an asset given a URI
def resolve_asset_uri(uri) filename, _ = URIUtils.parse_asset_uri(uri) return uri, Set.new( [URIUtils.build_file_digest_uri(filename)] ) end
def resolve_index_under_path(load_path, logical_name, mime_exts)
that are named `index` and have a matching mime type in `mime_exts`.
Looking in the given `load_path` this method will find all files under the `logical_name` directory
e.g. {".xml.builder"=>"application/xml+builder"}
mime_exts - Hash of file extensions and their mime types
e.g. "application" or "coffee/foo"
logical_name - String. A filename without extension
load_path - String. An absolute path to a directory
Internal: Finds candidate index files in a given path
def resolve_index_under_path(load_path, logical_name, mime_exts) dirname = File.join(load_path, logical_name) if self.directory?(dirname) candidates = self.find_matching_path_for_extensions(dirname, "index".freeze, mime_exts) else candidates = [] end candidates.map! do |c| { filename: c[0], type: c[1], index_alias: compress_from_root(c[0].sub(/\/index(\.[^\/]+)$/, '\1')) } end return candidates, [ URIUtils.build_file_digest_uri(dirname) ] end
def resolve_logical_path(paths, logical_path, accept)
Finds a file on the given paths.
e.g. "application/javascript" or "text/css, */*"
mime types that we are looking for. Can be nil.
accept - String. A Quality value incoded set of
e.g. "coffee/foo.js" or "foo.js"
logical_path - String. A filename with extension
paths - Array of Strings.
Internal: Finds a file in a set of given paths
def resolve_logical_path(paths, logical_path, accept) extname, mime_type = PathUtils.match_path_extname(logical_path, config[:mime_exts]) logical_name = logical_path.chomp(extname) extname, pipeline = PathUtils.match_path_extname(logical_name, config[:pipeline_exts]) logical_name = logical_name.chomp(extname) parsed_accept = parse_accept_options(mime_type, accept) transformed_accepts = expand_transform_accepts(parsed_accept) filename, mime_type, deps, index_alias = resolve_under_paths(paths, logical_name, transformed_accepts) if filename deps << build_file_digest_uri(filename) type = resolve_transform_type(mime_type, parsed_accept) return filename, type, pipeline, deps, index_alias else return nil, nil, nil, deps end end
def resolve_main_under_path(load_path, logical_name, mime_exts)
mime type that is included in `mime_exts` on the `load_path`.
Finds files that match a given `logical_name` with an acceptable
e.g. {".xml.builder"=>"application/xml+builder"}
mime_exts - Hash of file extensions and their mime types
e.g. "application" or "coffee/foo"
logical_name - String. A filename without extension
load_path - String. An absolute path to a directory
Internal: Finds candidate files on a given path
def resolve_main_under_path(load_path, logical_name, mime_exts) dirname = File.dirname(File.join(load_path, logical_name)) candidates = self.find_matching_path_for_extensions(dirname, File.basename(logical_name), mime_exts) candidates.map! do |c| { filename: c[0], type: c[1] } end return candidates, [ URIUtils.build_file_digest_uri(dirname) ] end
def resolve_relative_path(paths, path, dirname, accept)
e.g. "application/javascript" or "text/css, */*"
mime types that we are looking for. Can be nil.
accept - String. A Quality value incoded set of
dirname - String. Base path where we start looking for the given file.
e.g. "./jquery" or "../foo.js"
path - String. A relative filename with or without extension
paths - Array of Strings.
Internal: Finds a relative file in a set of given paths
def resolve_relative_path(paths, path, dirname, accept) filename = File.expand_path(path, dirname) load_path, _ = PathUtils.paths_split(paths, dirname) if load_path && logical_path = PathUtils.split_subpath(load_path, filename) resolve_logical_path([load_path], logical_path, accept) else return nil, nil, nil, Set.new end end
def resolve_under_paths(paths, logical_name, accepts)
`accepts`.
of the `logical_name` directory that matches a valid mime-type/version from
Finds a file with the same name as `logical_name` or "index" inside
e.g. [["application/javascript", 1.0]]
accepts - Array of array containing mime/version pairs
e.g. "application" or "coffee/foo"
logical_name - String. A filename without extension
paths - Array of Strings.
Internal: Finds a file in a set of given paths
def resolve_under_paths(paths, logical_name, accepts) deps = Set.new return nil, nil, deps if accepts.empty? # TODO: Allow new path resolves to be registered @resolvers ||= [ method(:resolve_main_under_path), method(:resolve_alts_under_path), method(:resolve_index_under_path) ] mime_exts = config[:mime_exts] paths.each do |load_path| candidates = [] @resolvers.each do |fn| result = fn.call(load_path, logical_name, mime_exts) candidates.concat(result[0]) deps.merge(result[1]) end candidate = HTTPUtils.find_best_q_match(accepts, candidates) do |c, matcher| match_mime_type?(c[:type] || "application/octet-stream", matcher) end return candidate[:filename], candidate[:type], deps, candidate[:index_alias] if candidate end return nil, nil, deps end