module Sprockets::Utils
def benchmark_end(start_time)
def benchmark_end(start_time) ((Time.now.to_f - start_time) * 1000).to_i end
def benchmark_start
def benchmark_start Time.now.to_f end
def concat_javascript_sources(buf, source)
asset - Asset
buf - String memo
semicolon if necessary.
Internal: Accumulate asset source to buffer and append a trailing
def concat_javascript_sources(buf, source) if string_end_with_semicolon?(buf) buf + source else buf + ";\n" + source end end
def dfs(initial)
node - Current node to get children of
block -
initial - Initial Array of nodes to traverse.
Used for resolving asset dependencies.
Internal: Post-order Depth-First search algorithm.
def dfs(initial) nodes, seen = Set.new, Set.new stack = Array(initial).reverse while node = stack.pop if seen.include?(node) nodes.add(node) else seen.add(node) stack.push(node) stack.concat(Array(yield node).reverse) end end nodes end
def hexdigest(obj)
obj - A JSON serializable object.
Internal: Generate a hexdigest for a nested JSON serializable object.
def hexdigest(obj) digest = Digest::SHA1.new queue = [obj] while queue.length > 0 obj = queue.shift klass = obj.class if klass == String digest << 'String' digest << obj elsif klass == Symbol digest << 'Symbol' digest << obj.to_s elsif klass == Fixnum digest << 'Fixnum' digest << obj.to_s elsif klass == TrueClass digest << 'TrueClass' elsif klass == FalseClass digest << 'FalseClass' elsif klass == NilClass digest << 'NilClass' elsif klass == Array digest << 'Array' queue.concat(obj) elsif klass == Hash digest << 'Hash' queue.concat(obj.sort) elsif klass == Set digest << 'Set' queue.concat(obj.to_a) elsif klass == Encoding digest << 'Encoding' digest << obj.name else raise TypeError, "couldn't digest #{klass}" end end digest.hexdigest end
def module_include(base, mod)
mod - Module
Internal: Inject into target module for the duration of the block.
def module_include(base, mod) old_methods = {} mod.instance_methods.each do |sym| old_methods[sym] = base.instance_method(sym) if base.method_defined?(sym) end unless UNBOUND_METHODS_BIND_TO_ANY_OBJECT base.send(:include, mod) unless base < mod end mod.instance_methods.each do |sym| method = mod.instance_method(sym) base.send(:define_method, sym, method) end yield ensure mod.instance_methods.each do |sym| base.send(:undef_method, sym) if base.method_defined?(sym) end old_methods.each do |sym, method| base.send(:define_method, sym, method) end end
def normalize_extension(extension)
# => ".css"
normalize_extension(".css")
# => ".js"
normalize_extension("js")
Internal: Prepends a leading "." to an extension if its missing.
def normalize_extension(extension) extension = extension.to_s if extension[/^\./] extension else ".#{extension}" end end
def string_end_with_semicolon?(str)
str - String
Internal: Check if string has a trailing semicolon.
def string_end_with_semicolon?(str) i = str.size - 1 while i >= 0 c = str[i] i -= 1 if c == "\n" || c == " " || c == "\t" next elsif c != ";" return false else return true end end true end