class Roger::Resolver
The resolver is here to resolve urls to paths and sometimes vice-versa
Constants
- EXTENSION_MAP
Maps output extensions to template extensions to find source files.
Attributes
load_paths[R]
Public Class Methods
new(paths)
click to toggle source
# File lib/roger/resolver.rb, line 31 def initialize(paths) raise ArgumentError, "Resolver base path can't be nil" if paths.nil? # Convert to paths @load_paths = [paths].flatten.map { |p| Pathname.new(p) } end
Public Instance Methods
find_template(url, options = {})
click to toggle source
@param [String] url The url to resolve to a path @param [Hash] options Options
@option options [String] :prefer The preferred template extension. When searching for
templates, the preferred template extension defines what file type we're requesting when we ask for a file without an extension
# File lib/roger/resolver.rb, line 44 def find_template(url, options = {}) options = { prefer: "html" }.update(options) orig_path, _qs, _anch = strip_query_string_and_anchor(url.to_s) output = nil load_paths.find do |load_path| path = File.join(load_path, orig_path) output = find_template_path(path, options) end output end
Also aliased as: url_to_path
path_to_url(path, relative_to = nil)
click to toggle source
Convert a disk path on file to an url
# File lib/roger/resolver.rb, line 63 def path_to_url(path, relative_to = nil) # Find the parent path we're in path = Pathname.new(path).realpath base = load_paths.find { |lp| path.to_s =~ /\A#{Regexp.escape(lp.realpath.to_s)}/ } path = path.relative_path_from(base).cleanpath if relative_to relative_path_to_url(path, relative_to, base).to_s else "/#{path}" end end
strip_query_string_and_anchor(url)
click to toggle source
# File lib/roger/resolver.rb, line 94 def strip_query_string_and_anchor(url) url = url.dup # Strip off anchors anchor = nil url.gsub!(/(#.+)\Z/) do |r| anchor = r "" end # Strip off query strings query = nil url.gsub!(/(\?.+)\Z/) do |r| query = r "" end [url, query, anchor] end
url_to_relative_url(url, relative_to_path)
click to toggle source
# File lib/roger/resolver.rb, line 77 def url_to_relative_url(url, relative_to_path) # Skip if the url doesn't start with a / (but not with //) return false unless url =~ %r{\A/[^/]} path, qs, anch = strip_query_string_and_anchor(url) # Get disk path if true_path = url_to_path(path, exact_match: true) path = path_to_url(true_path, relative_to_path) path += qs if qs path += anch if anch path else false end end
Protected Instance Methods
filter_files(files, path, path_without_extension, template_extensions)
click to toggle source
Filter a list of files to see wether or not we can process them. Will take into account that the longest match with path will be the first result.
# File lib/roger/resolver.rb, line 150 def filter_files(files, path, path_without_extension, template_extensions) results = [] files.each do |file| match = if file.start_with?(path) path else path_without_extension end processable_extensions = file[(match.length + 1)..-1].split(".") # All processable_extensions must be processable # by a template_extension next unless (processable_extensions - template_extensions).empty? if file.start_with?(path) # The whole path is found in the filename, not just # the path without the extension. # it must have priority over all else results.unshift(file) else results.push(file) end end results end
find_template_path(name, options = {})
click to toggle source
Finds the template path for “name”
# File lib/roger/resolver.rb, line 117 def find_template_path(name, options = {}) options = { prefer: "html", # Prefer a template with extension }.update(options) path = sanitize_name(name, options[:prefer]) # Exact match return Pathname.new(path) if File.exist?(path) # Split extension and path path_extension, path_without_extension = split_path(path) # Get possible output extensions for path_extension template_extensions = template_extensions_for_output(path_extension, options[:prefer]) # Let's look at the disk to see what files we've got files = Dir.glob(path_without_extension + ".*") results = filter_files(files, path, path_without_extension, template_extensions) if !results[0] # No results found, but maybe there is a directory # with the same name and it contains an index.XYZ find_template_path(File.join(name, "index")) if File.directory?(name) else Pathname.new(results[0]) end end
relative_path_to_url(path, relative_to, base)
click to toggle source
# File lib/roger/resolver.rb, line 216 def relative_path_to_url(path, relative_to, base) relative_to = Pathname.new(File.dirname(relative_to.to_s)) # If relative_to is an absolute path if relative_to.absolute? relative_to = relative_to.relative_path_from(base).cleanpath end Pathname.new("/" + path.to_s).relative_path_from(Pathname.new("/" + relative_to.to_s)) end
sanitize_name(name, prefer = nil)
click to toggle source
Check if the name is a directory and append index Append preferred extension or html if it doesn't have one yet
# File lib/roger/resolver.rb, line 180 def sanitize_name(name, prefer = nil) path = name.to_s # Check if we haven't got an extension # we'll assume you're looking for prefer or "html" otherwise path += ".#{prefer || 'html'}" unless File.basename(path).include?(".") path end
split_path(path)
click to toggle source
Split path in to extension an path without extension
# File lib/roger/resolver.rb, line 191 def split_path(path) path = path.to_s extension = File.extname(path)[1..-1] || "" path_without_extension = path.sub(/\.#{Regexp.escape(extension)}\Z/, "") [extension, path_without_extension] end
template_extensions_for_output(ext, prefer = nil)
click to toggle source
# File lib/roger/resolver.rb, line 198 def template_extensions_for_output(ext, prefer = nil) template_extensions = [] # The preferred template_extension is first template_extensions += prefer.to_s.split(".") if prefer # Any exact template matches for extension template_extensions += EXTENSION_MAP[ext] if EXTENSION_MAP[ext] # Any generic templates template_extensions += EXTENSION_MAP[nil] # Myself to pass extension matching later on template_extensions += [ext] template_extensions end