Module: Haml::Util

Extended by:
Util
Included in:
Buffer, Compiler, Engine, Parser, Util
Defined in:
lib/haml/util.rb,
lib/haml/template.rb

Overview

A module containing various useful functions.

Defined Under Namespace

Classes: StaticConditionalContext

Instance Method Summary (collapse)

Instance Method Details

- 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.

Parameters:

  • name (#to_s)

    The name of the class to get. For example, :Error will return ActionView::TemplateError or ActionView::Template::Error.



65
66
67
68
# File 'lib/haml/util.rb', line 65

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

- ((String, String)) balance(scanner, start, finish, count = 0)

Moves a scanner through a balanced pair of characters. For example:

Foo (Bar (Baz bang) bop) (Bang (bop bip))
^                       ^
from                    to

Parameters:

  • scanner (StringScanner)

    The string scanner to move

  • start (Character)

    The character opening the balanced pair. A Fixnum in 1.8, a String in 1.9

  • finish (Character)

    The character closing the balanced pair. A Fixnum in 1.8, a String in 1.9

  • count (Fixnum) (defaults to: 0)

    The number of opening characters matched before calling this method

Returns:

  • ((String, String))

    The string matched within the balanced pair and the rest of the string. ["Foo (Bar (Baz bang) bop)", " (Bang (bop bip))"] in the example above.



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/haml/util.rb', line 295

def balance(scanner, start, finish, count = 0)
  str = ''
  scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
  regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
  while scanner.scan(regexp)
    str << scanner.matched
    count += 1 if scanner.matched[-1] == start
    count -= 1 if scanner.matched[-1] == finish
    return [str.strip, scanner.rest] if count == 0
  end
end

- ([String, Fixnum, (String, nil)]) caller_info(entry = caller[1])

Returns information about the caller of the previous method.

Parameters:

  • entry (String) (defaults to: caller[1])

    An entry in the #caller list, or a similarly formatted string

Returns:

  • ([String, Fixnum, (String, nil)])

    An array containing the filename, line, and method name of the caller. The method name may be nil



39
40
41
42
43
44
45
# File 'lib/haml/util.rb', line 39

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

- check_encoding(str)



103
104
105
# File 'lib/haml/util.rb', line 103

def check_encoding(str)
  str.gsub(/\A\xEF\xBB\xBF/, '') # Get rid of the UTF-8 BOM
end

- check_haml_encoding(str, &block)



154
155
156
# File 'lib/haml/util.rb', line 154

def check_haml_encoding(str, &block)
  check_encoding(str, &block)
end

- (Boolean) contains_interpolation?(str)

Returns:

  • (Boolean)


324
325
326
# File 'lib/haml/util.rb', line 324

def contains_interpolation?(str)
  str.include?('#{')
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.

Parameters:

  • klass (Module)

    The class on which to define the static method

  • name (#to_s)

    The (base) name of the static method

  • args (Array<Symbol>)

    The names of the arguments to the defined methods (not to the ERB template)

  • vars (Array<Symbol>)

    The names of the static boolean variables to be made available to the ERB template



238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/haml/util.rb', line 238

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}
    method_content = (defined?(Erubis::TinyEruby) && Erubis::TinyEruby || ERB).new(erb).result(context)

    klass.class_eval(<<METHOD, info[0], info[1])
      def #{static_method_name(name, *vars.map {|v| set.include?(v)})}(#{args.join(', ')})
        #{method_content}
      end
METHOD
  end
end

- (String) handle_interpolation(str) {|scan| ... }

Scans through a string looking for the interoplation-opening #{ and, when it’s found, yields the scanner to the calling code so it can handle it properly.

The scanner will have any backslashes immediately in front of the #{ as the second capture group (scan[2]), and the text prior to that as the first (scan[1]).

Yield Parameters:

  • scan (StringScanner)

    The scanner scanning through the string

Returns:

  • (String)

    The text remaining in the scanner after all #{s have been processed



272
273
274
275
276
# File 'lib/haml/util.rb', line 272

def handle_interpolation(str)
  scan = StringScanner.new(str)
  yield scan while scan.scan(/(.*?)(\\*)\#\{/)
  scan.rest
end

- (String?) html_safe(text)

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.

Parameters:

  • text (String, nil)

Returns:

  • (String, nil)

    text, marked as HTML-safe



87
88
89
90
# File 'lib/haml/util.rb', line 87

def html_safe(text)
  return unless text
  text.html_safe
end

- (String) human_indentation(indentation)

Formats a string for use in error messages about indentation.

Parameters:

  • indentation (String)

    The string used for indentation

Returns:

  • (String)

    The name of the indentation (e.g. "12 spaces", "1 tab")



311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/haml/util.rb', line 311

def human_indentation(indentation)
  if !indentation.include?(?\t)
    noun = 'space'
  elsif !indentation.include?(?\s)
    noun = 'tab'
  else
    return indentation.inspect
  end

  singular = indentation.length == 1
  "#{indentation.length} #{noun}#{'s' unless singular}"
end

- inspect_obj(obj)



171
172
173
# File 'lib/haml/util.rb', line 171

def inspect_obj(obj)
  return obj.inspect
end

- (Set<Set>) powerset(arr)

Computes the powerset of the given array. This is the set of all subsets of the array.

Examples:

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]]

Parameters:

  • arr (Enumerable)

Returns:

  • (Set<Set>)

    The subsets of arr



23
24
25
26
27
28
29
30
31
32
# File 'lib/haml/util.rb', line 23

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

- (Boolean) rails_xss_safe?

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.

Returns:

  • (Boolean)


77
78
79
# File 'lib/haml/util.rb', line 77

def rails_xss_safe?
  false
end

- silence_warnings { ... }

Silence all output to STDERR within a block.

Yields:

  • A block in which no output will be printed to STDERR



50
51
52
53
54
55
# File 'lib/haml/util.rb', line 50

def silence_warnings
  the_real_stderr, $stderr = $stderr, StringIO.new
  yield
ensure
  $stderr = the_real_stderr
end

- (String) static_method_name(name, *vars)

Computes the name for a method defined via #def_static_method.

Parameters:

  • name (String)

    The base name of the static method

  • vars (Array<Boolean>)

    The static variable assignment

Returns:

  • (String)

    The real name of the static method



258
259
260
# File 'lib/haml/util.rb', line 258

def static_method_name(name, *vars)
  :"#{name}_#{vars.map {|v| !!v}.join('_')}"
end

- unescape_interpolation(str, escape_html = nil)



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/haml/util.rb', line 328

def unescape_interpolation(str, escape_html = nil)
  res = ''
  rest = Haml::Util.handle_interpolation str.dump do |scan|
    escapes = (scan[2].size - 1) / 2
    res << scan.matched[0...-3 - escapes]
    if escapes % 2 == 1
      res << '#{'
    else
      content = eval('"' + balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
      content = "Haml::Helpers.html_escape((#{content}))" if escape_html
      res << '#{' + content + "}"# Use eval to get rid of string escapes
    end
  end
  res + rest
end