Class List Method List File List

# 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)

- - av_template_class(name)

  Returns an ActionView::Template* class.

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

  Moves a scanner through a balanced pair of characters.

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

  Returns information about the caller of the previous method.

- - check_encoding(str)
- - check_haml_encoding(str, &block)
- - (Boolean) contains_interpolation?(str)
- - 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.

- - (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]`)..

- - (String?) html_safe(text)

  Returns the given text, marked as being HTML-safe.

- - (String) human_indentation(indentation)

  Formats a string for use in error messages about indentation.

- - inspect_obj(obj)
- - (Set<Set>) powerset(arr)

  Computes the powerset of the given array.

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

- - silence_warnings { ... }

  Silence all output to STDERR within a block.

- - (String) static_method_name(name, *vars)

  Computes the name for a method defined via #def_static_method.

- - unescape_interpolation(str, escape_html = nil)

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