Module: Sprockets::Utils
- Extended by:
- Utils
- Included in:
- Compressing, Configuration, Engines, Mime, Paths, Processing, Transformers, Utils
- Defined in:
- lib/sprockets/utils.rb
Overview
Internal: Utils, we didn’t know where else to put it! Functions may eventually be shuffled into more specific drawers.
Constant Summary collapse
- UNBOUND_METHODS_BIND_TO_ANY_OBJECT =
Internal: Feature detect if UnboundMethods can #bind to any Object or just Objects that share the same super class. Basically if RUBY_VERSION >= 2.
begin foo = Module.new { def ; end } foo.instance_method(:bar).bind(Object.new) true rescue TypeError false end
Instance Method Summary collapse
-
#concat_javascript_sources(buf, source) ⇒ Object
Internal: Accumulate asset source to buffer and append a trailing semicolon if necessary.
-
#dfs(initial) ⇒ Object
Internal: Post-order Depth-First search algorithm.
-
#dfs_paths(path) ⇒ Object
Internal: Post-order Depth-First search algorithm that gathers all paths along the way.
-
#duplicable?(obj) ⇒ Boolean
Internal: Check if object can safely be .dup’d.
-
#hash_reassoc(hash, *keys, &block) ⇒ Object
Internal: Duplicate and store key/value on new frozen hash.
-
#hash_reassoc1(hash, key) ⇒ Object
Internal: Duplicate and store key/value on new frozen hash.
-
#module_include(base, mod) ⇒ Object
Internal: Inject into target module for the duration of the block.
-
#normalize_extension(extension) ⇒ Object
Internal: Prepends a leading “.” to an extension if its missing.
-
#string_end_with_semicolon?(str) ⇒ Boolean
Internal: Check if string has a trailing semicolon.
Instance Method Details
#concat_javascript_sources(buf, source) ⇒ Object
Internal: Accumulate asset source to buffer and append a trailing semicolon if necessary.
buf - String buffer to append to source - String source to append
Returns buf String.
97 98 99 100 101 102 103 |
# File 'lib/sprockets/utils.rb', line 97 def concat_javascript_sources(buf, source) if string_end_with_semicolon?(buf) buf << source else buf << ";\n" << source end end |
#dfs(initial) ⇒ Object
Internal: Post-order Depth-First search algorithm.
Used for resolving asset dependencies.
initial - Initial Array of nodes to traverse. block -
node - Current node to get children of
Returns a Set of nodes.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/sprockets/utils.rb', line 173 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 |
#dfs_paths(path) ⇒ Object
Internal: Post-order Depth-First search algorithm that gathers all paths along the way.
TODO: Rename function.
path - Initial Array node path block -
node - Current node to get children of
Returns an Array of node Arrays.
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/sprockets/utils.rb', line 200 def dfs_paths(path) paths = [] stack, seen = [path], Set.new while path = stack.pop if !seen.include?(path.last) seen.add(path.last) paths << path if path.size > 1 Array(yield path.last).reverse_each do |node| stack.push(path + [node]) end end end paths end |
#duplicable?(obj) ⇒ Boolean
Internal: Check if object can safely be .dup’d.
Similar to ActiveSupport #duplicable? check.
obj - Any Object
Returns false if .dup would raise a TypeError, otherwise true.
16 17 18 19 20 21 22 23 |
# File 'lib/sprockets/utils.rb', line 16 def duplicable?(obj) case obj when NilClass, FalseClass, TrueClass, Symbol, Numeric false else true end end |
#hash_reassoc(hash, *keys, &block) ⇒ Object
Internal: Duplicate and store key/value on new frozen hash.
Similar to Hash#store for nested frozen hashes.
hash - Hash key - Object keys. Use multiple keys for nested hashes. block - Receives current value at key.
Examples
config = {paths: ["/bin", "/sbin"]}.freeze
new_config = hash_reassoc(config, :paths) do |paths|
paths << "/usr/local/bin"
end
Returns duplicated frozen Hash.
59 60 61 62 63 64 65 66 67 |
# File 'lib/sprockets/utils.rb', line 59 def hash_reassoc(hash, *keys, &block) if keys.size == 1 hash_reassoc1(hash, keys[0], &block) else hash_reassoc1(hash, keys[0]) do |value| hash_reassoc(value, *keys[1..-1], &block) end end end |
#hash_reassoc1(hash, key) ⇒ Object
Internal: Duplicate and store key/value on new frozen hash.
Seperated for recursive calls, always use hash_reassoc(hash, *keys).
hash - Hash key - Object key
Returns Hash.
33 34 35 36 37 38 39 40 41 |
# File 'lib/sprockets/utils.rb', line 33 def hash_reassoc1(hash, key) hash = hash.dup if hash.frozen? old_value = hash[key] old_value = old_value.dup if duplicable?(old_value) new_value = yield old_value new_value.freeze if duplicable?(new_value) hash.store(key, new_value) hash.freeze end |
#module_include(base, mod) ⇒ Object
Internal: Inject into target module for the duration of the block.
mod - Module
Returns result of block.
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/sprockets/utils.rb', line 138 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 |
#normalize_extension(extension) ⇒ Object
Internal: Prepends a leading “.” to an extension if its missing.
normalize_extension("js")
# => ".js"
normalize_extension(".css")
# => ".css"
113 114 115 116 117 118 119 120 |
# File 'lib/sprockets/utils.rb', line 113 def normalize_extension(extension) extension = extension.to_s if extension[/^\./] extension else ".#{extension}" end end |
#string_end_with_semicolon?(str) ⇒ Boolean
Internal: Check if string has a trailing semicolon.
str - String
Returns true or false.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/sprockets/utils.rb', line 74 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 |