haml 1.7.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of haml might be problematic. Click here for more details.
- data/README +17 -9
- data/Rakefile +12 -4
- data/VERSION +1 -1
- data/init.rb +1 -6
- data/lib/haml.rb +65 -7
- data/lib/haml/buffer.rb +49 -84
- data/lib/haml/engine.rb +155 -797
- data/lib/haml/error.rb +3 -33
- data/lib/haml/exec.rb +86 -65
- data/lib/haml/filters.rb +57 -27
- data/lib/haml/helpers.rb +52 -9
- data/lib/haml/helpers/action_view_mods.rb +1 -1
- data/lib/haml/html.rb +20 -5
- data/lib/haml/precompiler.rb +671 -0
- data/lib/haml/template.rb +20 -73
- data/lib/haml/template/patch.rb +51 -0
- data/lib/haml/template/plugin.rb +21 -0
- data/lib/sass.rb +78 -3
- data/lib/sass/constant.rb +45 -19
- data/lib/sass/constant.rb.rej +42 -0
- data/lib/sass/constant/string.rb +4 -0
- data/lib/sass/css.rb +162 -39
- data/lib/sass/engine.rb +38 -14
- data/lib/sass/plugin.rb +79 -44
- data/lib/sass/tree/attr_node.rb +12 -11
- data/lib/sass/tree/comment_node.rb +9 -3
- data/lib/sass/tree/directive_node.rb +51 -0
- data/lib/sass/tree/node.rb +13 -6
- data/lib/sass/tree/rule_node.rb +34 -12
- data/test/benchmark.rb +85 -52
- data/test/haml/engine_test.rb +172 -84
- data/test/haml/helper_test.rb +31 -3
- data/test/haml/html2haml_test.rb +60 -0
- data/test/haml/markaby/standard.mab +52 -0
- data/test/haml/results/eval_suppressed.xhtml +4 -1
- data/test/haml/results/helpers.xhtml +15 -4
- data/test/haml/results/just_stuff.xhtml +9 -1
- data/test/haml/results/standard.xhtml +0 -1
- data/test/haml/rhtml/_av_partial_1.rhtml +12 -0
- data/test/haml/rhtml/_av_partial_2.rhtml +8 -0
- data/test/haml/rhtml/action_view.rhtml +62 -0
- data/test/haml/rhtml/standard.rhtml +0 -1
- data/test/haml/template_test.rb +41 -21
- data/test/haml/templates/_av_partial_1.haml +9 -0
- data/test/haml/templates/_av_partial_2.haml +5 -0
- data/test/haml/templates/action_view.haml +47 -0
- data/test/haml/templates/eval_suppressed.haml +1 -0
- data/test/haml/templates/helpers.haml +9 -3
- data/test/haml/templates/just_stuff.haml +10 -1
- data/test/haml/templates/partials.haml +1 -1
- data/test/haml/templates/standard.haml +0 -1
- data/test/profile.rb +2 -2
- data/test/sass/engine_test.rb +113 -3
- data/test/sass/engine_test.rb.rej +18 -0
- data/test/sass/plugin_test.rb +34 -11
- data/test/sass/results/compact.css +1 -1
- data/test/sass/results/complex.css +1 -1
- data/test/sass/results/compressed.css +1 -0
- data/test/sass/results/constants.css +3 -1
- data/test/sass/results/expanded.css +2 -1
- data/test/sass/results/import.css +2 -0
- data/test/sass/results/nested.css +2 -1
- data/test/sass/templates/_partial.sass +2 -0
- data/test/sass/templates/compact.sass +2 -0
- data/test/sass/templates/complex.sass +1 -0
- data/test/sass/templates/compressed.sass +15 -0
- data/test/sass/templates/constants.sass +9 -0
- data/test/sass/templates/expanded.sass +2 -0
- data/test/sass/templates/import.sass +1 -1
- data/test/sass/templates/nested.sass +2 -0
- metadata +22 -2
    
        data/lib/sass/tree/attr_node.rb
    CHANGED
    
    | @@ -9,7 +9,7 @@ module Sass::Tree | |
| 9 9 | 
             
                  super(value, style)
         | 
| 10 10 | 
             
                end
         | 
| 11 11 |  | 
| 12 | 
            -
                def to_s(parent_name = nil)
         | 
| 12 | 
            +
                def to_s(tabs, parent_name = nil)
         | 
| 13 13 | 
             
                  if value[-1] == ?;
         | 
| 14 14 | 
             
                    raise Sass::SyntaxError.new("Invalid attribute: #{declaration.dump} (This isn't CSS!)", @line)
         | 
| 15 15 | 
             
                  end
         | 
| @@ -20,21 +20,22 @@ module Sass::Tree | |
| 20 20 | 
             
                    raise Sass::SyntaxError.new("Invalid attribute: #{declaration.dump}", @line)
         | 
| 21 21 | 
             
                  end
         | 
| 22 22 |  | 
| 23 | 
            -
                  join_string = @style | 
| 23 | 
            +
                  join_string = case @style
         | 
| 24 | 
            +
                                when :compact; ' '
         | 
| 25 | 
            +
                                when :compressed; ''
         | 
| 26 | 
            +
                                else "\n"
         | 
| 27 | 
            +
                                end
         | 
| 28 | 
            +
                  spaces = '  ' * (tabs - 1)
         | 
| 24 29 | 
             
                  to_return = ''
         | 
| 25 30 | 
             
                  if !value.empty?
         | 
| 26 | 
            -
                    to_return << "#{real_name}: #{value};#{join_string}"
         | 
| 31 | 
            +
                    to_return << "#{spaces}#{real_name}:#{@style == :compressed ? '' : ' '}#{value};#{join_string}"
         | 
| 27 32 | 
             
                  end
         | 
| 28 33 |  | 
| 29 34 | 
             
                  children.each do |kid|
         | 
| 30 | 
            -
                     | 
| 31 | 
            -
                      to_return << "#{kid.to_s(real_name)} "
         | 
| 32 | 
            -
                    else
         | 
| 33 | 
            -
                      to_return << "#{kid.to_s(real_name)}\n"
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            +
                    to_return << "#{kid.to_s(tabs, real_name)}" << join_string
         | 
| 35 36 | 
             
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  to_return[0...-1]
         | 
| 37 | 
            +
                        
         | 
| 38 | 
            +
                  (@style == :compressed && parent_name) ? to_return : to_return[0...-1]
         | 
| 38 39 | 
             
                end
         | 
| 39 40 |  | 
| 40 41 | 
             
                private
         | 
| @@ -44,7 +45,7 @@ module Sass::Tree | |
| 44 45 | 
             
                end
         | 
| 45 46 |  | 
| 46 47 | 
             
                def invalid_child?(child)
         | 
| 47 | 
            -
                  if !child.is_a?(AttrNode)
         | 
| 48 | 
            +
                  if !child.is_a?(AttrNode) && !child.is_a?(CommentNode)
         | 
| 48 49 | 
             
                    "Illegal nesting: Only attributes may be nested beneath attributes."
         | 
| 49 50 | 
             
                  end
         | 
| 50 51 | 
             
                end
         | 
| @@ -6,9 +6,15 @@ module Sass::Tree | |
| 6 6 | 
             
                  super(value[2..-1].strip, style)
         | 
| 7 7 | 
             
                end
         | 
| 8 8 |  | 
| 9 | 
            -
                def to_s(parent_name = nil)
         | 
| 10 | 
            -
                   | 
| 11 | 
            -
             | 
| 9 | 
            +
                def to_s(tabs = 0, parent_name = nil)
         | 
| 10 | 
            +
                  return if @style == :compressed
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  spaces = '  ' * (tabs - 1)
         | 
| 13 | 
            +
                  join_string = @style == :compact ? ' ' : "\n#{spaces} * "
         | 
| 14 | 
            +
                  str = "#{spaces}/* #{value}"
         | 
| 15 | 
            +
                  str << join_string unless children.empty?
         | 
| 16 | 
            +
                  str << "#{children.join join_string} */"
         | 
| 17 | 
            +
                  str
         | 
| 12 18 | 
             
                end
         | 
| 13 19 | 
             
              end
         | 
| 14 20 | 
             
            end
         | 
| @@ -0,0 +1,51 @@ | |
| 1 | 
            +
            require 'sass/tree/node'
         | 
| 2 | 
            +
            require 'sass/tree/value_node'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            module Sass::Tree
         | 
| 5 | 
            +
              class DirectiveNode < ValueNode
         | 
| 6 | 
            +
                def to_s(tabs)
         | 
| 7 | 
            +
                  if children.empty?
         | 
| 8 | 
            +
                    value + ";"
         | 
| 9 | 
            +
                  else
         | 
| 10 | 
            +
                    result = if @style == :compressed
         | 
| 11 | 
            +
                               "#{value}{"
         | 
| 12 | 
            +
                             else
         | 
| 13 | 
            +
                               "#{'  ' * (tabs - 1)}#{value} {" + (@style == :compact ? ' ' : "\n")
         | 
| 14 | 
            +
                             end
         | 
| 15 | 
            +
                    was_attr = false
         | 
| 16 | 
            +
                    first = true
         | 
| 17 | 
            +
                    children.each do |child|
         | 
| 18 | 
            +
                      if child.is_a?(RuleNode) && child.continued?
         | 
| 19 | 
            +
                        check_multiline_rule(child)
         | 
| 20 | 
            +
                        continued_rule = true
         | 
| 21 | 
            +
                      end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                      if @style == :compact
         | 
| 24 | 
            +
                        if child.is_a?(AttrNode)
         | 
| 25 | 
            +
                          result << "#{child.to_s(first || was_attr ? 1 : tabs + 1)} "
         | 
| 26 | 
            +
                        else
         | 
| 27 | 
            +
                          if was_attr
         | 
| 28 | 
            +
                            result[-1] = "\n"
         | 
| 29 | 
            +
                          end
         | 
| 30 | 
            +
                          rendered = child.to_s(tabs + 1)
         | 
| 31 | 
            +
                          rendered.lstrip! if first
         | 
| 32 | 
            +
                          result << rendered
         | 
| 33 | 
            +
                        end
         | 
| 34 | 
            +
                        was_attr = child.is_a?(AttrNode)
         | 
| 35 | 
            +
                        first = continued_rule
         | 
| 36 | 
            +
                      elsif @style == :compressed
         | 
| 37 | 
            +
                        result << (was_attr ? ";#{child.to_s(1)}" : child.to_s(1))
         | 
| 38 | 
            +
                        was_attr = child.is_a?(AttrNode)
         | 
| 39 | 
            +
                      else
         | 
| 40 | 
            +
                        result << child.to_s(tabs + 1) + (continued_rule ? '' : "\n")
         | 
| 41 | 
            +
                      end
         | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    result.rstrip + if @style == :compressed
         | 
| 44 | 
            +
                                      "}"
         | 
| 45 | 
            +
                                    else
         | 
| 46 | 
            +
                                      (@style == :expanded ? "\n" : " ") + "}\n"
         | 
| 47 | 
            +
                                    end
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
            end
         | 
    
        data/lib/sass/tree/node.rb
    CHANGED
    
    | @@ -22,15 +22,22 @@ module Sass | |
| 22 22 | 
             
                    children.each do |child|
         | 
| 23 23 | 
             
                      if child.is_a? AttrNode
         | 
| 24 24 | 
             
                        raise SyntaxError.new('Attributes aren\'t allowed at the root of a document.', child.line)
         | 
| 25 | 
            +
                      elsif child.is_a?(RuleNode) && child.continued?
         | 
| 26 | 
            +
                        check_multiline_rule(child)
         | 
| 27 | 
            +
                        result << child.to_s(1)
         | 
| 28 | 
            +
                      else
         | 
| 29 | 
            +
                        result << "#{child.to_s(1)}" + (@style == :compressed ? '' : "\n")
         | 
| 25 30 | 
             
                      end
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                    @style == :compressed ? result+"\n" : result[0...-1]
         | 
| 33 | 
            +
                  end
         | 
| 26 34 |  | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                      end
         | 
| 35 | 
            +
                  protected
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def check_multiline_rule(rule)
         | 
| 38 | 
            +
                    unless rule.children.empty?
         | 
| 39 | 
            +
                      raise SyntaxError.new('Rules can\'t end in commas.', rule.line)
         | 
| 32 40 | 
             
                    end
         | 
| 33 | 
            -
                    result[0...-1]
         | 
| 34 41 | 
             
                  end
         | 
| 35 42 |  | 
| 36 43 | 
             
                  private
         | 
    
        data/lib/sass/tree/rule_node.rb
    CHANGED
    
    | @@ -8,10 +8,18 @@ module Sass::Tree | |
| 8 8 |  | 
| 9 9 | 
             
                alias_method :rule, :value
         | 
| 10 10 | 
             
                alias_method :rule=, :value=
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def continued?
         | 
| 13 | 
            +
                  rule[-1] == ?,
         | 
| 14 | 
            +
                end
         | 
| 11 15 |  | 
| 12 16 | 
             
                def to_s(tabs, super_rules = nil)
         | 
| 13 17 | 
             
                  attributes = []
         | 
| 14 18 | 
             
                  sub_rules = []
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  # Save this because the comma's removed by the super_rule additions
         | 
| 21 | 
            +
                  was_continued = continued?
         | 
| 22 | 
            +
             | 
| 15 23 | 
             
                  total_rule = if super_rules
         | 
| 16 24 | 
             
                    super_rules.split(/,\s*/).collect! do |s|
         | 
| 17 25 | 
             
                      self.rule.split(/,\s*/).collect do |r|
         | 
| @@ -21,7 +29,7 @@ module Sass::Tree | |
| 21 29 | 
             
                          "#{s} #{r}"
         | 
| 22 30 | 
             
                        end
         | 
| 23 31 | 
             
                      end.join(", ")
         | 
| 24 | 
            -
                    end.join(", ")
         | 
| 32 | 
            +
                    end.join(", ") + (was_continued ? ',' : '')
         | 
| 25 33 | 
             
                  elsif self.rule.include?(PARENT)
         | 
| 26 34 | 
             
                    raise Sass::SyntaxError.new("Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'", line)
         | 
| 27 35 | 
             
                  else
         | 
| @@ -37,22 +45,36 @@ module Sass::Tree | |
| 37 45 | 
             
                  end
         | 
| 38 46 |  | 
| 39 47 | 
             
                  to_return = ''
         | 
| 40 | 
            -
                   | 
| 48 | 
            +
                  if !attributes.empty?
         | 
| 49 | 
            +
                    old_spaces = '  ' * (tabs - 1)
         | 
| 50 | 
            +
                    spaces = '  ' * tabs
         | 
| 41 51 | 
             
                    if @style == :compact
         | 
| 42 | 
            -
                       | 
| 52 | 
            +
                      attributes = attributes.map { |a| a.to_s(1) }.join(' ')
         | 
| 53 | 
            +
                      to_return << "#{old_spaces}#{total_rule} { #{attributes} }\n"
         | 
| 54 | 
            +
                    elsif @style == :compressed
         | 
| 55 | 
            +
                      attributes = attributes.map { |a| a.to_s(1) }.join(';')
         | 
| 56 | 
            +
                      to_return << "#{total_rule}{#{attributes}}"
         | 
| 43 57 | 
             
                    else
         | 
| 44 | 
            -
                       | 
| 45 | 
            -
                       | 
| 46 | 
            -
                       | 
| 47 | 
            -
             | 
| 48 | 
            -
                      attributes = attributes.join("\n").gsub("\n", "\n#{spaces}").rstrip
         | 
| 49 | 
            -
                      end_attrs = (@style == :expanded ? "\n" : ' ')
         | 
| 50 | 
            -
                      to_return << "#{old_spaces}#{total_rule} {\n#{spaces}#{attributes}#{end_attrs}}\n"
         | 
| 58 | 
            +
                      attributes = attributes.map { |a| a.to_s(tabs + 1) }.join("\n")
         | 
| 59 | 
            +
                      end_attrs = (@style == :expanded ? "\n" + old_spaces : ' ')
         | 
| 60 | 
            +
                      to_return << "#{old_spaces}#{total_rule} {\n#{attributes}#{end_attrs}}\n"
         | 
| 51 61 | 
             
                    end
         | 
| 62 | 
            +
                  elsif continued?
         | 
| 63 | 
            +
                    to_return << ('  ' * (tabs - 1)) + total_rule + case @style
         | 
| 64 | 
            +
                                                                    when :compressed; ''
         | 
| 65 | 
            +
                                                                    when :compact; ' '
         | 
| 66 | 
            +
                                                                    else "\n"
         | 
| 67 | 
            +
                                                                    end
         | 
| 52 68 | 
             
                  end
         | 
| 53 69 |  | 
| 54 | 
            -
                  tabs += 1 unless attributes.empty?
         | 
| 55 | 
            -
                  sub_rules.each  | 
| 70 | 
            +
                  tabs += 1 unless attributes.empty? || @style != :nested
         | 
| 71 | 
            +
                  sub_rules.each do |sub|
         | 
| 72 | 
            +
                    if sub.continued?
         | 
| 73 | 
            +
                      check_multiline_rule(sub)
         | 
| 74 | 
            +
                    end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                    to_return << sub.to_s(tabs, total_rule)
         | 
| 77 | 
            +
                  end
         | 
| 56 78 | 
             
                  to_return
         | 
| 57 79 | 
             
                end
         | 
| 58 80 | 
             
              end
         | 
    
        data/test/benchmark.rb
    CHANGED
    
    | @@ -1,62 +1,95 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
            require File.dirname(__FILE__) + '/../lib/haml'
         | 
| 7 | 
            -
            require 'haml | 
| 8 | 
            -
             | 
| 1 | 
            +
            # There's a bizarre error where ActionController tries to load a benchmark file
         | 
| 2 | 
            +
            # and ends up finding this.
         | 
| 3 | 
            +
            # These declarations then cause it to break.
         | 
| 4 | 
            +
            # This only happens when running rcov, though, so we can avoid it.
         | 
| 5 | 
            +
            unless $0 =~ /rcov$/
         | 
| 6 | 
            +
              require File.dirname(__FILE__) + '/../lib/haml'
         | 
| 7 | 
            +
              require 'haml'
         | 
| 8 | 
            +
            end
         | 
| 9 9 |  | 
| 10 | 
            +
            require 'rubygems'
         | 
| 11 | 
            +
            require 'erb'
         | 
| 12 | 
            +
            require 'erubis'
         | 
| 13 | 
            +
            require 'markaby'
         | 
| 10 14 | 
             
            require 'benchmark'
         | 
| 11 15 | 
             
            require 'stringio'
         | 
| 16 | 
            +
            require 'open-uri'
         | 
| 12 17 |  | 
| 13 18 | 
             
            module Haml
         | 
| 14 | 
            -
               | 
| 15 | 
            -
              
         | 
| 16 | 
            -
                 | 
| 17 | 
            -
                 | 
| 18 | 
            -
                 | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 19 | 
            +
              # Benchmarks Haml against ERB, Erubis, and Markaby and Sass on its own.
         | 
| 20 | 
            +
              def self.benchmark(runs = 100)
         | 
| 21 | 
            +
                template_name = 'standard'
         | 
| 22 | 
            +
                directory = File.dirname(__FILE__) + '/haml'
         | 
| 23 | 
            +
                haml_template =    File.read("#{directory}/templates/#{template_name}.haml")
         | 
| 24 | 
            +
                erb_template =   File.read("#{directory}/rhtml/#{template_name}.rhtml")
         | 
| 25 | 
            +
                markaby_template = File.read("#{directory}/markaby/#{template_name}.mab")
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                puts '-'*51, "Haml and Friends: No Caching", '-'*51
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                times = Benchmark.bmbm do |b|
         | 
| 30 | 
            +
                  b.report("haml:")   { runs.times { Haml::Engine.new(haml_template).render } }
         | 
| 31 | 
            +
                  b.report("erb:")    { runs.times { ERB.new(erb_template, nil, '-').render } }
         | 
| 32 | 
            +
                  b.report("erubis:") { runs.times { Erubis::Eruby.new(erb_template).result } }
         | 
| 33 | 
            +
                  b.report("mab:")    { runs.times { Markaby::Template.new(markaby_template).render } }
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                print_result = proc do |s, n|
         | 
| 37 | 
            +
                  printf "%1$*2$s %3$*4$g",
         | 
| 38 | 
            +
                    "Haml/#{s}:", -13, times[0].to_a[5] / times[n].to_a[5], -17
         | 
| 39 | 
            +
                  printf "%1$*2$s %3$g\n",
         | 
| 40 | 
            +
                    "#{s}/Haml:", -13, times[n].to_a[5] / times[0].to_a[5]
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                
         | 
| 43 | 
            +
                print_result["ERB", 1]
         | 
| 44 | 
            +
                print_result["Erubis", 2]
         | 
| 45 | 
            +
                print_result["Markaby", 3]
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                puts '', '-' * 50, 'Haml and Friends: Cached', '-' * 50
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                obj = Object.new
         | 
| 50 | 
            +
                Haml::Engine.new(haml_template).def_method(obj, :haml)
         | 
| 51 | 
            +
                erb = ERB.new(erb_template, nil, '-')
         | 
| 52 | 
            +
                obj.instance_eval("def erb; #{erb.src}; end")
         | 
| 53 | 
            +
                Erubis::Eruby.new(erb_template).def_method(obj, :erubis)
         | 
| 54 | 
            +
                times = Benchmark.bmbm do |b|
         | 
| 55 | 
            +
                  b.report("haml:")   { runs.times { obj.haml      } }
         | 
| 56 | 
            +
                  b.report("erb:")    { runs.times { obj.erb       } }
         | 
| 57 | 
            +
                  b.report("erubis:") { runs.times { obj.erubis    } }
         | 
| 58 | 
            +
                end    
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                print_result["ERB", 1]
         | 
| 61 | 
            +
                print_result["Erubis", 2]
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                puts '', '-' * 50, 'Haml and ERB: Via ActionView', '-' * 50
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                require 'active_support'
         | 
| 66 | 
            +
                require 'action_controller'
         | 
| 67 | 
            +
                require 'action_view'
         | 
| 68 | 
            +
                require 'haml/template'
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                @base = ActionView::Base.new(File.dirname(__FILE__))
         | 
| 71 | 
            +
                times = Benchmark.bmbm do |b|
         | 
| 72 | 
            +
                  b.report("haml:") { runs.times { @base.render 'haml/templates/standard' } }
         | 
| 73 | 
            +
                  b.report("erb:")  { runs.times { @base.render 'haml/rhtml/standard'     } }
         | 
| 25 74 | 
             
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                print_result["ERB", 1]
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                puts '', '-' * 50, 'Haml and ERB: Via ActionView with deep partials', '-' * 50
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                @base = ActionView::Base.new(File.dirname(__FILE__))
         | 
| 81 | 
            +
                times = Benchmark.bmbm do |b|
         | 
| 82 | 
            +
                  b.report("haml:") { runs.times { @base.render 'haml/templates/action_view' } }
         | 
| 83 | 
            +
                  b.report("erb:")  { runs.times { @base.render 'haml/rhtml/action_view'     } }
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                print_result["ERB", 1]
         | 
| 87 | 
            +
                
         | 
| 88 | 
            +
                puts '', '-' * 50, 'Sass', '-' * 50
         | 
| 89 | 
            +
                sass_template = File.read("#{File.dirname(__FILE__)}/sass/templates/complex.sass")
         | 
| 26 90 |  | 
| 27 | 
            -
                 | 
| 28 | 
            -
             | 
| 29 | 
            -
                # Returns the results of the benchmarking as a string.
         | 
| 30 | 
            -
                # 
         | 
| 31 | 
            -
                def benchmark(runs = 100)
         | 
| 32 | 
            -
                  template_name = 'standard'
         | 
| 33 | 
            -
                  haml_template = "haml/templates/#{template_name}"
         | 
| 34 | 
            -
                  rhtml_template = "haml/rhtml/#{template_name}"
         | 
| 35 | 
            -
                  sass_template = File.dirname(__FILE__) + "/sass/templates/complex.sass"
         | 
| 36 | 
            -
                  
         | 
| 37 | 
            -
                  old_stdout = $stdout
         | 
| 38 | 
            -
                  $stdout = StringIO.new
         | 
| 39 | 
            -
                  
         | 
| 40 | 
            -
                  times = Benchmark.bmbm do |b|
         | 
| 41 | 
            -
                    b.report("haml:") { runs.times { @base.render haml_template } }
         | 
| 42 | 
            -
                    b.report("erb:") { runs.times { @base.render rhtml_template } }
         | 
| 43 | 
            -
                  end
         | 
| 44 | 
            -
                  
         | 
| 45 | 
            -
                  #puts times[0].inspect, times[1].inspect
         | 
| 46 | 
            -
                  ratio = sprintf("%g", times[0].to_a[5] / times[1].to_a[5])
         | 
| 47 | 
            -
                  puts "Haml/ERB: " + ratio
         | 
| 48 | 
            -
                  
         | 
| 49 | 
            -
                  puts '', '-' * 50, 'Sass on its own', '-' * 50
         | 
| 50 | 
            -
                  
         | 
| 51 | 
            -
                  Benchmark.bmbm do |b|
         | 
| 52 | 
            -
                    b.report("sass:") { runs.times { Sass::Engine.new(File.read(sass_template)).render } }
         | 
| 53 | 
            -
                  end
         | 
| 54 | 
            -
                  
         | 
| 55 | 
            -
                  $stdout.pos = 0
         | 
| 56 | 
            -
                  to_return = $stdout.read
         | 
| 57 | 
            -
                  $stdout = old_stdout
         | 
| 58 | 
            -
                  
         | 
| 59 | 
            -
                  to_return
         | 
| 91 | 
            +
                Benchmark.bmbm do |b|
         | 
| 92 | 
            +
                  b.report("sass:") { runs.times { Sass::Engine.new(sass_template).render } }
         | 
| 60 93 | 
             
                end
         | 
| 61 94 | 
             
              end
         | 
| 62 95 | 
             
            end
         | 
    
        data/test/haml/engine_test.rb
    CHANGED
    
    | @@ -11,21 +11,18 @@ require 'haml/engine' | |
| 11 11 |  | 
| 12 12 | 
             
            class EngineTest < Test::Unit::TestCase
         | 
| 13 13 |  | 
| 14 | 
            -
              def render(text, options = {})
         | 
| 15 | 
            -
                 | 
| 14 | 
            +
              def render(text, options = {}, &block)
         | 
| 15 | 
            +
                scope  = options.delete(:scope)  || Object.new
         | 
| 16 | 
            +
                locals = options.delete(:locals) || {}
         | 
| 17 | 
            +
                Haml::Engine.new(text, options).to_html(scope, locals, &block)
         | 
| 16 18 | 
             
              end
         | 
| 17 19 |  | 
| 18 20 | 
             
              def test_empty_render_should_remain_empty
         | 
| 19 21 | 
             
                assert_equal('', render(''))
         | 
| 20 22 | 
             
              end
         | 
| 21 23 |  | 
| 22 | 
            -
              # This is ugly because Hashes are unordered; we don't always know the order
         | 
| 23 | 
            -
              # in which attributes will be returned.
         | 
| 24 | 
            -
              # There is probably a better way to do this.
         | 
| 25 24 | 
             
              def test_attributes_should_render_correctly
         | 
| 26 25 | 
             
                assert_equal("<div class='atlantis' style='ugly'>\n</div>", render(".atlantis{:style => 'ugly'}").chomp)
         | 
| 27 | 
            -
              rescue
         | 
| 28 | 
            -
                assert_equal("<div style='ugly' class='atlantis'>\n</div>", render(".atlantis{:style => 'ugly'}").chomp)
         | 
| 29 26 | 
             
              end
         | 
| 30 27 |  | 
| 31 28 | 
             
              def test_ruby_code_should_work_inside_attributes
         | 
| @@ -50,6 +47,18 @@ class EngineTest < Test::Unit::TestCase | |
| 50 47 | 
             
              def test_long_liner_should_not_print_on_one_line
         | 
| 51 48 | 
             
                assert_equal("<div>\n  #{'x' * 51}\n</div>", render("%div #{'x' * 51}").chomp)
         | 
| 52 49 | 
             
              end
         | 
| 50 | 
            +
              
         | 
| 51 | 
            +
              def test_non_prerendered_one_liner
         | 
| 52 | 
            +
                assert_equal("<p class='awesome'>One line</p>\n", render("%p{:class => c} One line", :locals => {:c => 'awesome'}))
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
              
         | 
| 55 | 
            +
              def test_non_prerendered_script_one_liner
         | 
| 56 | 
            +
                assert_equal("<p class='awesome'>One line</p>\n", render("%p{:class => c}= 'One line'", :locals => {:c => 'awesome'}))
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
              
         | 
| 59 | 
            +
              def test_non_prerendered_long_script_one_liner
         | 
| 60 | 
            +
                assert_equal("<p class='awesome'>\n  #{'x' * 60}\n</p>\n", render("%p{:class => c}= 'x' * 60", :locals => {:c => 'awesome'}))
         | 
| 61 | 
            +
              end
         | 
| 53 62 |  | 
| 54 63 | 
             
              def test_multi_render
         | 
| 55 64 | 
             
                engine = Haml::Engine.new("%strong Hi there!")
         | 
| @@ -63,6 +72,11 @@ class EngineTest < Test::Unit::TestCase | |
| 63 72 | 
             
                assert_equal("<p>\n  Hello World\n</p>\n", render("%p\n  == Hello \#{who}", :locals => {:who => 'World'}))
         | 
| 64 73 | 
             
              end
         | 
| 65 74 |  | 
| 75 | 
            +
              def test_double_equals_in_the_middle_of_a_string
         | 
| 76 | 
            +
                assert_equal("\"title 'Title'. \"\n",
         | 
| 77 | 
            +
                             render("== \"title '\#{\"Title\"}'. \""))
         | 
| 78 | 
            +
              end
         | 
| 79 | 
            +
             | 
| 66 80 | 
             
              def test_nil_tag_value_should_render_as_empty
         | 
| 67 81 | 
             
                assert_equal("<p></p>\n", render("%p= nil"))
         | 
| 68 82 | 
             
              end
         | 
| @@ -71,6 +85,14 @@ class EngineTest < Test::Unit::TestCase | |
| 71 85 | 
             
                assert_equal("<p></p>\n", render("%p= 'Hello' if false"))
         | 
| 72 86 | 
             
              end
         | 
| 73 87 |  | 
| 88 | 
            +
              def test_static_attributes_with_empty_attr
         | 
| 89 | 
            +
                assert_equal("<img alt='' src='/foo.png' />\n", render("%img{:src => '/foo.png', :alt => ''}"))
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              def test_dynamic_attributes_with_empty_attr
         | 
| 93 | 
            +
                assert_equal("<img alt='' src='/foo.png' />\n", render("%img{:width => nil, :src => '/foo.png', :alt => String.new}"))
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 74 96 | 
             
              # Options tests
         | 
| 75 97 |  | 
| 76 98 | 
             
              def test_stop_eval
         | 
| @@ -84,7 +106,7 @@ class EngineTest < Test::Unit::TestCase | |
| 84 106 | 
             
                  assert_equal("", render(":ruby\n  puts 'hello'", :suppress_eval => true))
         | 
| 85 107 | 
             
                rescue Haml::HamlError => err
         | 
| 86 108 | 
             
                  caught = true
         | 
| 87 | 
            -
                  assert_equal(' | 
| 109 | 
            +
                  assert_equal('"ruby" filter is not defined!', err.message)
         | 
| 88 110 | 
             
                end
         | 
| 89 111 | 
             
                assert(caught, "Rendering a ruby filter without evaluating didn't throw an error!")
         | 
| 90 112 | 
             
              end
         | 
| @@ -102,25 +124,34 @@ class EngineTest < Test::Unit::TestCase | |
| 102 124 | 
             
                assert_equal("<p escaped='quo\nte'>\n</p>\n", render("%p{ :escaped => \"quo\\nte\"}"))
         | 
| 103 125 | 
             
                assert_equal("<p escaped='quo4te'>\n</p>\n", render("%p{ :escaped => \"quo\#{2 + 2}te\"}"))
         | 
| 104 126 | 
             
              end
         | 
| 127 | 
            +
              
         | 
| 128 | 
            +
              def test_empty_attrs
         | 
| 129 | 
            +
                assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => '' } empty"))
         | 
| 130 | 
            +
                assert_equal("<p attr=''>empty</p>\n", render("%p{ :attr => x } empty", :locals => {:x => ''}))
         | 
| 131 | 
            +
              end
         | 
| 132 | 
            +
              
         | 
| 133 | 
            +
              def test_nil_attrs
         | 
| 134 | 
            +
                assert_equal("<p>nil</p>\n", render("%p{ :attr => nil } nil"))
         | 
| 135 | 
            +
                assert_equal("<p>nil</p>\n", render("%p{ :attr => x } nil", :locals => {:x => nil}))
         | 
| 136 | 
            +
              end
         | 
| 105 137 |  | 
| 106 138 | 
             
              def test_locals
         | 
| 107 139 | 
             
                assert_equal("<p>Paragraph!</p>\n", render("%p= text", :locals => { :text => "Paragraph!" }))
         | 
| 108 140 | 
             
              end
         | 
| 109 | 
            -
              
         | 
| 110 | 
            -
              def test_recompile_with_new_locals
         | 
| 111 | 
            -
                template = "%p= (text == 'first time') ? text : new_text"
         | 
| 112 | 
            -
                assert_equal("<p>first time</p>\n", render(template, :locals => { :text => "first time" }))
         | 
| 113 | 
            -
                assert_equal("<p>second time</p>\n", render(template, :locals => { :text => "recompile", :new_text => "second time" }))
         | 
| 114 141 |  | 
| 115 | 
            -
             | 
| 116 | 
            -
                 | 
| 117 | 
            -
             | 
| 142 | 
            +
              def test_deprecated_locals_option
         | 
| 143 | 
            +
                Kernel.module_eval do
         | 
| 144 | 
            +
                  def warn_with_stub(msg); end
         | 
| 145 | 
            +
                  alias_method :warn_without_stub, :warn
         | 
| 146 | 
            +
                  alias_method :warn, :warn_with_stub
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                assert_equal("<p>Paragraph!</p>\n", Haml::Engine.new("%p= text", :locals => { :text => "Paragraph!" }).render)
         | 
| 118 150 |  | 
| 119 | 
            -
                 | 
| 120 | 
            -
                assert_equal("<p>first time</p>\n", render(template, :locals => { :text => "first time", :foo => 'bar' }))
         | 
| 151 | 
            +
                Kernel.module_eval { alias_method :warn, :warn_without_stub }
         | 
| 121 152 | 
             
              end
         | 
| 122 153 |  | 
| 123 | 
            -
              def  | 
| 154 | 
            +
              def test_dynamic_attrs_shouldnt_register_as_literal_values
         | 
| 124 155 | 
             
                assert_equal("<p a='b2c'>\n</p>\n", render('%p{:a => "b#{1 + 1}c"}'))
         | 
| 125 156 | 
             
                assert_equal("<p a='b2c'>\n</p>\n", render("%p{:a => 'b' + (1 + 1).to_s + 'c'}"))
         | 
| 126 157 | 
             
              end
         | 
| @@ -134,20 +165,6 @@ class EngineTest < Test::Unit::TestCase | |
| 134 165 | 
             
                assert_equal(hash3, hash1)
         | 
| 135 166 | 
             
              end
         | 
| 136 167 |  | 
| 137 | 
            -
              def test_exception_type
         | 
| 138 | 
            -
                begin
         | 
| 139 | 
            -
                  render("%p hi\n= undefined")
         | 
| 140 | 
            -
                rescue Exception => e
         | 
| 141 | 
            -
                  assert(e.is_a?(Haml::Error))
         | 
| 142 | 
            -
                  assert_equal(2, e.haml_line)
         | 
| 143 | 
            -
                  assert_equal(nil, e.haml_filename)
         | 
| 144 | 
            -
                  assert_equal('(haml):2', e.backtrace[0])
         | 
| 145 | 
            -
                else
         | 
| 146 | 
            -
                  # Test failed... should have raised an exception
         | 
| 147 | 
            -
                  assert(false)
         | 
| 148 | 
            -
                end
         | 
| 149 | 
            -
              end
         | 
| 150 | 
            -
             | 
| 151 168 | 
             
              def test_syntax_errors
         | 
| 152 169 | 
             
                errs = [ "!!!\n  a", "a\n  b", "a\n:foo\nb", "/ a\n  b",
         | 
| 153 170 | 
             
                         "% a", "%p a\n  b", "a\n%p=\nb", "%p=\n  a",
         | 
| @@ -159,81 +176,84 @@ class EngineTest < Test::Unit::TestCase | |
| 159 176 | 
             
                  begin
         | 
| 160 177 | 
             
                    render(err)
         | 
| 161 178 | 
             
                  rescue Exception => e
         | 
| 162 | 
            -
                    assert(e.is_a?(Haml::Error),
         | 
| 163 | 
            -
                           "#{err.dump} doesn't produce Haml::SyntaxError!")
         | 
| 179 | 
            +
                    assert(e.is_a?(Haml::Error), "#{err.dump} doesn't produce Haml::SyntaxError")
         | 
| 164 180 | 
             
                  else
         | 
| 165 | 
            -
                    assert(false,
         | 
| 166 | 
            -
                           "#{err.dump} doesn't produce an exception!")
         | 
| 181 | 
            +
                    assert(false, "#{err.dump} doesn't produce an exception")
         | 
| 167 182 | 
             
                  end
         | 
| 168 183 | 
             
                end
         | 
| 169 184 | 
             
              end
         | 
| 170 185 |  | 
| 186 | 
            +
              def test_syntax_error
         | 
| 187 | 
            +
                render("a\nb\n!!!\n  c\nd")
         | 
| 188 | 
            +
              rescue Haml::SyntaxError => e
         | 
| 189 | 
            +
                assert_equal(e.message, "Illegal Nesting: Nesting within a header command is illegal.")
         | 
| 190 | 
            +
                assert_equal("(haml):3", e.backtrace[0])
         | 
| 191 | 
            +
              rescue Exception => e
         | 
| 192 | 
            +
                assert(false, '"a\nb\n!!!\n  c\nd" doesn\'t produce a Haml::SyntaxError')
         | 
| 193 | 
            +
              else
         | 
| 194 | 
            +
                assert(false, '"a\nb\n!!!\n  c\nd" doesn\'t produce an exception')
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              def test_exception
         | 
| 198 | 
            +
                render("%p\n  hi\n  %a= undefined\n= 12")
         | 
| 199 | 
            +
              rescue Exception => e
         | 
| 200 | 
            +
                assert_match("(haml):3", e.backtrace[0])
         | 
| 201 | 
            +
              else
         | 
| 202 | 
            +
                # Test failed... should have raised an exception
         | 
| 203 | 
            +
                assert(false)
         | 
| 204 | 
            +
              end
         | 
| 205 | 
            +
             | 
| 171 206 | 
             
              def test_compile_error
         | 
| 172 | 
            -
                 | 
| 173 | 
            -
             | 
| 174 | 
            -
                 | 
| 175 | 
            -
             | 
| 176 | 
            -
                 | 
| 177 | 
            -
             | 
| 178 | 
            -
                         '"a\nb\n- fee do\nc" doesn\'t produce an exception!')
         | 
| 179 | 
            -
                end
         | 
| 207 | 
            +
                render("a\nb\n- fee)\nc")
         | 
| 208 | 
            +
              rescue Exception => e
         | 
| 209 | 
            +
                assert_match(/^compile error\n\(haml\):3: syntax error/i, e.message)
         | 
| 210 | 
            +
              else
         | 
| 211 | 
            +
                assert(false,
         | 
| 212 | 
            +
                       '"a\nb\n- fee)\nc" doesn\'t produce an exception!')
         | 
| 180 213 | 
             
              end
         | 
| 181 214 |  | 
| 182 | 
            -
              def  | 
| 183 | 
            -
                 | 
| 184 | 
            -
             | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 215 | 
            +
              def test_unbalanced_brackets
         | 
| 216 | 
            +
                render('== #{1 + 5} foo #{6 + 7 bar #{8 + 9}')
         | 
| 217 | 
            +
              rescue Haml::SyntaxError => e
         | 
| 218 | 
            +
                assert_equal("Unbalanced brackets.", e.message)
         | 
| 219 | 
            +
              end
         | 
| 187 220 |  | 
| 221 | 
            +
              def test_no_bluecloth
         | 
| 188 222 | 
             
                Kernel.module_eval do
         | 
| 189 | 
            -
                   | 
| 190 | 
            -
             | 
| 191 | 
            -
                  def gem_original_require(file)
         | 
| 223 | 
            +
                  def gem_original_require_with_bluecloth(file)
         | 
| 192 224 | 
             
                    raise LoadError if file == 'bluecloth'
         | 
| 193 | 
            -
                     | 
| 194 | 
            -
                  end
         | 
| 195 | 
            -
                end
         | 
| 196 | 
            -
                
         | 
| 197 | 
            -
                if old_markdown
         | 
| 198 | 
            -
                  Haml::Filters.instance_eval do
         | 
| 199 | 
            -
                    remove_const 'Markdown'
         | 
| 225 | 
            +
                    gem_original_require_without_bluecloth(file)
         | 
| 200 226 | 
             
                  end
         | 
| 227 | 
            +
                  alias_method :gem_original_require_without_bluecloth, :gem_original_require
         | 
| 228 | 
            +
                  alias_method :gem_original_require, :gem_original_require_with_bluecloth
         | 
| 201 229 | 
             
                end
         | 
| 202 230 |  | 
| 203 | 
            -
                 | 
| 204 | 
            -
             | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
                   | 
| 231 | 
            +
                begin
         | 
| 232 | 
            +
                  assert_equal("<h1>Foo</h1>\t<p>- a\n- b</p>\n",
         | 
| 233 | 
            +
                               Haml::Engine.new(":markdown\n  Foo\n  ===\n  - a\n  - b").to_html)
         | 
| 234 | 
            +
                rescue Haml::HamlError => e
         | 
| 235 | 
            +
                  if e.message == "Can't run Markdown filter; required 'bluecloth' or 'redcloth', but none were found"
         | 
| 236 | 
            +
                    puts "\nCouldn't require 'bluecloth' or 'redcloth'; skipping a test."
         | 
| 237 | 
            +
                  else
         | 
| 238 | 
            +
                    raise e
         | 
| 239 | 
            +
                  end
         | 
| 212 240 | 
             
                end
         | 
| 213 241 |  | 
| 214 | 
            -
                Haml::Filters.const_set('Markdown', old_markdown) if old_markdown
         | 
| 215 | 
            -
             | 
| 216 242 | 
             
                Kernel.module_eval do
         | 
| 217 | 
            -
                  alias_method :gem_original_require, : | 
| 243 | 
            +
                  alias_method :gem_original_require, :gem_original_require_without_bluecloth
         | 
| 218 244 | 
             
                end
         | 
| 219 | 
            -
             | 
| 220 | 
            -
                NOT_LOADED.delete 'bluecloth'
         | 
| 221 245 | 
             
              end
         | 
| 222 246 |  | 
| 223 247 | 
             
              def test_no_redcloth
         | 
| 224 248 | 
             
                Kernel.module_eval do
         | 
| 225 | 
            -
                   | 
| 226 | 
            -
             | 
| 227 | 
            -
                  def gem_original_require(file)
         | 
| 249 | 
            +
                  def gem_original_require_with_redcloth(file)
         | 
| 228 250 | 
             
                    raise LoadError if file == 'redcloth'
         | 
| 229 | 
            -
                     | 
| 251 | 
            +
                    gem_original_require_without_redcloth(file)
         | 
| 230 252 | 
             
                  end
         | 
| 253 | 
            +
                  alias_method :gem_original_require_without_redcloth, :gem_original_require
         | 
| 254 | 
            +
                  alias_method :gem_original_require, :gem_original_require_with_redcloth
         | 
| 231 255 | 
             
                end
         | 
| 232 256 |  | 
| 233 | 
            -
                # This is purposefully redundant, so it doesn't stop
         | 
| 234 | 
            -
                # haml/filters from being required later on.
         | 
| 235 | 
            -
                require 'haml/../haml/../haml/filters'
         | 
| 236 | 
            -
             | 
| 237 257 | 
             
                begin
         | 
| 238 258 | 
             
                  Haml::Engine.new(":redcloth\n  _foo_").to_html
         | 
| 239 259 | 
             
                rescue Haml::HamlError
         | 
| @@ -242,10 +262,30 @@ class EngineTest < Test::Unit::TestCase | |
| 242 262 | 
             
                end
         | 
| 243 263 |  | 
| 244 264 | 
             
                Kernel.module_eval do
         | 
| 245 | 
            -
                  alias_method : | 
| 265 | 
            +
                  alias_method :gem_original_require, :gem_original_require_without_redcloth
         | 
| 266 | 
            +
                end
         | 
| 267 | 
            +
              end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
              def test_no_redcloth_or_bluecloth
         | 
| 270 | 
            +
                Kernel.module_eval do
         | 
| 271 | 
            +
                  def gem_original_require_with_redcloth_and_bluecloth(file)
         | 
| 272 | 
            +
                    raise LoadError if file == 'redcloth' || file == 'bluecloth'
         | 
| 273 | 
            +
                    gem_original_require_without_redcloth_and_bluecloth(file)
         | 
| 274 | 
            +
                  end
         | 
| 275 | 
            +
                  alias_method :gem_original_require_without_redcloth_and_bluecloth, :gem_original_require
         | 
| 276 | 
            +
                  alias_method :gem_original_require, :gem_original_require_with_redcloth_and_bluecloth
         | 
| 277 | 
            +
                end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                begin
         | 
| 280 | 
            +
                  Haml::Engine.new(":markdown\n  _foo_").to_html
         | 
| 281 | 
            +
                rescue Haml::HamlError
         | 
| 282 | 
            +
                else
         | 
| 283 | 
            +
                  assert(false, "No exception raised!")
         | 
| 246 284 | 
             
                end
         | 
| 247 285 |  | 
| 248 | 
            -
                 | 
| 286 | 
            +
                Kernel.module_eval do
         | 
| 287 | 
            +
                  alias_method :gem_original_require, :gem_original_require_without_redcloth_and_bluecloth
         | 
| 288 | 
            +
                end    
         | 
| 249 289 | 
             
              end
         | 
| 250 290 |  | 
| 251 291 | 
             
              def test_local_assigns_dont_modify_class
         | 
| @@ -258,4 +298,52 @@ class EngineTest < Test::Unit::TestCase | |
| 258 298 | 
             
                assert_equal("<p class='struct_user' id='struct_user_new'>New User</p>\n",
         | 
| 259 299 | 
             
                             render("%p[user] New User", :locals => {:user => user}))
         | 
| 260 300 | 
             
              end
         | 
| 301 | 
            +
             | 
| 302 | 
            +
              def test_non_literal_attributes
         | 
| 303 | 
            +
                assert_equal("<p a1='foo' a2='bar' a3='baz' />\n",
         | 
| 304 | 
            +
                             render("%p{a2, a1, :a3 => 'baz'}/",
         | 
| 305 | 
            +
                                    :locals => {:a1 => {:a1 => 'foo'}, :a2 => {:a2 => 'bar'}}))
         | 
| 306 | 
            +
              end
         | 
| 307 | 
            +
             | 
| 308 | 
            +
              def test_render_should_accept_a_binding_as_scope
         | 
| 309 | 
            +
                string = "This is a string!"
         | 
| 310 | 
            +
                string.instance_variable_set("@var", "Instance variable")
         | 
| 311 | 
            +
                b = string.instance_eval do
         | 
| 312 | 
            +
                  var = "Local variable"
         | 
| 313 | 
            +
                  binding
         | 
| 314 | 
            +
                end
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                assert_equal("<p>THIS IS A STRING!</p>\n<p>Instance variable</p>\n<p>Local variable</p>\n",
         | 
| 317 | 
            +
                             render("%p= upcase\n%p= @var\n%p= var", :scope => b))
         | 
| 318 | 
            +
              end
         | 
| 319 | 
            +
             | 
| 320 | 
            +
              def test_yield_should_work_with_binding
         | 
| 321 | 
            +
                assert_equal("12\nFOO\n", render("= yield\n= upcase", :scope => "foo".instance_eval{binding}) { 12 })
         | 
| 322 | 
            +
              end
         | 
| 323 | 
            +
             | 
| 324 | 
            +
              def test_yield_should_work_with_def_method
         | 
| 325 | 
            +
                s = "foo"
         | 
| 326 | 
            +
                Haml::Engine.new("= yield\n= upcase").def_method(s, :render)
         | 
| 327 | 
            +
                assert_equal("12\nFOO\n", s.render { 12 })
         | 
| 328 | 
            +
              end
         | 
| 329 | 
            +
             | 
| 330 | 
            +
              def test_def_method_with_module
         | 
| 331 | 
            +
                Haml::Engine.new("= yield\n= upcase").def_method(String, :render_haml)
         | 
| 332 | 
            +
                assert_equal("12\nFOO\n", "foo".render_haml { 12 })
         | 
| 333 | 
            +
              end
         | 
| 334 | 
            +
             | 
| 335 | 
            +
              def test_def_method_locals
         | 
| 336 | 
            +
                obj = Object.new
         | 
| 337 | 
            +
                Haml::Engine.new("%p= foo\n.bar{:baz => baz}= boom").def_method(obj, :render, :foo, :baz, :boom)
         | 
| 338 | 
            +
                assert_equal("<p>1</p>\n<div baz='2' class='bar'>3</div>\n", obj.render(:foo => 1, :baz => 2, :boom => 3))
         | 
| 339 | 
            +
              end
         | 
| 340 | 
            +
             | 
| 341 | 
            +
              def test_render_proc_locals
         | 
| 342 | 
            +
                proc = Haml::Engine.new("%p= foo\n.bar{:baz => baz}= boom").render_proc(Object.new, :foo, :baz, :boom)
         | 
| 343 | 
            +
                assert_equal("<p>1</p>\n<div baz='2' class='bar'>3</div>\n", proc[:foo => 1, :baz => 2, :boom => 3])
         | 
| 344 | 
            +
              end
         | 
| 345 | 
            +
             | 
| 346 | 
            +
              def test_render_proc_with_binding
         | 
| 347 | 
            +
                assert_equal("FOO\n", Haml::Engine.new("= upcase").render_proc("foo".instance_eval{binding}).call)
         | 
| 348 | 
            +
              end
         | 
| 261 349 | 
             
            end
         |