module Sprockets::Resolve
def dirname_matches(dirname, basename)
def dirname_matches(dirname, basename) candidates = [] entries = self.entries(dirname) entries.each do |entry| next unless File.basename(entry).start_with?(basename) name, type, _, _ = parse_path_extnames(entry) if basename == name candidates << [File.join(dirname, entry), type] end end candidates end
def parse_accept_options(mime_type, types)
def parse_accept_options(mime_type, types) accepts = [] accepts += parse_q_values(types) if types if mime_type if accepts.empty? || accepts.any? { |accept, _| match_mime_type?(mime_type, accept) } accepts = [[mime_type, 1.0]] else return [] end end if accepts.empty? accepts << ['*/*', 1.0] end accepts end
def parse_path_extnames(path)
# => ["foo", "application/javascript", [".coffee", ".erb"]]
"foo.js.coffee.erb"
Internal: Returns the name, mime type and `Array` of engine extensions.
def parse_path_extnames(path) engines = [] extname, value = match_path_extname(path, extname_map) if extname path = path.chomp(extname) type, engines, pipeline = value.values_at(:type, :engines, :pipeline) end return path, type, engines, pipeline end
def path_matches(load_path, logical_name, logical_basename)
def path_matches(load_path, logical_name, logical_basename) dirname = File.dirname(File.join(load_path, logical_name)) candidates = dirname_matches(dirname, logical_basename) deps = file_digest_dependency_set(dirname) result = resolve_alternates(load_path, logical_name) result[0].each do |fn| candidates << [fn, parse_path_extnames(fn)[1]] end deps.merge(result[1]) dirname = File.join(load_path, logical_name) if directory? dirname result = dirname_matches(dirname, "index") candidates.concat(result) end deps.merge(file_digest_dependency_set(dirname)) return candidates.select { |fn, _| file?(fn) }, deps end
def resolve(path, options = {})
# => "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, options = {}) path = path.to_s paths = options[:load_paths] || config[:paths] accept = options[:accept] 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, pipeline, deps = resolve_relative_path(paths, path, options[:base_path], accept) else filename, type, pipeline, deps = resolve_logical_path(paths, path, accept) end if filename params = {} params[:type] = type if type params[:pipeline] = pipeline if pipeline params[:pipeline] = options[:pipeline] if options[:pipeline] uri = build_asset_uri(filename, params) end return uri, deps end
def resolve!(path, options = {})
Public: Same as resolve() but raises a FileNotFound exception instead of
def resolve!(path, options = {}) uri, deps = resolve(path, options.merge(compat: false)) unless uri message = "couldn't find file '#{path}'" if relative_path?(path) && options[:base_path] load_path, _ = paths_split(config[:paths], options[:base_path]) message << " under '#{load_path}'" end message << " with type '#{options[:accept]}'" if options[:accept] message << "\nChecked in these paths: \n #{ config[:paths].join("\n ") }" raise FileNotFound, message end return uri, deps end
def resolve_absolute_path(paths, filename, accept)
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 paths_split(paths, filename) _, mime_type, _, _ = parse_path_extnames(filename) type = resolve_transform_type(mime_type, accept) return nil, nil, deps if accept && !type return nil, nil, deps unless file?(filename) deps << 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_asset_uri(uri)
def resolve_asset_uri(uri) filename, _ = parse_asset_uri(uri) return uri, Set.new([build_file_digest_uri(filename)]) end
def resolve_logical_path(paths, logical_path, accept)
def resolve_logical_path(paths, logical_path, accept) logical_name, mime_type, _, pipeline = parse_path_extnames(logical_path) parsed_accept = parse_accept_options(mime_type, accept) transformed_accepts = expand_transform_accepts(parsed_accept) filename, mime_type, deps = 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 else return nil, nil, nil, deps end end
def resolve_relative_path(paths, path, dirname, accept)
def resolve_relative_path(paths, path, dirname, accept) filename = File.expand_path(path, dirname) load_path, _ = paths_split(paths, dirname) if load_path && logical_path = split_subpath(load_path, filename) resolve_logical_path([load_path], logical_path, accept) else return nil, nil, Set.new end end
def resolve_under_paths(paths, logical_name, accepts)
def resolve_under_paths(paths, logical_name, accepts) all_deps = Set.new return nil, nil, all_deps if accepts.empty? logical_basename = File.basename(logical_name) paths.each do |load_path| candidates, deps = path_matches(load_path, logical_name, logical_basename) all_deps.merge(deps) candidate = find_best_q_match(accepts, candidates) do |c, matcher| match_mime_type?(c[1] || "application/octet-stream", matcher) end return candidate + [all_deps] if candidate end return nil, nil, all_deps end