| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- require 'uri'
- require 'pathname'
- module Docs
- class URL < URI::Generic
- PARSER = URI::Parser.new
- def initialize(*args)
- if args.empty?
- super(*Array.new(9))
- elsif args.length == 1 && args.first.is_a?(Hash)
- args.first.assert_valid_keys URI::Generic::COMPONENT
- super(*args.first.values_at(*URI::Generic::COMPONENT))
- else
- super
- end
- end
- def self.parse(url)
- return url if url.kind_of? self
- new(*PARSER.split(url), PARSER)
- end
- def self.join(*args)
- PARSER.join(*args)
- end
- def join(*args)
- self.class.join self, *args
- end
- def merge!(hash)
- return super unless hash.is_a? Hash
- hash.assert_valid_keys URI::Generic::COMPONENT
- hash.each_pair do |key, value|
- send "#{key}=", value
- end
- self
- end
- def merge(hash)
- return super unless hash.is_a? Hash
- dup.merge!(hash)
- end
- def origin
- if scheme && host
- origin = "#{scheme}://#{host}"
- origin.downcase!
- origin << ":#{port}" if port
- origin
- else
- nil
- end
- end
- def normalized_path
- path == '' ? '/' : path
- end
- def subpath_to(url, options = nil)
- url = self.class.parse(url)
- return unless origin == url.origin
- base = path
- dest = url.path
- if options && options[:ignore_case]
- base = base.downcase
- dest = dest.downcase
- end
- if base == dest
- ''
- elsif dest.start_with?(::File.join(base, ''))
- url.path[(path.length)..-1]
- end
- end
- def subpath_from(url, options = nil)
- self.class.parse(url).subpath_to(self, options)
- end
- def contains?(url, options = nil)
- !!subpath_to(url, options)
- end
- def relative_path_to(url)
- url = self.class.parse(url)
- return unless origin == url.origin
- base_dir = Pathname.new(normalized_path)
- base_dir = base_dir.parent unless path.end_with? '/'
- dest = url.normalized_path
- dest_dir = Pathname.new(dest)
- if dest.end_with? '/'
- dest_dir.relative_path_from(base_dir).to_s.tap do |result|
- result << '/' if result != '.'
- end
- else
- dest_dir.parent.relative_path_from(base_dir).join(dest.split('/').last).to_s
- end
- end
- def relative_path_from(url)
- self.class.parse(url).relative_path_to(self)
- end
- end
- end
|