lib/roda/plugins/relative_path.rb
# frozen-string-literal: true # class Roda module RodaPlugins # The relative_path plugin adds a relative_path method that accepts # an absolute path and returns a path relative to the current request # by adding an appropriate prefix: # # plugin :relative_path # route do |r| # relative_path("/foo") # end # # # GET / # "./foo" # # # GET /bar # "./foo" # # # GET /bar/ # "../foo" # # # GET /bar/baz/quux # "../../foo" # # It also offers a relative_prefix method that returns a string that can # be prepended to an absolute path. This can be more efficient if you # need to convert multiple paths. # # This plugin is mostly designed for applications using Roda as a static # site generator, where the generated site can be hosted at any subpath. module RelativePath module InstanceMethods # Return a relative path for the absolute path based on the current path # of the request by adding the appropriate prefix. def relative_path(absolute_path) relative_prefix + absolute_path end # Return a relative prefix to append to an absolute path to a relative path # based on the current path of the request. def relative_prefix return @_relative_prefix if @_relative_prefix env = @_request.env script_name = env["SCRIPT_NAME"] path_info = env["PATH_INFO"] # Check path begins with slash. All valid paths should, but in case this # request is bad, just skip using a relative prefix. case script_name.getbyte(0) when nil # SCRIPT_NAME empty unless path_info.getbyte(0) == 47 # PATH_INFO starts with / return(@_relative_prefix = '') end when 47 # SCRIPT_NAME starts with / # nothing else return(@_relative_prefix = '') end slash_count = script_name.count('/') + path_info.count('/') @_relative_prefix = if slash_count > 1 ("../" * (slash_count - 2)) << ".." else "." end end end end register_plugin(:relative_path, RelativePath) end end