Module: Haml::Util
- Extended by:
- Util
- Included in:
- Buffer, Util, Version, Sass::Engine, Sass::Plugin, Sass::Script::Color
- Defined in:
- lib/haml/util.rb,
lib/haml/util/subset_map.rb
Overview
A module containing various useful functions.
Defined Under Namespace
Classes: StaticConditionalContext, SubsetMap
Constant Summary collapse
- RUBY_VERSION =
An array of ints representing the Ruby version number.
::RUBY_VERSION.split(".").map {|s| s.to_i}
- @@silence_warnings =
false
Instance Method Summary collapse
-
#ap_geq_3? ⇒ Boolean
Returns whether this environment is using ActionPack version 3.0.0 or greater.
-
#ap_geq_3_beta_3? ⇒ Boolean
Returns whether this environment is using ActionPack version 3.0.0.beta.3 or greater.
-
#assert_html_safe!(text)
Assert that a given object (usually a String) is HTML safe according to Rails' XSS handling, if it's loaded.
-
#av_template_class(name)
Returns an ActionView::Template* class.
-
#caller_info(entry = ) ⇒ [String, Fixnum, (String, nil)]
Returns information about the caller of the previous method.
-
#check_encoding(str) {|msg| ... } ⇒ String
Checks that the encoding of a string is valid in Ruby 1.9 and cleans up potential encoding gotchas like the UTF-8 BOM.
-
#def_static_method(klass, name, args, *vars, erb)
This is used for methods in Buffer that need to be very fast, and take a lot of boolean parameters that are known at compile-time.
-
#enum_cons(enum, n) ⇒ Enumerator
A version of
Enumerable#enum_cons
that works in Ruby 1.8 and 1.9. -
#enum_slice(enum, n) ⇒ Enumerator
A version of
Enumerable#enum_slice
that works in Ruby 1.8 and 1.9. -
#enum_with_index(enum) ⇒ Enumerator
A version of
Enumerable#enum_with_index
that works in Ruby 1.8 and 1.9. -
#flatten(arr, n) ⇒ Array
Flattens the first
n
nested arrays in a cross-version manner. -
#haml_warn(msg)
The same as
Kernel#warn
, but is silenced by #silence_haml_warnings. -
#has?(attr, klass, method) ⇒ Boolean
Checks to see if a class has a given method.
-
#html_safe(text) ⇒ String?
Returns the given text, marked as being HTML-safe.
-
#intersperse(enum, val) ⇒ Array
Intersperses a value in an enumerable, as would be done with
Array#join
but without concatenating the array together afterwards. -
#map_hash(hash) {|key, value| ... } ⇒ Hash
Maps the key-value pairs of a hash according to a block.
-
#map_keys(hash) {|key| ... } ⇒ Hash
Maps the keys in a hash according to a block.
-
#map_vals(hash) {|value| ... } ⇒ Hash
Maps the values in a hash according to a block.
-
#merge_adjacent_strings(enum) ⇒ Array
Concatenates all strings that are adjacent in an array, while leaving other elements as they are.
-
#ord(c) ⇒ Fixnum
Returns the ASCII code of the given character.
-
#paths(arrs) ⇒ Array<Arrays>
Return an array of all possible paths through the given arrays.
-
#powerset(arr) ⇒ Set<Set>
Computes the powerset of the given array.
-
#rails_env ⇒ String?
Returns the environment of the Rails application, if this is running in a Rails context.
-
#rails_root ⇒ String?
Returns the root of the Rails application, if this is running in a Rails context.
-
#rails_safe_buffer_class ⇒ Class
The class for the Rails SafeBuffer XSS protection class.
-
#rails_xss_safe? ⇒ Boolean
Whether or not ActionView's XSS protection is available and enabled, as is the default for Rails 3.0+, and optional for version 2.3.5+.
-
#restrict(value, range) ⇒ Numeric
Restricts a number to falling within a given range.
-
#ruby1_8? ⇒ Boolean
Whether or not this is running under Ruby 1.8 or lower.
-
#ruby1_8_6? ⇒ Boolean
Whether or not this is running under Ruby 1.8.6 or lower.
-
#scope(file) ⇒ String
Returns the path of a file relative to the Haml root directory.
-
#set_eql?(set1, set2) ⇒ Boolean
Tests the hash-equality of two sets in a cross-version manner.
-
#set_hash(set) ⇒ Fixnum
Returns the hash code for a set in a cross-version manner.
-
#silence_haml_warnings { ... }
Silences all Haml warnings within a block.
-
#silence_warnings { ... }
Silence all output to STDERR within a block.
-
#static_method_name(name, *vars) ⇒ String
Computes the name for a method defined via #def_static_method.
-
#strip_string_array(arr) ⇒ Array
Destructively strips whitespace from the beginning and end of the first and last elements, respectively, in the array (if those elements are strings).
-
#substitute(ary, from, to)
Substitutes a sub-array of one array with another sub-array.
-
#to_hash(arr) ⇒ Hash
Converts an array of
[key, value]
pairs to a hash.
Instance Method Details
#ap_geq_3? ⇒ Boolean
Returns whether this environment is using ActionPack version 3.0.0 or greater.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/haml/util.rb', line 265
def ap_geq_3?
# The ActionPack module is always loaded automatically in Rails >= 3
return false unless defined?(ActionPack) && defined?(ActionPack::VERSION)
version =
if defined?(ActionPack::VERSION::MAJOR)
ActionPack::VERSION::MAJOR
else
# Rails 1.2
ActionPack::VERSION::Major
end
version >= 3
end
|
#ap_geq_3_beta_3? ⇒ Boolean
Returns whether this environment is using ActionPack version 3.0.0.beta.3 or greater.
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/haml/util.rb', line 284
def ap_geq_3_beta_3?
# The ActionPack module is always loaded automatically in Rails >= 3
return false unless defined?(ActionPack) && defined?(ActionPack::VERSION)
version =
if defined?(ActionPack::VERSION::MAJOR)
ActionPack::VERSION::MAJOR
else
# Rails 1.2
ActionPack::VERSION::Major
end
version >= 3 &&
((defined?(ActionPack::VERSION::TINY) &&
ActionPack::VERSION::TINY.is_a?(Fixnum) &&
ActionPack::VERSION::TINY >= 1) ||
(defined?(ActionPack::VERSION::BUILD) &&
ActionPack::VERSION::BUILD =~ /beta(\d+)/ &&
$1.to_i >= 3))
end
|
#assert_html_safe!(text)
Assert that a given object (usually a String) is HTML safe according to Rails' XSS handling, if it's loaded.
344 345 346 347 |
# File 'lib/haml/util.rb', line 344
def assert_html_safe!(text)
return unless rails_xss_safe? && text && !text.to_s.html_safe?
raise Haml::Error.new("Expected #{text.inspect} to be HTML-safe.")
end
|
#av_template_class(name)
Returns an ActionView::Template* class.
In pre-3.0 versions of Rails, most of these classes
were of the form ActionView::TemplateFoo
,
while afterwards they were of the form ActionView;:Template::Foo
.
312 313 314 315 |
# File 'lib/haml/util.rb', line 312
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
|
#caller_info(entry = ) ⇒ [String, Fixnum, (String, nil)]
Returns information about the caller of the previous method.
201 202 203 204 205 |
# File 'lib/haml/util.rb', line 201
def caller_info(entry = caller[1])
info = entry.scan(/^(.*?):(-?.*?)(?::.*`(.+)')?$/).first
info[1] = info[1].to_i
info
end
|
#check_encoding(str) {|msg| ... } ⇒ String
Checks that the encoding of a string is valid in Ruby 1.9 and cleans up potential encoding gotchas like the UTF-8 BOM. If it's not, yields an error string describing the invalid character and the line on which it occurrs.
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/haml/util.rb', line 385
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
Invalid #{encoding.name} character #{e.error_char.dump}
MSG
end
end
return str
end
|
#def_static_method(klass, name, args, *vars, erb)
This is used for methods in Buffer that need to be very fast, and take a lot of boolean parameters that are known at compile-time. Instead of passing the parameters in normally, a separate method is defined for every possible combination of those parameters; these are then called using #static_method_name.
To define a static method, an ERB template for the method is provided. All conditionals based on the static parameters are done as embedded Ruby within this template. For example:
def_static_method(Foo, :my_static_method, [:foo, :bar], :baz, :bang, <<RUBY)
<% if baz && bang %>
return foo + bar
<% elsif baz || bang %>
return foo - bar
<% else %>
return 17
<% end %>
RUBY
#static_method_name can be used to call static methods.
546 547 548 549 550 551 552 553 554 555 556 557 |
# File 'lib/haml/util.rb', line 546
def def_static_method(klass, name, args, *vars)
erb = vars.pop
info = caller_info
powerset(vars).each do |set|
context = StaticConditionalContext.new(set).instance_eval {binding}
klass.class_eval(<<METHOD, info[0], info[1])
def #{static_method_name(name, *vars.map {|v| set.include?(v)})}(#{args.join(', ')})
#{ERB.new(erb).result(context)}
end
METHOD
end
end
|
#enum_cons(enum, n) ⇒ Enumerator
A version of Enumerable#enum_cons
that works in Ruby 1.8 and 1.9.
442 443 444 |
# File 'lib/haml/util.rb', line 442
def enum_cons(enum, n)
ruby1_8? ? enum.enum_cons(n) : enum.each_cons(n)
end
|
#enum_slice(enum, n) ⇒ Enumerator
A version of Enumerable#enum_slice
that works in Ruby 1.8 and 1.9.
451 452 453 |
# File 'lib/haml/util.rb', line 451
def enum_slice(enum, n)
ruby1_8? ? enum.enum_slice(n) : enum.each_slice(n)
end
|
#enum_with_index(enum) ⇒ Enumerator
A version of Enumerable#enum_with_index
that works in Ruby 1.8 and 1.9.
433 434 435 |
# File 'lib/haml/util.rb', line 433
def enum_with_index(enum)
ruby1_8? ? enum.enum_with_index : enum.each_with_index
end
|
#flatten(arr, n) ⇒ Array
Flattens the first n
nested arrays in a cross-version manner.
468 469 470 471 472 |
# File 'lib/haml/util.rb', line 468
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
|
#haml_warn(msg)
The same as Kernel#warn
, but is silenced by #silence_haml_warnings.
232 233 234 235 |
# File 'lib/haml/util.rb', line 232
def haml_warn(msg)
return if @@silence_warnings
warn(msg)
end
|
#has?(attr, klass, method) ⇒ Boolean
Checks to see if a class has a given method. For example:
Haml::Util.has?(:public_instance_method, String, :gsub) #=> true
Method collections like Class#instance_methods
return strings in Ruby 1.8 and symbols in Ruby 1.9 and on,
so this handles checking for them in a compatible way.
425 426 427 |
# File 'lib/haml/util.rb', line 425
def has?(attr, klass, method)
klass.send("#{attr}s").include?(ruby1_8? ? method.to_s : method.to_sym)
end
|
#html_safe(text) ⇒ String?
Returns the given text, marked as being HTML-safe.
With older versions of the Rails XSS-safety mechanism,
this destructively modifies the HTML-safety of text
.
334 335 336 337 338 |
# File 'lib/haml/util.rb', line 334
def html_safe(text)
return unless text
return text.html_safe if defined?(ActiveSupport::SafeBuffer)
text.html_safe!
end
|
#intersperse(enum, val) ⇒ Array
Intersperses a value in an enumerable, as would be done with Array#join
but without concatenating the array together afterwards.
146 147 148 |
# File 'lib/haml/util.rb', line 146
def intersperse(enum, val)
enum.inject([]) {|a, e| a << e << val}[0...-1]
end
|
#map_hash(hash) {|key, value| ... } ⇒ Hash
Maps the key-value pairs of a hash according to a block. For example:
map_hash({:foo => "bar", :baz => "bang"}) {|k, v| [k.to_s, v.to_sym]}
#=> {"foo" => :bar, "baz" => :bang}
85 86 87 |
# File 'lib/haml/util.rb', line 85
def map_hash(hash, &block)
to_hash(hash.map(&block))
end
|
#map_keys(hash) {|key| ... } ⇒ Hash
Maps the keys in a hash according to a block. For example:
map_keys({:foo => "bar", :baz => "bang"}) {|k| k.to_s}
#=> {"foo" => "bar", "baz" => "bang"}
50 51 52 |
# File 'lib/haml/util.rb', line 50
def map_keys(hash)
to_hash(hash.map {|k, v| [yield(k), v]})
end
|
#map_vals(hash) {|value| ... } ⇒ Hash
Maps the values in a hash according to a block. For example:
map_values({:foo => "bar", :baz => "bang"}) {|v| v.to_sym}
#=> {:foo => :bar, :baz => :bang}
67 68 69 |
# File 'lib/haml/util.rb', line 67
def map_vals(hash)
to_hash(hash.map {|k, v| [k, yield(v)]})
end
|
#merge_adjacent_strings(enum) ⇒ Array
Concatenates all strings that are adjacent in an array, while leaving other elements as they are. For example:
merge_adjacent_strings([1, "foo", "bar", 2, "baz"])
#=> [1, "foobar", 2, "baz"]
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/haml/util.rb', line 129
def merge_adjacent_strings(enum)
e = enum.inject([]) do |a, e|
if e.is_a?(String) && a.last.is_a?(String)
a.last << e
else
a << e
end
a
end
end
|
#ord(c) ⇒ Fixnum
Returns the ASCII code of the given character.
459 460 461 |
# File 'lib/haml/util.rb', line 459
def ord(c)
ruby1_8? ? c[0] : c.ord
end
|
#paths(arrs) ⇒ Array<Arrays>
Return an array of all possible paths through the given arrays.
paths([[1, 2], [3, 4], [5]]) #=> # [[1, 3, 5], # [2, 3, 5], # [1, 4, 5], # [2, 4, 5]]
190 191 192 193 194 |
# File 'lib/haml/util.rb', line 190
def paths(arrs)
arrs.inject([[]]) do |paths, arr|
flatten(arr.map {|e| paths.map {|path| path + [e]}}, 1)
end
end
|
#powerset(arr) ⇒ Set<Set>
Computes the powerset of the given array. This is the set of all subsets of the array. For example:
powerset([1, 2, 3]) #=>
Set[Set[], Set[1], Set[2], Set[3], Set[1, 2], Set[2, 3], Set[1, 3], Set[1, 2, 3]]
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/haml/util.rb', line 98
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
|
#rails_env ⇒ String?
Returns the environment of the Rails application,
if this is running in a Rails context.
Returns nil
if no such environment is defined.
255 256 257 258 259 |
# File 'lib/haml/util.rb', line 255
def rails_env
return Rails.env.to_s if defined?(Rails.root)
return RAILS_ENV.to_s if defined?(RAILS_ENV)
return nil
end
|
#rails_root ⇒ String?
Returns the root of the Rails application,
if this is running in a Rails context.
Returns nil
if no such root is defined.
244 245 246 247 248 |
# File 'lib/haml/util.rb', line 244
def rails_root
return Rails.root.to_s if defined?(Rails.root)
return RAILS_ROOT.to_s if defined?(RAILS_ROOT)
return nil
end
|
#rails_safe_buffer_class ⇒ Class
The class for the Rails SafeBuffer XSS protection class. This varies depending on Rails version.
353 354 355 356 |
# File 'lib/haml/util.rb', line 353
def rails_safe_buffer_class
return ActionView::SafeBuffer if defined?(ActionView::SafeBuffer)
ActiveSupport::SafeBuffer
end
|
#rails_xss_safe? ⇒ Boolean
Whether or not ActionView's XSS protection is available and enabled, as is the default for Rails 3.0+, and optional for version 2.3.5+. Overridden in haml/template.rb if this is the case.
324 325 326 |
# File 'lib/haml/util.rb', line 324
def rails_xss_safe?
false
end
|
#restrict(value, range) ⇒ Numeric
Restricts a number to falling within a given range. Returns the number if it falls within the range, or the closest value in the range if it doesn't.
116 117 118 |
# File 'lib/haml/util.rb', line 116
def restrict(value, range)
[[value, range.first].max, range.last].min
end
|
#ruby1_8? ⇒ Boolean
Whether or not this is running under Ruby 1.8 or lower.
363 364 365 |
# File 'lib/haml/util.rb', line 363
def ruby1_8?
Haml::Util::RUBY_VERSION[0] == 1 && Haml::Util::RUBY_VERSION[1] < 9
end
|
#ruby1_8_6? ⇒ Boolean
Whether or not this is running under Ruby 1.8.6 or lower. Note that lower versions are not officially supported.
371 372 373 |
# File 'lib/haml/util.rb', line 371
def ruby1_8_6?
ruby1_8? && Haml::Util::RUBY_VERSION[2] < 7
end
|
#scope(file) ⇒ String
Returns the path of a file relative to the Haml root directory.
21 22 23 |
# File 'lib/haml/util.rb', line 21
def scope(file)
File.join(Haml::ROOT_DIR, file)
end
|
#set_eql?(set1, set2) ⇒ Boolean
Tests the hash-equality of two sets in a cross-version manner. Aggravatingly, this is order-dependent in Ruby 1.8.6.
490 491 492 493 |
# File 'lib/haml/util.rb', line 490
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
|
#set_hash(set) ⇒ Fixnum
Returns the hash code for a set in a cross-version manner. Aggravatingly, this is order-dependent in Ruby 1.8.6.
479 480 481 482 |
# File 'lib/haml/util.rb', line 479
def set_hash(set)
return set.hash unless ruby1_8_6?
set.map {|e| e.hash}.uniq.sort.hash
end
|
#silence_haml_warnings { ... }
Silences all Haml warnings within a block.
221 222 223 224 225 226 227 |
# File 'lib/haml/util.rb', line 221
def silence_haml_warnings
old_silence_warnings = @@silence_warnings
@@silence_warnings = true
yield
ensure
@@silence_warnings = old_silence_warnings
end
|
#silence_warnings { ... }
Silence all output to STDERR within a block.
210 211 212 213 214 215 |
# File 'lib/haml/util.rb', line 210
def silence_warnings
the_real_stderr, $stderr = $stderr, StringIO.new
yield
ensure
$stderr = the_real_stderr
end
|
#static_method_name(name, *vars) ⇒ String
Computes the name for a method defined via #def_static_method.
564 565 566 |
# File 'lib/haml/util.rb', line 564
def static_method_name(name, *vars)
"#{name}_#{vars.map {|v| !!v}.join('_')}"
end
|
#strip_string_array(arr) ⇒ Array
Destructively strips whitespace from the beginning and end of the first and last elements, respectively, in the array (if those elements are strings).
173 174 175 176 177 |
# File 'lib/haml/util.rb', line 173
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
|
#substitute(ary, from, to)
Substitutes a sub-array of one array with another sub-array.
155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/haml/util.rb', line 155
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
|
#to_hash(arr) ⇒ Hash
Converts an array of [key, value]
pairs to a hash.
For example:
to_hash([[:foo, "bar"], [:baz, "bang"]])
#=> {:foo => "bar", :baz => "bang"}
33 34 35 |
# File 'lib/haml/util.rb', line 33
def to_hash(arr)
arr.compact.inject({}) {|h, (k, v)| h[k] = v; h}
end
|