| require 'delegate' |
| |
| module Sass |
| module Util |
| # A hash that normalizes its string keys while still allowing you to get back |
| # to the original keys that were stored. If several different values normalize |
| # to the same value, whichever is stored last wins. |
| class NormalizedMap |
| # Create a normalized map |
| def initialize(map = nil) |
| @key_strings = {} |
| @map = {} |
| |
| map.each {|key, value| self[key] = value} if map |
| end |
| |
| # Specifies how to transform the key. |
| # |
| # This can be overridden to create other normalization behaviors. |
| def normalize(key) |
| key.tr("-", "_") |
| end |
| |
| # Returns the version of `key` as it was stored before |
| # normalization. If `key` isn't in the map, returns it as it was |
| # passed in. |
| # |
| # @return [String] |
| def denormalize(key) |
| @key_strings[normalize(key)] || key |
| end |
| |
| # @private |
| def []=(k, v) |
| normalized = normalize(k) |
| @map[normalized] = v |
| @key_strings[normalized] = k |
| v |
| end |
| |
| # @private |
| def [](k) |
| @map[normalize(k)] |
| end |
| |
| # @private |
| def has_key?(k) |
| @map.has_key?(normalize(k)) |
| end |
| |
| # @private |
| def delete(k) |
| normalized = normalize(k) |
| @key_strings.delete(normalized) |
| @map.delete(normalized) |
| end |
| |
| # @return [Hash] Hash with the keys as they were stored (before normalization). |
| def as_stored |
| Sass::Util.map_keys(@map) {|k| @key_strings[k]} |
| end |
| |
| def empty? |
| @map.empty? |
| end |
| |
| def values |
| @map.values |
| end |
| |
| def keys |
| @map.keys |
| end |
| |
| def each |
| @map.each {|k, v| yield(k, v)} |
| end |
| |
| def size |
| @map.size |
| end |
| |
| def to_hash |
| @map.dup |
| end |
| |
| def to_a |
| @map.to_a |
| end |
| |
| def map |
| @map.map {|k, v| yield(k, v)} |
| end |
| |
| def dup |
| d = super |
| d.send(:instance_variable_set, "@map", @map.dup) |
| d |
| end |
| |
| def sort_by |
| @map.sort_by {|k, v| yield k, v} |
| end |
| |
| def update(map) |
| map = map.as_stored if map.is_a?(NormalizedMap) |
| map.each {|k, v| self[k] = v} |
| end |
| |
| def method_missing(method, *args, &block) |
| if Sass.tests_running |
| raise ArgumentError.new("The method #{method} must be implemented explicitly") |
| end |
| @map.send(method, *args, &block) |
| end |
| |
| def respond_to_missing?(method, include_private = false) |
| @map.respond_to?(method, include_private) |
| end |
| end |
| end |
| end |