module Sass::Util

def _enc(string, encoding)

Other tags:
    Private: -
def _enc(string, encoding)
  string.encode(encoding).force_encoding("BINARY")
end

def abstract(obj)

Raises:
  • (NotImplementedError) -

Parameters:
  • obj (Object) -- `self`
def abstract(obj)
  raise NotImplementedError.new("#{obj.class} must implement ##{caller_info[2]}")
end

def ap_geq?(version)

Returns:
  • (Boolean) -

Parameters:
  • version (String) -- The string version number to check against.
def ap_geq?(version)
  # The ActionPack module is always loaded automatically in Rails >= 3
  return false unless defined?(ActionPack) && defined?(ActionPack::VERSION) &&
    defined?(ActionPack::VERSION::STRING)
  version_geq(ActionPack::VERSION::STRING, version)
end

def ap_geq_3?

Returns:
  • (Boolean) -
def ap_geq_3?
  ap_geq?("3.0.0.beta1")
end

def av_template_class(name)

Parameters:
  • name (#to_s) -- The name of the class to get.
def av_template_class(name)
  return ActionView.const_get("Template#{name}") if ActionView.const_defined?("Template#{name}")
  return ActionView::Template.const_get(name.to_s)
end

def caller_info(entry = caller[1])

Returns:
  • ([String, Fixnum, (String, nil)]) - An array containing the filename, line, and method name of the caller.

Parameters:
  • entry (String) -- An entry in the `#caller` list, or a similarly formatted string
def caller_info(entry = caller[1])
  info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
  info[1] = info[1].to_i
  # This is added by Rubinius to designate a block, but we don't care about it.
  info[2].sub!(/ \{\}\Z/, '') if info[2]
  info
end

def check_encoding(str)

Returns:
  • (String) - `str`, potentially with encoding gotchas like BOMs removed

Other tags:
    Yieldparam: msg - The error message to be raised

Other tags:
    Yield: - A block in which an encoding error can be raised.

Parameters:
  • str (String) -- The string of which to check the encoding
def check_encoding(str)
  if ruby1_8?
    return str.gsub(/\A\xEF\xBB\xBF/, '') # Get rid of the UTF-8 BOM
  elsif str.valid_encoding?
    # Get rid of the Unicode BOM if possible
    if str.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?$/
      return str.gsub(Regexp.new("\\A\uFEFF".encode(str.encoding.name)), '')
    else
      return str
    end
  end
  encoding = str.encoding
  newlines = Regexp.new("\r\n|\r|\n".encode(encoding).force_encoding("binary"))
  str.force_encoding("binary").split(newlines).each_with_index do |line, i|
    begin
      line.encode(encoding)
    rescue Encoding::UndefinedConversionError => e
      yield <<MSG.rstrip, i + 1
lid #{encoding.name} character #{e.error_char.dump}
    end
  end
  return str
end

def check_sass_encoding(str, &block)

Raises:
  • (ArgumentError) - if the document uses an unknown encoding with `@charset`
  • (Encoding::UndefinedConversionError) - if the source encoding

Returns:
  • ((String, Encoding)) - The original string encoded as UTF-8,

Other tags:
    Yieldparam: msg - The error message to be raised

Other tags:
    Yield: - A block in which an encoding error can be raised.

Parameters:
  • str (String) -- The string of which to check the encoding
def check_sass_encoding(str, &block)
  return check_encoding(str, &block), nil if ruby1_8?
  # We allow any printable ASCII characters but double quotes in the charset decl
  bin = str.dup.force_encoding("BINARY")
  encoding = Sass::Util::ENCODINGS_TO_CHECK.find do |enc|
    re = Sass::Util::CHARSET_REGEXPS[enc]
    re && bin =~ re
  end
  charset, bom = $1, $2
  if charset
    charset = charset.force_encoding(encoding).encode("UTF-8")
    if endianness = encoding[/[BL]E$/]
      begin
        Encoding.find(charset + endianness)
        charset << endianness
      rescue ArgumentError # Encoding charset + endianness doesn't exist
      end
    end
    str.force_encoding(charset)
  elsif bom
    str.force_encoding(encoding)
  end
  str = check_encoding(str, &block)
  return str.encode("UTF-8"), str.encoding
end

def enum_cons(enum, n)

Returns:
  • (Enumerator) - The consed enumerator

Parameters:
  • n (Fixnum) -- The size of each cons
  • enum (Enumerable) -- The enumerable to get the enumerator for
def enum_cons(enum, n)
  ruby1_8? ? enum.enum_cons(n) : enum.each_cons(n)
end

def enum_slice(enum, n)

Returns:
  • (Enumerator) - The consed enumerator

Parameters:
  • n (Fixnum) -- The size of each slice
  • enum (Enumerable) -- The enumerable to get the enumerator for
def enum_slice(enum, n)
  ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
end

def enum_with_index(enum)

Returns:
  • (Enumerator) - The with-index enumerator

Parameters:
  • enum (Enumerable) -- The enumerable to get the enumerator for
def enum_with_index(enum)
  ruby1_8? ? enum.enum_with_index : enum.each_with_index
end

def extract_values(arr)

Returns:
  • ((String, Array)) - The resulting string, and an array of extracted values.

Parameters:
  • arr (Array) -- The array from which values are extracted.
def extract_values(arr)
  values = []
  return arr.map do |e|
    next e.gsub('{', '{{') if e.is_a?(String)
    values << e
    next "{#{values.count - 1}}"
  end.join, values
end

def flatten(arr, n)

Returns:
  • (Array) - The flattened array

Parameters:
  • n (Fixnum) -- The number of levels to flatten
  • arr (Array) -- The array to flatten
def flatten(arr, n)
  return arr.flatten(n) unless ruby1_8_6?
  return arr if n == 0
  arr.inject([]) {|res, e| e.is_a?(Array) ? res.concat(flatten(e, n - 1)) : res << e}
end

def has?(attr, klass, method)

Returns:
  • (Boolean) - Whether or not the given collection has the given method

Parameters:
  • method (String, Symbol) -- The name of the method do check for
  • klass (Module) -- The class to check the methods of which to check
  • attr (#to_s) -- The (singular) name of the method-collection method
def has?(attr, klass, method)
  klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
end

def inject_values(str, values)

Returns:
  • (Array) - The array of strings and values.

Parameters:
  • values (Array) -- The array of values to inject.
  • str (String) -- The string with escape sequences.
def inject_values(str, values)
  return [str.gsub('{{', '{')] if values.empty?
  # Add an extra { so that we process the tail end of the string
  result = (str + '{{').scan(/(.*?)(?:(\{\{)|\{(\d+)\})/m).map do |(pre, esc, n)|
    [pre, esc ? '{' : '', n ? values[n.to_i] : '']
  end.flatten(1)
  result[-2] = '' # Get rid of the extra {
  merge_adjacent_strings(result).reject {|s| s == ''}
end

def inspect_obj(obj)

Returns:
  • (String) -

Parameters:
  • obj (Object) --
def inspect_obj(obj)
  return obj.inspect unless version_geq(::RUBY_VERSION, "1.9.2")
  return ':' + inspect_obj(obj.to_s) if obj.is_a?(Symbol)
  return obj.inspect unless obj.is_a?(String)
  '"' + obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]} + '"'
end

def intersperse(enum, val)

Returns:
  • (Array) -

Parameters:
  • val () --
  • enum (Enumerable) --
def intersperse(enum, val)
  enum.inject([]) {|a, e| a << e << val}[0...-1]
end

def ironruby?

Returns:
  • (Boolean) -
def ironruby?
  RUBY_ENGINE == "ironruby"
end

def lcs(x, y, &block)

Returns:
  • (Array) - The LCS

Other tags:
    Yieldreturn: - If the two values register as equal,

Other tags:
    Yield: - An optional block to use in place of a check for equality

Parameters:
  • y (Array) --
  • x (Array) --
def lcs(x, y, &block)
  x = [nil, *x]
  y = [nil, *y]
  block ||= proc {|a, b| a == b && a}
  lcs_backtrace(lcs_table(x, y, &block), x, y, x.size-1, y.size-1, &block)
end

def lcs_backtrace(c, x, y, i, j, &block)

Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Reading_out_an_LCS)
Computes a single longest common subsequence for arrays x and y.
def lcs_backtrace(c, x, y, i, j, &block)
  return [] if i == 0 || j == 0
  if v = yield(x[i], y[j])
    return lcs_backtrace(c, x, y, i-1, j-1, &block) << v
  end
  return lcs_backtrace(c, x, y, i, j-1, &block) if c[i][j-1] > c[i-1][j]
  return lcs_backtrace(c, x, y, i-1, j, &block)
end

def lcs_table(x, y)

Algorithm from [Wikipedia](http://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Computing_the_length_of_the_LCS)
Calculates the memoization table for the Least Common Subsequence algorithm.
def lcs_table(x, y)
  c = Array.new(x.size) {[]}
  x.size.times {|i| c[i][0] = 0}
  y.size.times {|j| c[0][j] = 0}
  (1...x.size).each do |i|
    (1...y.size).each do |j|
      c[i][j] =
        if yield x[i], y[j]
          c[i-1][j-1] + 1
        else
          [c[i][j-1], c[i-1][j]].max
        end
    end
  end
  return c
end

def map_hash(hash, &block)

Other tags:
    See: #map_vals -
    See: #map_keys -

Returns:
  • (Hash) - The mapped hash

Other tags:
    Yieldreturn: - The new value for the `[key, value]` pair

Other tags:
    Yieldparam: The - hash value
    Yieldparam: The - hash key

Other tags:
    Yield: - A block in which the key-value pairs are transformed

Parameters:
  • hash (Hash) -- The hash to map
def map_hash(hash, &block)
  to_hash(hash.map(&block))
end

def map_keys(hash)

Other tags:
    See: #map_hash -
    See: #map_vals -

Returns:
  • (Hash) - The mapped hash

Other tags:
    Yieldreturn: - The new value for the key

Other tags:
    Yieldparam: key - The key that should be mapped

Other tags:
    Yield: - A block in which the keys are transformed

Parameters:
  • hash (Hash) -- The hash to map
def map_keys(hash)
  to_hash(hash.map {|k, v| [yield(k), v]})
end

def map_vals(hash)

Other tags:
    See: #map_hash -
    See: #map_keys -

Returns:
  • (Hash) - The mapped hash

Other tags:
    Yieldreturn: - The new value for the value

Other tags:
    Yieldparam: value - The value that should be mapped

Other tags:
    Yield: - A block in which the values are transformed

Parameters:
  • hash (Hash) -- The hash to map
def map_vals(hash)
  to_hash(hash.map {|k, v| [k, yield(v)]})
end

def merge_adjacent_strings(arr)

Returns:
  • (Array) - The enumerable with strings merged

Parameters:
  • arr (Array) --
def merge_adjacent_strings(arr)
  # Optimize for the common case of one element
  return arr if arr.size < 2
  arr.inject([]) do |a, e|
    if e.is_a?(String)
      if a.last.is_a?(String)
        a.last << e
      else
        a << e.dup
      end
    else
      a << e
    end
    a
  end
end

def ord(c)

Returns:
  • (Fixnum) - The ASCII code of `c`.

Parameters:
  • c (String) -- All characters but the first are ignored.
def ord(c)
  ruby1_8? ? c[0] : c.ord
end

def paths(arrs)

Returns:
  • (Array) -

Parameters:
  • arrs (Array) --
def paths(arrs)
  arrs.inject([[]]) do |paths, arr|
    flatten(arr.map {|e| paths.map {|path| path + [e]}}, 1)
  end
end

def powerset(arr)

Returns:
  • (Set) - The subsets of `arr`

Parameters:
  • arr (Enumerable) --
def powerset(arr)
  arr.inject([Set.new].to_set) do |powerset, el|
    new_powerset = Set.new
    powerset.each do |subset|
      new_powerset << subset
      new_powerset << subset + [el]
    end
    new_powerset
  end
end

def rails_env

Returns:
  • (String, nil) -
def rails_env
  return ::Rails.env.to_s if defined?(::Rails.env)
  return RAILS_ENV.to_s if defined?(RAILS_ENV)
  return nil
end

def rails_root

Returns:
  • (String, nil) -
def rails_root
  if defined?(::Rails.root)
    return ::Rails.root.to_s if ::Rails.root
    raise "ERROR: Rails.root is nil!"
  end
  return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
  return nil
end

def restrict(value, range)

Returns:
  • (Numeric) -

Parameters:
  • range (Range) --
  • value (Numeric) --
def restrict(value, range)
  [[value, range.first].max, range.last].min
end

def ruby1_8?

Returns:
  • (Boolean) -
def ruby1_8?
  # IronRuby says its version is 1.9, but doesn't support any of the encoding APIs.
  # We have to fall back to 1.8 behavior.
  ironruby? || (Sass::Util::RUBY_VERSION[0] == 1 && Sass::Util::RUBY_VERSION[1] < 9)
end

def ruby1_8_6?

Returns:
  • (Boolean) -
def ruby1_8_6?
  ruby1_8? && Sass::Util::RUBY_VERSION[2] < 7
end

def sass_warn(msg)

Parameters:
  • msg (String) --
def sass_warn(msg)
  Sass.logger.warn(msg)
end

def scope(file)

Returns:
  • (String) - The filename relative to the the working directory

Parameters:
  • file (String) -- The filename relative to the Sass root
def scope(file)
  File.join(Sass::ROOT_DIR, file)
end

def set_eql?(set1, set2)

Returns:
  • (Boolean) - Whether or not the sets are hashcode equal

Parameters:
  • set2 (Set) --
  • set1 (Set) --
def set_eql?(set1, set2)
  return set1.eql?(set2) unless ruby1_8_6?
  set1.to_a.uniq.sort_by {|e| e.hash}.eql?(set2.to_a.uniq.sort_by {|e| e.hash})
end

def set_hash(set)

Returns:
  • (Fixnum) - The order-independent hashcode of `set`

Parameters:
  • set (Set) --
def set_hash(set)
  return set.hash unless ruby1_8_6?
  set.map {|e| e.hash}.uniq.sort.hash
end

def silence_sass_warnings

Other tags:
    Yield: - A block in which no Sass warnings will be printed
def silence_sass_warnings
  old_level, Sass.logger.log_level = Sass.logger.log_level, :error
  yield
ensure
  Sass.logger.log_level = old_level
end

def silence_warnings

Other tags:
    Yield: - A block in which no output will be printed to STDERR
def silence_warnings
  the_real_stderr, $stderr = $stderr, StringIO.new
  yield
ensure
  $stderr = the_real_stderr
end

def strip_string_array(arr)

Returns:
  • (Array) - `arr`

Parameters:
  • arr (Array) --
def strip_string_array(arr)
  arr.first.lstrip! if arr.first.is_a?(String)
  arr.last.rstrip! if arr.last.is_a?(String)
  arr
end

def substitute(ary, from, to)

Parameters:
  • to (Array) -- The sequence of elements to replace `from` with
  • from (Array) -- The sequence of elements to replace with `to`
  • ary (Array) -- The array in which to make the substitution
def substitute(ary, from, to)
  res = ary.dup
  i = 0
  while i < res.size
    if res[i...i+from.size] == from
      res[i...i+from.size] = to
    end
    i += 1
  end
  res
end

def to_hash(arr)

Returns:
  • (Hash) - A hash

Parameters:
  • arr (Array<(Object, Object)>) -- An array of pairs
def to_hash(arr)
  Hash[arr.compact]
end

def version_geq(v1, v2)

Returns:
  • (Boolean) -

Parameters:
  • v2 (String) -- Another version string.
  • v1 (String) -- A version string.
def version_geq(v1, v2)
  version_gt(v1, v2) || !version_gt(v2, v1)
end

def version_gt(v1, v2)

Returns:
  • (Boolean) -

Parameters:
  • v2 (String) -- Another version string.
  • v1 (String) -- A version string.
def version_gt(v1, v2)
  # Construct an array to make sure the shorter version is padded with nil
  Array.new([v1.length, v2.length].max).zip(v1.split("."), v2.split(".")) do |_, p1, p2|
    p1 ||= "0"
    p2 ||= "0"
    release1 = p1 =~ /^[0-9]+$/
    release2 = p2 =~ /^[0-9]+$/
    if release1 && release2
      # Integer comparison if both are full releases
      p1, p2 = p1.to_i, p2.to_i
      next if p1 == p2
      return p1 > p2
    elsif !release1 && !release2
      # String comparison if both are prereleases
      next if p1 == p2
      return p1 > p2
    else
      # If only one is a release, that one is newer
      return release1
    end
  end
end

def windows?

Returns:
  • (Boolean) -
def windows?
  RbConfig::CONFIG['host_os'] =~ /mswin|windows|mingw/i
end

def with_extracted_values(arr)

Returns:
  • (Array) - The modified, interpolated array.

Other tags:
    Yieldreturn: - The modified string.

Other tags:
    Yieldparam: str - The string form of `arr`.

Other tags:
    Yield: - A block in which string manipulation can be done to the array.

Parameters:
  • arr (Array) -- The array from which values are extracted.
def with_extracted_values(arr)
  str, vals = extract_values(arr)
  str = yield str
  inject_values(str, vals)
end