1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
require 'mustermann'
require 'mustermann/expander'
module Mustermann
# A mapper allows mapping one string to another based on pattern parsing and expanding.
#
# @example
# require 'mustermann/mapper'
# mapper = Mustermann::Mapper.new("/:foo" => "/:foo.html")
# mapper['/example'] # => "/example.html"
class Mapper
# Creates a new mapper.
#
# @overload initialize(**options)
# @param options [Hash] options The options hash
# @yield block for generating mappings as a hash
# @yieldreturn [Hash] see {#update}
#
# @example
# require 'mustermann/mapper'
# Mustermann::Mapper.new(type: :rails) {{
# "/:foo" => ["/:foo.html", "/:foo.:format"]
# }}
#
# @overload initialize(**options)
# @param options [Hash] options The options hash
# @yield block for generating mappings as a hash
# @yieldparam mapper [Mustermann::Mapper] the mapper instance
#
# @example
# require 'mustermann/mapper'
# Mustermann::Mapper.new(type: :rails) do |mapper|
# mapper["/:foo"] = ["/:foo.html", "/:foo.:format"]
# end
#
# @overload initialize(map = {}, **options)
# @param map [Hash] see {#update}
# @param [Hash] options The options hash
#
# @example map before options
# require 'mustermann/mapper'
# Mustermann::Mapper.new("/:foo" => "/:foo.html", type: :rails)
#
# @example map after options
# require 'mustermann/mapper'
# Mustermann::Mapper.new(type: :rails, "/:foo" => "/:foo.html")
def initialize(options = {}, &block)
@map = []
@additional_values = options.delete(:additional_values) || :ignore
@options = options
map = @options.inject({}) do |result, entry|
result[entry[0]] = @options.delete(entry[0]) if entry[0].is_a?(String)
result
end
block.arity == 0 ? update(yield) : yield(self) if block
update(map) if map
end
# Add multiple mappings.
#
# @param map [Hash{String, Pattern: String, Pattern, Arry<String, Pattern>, Expander}] the mapping
def update(map)
map.to_hash.each_pair do |input, output|
input = Mustermann.new(input, @options.dup)
output = Expander.new(*output, @options.merge(additional_values: @additional_values)) unless output.is_a? Expander
@map << [input, output]
end
end
# @return [Hash{Patttern: Expander}] Hash version of the mapper.
def to_h
Hash[@map]
end
# Convert a string according to mappings. You can pass in additional params.
#
# @example mapping with and without additional parameters
# mapper = Mustermann::Mapper.new("/:example" => "(/:prefix)?/:example.html")
#
def convert(input, values = {})
@map.inject(input) do |current, (pattern, expander)|
params = pattern.params(current)
params &&= Hash[values.merge(params).map { |k,v| [k.to_s, v] }]
expander.expandable?(params) ? expander.expand(params) : current
end
end
# Add a single mapping.
#
# @param key [String, Pattern] format of the input string
# @param value [String, Pattern, Arry<String, Pattern>, Expander] format of the output string
def []=(key, value)
update key => value
end
alias_method :[], :convert
end
end
|