<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>vendor/plugins/haml/.gitignore</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/README.rdoc</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/haml.gemspec</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/haml/results/nuke_inner_whitespace.xhtml</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/haml/results/nuke_outer_whitespace.xhtml</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/haml/templates/nuke_inner_whitespace.haml</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/haml/templates/nuke_outer_whitespace.haml</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/haml/test_helper.rb</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/sass/results/mixins.css</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/sass/results/multiline.css</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/sass/templates/mixins.sass</filename>
    </added>
    <added>
      <filename>vendor/plugins/haml/test/sass/templates/multiline.sass</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,4 @@
-Copyright (c) 2006-2007 Hampton Catlin
+Copyright (c) 2006-2008 Hampton Catlin
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the</diff>
      <filename>vendor/plugins/haml/MIT-LICENSE</filename>
    </modified>
    <modified>
      <diff>@@ -20,153 +20,139 @@ END
 
 desc temp_desc.chomp
 task :benchmark do
-  require 'test/benchmark'
-
-  puts &quot;Running benchmarks #{ENV['TIMES']} times...&quot; if ENV['TIMES']
-  times = ENV['TIMES'].to_i if ENV['TIMES']
-  Haml.benchmark(times || 100)
-  puts '-'*51
+  sh &quot;ruby test/benchmark.rb #{ENV['TIMES']}&quot;
 end
 
-# Benchmarking gets screwed up if some other tasks have been
-# initialized.
-unless ARGV[0] == 'benchmark'
+# ----- Default: Testing ------
 
-  # ----- Default: Testing ------
+desc 'Default: run unit tests.'
+task :default =&gt; :test
 
-  desc 'Default: run unit tests.'
-  task :default =&gt; :test
+require 'rake/testtask'
 
-  require 'rake/testtask'
+Rake::TestTask.new do |t|
+  t.libs &lt;&lt; 'lib'
+  t.pattern = 'test/**/*_test.rb'
+  t.verbose = true
+end
+Rake::Task[:test].send(:add_comment, &lt;&lt;END)
+To run with an alternate version of Rails, make test/rails a symlink to that version.
+END
 
-  desc 'Test the Haml plugin'
-  Rake::TestTask.new(:test) do |t|
-    t.libs &lt;&lt; 'lib'
-    t.pattern = 'test/**/*_test.rb'
-    t.verbose = true
-  end
+# ----- Packaging -----
 
-  # ----- Packaging -----
-
-  require 'rake/gempackagetask'
-
-  spec = Gem::Specification.new do |spec|
-    spec.name = 'haml'
-    spec.summary = &quot;An elegant, structured XHTML/XML templating engine.\nComes with Sass, a similar CSS templating engine.&quot;
-    spec.version = File.read('VERSION').strip
-    spec.author = 'Hampton Catlin'
-    spec.email = 'haml@googlegroups.com'
-    spec.description = &lt;&lt;-END
-      Haml (HTML Abstraction Markup Language) is a layer on top of XHTML or XML
-      that's designed to express the structure of XHTML or XML documents
-      in a non-repetitive, elegant, easy way,
-      using indentation rather than closing tags
-      and allowing Ruby to be embedded with ease.
-      It was originally envisioned as a plugin for Ruby on Rails,
-      but it can function as a stand-alone templating engine.
-    END
-    #'
-    
-    readmes = FileList.new('*') do |list|
-      list.exclude(/[a-z]/)
-      list.exclude('TODO')
-    end.to_a
-    spec.executables = ['haml', 'html2haml', 'sass']
-    spec.files = FileList['lib/**/*', 'bin/*', 'test/**/*', 'Rakefile', 'init.rb'].to_a + readmes
-    spec.autorequire = ['haml', 'sass']
-    spec.homepage = 'http://haml.hamptoncatlin.com/'
-    spec.has_rdoc = true
-    spec.extra_rdoc_files = readmes
-    spec.rdoc_options += [
-      '--title', 'Haml',
-      '--main', 'README',
-      '--exclude', 'lib/haml/buffer.rb',
-      '--line-numbers',
-      '--inline-source'
-    ]
-    spec.test_files = FileList['test/**/*_test.rb'].to_a
-  end
+require 'rake/gempackagetask'
+require 'lib/haml'
+load    'haml.gemspec'
 
-  Rake::GemPackageTask.new(spec) do |pkg|
-    pkg.need_zip     = true
+Rake::GemPackageTask.new(HAML_GEMSPEC) do |pkg|
+  if Rake.application.top_level_tasks.include?('release')
     pkg.need_tar_gz  = true
     pkg.need_tar_bz2 = true
+    pkg.need_zip     = true
   end
+end
 
-  task :install =&gt; [:package] do
-    sh %{gem install --no-ri pkg/haml-#{File.read('VERSION').strip}}
+desc &quot;This is an internal task.&quot;
+task :revision_file do
+  if Haml.version[:rev] &amp;&amp; !Rake.application.top_level_tasks.include?('release')
+    File.open('REVISION', 'w') { |f| f.puts Haml.version[:rev] }
+  elsif Rake.application.top_level_tasks.include?('release')
+    File.open('REVISION', 'w') { |f| f.puts &quot;(release)&quot; }
+  else
+    File.open('REVISION', 'w') { |f| f.puts &quot;(unknown)&quot; }
   end
+end
+Rake::Task[:package].prerequisites.insert(0, :revision_file)
+
+# We also need to get rid of this file after packaging.
+Rake::Task[:package].enhance { File.delete('REVISION') if File.exists?('REVISION') }
+
+task :install =&gt; [:package] do
+  sudo = RUBY_PLATFORM =~ /win32/ ? '' : 'sudo'
+  sh %{#{sudo} gem install --no-ri pkg/haml-#{File.read('VERSION').strip}}
+end
+
+task :release =&gt; [:package] do
+  name, version = ENV['NAME'], ENV['VERSION']
+  raise &quot;Must supply NAME and VERSION for release task.&quot; unless name &amp;&amp; version
+  sh %{rubyforge login}
+  sh %{rubyforge add_release haml haml &quot;#{name} (v#{version})&quot; pkg/haml-#{version}.gem}
+  sh %{rubyforge add_file    haml haml &quot;#{name} (v#{version})&quot; pkg/haml-#{version}.tar.gz}
+  sh %{rubyforge add_file    haml haml &quot;#{name} (v#{version})&quot; pkg/haml-#{version}.tar.bz2}
+  sh %{rubyforge add_file    haml haml &quot;#{name} (v#{version})&quot; pkg/haml-#{version}.zip}
+end
 
-  # ----- Documentation -----
+# ----- Documentation -----
 
+begin
+  require 'hanna/rdoctask'
+rescue LoadError
   require 'rake/rdoctask'
+end
 
-  rdoc_task = Proc.new do |rdoc|
-    rdoc.title    = 'Haml/Sass'
-    rdoc.options &lt;&lt; '--line-numbers' &lt;&lt; '--inline-source'
-    rdoc.rdoc_files.include('README')
-    rdoc.rdoc_files.include('lib/**/*.rb')
-    rdoc.rdoc_files.exclude('lib/haml/buffer.rb')
-    rdoc.rdoc_files.exclude('lib/haml/util.rb')
-    rdoc.rdoc_files.exclude('lib/sass/tree/*')
-  end
+rdoc_task = Proc.new do |rdoc|
+  rdoc.title    = 'Haml/Sass'
+  rdoc.options &lt;&lt; '--line-numbers' &lt;&lt; '--inline-source'
+  rdoc.rdoc_files.include('README.rdoc')
+  rdoc.rdoc_files.include('lib/**/*.rb')
+  rdoc.rdoc_files.exclude('lib/haml/buffer.rb')
+  rdoc.rdoc_files.exclude('lib/sass/tree/*')
+end
 
-  Rake::RDocTask.new do |rdoc|
-    rdoc_task.call(rdoc)
-    rdoc.rdoc_dir = 'rdoc'
-  end
+Rake::RDocTask.new do |rdoc|
+  rdoc_task.call(rdoc)
+  rdoc.rdoc_dir = 'rdoc'
+end
 
-  Rake::RDocTask.new(:rdoc_devel) do |rdoc|
-    rdoc_task.call(rdoc)
-    rdoc.rdoc_dir = 'rdoc_devel'
-    rdoc.options &lt;&lt; '--all'
-    rdoc.rdoc_files.include('test/*.rb')
-    
-    # Get rid of exclusion rules
-    rdoc.rdoc_files = Rake::FileList.new(*rdoc.rdoc_files.to_a)
-    rdoc.rdoc_files.include('lib/haml/buffer.rb')
-    rdoc.rdoc_files.include('lib/sass/tree/*')
-  end
+Rake::RDocTask.new(:rdoc_devel) do |rdoc|
+  rdoc_task.call(rdoc)
+  rdoc.rdoc_dir = 'rdoc_devel'
+  rdoc.options &lt;&lt; '--all'
+  rdoc.rdoc_files.include('test/*.rb')
 
-  # ----- Coverage -----
-
-  unless not_loaded.include? 'rcov/rcovtask'
-    Rcov::RcovTask.new do |t|
-      t.libs &lt;&lt; &quot;test&quot;
-      t.test_files = FileList['test/**/*_test.rb']
-      t.rcov_opts &lt;&lt; '-x' &lt;&lt; '&quot;^\/&quot;'
-      if ENV['NON_NATIVE']
-        t.rcov_opts &lt;&lt; &quot;--no-rcovrt&quot;
-      end
-      t.verbose = true
+  # Get rid of exclusion rules
+  rdoc.rdoc_files = Rake::FileList.new(*rdoc.rdoc_files.to_a)
+  rdoc.rdoc_files.include('lib/haml/buffer.rb')
+  rdoc.rdoc_files.include('lib/sass/tree/*')
+end
+
+# ----- Coverage -----
+
+unless not_loaded.include? 'rcov/rcovtask'
+  Rcov::RcovTask.new do |t|
+    t.test_files = FileList['test/**/*_test.rb']
+    t.rcov_opts &lt;&lt; '-x' &lt;&lt; '&quot;^\/&quot;'
+    if ENV['NON_NATIVE']
+      t.rcov_opts &lt;&lt; &quot;--no-rcovrt&quot;
     end
+    t.verbose = true
   end
+end
 
-  # ----- Profiling -----
+# ----- Profiling -----
 
-  temp_desc = &lt;&lt;-END
+temp_desc = &lt;&lt;-END
   Run a profile of haml.
     ENGINE=str sets the engine to be profiled (Haml or Sass).
     TIMES=n sets the number of runs. Defaults to 100.
     FILE=n sets the file to profile. Defaults to 'standard'.
   END
-  desc temp_desc.chomp
-  task :profile do
-    require 'test/profile'
-
-    engine = ENV['ENGINE'] &amp;&amp; ENV['ENGINE'].downcase == 'sass' ? Sass : Haml
-    
-    puts '-'*51, &quot;Profiling #{engine}&quot;, '-'*51
-    
-    args = []
-    args.push ENV['TIMES'].to_i if ENV['TIMES']
-    args.push ENV['FILE'] if ENV['FILE']
-    
-    profiler = engine::Profiler.new
-    res = profiler.profile(*args)
-    puts res
-    
-    puts '-'*51
-  end
+desc temp_desc.chomp
+task :profile do
+  require 'test/profile'
+
+  engine = ENV['ENGINE'] &amp;&amp; ENV['ENGINE'].downcase == 'sass' ? Sass : Haml
 
+  puts '-'*51, &quot;Profiling #{engine}&quot;, '-'*51
+
+  args = []
+  args.push ENV['TIMES'].to_i if ENV['TIMES']
+  args.push ENV['FILE'] if ENV['FILE']
+
+  profiler = engine::Profiler.new
+  res = profiler.profile(*args)
+  puts res
+
+  puts '-'*51
 end</diff>
      <filename>vendor/plugins/haml/Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,17 +1,9 @@
-Bugs:
-  If an @imported document is changed, Sass should recompile the template
-
 Testing:
   Test html2haml and css2sass
 
-Documentation:
-  Haml::Engine public method documentation could use work
-  !! Document at-rules.
-
 Features:
   Sass should throw generic errors for undefined constants, not syntax errors
   Sass::Plugin should log errors
-  There should be a way to represent options in-document
   There should be a way to make Haml tags not insert whitespace
   &quot;%li, %a&quot;?
   Sass::Engine load_paths option should be set by executable</diff>
      <filename>vendor/plugins/haml/TODO</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,4 @@
 ;;; haml-mode.el -- Major mode for editing Haml files
-;;; Version 0.0.1
 ;;; Written by Nathan Weizenbaum
 
 ;;; Because Haml's indentation schema is similar
@@ -7,13 +6,16 @@
 ;;; functions are similar to those in yaml-mode and python-mode.
 
 ;;; To install, save this somewhere and add the following to your .emacs file:
-;;; 
+;;;
 ;;; (add-to-list 'load-path &quot;/path/to/haml-mode.el&quot;)
 ;;; (require 'haml-mode nil 't)
-;;; 
+;;; (add-to-list 'auto-mode-alist '(&quot;\\.sass$&quot; . sass-mode))
+;;;
 
 ;;; Code:
 
+(eval-when-compile (require 'cl))
+
 ;; User definable variables
 
 (defgroup haml nil
@@ -22,120 +24,73 @@
   :prefix &quot;haml-&quot;)
 
 (defcustom haml-mode-hook nil
-  &quot;*Hook run by `haml-mode'.&quot;
+  &quot;Hook run when entering Haml mode.&quot;
   :type 'hook
   :group 'haml)
 
 (defcustom haml-indent-offset 2
-  &quot;*Amount of offset per level of indentation.&quot;
+  &quot;Amount of offset per level of indentation.&quot;
   :type 'integer
   :group 'haml)
 
-(defcustom haml-backspace-function 'backward-delete-char-untabify
-  &quot;*Function called by `haml-electric-backspace' when deleting backwards.&quot;
-  :type 'function
+(defcustom haml-backspace-backdents-nesting t
+  &quot;Non-nil to have `haml-electric-backspace' re-indent all code
+nested beneath the backspaced line be re-indented along with the
+line itself.&quot;
+  :type 'boolean
   :group 'haml)
 
 (defface haml-tab-face
-   '((((class color)) (:background &quot;red&quot; :foreground &quot;red&quot; :bold t))
-     (t (:reverse-video t)))
+  '((((class color)) (:background &quot;hotpink&quot;))
+    (t (:reverse-video t)))
   &quot;Face to use for highlighting tabs in Haml files.&quot;
   :group 'faces
   :group 'haml)
 
-;; Helper Functions
-
-(defun string-* (str n)
-  &quot;Concatenates a string with itself n times.&quot;
-  (if (= n 0) &quot;&quot;
-    (concat str (string-* str (- n 1)))))
-
-(defun find-if (f lst)
-  &quot;Returns the first element of a list for which a function returns a non-nil value, or nil if no such element is found.&quot;
-  (while (not (or (null lst)
-                  (apply f (list (car lst)))))
-    (setq lst (cdr lst)))
-  (if (null lst) nil (car lst)))
-
-(defun hre (str)
-  &quot;Prepends a Haml-tab-matching regexp to str.&quot;
-  (concat &quot;^\\(&quot; (string-* &quot; &quot; haml-indent-offset) &quot;\\)*&quot; str))
+(defvar haml-indent-function 'haml-indent-p
+  &quot;This function should look at the current line and return true
+if the next line could be nested within this line.&quot;)
+
+(defvar haml-block-openers
+  `(&quot;^ *\\([%\\.#][^ \t]*\\)\\(\\[.*\\]\\)?\\({.*}\\)?\\(\\[.*\\]\\)?[ \t]*$&quot;
+    &quot;^ *[-=].*do[ \t]*\\(|.*|[ \t]*\\)?$&quot;
+    ,(concat &quot;^ *-[ \t]*\\(&quot;
+             (regexp-opt '(&quot;else&quot; &quot;elsif&quot; &quot;rescue&quot; &quot;ensure&quot; &quot;when&quot;))
+             &quot;\\)&quot;)
+    &quot;^ */\\(\\[.*\\]\\)?[ \t]*$&quot;
+    &quot;^ *-#&quot;
+    &quot;^ *:&quot;)
+  &quot;A list of regexps that match lines of Haml that could have
+text nested beneath them.&quot;)
 
 ;; Font lock
 
-(defconst haml-font-lock-keywords-1
-  (list
-   ;; instruct
-   '(&quot;^!!!.*&quot;                    0 font-lock-constant-face)
-   ;; strings
-   '(&quot;\\('[^']*'\\)&quot;             1 font-lock-string-face append)
-   '(&quot;\\(\&quot;[^\&quot;]*\&quot;\\)&quot;          1 font-lock-string-face append)
-   ;; symbol
-   '(&quot;&amp;?:\\w+&quot;                   0 font-lock-constant-face append)
-   ;; ruby varible
-   '(&quot;@[a-z0-9_]+&quot;               0 font-lock-variable-name-face append)
-   ;; pipe
-   '(&quot;| *$&quot;                      0 font-lock-string-face)
-   ;; comment
-   '(&quot;^[ \t]*\\(/.*\\)$&quot;         1 font-lock-comment-face append)
-   ;; id
-   '(&quot;^ *\\(#[a-z0-9_]+\/?\\)&quot;   1 font-lock-keyword-face)
-   ;; class
-   '(&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; 1 font-lock-type-face)
-   ;; tag
-   '(&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   1 font-lock-function-name-face )
-   ;; class after id
-   '(&quot;^ *\\(#[a-z0-9_]+\/?\\)&quot;   (1 font-lock-keyword-face) (&quot;\\.[a-z0-9_]+&quot; nil nil (0 font-lock-type-face)))
-   ;; class after class
-   '(&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; (1 font-lock-type-face) (&quot;\\.[a-z0-9_]+&quot; nil nil (0 font-lock-type-face)))
-   ;; id after class
-   '(&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; (1 font-lock-type-face) (&quot;\\#[a-z0-9_]+&quot; nil nil (0 font-lock-keyword-face)))
-   ;; class after tag
-   '(&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   (1 font-lock-function-name-face) (&quot;\\.[a-z0-9_]+&quot; nil nil (0 font-lock-type-face)))
-   ;; id after tag
-   '(&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   (1 font-lock-function-name-face) (&quot;\\#[a-z0-9_]+&quot; nil nil (0 font-lock-keyword-face)))
-   ;; embeded ruby: beggin of line
-   '(&quot;^ *\\([~=-] .*\\)&quot;          1 font-lock-preprocessor-face prepend)
-   ;; embeded ruby: after tag,class,id
-   '(&quot;^ *[\\.#%a-z0-9_]+\\([~=-] .*\\)&quot;     1 font-lock-preprocessor-face prepend)
-   ;; embeded ruby: attributes
-   '(&quot;^ *[\\.#%a-z0-9_]+\\({[^}]+}\\)&quot;      1 font-lock-preprocessor-face prepend)
-   ;; embeded ruby: square
-   '(&quot;^ *[\\.#%a-z0-9_]+\\(\\[[^]]+\\]\\)&quot;  1 font-lock-preprocessor-face prepend)))
-
-;; Constants
-
-(defconst haml-mode-version &quot;0.0.1&quot; &quot;Version of `haml-mode.'&quot;)
-
-(defconst haml-blank-line-re &quot;^[ \t]*$&quot;
-  &quot;Regexp matching a line containing only whitespace.&quot;)
-
-; Base for Regexen matching a Haml tag.
-(setq haml-tag-re-base (hre &quot;\\([%\\.#][^ \t]*\\)\\({.*}\\)?\\(\\[.*\\]\\)?&quot;))
-
-(defconst haml-tag-nest-re (concat haml-tag-re-base &quot;[ \t]*$&quot;)
-  &quot;Regexp matching a Haml tag that can have nested elements.&quot;)
-
-(defconst haml-tag-re (concat haml-tag-re-base &quot;\\(.?\\)&quot;)
-  &quot;Regexp matching a Haml tag.&quot;)
-
-(defconst haml-block-re (hre &quot;[-=].*do[ \t]*\\(|.*|[ \t]*\\)?$&quot;)
-  &quot;Regexp matching a Ruby block in Haml.&quot;)
-
-(defconst haml-block-cont-re (hre (concat &quot;-[ \t]*&quot;
-                                          (regexp-opt '(&quot;else&quot; &quot;elsif&quot;
-                                                        &quot;rescue&quot; &quot;ensure&quot;
-                                                        &quot;when&quot;))))
-  &quot;Regexp matching a continued Ruby block in Haml.&quot;)
-
-(defconst haml-html-comment-re (hre &quot;/\\(\\[.*\\]\\)?[ \t]*$&quot;)
-  &quot;Regexp matching a Haml HTML comment command.&quot;)
-
-(defconst haml-comment-re (hre &quot;-#[ \t]$&quot;)
-  &quot;Regexp matching a Haml comment command.&quot;)
-
-(defconst haml-filter-re (hre &quot;:&quot;)
-  &quot;Regexp matching a Haml filter command.&quot;)
+(defconst haml-font-lock-keywords
+  '((&quot;^ *\\(\t\\)&quot;               1 'haml-tab-face)
+    (&quot;^!!!.*&quot;                    0 font-lock-constant-face)
+    (&quot;\\('[^']*'\\)&quot;             1 font-lock-string-face append)
+    (&quot;\\(\&quot;[^\&quot;]*\&quot;\\)&quot;          1 font-lock-string-face append)
+    (&quot;&amp;?:\\w+&quot;                   0 font-lock-constant-face append)
+    (&quot;@[a-z0-9_]+&quot;               0 font-lock-variable-name-face append)
+    (&quot;| *$&quot;                      0 font-lock-string-face)
+    (&quot;^[ \t]*\\(/.*\\)$&quot;         1 font-lock-comment-face append)
+    (&quot;^ *\\(#[a-z0-9_]+\/?\\)&quot;   1 font-lock-keyword-face)
+    (&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; 1 font-lock-type-face)
+    (&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   1 font-lock-function-name-face)
+    (&quot;^ *\\(#[a-z0-9_]+\/?\\)&quot;   (1 font-lock-keyword-face)
+     (&quot;\\.[a-z0-9_]+&quot; nil nil    (0 font-lock-type-face)))
+    (&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; (1 font-lock-type-face)
+     (&quot;\\.[a-z0-9_]+&quot; nil nil    (0 font-lock-type-face)))
+    (&quot;^ *\\(\\.[a-z0-9_]+\/?\\)&quot; (1 font-lock-type-face)
+     (&quot;\\#[a-z0-9_]+&quot; nil nil    (0 font-lock-keyword-face)))
+    (&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   (1 font-lock-function-name-face)
+     (&quot;\\.[a-z0-9_]+&quot; nil nil    (0 font-lock-type-face)))
+    (&quot;^ *\\(%[a-z0-9_]+\/?\\)&quot;   (1 font-lock-function-name-face)
+     (&quot;\\#[a-z0-9_]+&quot; nil nil    (0 font-lock-keyword-face)))
+    (&quot;^ *\\([~=-] .*\\)&quot;         1 font-lock-preprocessor-face prepend)
+    (&quot;^ *[\\.#%a-z0-9_]+\\([~=-] .*\\)&quot;     1 font-lock-preprocessor-face prepend)
+    (&quot;^ *[\\.#%a-z0-9_]+\\({[^}]+}\\)&quot;      1 font-lock-preprocessor-face prepend)
+    (&quot;^ *[\\.#%a-z0-9_]+\\(\\[[^]]+\\]\\)&quot;  1 font-lock-preprocessor-face prepend)))
 
 ;; Mode setup
 
@@ -146,45 +101,169 @@
     table)
   &quot;Syntax table in use in haml-mode buffers.&quot;)
 
-(defvar haml-mode-map ()
-  &quot;Keymap used in `haml-mode' buffers.&quot;)
-(if haml-mode-map
-    nil
-  (setq haml-mode-map (make-sparse-keymap))
-  (define-key haml-mode-map [backspace] 'haml-electric-backspace)
-  (define-key haml-mode-map &quot;\C-?&quot; 'haml-electric-backspace)
-  (define-key haml-mode-map &quot;\C-j&quot; 'newline-and-indent))
+(defvar haml-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [backspace] 'haml-electric-backspace)
+    (define-key map &quot;\C-?&quot; 'haml-electric-backspace)
+    (define-key map &quot;\C-\M-f&quot; 'haml-forward-sexp)
+    (define-key map &quot;\C-\M-b&quot; 'haml-backward-sexp)
+    (define-key map &quot;\C-\M-u&quot; 'haml-up-list)
+    (define-key map &quot;\C-\M-d&quot; 'haml-down-list)
+    (define-key map &quot;\C-C\C-k&quot; 'haml-kill-line-and-indent)
+    map))
 
 (define-derived-mode haml-mode fundamental-mode &quot;Haml&quot;
-  &quot;Simple mode to edit Haml.
+  &quot;Major mode for editing Haml files.
 
 \\{haml-mode-map}&quot;
   (set-syntax-table haml-mode-syntax-table)
   (set (make-local-variable 'indent-line-function) 'haml-indent-line)
-  (set (make-local-variable 'font-lock-defaults)
-       '((haml-font-lock-keywords-1)
-         nil
-         t)))
+  (set (make-local-variable 'indent-region-function) 'haml-indent-region)
+  (set (make-local-variable 'forward-sexp-function) 'haml-forward-sexp)
+  (setq font-lock-defaults '((haml-font-lock-keywords) nil t)))
+
+;; Navigation
+
+(defun haml-forward-through-whitespace (&amp;optional backward)
+  &quot;Move the point forward at least one line, until it reaches
+either the end of the buffer or a line with no whitespace.
+
+If `backward' is non-nil, move the point backward instead.&quot;
+  (let ((arg (if backward -1 1))
+        (endp (if backward 'bobp 'eobp)))
+    (loop do (forward-line arg)
+          while (and (not (funcall endp))
+                     (looking-at &quot;^[ \t]*$&quot;)))))
+
+(defun haml-at-indent-p ()
+  &quot;Returns whether or not the point is at the first
+non-whitespace character in a line or whitespace preceding that
+character.&quot;
+  (let ((opoint (point)))
+    (save-excursion
+      (back-to-indentation)
+      (&gt;= (point) opoint))))
+
+(defun haml-forward-sexp (&amp;optional arg)
+  &quot;Move forward across one nested expression.
+With `arg', do it that many times.  Negative arg -N means move
+backward across N balanced expressions.
+
+A sexp in Haml is defined as a line of Haml code as well as any
+lines nested beneath it.&quot;
+  (interactive &quot;p&quot;)
+  (or arg (setq arg 1))
+  (if (and (&lt; arg 0) (not (haml-at-indent-p)))
+      (back-to-indentation)
+    (while (/= arg 0)
+      (let ((indent (current-indentation)))
+        (loop do (haml-forward-through-whitespace (&lt; arg 0))
+              while (and (not (eobp))
+                         (not (bobp))
+                         (&gt; (current-indentation) indent)))
+        (back-to-indentation)
+      (setq arg (+ arg (if (&gt; arg 0) -1 1)))))))
+
+(defun haml-backward-sexp (&amp;optional arg)
+  &quot;Move backward across one nested expression.
+With ARG, do it that many times.  Negative arg -N means move
+forward across N balanced expressions.
+
+A sexp in Haml is defined as a line of Haml code as well as any
+lines nested beneath it.&quot;
+  (interactive &quot;p&quot;)
+  (haml-forward-sexp (if arg (- arg) -1)))
+
+(defun haml-up-list (&amp;optional arg)
+  &quot;Move out of one level of nesting.
+With ARG, do this that many times.&quot;
+  (interactive &quot;p&quot;)
+  (or arg (setq arg 1))
+  (while (&gt; arg 0)
+    (let ((indent (current-indentation)))
+      (loop do (haml-forward-through-whitespace t)
+            while (and (not (bobp))
+                       (&gt;= (current-indentation) indent)))
+      (setq arg (- arg 1))))
+  (back-to-indentation))
+
+(defun haml-down-list (&amp;optional arg)
+  &quot;Move down one level of nesting.
+With ARG, do this that many times.&quot;
+  (interactive &quot;p&quot;)
+  (or arg (setq arg 1))
+  (while (&gt; arg 0)
+    (let ((indent (current-indentation)))
+      (haml-forward-through-whitespace)
+      (when (&lt;= (current-indentation) indent)
+        (haml-forward-through-whitespace t)
+        (back-to-indentation)
+        (error &quot;Nothing is nested beneath this line&quot;))
+      (setq arg (- arg 1))))
+  (back-to-indentation))
+
+(defun haml-mark-sexp-but-not-next-line ()
+  &quot;Marks the next Haml sexp, but puts the mark at the end of the
+last line of the sexp rather than the first non-whitespace
+character of the next line.&quot;
+  (mark-sexp)
+  (set-mark
+   (save-excursion
+     (goto-char (mark))
+     (forward-line -1)
+     (end-of-line)
+     (point))))
 
 ;; Indentation and electric keys
 
+(defun haml-indent-p ()
+  &quot;Returns true if the current line can have lines nested beneath it.&quot;
+  (loop for opener in haml-block-openers
+        if (looking-at opener) return t
+        finally return nil))
+
 (defun haml-compute-indentation ()
   &quot;Calculate the maximum sensible indentation for the current line.&quot;
   (save-excursion
     (beginning-of-line)
-    (if (bobp) 10
-      (forward-line -1)
-      (while (and (looking-at haml-blank-line-re)
-                  (&gt; (point) (point-min)))
-        (forward-line -1))
+    (if (bobp) 0
+      (haml-forward-through-whitespace t)
       (+ (current-indentation)
-         (if (or (looking-at haml-filter-re)
-                 (looking-at haml-comment-re)
-                 (looking-at haml-html-comment-re)
-                 (looking-at haml-block-cont-re)
-                 (looking-at haml-tag-nest-re)
-                 (looking-at haml-block-re))
-             haml-indent-offset 0)))))
+         (if (funcall haml-indent-function) haml-indent-offset
+           0)))))
+
+(defun haml-indent-region (start end)
+  &quot;Indent each nonblank line in the region.
+This is done by indenting the first line based on
+`haml-compute-indentation' and preserving the relative
+indentation of the rest of the region.
+
+If this command is used multiple times in a row, it will cycle
+between possible indentations.&quot;
+  (save-excursion
+    (goto-char end)
+    (setq end (point-marker))
+    (goto-char start)
+    (let (this-line-column current-column
+          (next-line-column
+           (if (and (equal last-command this-command) (/= (current-indentation) 0))
+               (* (/ (- (current-indentation) 1) haml-indent-offset) haml-indent-offset)
+             (haml-compute-indentation))))
+      (while (&lt; (point) end)
+        (setq this-line-column next-line-column
+              current-column (current-indentation))
+        ;; Delete whitespace chars at beginning of line
+        (delete-horizontal-space)
+        (unless (eolp)
+          (setq next-line-column (save-excursion
+                                   (loop do (forward-line 1)
+                                         while (and (not (eobp)) (looking-at &quot;^[ \t]*$&quot;)))
+                                   (+ this-line-column
+                                      (- (current-indentation) current-column))))
+          ;; Don't indent an empty line
+          (unless (eolp) (indent-to this-line-column)))
+        (forward-line 1)))
+    (move-marker end nil)))
 
 (defun haml-indent-line ()
   &quot;Indent the current line.
@@ -205,33 +284,46 @@ back-dent the line by `haml-indent-offset' spaces.  On reaching column
       (if (&lt; (current-column) (current-indentation))
           (forward-to-indentation 0))))
 
+(defun haml-reindent-region-by (n)
+  &quot;Add N spaces to the beginning of each line in the region.
+If N is negative, will remove the spaces instead.  Assumes all
+lines in the region have indentation &gt;= that of the first line.&quot;
+  (let ((ci (current-indentation)))
+    (save-excursion
+      (replace-regexp (concat &quot;^&quot; (make-string ci ? ))
+                      (make-string (max 0 (+ ci n)) ? )
+                      nil (point) (mark)))))
+
 (defun haml-electric-backspace (arg)
   &quot;Delete characters or back-dent the current line.
-If invoked following only whitespace on a line, will back-dent to the
-immediately previous multiple of `haml-indent-offset' spaces.&quot;
+If invoked following only whitespace on a line, will back-dent
+the line and all nested lines to the immediately previous
+multiple of `haml-indent-offset' spaces.
+
+Set `haml-backspace-backdents-nesting' to nil to just back-dent
+the current line.&quot;
   (interactive &quot;*p&quot;)
-  (if (or (/= (current-indentation) (current-column)) (bolp))
-      (funcall haml-backspace-function arg)
+  (if (or (/= (current-indentation) (current-column))
+          (bolp)
+          (looking-at &quot;^[ \t]+$&quot;))
+      (backward-delete-char arg)
     (let ((ci (current-column)))
       (beginning-of-line)
-      (delete-horizontal-space)
-      (indent-to (* (/ (- ci (* arg haml-indent-offset))
-                       haml-indent-offset)
-                    haml-indent-offset)))))
+      (if haml-backspace-backdents-nesting
+          (haml-mark-sexp-but-not-next-line)
+        (set-mark (save-excursion (end-of-line) (point))))
+      (haml-reindent-region-by (* (- arg) haml-indent-offset))
+      (back-to-indentation)
+      (pop-mark))))
+
+(defun haml-kill-line-and-indent ()
+  &quot;Kill the current line, and re-indent all lines nested beneath it.&quot;
+  (interactive)
+  (beginning-of-line)
+  (haml-mark-sexp-but-not-next-line)
+  (kill-line 1)
+  (haml-reindent-region-by (* -1 haml-indent-offset)))
 
 ;; Setup/Activation
 
-(defun haml-mode-version ()
-  &quot;Diplay version of `haml-mode'.&quot;
-  (interactive)
-  (message &quot;haml-mode %s&quot; haml-mode-version)
-  haml-mode-version)
-
 (provide 'haml-mode)
-
-(unless (find-if
-         #'(lambda(it) (string= it &quot;\\.haml\\'&quot;))
-         (mapcar 'car auto-mode-alist))
-  (add-to-list 'auto-mode-alist '(&quot;\\.haml\\'&quot; . haml-mode)))
-
-;;; haml-mode.el ends here</diff>
      <filename>vendor/plugins/haml/extra/haml-mode.el</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,4 @@
 ;;; sass-mode.el -- Major mode for editing Sass files
-;;; Version 0.0.1
 ;;; Written by Nathan Weizenbaum
 
 ;;; Because Sass's indentation schema is similar
@@ -7,13 +6,16 @@
 ;;; functions are similar to those in yaml-mode and python-mode.
 
 ;;; To install, save this somewhere and add the following to your .emacs file:
-;;; 
+;;;
 ;;; (add-to-list 'load-path &quot;/path/to/sass-mode.el&quot;)
 ;;; (require 'sass-mode nil 't)
-;;; 
+;;; (add-to-list 'auto-mode-alist '(&quot;\\.sass$&quot; . sass-mode))
+;;;
 
 ;;; Code:
 
+(require 'haml-mode)
+
 ;; User definable variables
 
 (defgroup sass nil
@@ -22,134 +24,65 @@
   :prefix &quot;sass-&quot;)
 
 (defcustom sass-mode-hook nil
-  &quot;*Hook run by `sass-mode'.&quot;
+  &quot;Hook run when entering Sass mode.&quot;
   :type 'hook
   :group 'sass)
 
 (defcustom sass-indent-offset 2
-  &quot;*Amount of offset per level of indentation.&quot;
+  &quot;Amount of offset per level of indentation.&quot;
   :type 'integer
   :group 'sass)
 
-(defcustom sass-backspace-function 'backward-delete-char-untabify
-  &quot;*Function called by `sass-electric-backspace' when deleting backwards.&quot;
-  :type 'function
-  :group 'sass)
-
-(defface sass-tab-face
-   '((((class color)) (:background &quot;red&quot; :foreground &quot;red&quot; :bold t))
-     (t (:reverse-video t)))
-  &quot;Face to use for highlighting tabs in Sass files.&quot;
-  :group 'faces
-  :group 'sass)
-
-;; Helper Functions
-
-(defun string-* (str n)
-  &quot;Concatenates a string with itself n times.&quot;
-  (if (= n 0) &quot;&quot;
-    (concat str (string-* str (- n 1)))))
-
-(defun find-if (f lst)
-  &quot;Returns the first element of a list for which a function returns a non-nil value, or nil if no such element is found.&quot;
-  (while (not (or (null lst)
-                  (apply f (list (car lst)))))
-    (setq lst (cdr lst)))
-  (if (null lst) nil (car lst)))
-
-(defun sre (str)
-  &quot;Prepends a Sass-tab-matching regexp to str.&quot;
-  (concat &quot;^\\(&quot; (string-* &quot; &quot; sass-indent-offset) &quot;\\)*&quot; str))
+(defvar sass-non-block-openers
+  '(&quot;^ *:[^ \t]+[ \t]+[^ \t]&quot;
+    &quot;^ *[^ \t:]+[ \t]*[=:][ \t]*[^ \t]&quot;)
+  &quot;A list of regexps that match lines of Sass that couldn't have
+text nested beneath them.&quot;)
+
+;; Font lock
+
+(defconst sass-font-lock-keywords
+  '((&quot;^ *\\(\t\\)&quot;                            1 'haml-tab-face)
+    (&quot;^@.*&quot;                                   0 font-lock-constant-face)
+    (&quot;\\(\'[^']*'\\)&quot;                         1 font-lock-string-face append)
+    (&quot;\\(\&quot;[^\&quot;]*\&quot;\\)&quot;                       1 font-lock-string-face append)
+    (&quot;\\(#[0-9a-fA-F]\\{3\\}\\{1,2\\}\\&gt;\\)&quot;  1 font-lock-string-face append)
+    (&quot;\\(:[A-Za-z-]+\\|[A-Za-z-]+:\\)&quot;        0 font-lock-constant-face append)
+    (&quot;![a-z0-9_-]+&quot;                           0 font-lock-variable-name-face append)
+    (&quot;^ *\\(/[/*].*\\)$&quot;                      1 font-lock-comment-face append)
+    (&quot;\\(?:^\\|,\\) *\\(#[a-z0-9_-]+\/?\\)&quot;   1 font-lock-keyword-face)
+    (&quot;\\(?:^\\|,\\) *\\(\\.[a-z0-9_-]+\/?\\)&quot; 1 font-lock-type-face)
+    (&quot;\\(?:^\\|,\\) *\\(&amp;\\|[a-z0-9_]+\/?\\)&quot; 1 font-lock-function-name-face)
+    (&quot;\\([=]\\)&quot;                              0 font-lock-preprocessor-face prepend)
+    (&quot;\\(?:^\\|,\\) *\\(#[a-z0-9_]+\/?\\)&quot;    (1 font-lock-keyword-face)
+     (&quot;\\.[a-z0-9_-]+&quot; nil nil                (0 font-lock-type-face)))
+    (&quot;\\(?:^\\|,\\) *\\(\\.[a-z0-9_]+\/?\\)&quot;  (1 font-lock-type-face)
+     (&quot;\\.[a-z0-9_-]+&quot; nil nil                (0 font-lock-type-face)))
+    (&quot;\\(?:^\\|,\\) *\\(\\.[a-z0-9_]+\/?\\)&quot;  (1 font-lock-type-face)
+     (&quot;\\#[a-z0-9_-]+&quot; nil nil                (0 font-lock-keyword-face)))
+    (&quot;\\(?:^\\|,\\) *\\(&amp;\\|[a-z0-9_]+\/?\\)&quot; (1 font-lock-function-name-face)
+     (&quot;\\.[a-z0-9_-]+&quot; nil nil                (0 font-lock-type-face)))
+    (&quot;\\(?:^\\|,\\) *\\(&amp;\\|[a-z0-9_]+\/?\\)&quot; (1 font-lock-function-name-face)
+     (&quot;\\#[a-z0-9_-]+&quot; nil nil                (0 font-lock-keyword-face)))))
 
 ;; Constants
 
-(defconst sass-mode-version &quot;0.0.1&quot; &quot;Version of `sass-mode.'&quot;)
-
-(defconst sass-blank-line-re &quot;^[ \t]*$&quot;
-  &quot;Regexp matching a line containing only whitespace.&quot;)
+;; Mode setup
 
-(defconst sass-full-attr-re (sre &quot;:[^ \t]+[ \t]+[^ \t]&quot;)
-  &quot;Regexp matching a Sass attribute with content.&quot;)
+(define-derived-mode sass-mode haml-mode &quot;Sass&quot;
+  &quot;Major mode for editing Sass files.&quot;
+  (set (make-local-variable 'haml-indent-function) 'sass-indent-p)
+  (set (make-local-variable 'haml-indent-offset) sass-indent-offset)
+  (setq font-lock-defaults '(sass-font-lock-keywords nil t)))
 
-;; Mode setup
+;; Indentation
 
-(defvar sass-mode-map ()
-  &quot;Keymap used in `sass-mode' buffers.&quot;)
-(if sass-mode-map
-    nil
-  (setq sass-mode-map (make-sparse-keymap))
-  (define-key sass-mode-map [backspace] 'sass-electric-backspace)
-  (define-key sass-mode-map &quot;\C-?&quot; 'sass-electric-backspace)
-  (define-key sass-mode-map &quot;\C-j&quot; 'newline-and-indent))
-
-(define-derived-mode sass-mode fundamental-mode &quot;Sass&quot;
-  &quot;Simple mode to edit Sass.
-
-\\{sass-mode-map}&quot;
-  (set (make-local-variable 'indent-line-function) 'sass-indent-line))
-
-;; Indentation and electric keys
-
-(defun sass-compute-indentation ()
-  &quot;Calculate the maximum sensible indentation for the current line.&quot;
-  (save-excursion
-    (beginning-of-line)
-    (if (bobp) 10
-      (forward-line -1)
-      (while (and (looking-at sass-blank-line-re)
-                  (&gt; (point) (point-min)))
-        (forward-line -1))
-      (+ (current-indentation)
-         (if (not (looking-at sass-full-attr-re))
-             sass-indent-offset 0)))))
-
-(defun sass-indent-line ()
-  &quot;Indent the current line.
-The first time this command is used, the line will be indented to the
-maximum sensible indentation.  Each immediately subsequent usage will
-back-dent the line by `sass-indent-offset' spaces.  On reaching column
-0, it will cycle back to the maximum sensible indentation.&quot;
-  (interactive &quot;*&quot;)
-  (let ((ci (current-indentation))
-        (cc (current-column))
-        (need (sass-compute-indentation)))
-    (save-excursion
-      (beginning-of-line)
-      (delete-horizontal-space)
-      (if (and (equal last-command this-command) (/= ci 0))
-          (indent-to (* (/ (- ci 1) sass-indent-offset) sass-indent-offset))
-        (indent-to need)))
-      (if (&lt; (current-column) (current-indentation))
-          (forward-to-indentation 0))))
-
-(defun sass-electric-backspace (arg)
-  &quot;Delete characters or back-dent the current line.
-If invoked following only whitespace on a line, will back-dent to the
-immediately previous multiple of `sass-indent-offset' spaces.&quot;
-  (interactive &quot;*p&quot;)
-  (if (or (/= (current-indentation) (current-column)) (bolp))
-      (funcall sass-backspace-function arg)
-    (let ((ci (current-column)))
-      (beginning-of-line)
-      (delete-horizontal-space)
-      (indent-to (* (/ (- ci (* arg sass-indent-offset))
-                       sass-indent-offset)
-                    sass-indent-offset)))))
+(defun sass-indent-p ()
+  &quot;Returns true if the current line can have lines nested beneath it.&quot;
+  (loop for opener in sass-non-block-openers
+        unless (looking-at opener) return t
+        return nil))
 
 ;; Setup/Activation
 
-(defun sass-mode-version ()
-  &quot;Diplay version of `sass-mode'.&quot;
-  (interactive)
-  (message &quot;sass-mode %s&quot; sass-mode-version)
-  sass-mode-version)
-
 (provide 'sass-mode)
-
-
-(unless (find-if
-         #'(lambda(it) (string= it &quot;\\.sass\\'&quot;))
-         (mapcar 'car auto-mode-alist))
-  (add-to-list 'auto-mode-alist '(&quot;\\.sass\\'&quot; . sass-mode)))
-
-;;; sass-mode.el ends here</diff>
      <filename>vendor/plugins/haml/extra/sass-mode.el</filename>
    </modified>
    <modified>
      <diff>@@ -2,18 +2,18 @@ dir = File.dirname(__FILE__)
 $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 
 # = Haml (XHTML Abstraction Markup Language)
-# 
+#
 # Haml is a markup language
 # that's used to cleanly and simply describe the XHTML of any web document,
 # without the use of inline code.
 # Haml functions as a replacement
-# for inline page templating systems such as PHP, ERB, and ASP. 
-# However, Haml avoids the need for explicitly coding XHTML into the template, 
+# for inline page templating systems such as PHP, ERB, and ASP.
+# However, Haml avoids the need for explicitly coding XHTML into the template,
 # because it is actually an abstract description of the XHTML,
 # with some code to generate dynamic content.
-# 
+#
 # == Features
-# 
+#
 # * Whitespace active
 # * Well-formatted markup
 # * DRY
@@ -36,9 +36,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #
 # To enable it as a Rails plugin,
 # then run
-# 
+#
 #   haml --rails path/to/rails/app
-# 
+#
 # Haml is enabled in Merb by default,
 # so Merb users don't have to do anything more.
 #
@@ -50,24 +50,24 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # the same way you do in ERb templates.
 # Helper methods are also available in Haml templates.
 # For example (this example uses Rails, but the principle for Merb is the same):
-# 
+#
 #   # file: app/controllers/movies_controller.rb
-# 
+#
 #   class MoviesController &lt; ApplicationController
 #     def index
 #       @title = &quot;Teen Wolf&quot;
 #     end
 #   end
-# 
+#
 #   -# file: app/views/movies/index.haml
-# 
+#
 #   #content
 #    .title
 #      %h1= @title
 #      = link_to 'Home', home_url
-# 
+#
 # may be compiled to:
-# 
+#
 #   &lt;div id='content'&gt;
 #     &lt;div class='title'&gt;
 #       &lt;h1&gt;Teen Wolf&lt;/h1&gt;
@@ -89,41 +89,41 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #   engine.render #=&gt; &quot;&lt;p&gt;Haml code!&lt;/p&gt;\n&quot;
 #
 # == Characters with meaning to Haml
-# 
+#
 # Various characters, when placed at a certain point in a line,
 # instruct Haml to render different types of things.
-# 
+#
 # === XHTML Tags
-# 
+#
 # These characters render XHTML tags.
-# 
+#
 # ==== %
-# 
-# 
+#
+#
 # The percent character is placed at the beginning of a line.
 # It's followed immediately by the name of an element,
 # then optionally by modifiers (see below), a space,
 # and text to be rendered inside the element.
 # It creates an element in the form of &lt;tt&gt;&lt;element&gt;&lt;/element&gt;&lt;/tt&gt;.
 # For example:
-# 
+#
 #   %one
 #     %two
 #       %three Hey there
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;one&gt;
 #     &lt;two&gt;
 #       &lt;three&gt;Hey there&lt;/three&gt;
 #     &lt;/two&gt;
 #   &lt;/one&gt;
-# 
+#
 # Any string is a valid element name;
 # Haml will automatically generate opening and closing tags for any element.
-# 
+#
 # ==== {}
-# 
+#
 # Brackets represent a Ruby hash
 # that is used for specifying the attributes of an element.
 # It is literally evaluated as a Ruby hash,
@@ -132,20 +132,88 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # will be replaced by appropriate escape sequences.
 # The hash is placed after the tag is defined.
 # For example:
-# 
+#
 #   %head{ :name =&gt; &quot;doc_head&quot; }
 #     %script{ 'type' =&gt; &quot;text/&quot; + &quot;javascript&quot;,
 #              :src   =&gt; &quot;javascripts/script_#{2 + 7}&quot; }
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;head name=&quot;doc_head&quot;&gt;
 #     &lt;script src='javascripts/script_9' type='text/javascript'&gt;
 #     &lt;/script&gt;
 #   &lt;/head&gt;
-# 
+#
+# ===== Attribute Methods
+#
+# A Ruby method call that returns a hash
+# can be substituted for the hash contents.
+# For example, Haml::Helpers defines the following method:
+#
+#   def html_attrs(lang = 'en-US')
+#     {:xmlns =&gt; &quot;http://www.w3.org/1999/xhtml&quot;, 'xml:lang' =&gt; lang, :lang =&gt; lang}
+#   end
+#
+# This can then be used in Haml, like so:
+#
+#   %html{html_attrs('fr-fr')}
+#
+# This is compiled to:
+#
+#   &lt;html lang='fr-fr' xml:lang='fr=fr' xmlns='http://www.w3.org/1999/xhtml'&gt;
+#   &lt;/html&gt;
+#
+# You can use as many such attribute methods as you want
+# by separating them with commas,
+# like a Ruby argument list.
+# All the hashes will me merged together, from left to right.
+# For example, if you defined
+#
+#   def hash1
+#     {:bread =&gt; 'white', :filling =&gt; 'peanut butter and jelly'}
+#   end
+#
+#   def hash2
+#     {:bread =&gt; 'whole wheat'}
+#   end
+#
+# then
+#
+#   %sandwich{hash1, hash2, :delicious =&gt; true}/
+#
+# would compile to:
+#
+#   &lt;sandwich bread='whole wheat' delicious='true' filling='peanut butter and jelly' /&gt;
+#
+# ===== Boolean Attributes
+#
+# Some attributes, such as &quot;checked&quot; for &lt;tt&gt;input&lt;/tt&gt; tags or &quot;selected&quot; for &lt;tt&gt;option&lt;/tt&gt; tags,
+# are &quot;boolean&quot; in the sense that their values don't matter -
+# it only matters whether or not they're present.
+# In HTML (but not XHTML), these attributes can be written as
+#
+#   &lt;input selected&gt;
+#
+# To do this in Haml, just assign a Ruby true value to the attribute:
+#
+#   %input{:selected =&gt; true}
+#
+# In XHTML, the only valid value for these attributes is the name of the attribute.
+# Thus this will render in XHTML as
+#
+#   &lt;input selected=&quot;selected&quot;&gt;
+#
+# To set these attributes to false, simply assign them to a Ruby false value.
+# In both XHTML and HTML
+#
+#   %input{:selected =&gt; false}
+#
+# will just render as
+#
+#   &lt;input&gt;
+#
 # ==== []
-# 
+#
 # Square brackets follow a tag definition and contain a Ruby object
 # that is used to set the class and id of that tag.
 # The class is set to the object's class
@@ -153,41 +221,40 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # and the id is set to the object's class, followed by its id.
 # Because the id of an object is normally an obscure implementation detail,
 # this is most useful for elements that represent instances of Models.
+# Additionally, the second argument (if present) will be used as a prefix for
+# both the id and class attributes.
 # For example:
-# 
+#
 #   # file: app/controllers/users_controller.rb
-# 
+#
 #   def show
 #     @user = CrazyUser.find(15)
 #   end
-# 
+#
 #   -# file: app/views/users/show.haml
-# 
-#   %div[@user]
+#
+#   %div[@user, :greeting]
 #     %bar[290]/
 #     Hello!
-# 
+#
 # is compiled to:
-# 
-#   &lt;div class=&quot;crazy_user&quot; id=&quot;crazy_user_15&quot;&gt;
+#
+#   &lt;div class=&quot;greeting_crazy_user&quot; id=&quot;greeting_crazy_user_15&quot;&gt;
 #     &lt;bar class=&quot;fixnum&quot; id=&quot;fixnum_581&quot; /&gt;
 #     Hello!
 #   &lt;/div&gt;
-# 
-# This is based off of DHH's SimplyHelpful syntax,
-# as presented at RailsConf Europe 2006.
-# 
+#
 # ==== /
-# 
+#
 # The forward slash character, when placed at the end of a tag definition,
 # causes the tag to be self-closed.
 # For example:
-# 
+#
 #   %br/
 #   %meta{'http-equiv' =&gt; 'Content-Type', :content =&gt; 'text/html'}/
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;br /&gt;
 #   &lt;meta http-equiv='Content-Type' content='text/html' /&gt;
 #
@@ -203,9 +270,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #
 #   &lt;br /&gt;
 #   &lt;meta http-equiv='Content-Type' content='text/html' /&gt;
-# 
+#
 # ==== . and #
-# 
+#
 # The period and pound sign are borrowed from CSS.
 # They are used as shortcuts to specify the &lt;tt&gt;class&lt;/tt&gt;
 # and &lt;tt&gt;id&lt;/tt&gt; attributes of an element, respectively.
@@ -213,22 +280,22 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # by chaining the class names together with periods.
 # They are placed immediately after the tag and before an attributes hash.
 # For example:
-# 
+#
 #   %div#things
 #     %span#rice Chicken Fried
 #     %p.beans{ :food =&gt; 'true' } The magical fruit
 #     %h1.class.otherclass#id La La La
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;div id='things'&gt;
 #     &lt;span id='rice'&gt;Chicken Fried&lt;/span&gt;
 #     &lt;p class='beans' food='true'&gt;The magical fruit&lt;/p&gt;
 #     &lt;h1 class='class otherclass' id='id'&gt;La La La&lt;/h1&gt;
 #   &lt;/div&gt;
-# 
+#
 # And,
-# 
+#
 #   #content
 #     .articles
 #       .article.title
@@ -237,9 +304,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #         2006-11-05
 #       .article.entry
 #         Neil Patrick Harris would like to dispel any rumors that he is straight
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;div id=&quot;content&quot;&gt;
 #     &lt;div class=&quot;articles&quot;&gt;
 #       &lt;div class=&quot;article title&quot;&gt;Doogie Howser Comes Out&lt;/div&gt;
@@ -249,34 +316,89 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #       &lt;/div&gt;
 #     &lt;/div&gt;
 #   &lt;/div&gt;
-# 
+#
 # ==== Implicit Div Elements
-# 
+#
 # Because the div element is used so often, it is the default element.
 # If you only define a class and/or id using the &lt;tt&gt;.&lt;/tt&gt; or &lt;tt&gt;#&lt;/tt&gt; syntax,
 # a div element is automatically used.
 # For example:
-# 
+#
 #   #collection
 #     .item
 #       .description What a cool item!
-# 
+#
 # is the same as:
-# 
+#
 #   %div{:id =&gt; collection}
 #     %div{:class =&gt; 'item'}
 #       %div{:class =&gt; 'description'} What a cool item!
-# 
+#
 # and is compiled to:
-# 
+#
 #   &lt;div id='collection'&gt;
 #     &lt;div class='item'&gt;
 #       &lt;div class='description'&gt;What a cool item!&lt;/div&gt;
 #     &lt;/div&gt;
 #   &lt;/div&gt;
-# 
+#
+# ==== &gt; and &lt;
+#
+# &lt;tt&gt;&gt;&lt;/tt&gt; and &lt;tt&gt;&lt;&lt;/tt&gt; give you more control over the whitespace near a tag.
+# &lt;tt&gt;&gt;&lt;/tt&gt; will remove all whitespace surrounding a tag,
+# while &lt;tt&gt;&lt;&lt;/tt&gt; will remove all whitespace immediately within a tag.
+# You can think of them as alligators eating the whitespace:
+# &lt;tt&gt;&gt;&lt;/tt&gt; faces out of the tag and eats the whitespace on the outside,
+# and &lt;tt&gt;&lt;&lt;/tt&gt; faces into the tag and eats the whitespace on the inside.
+# They're placed at the end of a tag definition,
+# after class, id, and attribute declarations
+# but before &lt;tt&gt;/&lt;/tt&gt; or &lt;tt&gt;=&lt;/tt&gt;.
+# For example:
+#
+#   %blockquote&lt;
+#     %div
+#       Foo!
+#
+# is compiled to:
+#
+#   &lt;blockquote&gt;&lt;div&gt;
+#     Foo!
+#   &lt;/div&gt;&lt;/blockquote&gt;
+#
+# And:
+#
+#   %img
+#   %img&gt;
+#   %img
+#
+# is compiled to:
+#
+#   &lt;img /&gt;&lt;img /&gt;&lt;img /&gt;
+#
+# And:
+#
+#  %p&lt;= &quot;Foo\nBar&quot;
+#
+# is compiled to:
+#
+#  &lt;p&gt;Foo
+#  Bar&lt;/p&gt;
+#
+# And finally:
+#
+#   %img
+#   %pre&gt;&lt;
+#     foo
+#     bar
+#   %img
+#
+# is compiled to:
+#
+#   &lt;img /&gt;&lt;pre&gt;foo
+#   bar&lt;/pre&gt;&lt;img /&gt;
+#
 # ==== =
-# 
+#
 # &lt;tt&gt;=&lt;/tt&gt; is placed at the end of a tag definition,
 # after class, id, and attribute declarations.
 # It's just a shortcut for inserting Ruby code into an element.
@@ -285,45 +407,63 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # However, if the result is short enough,
 # it is displayed entirely on one line.
 # For example:
-# 
+#
 #   %p= &quot;hello&quot;
-# 
+#
 # is not quite the same as:
-# 
+#
 #   %p
 #     = &quot;hello&quot;
-# 
+#
 # It's compiled to:
-# 
+#
 #   &lt;p&gt;hello&lt;/p&gt;
-# 
+#
+# ==== ~
+#
+# ~ works just like =, except that it runs Haml::Helpers#find_and_preserve on its input.
+# For example,
+#
+#   ~ &quot;Foo\n&lt;pre&gt;Bar\nBaz&lt;/pre&gt;&quot;
+#
+# is the same as:
+#
+#   = find_and_preserve(&quot;Foo\n&lt;pre&gt;Bar\nBaz&lt;/pre&gt;&quot;)
+#
+# and is compiled to:
+#
+#   Foo
+#   &lt;pre&gt;Bar&amp;#x000A;Baz&lt;/pre&gt;
+#
+# See also Whitespace Preservation, below.
+#
 # === XHTML Helpers
-# 
+#
 # ==== No Special Character
-# 
+#
 # If no special character appears at the beginning of a line,
 # the line is rendered as plain text.
 # For example:
-# 
+#
 #   %gee
 #     %whiz
 #       Wow this is cool!
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;gee&gt;
 #     &lt;whiz&gt;
 #       Wow this is cool!
 #     &lt;/whiz&gt;
 #   &lt;/gee&gt;
-# 
+#
 # ==== !!!
-# 
+#
 # When describing XHTML documents with Haml,
 # you can have a document type or XML prolog generated automatically
 # by including the characters &lt;tt&gt;!!!&lt;/tt&gt;.
 # For example:
-# 
+#
 #   !!! XML
 #   !!!
 #   %html
@@ -332,9 +472,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #     %body
 #       %h1 I am the international space station
 #       %p Sign my guestbook
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;
 #   &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
 #   &lt;html&gt;
@@ -346,112 +486,112 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #       &lt;p&gt;Sign my guestbook&lt;/p&gt;
 #     &lt;/body&gt;
 #   &lt;/html&gt;
-# 
+#
 # You can also specify the version and type of XHTML after the &lt;tt&gt;!!!&lt;/tt&gt;.
 # XHTML 1.0 Strict, Transitional, and Frameset and XHTML 1.1 are supported.
 # The default version is 1.0 and the default type is Transitional.
 # For example:
-# 
+#
 #   !!! 1.1
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.1//EN&quot; &quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;&gt;
-# 
+#
 # and
-# 
+#
 #   !!! Strict
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
-# 
+#
 # If you're not using the UTF-8 character set for your document,
 # you can specify which encoding should appear
 # in the XML prolog in a similar way.
 # For example:
-# 
+#
 #   !!! XML iso-8859-1
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot; ?&gt;
-# 
+#
 # ==== /
-# 
+#
 # The forward slash character, when placed at the beginning of a line,
 # wraps all text after it in an HTML comment.
 # For example:
-# 
+#
 #   %peanutbutterjelly
 #     / This is the peanutbutterjelly element
 #     I like sandwiches!
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;peanutbutterjelly&gt;
 #     &lt;!-- This is the peanutbutterjelly element --&gt;
 #     I like sandwiches!
 #   &lt;/peanutbutterjelly&gt;
-# 
+#
 # The forward slash can also wrap indented sections of code. For example:
-# 
+#
 #   /
 #     %p This doesn't render...
 #     %div
 #       %h1 Because it's commented out!
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;!--
 #     &lt;p&gt;This doesn't render...&lt;/p&gt;
 #     &lt;div&gt;
 #       &lt;h1&gt;Because it's commented out!&lt;/h1&gt;
 #     &lt;/div&gt;
 #   --&gt;
-# 
+#
 # You can also use Internet Explorer conditional comments
 # (about)[http://www.quirksmode.org/css/condcom.html]
 # by enclosing the condition in square brackets after the &lt;tt&gt;/&lt;/tt&gt;.
 # For example:
-# 
+#
 #   /[if IE]
 #     %a{ :href =&gt; 'http://www.mozilla.com/en-US/firefox/' }
 #       %h1 Get Firefox
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;!--[if IE]&gt;
 #     &lt;a href='http://www.mozilla.com/en-US/firefox/'&gt;
 #       &lt;h1&gt;Get Firefox&lt;/h1&gt;
 #     &lt;/a&gt;
 #   &lt;![endif]--&gt;
-# 
+#
 # ==== \
-# 
+#
 # The backslash character escapes the first character of a line,
 # allowing use of otherwise interpreted characters as plain text.
 # For example:
-# 
+#
 #   %title
 #     = @title
 #     \- MySite
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;title&gt;
 #     MyPage
 #     - MySite
 #   &lt;/title&gt;
-# 
+#
 # ==== |
-# 
+#
 # The pipe character designates a multiline string.
 # It's placed at the end of a line
 # and means that all following lines that end with &lt;tt&gt;|&lt;/tt&gt;
 # will be evaluated as though they were on the same line.
 # For example:
-# 
+#
 #   %whoo
 #     %hoo I think this might get |
 #       pretty long so I should |
@@ -459,9 +599,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #       multiline so it doesn't |
 #       look awful. |
 #     %p This is short.
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;whoo&gt;
 #     &lt;hoo&gt;
 #       I think this might get pretty long so I should probably make it multiline so it doesn't look awful.
@@ -491,101 +631,180 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #     &lt;p&gt;Hello, &lt;em&gt;World&lt;/em&gt;&lt;/p&gt;
 #   &lt;/p&gt;
 #
+# Filters can have Ruby code interpolated, like with ==.
+# For example,
+#
+#   - flavor = &quot;raspberry&quot;
+#   #content
+#     :textile
+#       I *really* prefer _#{h flavor}_ jam.
+#
+# is compiled to
+#
+#   &lt;div id='content'&gt;
+#     &lt;p&gt;I &lt;strong&gt;really&lt;/strong&gt; prefer &lt;em&gt;raspberry&lt;/em&gt; jam.&lt;/p&gt;
+#   &lt;/div&gt;
+#
 # Haml has the following filters defined:
 #
-# [plain]     Does not parse the filtered text.
-#             This is useful for large blocks of text without HTML tags,
-#             when you don't want lines starting with &lt;tt&gt;.&lt;/tt&gt; or &lt;tt&gt;-&lt;/tt&gt;
-#             to be parsed.
+# [plain]      Does not parse the filtered text.
+#              This is useful for large blocks of text without HTML tags,
+#              when you don't want lines starting with &lt;tt&gt;.&lt;/tt&gt; or &lt;tt&gt;-&lt;/tt&gt;
+#              to be parsed.
 #
-# [ruby]      Parses the filtered text with the normal Ruby interpreter.
-#             All output sent to &lt;tt&gt;$stdout&lt;/tt&gt;, like with +puts+,
-#             is output into the Haml document.
-#             Not available if the &lt;tt&gt;suppress_eval&lt;/tt&gt; option is set to true.
+# [javascript] Surrounds the filtered text with &lt;script&gt; and CDATA tags.
+#              Useful for including inline Javascript.
 #
-# [preserve]  Inserts the filtered text into the template with whitespace preserved.
-#             &lt;tt&gt;preserve&lt;/tt&gt;d blocks of text aren't indented,
-#             and newlines are replaced with the HTML escape code for newlines,
-#             to preserve nice-looking output.
+# [escaped]    Works the same as plain, but HTML-escapes the text
+#              before placing it in the document.
 #
-# [erb]       Parses the filtered text with ERB, like an RHTML template.
-#             Not available if the &lt;tt&gt;suppress_eval&lt;/tt&gt; option is set to true.
-#             At the moment, this doesn't support access to variables
-#             defined by Ruby on Rails or Haml code.
+# [ruby]       Parses the filtered text with the normal Ruby interpreter.
+#              All output sent to &lt;tt&gt;$stdout&lt;/tt&gt;, like with +puts+,
+#              is output into the Haml document.
+#              Not available if the &lt;tt&gt;suppress_eval&lt;/tt&gt; option is set to true.
+#              The Ruby code is evaluated in the same context as the Haml template.
 #
-# [sass]      Parses the filtered text with Sass to produce CSS output.
+# [preserve]   Inserts the filtered text into the template with whitespace preserved.
+#              &lt;tt&gt;preserve&lt;/tt&gt;d blocks of text aren't indented,
+#              and newlines are replaced with the HTML escape code for newlines,
+#              to preserve nice-looking output.
+#              See also Whitespace Preservation, below.
 #
-# [redcloth]  Parses the filtered text with RedCloth (http://whytheluckystiff.net/ruby/redcloth),
-#             which uses both Textile and Markdown syntax.
-#             Only works if RedCloth is installed.
+# [erb]        Parses the filtered text with ERB, like an RHTML template.
+#              Not available if the &lt;tt&gt;suppress_eval&lt;/tt&gt; option is set to true.
+#              Embedded Ruby code is evaluated in the same context as the Haml template.
 #
-# [textile]   Parses the filtered text with Textile (http://www.textism.com/tools/textile).
-#             Only works if RedCloth is installed.
+# [sass]       Parses the filtered text with Sass to produce CSS output.
 #
-# [markdown]  Parses the filtered text with Markdown (http://daringfireball.net/projects/markdown).
-#             Only works if RedCloth or BlueCloth (http://www.deveiate.org/projects/BlueCloth)
-#             is installed
-#             (BlueCloth takes precedence if both are installed).
+# [redcloth]   Parses the filtered text with RedCloth (http://whytheluckystiff.net/ruby/redcloth),
+#              which uses both Textile and Markdown syntax.
+#              Only works if RedCloth is installed.
+#
+# [textile]    Parses the filtered text with Textile (http://www.textism.com/tools/textile).
+#              Only works if RedCloth is installed.
+#
+# [markdown]   Parses the filtered text with Markdown (http://daringfireball.net/projects/markdown).
+#              Only works if RedCloth or BlueCloth (http://www.deveiate.org/projects/BlueCloth)
+#              is installed
+#              (BlueCloth takes precedence if both are installed).
 #
 # You can also define your own filters (see Setting Options, below).
-# 
+#
 # === Ruby evaluators
-# 
+#
 # ==== =
-# 
+#
 # The equals character is followed by Ruby code,
 # which is evaluated and the output inserted into the document as plain text.
 # For example:
-# 
+#
 #   %p
 #     = ['hi', 'there', 'reader!'].join &quot; &quot;
 #     = &quot;yo&quot;
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;p&gt;
 #     hi there reader!
 #     yo
 #   &lt;/p&gt;
 #
-# You can also use two equal signs, &lt;tt&gt;==&lt;/tt&gt;,
-# along with conventional Ruby string-embedding syntax
-# to easily embed Ruby code in otherwise static text.
-# For example:
+# If the &lt;tt&gt;:escape_html&lt;/tt&gt; option is set, &lt;tt&gt;=&lt;/tt&gt; will sanitize any
+# HTML-sensitive characters generated by the script. For example:
 #
-#   %p
-#     == 1 + 1 = #{1 + 1}
+#   = '&lt;script&gt;alert(&quot;I\'m evil!&quot;);&lt;/script&gt;'
 #
-# is compiled to:
+# would be compiled to
+#
+#   &amp;lt;script&amp;gt;alert(&amp;quot;I'm evil!&amp;quot;);&amp;lt;/script&amp;gt;
 #
-#   &lt;p&gt;
-#     1 + 1 = 2
-#   &lt;/p&gt;
-# 
 # ==== -
-# 
+#
 # The hyphen character makes the text following it into &quot;silent script&quot;:
 # Ruby script that is evaluated, but not output.
-# 
+#
 # &lt;b&gt;It is not recommended that you use this widely;
 # almost all processing code and logic should be restricted
 # to the Controller, the Helper, or partials.&lt;/b&gt;
-# 
+#
 # For example:
-# 
+#
 #   - foo = &quot;hello&quot;
 #   - foo &lt;&lt; &quot; there&quot;
 #   - foo &lt;&lt; &quot; you!&quot;
 #   %p= foo
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;p&gt;
 #     hello there you!
 #   &lt;/p&gt;
-# 
+#
+# ==== ==
+#
+# Two equals characters interpolates Ruby code into plain text,
+# similarly to Ruby string interpolation.
+# For example,
+#
+#   %p== This is #{h quality} cake!
+#
+# is the same as
+#
+#   %p= &quot;This is #{h quality} cake!&quot;
+#
+# and might compile to
+#
+#   &lt;p&gt;This is scrumptious cake!&lt;/p&gt;
+#
+# Backslashes can be used to escape &quot;#{&quot; strings,
+# but they don't act as escapes anywhere else in the string.
+# For example:
+#
+#   %p
+#     == \\ Look at \\#{h word} lack of backslash: \#{foo}
+#
+# might compile to
+#
+#  &lt;p&gt;
+#    \\ Look at \yon lack of backslash: #{foo}
+#  &lt;/p&gt;
+#
+# ==== &amp;=
+#
+# An ampersand followed by one or two equals characters
+# evaluates Ruby code just like the equals without the ampersand,
+# but sanitizes any HTML-sensitive characters in the result of the code.
+# For example:
+#
+#   &amp;= &quot;I like cheese &amp; crackers&quot;
+#
+# compiles to
+#
+#   I like cheese &amp;amp; crackers
+#
+# If the &lt;tt&gt;:escape_html&lt;/tt&gt; option is set,
+# &amp;= behaves identically to =.
+#
+# ==== !=
+#
+# An exclamation mark followed by one or two equals characters
+# evaluates Ruby code just like the equals would,
+# but never sanitizes the HTML.
+#
+# By default, the single equals doesn't sanitize HTML either.
+# However, if the &lt;tt&gt;:escape_html&lt;/tt&gt; option is set, = will sanitize the HTML, but != still won't.
+# For example, if &lt;tt&gt;:escape_html&lt;/tt&gt; is set:
+#
+#   = &quot;I feel &lt;strong&gt;!&quot;
+#   != &quot;I feel &lt;strong&gt;!&quot;
+#
+# compiles to
+#
+#   I feel &amp;lt;strong&amp;gt;!
+#   I feel &lt;strong&gt;!
+#
 # ===== Blocks
-# 
+#
 # Ruby blocks, like XHTML tags, don't need to be explicitly closed in Haml.
 # Rather, they're automatically closed, based on indentation.
 # A block begins whenever the indentation is increased
@@ -593,13 +812,13 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # It ends when the indentation decreases
 # (as long as it's not an +else+ clause or something similar).
 # For example:
-# 
+#
 #   - (42...47).each do |i|
 #     %p= i
 #   %p See, I can count!
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;p&gt;
 #     42
 #   &lt;/p&gt;
@@ -615,9 +834,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #   &lt;p&gt;
 #     46
 #   &lt;/p&gt;
-# 
+#
 # Another example:
-# 
+#
 #   %p
 #     - case 2
 #     - when 1
@@ -626,9 +845,9 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #       = &quot;2?&quot;
 #     - when 3
 #       = &quot;3.&quot;
-# 
+#
 # is compiled to:
-# 
+#
 #   &lt;p&gt;
 #     2?
 #   &lt;/p&gt;
@@ -639,35 +858,52 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # signifies a silent comment.
 # Any text following this isn't rendered in the resulting document
 # at all.
-# 
+#
 # For example:
 #
-# %p foo
-# -# This is a comment
-# %p bar
+#   %p foo
+#   -# This is a comment
+#   %p bar
 #
 # is compiled to:
 #
-# &lt;p&gt;foo&lt;/p&gt;
-# &lt;p&gt;bar&lt;/p&gt;
+#   &lt;p&gt;foo&lt;/p&gt;
+#   &lt;p&gt;bar&lt;/p&gt;
 #
 # You can also nest text beneath a silent comment.
 # None of this text will be rendered.
 # For example:
 #
-# %p foo
-# -#
-#   This won't be displayed
-#     Nor will this
-# %p bar
+#   %p foo
+#   -#
+#     This won't be displayed
+#       Nor will this
+#   %p bar
 #
 # is compiled to:
 #
-# &lt;p&gt;foo&lt;/p&gt;
-# &lt;p&gt;bar&lt;/p&gt;
-# 
+#   &lt;p&gt;foo&lt;/p&gt;
+#   &lt;p&gt;bar&lt;/p&gt;
+#
 # == Other Useful Things
 #
+# === Whitespace Preservation
+#
+# Sometimes you don't want Haml to indent all your text.
+# For example, tags like +pre+ and +textarea+ are whitespace-sensitive;
+# indenting the text makes them render wrong.
+#
+# Haml deals with this by &quot;preserving&quot; newlines before they're put into the document --
+# converting them to the XHTML whitespace escape code, &lt;tt&gt;&amp;#x000A;&lt;/tt&gt;.
+# Then Haml won't try to re-format the indentation.
+#
+# Literal +textarea+ and +pre+ tags automatically preserve their content.
+# Dynamically can't be caught automatically,
+# and so should be passed through Haml::Helpers#find_and_preserve or the &lt;tt&gt;~&lt;/tt&gt; command,
+# which has the same effect (see above).
+#
+# Blocks of literal text can be preserved using the :preserve filter (see above).
+#
 # === Helpers
 #
 # Haml offers a bunch of helpers that are useful
@@ -675,19 +911,30 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # creating nicely indented output for user-defined helpers,
 # and other useful things.
 # The helpers are all documented in the Haml::Helpers and Haml::Helpers::ActionViewExtensions modules.
-# 
+#
 # === Haml Options
-# 
+#
 # Options can be set by setting the hash &lt;tt&gt;Haml::Template.options&lt;/tt&gt;
 # from &lt;tt&gt;environment.rb&lt;/tt&gt; in Rails,
 # or by passing an options hash to Haml::Engine.
 # Available options are:
-# 
+#
+# [&lt;tt&gt;:output&lt;/tt&gt;]        Determines the output format. The default is :xhtml.
+#                           Other options are :html4 and :html5, which are
+#                           identical to :xhtml except there are no self-closing tags,
+#                           XML prolog is ignored and correct DOCTYPEs are generated.
+#
+# [&lt;tt&gt;:escape_html&lt;/tt&gt;]   Sets whether or not to escape HTML-sensitive characters in script.
+#                           If this is true, = behaves like &amp;=;
+#                           otherwise, it behaves like !=.
+#                           &lt;b&gt;Note that this escapes tag attributes.&lt;/b&gt;
+#                           Defaults to false.
+#
 # [&lt;tt&gt;:suppress_eval&lt;/tt&gt;] Whether or not attribute hashes and Ruby scripts
 #                           designated by &lt;tt&gt;=&lt;/tt&gt; or &lt;tt&gt;~&lt;/tt&gt; should be
 #                           evaluated. If this is true, said scripts are
 #                           rendered as empty strings. Defaults to false.
-# 
+#
 # [&lt;tt&gt;:attr_wrapper&lt;/tt&gt;]  The character that should wrap element attributes.
 #                           This defaults to &lt;tt&gt;'&lt;/tt&gt; (an apostrophe). Characters
 #                           of this type within the attributes will be escaped
@@ -700,20 +947,81 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #                           so it's really only useful for the user to assign
 #                           when dealing with Haml programatically.
 #
+# [&lt;tt&gt;:line&lt;/tt&gt;]          The line offset of the Haml template being parsed.
+#                           This is useful for inline templates,
+#                           similar to the last argument to Kernel#eval.
+#
 # [&lt;tt&gt;:filters&lt;/tt&gt;]       A hash of filters that can be applied to Haml code.
 #                           The keys are the string names of the filters;
 #                           the values are references to the classes of the filters.
 #                           User-defined filters should always have lowercase keys,
-#                           and should have:
-#                           * An +initialize+ method that accepts one parameter,
-#                             the text to be filtered.
-#                           * A +render+ method that returns the result of the filtering.
+#                           and should have the interface described in Haml::Filters::Base.
 #
 # [&lt;tt&gt;:autoclose&lt;/tt&gt;]     A list of tag names that should be automatically self-closed
 #                           if they have no content.
-#                           Defaults to &lt;tt&gt;['meta', 'img', 'link', 'script', 'br', 'hr']&lt;/tt&gt;.
+#                           Defaults to &lt;tt&gt;['meta', 'img', 'link', 'br', 'hr', 'input', 'area', 'param', 'col', 'base']&lt;/tt&gt;.
+#
+# [&lt;tt&gt;:preserve&lt;/tt&gt;]      A list of tag names that should automatically have their newlines preserved
+#                           using the Haml::Helpers#preserve helper.
+#                           This means that any content given on the same line as the tag will be preserved.
+#                           For example:
+#
+#                             %textarea= &quot;Foo\nBar&quot;
+#
+#                           compiles to:
+#
+#                             &lt;textarea&gt;Foo&amp;&amp;#x000A;Bar&lt;/textarea&gt;
+#
+#                           Defaults to &lt;tt&gt;['textarea', 'pre']&lt;/tt&gt;.
+#
+#                           See also Whitespace Preservation, above.
 #
 module Haml
+  # Returns a hash representing the version of Haml.
+  # The :major, :minor, and :teeny keys have their respective numbers.
+  # The :string key contains a human-readable string representation of the version.
+  # If Haml is checked out from Git,
+  # the :rev key will have the revision hash.
+  def self.version
+    return @@version if defined?(@@version)
+
+    numbers = File.read(scope('VERSION')).strip.split('.').map { |n| n.to_i }
+    @@version = {
+      :major =&gt; numbers[0],
+      :minor =&gt; numbers[1],
+      :teeny =&gt; numbers[2]
+    }
+    @@version[:string] = [:major, :minor, :teeny].map { |comp| @@version[comp] }.compact.join('.')
+
+    if File.exists?(scope('REVISION'))
+      rev = File.read(scope('REVISION')).strip
+      rev = nil if rev !~ /a-f0-9+/
+    end
+
+    if rev.nil? &amp;&amp; File.exists?(scope('.git/HEAD'))
+      rev = File.read(scope('.git/HEAD')).strip
+      if rev =~ /^ref: (.*)$/
+        rev = File.read(scope(&quot;.git/#{$1}&quot;)).strip
+      end
+    end
+
+    if rev
+      @@version[:rev] = rev
+      @@version[:string] &lt;&lt; &quot;.&quot; &lt;&lt; rev[0...7]
+    end
+
+    @@version
+  end
+
+  # Returns the path of file relative to the Haml root.
+  def self.scope(file) # :nodoc:
+    File.join(File.dirname(__FILE__), '..', file)
+  end
+
+  # A string representing the version of Haml.
+  # A more fine-grained representation is generated by Haml.version.
+  VERSION = version[:string] unless defined?(Haml::VERSION)
+
   # This method is called by init.rb,
   # which is run by Rails on startup.
   # We use it rather than putting stuff straight into init.rb</diff>
      <filename>vendor/plugins/haml/lib/haml.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,11 +6,6 @@ module Haml
   class Buffer
     include Haml::Helpers
 
-    # Set the maximum length for a line to be considered a one-liner.
-    # Lines &lt;= the maximum will be rendered on one line,
-    # i.e. &lt;tt&gt;&lt;p&gt;Hello world&lt;/p&gt;&lt;/tt&gt;
-    ONE_LINER_LENGTH     = 50
-
     # The string that holds the compiled XHTML. This is aliased as
     # _erbout for compatibility with ERB-specific code.
     attr_accessor :buffer
@@ -18,6 +13,47 @@ module Haml
     # The options hash passed in from Haml::Engine.
     attr_accessor :options
 
+    # The Buffer for the enclosing Haml document.
+    # This is set for partials and similar sorts of nested templates.
+    # It's nil at the top level (see #toplevel?).
+    attr_accessor :upper
+
+    # See #active?
+    attr_writer :active
+
+    # True if the format is XHTML
+    def xhtml?
+      not html?
+    end
+
+    # True if the format is any flavor of HTML
+    def html?
+      html4? or html5?
+    end
+
+    # True if the format is HTML4
+    def html4?
+      @options[:format] == :html4
+    end
+
+    # True if the format is HTML5
+    def html5?
+      @options[:format] == :html5
+    end
+
+    # True if this buffer is a top-level template,
+    # as opposed to a nested partial.
+    def toplevel?
+      upper.nil?
+    end
+
+    # True if this buffer is currently being used to render a Haml template.
+    # However, this returns false if a subtemplate is being rendered,
+    # even if it's a subtemplate of this buffer's template.
+    def active?
+      @active
+    end
+
     # Gets the current tabulation of the document.
     def tabulation
       @real_tabs + @tabulation
@@ -30,9 +66,13 @@ module Haml
     end
 
     # Creates a new buffer.
-    def initialize(options = {})
+    def initialize(upper = nil, options = {})
+      @active = true
+      @upper = upper
       @options = {
-        :attr_wrapper =&gt; &quot;'&quot;
+        :attr_wrapper =&gt; &quot;'&quot;,
+        :ugly =&gt; false,
+        :format =&gt; :xhtml
       }.merge options
       @buffer = &quot;&quot;
       @tabulation = 0
@@ -44,122 +84,140 @@ module Haml
 
     # Renders +text+ with the proper tabulation. This also deals with
     # making a possible one-line tag one line or not.
-    def push_text(text, tab_change = 0)
-      if(@tabulation &gt; 0)
-        # Have to push every line in by the extra user set tabulation
-        text.gsub!(/^/m, '  ' * @tabulation)
+    def push_text(text, dont_tab_up = false, tab_change = 0)
+      if @tabulation &gt; 0 &amp;&amp; !@options[:ugly]
+        # Have to push every line in by the extra user set tabulation.
+        # Don't push lines with just whitespace, though,
+        # because that screws up precompiled indentation.
+        text.gsub!(/^(?!\s+$)/m, tabs)
+        text.sub!(tabs, '') if dont_tab_up
       end
-      
-      @buffer &lt;&lt; &quot;#{text}&quot;
+
+      @buffer &lt;&lt; text
       @real_tabs += tab_change
+      @dont_tab_up_next_line = false
     end
 
     # Properly formats the output of a script that was run in the
     # instance_eval.
-    def push_script(result, flattened, close_tag = nil)
+    def push_script(result, preserve_script, in_tag = false, preserve_tag = false,
+                    escape_html = false, nuke_inner_whitespace = false)
       tabulation = @real_tabs
-      
-      if flattened
+
+      if preserve_tag
+        result = Haml::Helpers.preserve(result)
+      elsif preserve_script
         result = Haml::Helpers.find_and_preserve(result)
       end
-      
-      result = result.to_s
-      while result[-1] == ?\n
-        # String#chomp is slow
-        result = result[0...-1]
-      end
-      
-      if close_tag &amp;&amp; Buffer.one_liner?(result)
+
+      result = result.to_s.rstrip
+      result = html_escape(result) if escape_html
+
+      has_newline = result.include?(&quot;\n&quot;)
+      if in_tag &amp;&amp; (@options[:ugly] || !has_newline || preserve_tag)
         @buffer &lt;&lt; result
-        @buffer &lt;&lt; &quot;&lt;/#{close_tag}&gt;\n&quot;
         @real_tabs -= 1
-      else
-        if close_tag
-          @buffer &lt;&lt; &quot;\n&quot;
-        end
-        
-        result = result.gsub(/^/m, tabs(tabulation))
-        @buffer &lt;&lt; &quot;#{result}\n&quot;
-        
-        if close_tag
-          @buffer &lt;&lt; &quot;#{tabs(tabulation-1)}&lt;/#{close_tag}&gt;\n&quot;
-          @real_tabs -= 1
-        end
+        return
+      end
+
+      @buffer &lt;&lt; &quot;\n&quot; if in_tag &amp;&amp; !nuke_inner_whitespace
+
+      # Precompiled tabulation may be wrong
+      if @tabulation &gt; 0 &amp;&amp; !in_tag
+        result = tabs + result
+      end
+
+      if has_newline &amp;&amp; !@options[:ugly]
+        result = result.gsub &quot;\n&quot;, &quot;\n&quot; + tabs(tabulation)
+
+        # Add tabulation if it wasn't precompiled
+        result = tabs(tabulation) + result if in_tag &amp;&amp; !nuke_inner_whitespace
+      end
+      @buffer &lt;&lt; &quot;#{result}&quot;
+      @buffer &lt;&lt; &quot;\n&quot; unless nuke_inner_whitespace
+
+      if in_tag &amp;&amp; !nuke_inner_whitespace
+        # We never get here if @options[:ugly] is true
+        @buffer &lt;&lt; tabs(tabulation-1)
+        @real_tabs -= 1
       end
       nil
     end
 
     # Takes the various information about the opening tag for an
     # element, formats it, and adds it to the buffer.
-    def open_tag(name, atomic, try_one_line, class_id, obj_ref, content, attributes_hash)
+    def open_tag(name, self_closing, try_one_line, preserve_tag, escape_html, class_id,
+                 nuke_outer_whitespace, nuke_inner_whitespace, obj_ref, content, *attributes_hashes)
       tabulation = @real_tabs
-      
+
       attributes = class_id
-      if attributes_hash
+      attributes_hashes.each do |attributes_hash|
         attributes_hash.keys.each { |key| attributes_hash[key.to_s] = attributes_hash.delete(key) }
         self.class.merge_attrs(attributes, attributes_hash)
       end
       self.class.merge_attrs(attributes, parse_object_ref(obj_ref)) if obj_ref
 
-      if atomic
-        str = &quot; /&gt;\n&quot;
-      elsif try_one_line
-        str = &quot;&gt;&quot;
+      if self_closing
+        str = &quot; /&gt;&quot; + (nuke_outer_whitespace ? &quot;&quot; : &quot;\n&quot;)
       else
-        str = &quot;&gt;\n&quot;
+        str = &quot;&gt;&quot; + (try_one_line || preserve_tag || nuke_inner_whitespace ? &quot;&quot; : &quot;\n&quot;)
       end
-      @buffer &lt;&lt; &quot;#{tabs(tabulation)}&lt;#{name}#{Precompiler.build_attributes(@options[:attr_wrapper], attributes)}#{str}&quot;
+
+      attributes = Precompiler.build_attributes(html?, @options[:attr_wrapper], attributes)
+      @buffer &lt;&lt; &quot;#{nuke_outer_whitespace || @options[:ugly] ? '' : tabs(tabulation)}&lt;#{name}#{attributes}#{str}&quot;
+
       if content
-        if Buffer.one_liner?(content)
-          @buffer &lt;&lt; &quot;#{content}&lt;/#{name}&gt;\n&quot;
-        else
-          @buffer &lt;&lt; &quot;\n#{tabs(@real_tabs+1)}#{content}\n#{tabs(@real_tabs)}&lt;/#{name}&gt;\n&quot;
-        end
-      else
-        @real_tabs += 1
+        @buffer &lt;&lt; &quot;#{content}&lt;/#{name}&gt;&quot; &lt;&lt; (nuke_outer_whitespace ? &quot;&quot; : &quot;\n&quot;)
+        return
       end
+
+      @real_tabs += 1 unless self_closing || nuke_inner_whitespace
     end
 
     def self.merge_attrs(to, from)
       if to['id'] &amp;&amp; from['id']
         to['id'] &lt;&lt; '_' &lt;&lt; from.delete('id')
+      elsif to['id'] || from['id']
+        from['id'] ||= to['id']
       end
 
       if to['class'] &amp;&amp; from['class']
         # Make sure we don't duplicate class names
         from['class'] = (from['class'].split(' ') | to['class'].split(' ')).join(' ')
+      elsif to['class'] || from['class']
+        from['class'] ||= to['class']
       end
 
       to.merge!(from)
     end
 
+    private
+
     # Some of these methods are exposed as public class methods
     # so they can be re-used in helpers.
 
-    # Returns whether or not the given value is short enough to be rendered
-    # on one line.
-    def self.one_liner?(value)
-      value.length &lt;= ONE_LINER_LENGTH &amp;&amp; value.scan(/\n/).empty?
-    end
-
-    private
-
     @@tab_cache = {}
     # Gets &lt;tt&gt;count&lt;/tt&gt; tabs. Mostly for internal use.
-    def tabs(count)
+    def tabs(count = 0)
       tabs = count + @tabulation
-      '  ' * tabs
       @@tab_cache[tabs] ||= '  ' * tabs
     end
 
     # Takes an array of objects and uses the class and id of the first
     # one to create an attributes hash.
+    # The second object, if present, is used as a prefix,
+    # just like you can do with dom_id() and dom_class() in Rails
     def parse_object_ref(ref)
+      prefix = ref[1]
       ref = ref[0]
       # Let's make sure the value isn't nil. If it is, return the default Hash.
       return {} if ref.nil?
       class_name = underscore(ref.class)
       id = &quot;#{class_name}_#{ref.id || 'new'}&quot;
+      if prefix
+        class_name = &quot;#{ prefix }_#{ class_name}&quot;
+        id = &quot;#{ prefix }_#{ id }&quot;
+      end
 
       {'id' =&gt; id, 'class' =&gt; class_name}
     end</diff>
      <filename>vendor/plugins/haml/lib/haml/buffer.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,6 @@ require 'haml/buffer'
 require 'haml/precompiler'
 require 'haml/filters'
 require 'haml/error'
-require 'haml/util'
 
 module Haml
   # This is the class where all the parsing and processing of the Haml
@@ -20,38 +19,76 @@ module Haml
     # Allow reading and writing of the options hash
     attr :options, true
 
+    # This string contains the source code that is evaluated
+    # to produce the Haml document.
+    attr :precompiled, true
+
+    # True if the format is XHTML
+    def xhtml?
+      not html?
+    end
+
+    # True if the format is any flavor of HTML
+    def html?
+      html4? or html5?
+    end
+
+    # True if the format is HTML4
+    def html4?
+      @options[:format] == :html4
+    end
+
+    # True if the format is HTML5
+    def html5?
+      @options[:format] == :html5
+    end
+
     # Creates a new instace of Haml::Engine that will compile the given
     # template string when &lt;tt&gt;render&lt;/tt&gt; is called.
-    # See README for available options.
+    # See README.rdoc for available options.
     #
     #--
     # When adding options, remember to add information about them
-    # to README!
+    # to README.rdoc!
     #++
     #
     def initialize(template, options = {})
       @options = {
         :suppress_eval =&gt; false,
         :attr_wrapper =&gt; &quot;'&quot;,
-        :autoclose =&gt; ['meta', 'img', 'link', 'br', 'hr', 'input', 'area'],
+
+        # Don't forget to update the docs in lib/haml.rb if you update these
+        :autoclose =&gt; %w[meta img link br hr input area param col base],
+        :preserve =&gt; %w[textarea pre],
+
         :filters =&gt; {
-          'sass' =&gt; Sass::Engine,
+          'sass' =&gt; Haml::Filters::Sass,
           'plain' =&gt; Haml::Filters::Plain,
+          'javascript' =&gt; Haml::Filters::Javascript,
+          'escaped' =&gt; Haml::Filters::Escaped,
           'preserve' =&gt; Haml::Filters::Preserve,
           'redcloth' =&gt; Haml::Filters::RedCloth,
           'textile' =&gt; Haml::Filters::Textile,
           'markdown' =&gt; Haml::Filters::Markdown },
-        :filename =&gt; '(haml)'
+        :filename =&gt; '(haml)',
+        :line =&gt; 1,
+        :ugly =&gt; false,
+        :format =&gt; :xhtml,
+        :escape_html =&gt; false
       }
-      @options.rec_merge! options
+      @options[:filters].merge! options.delete(:filters) if options[:filters]
+      @options.merge! options
+
+      unless [:xhtml, :html4, :html5].include?(@options[:format])
+        raise Haml::Error, &quot;Invalid format #{@options[:format].inspect}&quot;
+      end
 
       unless @options[:suppress_eval]
         @options[:filters].merge!({
-          'erb' =&gt; ERB,
+          'erb' =&gt; Haml::Filters::ERB,
           'ruby' =&gt; Haml::Filters::Ruby
         })
       end
-      @options[:filters].rec_merge! options[:filters] if options[:filters]
 
       if @options[:locals]
         warn &lt;&lt;END
@@ -61,16 +98,17 @@ Use the locals option for Haml::Engine#render instead.
 END
       end
 
-      @template = template.strip #String
+      @template = template.rstrip #String
       @to_close_stack = []
       @output_tabs = 0
       @template_tabs = 0
       @index = 0
       @flat_spaces = -1
+      @newlines = 0
 
       precompile
     rescue Haml::Error
-      $!.backtrace.unshift &quot;#{@options[:filename]}:#{@index}&quot;
+      $!.backtrace.unshift &quot;#{@options[:filename]}:#{@index + $!.line_offset + @options[:line] - 1}&quot; if @index
       raise
     end
 
@@ -80,7 +118,7 @@ END
     # If it's a Binding or Proc object,
     # Haml uses it as the second argument to Kernel#eval;
     # otherwise, Haml just uses its #instance_eval context.
-    # 
+    #
     # Note that Haml modifies the evaluation context
     # (either the scope object or the &quot;self&quot; object of the scope binding).
     # It extends Haml::Helpers, and various instance variables are set
@@ -111,7 +149,7 @@ END
     # they won't work.
     def render(scope = Object.new, locals = {}, &amp;block)
       locals = (@options[:locals] || {}).merge(locals)
-      buffer = Haml::Buffer.new(options_for_buffer)
+      buffer = Haml::Buffer.new(scope.instance_variable_get('@haml_buffer'), options_for_buffer)
 
       if scope.is_a?(Binding) || scope.is_a?(Proc)
         scope_object = eval(&quot;self&quot;, scope)
@@ -125,17 +163,14 @@ END
 
       scope_object.instance_eval do
         extend Haml::Helpers
-        @haml_stack ||= Array.new
-        @haml_stack.push(buffer)
-        @haml_is_haml = true
+        @haml_buffer = buffer
       end
 
-      eval(@precompiled, scope, @options[:filename], 0)
+      eval(@precompiled, scope, @options[:filename], @options[:line])
 
       # Get rid of the current buffer
       scope_object.instance_eval do
-        @haml_stack.pop
-        @haml_is_haml = false
+        @haml_buffer = buffer.upper
       end
 
       buffer.buffer
@@ -172,7 +207,7 @@ END
       end
 
       eval(&quot;Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {};&quot; +
-           precompiled_with_ambles(local_names) + &quot;}\n&quot;, scope, @options[:filename], 0)
+           precompiled_with_ambles(local_names) + &quot;}\n&quot;, scope, @options[:filename], @options[:line])
     end
 
     # Defines a method on +object+
@@ -189,7 +224,7 @@ END
     #
     #   Haml::Engine.new(&quot;.upcased= upcase&quot;).def_method(String, :upcased_div)
     #   &quot;foobar&quot;.upcased_div #=&gt; &quot;&lt;div class='upcased'&gt;FOOBAR&lt;/div&gt;\n&quot;
-    # 
+    #
     # The first argument of the defined method is a hash of local variable names to values.
     # However, due to an unfortunate Ruby quirk,
     # the local variables which can be assigned must be pre-declared.
@@ -205,7 +240,7 @@ END
     #   obj = Object.new
     #   Haml::Engine.new(&quot;%p= foo&quot;).def_method(obj, :render)
     #   obj.render(:foo =&gt; &quot;Hello!&quot;) #=&gt; NameError: undefined local variable or method `foo'
-    # 
+    #
     # Note that Haml modifies the evaluation context
     # (either the scope object or the &quot;self&quot; object of the scope binding).
     # It extends Haml::Helpers, and various instance variables are set
@@ -214,7 +249,7 @@ END
       method = object.is_a?(Module) ? :module_eval : :instance_eval
 
       object.send(method, &quot;def #{name}(_haml_locals = {}); #{precompiled_with_ambles(local_names)}; end&quot;,
-                  @options[:filename], 0)
+                  @options[:filename], @options[:line])
     end
 
     private
@@ -226,9 +261,15 @@ END
     end
 
     # Returns a hash of options that Haml::Buffer cares about.
-    # This should remain loadable form #inspect.
+    # This should remain loadable from #inspect.
     def options_for_buffer
-      {:attr_wrapper =&gt; @options[:attr_wrapper]}
+      {
+        :autoclose =&gt; @options[:autoclose],
+        :preserve =&gt; @options[:preserve],
+        :attr_wrapper =&gt; @options[:attr_wrapper],
+        :ugly =&gt; @options[:ugly],
+        :format =&gt; @options[:format]
+      }
     end
   end
 end</diff>
      <filename>vendor/plugins/haml/lib/haml/engine.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,23 @@
 module Haml
-  # The abstract type of exception raised by Haml code.
-  class Error &lt; StandardError; end
+  # An exception raised by Haml code.
+  class Error &lt; Exception
+    # :stopdoc:
+
+    # By default, an error is taken to refer to the line of the template
+    # that was being processed when the exception was raised.
+    # However, if line_offset is non-zero, it's added to that line number
+    # to get the line to report for the error.
+    attr_reader :line_offset
+
+    def initialize(message = nil, line_offset = 0)
+      super(message)
+      @line_offset = line_offset
+    end
+    # :startdoc:
+  end
 
   # SyntaxError is the type of exception raised when Haml encounters an
   # ill-formatted document.
   # It's not particularly interesting, except in that it includes Haml::Error.
   class SyntaxError &lt; Haml::Error; end
-
-  # HamlError is the type of exception raised when Haml encounters an error
-  # not of a syntactical nature, such as an undefined Filter.
-  class HamlError &lt; Haml::Error; end
 end</diff>
      <filename>vendor/plugins/haml/lib/haml/error.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,7 +21,7 @@ module Haml
           @opts.parse!(@args)
 
           process_result
-          
+
           @options
         rescue Exception =&gt; e
           raise e if e.is_a? SystemExit
@@ -43,9 +43,13 @@ module Haml
       protected
 
       def get_line(exception)
+        # SyntaxErrors have weird line reporting
+        # when there's trailing whitespace,
+        # which there is for Haml documents.
+        return exception.message.scan(/:(\d+)/)[0] if exception.is_a?(::SyntaxError)
         exception.backtrace[0].scan(/:(\d+)/)[0]
       end
-      
+
       private
 
       def set_opts(opts)
@@ -63,7 +67,7 @@ module Haml
         end
 
         opts.on_tail(&quot;-v&quot;, &quot;--version&quot;, &quot;Print version&quot;) do
-          puts(&quot;Haml &quot; + File.read(File.dirname(__FILE__) + '/../../VERSION'))
+          puts(&quot;Haml #{::Haml.version[:string]}&quot;)
           exit
         end
       end
@@ -110,7 +114,7 @@ Description:
 
 Options:
 END
-       
+
         opts.on('--rails RAILS_DIR', &quot;Install Haml and Sass from the Gem to a Rails project&quot;) do |dir|
           original_dir = dir
 
@@ -145,6 +149,7 @@ END
         end
 
         opts.on('-c', '--check', &quot;Just check syntax, don't evaluate.&quot;) do
+          require 'stringio'
           @options[:check_syntax] = true
           @options[:output] = StringIO.new
         end
@@ -170,7 +175,7 @@ END
         super
 
         opts.on('-t', '--style NAME',
-                'Output style. Can be nested (default), compact, or expanded.') do |name|
+                'Output style. Can be nested (default), compact, compressed, or expanded.') do |name|
           @options[:for_engine][:style] = name.to_sym
         end
       end
@@ -206,6 +211,25 @@ END
         @name = &quot;Haml&quot;
       end
 
+      def set_opts(opts)
+        super
+
+        opts.on('-t', '--style NAME',
+                'Output style. Can be indented (default) or ugly.') do |name|
+          @options[:for_engine][:ugly] = true if name.to_sym == :ugly
+        end
+
+        opts.on('-f', '--format NAME',
+                'Output format. Can be xhtml (default), html4, or html5.') do |name|
+          @options[:for_engine][:format] = name.to_sym
+        end
+
+        opts.on('-e', '--escape-html',
+                'Escape HTML characters (like ampersands and angle brackets) by default.') do
+          @options[:for_engine][:escape_html] = true
+        end
+      end
+
       def process_result
         super
         input = @options[:input]
@@ -225,8 +249,8 @@ END
           raise e if @options[:trace]
 
           case e
-          when ::Haml::SyntaxError: raise &quot;Syntax error on line #{get_line e}: #{e.message}&quot;
-          when ::Haml::HamlError:   raise &quot;Haml error on line #{get_line e}: #{e.message}&quot;
+          when ::Haml::SyntaxError; raise &quot;Syntax error on line #{get_line e}: #{e.message}&quot;
+          when ::Haml::Error;       raise &quot;Haml error on line #{get_line e}: #{e.message}&quot;
           else raise &quot;Exception on line #{get_line e}: #{e.message}\n  Use --trace for backtrace.&quot;
           end
         end
@@ -289,6 +313,8 @@ END
       def initialize(args)
         super
 
+        @module_opts = {}
+
         require 'sass/css'
       end
 
@@ -301,6 +327,10 @@ Description: Transforms a CSS file into corresponding Sass code.
 Options:
 END
 
+        opts.on('-a', '--alternate', 'Output using alternative Sass syntax (margin: 1px)') do
+          @module_opts[:alternate] = true
+        end
+
         super
       end
 
@@ -310,7 +340,7 @@ END
         input = @options[:input]
         output = @options[:output]
 
-        output.write(::Sass::CSS.new(input).render)
+        output.write(::Sass::CSS.new(input, @module_opts).render)
       end
     end
   end</diff>
      <filename>vendor/plugins/haml/lib/haml/exec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,115 +1,242 @@
 # This file contains redefinitions of and wrappers around various text
 # filters so they can be used as Haml filters.
 
-# :stopdoc:
-
-require 'erb'
-require 'sass/engine'
-require 'stringio'
-
-begin
-  require 'rubygems'
-rescue LoadError; end
-
-class ERB; alias_method :render, :result; end
-
 module Haml
+  # The module containing the default filters,
+  # as well as the base module,
+  # Haml::Filters::Base.
   module Filters
-    class Plain
-      def initialize(text)
-        @text = text
+    # The base module for Haml filters.
+    # User-defined filters should be modules including this module.
+    #
+    # A user-defined filter should override either Base#render or Base #compile.
+    # Base#render is the most common.
+    # It takes a string, the filter source,
+    # and returns another string,
+    # the result of the filter.
+    # For example:
+    #
+    #   module Haml::Filters::Sass
+    #     include Haml::Filters::Base
+    #
+    #     def render(text)
+    #       ::Sass::Engine.new(text).render
+    #     end
+    #   end
+    #
+    # For details on overriding #compile, see its documentation.
+    #
+    module Base
+      def self.included(base) # :nodoc:
+        base.extend(base)
       end
 
-      def render
-        @text
+      # Takes a string, the source text that should be passed to the filter,
+      # and returns the string resulting from running the filter on &lt;tt&gt;text&lt;/tt&gt;.
+      #
+      # This should be overridden in most individual filter modules
+      # to render text with the given filter.
+      # If compile is overridden, however, render doesn't need to be.
+      def render(text)
+        raise Error.new(&quot;#{self.inspect}#render not defined!&quot;)
       end
-    end
 
-    class Ruby
-      def initialize(text)
-        @text = text
+      def internal_compile(*args) # :nodoc:
+        resolve_lazy_requires
+        compile(*args)
       end
 
-      def render
-        old_stdout = $stdout
-        $stdout = StringIO.new
-        Object.new.instance_eval(@text)
-        old_stdout, $stdout = $stdout, old_stdout
-        old_stdout.pos = 0
-        old_stdout.read
-      end
-    end
+      # compile should be overridden when a filter needs to have access
+      # to the Haml evaluation context.
+      # Rather than applying a filter to a string at compile-time,
+      # compile uses the Haml::Precompiler instance to compile the string to Ruby code
+      # that will be executed in the context of the active Haml template.
+      #
+      # Warning: the Haml::Precompiler interface is neither well-documented
+      # nor guaranteed to be stable.
+      # If you want to make use of it,
+      # you'll probably need to look at the source code
+      # and should test your filter when upgrading to new Haml versions.
+      def compile(precompiler, text)
+        resolve_lazy_requires
+        filter = self
+        precompiler.instance_eval do
+          if contains_interpolation?(text)
+            return if options[:suppress_eval]
+
+            push_script(&quot;#{filter.inspect}.render(#{unescape_interpolation(text)})&quot;, false)
+            return
+          end
+
+          rendered = filter.render(text)
 
-    class Preserve
-      def initialize(text)
-        @text = text
+          if !options[:ugly]
+            push_text(rendered.rstrip.gsub(&quot;\n&quot;, &quot;\n#{'  ' * @output_tabs}&quot;))
+          else
+            push_text(rendered.rstrip)
+          end
+        end
       end
 
-      def render
-        Haml::Helpers.preserve(@text)
+      # This becomes a class method of modules that include Base.
+      # It allows the module to specify one or more Ruby files
+      # that Haml should try to require when compiling the filter.
+      #
+      # The first file specified is tried first,
+      # then the second, etc.
+      # If none are found, the compilation throws an exception.
+      #
+      # For example:
+      #
+      #   module Haml::Filters::Markdown
+      #     lazy_require 'bluecloth', 'redcloth'
+      #
+      #     ...
+      #   end
+      #
+      def lazy_require(*reqs)
+        @lazy_requires = reqs
       end
-    end
 
-    class LazyLoaded
-      def initialize(*reqs)
-        reqs[0...-1].each do |req|
+      private
+
+      def resolve_lazy_requires
+        return unless @lazy_requires
+
+        @lazy_requires[0...-1].each do |req|
           begin
             @required = req
             require @required
             return
           rescue LoadError; end # RCov doesn't see this, but it is run
         end
-       
+
         begin
-          @required = reqs[-1]
+          @required = @lazy_requires[-1]
           require @required
         rescue LoadError =&gt; e
           classname = self.class.to_s.gsub(/\w+::/, '')
 
-          if reqs.size == 1
-            raise HamlError.new(&quot;Can't run #{classname} filter; required file '#{reqs.first}' not found&quot;)
+          if @lazy_requires.size == 1
+            raise Error.new(&quot;Can't run #{classname} filter; required file '#{@lazy_requires.first}' not found&quot;)
           else
-            raise HamlError.new(&quot;Can't run #{classname} filter; required #{reqs.map { |r| &quot;'#{r}'&quot; }.join(' or ')}, but none were found&quot;)
+            raise Error.new(&quot;Can't run #{classname} filter; required #{@lazy_requires.map { |r| &quot;'#{r}'&quot; }.join(' or ')}, but none were found&quot;)
           end
         end
       end
     end
-    
-    class RedCloth &lt; LazyLoaded
-      def initialize(text)
-        super('redcloth')
-        @engine = ::RedCloth.new(text)
+  end
+end
+
+# :stopdoc:
+
+begin
+  require 'rubygems'
+rescue LoadError; end
+
+module Haml
+  module Filters
+    module Plain
+      include Base
+
+      def render(text); text; end
+    end
+
+    module Javascript
+      include Base
+
+      def render(text)
+        &lt;&lt;END
+&lt;script type='text/javascript'&gt;
+  //&lt;![CDATA[
+    #{text.rstrip.gsub(&quot;\n&quot;, &quot;\n    &quot;)}
+  //]]&gt;
+&lt;/script&gt;
+END
+      end
+    end
+
+    module Escaped
+      include Base
+
+      def render(text)
+        Haml::Helpers.html_escape text
+      end
+    end
+
+    module Ruby
+      include Base
+      lazy_require 'stringio'
+
+      def compile(precompiler, text)
+        precompiler.instance_eval do
+          push_silent &lt;&lt;-END.gsub(&quot;\n&quot;, ';')
+            _haml_old_stdout = $stdout
+            $stdout = StringIO.new(_hamlout.buffer, 'a')
+            #{text}
+            _haml_old_stdout, $stdout = $stdout, _haml_old_stdout
+            _haml_old_stdout.close
+          END
+        end
       end
+    end
 
-      def render
-        @engine.to_html
+    module Preserve
+      include Base
+
+      def render(text)
+        Haml::Helpers.preserve text
       end
     end
-      
+
+    module Sass
+      include Base
+      lazy_require 'sass/engine'
+
+      def render(text)
+        ::Sass::Engine.new(text).render
+      end
+    end
+
+    module ERB
+      include Base
+      lazy_require 'erb'
+
+      def compile(precompiler, text)
+        src = ::ERB.new(text).src.sub(/^_erbout = '';/, &quot;&quot;).gsub(&quot;\n&quot;, ';')
+        precompiler.send(:push_silent, src)
+      end
+    end
+
+    module RedCloth
+      include Base
+      lazy_require 'redcloth'
+
+      def render(text)
+        ::RedCloth.new(text).to_html
+      end
+    end
+
     # Uses RedCloth to provide only Textile (not Markdown) parsing
-    class Textile &lt; RedCloth
-      def render
-        @engine.to_html(:textile)
+    module Textile
+      include Base
+      lazy_require 'redcloth'
+
+      def render(text)
+        ::RedCloth.new(text).to_html(:textile)
       end
     end
 
     # Uses BlueCloth or RedCloth to provide only Markdown (not Textile) parsing
-    class Markdown &lt; LazyLoaded
-      def initialize(text)
-        super('bluecloth', 'redcloth')
+    module Markdown
+      include Base
+      lazy_require 'bluecloth', 'redcloth'
 
+      def render(text)
         if @required == 'bluecloth'
-          @engine = ::BlueCloth.new(text)
-        else
-          @engine = ::RedCloth.new(text)
-        end
-      end
-
-      def render
-        if @engine.is_a?(::BlueCloth)
-          @engine.to_html
+          ::BlueCloth.new(text).to_html
         else
-          @engine.to_html(:markdown)
+          ::RedCloth.new(text).to_html(:markdown)
         end
       end
     end</diff>
      <filename>vendor/plugins/haml/lib/haml/filters.rb</filename>
    </modified>
    <modified>
      <diff>@@ -34,28 +34,57 @@ module Haml
     #     include Haml::Helpers
     #   end
     #   context.init_haml_helpers
-    #   context.open :p, &quot;Stuff&quot;
-    # 
+    #   context.haml_tag :p, &quot;Stuff&quot;
+    #
     def init_haml_helpers
-      @haml_is_haml = true
-      @haml_stack = [Haml::Buffer.new]
+      @haml_buffer = Haml::Buffer.new(@haml_buffer, Haml::Engine.new('').send(:options_for_buffer))
       nil
     end
 
+    # call-seq:
+    #   non_haml { ... }
+    #
+    # Runs a block of code in a non-Haml context
+    # (i.e. #is_haml? will return false).
+    #
+    # This is mainly useful for rendering sub-templates such as partials in a non-Haml language,
+    # particularly where helpers may behave differently when run from Haml.
+    #
+    # Note that this is automatically applied to Rails partials.
+    def non_haml
+      was_active = @haml_buffer.active?
+      @haml_buffer.active = false
+      res = yield
+      @haml_buffer.active = was_active
+      res
+    end
+
+    # call-seq:
+    #   find_and_preserve(input)
+    #   find_and_preserve {...}
+    #
     # Isolates the whitespace-sensitive tags in the string and uses preserve
     # to convert any endlines inside them into HTML entities for endlines.
-    def find_and_preserve(input)
+    def find_and_preserve(input = '', &amp;block)
+      return find_and_preserve(capture_haml(&amp;block)) if block
+
       input = input.to_s
       input.gsub(/&lt;(textarea|code|pre)([^&gt;]*)&gt;(.*?)(&lt;\/\1&gt;)/im) do
         &quot;&lt;#{$1}#{$2}&gt;#{preserve($3)}&lt;/#{$1}&gt;&quot;
       end
     end
 
+    # call-seq:
+    #   preserve(input)
+    #   preserve {...}
+    #
     # Takes any string, finds all the endlines and converts them to
     # HTML entities for endlines so they'll render correctly in
     # whitespace-sensitive tags without screwing up the indentation.
-    def preserve(input)      
-      input.gsub(/\n/, '&amp;#x000A;').gsub(/\r/, '')
+    def preserve(input = '', &amp;block)
+      return preserve(capture_haml(&amp;block)) if block
+
+      input.chomp(&quot;\n&quot;).gsub(/\n/, '&amp;#x000A;').gsub(/\r/, '')
     end
 
     alias_method :flatten, :preserve
@@ -95,14 +124,14 @@ module Haml
     def list_of(array, &amp;block) # :yields: item
       to_return = array.collect do |i|
         result = capture_haml(i, &amp;block)
-        
+
         if result.count(&quot;\n&quot;) &gt; 1
           result.gsub!(&quot;\n&quot;, &quot;\n  &quot;)
           result = &quot;\n  #{result.strip}\n&quot;
         else
           result.strip!
         end
-        
+
         &quot;&lt;li&gt;#{result}&lt;/li&gt;&quot;
       end
       to_return.join(&quot;\n&quot;)
@@ -141,17 +170,17 @@ module Haml
     #   &lt;strong&gt;baz&lt;/strong&gt;
     #
     def tab_up(i = 1)
-      buffer.tabulation += i
+      haml_buffer.tabulation += i
     end
 
-    # Increments the number of tabs the buffer automatically adds
+    # Decrements the number of tabs the buffer automatically adds
     # to the lines of the template.
     #
-    # See tab_up.
+    # See also tab_up.
     def tab_down(i = 1)
-      buffer.tabulation -= i
+      haml_buffer.tabulation -= i
     end
-    
+
     # Surrounds the given block of Haml code with the given characters,
     # with no whitespace in between.
     # For example:
@@ -175,10 +204,10 @@ module Haml
     def surround(front, back = nil, &amp;block)
       back ||= front
       output = capture_haml(&amp;block)
-      
+
       &quot;#{front}#{output.chomp}#{back}\n&quot;
     end
-    
+
     # Prepends the given character to the beginning of the Haml block,
     # with no whitespace between.
     # For example:
@@ -193,7 +222,7 @@ module Haml
     def precede(char, &amp;block)
       &quot;#{char}#{capture_haml(&amp;block).chomp}\n&quot;
     end
-    
+
     # Appends the given character to the end of the Haml block,
     # with no whitespace between.
     # For example:
@@ -210,7 +239,7 @@ module Haml
     def succeed(char, &amp;block)
       &quot;#{capture_haml(&amp;block).chomp}#{char}\n&quot;
     end
-    
+
     # Captures the result of the given block of Haml code,
     # gets rid of the excess indentation,
     # and returns it as a string.
@@ -223,35 +252,35 @@ module Haml
     # the local variable &lt;tt&gt;foo&lt;/tt&gt; would be assigned to &quot;&lt;p&gt;13&lt;/p&gt;\n&quot;.
     #
     def capture_haml(*args, &amp;block)
-      capture_haml_with_buffer(buffer.buffer, *args, &amp;block)
+      capture_haml_with_buffer(haml_buffer.buffer, *args, &amp;block)
     end
 
     # Outputs text directly to the Haml buffer, with the proper tabulation
     def puts(text = &quot;&quot;)
-      buffer.buffer &lt;&lt; ('  ' * buffer.tabulation) &lt;&lt; text.to_s &lt;&lt; &quot;\n&quot;
+      haml_buffer.buffer &lt;&lt; ('  ' * haml_buffer.tabulation) &lt;&lt; text.to_s &lt;&lt; &quot;\n&quot;
       nil
     end
 
     #
     # call-seq:
-    #   open(name, attributes = {}) {...}
-    #   open(name, text, attributes = {}) {...}
+    #   haml_tag(name, attributes = {}) {...}
+    #   haml_tag(name, text, attributes = {}) {...}
     #
     # Creates an HTML tag with the given name and optionally text and attributes.
     # Can take a block that will be executed
     # between when the opening and closing tags are output.
     # If the block is a Haml block or outputs text using puts,
     # the text will be properly indented.
-    # 
+    #
     # For example,
     #
-    #   open :table do
-    #     open :tr do
-    #       open :td, {:class =&gt; 'cell'} do
-    #         open :strong, &quot;strong!&quot;
+    #   haml_tag :table do
+    #     haml_tag :tr do
+    #       haml_tag :td, {:class =&gt; 'cell'} do
+    #         haml_tag :strong, &quot;strong!&quot;
     #         puts &quot;data&quot;
     #       end
-    #       open :td do
+    #       haml_tag :td do
     #         puts &quot;more_data&quot;
     #       end
     #     end
@@ -273,19 +302,24 @@ module Haml
     #     &lt;/tr&gt;
     #   &lt;/table&gt;
     #
-    def open(name, attributes = {}, alt_atts = {}, &amp;block)
+    def haml_tag(name, attributes = {}, alt_atts = {}, &amp;block)
+      name = name.to_s
+
       text = nil
       if attributes.is_a? String
         text = attributes
         attributes = alt_atts
       end
 
-      if text.nil? &amp;&amp; block.nil?
-        puts &quot;&lt;#{name}#{Haml::Precompiler.build_attributes(buffer.options[:attr_wrapper], attributes)} /&gt;&quot;
+      attributes = Haml::Precompiler.build_attributes(
+        haml_buffer.html?, haml_buffer.options[:attr_wrapper], attributes)
+
+      if text.nil? &amp;&amp; block.nil? &amp;&amp; haml_buffer.options[:autoclose].include?(name)
+        puts &quot;&lt;#{name}#{attributes} /&gt;&quot;
         return nil
       end
 
-      puts &quot;&lt;#{name}#{Haml::Precompiler.build_attributes(buffer.options[:attr_wrapper], attributes)}&gt;&quot;
+      puts &quot;&lt;#{name}#{attributes}&gt;&quot;
       unless text &amp;&amp; text.empty?
         tab_up
         # Print out either the text (using push_text) or call the block and add an endline
@@ -299,61 +333,81 @@ module Haml
       puts &quot;&lt;/#{name}&gt;&quot;
       nil
     end
-    
+
+    # Characters that need to be escaped to HTML entities from user input
+    HTML_ESCAPE = { '&amp;'=&gt;'&amp;amp;', '&lt;'=&gt;'&amp;lt;', '&gt;'=&gt;'&amp;gt;', '&quot;'=&gt;'&amp;quot;', &quot;'&quot;=&gt;'&amp;#039;', }
+
+    # Returns a copy of &lt;tt&gt;text&lt;/tt&gt; with ampersands, angle brackets and quotes
+    # escaped into HTML entities.
+    def html_escape(text)
+      text.to_s.gsub(/[\&quot;&gt;&lt;&amp;]/) { |s| HTML_ESCAPE[s] }
+    end
+
+    # Escapes HTML entities in &lt;tt&gt;text&lt;/tt&gt;, but without escaping an ampersand
+    # that is already part of an escaped entity.
+    def escape_once(text)
+      text.to_s.gsub(/[\&quot;&gt;&lt;]|&amp;(?!([a-zA-Z]+|(#\d+));)/) { |s| HTML_ESCAPE[s] }
+    end
+
+    # Returns whether or not the current template is a Haml template.
+    #
+    # This function, unlike other Haml::Helpers functions,
+    # also works in other ActionView templates,
+    # where it will always return false.
+    def is_haml?
+      !@haml_buffer.nil? &amp;&amp; @haml_buffer.active?
+    end
+
     private
 
     # Gets a reference to the current Haml::Buffer object.
-    def buffer
-      @haml_stack[-1]
+    def haml_buffer
+      @haml_buffer
     end
-    
+
     # Gives a proc the same local &quot;_hamlout&quot; and &quot;_erbout&quot; variables
     # that the current template has.
-    def bind_proc(&amp;proc)
-      _hamlout = buffer
+    def haml_bind_proc(&amp;proc)
+      _hamlout = haml_buffer
       _erbout = _hamlout.buffer
       proc { |*args| proc.call(*args) }
     end
-    
+
     # Performs the function of capture_haml, assuming &lt;tt&gt;local_buffer&lt;/tt&gt;
     # is where the output of block goes.
     def capture_haml_with_buffer(local_buffer, *args, &amp;block)
       position = local_buffer.length
-      
+
       block.call *args
-      
+
       captured = local_buffer.slice!(position..-1)
-      
+
       min_tabs = nil
       captured.each do |line|
         tabs = line.index(/[^ ]/)
         min_tabs ||= tabs
         min_tabs = min_tabs &gt; tabs ? tabs : min_tabs
       end
-      
+
       result = captured.map do |line|
         line[min_tabs..-1]
       end
       result.to_s
     end
 
-    # Returns whether or not the current template is a Haml template.
-    # 
-    # This function, unlike other Haml::Helpers functions,
-    # also works in other ActionView templates,
-    # where it will always return false.
-    def is_haml?
-      @haml_is_haml
-    end
-
     include ActionViewExtensions if self.const_defined? &quot;ActionViewExtensions&quot;
   end
 end
 
-module ActionView
-  class Base # :nodoc:
-    def is_haml?
-      false
-    end
+class Object
+  # Haml overrides various ActionView helpers,
+  # which call an #is_haml? method
+  # to determine whether or not the current context object
+  # is a proper Haml context.
+  # Because ActionView helpers may be included in non-ActionView::Base classes,
+  # it's a good idea to define is_haml? for all objects.
+  def is_haml?
+    false
   end
 end
+</diff>
      <filename>vendor/plugins/haml/lib/haml/helpers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -31,7 +31,7 @@ if defined?(ActionView)
         #
         #   .entry
         #     :color #00f
-        # 
+        #
         def page_class
           controller.controller_name + &quot; &quot; + controller.action_name
         end</diff>
      <filename>vendor/plugins/haml/lib/haml/helpers/action_view_extensions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,11 +2,8 @@ if defined?(ActionView) and not defined?(Merb::Plugins)
   module ActionView
     class Base # :nodoc:
       def render_with_haml(*args, &amp;block)
-        was_haml = is_haml?
-        @haml_is_haml = false
-        res = render_without_haml(*args, &amp;block)
-        @haml_is_haml = was_haml
-        res
+        return non_haml { render_without_haml(*args, &amp;block) } if is_haml?
+        render_without_haml(*args, &amp;block)
       end
       alias_method :render_without_haml, :render
       alias_method :render, :render_with_haml
@@ -17,6 +14,16 @@ if defined?(ActionView) and not defined?(Merb::Plugins)
     module Helpers
       # :stopdoc:
       module CaptureHelper
+        def capture_with_haml(*args, &amp;block)
+          if is_haml?
+            capture_haml(*args, &amp;block)
+          else
+            capture_without_haml(*args, &amp;block)
+          end
+        end
+        alias_method :capture_without_haml, :capture
+        alias_method :capture, :capture_with_haml
+
         def capture_erb_with_buffer_with_haml(*args, &amp;block)
           if is_haml?
             capture_haml_with_buffer(*args, &amp;block)
@@ -31,7 +38,7 @@ if defined?(ActionView) and not defined?(Merb::Plugins)
       module TextHelper
         def concat_with_haml(string, binding = nil)
           if is_haml?
-            buffer.buffer.concat(string)
+            haml_buffer.buffer.concat(string)
           else
             concat_without_haml(string, binding)
           end
@@ -40,12 +47,41 @@ if defined?(ActionView) and not defined?(Merb::Plugins)
         alias_method :concat, :concat_with_haml
       end
 
+      module TagHelper
+        def content_tag_with_haml(name, *args, &amp;block)
+          content = content_tag_without_haml(name, *args, &amp;block)
+
+          if is_haml? &amp;&amp; haml_buffer.options[:preserve].include?(name.to_s)
+            content = Haml::Helpers.preserve content
+          end
+
+          content
+        end
+        alias_method :content_tag_without_haml, :content_tag
+        alias_method :content_tag, :content_tag_with_haml
+      end
+
+      class InstanceTag
+        # Includes TagHelper
+
+        def haml_buffer
+          @template_object.send :haml_buffer
+        end
+
+        def is_haml?
+          @template_object.send :is_haml?
+        end
+
+        alias_method :content_tag_without_haml, :content_tag
+        alias_method :content_tag, :content_tag_with_haml
+      end
+
       module FormTagHelper
         def form_tag_with_haml(url_for_options = {}, options = {}, *parameters_for_url, &amp;proc)
           if is_haml?
             if block_given?
               oldproc = proc
-              proc = bind_proc do |*args|
+              proc = haml_bind_proc do |*args|
                 concat &quot;\n&quot;
                 tab_up
                 oldproc.call(*args)
@@ -66,8 +102,8 @@ if defined?(ActionView) and not defined?(Merb::Plugins)
       module FormHelper
         def form_for_with_haml(object_name, *args, &amp;proc)
           if block_given? &amp;&amp; is_haml?
-            oldproc = proc 
-            proc = bind_proc do |*args|
+            oldproc = proc
+            proc = haml_bind_proc do |*args|
               tab_up
               oldproc.call(*args)
               tab_down</diff>
      <filename>vendor/plugins/haml/lib/haml/helpers/action_view_mods.rb</filename>
    </modified>
    <modified>
      <diff>@@ -59,7 +59,7 @@ module Haml
           String.new
         else
           lines = text.split(&quot;\n&quot;)
-          
+
           lines.map do |line|
             line.strip!
             &quot;#{tabulate(tabs)}#{'\\' if Haml::Engine::SPECIAL_CHARACTERS.include?(line[0])}#{line}\n&quot;
@@ -73,7 +73,7 @@ module Haml
     def self.options
       @@options
     end
-    
+
     TEXT_REGEXP = /^(\s*).*$/
 
     class ::Hpricot::Doc
@@ -129,14 +129,14 @@ module Haml
 
     class ::Hpricot::Elem
       def to_haml(tabs = 0)
-        output = &quot;#{tabulate(tabs)}&quot;        
+        output = &quot;#{tabulate(tabs)}&quot;
         if HTML.options[:rhtml] &amp;&amp; name[0...5] == 'haml:'
           return output + HTML.send(&quot;haml_tag_#{name[5..-1]}&quot;,
                                     CGI.unescapeHTML(self.innerHTML))
         end
 
         output += &quot;%#{name}&quot; unless name == 'div' &amp;&amp; (attributes.include?('id') || attributes.include?('class'))
-        
+
         if attributes
           output += &quot;##{attributes['id']}&quot; if attributes['id']
           attributes['class'].split(' ').each { |c| output += &quot;.#{c}&quot; } if attributes['class']
@@ -144,10 +144,10 @@ module Haml
           remove_attribute('class')
           output += haml_attributes if attributes.length &gt; 0
         end
-        
+
         output += &quot;/&quot; if children.length == 0
         output += &quot;\n&quot;
-        
+
         self.children.each do |child|
           output += child.to_haml(tabs + 1)
         end</diff>
      <filename>vendor/plugins/haml/lib/haml/html.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,12 +14,15 @@ module Haml
     # Designates an XHTML/XML comment.
     COMMENT         = ?/
 
-    # Designates an XHTML doctype.
+    # Designates an XHTML doctype or script that is never HTML-escaped.
     DOCTYPE         = ?!
 
     # Designates script, the result of which is output.
     SCRIPT          = ?=
 
+    # Designates script that is always HTML-escaped.
+    SANITIZE        = ?&amp;
+
     # Designates script, the result of which is flattened and output.
     FLAT_SCRIPT     = ?~
 
@@ -47,6 +50,7 @@ module Haml
       COMMENT,
       DOCTYPE,
       SCRIPT,
+      SANITIZE,
       FLAT_SCRIPT,
       SILENT_SCRIPT,
       ESCAPE,
@@ -75,15 +79,9 @@ module Haml
     # is a member of this array.
     MID_BLOCK_KEYWORDS   = ['else', 'elsif', 'rescue', 'ensure', 'when']
 
-    # The Regex that matches an HTML comment command.
-    COMMENT_REGEX = /\/(\[[\w\s\.]*\])?(.*)/
-
     # The Regex that matches a Doctype command.
     DOCTYPE_REGEX = /(\d\.\d)?[\s]*([a-z]*)/i
 
-    # The Regex that matches an HTML tag command.
-    TAG_REGEX = /[%]([-:\w]+)([-\w\.\#]*)(\{.*\})?(\[.*\])?([=\/\~]?)?(.*)?/
-
     # The Regex that matches a literal string or symbol value
     LITERAL_VALUE_REGEX = /^\s*(:(\w*)|(('|&quot;)([^\\\#'&quot;]*?)\4))\s*$/
 
@@ -93,15 +91,12 @@ module Haml
     def precompiled_with_ambles(local_names)
       preamble = &lt;&lt;END.gsub(&quot;\n&quot;, &quot;;&quot;)
 extend Haml::Helpers
-@haml_stack ||= Array.new
-@haml_stack.push(Haml::Buffer.new(#{options_for_buffer.inspect}))
-@haml_is_haml = true
-_hamlout = @haml_stack[-1]
+_hamlout = @haml_buffer = Haml::Buffer.new(@haml_buffer, #{options_for_buffer.inspect})
 _erbout = _hamlout.buffer
 END
       postamble = &lt;&lt;END.gsub(&quot;\n&quot;, &quot;;&quot;)
-@haml_is_haml = false
-@haml_stack.pop.buffer
+@haml_buffer = @haml_buffer.upper
+_erbout
 END
       preamble + locals_code(local_names) + @precompiled + postamble
     end
@@ -122,12 +117,12 @@ END
       @tab_change  = 0
 
       old_line = Line.new
-      (@template + &quot;\n-#&quot;).each_with_index do |text, index|
+      (@template + &quot;\n-#\n-#&quot;).split(/\n?\r|\r?\n/).each_with_index do |text, index|
         line = Line.new text.strip, text.lstrip.chomp, index
         line.spaces, line.tabs = count_soft_tabs(text)
 
         if line.text.empty?
-          process_indent(old_line) unless !flat? || old_line.text.empty?
+          process_indent(old_line) if flat? &amp;&amp; !old_line.text.empty?
 
           unless flat?
             newline
@@ -144,6 +139,7 @@ END
 
         if old_line.text.nil? || suppress_render
           old_line = line
+          resolve_newlines
           newline
           next
         end
@@ -158,15 +154,20 @@ END
         end
 
         if old_line.spaces != old_line.tabs * 2
-          raise SyntaxError.new(&quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;)
+          raise SyntaxError.new(&lt;&lt;END.strip, 1 + old_line.index - @index)
+#{old_line.spaces} space#{old_line.spaces == 1 ? ' was' : 's were'} used for indentation. Haml must be indented using two spaces.
+END
         end
 
         unless old_line.text.empty? || @haml_comment
           process_line(old_line.text, old_line.index, line.tabs &gt; old_line.tabs &amp;&amp; !line.text.empty?)
         end
+        resolve_newlines
 
         if !flat? &amp;&amp; line.tabs - old_line.tabs &gt; 1
-          raise SyntaxError.new(&quot;Illegal Indentation: Indenting more than once per line is illegal.&quot;)
+          raise SyntaxError.new(&lt;&lt;END.strip, 2 + old_line.index - @index)
+#{line.spaces} spaces were used for indentation. Haml must be indented using two spaces.
+END
         end
         old_line = line
         newline
@@ -176,7 +177,7 @@ END
       close until @to_close_stack.empty?
       flush_merged_text
     end
-        
+
     # Processes and deals with lowering indentation.
     def process_indent(line)
       return unless line.tabs &lt;= @template_tabs &amp;&amp; @template_tabs &gt; 0
@@ -194,30 +195,37 @@ END
       @index = index + 1
 
       case text[0]
-      when DIV_CLASS, DIV_ID: render_div(text)
-      when ELEMENT: render_tag(text)
-      when COMMENT: render_comment(text)
+      when DIV_CLASS, DIV_ID; render_div(text)
+      when ELEMENT; render_tag(text)
+      when COMMENT; render_comment(text[1..-1].strip)
+      when SANITIZE
+        return push_script(unescape_interpolation(text[3..-1].strip), false, false, false, true) if text[1..2] == &quot;==&quot;
+        return push_script(text[2..-1].strip, false, false, false, true) if text[1] == SCRIPT
+        push_plain text
       when SCRIPT
         return push_script(unescape_interpolation(text[2..-1].strip), false) if text[1] == SCRIPT
+        return push_script(text[1..-1], false, false, false, true) if options[:escape_html]
         push_script(text[1..-1], false)
-      when FLAT_SCRIPT: push_flat_script(text[1..-1])
+      when FLAT_SCRIPT; push_flat_script(text[1..-1])
       when SILENT_SCRIPT
         return start_haml_comment if text[1] == SILENT_COMMENT
 
         push_silent(text[1..-1], true)
-        newline true
+        newline_now
         if (@block_opened &amp;&amp; !mid_block_keyword?(text)) || text[1..-1].split(' ', 2)[0] == &quot;case&quot;
           push_and_tabulate([:script])
         end
-      when FILTER: start_filtered(text[1..-1].downcase)
+      when FILTER; start_filtered(text[1..-1].downcase)
       when DOCTYPE
         return render_doctype(text) if text[0...3] == '!!!'
+        return push_script(unescape_interpolation(text[3..-1].strip), false) if text[1..2] == &quot;==&quot;
+        return push_script(text[2..-1].strip, false) if text[1] == SCRIPT
         push_plain text
-      when ESCAPE: push_plain text[1..-1]
+      when ESCAPE; push_plain text[1..-1]
       else push_plain text
       end
     end
-    
+
     # Returns whether or not the text is a silent script text with one
     # of Ruby's mid-block keywords.
     def mid_block_keyword?(text)
@@ -237,7 +245,7 @@ END
         @multiline.text &lt;&lt; text[0...-1]
         return true
       end
-      
+
       # A multiline string has just been activated, start adding the lines
       if is_multiline?(text) &amp;&amp; (MULTILINE_STARTERS.include? text[0])
         @multiline = Line.new text[0...-1], nil, line.index, nil, line.tabs
@@ -262,73 +270,91 @@ END
     # Evaluates &lt;tt&gt;text&lt;/tt&gt; in the context of the scope object, but
     # does not output the result.
     def push_silent(text, can_suppress = false)
-      flush_merged_text      
+      flush_merged_text
       return if can_suppress &amp;&amp; options[:suppress_eval]
       @precompiled &lt;&lt; &quot;#{text};&quot;
     end
 
     # Adds &lt;tt&gt;text&lt;/tt&gt; to &lt;tt&gt;@buffer&lt;/tt&gt; with appropriate tabulation
     # without parsing it.
-    def push_merged_text(text, tab_change = 0, try_one_liner = false)
-      @merged_text  &lt;&lt; &quot;#{'  ' * @output_tabs}#{text}&quot;
+    def push_merged_text(text, tab_change = 0, indent = true)
+      @merged_text  &lt;&lt; (!indent || @dont_indent_next_line || @options[:ugly] ? text : &quot;#{'  ' * @output_tabs}#{text}&quot;)
+      @dont_indent_next_line = false
       @tab_change   += tab_change
-      @try_one_liner = try_one_liner
     end
-    
-    def push_text(text, tab_change = 0, try_one_liner = false)
-      push_merged_text(&quot;#{text}\n&quot;, tab_change, try_one_liner)
+
+    # Concatenate &lt;tt&gt;text&lt;/tt&gt; to &lt;tt&gt;@buffer&lt;/tt&gt; without tabulation.
+    def concat_merged_text(text)
+      @merged_text  &lt;&lt; text
     end
-    
+
+    def push_text(text, tab_change = 0)
+      push_merged_text(&quot;#{text}\n&quot;, tab_change)
+    end
+
     def flush_merged_text
       return if @merged_text.empty?
 
       @precompiled  &lt;&lt; &quot;_hamlout.push_text(#{@merged_text.dump}&quot;
-      @precompiled  &lt;&lt; &quot;, #{@tab_change}&quot; if @tab_change != 0 || @try_one_liner
+      @precompiled  &lt;&lt; &quot;, #{@dont_tab_up_next_text.inspect}&quot; if @dont_tab_up_next_text || @tab_change != 0
+      @precompiled  &lt;&lt; &quot;, #{@tab_change}&quot; if @tab_change != 0
       @precompiled  &lt;&lt; &quot;);&quot;
       @merged_text   = ''
+      @dont_tab_up_next_text = false
       @tab_change    = 0
-      @try_one_liner = false
-    end  
+    end
 
     # Renders a block of text as plain text.
     # Also checks for an illegally opened block.
     def push_plain(text)
-      raise SyntaxError.new(&quot;Illegal Nesting: Nesting within plain text is illegal.&quot;) if @block_opened
+      raise SyntaxError.new(&quot;Illegal nesting: nesting within plain text is illegal.&quot;, 1) if @block_opened
       push_text text
     end
 
     # Adds +text+ to &lt;tt&gt;@buffer&lt;/tt&gt; while flattening text.
     def push_flat(line)
-      tabulation = line.spaces - @flat_spaces
-      tabulation = tabulation &gt; -1 ? tabulation : 0
-      @filter_buffer &lt;&lt; &quot;#{' ' * tabulation}#{line.unstripped}\n&quot;
+      unless @options[:ugly]
+        tabulation = line.spaces - @flat_spaces
+        tabulation = tabulation &gt; -1 ? tabulation : 0
+        @filter_buffer &lt;&lt; &quot;#{' ' * tabulation}#{line.unstripped}\n&quot;
+      else
+        @filter_buffer &lt;&lt; &quot;#{line.unstripped}\n&quot;
+      end
     end
 
     # Causes &lt;tt&gt;text&lt;/tt&gt; to be evaluated in the context of
     # the scope object and the result to be added to &lt;tt&gt;@buffer&lt;/tt&gt;.
     #
-    # If &lt;tt&gt;flattened&lt;/tt&gt; is true, Haml::Helpers#find_and_flatten is run on
+    # If &lt;tt&gt;preserve_script&lt;/tt&gt; is true, Haml::Helpers#find_and_flatten is run on
     # the result before it is added to &lt;tt&gt;@buffer&lt;/tt&gt;
-    def push_script(text, flattened, close_tag = nil)
+    def push_script(text, preserve_script, in_tag = false, preserve_tag = false,
+                    escape_html = false, nuke_inner_whitespace = false)
+      # Prerender tabulation unless we're in a tag
+      push_merged_text '' unless in_tag
+
       flush_merged_text
       return if options[:suppress_eval]
 
+      raise SyntaxError.new(&quot;There's no Ruby code for = to evaluate.&quot;) if text.empty?
+
       push_silent &quot;haml_temp = #{text}&quot;
-      newline true
-      out = &quot;haml_temp = _hamlout.push_script(haml_temp, #{flattened.inspect}, #{close_tag.inspect});&quot;
+      newline_now
+      args = [preserve_script, in_tag, preserve_tag,
+              escape_html, nuke_inner_whitespace].map { |a| a.inspect }.join(', ')
+      out = &quot;haml_temp = _hamlout.push_script(haml_temp, #{args});&quot;
       if @block_opened
         push_and_tabulate([:loud, out])
       else
         @precompiled &lt;&lt; out
       end
     end
-    
+
     # Causes &lt;tt&gt;text&lt;/tt&gt; to be evaluated, and Haml::Helpers#find_and_flatten
     # to be run on it afterwards.
     def push_flat_script(text)
       flush_merged_text
-      
-      raise SyntaxError.new(&quot;Tag has no content.&quot;) if text.empty?
+
+      raise SyntaxError.new(&quot;There's no Ruby code for ~ to evaluate.&quot;) if text.empty?
       push_script(text, true)
     end
 
@@ -343,21 +369,25 @@ END
     def close
       tag, value = @to_close_stack.pop
       case tag
-      when :script: close_block
-      when :comment: close_comment value
-      when :element: close_tag value
-      when :loud: close_loud value
-      when :filtered: close_filtered value
-      when :haml_comment: close_haml_comment
+      when :script; close_block
+      when :comment; close_comment value
+      when :element; close_tag value
+      when :loud; close_loud value
+      when :filtered; close_filtered value
+      when :haml_comment; close_haml_comment
       end
     end
 
     # Puts a line in &lt;tt&gt;@precompiled&lt;/tt&gt; that will add the closing tag of
     # the most recently opened tag.
-    def close_tag(tag)
-      @output_tabs -= 1
+    def close_tag(value)
+      tag, nuke_outer_whitespace, nuke_inner_whitespace = value
+      @output_tabs -= 1 unless nuke_inner_whitespace
       @template_tabs -= 1
-      push_text(&quot;&lt;/#{tag}&gt;&quot;, -1)
+      rstrip_buffer! if nuke_inner_whitespace
+      push_merged_text(&quot;&lt;/#{tag}&gt;&quot; + (nuke_outer_whitespace ? &quot;&quot; : &quot;\n&quot;),
+                       nuke_inner_whitespace ? 0 : -1, !nuke_inner_whitespace)
+      @dont_indent_next_line = nuke_outer_whitespace
     end
 
     # Closes a Ruby block.
@@ -373,7 +403,7 @@ END
       close_tag = has_conditional ? &quot;&lt;![endif]--&gt;&quot; : &quot;--&gt;&quot;
       push_text(close_tag, -1)
     end
-    
+
     # Closes a loud Ruby block.
     def close_loud(command)
       push_silent 'end', true
@@ -384,14 +414,7 @@ END
     # Closes a filtered block.
     def close_filtered(filter)
       @flat_spaces = -1
-      filtered = filter.new(@filter_buffer).render
-
-      if filter == Haml::Filters::Preserve
-        push_silent(&quot;_hamlout.buffer &lt;&lt; #{filtered.dump} &lt;&lt; \&quot;\\n\&quot;;&quot;)
-      else
-        push_text(filtered.rstrip.gsub(&quot;\n&quot;, &quot;\n#{'  ' * @output_tabs}&quot;))
-      end
-
+      filter.internal_compile(self, @filter_buffer)
       @filter_buffer = nil
       @template_tabs -= 1
     end
@@ -400,7 +423,7 @@ END
       @haml_comment = false
       @template_tabs -= 1
     end
-    
+
     # Iterates through the classes and ids supplied through &lt;tt&gt;.&lt;/tt&gt;
     # and &lt;tt&gt;#&lt;/tt&gt; syntax, and returns a hash with them as attributes,
     # that can then be merged with another attributes hash.
@@ -415,7 +438,7 @@ END
             attributes['class'] = &quot;&quot;
           end
           attributes['class'] += property
-        when '#': attributes['id'] = property
+        when '#'; attributes['id'] = property
         end
       end
       attributes
@@ -429,16 +452,16 @@ END
       # $5 holds the value matched by a string
       $2 || $5
     end
-    
-    def parse_static_hash(text)  
-      return {} unless text &amp;&amp; inner = text.scan(/^\{(.*)\}$/)[0]
+
+    def parse_static_hash(text)
+      return {} unless text
 
       attributes = {}
-      inner[0].split(',').each do |attrib|
+      text.split(',').each do |attrib|
         key, value, more = attrib.split('=&gt;')
 
         # Make sure the key and value and only the key and value exist
-        # Otherwise, it's too complicated and we'll defer it to the actual Ruby parser
+        # Otherwise, it's too complicated or dynamic and we'll defer it to the actual Ruby parser
         key = parse_literal_value key
         value = parse_literal_value value
         return nil if more || key.nil? || value.nil?
@@ -449,14 +472,23 @@ END
     end
 
     # This is a class method so it can be accessed from Buffer.
-    def self.build_attributes(attr_wrapper, attributes = {})
+    def self.build_attributes(is_html, attr_wrapper, attributes = {})
       quote_escape = attr_wrapper == '&quot;' ? &quot;&amp;quot;&quot; : &quot;&amp;apos;&quot;
       other_quote_char = attr_wrapper == '&quot;' ? &quot;'&quot; : '&quot;'
-  
+
       result = attributes.collect do |attr, value|
         next if value.nil?
 
-        value = value.to_s
+        if value == true
+          next &quot; #{attr}&quot; if is_html
+          next &quot; #{attr}=#{attr_wrapper}#{attr}#{attr_wrapper}&quot;
+        elsif value == false
+          next
+        end
+
+        value = Haml::Helpers.escape_once(value.to_s)
+        # We want to decide whether or not to escape quotes
+        value.gsub!('&amp;quot;', '&quot;')
         this_attr_wrapper = attr_wrapper
         if value.include? attr_wrapper
           if value.include? other_quote_char
@@ -470,73 +502,129 @@ END
       result.compact.sort.join
     end
 
-    def prerender_tag(name, atomic, attributes)
-      &quot;&lt;#{name}#{Precompiler.build_attributes(@options[:attr_wrapper], attributes)}#{atomic ? ' /&gt;' : '&gt;'}&quot;
+    def prerender_tag(name, self_close, attributes)
+      attributes_string = Precompiler.build_attributes(html?, @options[:attr_wrapper], attributes)
+      &quot;&lt;#{name}#{attributes_string}#{self_close &amp;&amp; xhtml? ? ' /' : ''}&gt;&quot;
+    end
+
+    # Parses a line into tag_name, attributes, attributes_hash, object_ref, action, value
+    def parse_tag(line)
+      raise SyntaxError.new(&quot;Invalid tag: \&quot;#{line}\&quot;.&quot;) unless match = line.scan(/%([-:\w]+)([-\w\.\#]*)(.*)/)[0]
+      tag_name, attributes, rest = match
+      attributes_hash, rest = parse_attributes(rest) if rest[0] == ?{
+      if rest
+        object_ref, rest = balance(rest, ?[, ?]) if rest[0] == ?[
+        attributes_hash, rest = parse_attributes(rest) if rest[0] == ?{ &amp;&amp; attributes_hash.nil?
+        nuke_whitespace, action, value = rest.scan(/(&lt;&gt;|&gt;&lt;|[&gt;&lt;])?([=\/\~&amp;!])?(.*)?/)[0]
+        nuke_whitespace ||= ''
+        nuke_outer_whitespace = nuke_whitespace.include? '&gt;'
+        nuke_inner_whitespace = nuke_whitespace.include? '&lt;'
+      end
+      value = value.to_s.strip
+      [tag_name, attributes, attributes_hash, object_ref, nuke_outer_whitespace,
+       nuke_inner_whitespace, action, value]
+    end
+
+    def parse_attributes(line)
+      scanner = StringScanner.new(line)
+      attributes_hash, rest = balance(scanner, ?{, ?})
+      attributes_hash = attributes_hash[1...-1] if attributes_hash
+      return attributes_hash, rest
     end
 
     # Parses a line that will render as an XHTML tag, and adds the code that will
     # render that tag to &lt;tt&gt;@precompiled&lt;/tt&gt;.
     def render_tag(line)
-      raise SyntaxError.new(&quot;Invalid tag: \&quot;#{line}\&quot;&quot;) unless match = line.scan(TAG_REGEX)[0]
-      tag_name, attributes, attributes_hash, object_ref, action, value = match
-      value = value.to_s.strip
+      tag_name, attributes, attributes_hash, object_ref, nuke_outer_whitespace,
+        nuke_inner_whitespace, action, value = parse_tag(line)
 
       raise SyntaxError.new(&quot;Illegal element: classes and ids must have values.&quot;) if attributes =~ /[\.#](\.|#|\z)/
 
+      # Get rid of whitespace outside of the tag if we need to
+      rstrip_buffer! if nuke_outer_whitespace
+
+      preserve_tag = options[:preserve].include?(tag_name)
+      nuke_inner_whitespace ||= preserve_tag
+
       case action
-      when '/': atomic = true
-      when '~': parse = flattened = true
-      when '=':
+      when '/'; self_closing = xhtml?
+      when '~'; parse = preserve_script = true
+      when '='
         parse = true
         value = unescape_interpolation(value[1..-1].strip) if value[0] == ?=
+      when '&amp;', '!'
+        if value[0] == ?=
+          parse = true
+          value = (value[1] == ?= ? unescape_interpolation(value[2..-1].strip) : value[1..-1].strip)
+        end
       end
-        
+
       if parse &amp;&amp; @options[:suppress_eval]
         parse = false
         value = ''
       end
 
+      escape_html = (action == '&amp;' || (action != '!' &amp;&amp; @options[:escape_html]))
+
       object_ref = &quot;nil&quot; if object_ref.nil? || @options[:suppress_eval]
 
       static_attributes = parse_static_hash(attributes_hash) # Try pre-compiling a static attributes hash
-      attributes_hash = &quot;{nil}&quot; if attributes_hash.nil? || static_attributes || @options[:suppress_eval]
+      attributes_hash = nil if static_attributes || @options[:suppress_eval]
       attributes = parse_class_and_id(attributes)
       Buffer.merge_attrs(attributes, static_attributes) if static_attributes
 
-      raise SyntaxError.new(&quot;Illegal Nesting: Nesting within an atomic tag is illegal.&quot;) if @block_opened &amp;&amp; atomic
-      raise SyntaxError.new(&quot;Illegal Nesting: Nesting within a tag that already has content is illegal.&quot;) if @block_opened &amp;&amp; !value.empty?
-      raise SyntaxError.new(&quot;Tag has no content.&quot;) if parse &amp;&amp; value.empty?
-      raise SyntaxError.new(&quot;Atomic tags can't have content.&quot;) if atomic &amp;&amp; !value.empty?
+      raise SyntaxError.new(&quot;Illegal nesting: nesting within a self-closing tag is illegal.&quot;, 1) if @block_opened &amp;&amp; self_closing
+      raise SyntaxError.new(&quot;Illegal nesting: content can't be both given on the same line as %#{tag_name} and nested within it.&quot;, 1) if @block_opened &amp;&amp; !value.empty?
+      raise SyntaxError.new(&quot;There's no Ruby code for #{action} to evaluate.&quot;) if parse &amp;&amp; value.empty?
+      raise SyntaxError.new(&quot;Self-closing tags can't have content.&quot;) if self_closing &amp;&amp; !value.empty?
 
-      atomic = true if !@block_opened &amp;&amp; value.empty? &amp;&amp; @options[:autoclose].include?(tag_name)
-      
-      if object_ref == &quot;nil&quot; &amp;&amp; attributes_hash == &quot;{nil}&quot; &amp;&amp; !flattened &amp;&amp; (parse || Buffer.one_liner?(value))
-        # This means that we can render the tag directly to text and not process it in the buffer
-        tag_closed = !value.empty? &amp;&amp; Buffer.one_liner?(value) &amp;&amp; !parse
+      self_closing ||= !!( !@block_opened &amp;&amp; value.empty? &amp;&amp; @options[:autoclose].include?(tag_name) )
 
-        open_tag  = prerender_tag(tag_name, atomic, attributes)
-        open_tag &lt;&lt; &quot;#{value}&lt;/#{tag_name}&gt;&quot; if tag_closed
-        open_tag &lt;&lt; &quot;\n&quot; unless parse
+      dont_indent_next_line =
+        (nuke_outer_whitespace &amp;&amp; !@block_opened) ||
+        (nuke_inner_whitespace &amp;&amp; @block_opened)
 
-        push_merged_text(open_tag, tag_closed || atomic ? 0 : 1, parse)
+      # Check if we can render the tag directly to text and not process it in the buffer
+      if object_ref == &quot;nil&quot; &amp;&amp; attributes_hash.nil? &amp;&amp; !preserve_script
+        tag_closed = !@block_opened &amp;&amp; !self_closing &amp;&amp; !parse
+
+        open_tag  = prerender_tag(tag_name, self_closing, attributes)
+        if tag_closed
+          open_tag &lt;&lt; &quot;#{value}&lt;/#{tag_name}&gt;&quot;
+          open_tag &lt;&lt; &quot;\n&quot; unless nuke_outer_whitespace
+        else
+          open_tag &lt;&lt; &quot;\n&quot; unless parse || nuke_inner_whitespace || (self_closing &amp;&amp; nuke_outer_whitespace)
+        end
+        
+        push_merged_text(open_tag, tag_closed || self_closing || nuke_inner_whitespace ? 0 : 1,
+                         !nuke_outer_whitespace)
+
+        @dont_indent_next_line = dont_indent_next_line
         return if tag_closed
       else
         flush_merged_text
         content = value.empty? || parse ? 'nil' : value.dump
-        push_silent &quot;_hamlout.open_tag(#{tag_name.inspect}, #{atomic.inspect}, #{(!value.empty?).inspect}, #{attributes.inspect}, #{object_ref}, #{content}, #{attributes_hash[1...-1]})&quot;
+        attributes_hash = ', ' + attributes_hash if attributes_hash
+        args = [tag_name, self_closing, !@block_opened, preserve_tag, escape_html,
+                attributes, nuke_outer_whitespace, nuke_inner_whitespace
+               ].map { |v| v.inspect }.join(', ')
+        push_silent &quot;_hamlout.open_tag(#{args}, #{object_ref}, #{content}#{attributes_hash})&quot;
+        @dont_tab_up_next_text = @dont_indent_next_line = dont_indent_next_line
       end
-          
-      return if atomic
+
+      return if self_closing
 
       if value.empty?
-        push_and_tabulate([:element, tag_name])
-        @output_tabs += 1
+        push_and_tabulate([:element, [tag_name, nuke_outer_whitespace, nuke_inner_whitespace]])
+        @output_tabs += 1 unless nuke_inner_whitespace
         return
       end
-      
+
       if parse
         flush_merged_text
-        push_script(value, flattened, tag_name)
+        push_script(value, preserve_script, true, preserve_tag, escape_html, nuke_inner_whitespace)
+        @dont_tab_up_next_text = true
+        concat_merged_text(&quot;&lt;/#{tag_name}&gt;&quot; + (nuke_outer_whitespace ? &quot;&quot; : &quot;\n&quot;))
       end
     end
 
@@ -548,92 +636,119 @@ END
 
     # Renders an XHTML comment.
     def render_comment(line)
-      conditional, content = line.scan(COMMENT_REGEX)[0]
-      content.strip!
+      conditional, line = balance(line, ?[, ?]) if line[0] == ?[
+      line.strip!
       conditional &lt;&lt; &quot;&gt;&quot; if conditional
-      
-      if @block_opened &amp;&amp; !content.empty?
-        raise SyntaxError.new('Illegal Nesting: Nesting within a tag that already has content is illegal.')
+
+      if @block_opened &amp;&amp; !line.empty?
+        raise SyntaxError.new('Illegal nesting: nesting within a tag that already has content is illegal.', 1)
       end
 
       open = &quot;&lt;!--#{conditional} &quot;
-      
+
       # Render it statically if possible
-      if !content.empty? &amp;&amp; Buffer.one_liner?(content)
-        return push_text(&quot;#{open}#{content} #{conditional ? &quot;&lt;![endif]--&gt;&quot; : &quot;--&gt;&quot;}&quot;)
+      unless line.empty?
+        return push_text(&quot;#{open}#{line} #{conditional ? &quot;&lt;![endif]--&gt;&quot; : &quot;--&gt;&quot;}&quot;)
       end
 
       push_text(open, 1)
       @output_tabs += 1
       push_and_tabulate([:comment, !conditional.nil?])
-      unless content.empty?
-        push_text(content)
+      unless line.empty?
+        push_text(line)
         close
       end
     end
-    
+
     # Renders an XHTML doctype or XML shebang.
     def render_doctype(line)
-      raise SyntaxError.new(&quot;Illegal Nesting: Nesting within a header command is illegal.&quot;) if @block_opened
-      push_text text_for_doctype(line)
+      raise SyntaxError.new(&quot;Illegal nesting: nesting within a header command is illegal.&quot;, 1) if @block_opened
+      doctype = text_for_doctype(line)
+      push_text doctype if doctype
     end
 
     def text_for_doctype(text)
       text = text[3..-1].lstrip.downcase
-      if text[0...3] == &quot;xml&quot;
+      if text.index(&quot;xml&quot;) == 0
+        return nil if html?
         wrapper = @options[:attr_wrapper]
         return &quot;&lt;?xml version=#{wrapper}1.0#{wrapper} encoding=#{wrapper}#{text.split(' ')[1] || &quot;utf-8&quot;}#{wrapper} ?&gt;&quot;
       end
 
-      version, type = text.scan(DOCTYPE_REGEX)[0]
-      if version == &quot;1.1&quot;
-        return '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.1//EN&quot; &quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;&gt;'
-      end
+      if html5?
+        '&lt;!DOCTYPE html&gt;'
+      else
+        version, type = text.scan(DOCTYPE_REGEX)[0]
 
-      case type
-      when &quot;strict&quot;:   return '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;'
-      when &quot;frameset&quot;: return '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Frameset//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd&quot;&gt;'
-      else             return '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;'
+        if xhtml?
+          if version == &quot;1.1&quot;
+            '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.1//EN&quot; &quot;http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd&quot;&gt;'
+          else
+            case type
+            when &quot;strict&quot;;   '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;'
+            when &quot;frameset&quot;; '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Frameset//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd&quot;&gt;'
+            else             '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;'
+            end
+          end
+
+        elsif html4?
+          case type
+          when &quot;strict&quot;;   '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt;'
+          when &quot;frameset&quot;; '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Frameset//EN&quot; &quot;http://www.w3.org/TR/html4/frameset.dtd&quot;&gt;'
+          else             '&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;'
+          end
+        end
       end
     end
 
     # Starts a filtered block.
     def start_filtered(name)
-      raise SyntaxError.new('Filters must have nested text.') unless @block_opened
+      raise Error.new(&quot;Invalid filter name \&quot;:#{name}\&quot;.&quot;) unless name =~ /^\w+$/
 
       unless filter = options[:filters][name]
         if filter == 'redcloth' || filter == 'markdown' || filter == 'textile'
-          raise HamlError.new(&quot;You must have the RedCloth gem installed to use \&quot;#{name}\&quot; filter&quot;)
+          raise Error.new(&quot;You must have the RedCloth gem installed to use \&quot;#{name}\&quot; filter&quot;)
         end
-        raise HamlError.new(&quot;\&quot;#{name}\&quot; filter is not defined!&quot;)
+        raise Error.new(&quot;Filter \&quot;#{name}\&quot; is not defined.&quot;)
       end
 
       push_and_tabulate([:filtered, filter])
       @flat_spaces = @template_tabs * 2
       @filter_buffer = String.new
+      @block_opened = false
+    end
+
+    def contains_interpolation?(str)
+      str.include?('#{')
     end
 
     def unescape_interpolation(str)
       scan = StringScanner.new(str.dump)
       str = ''
 
-      while scan.scan(/(.*?)\\\#\{/)
-        str &lt;&lt; scan.matched[0...-3]
-        str &lt;&lt; eval(&quot;\&quot;\\\#{#{balance_brackets(scan)}}\&quot;&quot;)
+      while scan.scan(/(.*?)(\\+)\#\{/)
+        escapes = (scan[2].size - 1) / 2
+        str &lt;&lt; scan.matched[0...-3 - escapes]
+        if escapes % 2 == 1
+          str &lt;&lt; '#{'
+        else
+          # Use eval to get rid of string escapes
+          str &lt;&lt; '#{' + eval('&quot;' + balance(scan, ?{, ?}, 1)[0][0...-1] + '&quot;') + &quot;}&quot;
+        end
       end
 
       str + scan.rest
     end
 
-    def balance_brackets(scanner)
+    def balance(scanner, start, finish, count = 0)
       str = ''
-      count = 1
-
-      while scanner.scan(/(.*?)[\{\}]/)
+      scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
+      regexp = Regexp.new(&quot;(.*?)[\\#{start.chr}\\#{finish.chr}]&quot;)
+      while scanner.scan(regexp)
         str &lt;&lt; scanner.matched
-        count += 1 if scanner.matched[-1] == ?{
-        count -= 1 if scanner.matched[-1] == ?}
-        return str[0...-1] if count == 0
+        count += 1 if scanner.matched[-1] == start
+        count -= 1 if scanner.matched[-1] == finish
+        return [str.strip, scanner.rest] if count == 0
       end
 
       raise SyntaxError.new(&quot;Unbalanced brackets.&quot;)
@@ -641,14 +756,17 @@ END
 
     # Counts the tabulation of a line.
     def count_soft_tabs(line)
-      spaces = line.index(/[^ ]/)
+      spaces = line.index(/([^ ]|$)/)
       if line[spaces] == ?\t
         return nil if line.strip.empty?
-        raise SyntaxError.new(&quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;)
+        raise SyntaxError.new(&lt;&lt;END.strip, 2)
+A tab character was used for indentation. Haml must be indented using two spaces.
+Are you sure you have soft tabs enabled in your editor?
+END
       end
       [spaces, spaces/2]
     end
-    
+
     # Pushes value onto &lt;tt&gt;@to_close_stack&lt;/tt&gt; and increases
     # &lt;tt&gt;@template_tabs&lt;/tt&gt;.
     def push_and_tabulate(value)
@@ -660,10 +778,30 @@ END
       @flat_spaces != -1
     end
 
-    def newline(skip_next = false)
-      return @skip_next_newline = false if @skip_next_newline
-      @skip_next_newline = true if skip_next
+    def newline
+      @newlines += 1
+    end
+
+    def newline_now
       @precompiled &lt;&lt; &quot;\n&quot;
+      @newlines -= 1
+    end
+
+    def resolve_newlines
+      return unless @newlines &gt; 0
+      @precompiled &lt;&lt; &quot;\n&quot; * @newlines
+      @newlines = 0
+    end
+
+    # Get rid of and whitespace at the end of the buffer
+    # or the merged text
+    def rstrip_buffer!
+      unless @merged_text.empty?
+        @merged_text.rstrip!
+      else
+        push_silent(&quot;_erbout.rstrip!&quot;, false)
+        @dont_tab_up_next_text = true
+      end
     end
   end
 end</diff>
      <filename>vendor/plugins/haml/lib/haml/precompiler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,19 +1,16 @@
 require 'haml/engine'
-require 'rubygems'
-require 'active_support'
-require 'action_view'
 
 module Haml
   class Template
     class &lt;&lt; self
       @@options = {}
 
-      # Gets various options for Haml. See README for details.
+      # Gets various options for Haml. See README.rdoc for details.
       def options
         @@options
       end
 
-      # Sets various options for Haml. See README for details.
+      # Sets various options for Haml. See README.rdoc for details.
       def options=(value)
         @@options = value
       end
@@ -29,3 +26,18 @@ if defined?(ActionView::TemplateHandler)
 else
   require 'haml/template/patch'
 end
+
+if defined?(RAILS_ROOT)
+  # Update init.rb to the current version
+  # if it's out of date.
+  #
+  # We can probably remove this as of v1.9,
+  # because the new init file is sufficiently flexible
+  # to not need updating.
+  rails_init_file = File.join(RAILS_ROOT, 'vendor', 'plugins', 'haml', 'init.rb')
+  haml_init_file = Haml.scope('init.rb')
+  if File.exists?(rails_init_file)
+    require 'fileutils'
+    FileUtils.cp(haml_init_file, rails_init_file) unless FileUtils.cmp(rails_init_file, haml_init_file)
+  end
+end</diff>
      <filename>vendor/plugins/haml/lib/haml/template.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ module ActionView
     def compile_haml(template, file_name, local_assigns)
       render_symbol = assign_method_name(:haml, template, file_name)
       locals = local_assigns.keys
-      
+
       @@template_args[render_symbol] ||= {}
       locals_keys = @@template_args[render_symbol].keys | locals
       @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h }
@@ -42,7 +42,14 @@ module ActionView
           logger.debug &quot;Backtrace: #{e.backtrace.join(&quot;\n&quot;)}&quot;
         end
 
-        raise TemplateError.new(@base_path, file_name || template, @assigns, template, e)
+        base_path = if defined?(extract_base_path_from)
+                      # Rails 2.0.x
+                      extract_base_path_from(file_name) || view_paths.first
+                    else
+                      # Rails &lt;=1.2.6
+                      @base_path
+                    end
+        raise ActionView::TemplateError.new(base_path, file_name || template, @assigns, template, e)
       end
 
       @@compile_time[render_symbol] = Time.now</diff>
      <filename>vendor/plugins/haml/lib/haml/template/patch.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,72 @@
+# :stopdoc:
 # This file makes Haml work with Rails
 # using the &gt; 2.0.1 template handler API.
 
 module Haml
-  class Template
-    def self.line_offset
-      1
-    end
-
-    def initialize(view)
-      @view = view
-    end
+  class Plugin &lt; ActionView::TemplateHandler
+    include ActionView::TemplateHandlers::Compilable if defined?(ActionView::TemplateHandlers::Compilable)
 
     def compile(template)
       options = Haml::Template.options.dup
-      Haml::Engine.new(template, options).send(:precompiled_with_ambles, [])
+
+      # template is a template object in Rails &gt;=2.1.0,
+      # a source string previously
+      if template.respond_to? :source
+        options[:filename] = template.filename
+        source = template.source
+      else
+        source = template
+      end
+
+      Haml::Engine.new(source, options).send(:precompiled_with_ambles, [])
+    end
+
+    def cache_fragment(block, name = {}, options = nil)
+      @view.fragment_for(block, name, options) do
+        eval(&quot;_hamlout.buffer&quot;, block.binding)
+      end
     end
   end
 end
 
-ActionView::Base.register_template_handler(:haml, Haml::Template)
+if defined? ActionView::Template and ActionView::Template.respond_to? :register_template_handler
+  ActionView::Template
+else
+  ActionView::Base
+end.register_template_handler(:haml, Haml::Plugin)
+
+# In Rails 2.0.2, ActionView::TemplateError took arguments
+# that we can't fill in from the Haml::Plugin context.
+# Thus, we've got to monkeypatch ActionView::Base to catch the error.
+if ActionView::TemplateError.instance_method(:initialize).arity == 5
+  class ActionView::Base
+    def compile_template(handler, template, file_name, local_assigns)
+      render_symbol = assign_method_name(handler, template, file_name)
+
+      # Move begin up two lines so it captures compilation exceptions.
+      begin
+        render_source = create_template_source(handler, template, render_symbol, local_assigns.keys)
+        line_offset = @@template_args[render_symbol].size + handler.line_offset
+      
+        file_name = 'compiled-template' if file_name.blank?
+        CompiledTemplates.module_eval(render_source, file_name, -line_offset)
+      rescue Exception =&gt; e # errors from template code
+        if logger
+          logger.debug &quot;ERROR: compiling #{render_symbol} RAISED #{e}&quot;
+          logger.debug &quot;Function body: #{render_source}&quot;
+          logger.debug &quot;Backtrace: #{e.backtrace.join(&quot;\n&quot;)}&quot;
+        end
+
+        # There's no way to tell Haml about the filename,
+        # so we've got to insert it ourselves.
+        e.backtrace[0].gsub!('(haml)', file_name) if e.is_a?(Haml::Error)
+        
+        raise ActionView::TemplateError.new(extract_base_path_from(file_name) || view_paths.first, file_name || template, @assigns, template, e)
+      end
+      
+      @@compile_time[render_symbol] = Time.now
+      # logger.debug &quot;Compiled template #{file_name || template}\n ==&gt; #{render_symbol}&quot; if logger
+    end
+  end
+end
+# :startdoc:</diff>
      <filename>vendor/plugins/haml/lib/haml/template/plugin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -11,7 +11,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # and implements various features that are useful
 # for creating manageable stylesheets.
 #
-# == Features 
+# == Features
 #
 # * Whitespace active
 # * Well-formatted output
@@ -32,13 +32,13 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #
 # To enable it as a Rails plugin,
 # then run
-# 
+#
 #   haml --rails path/to/rails/app
-# 
+#
 # To enable Sass in Merb,
 # add
 #
-#   dependency &quot;haml&quot;
+#   dependency &quot;merb-haml&quot;
 #
 # to config/dependencies.rb.
 #
@@ -128,7 +128,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #
 # By default, either attribute syntax may be used.
 # If you want to force one or the other,
-# see the :attribute_syntax option below.
+# see the &lt;tt&gt;:attribute_syntax&lt;/tt&gt; option below.
 #
 # === Nested Rules
 #
@@ -157,12 +157,12 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #
 #   #main
 #     :width 97%
-#     
+#
 #     p, div
 #       :font-size 2em
 #       a
 #         :font-weight bold
-#         
+#
 #     pre
 #       :font-size 3em
 #
@@ -363,6 +363,39 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #   #main {
 #     content: string(Hello, &quot;Hubert&quot; Bean.) }
 #
+# === Optional Assignment
+#
+# You can assign Sass constants if they aren't already assigned
+# using the ||= assignment operator.
+# This means that if the constant has already been assigned to,
+# it won't be re-assigned,
+# but if it doesn't have a value yet,
+# it will be given one.
+# For example:
+#
+#   !content = &quot;First content&quot;
+#   !content ||= &quot;Second content?&quot;
+#
+#   #main
+#     content = content
+#
+# is compiled to:
+#
+#   #main {
+#     content: First content; }
+#
+# However,
+#
+#   !content ||= &quot;Second content?&quot;
+#
+#   #main
+#     content = content
+#
+# is compiled to:
+#
+#   #main {
+#     content: Second content?; }
+#
 # === Default Concatenation
 #
 # All those plusses and quotes for concatenating strings
@@ -453,6 +486,40 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # might compile to either,
 # depending on whether a file called &quot;foo.sass&quot; existed.
 #
+# === @font-face, @media, etc.
+#
+# Sass behaves as you'd expect for normal CSS @-directives.
+# For example:
+#
+#   @font-face
+#     font-family: &quot;Bitstream Vera Sans&quot;
+#     src: url(http://foo.bar/bvs&quot;)
+#
+# compiles to:
+#
+#   @font-face {
+#     font-family: &quot;Bitstream Vera Sans&quot;;
+#     src: url(http://foo.bar/bvs&quot;); }
+#
+# and
+#
+#   @media print
+#     #sidebar
+#       display: none
+#
+#     #main
+#       background-color: white
+#
+# compiles to:
+#
+#   @media print {
+#     #sidebar {
+#       display: none; }
+#
+#     #main {
+#       background-color: white; }
+#   }
+#
 # == Comments
 #
 # === Silent Comments
@@ -528,6 +595,84 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #     background-image: url(/images/pbj.png);
 #     color: red; }
 #
+# == Mixins
+#
+# Mixins enable you to define groups of CSS attributes and
+# then include them inline in any number of selectors
+# throughout the document.
+#
+# === Defining a Mixin
+#
+# To define a mixin you use a slightly modified form of selector syntax.
+# For example the 'large-text' mixin is defined as follows:
+#
+#   =large-text
+#     :font
+#       :family Arial
+#       :size 20px
+#       :weight bold
+#     :color #ff0000
+#
+# The initial '=' marks this as a mixin rather than a standard selector.
+# The CSS rules that follow won't be included until the mixin is referenced later on.
+# Anything you can put into a standard selector,
+# you can put into a mixin definition. e.g.
+#
+#   =clearfix
+#     display: inline-block
+#     &amp;:after
+#       content: &quot;.&quot;
+#       display: block
+#       height: 0
+#       clear: both
+#       visibility: hidden
+#     * html &amp;
+#       height: 1px
+#
+#
+# === Mixing it in
+#
+# Inlining a defined mixin is simple,
+# just prepend a '+' symbol to the name of a mixin defined earlier in the document.
+# So to inline the 'large-text' defined earlier,
+# we include the statment '+large-text' in our selector definition thus:
+#
+#   .page-title
+#     +large-text
+#     :padding 4px
+#     :margin
+#       :top 10px
+#
+#
+# This will produce the following CSS output:
+#
+#   .page-title {
+#     font-family: Arial;
+#     font-size: 20px;
+#     font-weight: bold;
+#     color: #ff0000;
+#     padding: 4px;
+#     margin-top: 10px;
+#   }
+#
+# Any number of mixins may be defined and there is no limit on
+# the number that can be included in a particular selector.
+#
+# Mixin definitions can also include references to other mixins defined earlier in the file.
+# E.g.
+#
+#   =highlighted-background
+#     background:
+#       color: #fc0
+#   =header-text
+#     font:
+#       size: 20px
+#
+#   =compound
+#     +highlighted-background
+#     +header-text
+#
+#
 # == Output Style
 #
 # Although the default CSS style that Sass outputs is very nice,
@@ -601,7 +746,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #   #main { color: #fff; background-color: #000; }
 #   #main p { width: 10em; }
 #
-#   .huge { font-size: 10em; font-weight: bold; text-decoration: underline; } 
+#   .huge { font-size: 10em; font-weight: bold; text-decoration: underline; }
 #
 # === &lt;tt&gt;:compressed&lt;/tt&gt;
 #
@@ -611,7 +756,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 # It's not meant to be human-readable.
 # For example:
 #
-#   #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline} 
+#   #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}
 #
 # == Sass Options
 #
@@ -634,7 +779,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #                               For example: &lt;tt&gt;color: #0f3&lt;/tt&gt;
 #                               or &lt;tt&gt;width = !main_width&lt;/tt&gt;.
 #                               By default, either syntax is valid.
-#                               
+#
 # [&lt;tt&gt;:never_update&lt;/tt&gt;]      Whether the CSS files should never be updated,
 #                               even if the template file changes.
 #                               Setting this to true may give small performance gains.
@@ -646,7 +791,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #                               as opposed to only when the template has been modified.
 #                               Defaults to false.
 #                               Only has meaning within Ruby on Rails or Merb.
-#                               
+#
 # [&lt;tt&gt;:always_check&lt;/tt&gt;]      Whether a Sass template should be checked for updates every
 #                               time a controller is accessed,
 #                               as opposed to only when the Rails server starts.
@@ -681,7 +826,7 @@ $LOAD_PATH &lt;&lt; dir unless $LOAD_PATH.include?(dir)
 #                               for Sass templates imported with the &quot;@import&quot; directive.
 #                               This defaults to the working directory and, in Rails or Merb,
 #                               whatever &lt;tt&gt;:template_location&lt;/tt&gt; is.
-# 
+#
 module Sass; end
 
 require 'sass/engine'</diff>
      <filename>vendor/plugins/haml/lib/sass.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,13 +8,13 @@ module Sass
 
     # Whitespace characters
     WHITESPACE = [?\ , ?\t, ?\n, ?\r]
-  
+
     # The character used to escape values
     ESCAPE_CHAR = ?\\
 
     # The character used to open and close strings
     STRING_CHAR = ?&quot;
-    
+
     # A mapping of syntactically-significant characters
     # to parsed symbols
     SYMBOLS = {
@@ -31,14 +31,14 @@ module Sass
     }
 
     # The regular expression used to parse constants
-    MATCH = /^#{Regexp.escape(CONSTANT_CHAR.chr)}([^\s#{(SYMBOLS.keys + [ ?= ]).map {|c| Regexp.escape(&quot;#{c.chr}&quot;) }}]+)\s*=\s*(.+)/
-    
+    MATCH = /^#{Regexp.escape(CONSTANT_CHAR.chr)}([^\s#{(SYMBOLS.keys + [ ?= ]).map {|c| Regexp.escape(&quot;#{c.chr}&quot;) }.join}]+)\s*((?:\|\|)?=)\s*(.+)/
+
     # First-order operations
     FIRST_ORDER = [:times, :div, :mod]
-    
+
     # Second-order operations
     SECOND_ORDER = [:plus, :minus]
-  
+
     class &lt;&lt; self
       def parse(value, constants, line)
         begin
@@ -46,28 +46,28 @@ module Sass
         rescue Sass::SyntaxError =&gt; e
           if e.message == &quot;Constant arithmetic error&quot;
             e.instance_eval do
-              @message += &quot;: #{value.dump}&quot;
+              @message += &quot;: #{value.dump}.&quot;
             end
           end
           e.sass_line = line
           raise e
         end
       end
-      
+
       private
-      
+
       def tokenize(value)
         escaped = false
         is_string = false
         beginning_of_token = true
         str = ''
         to_return = []
-        
+
         reset_str = Proc.new do
           to_return &lt;&lt; str unless str.empty?
           ''
         end
-        
+
         value.each_byte do |byte|
           unless escaped
             if byte == ESCAPE_CHAR
@@ -97,7 +97,7 @@ module Sass
                 str = reset_str.call
                 next
               end
-            
+
               symbol = SYMBOLS[byte]
 
               # Adjacent values without an operator should be concatenated
@@ -135,28 +135,28 @@ module Sass
               end
             end
           end
-          
+
           escaped = false
           beginning_of_token = false
           str &lt;&lt; byte.chr
         end
-        
+
         if is_string
-          raise Sass::SyntaxError.new(&quot;Unterminated string: #{value.dump}&quot;)
+          raise Sass::SyntaxError.new(&quot;Unterminated string: #{value.dump}.&quot;)
         end
         str = reset_str.call
         to_return
       end
-      
+
       def parenthesize(value)
         parenthesize_helper(0, value, value.length)[0]
       end
-      
+
       def parenthesize_helper(i, value, value_len, return_after_expr = false)
         to_return = []
         beginning = i
         token = value[i]
-        
+
         while i &lt; value_len &amp;&amp; token != :close
           if token == :open
             to_return.push(*value[beginning...i])
@@ -194,13 +194,13 @@ module Sass
           else
             i += 1
           end
-          
+
           token = value[i]
         end
         to_return.push(*value[beginning...i])
         return to_return, i + 1
       end
-      
+
       #--
       # TODO: Don't pass around original value;
       #       have Constant.parse automatically add it to exception.
@@ -234,10 +234,10 @@ module Sass
           end
         end
       end
-      
+
       def get_constant(value, constants)
         to_return = constants[value]
-        raise SyntaxError.new(&quot;Undefined constant: \&quot;!#{value}\&quot;&quot;) unless to_return
+        raise SyntaxError.new(&quot;Undefined constant: \&quot;!#{value}\&quot;.&quot;) unless to_return
         to_return
       end
     end</diff>
      <filename>vendor/plugins/haml/lib/sass/constant.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,9 +21,9 @@ module Sass::Constant # :nodoc:
       'teal'    =&gt; 0x008080,
       'aqua'    =&gt; 0x00ffff
     }
-  
+
     REGEXP = /\##{&quot;([0-9a-fA-F]{1,2})&quot; * 3}/
-  
+
     def parse(value)
       if (value =~ REGEXP)
         @value = value.scan(REGEXP)[0].map { |num| num.ljust(2, num).to_i(16) }
@@ -32,7 +32,7 @@ module Sass::Constant # :nodoc:
         @value = (0..2).map{ |n| color &gt;&gt; (n &lt;&lt; 3) &amp; 0xff }.reverse
       end
     end
-    
+
     def plus(other)
       if other.is_a? Sass::Constant::String
         Sass::Constant::String.from_value(self.to_s + other.to_s)
@@ -40,7 +40,7 @@ module Sass::Constant # :nodoc:
         piecewise(other, :+)
       end
     end
-    
+
     def minus(other)
       if other.is_a? Sass::Constant::String
         raise NoMethodError.new(nil, :minus)
@@ -48,7 +48,7 @@ module Sass::Constant # :nodoc:
         piecewise(other, :-)
       end
     end
-    
+
     def times(other)
       if other.is_a? Sass::Constant::String
         raise NoMethodError.new(nil, :times)
@@ -56,7 +56,7 @@ module Sass::Constant # :nodoc:
         piecewise(other, :*)
       end
     end
-    
+
     def div(other)
       if other.is_a? Sass::Constant::String
         raise NoMethodError.new(nil, :div)
@@ -64,7 +64,7 @@ module Sass::Constant # :nodoc:
         piecewise(other, :/)
       end
     end
-    
+
     def mod(other)
       if other.is_a? Sass::Constant::String
         raise NoMethodError.new(nil, :mod)
@@ -72,24 +72,24 @@ module Sass::Constant # :nodoc:
         piecewise(other, :%)
       end
     end
-    
+
     def to_s
       red, green, blue = @value.map { |num| num.to_s(16).rjust(2, '0') }
       &quot;##{red}#{green}#{blue}&quot;
     end
-    
+
     protected
-    
+
     def self.filter_value(value)
       value.map { |num| num.to_i }
     end
-    
+
     private
-    
+
     def piecewise(other, operation)
       other_num = other.is_a? Number
       other_val = other.value
-    
+
       rgb = []
       for i in (0...3)
         res = @value[i].send(operation, other_num ? other_val : other_val[i])</diff>
      <filename>vendor/plugins/haml/lib/sass/constant/color.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,7 @@ class Sass::Constant::Literal # :nodoc:
 
   # The regular expression matching colors.
   COLOR = /^\# (?: [\da-f]{3} | [\da-f]{6} ) | #{html_color_matcher}/ix
-  
+
   def self.parse(value)
     case value
     when NUMBER
@@ -24,11 +24,11 @@ class Sass::Constant::Literal # :nodoc:
       Sass::Constant::String.new(value)
     end
   end
-  
+
   def initialize(value = nil)
     self.parse(value) if value
   end
-  
+
   def perform
     self
   end
@@ -36,15 +36,15 @@ class Sass::Constant::Literal # :nodoc:
   def concat(other)
     Sass::Constant::String.from_value(&quot;#{self.to_s} #{other.to_s}&quot;)
   end
-  
+
   attr_reader :value
-  
+
   protected
-  
+
   def self.filter_value(value)
     value
   end
-  
+
   def self.from_value(value)
     instance = self.new
     instance.instance_variable_set('@value', self.filter_value(value))</diff>
      <filename>vendor/plugins/haml/lib/sass/constant/literal.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,7 +10,7 @@ module Sass::Constant  # :nodoc:
       @value = first.empty? ? second.to_i : &quot;#{first}#{second}&quot;.to_f
       @unit = unit unless unit.empty?
     end
-    
+
     def plus(other)
       if other.is_a? Number
         operate(other, :+)
@@ -20,7 +20,7 @@ module Sass::Constant  # :nodoc:
         Sass::Constant::String.from_value(self.to_s + other.to_s)
       end
     end
-    
+
     def minus(other)
       if other.is_a? Number
         operate(other, :-)
@@ -28,7 +28,7 @@ module Sass::Constant  # :nodoc:
         raise NoMethodError.new(nil, :minus)
       end
     end
-    
+
     def times(other)
       if other.is_a? Number
         operate(other, :*)
@@ -38,7 +38,7 @@ module Sass::Constant  # :nodoc:
         raise NoMethodError.new(nil, :times)
       end
     end
-    
+
     def div(other)
       if other.is_a? Number
         operate(other, :/)
@@ -46,7 +46,7 @@ module Sass::Constant  # :nodoc:
         raise NoMethodError.new(nil, :div)
       end
     end
-    
+
     def mod(other)
       if other.is_a? Number
         operate(other, :%)
@@ -54,13 +54,13 @@ module Sass::Constant  # :nodoc:
         raise NoMethodError.new(nil, :mod)
       end
     end
-    
+
     def to_s
       value = @value
       value = value.to_i if value % 1 == 0.0
       &quot;#{value}#{@unit}&quot;
     end
-    
+
     protected
 
     def self.from_value(value, unit=nil)
@@ -68,7 +68,7 @@ module Sass::Constant  # :nodoc:
       instance.instance_variable_set('@unit', unit)
       instance
     end
-    
+
     def operate(other, operation)
       unit = nil
       if other.unit.nil?
@@ -78,7 +78,7 @@ module Sass::Constant  # :nodoc:
       elsif other.unit == self.unit
         unit = self.unit
       else
-        raise Sass::SyntaxError.new(&quot;Incompatible units: #{self.unit} and #{other.unit}&quot;)
+        raise Sass::SyntaxError.new(&quot;Incompatible units: #{self.unit} and #{other.unit}.&quot;)
       end
 
       Number.from_value(self.value.send(operation, other.value), unit)</diff>
      <filename>vendor/plugins/haml/lib/sass/constant/number.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,13 +9,13 @@ module Sass::Constant # :nodoc:
       @operand2 = operand2
       @operator = operator
     end
-    
+
     def to_s
       self.perform.to_s
     end
-    
+
     protected
-    
+
     def perform
       literal1 = @operand1.perform
       literal2 = @operand2.perform
@@ -23,7 +23,7 @@ module Sass::Constant # :nodoc:
         literal1.send(@operator, literal2)
       rescue NoMethodError =&gt; e
         raise e unless e.name.to_s == @operator.to_s
-        raise Sass::SyntaxError.new(&quot;Undefined operation: \&quot;#{literal1} #{@operator} #{literal2}\&quot;&quot;)
+        raise Sass::SyntaxError.new(&quot;Undefined operation: \&quot;#{literal1} #{@operator} #{literal2}\&quot;.&quot;)
       end
     end
   end</diff>
      <filename>vendor/plugins/haml/lib/sass/constant/operation.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,11 +2,11 @@ require 'sass/constant/literal'
 
 module Sass::Constant # :nodoc:
   class String &lt; Literal # :nodoc:
-    
+
     def parse(value)
       @value = value
     end
-    
+
     def plus(other)
       Sass::Constant::String.from_value(self.to_s + other.to_s)
     end
@@ -14,7 +14,7 @@ module Sass::Constant # :nodoc:
     def funcall(other)
       Sass::Constant::String.from_value(&quot;#{self.to_s}(#{other.to_s})&quot;)
     end
-    
+
     def to_s
       @value
     end</diff>
      <filename>vendor/plugins/haml/lib/sass/constant/string.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,11 +6,11 @@ module Sass
   # :stopdoc:
   module Tree
     class Node
-      def to_sass
+      def to_sass(opts = {})
         result = ''
 
         children.each do |child|
-          result &lt;&lt; &quot;#{child.to_sass(0)}\n&quot;
+          result &lt;&lt; &quot;#{child.to_sass(0, opts)}\n&quot;
         end
 
         result
@@ -24,11 +24,11 @@ module Sass
     end
 
     class RuleNode
-      def to_sass(tabs)
-        str = &quot;#{'  ' * tabs}#{rule}\n&quot;
+      def to_sass(tabs, opts = {})
+        str = &quot;\n#{'  ' * tabs}#{rule}#{children.any? { |c| c.is_a? AttrNode } ? &quot;\n&quot; : ''}&quot;
 
         children.each do |child|
-          str &lt;&lt; &quot;#{child.to_sass(tabs + 1)}&quot;
+          str &lt;&lt; &quot;#{child.to_sass(tabs + 1, opts)}&quot;
         end
 
         str
@@ -36,8 +36,8 @@ module Sass
     end
 
     class AttrNode
-      def to_sass(tabs)
-        &quot;#{'  ' * tabs}:#{name} #{value}\n&quot;
+      def to_sass(tabs, opts = {})
+        &quot;#{'  ' * tabs}#{opts[:alternate] ? '' : ':'}#{name}#{opts[:alternate] ? ':' : ''} #{value}\n&quot;
       end
     end
   end
@@ -90,11 +90,12 @@ module Sass
 
     # Creates a new instance of Sass::CSS that will compile the given document
     # to a Sass string when +render+ is called.
-    def initialize(template)
+    def initialize(template, options = {})
       if template.is_a? IO
         template = template.read
       end
 
+      @options = options
       @template = StringScanner.new(template)
     end
 
@@ -102,10 +103,10 @@ module Sass
     # containing the CSS template.
     def render
       begin
-        build_tree.to_sass
+        build_tree.to_sass(@options).lstrip
       rescue Exception =&gt; err
         line = @template.string[0...@template.pos].split(&quot;\n&quot;).size
-        
+
         err.backtrace.unshift &quot;(css):#{line}&quot;
         raise err
       end
@@ -116,12 +117,13 @@ module Sass
     def build_tree
       root = Tree::Node.new(nil)
       whitespace
-      directives    root
-      rules         root
-      expand_commas root
-      nest_rules    root
-      flatten_rules root
-      fold_commas   root
+      directives         root
+      rules              root
+      expand_commas      root
+      parent_ref_rules   root
+      remove_parent_refs root
+      flatten_rules      root
+      fold_commas        root
       root
     end
 
@@ -164,12 +166,12 @@ module Sass
         whitespace
 
         assert_match /:/
-        
+
         value = ''
         while @template.scan(/[^;\s\}]+/)
           value &lt;&lt; @template[0] &lt;&lt; whitespace
         end
-        
+
         assert_match /(;|(?=\}))/
         rule &lt;&lt; Tree::AttrNode.new(name, value, nil)
       end
@@ -191,7 +193,10 @@ module Sass
 
     def assert_match(re)
       if !@template.scan(re)
-        raise Exception.new(&quot;Invalid CSS!&quot;)
+        line = @template.string[0..@template.pos].count &quot;\n&quot;
+        # Display basic regexps as plain old strings
+        expected = re.source == Regexp.escape(re.source) ? &quot;\&quot;#{re.source}\&quot;&quot; : re.inspect
+        raise Exception.new(&quot;Invalid CSS on line #{line}: expected #{expected}&quot;)
       end
       whitespace
     end
@@ -224,7 +229,22 @@ module Sass
       root.children.flatten!
     end
 
-    # Nest rules so that
+    # Make rules use parent refs so that
+    #
+    #   foo
+    #     color: green
+    #   foo.bar
+    #     color: blue
+    #
+    # becomes
+    #
+    #   foo
+    #     color: green
+    #     &amp;.bar
+    #       color: blue
+    #
+    # This has the side effect of nesting rules,
+    # so that
     #
     #   foo
     #     color: green
@@ -237,29 +257,50 @@ module Sass
     #
     #   foo
     #     color: green
-    #     bar
+    #     &amp; bar
     #       color: red
-    #     baz
+    #     &amp; baz
     #       color: blue
-    # 
-    def nest_rules(root)
+    #
+    def parent_ref_rules(root)
       rules = OrderedHash.new
       root.children.select { |c| Tree::RuleNode === c }.each do |child|
         root.children.delete child
-        first, rest = child.rule.split(' ', 2)
+        first, rest = child.rule.scan(/^(&amp;?(?: .|[^ ])[^.#: \[]*)([.#: \[].*)?$/).first
         rules[first] ||= Tree::RuleNode.new(first, nil)
         if rest
-          child.rule = rest
+          child.rule = &quot;&amp;&quot; + rest
           rules[first] &lt;&lt; child
         else
           rules[first].children += child.children
         end
       end
 
-      rules.values.each { |v| nest_rules(v) }
+      rules.values.each { |v| parent_ref_rules(v) }
       root.children += rules.values
     end
 
+    # Remove useless parent refs so that
+    #
+    #   foo
+    #     &amp; bar
+    #       color: blue
+    #
+    # becomes
+    #
+    #   foo
+    #     bar
+    #       color: blue
+    #
+    def remove_parent_refs(root)
+      root.children.each do |child|
+        if child.is_a?(Tree::RuleNode)
+          child.rule.gsub! /^&amp; /, ''
+          remove_parent_refs child
+        end
+      end
+    end
+
     # Flatten rules so that
     #
     #   foo
@@ -271,7 +312,18 @@ module Sass
     #
     #   foo bar baz
     #     color: red
-    # 
+    #
+    # and
+    #
+    #   foo
+    #     &amp;.bar
+    #       color: blue
+    #
+    # becomes
+    #
+    #   foo.bar
+    #     color: blue
+    #
     def flatten_rules(root)
       root.children.each { |child| flatten_rule(child) if child.is_a?(Tree::RuleNode) }
     end
@@ -279,7 +331,13 @@ module Sass
     def flatten_rule(rule)
       while rule.children.size == 1 &amp;&amp; rule.children.first.is_a?(Tree::RuleNode)
         child = rule.children.first
-        rule.rule = &quot;#{rule.rule} #{child.rule}&quot;
+
+        if child.rule[0] == ?&amp;
+          rule.rule = child.rule.gsub /^&amp;/, rule.rule
+        else
+          rule.rule = &quot;#{rule.rule} #{child.rule}&quot;
+        end
+
         rule.children = child.children
       end
 </diff>
      <filename>vendor/plugins/haml/lib/sass/css.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,6 @@ require 'sass/tree/attr_node'
 require 'sass/tree/directive_node'
 require 'sass/constant'
 require 'sass/error'
-require 'haml/util'
 
 module Sass
   # This is the class where all the parsing and processing of the Sass
@@ -39,10 +38,16 @@ module Sass
 
     # The character used to denote a compiler directive.
     DIRECTIVE_CHAR = ?@
-    
+
     # Designates a non-parsed rule.
     ESCAPE_CHAR    = ?\\
 
+    # Designates block as mixin definition rather than CSS rules to output
+    MIXIN_DEFINITION_CHAR = ?=
+
+    # Includes named mixin declared using MIXIN_DEFINITION_CHAR
+    MIXIN_INCLUDE_CHAR    = ?+
+
     # The regex that matches and extracts data from
     # attributes of the form &lt;tt&gt;:name attr&lt;/tt&gt;.
     ATTRIBUTE = /^:([^\s=:]+)\s*(=?)(?:\s+|$)(.*)/
@@ -56,14 +61,14 @@ module Sass
 
     # Creates a new instace of Sass::Engine that will compile the given
     # template string when &lt;tt&gt;render&lt;/tt&gt; is called.
-    # See README for available options.
+    # See README.rdoc for available options.
     #
     #--
     #
     # TODO: Add current options to REFRENCE. Remember :filename!
     #
     # When adding options, remember to add information about them
-    # to README!
+    # to README.rdoc!
     #++
     #
     def initialize(template, options={})
@@ -71,9 +76,10 @@ module Sass
         :style =&gt; :nested,
         :load_paths =&gt; ['.']
       }.merge! options
-      @template = template.split(/\n\r|\n/)
+      @template = template.split(/\n?\r|\r?\n/)
       @lines = []
       @constants = {&quot;important&quot; =&gt; &quot;!important&quot;}
+      @mixins = {}
     end
 
     # Processes the template and returns the result as a string.
@@ -96,6 +102,10 @@ module Sass
       @constants
     end
 
+    def mixins
+      @mixins
+    end
+
     def render_to_tree
       split_lines
 
@@ -113,7 +123,7 @@ module Sass
           end
         end
       end
-      @line = nil
+      @lines.clear
 
       root
     end
@@ -136,7 +146,7 @@ module Sass
 
         if tabs # if line isn't blank
           if tabs - old_tabs &gt; 1
-            raise SyntaxError.new(&quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;, @line)
+            raise SyntaxError.new(&quot;#{tabs * 2} spaces were used for indentation. Sass must be indented using two spaces.&quot;, @line)
           end
           @lines &lt;&lt; [line.strip, tabs]
 
@@ -151,18 +161,20 @@ module Sass
 
     # Counts the tabulation of a line.
     def count_tabs(line)
-      spaces = line.index(/[^ ]/)
-      if spaces
-        if spaces % 2 == 1 || line[spaces] == ?\t
-          # Make sure a line with just tabs isn't an error
-          return nil if line.strip.empty?
-
-          raise SyntaxError.new(&quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;, @line)
-        end
-        spaces / 2
-      else
-        nil
+      return nil if line.strip.empty?
+      return nil unless spaces = line.index(/[^ ]/)
+
+      if spaces % 2 == 1
+          raise SyntaxError.new(&lt;&lt;END.strip, @line)
+#{spaces} space#{spaces == 1 ? ' was' : 's were'} used for indentation. Sass must be indented using two spaces.
+END
+      elsif line[spaces] == ?\t
+        raise SyntaxError.new(&lt;&lt;END.strip, @line)
+A tab character was used for indentation. Sass must be indented using two spaces.
+Are you sure you have soft tabs enabled in your editor?
+END
       end
+      spaces / 2
     end
 
     def build_tree(index)
@@ -177,15 +189,23 @@ module Sass
       unless node.is_a? Tree::Node
         if has_children
           if node == :constant
-            raise SyntaxError.new(&quot;Illegal nesting: Nothing may be nested beneath constants.&quot;, @line)
+            raise SyntaxError.new(&quot;Illegal nesting: Nothing may be nested beneath constants.&quot;, @line + 1)
           elsif node.is_a? Array
-            raise SyntaxError.new(&quot;Illegal nesting: Nothing may be nested beneath import directives.&quot;, @line)
+            # arrays can either be full of import statements
+            # or attributes from mixin includes
+            # in either case they shouldn't have children.
+            # Need to peek into the array in order to give meaningful errors
+            directive_type = (node.first.is_a?(Tree::DirectiveNode) ? &quot;import&quot; : &quot;mixin&quot;)
+            raise SyntaxError.new(&quot;Illegal nesting: Nothing may be nested beneath #{directive_type} directives.&quot;, @line + 1)
           end
         end
 
+        index = @line if node == :mixin
         return node, index
       end
 
+      node.line = @line
+
       if node.is_a? Tree::CommentNode
         while has_children
           line, index = raw_next_line(index)
@@ -193,26 +213,52 @@ module Sass
 
           has_children = has_children?(index, tabs)
         end
-      else
-        while has_children
-          child, index = build_tree(index)
 
-          if child == :constant
-            raise SyntaxError.new(&quot;Constants may only be declared at the root of a document.&quot;, @line)
-          elsif child.is_a? Array
-            raise SyntaxError.new(&quot;Import directives may only be used at the root of a document.&quot;, @line)
-          elsif child.is_a? Tree::Node
-            child.line = @line
-            node &lt;&lt; child
+        return node, index
+      end
+
+      # Resolve multiline rules
+      if node.is_a?(Tree::RuleNode)
+        if node.continued?
+          child, index = build_tree(index) if @lines[old_index = index]
+          if @lines[old_index].nil? || has_children?(old_index, tabs) || !child.is_a?(Tree::RuleNode)
+            raise SyntaxError.new(&quot;Rules can't end in commas.&quot;, @line)
           end
 
-          has_children = has_children?(index, tabs)
+          node.add_rules child
         end
+        node.children = child.children if child
+      end
+
+      while has_children
+        child, index = build_tree(index)
+
+        validate_and_append_child(node, child)
+
+        has_children = has_children?(index, tabs)
       end
 
       return node, index
     end
 
+    def validate_and_append_child(parent, child)
+      case child
+      when :constant
+        raise SyntaxError.new(&quot;Constants may only be declared at the root of a document.&quot;, @line)
+      when :mixin
+        raise SyntaxError.new(&quot;Mixins may only be defined at the root of a document.&quot;, @line)
+      when Array
+        child.each do |c|
+          if c.is_a?(Tree::DirectiveNode)
+            raise SyntaxError.new(&quot;Import directives may only be used at the root of a document.&quot;, @line)
+          end
+          parent &lt;&lt; c
+        end
+      when Tree::Node
+        parent &lt;&lt; child
+      end
+    end
+
     def has_children?(index, tabs)
       next_line = ['//', 0]
       while !next_line.nil? &amp;&amp; next_line[0] == '//' &amp;&amp; next_line[1] = 0
@@ -238,6 +284,10 @@ module Sass
         parse_directive(line)
       when ESCAPE_CHAR
         Tree::RuleNode.new(line[1..-1], @options[:style])
+      when MIXIN_DEFINITION_CHAR
+        parse_mixin_definition(line)
+      when MIXIN_INCLUDE_CHAR
+        parse_mixin_include(line)
       else
         if line =~ ATTRIBUTE_ALTERNATE_MATCHER
           parse_attribute(line, ATTRIBUTE_ALTERNATE)
@@ -259,7 +309,7 @@ module Sass
       name, eq, value = line.scan(attribute_regx)[0]
 
       if name.nil? || value.nil?
-        raise SyntaxError.new(&quot;Invalid attribute: \&quot;#{line}\&quot;&quot;, @line)
+        raise SyntaxError.new(&quot;Invalid attribute: \&quot;#{line}\&quot;.&quot;, @line)
       end
 
       if eq.strip[0] == SCRIPT_CHAR
@@ -270,11 +320,18 @@ module Sass
     end
 
     def parse_constant(line)
-      name, value = line.scan(Sass::Constant::MATCH)[0]
+      name, op, value = line.scan(Sass::Constant::MATCH)[0]
       unless name &amp;&amp; value
-        raise SyntaxError.new(&quot;Invalid constant: \&quot;#{line}\&quot;&quot;, @line)
+        raise SyntaxError.new(&quot;Invalid constant: \&quot;#{line}\&quot;.&quot;, @line)
+      end
+
+      constant = Sass::Constant.parse(value, @constants, @line)
+      if op == '||='
+        @constants[name] ||= constant
+      else
+        @constants[name] = constant
       end
-      @constants[name] = Sass::Constant.parse(value, @constants, @line)
+
       :constant
     end
 
@@ -291,14 +348,36 @@ module Sass
     def parse_directive(line)
       directive, value = line[1..-1].split(/\s+/, 2)
 
-      case directive
-      when &quot;import&quot;
+      # If value begins with url( or &quot;,
+      # it's a CSS @import rule and we don't want to touch it.
+      if directive == &quot;import&quot; &amp;&amp; value !~ /^(url\(|&quot;)/
         import(value)
       else
         Tree::DirectiveNode.new(line, @options[:style])
       end
     end
 
+    def parse_mixin_definition(line)
+      mixin_name = line[1..-1]
+      @mixins[mixin_name] =  []
+      index = @line
+      line, tabs = @lines[index]
+      while !line.nil? &amp;&amp; tabs &gt; 0
+        child, index = build_tree(index)
+        validate_and_append_child(@mixins[mixin_name], child)
+        line, tabs = @lines[index]
+      end
+      :mixin
+    end
+
+    def parse_mixin_include(line)
+      mixin_name = line[1..-1]
+      unless @mixins.has_key?(mixin_name)
+        raise SyntaxError.new(&quot;Undefined mixin '#{mixin_name}'.&quot;, @line)
+      end
+      @mixins[mixin_name]
+    end
+
     def import(files)
       nodes = []
 
@@ -312,7 +391,7 @@ module Sass
         end
 
         if filename =~ /\.css$/
-          nodes &lt;&lt; Tree::ValueNode.new(&quot;@import url(#{filename});&quot;, @options[:style])
+          nodes &lt;&lt; Tree::DirectiveNode.new(&quot;@import url(#{filename})&quot;, @options[:style])
         else
           File.open(filename) do |file|
             new_options = @options.dup
@@ -321,6 +400,7 @@ module Sass
           end
 
           engine.constants.merge! @constants
+          engine.mixins.merge! @mixins
 
           begin
             root = engine.render_to_tree
@@ -333,6 +413,7 @@ module Sass
             nodes &lt;&lt; child
           end
           @constants = engine.constants
+          @mixins = engine.mixins
         end
       end
 
@@ -354,7 +435,7 @@ module Sass
 
       if new_filename.nil?
         if was_sass
-          raise Exception.new(&quot;File to import not found or unreadable: #{original_filename}&quot;)
+          raise Exception.new(&quot;File to import not found or unreadable: #{original_filename}.&quot;)
         else
           return filename + '.css'
         end</diff>
      <filename>vendor/plugins/haml/lib/sass/engine.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ module Sass
   # and the Sass file that was being parsed (if applicable).
   # It also provides a handy way to rescue only exceptions raised
   # because of a faulty template.
-  class SyntaxError &lt; StandardError
+  class SyntaxError &lt; Exception
     # The line of the Sass template on which the exception was thrown.
     attr_accessor :sass_line
 </diff>
      <filename>vendor/plugins/haml/lib/sass/error.rb</filename>
    </modified>
    <modified>
      <diff>@@ -13,8 +13,15 @@ module Sass
         :always_check       =&gt; true,
         :full_exception     =&gt; true
       }
+      @@checked_for_updates = false
 
-      # Gets various options for Sass. See README for details.
+      # Whether or not Sass has *ever* checked if the stylesheets need updates
+      # (in this Ruby instance).
+      def checked_for_updates
+        @@checked_for_updates
+      end
+
+      # Gets various options for Sass. See README.rdoc for details.
       #--
       # TODO: *DOCUMENT OPTIONS*
       #++
@@ -35,6 +42,7 @@ module Sass
       def update_stylesheets
         return if options[:never_update]
 
+        @@checked_for_updates = true
         Dir.glob(File.join(options[:template_location], &quot;**&quot;, &quot;*.sass&quot;)).entries.each do |file|
 
           # Get the relative path to the file with no extension
@@ -96,7 +104,18 @@ module Sass
               end
             end
           end
-          &quot;/*\n#{e_string}\n\nBacktrace:\n#{e.backtrace.join(&quot;\n&quot;)}\n*/&quot;
+          &lt;&lt;END
+/*
+#{e_string}
+
+Backtrace:\n#{e.backtrace.join(&quot;\n&quot;)}
+*/
+body:before {
+  white-space: pre;
+  font-family: monospace;
+  content: &quot;#{e_string.gsub('&quot;', '\&quot;').gsub(&quot;\n&quot;, '\\A ')}&quot;; }
+END
+          # Fix an emacs syntax-highlighting hiccup: '
         else
           &quot;/* Internal stylesheet error */&quot;
         end
@@ -111,7 +130,7 @@ module Sass
       end
 
       def forbid_update?(name)
-        name[0] == ?_
+        name.sub(/^.*\//, '')[0] == ?_
       end
 
       def stylesheet_needs_update?(name)</diff>
      <filename>vendor/plugins/haml/lib/sass/plugin.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,56 @@
 unless defined?(Sass::MERB_LOADED)
   Sass::MERB_LOADED = true
 
-  Sass::Plugin.options.merge!(:template_location  =&gt; MERB_ROOT + '/public/stylesheets/sass',
-                              :css_location       =&gt; MERB_ROOT + '/public/stylesheets',
-                              :always_check       =&gt; MERB_ENV != &quot;production&quot;,
-                              :full_exception     =&gt; MERB_ENV != &quot;production&quot;)
+  version = Merb::VERSION.split('.').map { |n| n.to_i }
+  if version[0] &lt;= 0 &amp;&amp; version[1] &lt; 5
+    root = MERB_ROOT
+    env  = MERB_ENV
+  else
+    root = Merb.root
+    env  = Merb.environment
+  end
+
+  Sass::Plugin.options.merge!(:template_location  =&gt; root + '/public/stylesheets/sass',
+                              :css_location       =&gt; root + '/public/stylesheets',
+                              :always_check       =&gt; env != &quot;production&quot;,
+                              :full_exception     =&gt; env != &quot;production&quot;)
   config = Merb::Plugins.config[:sass] || Merb::Plugins.config[&quot;sass&quot;] || {}
-  config.symbolize_keys!
+
+  if defined? config.symbolize_keys!
+    config.symbolize_keys!
+  end
+
   Sass::Plugin.options.merge!(config)
-  
-  class MerbHandler # :nodoc:
-    def process_with_sass(request, response)
-      Sass::Plugin.update_stylesheets if Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
-      process_without_sass(request, response)
+
+  if version[0] &gt; 0 || version[1] &gt;= 9
+
+    class Merb::Rack::Application # :nodoc:
+      def call_with_sass(env)
+        if !Sass::Plugin.checked_for_updates ||
+            Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
+          Sass::Plugin.update_stylesheets
+        end
+
+        call_without_sass(env)
+      end
+      alias_method :call_without_sass, :call
+      alias_method :call, :call_with_sass
+    end
+
+  else
+
+    class MerbHandler # :nodoc:
+      def process_with_sass(request, response)
+        if !Sass::Plugin.checked_for_updates ||
+            Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
+          Sass::Plugin.update_stylesheets
+        end
+
+        process_without_sass(request, response)
+      end
+      alias_method :process_without_sass, :process
+      alias_method :process, :process_with_sass
     end
-    alias_method :process_without_sass, :process
-    alias_method :process, :process_with_sass
+
   end
 end</diff>
      <filename>vendor/plugins/haml/lib/sass/plugin/merb.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,14 +5,20 @@ unless defined?(Sass::RAILS_LOADED)
                               :css_location       =&gt; RAILS_ROOT + '/public/stylesheets',
                               :always_check       =&gt; RAILS_ENV != &quot;production&quot;,
                               :full_exception     =&gt; RAILS_ENV != &quot;production&quot;)
-  
-  module ActionController # :nodoc:
-    class Base # :nodoc:
+
+  # :stopdoc:
+  module ActionController
+    class Base
       alias_method :sass_old_process, :process
       def process(*args)
-        Sass::Plugin.update_stylesheets if Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
+        if !Sass::Plugin.checked_for_updates ||
+            Sass::Plugin.options[:always_update] || Sass::Plugin.options[:always_check]
+          Sass::Plugin.update_stylesheets
+        end
+
         sass_old_process(*args)
       end
     end
   end
+  # :startdoc:
 end</diff>
      <filename>vendor/plugins/haml/lib/sass/plugin/rails.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,26 +3,26 @@ require 'sass/tree/node'
 module Sass::Tree
   class AttrNode &lt; ValueNode
     attr_accessor :name
-    
+
     def initialize(name, value, style)
       @name = name
       super(value, style)
     end
-    
+
     def to_s(tabs, parent_name = nil)
       if value[-1] == ?;
-        raise Sass::SyntaxError.new(&quot;Invalid attribute: #{declaration.dump} (This isn't CSS!)&quot;, @line)
+        raise Sass::SyntaxError.new(&quot;Invalid attribute: #{declaration.dump} (This isn't CSS!).&quot;, @line)
       end
       real_name = name
       real_name = &quot;#{parent_name}-#{real_name}&quot; if parent_name
 
       if value.empty? &amp;&amp; children.empty?
-        raise Sass::SyntaxError.new(&quot;Invalid attribute: #{declaration.dump}&quot;, @line)
+        raise Sass::SyntaxError.new(&quot;Invalid attribute: #{declaration.dump}.&quot;, @line)
       end
 
       join_string = case @style
-                    when :compact: ' '
-                    when :compressed: ''
+                    when :compact; ' '
+                    when :compressed; ''
                     else &quot;\n&quot;
                     end
       spaces = '  ' * (tabs - 1)
@@ -34,7 +34,7 @@ module Sass::Tree
       children.each do |kid|
         to_return &lt;&lt; &quot;#{kid.to_s(tabs, real_name)}&quot; &lt;&lt; join_string
       end
-            
+
       (@style == :compressed &amp;&amp; parent_name) ? to_return : to_return[0...-1]
     end
 </diff>
      <filename>vendor/plugins/haml/lib/sass/tree/attr_node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,11 +15,6 @@ module Sass::Tree
         was_attr = false
         first = true
         children.each do |child|
-          if child.is_a?(RuleNode) &amp;&amp; child.continued?
-            check_multiline_rule(child)
-            continued_rule = true
-          end
-
           if @style == :compact
             if child.is_a?(AttrNode)
               result &lt;&lt; &quot;#{child.to_s(first || was_attr ? 1 : tabs + 1)} &quot;
@@ -32,12 +27,12 @@ module Sass::Tree
               result &lt;&lt; rendered
             end
             was_attr = child.is_a?(AttrNode)
-            first = continued_rule
+            first = false
           elsif @style == :compressed
             result &lt;&lt; (was_attr ? &quot;;#{child.to_s(1)}&quot; : child.to_s(1))
             was_attr = child.is_a?(AttrNode)
           else
-            result &lt;&lt; child.to_s(tabs + 1) + (continued_rule ? '' : &quot;\n&quot;)
+            result &lt;&lt; child.to_s(tabs + 1) + &quot;\n&quot;
           end
         end
         result.rstrip + if @style == :compressed</diff>
      <filename>vendor/plugins/haml/lib/sass/tree/directive_node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,15 +16,12 @@ module Sass
         end
         @children &lt;&lt; child
       end
-      
+
       def to_s
         result = String.new
         children.each do |child|
           if child.is_a? AttrNode
             raise SyntaxError.new('Attributes aren\'t allowed at the root of a document.', child.line)
-          elsif child.is_a?(RuleNode) &amp;&amp; child.continued?
-            check_multiline_rule(child)
-            result &lt;&lt; child.to_s(1)
           else
             result &lt;&lt; &quot;#{child.to_s(1)}&quot; + (@style == :compressed ? '' : &quot;\n&quot;)
           end
@@ -32,14 +29,6 @@ module Sass
         @style == :compressed ? result+&quot;\n&quot; : result[0...-1]
       end
 
-      protected
-
-      def check_multiline_rule(rule)
-        unless rule.children.empty?
-          raise SyntaxError.new('Rules can\'t end in commas.', rule.line)
-        end
-      end
-
       private
 
       # This method should be overridden by subclasses to return an error message</diff>
      <filename>vendor/plugins/haml/lib/sass/tree/node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,33 +9,50 @@ module Sass::Tree
     alias_method :rule, :value
     alias_method :rule=, :value=
 
+    def rules
+      Array(rule)
+    end
+
+    def add_rules(node)
+      self.rule = rules
+      self.rule += node.rules
+    end
+
     def continued?
       rule[-1] == ?,
     end
-    
+
     def to_s(tabs, super_rules = nil)
       attributes = []
       sub_rules = []
 
-      # Save this because the comma's removed by the super_rule additions
-      was_continued = continued?
-
+      rule_split = /\s*,\s*/
+      rule_separator = @style == :compressed ? ',' : ', '
+      line_separator = [:nested, :expanded].include?(@style) ? &quot;,\n&quot; : rule_separator
+      rule_indent = '  ' * (tabs - 1)
       total_rule = if super_rules
-        super_rules.split(/,\s*/).collect! do |s|
-          self.rule.split(/,\s*/).collect do |r|
-            if r.include?(PARENT)
-              r.gsub(PARENT, s)
-            else
-              &quot;#{s} #{r}&quot;
-            end
-          end.join(&quot;, &quot;)
-        end.join(&quot;, &quot;) + (was_continued ? ',' : '')
-      elsif self.rule.include?(PARENT)
-        raise Sass::SyntaxError.new(&quot;Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'&quot;, line)
+        super_rules.split(&quot;,\n&quot;).map do |super_line|
+          super_line.strip.split(rule_split).map do |super_rule|
+            self.rules.map do |line|
+              rule_indent + line.gsub(/,$/, '').split(rule_split).map do |rule|
+                if rule.include?(PARENT)
+                  rule.gsub(PARENT, super_rule)
+                else
+                  &quot;#{super_rule} #{rule}&quot;
+                end
+              end.join(rule_separator)
+            end.join(line_separator)
+          end.join(rule_separator)
+        end.join(line_separator)
+      elsif self.rules.any? { |r| r.include?(PARENT) }
+        raise Sass::SyntaxError.new(&quot;Base-level rules cannot contain the parent-selector-referencing character '#{PARENT}'.&quot;, line)
       else
-        self.rule
+        per_rule_indent, total_indent = [:nested, :expanded].include?(@style) ? [rule_indent, ''] : ['', rule_indent]
+        total_indent + self.rules.map do |r|
+          per_rule_indent + r.gsub(/,$/, '').gsub(rule_split, rule_separator).rstrip
+        end.join(line_separator)
       end
-      
+
       children.each do |child|
         if child.is_a? RuleNode
           sub_rules &lt;&lt; child
@@ -43,38 +60,29 @@ module Sass::Tree
           attributes &lt;&lt; child
         end
       end
-      
+
       to_return = ''
       if !attributes.empty?
         old_spaces = '  ' * (tabs - 1)
         spaces = '  ' * tabs
         if @style == :compact
           attributes = attributes.map { |a| a.to_s(1) }.join(' ')
-          to_return &lt;&lt; &quot;#{old_spaces}#{total_rule} { #{attributes} }\n&quot;
+          to_return &lt;&lt; &quot;#{total_rule} { #{attributes} }\n&quot;
         elsif @style == :compressed
           attributes = attributes.map { |a| a.to_s(1) }.join(';')
           to_return &lt;&lt; &quot;#{total_rule}{#{attributes}}&quot;
         else
           attributes = attributes.map { |a| a.to_s(tabs + 1) }.join(&quot;\n&quot;)
           end_attrs = (@style == :expanded ? &quot;\n&quot; + old_spaces : ' ')
-          to_return &lt;&lt; &quot;#{old_spaces}#{total_rule} {\n#{attributes}#{end_attrs}}\n&quot;
+          to_return &lt;&lt; &quot;#{total_rule} {\n#{attributes}#{end_attrs}}\n&quot;
         end
-      elsif continued?
-        to_return &lt;&lt; ('  ' * (tabs - 1)) + total_rule + case @style
-                                                        when :compressed: ''
-                                                        when :compact: ' '
-                                                        else &quot;\n&quot;
-                                                        end
       end
-      
+
       tabs += 1 unless attributes.empty? || @style != :nested
       sub_rules.each do |sub|
-        if sub.continued?
-          check_multiline_rule(sub)
-        end
-
         to_return &lt;&lt; sub.to_s(tabs, total_rule)
       end
+
       to_return
     end
   end</diff>
      <filename>vendor/plugins/haml/lib/sass/tree/rule_node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ require 'sass/tree/node'
 module Sass::Tree
   class ValueNode &lt; Node
     attr_accessor :value
-  
+
     def initialize(value, style)
       @value = value
       super(style)</diff>
      <filename>vendor/plugins/haml/lib/sass/tree/value_node.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,95 +1,82 @@
-# There's a bizarre error where ActionController tries to load a benchmark file
-# and ends up finding this.
-# These declarations then cause it to break.
-# This only happens when running rcov, though, so we can avoid it.
-unless $0 =~ /rcov$/
-  require File.dirname(__FILE__) + '/../lib/haml'
-  require 'haml'
+#!/usr/bin/env ruby
+
+times = (ARGV.first || 1000).to_i
+
+if times == 0 # Invalid parameter
+  puts &lt;&lt;END
+ruby #$0 [times=1000]
+  Benchmark Haml against various other templating languages and Sass
+  on its own.
+END
+  exit 1
+end
+
+require File.dirname(__FILE__) + '/../lib/haml'
+%w[sass rubygems erb erubis markaby active_support action_controller
+   action_view haml/template].each(&amp;method(:require))
+
+begin
+  require 'benchwarmer'
+rescue LoadError
+  # Since it's not as simple as gem install at the time of writing,
+  # we need to direct folks to the benchwarmer gem.
+  raise &quot;The Haml benchmarks require the benchwarmer gem, available from http://github.com/wycats/benchwarmer&quot;
 end
 
-require 'rubygems'
-require 'erb'
-require 'erubis'
-require 'markaby'
-require 'benchmark'
-require 'stringio'
-require 'open-uri'
-
-module Haml
-  # Benchmarks Haml against ERB, Erubis, and Markaby and Sass on its own.
-  def self.benchmark(runs = 100)
-    template_name = 'standard'
-    directory = File.dirname(__FILE__) + '/haml'
-    haml_template =    File.read(&quot;#{directory}/templates/#{template_name}.haml&quot;)
-    erb_template =   File.read(&quot;#{directory}/rhtml/#{template_name}.rhtml&quot;)
-    markaby_template = File.read(&quot;#{directory}/markaby/#{template_name}.mab&quot;)
-
-    puts '-'*51, &quot;Haml and Friends: No Caching&quot;, '-'*51
-
-    times = Benchmark.bmbm do |b|
-      b.report(&quot;haml:&quot;)   { runs.times { Haml::Engine.new(haml_template).render } }
-      b.report(&quot;erb:&quot;)    { runs.times { ERB.new(erb_template, nil, '-').render } }
-      b.report(&quot;erubis:&quot;) { runs.times { Erubis::Eruby.new(erb_template).result } }
-      b.report(&quot;mab:&quot;)    { runs.times { Markaby::Template.new(markaby_template).render } }
-    end
-
-    print_result = proc do |s, n|
-      printf &quot;%1$*2$s %3$*4$g&quot;,
-        &quot;Haml/#{s}:&quot;, -13, times[0].to_a[5] / times[n].to_a[5], -17
-      printf &quot;%1$*2$s %3$g\n&quot;,
-        &quot;#{s}/Haml:&quot;, -13, times[n].to_a[5] / times[0].to_a[5]
-    end
-    
-    print_result[&quot;ERB&quot;, 1]
-    print_result[&quot;Erubis&quot;, 2]
-    print_result[&quot;Markaby&quot;, 3]
-
-    puts '', '-' * 50, 'Haml and Friends: Cached', '-' * 50
+Benchmark.warmer(times) do
+  columns :haml, :erb, :erubis, :mab
+  titles :haml =&gt; &quot;Haml&quot;, :erb =&gt; &quot;ERB&quot;, :erubis =&gt; &quot;Erubis&quot;, :mab =&gt; &quot;Markaby&quot;
 
+  template_name = 'standard'
+  directory = File.dirname(__FILE__) + '/haml'
+  haml_template    = File.read(&quot;#{directory}/templates/#{template_name}.haml&quot;)
+  erb_template     = File.read(&quot;#{directory}/rhtml/#{template_name}.rhtml&quot;)
+  markaby_template = File.read(&quot;#{directory}/markaby/#{template_name}.mab&quot;)
+
+  report &quot;Uncached&quot; do
+    haml   { Haml::Engine.new(haml_template).render }
+    erb    { ERB.new(erb_template, nil, '-').result }
+    erubis { Erubis::Eruby.new(erb_template).result }
+    mab    { Markaby::Template.new(markaby_template).render }
+  end
+
+  report &quot;Cached&quot; do
     obj = Object.new
+
     Haml::Engine.new(haml_template).def_method(obj, :haml)
-    erb = ERB.new(erb_template, nil, '-')
-    obj.instance_eval(&quot;def erb; #{erb.src}; end&quot;)
     Erubis::Eruby.new(erb_template).def_method(obj, :erubis)
-    times = Benchmark.bmbm do |b|
-      b.report(&quot;haml:&quot;)   { runs.times { obj.haml      } }
-      b.report(&quot;erb:&quot;)    { runs.times { obj.erb       } }
-      b.report(&quot;erubis:&quot;) { runs.times { obj.erubis    } }
-    end    
+    obj.instance_eval(&quot;def erb; #{ERB.new(erb_template, nil, '-').src}; end&quot;)
 
-    print_result[&quot;ERB&quot;, 1]
-    print_result[&quot;Erubis&quot;, 2]
-
-    puts '', '-' * 50, 'Haml and ERB: Via ActionView', '-' * 50
-
-    require 'active_support'
-    require 'action_controller'
-    require 'action_view'
-    require 'haml/template'
+    haml   { obj.haml }
+    erb    { obj.erb }
+    erubis { obj.erubis }
+  end
 
+  report &quot;ActionView&quot; do
     @base = ActionView::Base.new(File.dirname(__FILE__))
-    times = Benchmark.bmbm do |b|
-      b.report(&quot;haml:&quot;) { runs.times { @base.render 'haml/templates/standard' } }
-      b.report(&quot;erb:&quot;)  { runs.times { @base.render 'haml/rhtml/standard'     } }
-    end
 
-    print_result[&quot;ERB&quot;, 1]
+    # To cache the template
+    @base.render 'haml/templates/standard'
+    @base.render 'haml/rhtml/standard'
 
-    puts '', '-' * 50, 'Haml and ERB: Via ActionView with deep partials', '-' * 50
+    haml { @base.render 'haml/templates/standard' }
+    erb  { @base.render 'haml/rhtml/standard' }
+  end
 
+  report &quot;ActionView with deep partials&quot; do
     @base = ActionView::Base.new(File.dirname(__FILE__))
-    times = Benchmark.bmbm do |b|
-      b.report(&quot;haml:&quot;) { runs.times { @base.render 'haml/templates/action_view' } }
-      b.report(&quot;erb:&quot;)  { runs.times { @base.render 'haml/rhtml/action_view'     } }
-    end
-
-    print_result[&quot;ERB&quot;, 1]
-    
-    puts '', '-' * 50, 'Sass', '-' * 50
-    sass_template = File.read(&quot;#{File.dirname(__FILE__)}/sass/templates/complex.sass&quot;)
-    
-    Benchmark.bmbm do |b|
-      b.report(&quot;sass:&quot;) { runs.times { Sass::Engine.new(sass_template).render } }
-    end
+
+    # To cache the template
+    @base.render 'haml/templates/action_view'
+    @base.render 'haml/rhtml/action_view'
+
+    haml { @base.render 'haml/templates/action_view' }
+    erb  { @base.render 'haml/rhtml/action_view' }
   end
 end
+
+Benchmark.warmer(times) do
+  sass_template = File.read(&quot;#{File.dirname(__FILE__)}/sass/templates/complex.sass&quot;)
+
+  report(&quot;Sass&quot;) { Sass::Engine.new(sass_template).render }
+end</diff>
      <filename>vendor/plugins/haml/test/benchmark.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,15 +1,45 @@
 #!/usr/bin/env ruby
-
-require 'rubygems'
-require 'active_support'
-require 'action_controller'
-require 'action_view'
-
-require 'test/unit'
-require File.dirname(__FILE__) + '/../../lib/haml'
-require 'haml/engine'
+require File.dirname(__FILE__) + '/test_helper'
 
 class EngineTest &lt; Test::Unit::TestCase
+  # A map of erroneous Sass documents to the error messages they should produce.
+  # The error messages may be arrays;
+  # if so, the second element should be the line number that should be reported for the error.
+  # If this isn't provided, the tests will assume the line number should be the last line of the document.
+  EXCEPTION_MAP = {
+    &quot;!!!\n  a&quot; =&gt; &quot;Illegal nesting: nesting within a header command is illegal.&quot;,
+    &quot;a\n  b&quot; =&gt; &quot;Illegal nesting: nesting within plain text is illegal.&quot;,
+    &quot;/ a\n  b&quot; =&gt; &quot;Illegal nesting: nesting within a tag that already has content is illegal.&quot;,
+    &quot;% a&quot; =&gt; 'Invalid tag: &quot;% a&quot;.',
+    &quot;%p a\n  b&quot; =&gt; &quot;Illegal nesting: content can't be both given on the same line as %p and nested within it.&quot;,
+    &quot;%p=&quot; =&gt; &quot;There's no Ruby code for = to evaluate.&quot;,
+    &quot;%p~&quot; =&gt; &quot;There's no Ruby code for ~ to evaluate.&quot;,
+    &quot;~&quot; =&gt; &quot;There's no Ruby code for ~ to evaluate.&quot;,
+    &quot;=&quot; =&gt; &quot;There's no Ruby code for = to evaluate.&quot;,
+    &quot;%p/\n  a&quot; =&gt; &quot;Illegal nesting: nesting within a self-closing tag is illegal.&quot;,
+    &quot;%p\n\ta&quot; =&gt; &lt;&lt;END.strip,
+A tab character was used for indentation. Haml must be indented using two spaces.
+Are you sure you have soft tabs enabled in your editor?
+END
+    &quot;%p\n a&quot; =&gt; &quot;1 space was used for indentation. Haml must be indented using two spaces.&quot;,
+    &quot;%p\n   a&quot; =&gt; &quot;3 spaces were used for indentation. Haml must be indented using two spaces.&quot;,
+    &quot;%p\n    a&quot; =&gt; &quot;4 spaces were used for indentation. Haml must be indented using two spaces.&quot;,
+    &quot;:a\n  b&quot; =&gt; ['Filter &quot;a&quot; is not defined.', 1],
+    &quot;:a= b&quot; =&gt; 'Invalid filter name &quot;:a= b&quot;.',
+    &quot;.&quot; =&gt; &quot;Illegal element: classes and ids must have values.&quot;,
+    &quot;.#&quot; =&gt; &quot;Illegal element: classes and ids must have values.&quot;,
+    &quot;.{} a&quot; =&gt; &quot;Illegal element: classes and ids must have values.&quot;,
+    &quot;.= a&quot; =&gt; &quot;Illegal element: classes and ids must have values.&quot;,
+    &quot;%p..a&quot; =&gt; &quot;Illegal element: classes and ids must have values.&quot;,
+    &quot;%a/ b&quot; =&gt; &quot;Self-closing tags can't have content.&quot;,
+
+    # Regression tests
+    &quot;- raise 'foo'\n\n\n\nbar&quot; =&gt; [&quot;foo&quot;, 1],
+    &quot;= 'foo'\n-raise 'foo'&quot; =&gt; [&quot;foo&quot;, 2],
+    &quot;\n\n\n- raise 'foo'&quot; =&gt; [&quot;foo&quot;, 4],
+  }
+
+  User = Struct.new('User', :id)
 
   def render(text, options = {}, &amp;block)
     scope  = options.delete(:scope)  || Object.new
@@ -22,7 +52,7 @@ class EngineTest &lt; Test::Unit::TestCase
   end
 
   def test_attributes_should_render_correctly
-    assert_equal(&quot;&lt;div class='atlantis' style='ugly'&gt;\n&lt;/div&gt;&quot;, render(&quot;.atlantis{:style =&gt; 'ugly'}&quot;).chomp)
+    assert_equal(&quot;&lt;div class='atlantis' style='ugly'&gt;&lt;/div&gt;&quot;, render(&quot;.atlantis{:style =&gt; 'ugly'}&quot;).chomp)
   end
 
   def test_ruby_code_should_work_inside_attributes
@@ -31,7 +61,7 @@ class EngineTest &lt; Test::Unit::TestCase
   end
 
   def test_nil_should_render_empty_tag
-    assert_equal(&quot;&lt;div class='no_attributes'&gt;\n&lt;/div&gt;&quot;,
+    assert_equal(&quot;&lt;div class='no_attributes'&gt;&lt;/div&gt;&quot;,
                  render(&quot;.no_attributes{:nil =&gt; nil}&quot;).chomp)
   end
 
@@ -44,20 +74,8 @@ class EngineTest &lt; Test::Unit::TestCase
     assert_equal(&quot;&lt;p&gt;Hello&lt;/p&gt;&quot;, render('%p Hello').chomp)
   end
 
-  def test_long_liner_should_not_print_on_one_line
-    assert_equal(&quot;&lt;div&gt;\n  #{'x' * 51}\n&lt;/div&gt;&quot;, render(&quot;%div #{'x' * 51}&quot;).chomp)
-  end
-  
-  def test_non_prerendered_one_liner
-    assert_equal(&quot;&lt;p class='awesome'&gt;One line&lt;/p&gt;\n&quot;, render(&quot;%p{:class =&gt; c} One line&quot;, :locals =&gt; {:c =&gt; 'awesome'}))
-  end
-  
-  def test_non_prerendered_script_one_liner
-    assert_equal(&quot;&lt;p class='awesome'&gt;One line&lt;/p&gt;\n&quot;, render(&quot;%p{:class =&gt; c}= 'One line'&quot;, :locals =&gt; {:c =&gt; 'awesome'}))
-  end
-  
-  def test_non_prerendered_long_script_one_liner
-    assert_equal(&quot;&lt;p class='awesome'&gt;\n  #{'x' * 60}\n&lt;/p&gt;\n&quot;, render(&quot;%p{:class =&gt; c}= 'x' * 60&quot;, :locals =&gt; {:c =&gt; 'awesome'}))
+  def test_one_liner_with_newline_shouldnt_be_one_line
+    assert_equal(&quot;&lt;p&gt;\n  foo\n  bar\n&lt;/p&gt;&quot;, render('%p= &quot;foo\nbar&quot;').chomp)
   end
 
   def test_multi_render
@@ -93,8 +111,148 @@ class EngineTest &lt; Test::Unit::TestCase
     assert_equal(&quot;&lt;img alt='' src='/foo.png' /&gt;\n&quot;, render(&quot;%img{:width =&gt; nil, :src =&gt; '/foo.png', :alt =&gt; String.new}&quot;))
   end
 
+  def test_end_of_file_multiline
+    assert_equal(&quot;&lt;p&gt;0&lt;/p&gt;\n&lt;p&gt;1&lt;/p&gt;\n&lt;p&gt;2&lt;/p&gt;\n&quot;, render(&quot;- for i in (0...3)\n  %p= |\n   i |&quot;))
+  end
+
+  def test_cr_newline
+    assert_equal(&quot;&lt;p&gt;foo&lt;/p&gt;\n&lt;p&gt;bar&lt;/p&gt;\n&lt;p&gt;baz&lt;/p&gt;\n&lt;p&gt;boom&lt;/p&gt;\n&quot;, render(&quot;%p foo\r%p bar\r\n%p baz\n\r%p boom&quot;))
+  end
+
+  def test_textareas
+    assert_equal(&quot;&lt;textarea&gt;Foo&amp;#x000A;  bar&amp;#x000A;   baz&lt;/textarea&gt;\n&quot;,
+                 render('%textarea= &quot;Foo\n  bar\n   baz&quot;'))
+
+    assert_equal(&quot;&lt;pre&gt;Foo&amp;#x000A;  bar&amp;#x000A;   baz&lt;/pre&gt;\n&quot;,
+                 render('%pre= &quot;Foo\n  bar\n   baz&quot;'))
+
+    assert_equal(&quot;&lt;textarea&gt;#{'a' * 100}&lt;/textarea&gt;\n&quot;,
+                 render(&quot;%textarea #{'a' * 100}&quot;))
+
+    assert_equal(&quot;&lt;p&gt;\n  &lt;textarea&gt;Foo\n  Bar\n  Baz&lt;/textarea&gt;\n&lt;/p&gt;\n&quot;, render(&lt;&lt;SOURCE))
+%p
+  %textarea
+    Foo
+    Bar
+    Baz
+SOURCE
+  end
+
+  def test_boolean_attributes
+    assert_equal(&quot;&lt;p bar baz='true' foo='bar'&gt;&lt;/p&gt;\n&quot;,
+                 render(&quot;%p{:foo =&gt; 'bar', :bar =&gt; true, :baz =&gt; 'true'}&quot;, :format =&gt; :html4))
+    assert_equal(&quot;&lt;p bar='bar' baz='true' foo='bar'&gt;&lt;/p&gt;\n&quot;,
+                 render(&quot;%p{:foo =&gt; 'bar', :bar =&gt; true, :baz =&gt; 'true'}&quot;, :format =&gt; :xhtml))
+
+    assert_equal(&quot;&lt;p baz='false' foo='bar'&gt;&lt;/p&gt;\n&quot;,
+                 render(&quot;%p{:foo =&gt; 'bar', :bar =&gt; false, :baz =&gt; 'false'}&quot;, :format =&gt; :html4))
+    assert_equal(&quot;&lt;p baz='false' foo='bar'&gt;&lt;/p&gt;\n&quot;,
+                 render(&quot;%p{:foo =&gt; 'bar', :bar =&gt; false, :baz =&gt; 'false'}&quot;, :format =&gt; :xhtml))
+  end
+
+  def test_both_whitespace_nukes_work_together
+    assert_equal(&lt;&lt;RESULT, render(&lt;&lt;SOURCE))
+&lt;p&gt;&lt;q&gt;Foo
+  Bar&lt;/q&gt;&lt;/p&gt;
+RESULT
+%p
+  %q&gt;&lt;= &quot;Foo\\nBar&quot;
+SOURCE
+  end
+
+  # HTML escaping tests
+
+  def test_ampersand_equals_should_escape
+    assert_equal(&quot;&lt;p&gt;\n  foo &amp;amp; bar\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  &amp;= 'foo &amp; bar'&quot;, :escape_html =&gt; false))
+  end
+
+  def test_ampersand_equals_inline_should_escape
+    assert_equal(&quot;&lt;p&gt;foo &amp;amp; bar&lt;/p&gt;\n&quot;, render(&quot;%p&amp;= 'foo &amp; bar'&quot;, :escape_html =&gt; false))
+  end
+
+  def test_bang_equals_should_not_escape
+    assert_equal(&quot;&lt;p&gt;\n  foo &amp; bar\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  != 'foo &amp; bar'&quot;, :escape_html =&gt; true))
+  end
+
+  def test_bang_equals_inline_should_not_escape
+    assert_equal(&quot;&lt;p&gt;foo &amp; bar&lt;/p&gt;\n&quot;, render(&quot;%p!= 'foo &amp; bar'&quot;, :escape_html =&gt; true))
+  end
+  
+  def test_static_attributes_should_be_escaped
+    assert_equal(&quot;&lt;img class='atlantis' style='ugly&amp;amp;stupid' /&gt;\n&quot;,
+                 render(&quot;%img.atlantis{:style =&gt; 'ugly&amp;stupid'}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;div class='atlantis' style='ugly&amp;amp;stupid'&gt;foo&lt;/div&gt;\n&quot;,
+                 render(&quot;.atlantis{:style =&gt; 'ugly&amp;stupid'} foo&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p class='atlantis' style='ugly&amp;amp;stupid'&gt;foo&lt;/p&gt;\n&quot;,
+                render(&quot;%p.atlantis{:style =&gt; 'ugly&amp;stupid'}= 'foo'&quot;, :escape_html =&gt; true))
+  end
+
+  def test_dynamic_attributes_should_be_escaped
+    assert_equal(&quot;&lt;img alt='' src='/foo.png' /&gt;\n&quot;,
+                 render(&quot;%img{:width =&gt; nil, :src =&gt; '/foo.png', :alt =&gt; String.new}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p alt='' src='/foo.png'&gt;foo&lt;/p&gt;\n&quot;,
+                 render(&quot;%p{:width =&gt; nil, :src =&gt; '/foo.png', :alt =&gt; String.new} foo&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;div alt='' src='/foo.png'&gt;foo&lt;/div&gt;\n&quot;,
+                 render(&quot;%div{:width =&gt; nil, :src =&gt; '/foo.png', :alt =&gt; String.new}= 'foo'&quot;, :escape_html =&gt; true))
+  end
+  
+  def test_string_interpolation_should_be_esaped
+    assert_equal(&quot;&lt;p&gt;4&amp;amp;3&lt;/p&gt;\n&quot;, render(&quot;%p== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;4&amp;3&lt;/p&gt;\n&quot;, render(&quot;%p== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; false))
+  end
+
+  def test_escaped_inline_string_interpolation
+    assert_equal(&quot;&lt;p&gt;4&amp;amp;3&lt;/p&gt;\n&quot;, render(&quot;%p&amp;== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;4&amp;amp;3&lt;/p&gt;\n&quot;, render(&quot;%p&amp;== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; false))
+  end
+
+  def test_unescaped_inline_string_interpolation
+    assert_equal(&quot;&lt;p&gt;4&amp;3&lt;/p&gt;\n&quot;, render(&quot;%p!== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;4&amp;3&lt;/p&gt;\n&quot;, render(&quot;%p!== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; false))
+  end
+
+  def test_escaped_string_interpolation
+    assert_equal(&quot;&lt;p&gt;\n  4&amp;amp;3\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  &amp;== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;\n  4&amp;amp;3\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  &amp;== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; false))
+  end
+
+  def test_unescaped_string_interpolation
+    assert_equal(&quot;&lt;p&gt;\n  4&amp;3\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  !== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;\n  4&amp;3\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  !== #{2+2}&amp;#{2+1}&quot;, :escape_html =&gt; false))
+  end
+
+  def test_scripts_should_respect_escape_html_option
+    assert_equal(&quot;&lt;p&gt;\n  foo &amp;amp; bar\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  = 'foo &amp; bar'&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;\n  foo &amp; bar\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  = 'foo &amp; bar'&quot;, :escape_html =&gt; false))
+  end
+
+  def test_inline_scripts_should_respect_escape_html_option
+    assert_equal(&quot;&lt;p&gt;foo &amp;amp; bar&lt;/p&gt;\n&quot;, render(&quot;%p= 'foo &amp; bar'&quot;, :escape_html =&gt; true))
+    assert_equal(&quot;&lt;p&gt;foo &amp; bar&lt;/p&gt;\n&quot;, render(&quot;%p= 'foo &amp; bar'&quot;, :escape_html =&gt; false))
+  end
+
+  def test_script_ending_in_comment_should_render_when_html_is_escaped
+    assert_equal(&quot;foo&amp;amp;bar\n&quot;, render(&quot;= 'foo&amp;bar' #comment&quot;, :escape_html =&gt; true))
+  end
+
   # Options tests
 
+  def test_filename_and_line
+    begin
+      render(&quot;\n\n = abc&quot;, :filename =&gt; 'test', :line =&gt; 2)
+    rescue Exception =&gt; e
+      assert_kind_of Haml::SyntaxError, e
+      assert_match /test:4/, e.backtrace.first
+    end
+
+    begin
+      render(&quot;\n\n= 123\n\n= nil[]&quot;, :filename =&gt; 'test', :line =&gt; 2)
+    rescue Exception =&gt; e
+      assert_kind_of NoMethodError, e
+      assert_match /test:6/, e.backtrace.first
+    end
+  end
+
   def test_stop_eval
     assert_equal(&quot;&quot;, render(&quot;= 'Hello'&quot;, :suppress_eval =&gt; true))
     assert_equal(&quot;&quot;, render(&quot;- puts 'foo'&quot;, :suppress_eval =&gt; true))
@@ -104,25 +262,46 @@ class EngineTest &lt; Test::Unit::TestCase
 
     begin
       assert_equal(&quot;&quot;, render(&quot;:ruby\n  puts 'hello'&quot;, :suppress_eval =&gt; true))
-    rescue Haml::HamlError =&gt; err
+    rescue Haml::Error =&gt; err
       caught = true
-      assert_equal('&quot;ruby&quot; filter is not defined!', err.message)
+      assert_equal('Filter &quot;ruby&quot; is not defined.', err.message)
     end
     assert(caught, &quot;Rendering a ruby filter without evaluating didn't throw an error!&quot;)
   end
 
   def test_attr_wrapper
-    assert_equal(&quot;&lt;p strange=*attrs*&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{ :strange =&gt; 'attrs'}&quot;, :attr_wrapper =&gt; '*'))
-    assert_equal(&quot;&lt;p escaped='quo\&quot;te'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; 'quo\&quot;te'}&quot;, :attr_wrapper =&gt; '&quot;'))
-    assert_equal(&quot;&lt;p escaped=\&quot;q'uo&amp;quot;te\&quot;&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; 'q\\'uo\&quot;te'}&quot;, :attr_wrapper =&gt; '&quot;'))
+    assert_equal(&quot;&lt;p strange=*attrs*&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :strange =&gt; 'attrs'}&quot;, :attr_wrapper =&gt; '*'))
+    assert_equal(&quot;&lt;p escaped='quo\&quot;te'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; 'quo\&quot;te'}&quot;, :attr_wrapper =&gt; '&quot;'))
+    assert_equal(&quot;&lt;p escaped=\&quot;quo'te\&quot;&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; 'quo\\'te'}&quot;, :attr_wrapper =&gt; '&quot;'))
+    assert_equal(&quot;&lt;p escaped=\&quot;q'uo&amp;quot;te\&quot;&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; 'q\\'uo\&quot;te'}&quot;, :attr_wrapper =&gt; '&quot;'))
     assert_equal(&quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;utf-8\&quot; ?&gt;\n&quot;, render(&quot;!!! XML&quot;, :attr_wrapper =&gt; '&quot;'))
   end
 
   def test_attrs_parsed_correctly
-    assert_equal(&quot;&lt;p boom=&gt;biddly='bar =&gt; baz'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{'boom=&gt;biddly' =&gt; 'bar =&gt; baz'}&quot;))
-    assert_equal(&quot;&lt;p foo,bar='baz, qux'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{'foo,bar' =&gt; 'baz, qux'}&quot;))
-    assert_equal(&quot;&lt;p escaped='quo\nte'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; \&quot;quo\\nte\&quot;}&quot;))
-    assert_equal(&quot;&lt;p escaped='quo4te'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; \&quot;quo\#{2 + 2}te\&quot;}&quot;))
+    assert_equal(&quot;&lt;p boom=&gt;biddly='bar =&amp;gt; baz'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{'boom=&gt;biddly' =&gt; 'bar =&gt; baz'}&quot;))
+    assert_equal(&quot;&lt;p foo,bar='baz, qux'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{'foo,bar' =&gt; 'baz, qux'}&quot;))
+    assert_equal(&quot;&lt;p escaped='quo\nte'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; \&quot;quo\\nte\&quot;}&quot;))
+    assert_equal(&quot;&lt;p escaped='quo4te'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{ :escaped =&gt; \&quot;quo\#{2 + 2}te\&quot;}&quot;))
+  end
+  
+  def test_correct_parsing_with_brackets
+    assert_equal(&quot;&lt;p class='foo'&gt;{tada} foo&lt;/p&gt;\n&quot;, render(&quot;%p{:class =&gt; 'foo'} {tada} foo&quot;))
+    assert_equal(&quot;&lt;p class='foo'&gt;deep {nested { things }}&lt;/p&gt;\n&quot;, render(&quot;%p{:class =&gt; 'foo'} deep {nested { things }}&quot;))
+    assert_equal(&quot;&lt;p class='bar foo'&gt;{a { d&lt;/p&gt;\n&quot;, render(&quot;%p{{:class =&gt; 'foo'}, :class =&gt; 'bar'} {a { d&quot;))
+    assert_equal(&quot;&lt;p foo='bar'&gt;a}&lt;/p&gt;\n&quot;, render(&quot;%p{:foo =&gt; 'bar'} a}&quot;))
+    
+    foo = []
+    foo[0] = Struct.new('Foo', :id).new
+    assert_equal(&quot;&lt;p class='struct_foo' id='struct_foo_new'&gt;New User]&lt;/p&gt;\n&quot;,
+                 render(&quot;%p[foo[0]] New User]&quot;, :locals =&gt; {:foo =&gt; foo}))
+    assert_equal(&quot;&lt;p class='prefix_struct_foo' id='prefix_struct_foo_new'&gt;New User]&lt;/p&gt;\n&quot;,
+                 render(&quot;%p[foo[0], :prefix] New User]&quot;, :locals =&gt; {:foo =&gt; foo}))
+
+    foo[0].id = 1
+    assert_equal(&quot;&lt;p class='struct_foo' id='struct_foo_1'&gt;New User]&lt;/p&gt;\n&quot;,
+                 render(&quot;%p[foo[0]] New User]&quot;, :locals =&gt; {:foo =&gt; foo}))
+    assert_equal(&quot;&lt;p class='prefix_struct_foo' id='prefix_struct_foo_1'&gt;New User]&lt;/p&gt;\n&quot;,
+                 render(&quot;%p[foo[0], :prefix] New User]&quot;, :locals =&gt; {:foo =&gt; foo}))
   end
   
   def test_empty_attrs
@@ -135,6 +314,19 @@ class EngineTest &lt; Test::Unit::TestCase
     assert_equal(&quot;&lt;p&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p{ :attr =&gt; x } nil&quot;, :locals =&gt; {:x =&gt; nil}))
   end
 
+  def test_nil_id_with_syntactic_id
+    assert_equal(&quot;&lt;p id='foo'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p#foo{:id =&gt; nil} nil&quot;))
+    assert_equal(&quot;&lt;p id='foo_bar'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p#foo{{:id =&gt; 'bar'}, :id =&gt; nil} nil&quot;))
+    assert_equal(&quot;&lt;p id='foo_bar'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p#foo{{:id =&gt; nil}, :id =&gt; 'bar'} nil&quot;))
+  end
+
+  def test_nil_class_with_syntactic_class
+    assert_equal(&quot;&lt;p class='foo'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p.foo{:class =&gt; nil} nil&quot;))
+    assert_equal(&quot;&lt;p class='bar foo'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p.bar.foo{:class =&gt; nil} nil&quot;))
+    assert_equal(&quot;&lt;p class='bar foo'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p.foo{{:class =&gt; 'bar'}, :class =&gt; nil} nil&quot;))
+    assert_equal(&quot;&lt;p class='bar foo'&gt;nil&lt;/p&gt;\n&quot;, render(&quot;%p.foo{{:class =&gt; nil}, :class =&gt; 'bar'} nil&quot;))
+  end
+
   def test_locals
     assert_equal(&quot;&lt;p&gt;Paragraph!&lt;/p&gt;\n&quot;, render(&quot;%p= text&quot;, :locals =&gt; { :text =&gt; &quot;Paragraph!&quot; }))
   end
@@ -152,44 +344,33 @@ class EngineTest &lt; Test::Unit::TestCase
   end
 
   def test_dynamic_attrs_shouldnt_register_as_literal_values
-    assert_equal(&quot;&lt;p a='b2c'&gt;\n&lt;/p&gt;\n&quot;, render('%p{:a =&gt; &quot;b#{1 + 1}c&quot;}'))
-    assert_equal(&quot;&lt;p a='b2c'&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p{:a =&gt; 'b' + (1 + 1).to_s + 'c'}&quot;))
+    assert_equal(&quot;&lt;p a='b2c'&gt;&lt;/p&gt;\n&quot;, render('%p{:a =&gt; &quot;b#{1 + 1}c&quot;}'))
+    assert_equal(&quot;&lt;p a='b2c'&gt;&lt;/p&gt;\n&quot;, render(&quot;%p{:a =&gt; 'b' + (1 + 1).to_s + 'c'}&quot;))
   end
 
-  def test_rec_merge
-    hash1 = {1=&gt;2, 3=&gt;{5=&gt;7, 8=&gt;9}}
-    hash2 = {4=&gt;5, 3=&gt;{5=&gt;2, 16=&gt;12}}
-    hash3 = {1=&gt;2, 4=&gt;5, 3=&gt;{5=&gt;2, 8=&gt;9, 16=&gt;12}}
-
-    hash1.rec_merge!(hash2)
-    assert_equal(hash3, hash1)
+  def test_dynamic_attrs_with_self_closed_tag
+    assert_equal(&quot;&lt;a b='2' /&gt;\nc\n&quot;, render(&quot;%a{'b' =&gt; 1 + 1}/\n= 'c'\n&quot;))
   end
 
-  def test_syntax_errors
-    errs = [ &quot;!!!\n  a&quot;, &quot;a\n  b&quot;, &quot;a\n:foo\nb&quot;, &quot;/ a\n  b&quot;,
-             &quot;% a&quot;, &quot;%p a\n  b&quot;, &quot;a\n%p=\nb&quot;, &quot;%p=\n  a&quot;,
-             &quot;a\n%p~\nb&quot;, &quot;a\n~\nb&quot;, &quot;a\n~\n  b&quot;, &quot;%p~\n  b&quot;, &quot;%p/\n  a&quot;,
-             &quot;%p\n \t%a b&quot;, &quot;%a\n b\nc&quot;, &quot;%a\n    b\nc&quot;,
-             &quot;:notafilter\n  This isn't\n  a filter!&quot;,
-             &quot;.{} a&quot;, &quot;\#{} a&quot;, &quot;.= 'foo'&quot;, &quot;%a/ b&quot;, &quot;%p..class&quot;, &quot;%p..#.&quot; ]
-    errs.each do |err|
+  def test_exceptions
+    EXCEPTION_MAP.each do |key, value|
       begin
-        render(err)
-      rescue Exception =&gt; e
-        assert(e.is_a?(Haml::Error), &quot;#{err.dump} doesn't produce Haml::SyntaxError&quot;)
+        render(key)
+      rescue Exception =&gt; err
+        value = [value] unless value.is_a?(Array)
+
+        assert_equal(value.first, err.message, &quot;Line: #{key}&quot;)
+        assert_equal(value[1] || key.split(&quot;\n&quot;).length, err.backtrace[0].gsub('(haml):', '').to_i, &quot;Line: #{key}&quot;)
       else
-        assert(false, &quot;#{err.dump} doesn't produce an exception&quot;)
+        assert(false, &quot;Exception not raised for\n#{key}&quot;)
       end
     end
   end
 
-  def test_syntax_error
+  def test_exception_line
     render(&quot;a\nb\n!!!\n  c\nd&quot;)
   rescue Haml::SyntaxError =&gt; e
-    assert_equal(e.message, &quot;Illegal Nesting: Nesting within a header command is illegal.&quot;)
-    assert_equal(&quot;(haml):3&quot;, e.backtrace[0])
-  rescue Exception =&gt; e
-    assert(false, '&quot;a\nb\n!!!\n  c\nd&quot; doesn\'t produce a Haml::SyntaxError')
+    assert_equal(&quot;(haml):4&quot;, e.backtrace[0])
   else
     assert(false, '&quot;a\nb\n!!!\n  c\nd&quot; doesn\'t produce an exception')
   end
@@ -218,6 +399,11 @@ class EngineTest &lt; Test::Unit::TestCase
     assert_equal(&quot;Unbalanced brackets.&quot;, e.message)
   end
 
+  def test_balanced_conditional_comments
+    assert_equal(&quot;&lt;!--[if !(IE 6)|(IE 7)]&gt; Bracket: ] &lt;![endif]--&gt;\n&quot;,
+                 render(&quot;/[if !(IE 6)|(IE 7)] Bracket: ]&quot;))
+  end
+
   def test_no_bluecloth
     Kernel.module_eval do
       def gem_original_require_with_bluecloth(file)
@@ -231,7 +417,7 @@ class EngineTest &lt; Test::Unit::TestCase
     begin
       assert_equal(&quot;&lt;h1&gt;Foo&lt;/h1&gt;\t&lt;p&gt;- a\n- b&lt;/p&gt;\n&quot;,
                    Haml::Engine.new(&quot;:markdown\n  Foo\n  ===\n  - a\n  - b&quot;).to_html)
-    rescue Haml::HamlError =&gt; e
+    rescue Haml::Error =&gt; e
       if e.message == &quot;Can't run Markdown filter; required 'bluecloth' or 'redcloth', but none were found&quot;
         puts &quot;\nCouldn't require 'bluecloth' or 'redcloth'; skipping a test.&quot;
       else
@@ -256,7 +442,7 @@ class EngineTest &lt; Test::Unit::TestCase
 
     begin
       Haml::Engine.new(&quot;:redcloth\n  _foo_&quot;).to_html
-    rescue Haml::HamlError
+    rescue Haml::Error
     else
       assert(false, &quot;No exception raised!&quot;)
     end
@@ -278,7 +464,7 @@ class EngineTest &lt; Test::Unit::TestCase
 
     begin
       Haml::Engine.new(&quot;:markdown\n  _foo_&quot;).to_html
-    rescue Haml::HamlError
+    rescue Haml::Error
     else
       assert(false, &quot;No exception raised!&quot;)
     end
@@ -288,17 +474,39 @@ class EngineTest &lt; Test::Unit::TestCase
     end    
   end
 
+  def test_empty_filter
+    assert_equal(&lt;&lt;END, render(':javascript'))
+&lt;script type='text/javascript'&gt;
+  //&lt;![CDATA[
+    
+  //]]&gt;
+&lt;/script&gt;
+END
+  end
+
   def test_local_assigns_dont_modify_class
     assert_equal(&quot;bar\n&quot;, render(&quot;= foo&quot;, :locals =&gt; {:foo =&gt; 'bar'}))
     assert_equal(nil, defined?(foo))
   end
 
   def test_object_ref_with_nil_id
-    user = Struct.new('User', :id).new
+    user = User.new
     assert_equal(&quot;&lt;p class='struct_user' id='struct_user_new'&gt;New User&lt;/p&gt;\n&quot;,
                  render(&quot;%p[user] New User&quot;, :locals =&gt; {:user =&gt; user}))
   end
 
+  def test_object_ref_before_attrs
+    user = User.new 42
+    assert_equal(&quot;&lt;p class='struct_user' id='struct_user_42' style='width: 100px;'&gt;New User&lt;/p&gt;\n&quot;,
+                 render(&quot;%p[user]{:style =&gt; 'width: 100px;'} New User&quot;, :locals =&gt; {:user =&gt; user}))
+  end
+
+  def test_non_literal_attributes
+    assert_equal(&quot;&lt;p a1='foo' a2='bar' a3='baz' /&gt;\n&quot;,
+                 render(&quot;%p{a2, a1, :a3 =&gt; 'baz'}/&quot;,
+                        :locals =&gt; {:a1 =&gt; {:a1 =&gt; 'foo'}, :a2 =&gt; {:a2 =&gt; 'bar'}}))
+  end
+
   def test_render_should_accept_a_binding_as_scope
     string = &quot;This is a string!&quot;
     string.instance_variable_set(&quot;@var&quot;, &quot;Instance variable&quot;)
@@ -340,4 +548,58 @@ class EngineTest &lt; Test::Unit::TestCase
   def test_render_proc_with_binding
     assert_equal(&quot;FOO\n&quot;, Haml::Engine.new(&quot;= upcase&quot;).render_proc(&quot;foo&quot;.instance_eval{binding}).call)
   end
+
+  def test_ugly_true
+    assert_equal(&quot;&lt;div id='outer'&gt;\n&lt;div id='inner'&gt;\n&lt;p&gt;hello world&lt;/p&gt;\n&lt;/div&gt;\n&lt;/div&gt;\n&quot;,
+                 render(&quot;#outer\n  #inner\n    %p hello world&quot;, :ugly =&gt; true))
+
+    assert_equal(&quot;&lt;p&gt;#{'s' * 75}&lt;/p&gt;\n&quot;,
+                 render(&quot;%p #{'s' * 75}&quot;, :ugly =&gt; true))
+
+    assert_equal(&quot;&lt;p&gt;#{'s' * 75}&lt;/p&gt;\n&quot;,
+                 render(&quot;%p= 's' * 75&quot;, :ugly =&gt; true))
+  end
+
+  def test_xhtml_output_option
+    assert_equal &quot;&lt;p&gt;\n  &lt;br /&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  %br&quot;, :format =&gt; :xhtml)
+    assert_equal &quot;&lt;a /&gt;\n&quot;, render(&quot;%a/&quot;, :format =&gt; :xhtml)
+  end
+
+  def test_arbitrary_output_option
+    assert_raise(Haml::Error, &quot;Invalid output format :html1&quot;) { Haml::Engine.new(&quot;%br&quot;, :format =&gt; :html1) }
+  end
+
+  # HTML 4.0
+
+  def test_html_has_no_self_closing_tags
+    assert_equal &quot;&lt;p&gt;\n  &lt;br&gt;\n&lt;/p&gt;\n&quot;, render(&quot;%p\n  %br&quot;, :format =&gt; :html4)
+    assert_equal &quot;&lt;br&gt;\n&quot;, render(&quot;%br/&quot;, :format =&gt; :html4)
+  end
+
+  def test_html_renders_empty_node_with_closing_tag
+    assert_equal &quot;&lt;div class='foo'&gt;&lt;/div&gt;\n&quot;, render(&quot;.foo&quot;, :format =&gt; :html4)
+  end
+
+  def test_html_ignores_explicit_self_closing_declaration
+    assert_equal &quot;&lt;a&gt;&lt;/a&gt;\n&quot;, render(&quot;%a/&quot;, :format =&gt; :html4)
+  end
+
+  def test_html_ignores_xml_prolog_declaration
+    assert_equal &quot;&quot;, render('!!! XML', :format =&gt; :html4)
+  end
+
+  def test_html_has_different_doctype
+    assert_equal %{&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;\n},
+    render('!!!', :format =&gt; :html4)
+  end
+
+  # because anything before the doctype triggers quirks mode in IE
+  def test_xml_prolog_and_doctype_dont_result_in_a_leading_whitespace_in_html
+    assert_no_match /^\s+/, render(&quot;!!! xml\n!!!&quot;, :format =&gt; :html4)
+  end
+
+  # HTML5
+  def test_html5_doctype
+    assert_equal %{&lt;!DOCTYPE html&gt;\n}, render('!!!', :format =&gt; :html5)
+  end
 end</diff>
      <filename>vendor/plugins/haml/test/haml/engine_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,15 @@
 #!/usr/bin/env ruby
-
-require 'rubygems'
-require 'active_support'
-require 'action_controller'
-require 'action_view'
-
-require 'test/unit'
-require File.dirname(__FILE__) + '/../../lib/haml'
+require File.dirname(__FILE__) + '/test_helper'
 require 'haml/template'
 
 class HelperTest &lt; Test::Unit::TestCase
   include Haml::Helpers
+  Post = Struct.new('Post', :body)
   
   def setup
     @base = ActionView::Base.new
     @base.controller = ActionController::Base.new
+    @base.instance_variable_set('@post', Post.new(&quot;Foo bar\nbaz&quot;))
   end
 
   def render(text, options = {})
@@ -27,14 +22,14 @@ class HelperTest &lt; Test::Unit::TestCase
   end
 
   def test_flatten
-    assert_equal(flatten(&quot;FooBar&quot;), &quot;FooBar&quot;)
+    assert_equal(&quot;FooBar&quot;, flatten(&quot;FooBar&quot;))
 
-    assert_equal(flatten(&quot;Foo\rBar&quot;), &quot;FooBar&quot;)
+    assert_equal(&quot;FooBar&quot;, flatten(&quot;Foo\rBar&quot;))
 
-    assert_equal(flatten(&quot;Foo\nBar&quot;), &quot;Foo&amp;#x000A;Bar&quot;)
+    assert_equal(&quot;Foo&amp;#x000A;Bar&quot;, flatten(&quot;Foo\nBar&quot;))
 
-    assert_equal(flatten(&quot;Hello\nWorld!\nYOU ARE \rFLAT?\n\rOMGZ!&quot;),
-                         &quot;Hello&amp;#x000A;World!&amp;#x000A;YOU ARE FLAT?&amp;#x000A;OMGZ!&quot;)
+    assert_equal(&quot;Hello&amp;#x000A;World!&amp;#x000A;YOU ARE FLAT?&amp;#x000A;OMGZ!&quot;,
+                 flatten(&quot;Hello\nWorld!\nYOU ARE \rFLAT?\n\rOMGZ!&quot;))
   end
 
   def test_list_of_should_render_correctly
@@ -85,10 +80,33 @@ class HelperTest &lt; Test::Unit::TestCase
     should_be = &quot;&lt;form action=\&quot;foo\&quot; method=\&quot;post\&quot;&gt;\n  &lt;p&gt;bar&lt;/p&gt;\n  &lt;strong&gt;baz&lt;/strong&gt;\n&lt;/form&gt;\n&quot;
     assert_equal(should_be, result)
   end
+
+  def test_text_area
+    assert_equal(%(&lt;textarea id=&quot;body&quot; name=&quot;body&quot;&gt;Foo&amp;#x000A;Bar&amp;#x000A; Baz&amp;#x000A;   Boom&lt;/textarea&gt;\n),
+                 render('= text_area_tag &quot;body&quot;, &quot;Foo\nBar\n Baz\n   Boom&quot;', :action_view))
+
+    assert_equal(%(&lt;textarea cols=&quot;40&quot; id=&quot;post_body&quot; name=&quot;post[body]&quot; rows=&quot;20&quot;&gt;Foo bar&amp;#x000A;baz&lt;/textarea&gt;\n),
+                 render('= text_area :post, :body', :action_view))    
+
+    assert_equal(%(&lt;pre&gt;Foo bar&amp;#x000A;   baz&lt;/pre&gt;\n),
+                 render('= content_tag &quot;pre&quot;, &quot;Foo bar\n   baz&quot;', :action_view))    
+  end
   
   def test_capture_haml
     assert_equal(&quot;\&quot;&lt;p&gt;13&lt;/p&gt;\\n\&quot;\n&quot;, render(&quot;- foo = capture_haml(13) do |a|\n  %p= a\n= foo.dump&quot;))
   end
+  
+  def test_haml_tag_attribute_html_escaping
+    assert_equal(&quot;&lt;p id='foo&amp;amp;bar'&gt;baz&lt;/p&gt;\n&quot;, render(&quot;%p{:id =&gt; 'foo&amp;bar'} baz&quot;, :escape_html =&gt; true))
+  end
+
+  def test_haml_tag_autoclosed_tags_are_closed
+    assert_equal(&quot;&lt;br class='foo' /&gt;\n&quot;, render(&quot;- haml_tag :br, :class =&gt; 'foo'&quot;))
+  end
+
+  def test_haml_tag_non_autoclosed_tags_arent_closed
+    assert_equal(&quot;&lt;p&gt;\n&lt;/p&gt;\n&quot;, render(&quot;- haml_tag :p&quot;))
+  end
 
   def test_is_haml
     assert(!ActionView::Base.new.is_haml?)
@@ -122,6 +140,16 @@ class HelperTest &lt; Test::Unit::TestCase
     assert_equal(&quot;1\n\n2\n\n3\n\n&quot;, render(&quot;- trc([1, 2, 3]) do |i|\n  = i.inspect&quot;))
   end
 
+  def test_find_and_preserve_with_block
+    assert_equal(&quot;&lt;pre&gt;Foo&amp;#x000A;Bar&lt;/pre&gt;\nFoo\nBar\n&quot;,
+                 render(&quot;= find_and_preserve do\n  %pre\n    Foo\n    Bar\n  Foo\n  Bar&quot;))
+  end
+
+  def test_preserve_with_block
+    assert_equal(&quot;&lt;pre&gt;Foo&amp;#x000A;Bar&lt;/pre&gt;&amp;#x000A;Foo&amp;#x000A;Bar\n&quot;,
+                 render(&quot;= preserve do\n  %pre\n    Foo\n    Bar\n  Foo\n  Bar&quot;))
+  end
+
   def test_init_haml_helpers
     context = Object.new
     class &lt;&lt; context
@@ -130,12 +158,30 @@ class HelperTest &lt; Test::Unit::TestCase
     context.init_haml_helpers
 
     result = context.capture_haml do
-      context.open :p, :attr =&gt; &quot;val&quot; do
+      context.haml_tag :p, :attr =&gt; &quot;val&quot; do
         context.puts &quot;Blah&quot;
       end
     end
 
     assert_equal(&quot;&lt;p attr='val'&gt;\n  Blah\n&lt;/p&gt;\n&quot;, result)
   end
+
+  def test_non_haml
+    assert_equal(&quot;false\n&quot;, render(&quot;= non_haml { is_haml? }&quot;))
+  end
+  
+  class ActsLikeTag
+    # We want to be able to have people include monkeypatched ActionView helpers
+    # without redefining is_haml?.
+    # This is accomplished via Object#is_haml?, and this is a test for it.
+    include ActionView::Helpers::TagHelper
+    def to_s
+      content_tag :p, 'some tag content'
+    end
+  end
+
+  def test_random_class_includes_tag_helper
+    assert_equal &quot;&lt;p&gt;some tag content&lt;/p&gt;&quot;, ActsLikeTag.new.to_s
+  end
 end
 </diff>
      <filename>vendor/plugins/haml/test/haml/helper_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,6 @@
 &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
 &lt;html&gt;
-  &lt;head&gt;
-  &lt;/head&gt;
+  &lt;head&gt;&lt;/head&gt;
   &lt;body&gt;
     &lt;div id='content'&gt;
       Lorem ipsum dolor sit amet</diff>
      <filename>vendor/plugins/haml/test/haml/results/content_for_layout.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,5 @@
-&lt;p&gt;
-&lt;/p&gt;
-&lt;p&gt;
-&lt;/p&gt;
+&lt;p&gt;&lt;/p&gt;
+&lt;p&gt;&lt;/p&gt;
 &lt;h1&gt;Me!&lt;/h1&gt;
 &lt;div id='foo'&gt;
   &lt;p id='bar'&gt;All&lt;/p&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/eval_suppressed.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 &lt;style&gt;
   p {
     border-style: dotted;
-    border-width: 10px;
+    border-width: 22px;
     border-color: #ff00ff; }
   
   h1 {
@@ -21,31 +21,54 @@ Wowie-zowie!&lt;/code&gt;&lt;/pre&gt;
 
 
 	&lt;p&gt;&lt;em&gt;pretty much the same as above&lt;/em&gt;&lt;/p&gt;
+&lt;p&gt;
+  &lt;script type='text/javascript'&gt;
+    //&lt;![CDATA[
+      function newline(str) {
+        return &quot;\n&quot; + str;
+      }
+    //]]&gt;
+  &lt;/script&gt;
+&lt;/p&gt;
 This
   Is
     Plain
       Text
         %strong right?
+ #{not interpolated}
+ \3
+ \#{also not}
+ \\
+&lt;p&gt;
+  &lt;pre&gt;This pre is pretty deeply&amp;#x000A;      nested.&amp;#x000A;   Does interpolation work?
+    This one is, too.&amp;#x000A;Nested, that is.&amp;#x000A;&lt;/pre&gt;
+&lt;/p&gt;
+&lt;ul&gt;
+
+  &lt;li&gt;a&lt;/li&gt;
+
+  &lt;li&gt;b&lt;/li&gt;
 
-  a
+  &lt;li&gt;c&lt;/li&gt;
 
-  b
+  &lt;li&gt;d&lt;/li&gt;
 
-  c
+  &lt;li&gt;e&lt;/li&gt;
 
-  d
+  &lt;li&gt;f&lt;/li&gt;
 
-  e
+  &lt;li&gt;g&lt;/li&gt;
 
-  f
+  &lt;li&gt;h&lt;/li&gt;
 
-  g
+  &lt;li&gt;i&lt;/li&gt;
 
-  h
+  &lt;li&gt;j&lt;/li&gt;
 
-  i
 
-  j
+
+&lt;/ul&gt;
+&lt;div class='res'&gt;178&lt;/div&gt;
 &lt;ul&gt;
 &lt;li&gt;Foo&lt;/li&gt;
 &lt;li&gt;Bar&lt;/li&gt;
@@ -54,4 +77,6 @@ This
 Text!
 Hello, World!
 How are you doing today?
-
+&amp;lt;div class=&amp;quot;foo&amp;quot;&amp;gt;
+  &amp;lt;p&amp;gt;I think &amp;amp;mdash; or do I?&amp;lt;/p&amp;gt;
+&amp;lt;/div&amp;gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/filters.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -24,9 +24,7 @@
   &lt;/p&gt;
 &lt;/div&gt;
 &lt;p&gt;foo&lt;/p&gt;
-  &lt;p&gt;
-    reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong
-  &lt;/p&gt;
+  &lt;p&gt;reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeally loooooooooooooooooong&lt;/p&gt;
 &lt;div class='woah'&gt;
   &lt;div id='funky'&gt;
     &lt;div&gt;
@@ -56,6 +54,7 @@ foo
     @foo =
     value one
   &lt;/p&gt;
+  Toplevel? false
   &lt;p&gt;
     @foo =
     value three</diff>
      <filename>vendor/plugins/haml/test/haml/results/helpers.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -28,9 +28,6 @@ stuff followed by whitespace
 &lt;/p&gt;
 &lt;!-- Short comment --&gt;
 &lt;!-- 
-  This is a really long comment look how long it is it should be on a line of its own don't you think?
---&gt;
-&lt;!-- 
   This is a block comment
   cool, huh?
   &lt;strong&gt;there can even be sub-tags!&lt;/strong&gt;
@@ -62,6 +59,5 @@ testtest
 &lt;p class='article foo' id='article_1'&gt;Blah&lt;/p&gt;
 &lt;p class='article quux qux' id='article_1'&gt;Blump&lt;/p&gt;
 Woah inner quotes
-&lt;p class='dynamic_quote' dyn='3' quotes=&quot;single '&quot;&gt;
-&lt;/p&gt;
-&lt;p class='dynamic_atomic' dyn='3' /&gt;
+&lt;p class='dynamic_quote' dyn='3' quotes=&quot;single '&quot;&gt;&lt;/p&gt;
+&lt;p class='dynamic_self_closing' dyn='3' /&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/just_stuff.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -4,9 +4,7 @@
     &lt;title&gt;Stop. haml time&lt;/title&gt;
     &lt;div id='content'&gt;
       &lt;h1&gt;This is a title!&lt;/h1&gt;
-      &lt;p&gt;
-        Lorem ipsum dolor sit amet, consectetur adipisicing elit
-      &lt;/p&gt;
+      &lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipisicing elit&lt;/p&gt;
       &lt;p class='foo'&gt;Cigarettes!&lt;/p&gt;
       &lt;h2&gt;Man alive!&lt;/h2&gt;
       &lt;ul class='things'&gt;
@@ -15,10 +13,8 @@
         &lt;li&gt;Bathrobe&lt;/li&gt;
         &lt;li&gt;Coffee&lt;/li&gt;
       &lt;/ul&gt;
-      &lt;pre&gt;
-        This is some text that's in a pre block!
-        Let's see what happens when it's rendered! What about now, since we're on a new line?
-      &lt;/pre&gt;
+      &lt;pre&gt;This is some text that's in a pre block!
+      Let's see what happens when it's rendered! What about now, since we're on a new line?&lt;/pre&gt;
     &lt;/div&gt;
   &lt;/head&gt;
 &lt;/html&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/original_engine.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -10,6 +10,7 @@
   @foo =
   value two
 &lt;/p&gt;
+Toplevel? false
 &lt;p&gt;
   @foo =
   value three</diff>
      <filename>vendor/plugins/haml/test/haml/results/partials.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -12,8 +12,7 @@
   &lt;foo2u&gt;11&lt;/foo2u&gt;
 &lt;/div&gt;
 &lt;div class='classes'&gt;
-  &lt;p class='foo bar' id='boom'&gt;
-  &lt;/p&gt;
+  &lt;p class='foo bar' id='boom'&gt;&lt;/p&gt;
   &lt;div class='fooBar'&gt;a&lt;/div&gt;
   &lt;div class='foo-bar'&gt;b&lt;/div&gt;
   &lt;div class='foo_bar'&gt;c&lt;/div&gt;
@@ -22,7 +21,3 @@
   &lt;div class='123'&gt;f&lt;/div&gt;
   &lt;div class='foo2u'&gt;g&lt;/div&gt;
 &lt;/div&gt;
-&lt;div class='broken'&gt;
-  &lt;foo&gt;&lt;{ :a =&gt; :b }&lt;/foo&gt;
-  &lt;div class='foo'&gt;&gt;{ :c =&gt; :d }&lt;/div&gt;
-&lt;/div&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/tag_parsing.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,5 @@
 &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
 &lt;html&gt;
-  &lt;head&gt;
-  &lt;/head&gt;
-  &lt;body&gt;
-  &lt;/body&gt;
+  &lt;head&gt;&lt;/head&gt;
+  &lt;body&gt;&lt;/body&gt;
 &lt;/html&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/very_basic.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -12,16 +12,16 @@
   &lt;div class='text_area_test_area'&gt;
     &lt;textarea&gt;Oneline&lt;/textarea&gt;
   &lt;/div&gt;
-  &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+  &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;div class='text_area_test_area'&gt;
     &lt;textarea&gt;Two&amp;#x000A;lines&lt;/textarea&gt;
   &lt;/div&gt;
-  &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+  &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;div id='flattened'&gt;
     &lt;div class='text_area_test_area'&gt;
       &lt;textarea&gt;Two&amp;#x000A;lines&lt;/textarea&gt;
     &lt;/div&gt;
-    &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+    &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;/div&gt;
 &lt;/div&gt;
 &lt;div class='hithere'&gt;
@@ -36,7 +36,7 @@
 &lt;/div&gt;
 &lt;div class='foo'&gt;
   13
-  &lt;textarea&gt;&amp;#x000A;a&amp;#x000A;&lt;/textarea&gt;&lt;textarea&gt;&amp;#x000A;b&amp;#x000A;&lt;/textarea&gt;&lt;textarea&gt;&amp;#x000A;c&amp;#x000A;&lt;/textarea&gt;
+  &lt;textarea&gt;&amp;#x000A;a&lt;/textarea&gt;&lt;textarea&gt;&amp;#x000A;b&lt;/textarea&gt;&lt;textarea&gt;&amp;#x000A;c&lt;/textarea&gt;
 &lt;/div&gt;
 &lt;div id='whitespace_test'&gt;
   &lt;div class='text_area_test_area'&gt;
@@ -52,16 +52,16 @@
   &lt;div class='text_area_test_area'&gt;
     &lt;textarea&gt;Oneline&lt;/textarea&gt;
   &lt;/div&gt;
-  &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+  &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;div class='text_area_test_area'&gt;
     &lt;textarea&gt;Two&amp;#x000A;lines&lt;/textarea&gt;
   &lt;/div&gt;
-  &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+  &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;div id='flattened'&gt;
     &lt;div class='text_area_test_area'&gt;
       &lt;textarea&gt;Two&amp;#x000A;lines&lt;/textarea&gt;
     &lt;/div&gt;
-    &lt;textarea&gt;BLAH&amp;#x000A;&lt;/textarea&gt;
+    &lt;textarea&gt;BLAH&lt;/textarea&gt;
   &lt;/div&gt;
 &lt;/div&gt;
 &lt;div class='hithere'&gt;
@@ -73,22 +73,14 @@
     foo
     bar
   &lt;/p&gt;
-  &lt;pre&gt;
-                                                 ___&amp;#x000A;                                              ,o88888&amp;#x000A;                                           ,o8888888'&amp;#x000A;                     ,:o:o:oooo.        ,8O88Pd8888&quot;&amp;#x000A;                 ,.::.::o:ooooOoOoO. ,oO8O8Pd888'&quot;&amp;#x000A;               ,.:.::o:ooOoOoOO8O8OOo.8OOPd8O8O&quot;&amp;#x000A;              , ..:.::o:ooOoOOOO8OOOOo.FdO8O8&quot;&amp;#x000A;             , ..:.::o:ooOoOO8O888O8O,COCOO&quot;&amp;#x000A;            , . ..:.::o:ooOoOOOO8OOOOCOCO&quot;&amp;#x000A;             . ..:.::o:ooOoOoOO8O8OCCCC&quot;o&amp;#x000A;                . ..:.::o:ooooOoCoCCC&quot;o:o&amp;#x000A;                . ..:.::o:o:,cooooCo&quot;oo:o:&amp;#x000A;             `   . . ..:.:cocoooo&quot;'o:o:::'&amp;#x000A;             .`   . ..::ccccoc&quot;'o:o:o:::'&amp;#x000A;            :.:.    ,c:cccc&quot;':.:.:.:.:.'&amp;#x000A;          ..:.:&quot;'`::::c:&quot;'..:.:.:.:.:.'  http://www.chris.com/ASCII/&amp;#x000A;        ...:.'.:.::::&quot;'    . . . . .'&amp;#x000A;       .. . ....:.&quot;' `   .  . . ''&amp;#x000A;     . . . ....&quot;'&amp;#x000A;     .. . .&quot;'     -hrr-&amp;#x000A;    .&amp;#x000A;&amp;#x000A;&amp;#x000A;                                              It's a planet!&amp;#x000A;%strong This shouldn't be bold!&amp;#x000A;
-  &lt;/pre&gt;
+  &lt;pre&gt;                                                 ___&amp;#x000A;                                              ,o88888&amp;#x000A;                                           ,o8888888'&amp;#x000A;                     ,:o:o:oooo.        ,8O88Pd8888&quot;&amp;#x000A;                 ,.::.::o:ooooOoOoO. ,oO8O8Pd888'&quot;&amp;#x000A;               ,.:.::o:ooOoOoOO8O8OOo.8OOPd8O8O&quot;&amp;#x000A;              , ..:.::o:ooOoOOOO8OOOOo.FdO8O8&quot;&amp;#x000A;             , ..:.::o:ooOoOO8O888O8O,COCOO&quot;&amp;#x000A;            , . ..:.::o:ooOoOOOO8OOOOCOCO&quot;&amp;#x000A;             . ..:.::o:ooOoOoOO8O8OCCCC&quot;o&amp;#x000A;                . ..:.::o:ooooOoCoCCC&quot;o:o&amp;#x000A;                . ..:.::o:o:,cooooCo&quot;oo:o:&amp;#x000A;             `   . . ..:.:cocoooo&quot;'o:o:::'&amp;#x000A;             .`   . ..::ccccoc&quot;'o:o:o:::'&amp;#x000A;            :.:.    ,c:cccc&quot;':.:.:.:.:.'&amp;#x000A;          ..:.:&quot;'`::::c:&quot;'..:.:.:.:.:.'  http://www.chris.com/ASCII/&amp;#x000A;        ...:.'.:.::::&quot;'    . . . . .'&amp;#x000A;       .. . ....:.&quot;' `   .  . . ''&amp;#x000A;     . . . ....&quot;'&amp;#x000A;     .. . .&quot;'     -hrr-&amp;#x000A;    .&amp;#x000A;&amp;#x000A;&amp;#x000A;                                              It's a planet!&amp;#x000A;%strong This shouldn't be bold!&lt;/pre&gt;
   &lt;strong&gt;This should!&lt;/strong&gt;
-  &lt;textarea&gt;
-      ___           ___           ___           ___ &amp;#x000A;     /\__\         /\  \         /\__\         /\__\&amp;#x000A;    /:/  /        /::\  \       /::|  |       /:/  /&amp;#x000A;   /:/__/        /:/\:\  \     /:|:|  |      /:/  / &amp;#x000A;  /::\  \ ___   /::\~\:\  \   /:/|:|__|__   /:/  /  &amp;#x000A; /:/\:\  /\__\ /:/\:\ \:\__\ /:/ |::::\__\ /:/__/   &amp;#x000A; \/__\:\/:/  / \/__\:\/:/  / \/__/~~/:/  / \:\  \   &amp;#x000A;      \::/  /       \::/  /        /:/  /   \:\  \  &amp;#x000A;      /:/  /        /:/  /        /:/  /     \:\  \ &amp;#x000A;     /:/  /        /:/  /        /:/  /       \:\__\&amp;#x000A;     \/__/         \/__/         \/__/         \/__/&amp;#x000A;&amp;#x000A;     Many&amp;#x000A;                   thanks&amp;#x000A;           to&amp;#x000A;                                http://www.network-science.de/ascii/&amp;#x000A;
-    &lt;strong&gt;indeed!&lt;/strong&gt;
-  &lt;/textarea&gt;
+  &lt;textarea&gt;      ___           ___           ___           ___ &amp;#x000A;     /\__\         /\  \         /\__\         /\__\&amp;#x000A;    /:/  /        /::\  \       /::|  |       /:/  /&amp;#x000A;   /:/__/        /:/\:\  \     /:|:|  |      /:/  / &amp;#x000A;  /::\  \ ___   /::\~\:\  \   /:/|:|__|__   /:/  /  &amp;#x000A; /:/\:\  /\__\ /:/\:\ \:\__\ /:/ |::::\__\ /:/__/   &amp;#x000A; \/__\:\/:/  / \/__\:\/:/  / \/__/~~/:/  / \:\  \   &amp;#x000A;      \::/  /       \::/  /        /:/  /   \:\  \  &amp;#x000A;      /:/  /        /:/  /        /:/  /     \:\  \ &amp;#x000A;     /:/  /        /:/  /        /:/  /       \:\__\&amp;#x000A;     \/__/         \/__/         \/__/         \/__/&amp;#x000A;&amp;#x000A;     Many&amp;#x000A;                   thanks&amp;#x000A;           to&amp;#x000A;                                http://www.network-science.de/ascii/
+  &lt;strong&gt;indeed!&lt;/strong&gt;&lt;/textarea&gt;
 &lt;/div&gt;
 &lt;div class='foo'&gt;
   13
 &lt;/div&gt;
-&lt;pre&gt;
-       __     ______        __               ______&amp;#x000A;.----.|  |--.|__    |.----.|  |--..--------.|  __  |&amp;#x000A;|  __||     ||__    ||  __||    &lt; |        ||  __  |&amp;#x000A;|____||__|__||______||____||__|__||__|__|__||______|&amp;#x000A;
-&lt;/pre&gt;
-&lt;pre&gt;
-foo&amp;#x000A;
-  bar
-&lt;/pre&gt;
+&lt;pre&gt;       __     ______        __               ______&amp;#x000A;.----.|  |--.|__    |.----.|  |--..--------.|  __  |&amp;#x000A;|  __||     ||__    ||  __||    &lt; |        ||  __  |&amp;#x000A;|____||__|__||______||____||__|__||__|__|__||______|&lt;/pre&gt;
+&lt;pre&gt;foo
+bar&lt;/pre&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/results/whitespace_handling.xhtml</filename>
    </modified>
    <modified>
      <diff>@@ -1,19 +1,12 @@
 #!/usr/bin/env ruby
-
-require 'test/unit'
-require 'rubygems'
-require 'action_pack'
-
-require File.dirname(__FILE__) + '/../../lib/haml'
+require File.dirname(__FILE__) + '/test_helper'
 require 'haml/template'
 require File.dirname(__FILE__) + '/mocks/article'
 
-class TestFilter
-  def initialize(text)
-    @text = text
-  end
+module TestFilter
+  include Haml::Filters::Base
 
-  def render
+  def render(text)
     &quot;TESTING HAHAHAHA!&quot;
   end
 end
@@ -22,7 +15,7 @@ class TemplateTest &lt; Test::Unit::TestCase
   @@templates = %w{       very_basic        standard    helpers
     whitespace_handling   original_engine   list        helpful
     silent_script         tag_parsing       just_stuff  partials
-    filters }
+    filters               nuke_outer_whitespace         nuke_inner_whitespace }
 
   def setup
     Haml::Template.options = { :filters =&gt; { 'test'=&gt;TestFilter } }</diff>
      <filename>vendor/plugins/haml/test/haml/template_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@
   @foo = 
   = @foo
 - @foo = 'value three'
+== Toplevel? #{haml_buffer.toplevel?}
 %p
   @foo = 
   = @foo</diff>
      <filename>vendor/plugins/haml/test/haml/templates/_partial.haml</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,10 @@
 %style
+  - width = 5 + 17
   :sass
     p
       :border
         :style dotted
-        :width 10px
+        :width #{width}px
         :color #ff00ff
     h1
       :font-weight normal
@@ -29,17 +30,43 @@
 
   _pretty much the same as above_
 
+%p
+  :javascript
+    function newline(str) {
+      return &quot;\n&quot; + str;
+    }
+
 :plain
   This
     Is
       Plain
         Text
           %strong right?
+   \#{not interpolated}
+   \\#{1 + 2}
+   \\\#{also not}
+   \\
+
+- last = &quot;noitalo&quot;
+%p
+  %pre
+    :preserve
+      This pre is pretty deeply
+            nested.
+         Does #{&quot;interp&quot; + last.reverse} work?
+    :preserve
+        This one is, too.
+      Nested, that is.
 
-:erb
-  &lt;% 10.times do |c| %&gt;
-    &lt;%= (c+97).chr %&gt;
-  &lt;% end %&gt;
+- num = 10
+%ul
+  :erb
+    &lt;% num.times do |c| %&gt;
+      &lt;li&gt;&lt;%= (c+97).chr %&gt;&lt;/li&gt;
+    &lt;% end %&gt;
+    &lt;% res = 178 %&gt;
+
+.res= res
 
 :markdown
   *  Foo
@@ -48,6 +75,12 @@
 
 = &quot;Text!&quot;
 
+- var = &quot;Hello&quot;
 :ruby
-  puts &quot;Hello, World!&quot;
-  puts &quot;How are you doing today?&quot;
+  printf &quot;%s, World!\n&quot;, var
+  print &quot;How are you doing today?\n&quot;
+
+:escaped
+  &lt;div class=&quot;foo&quot;&gt;
+    &lt;p&gt;I think &amp;mdash; or do I?&lt;/p&gt;
+  &lt;/div&gt;</diff>
      <filename>vendor/plugins/haml/test/haml/templates/filters.haml</filename>
    </modified>
    <modified>
      <diff>@@ -31,10 +31,10 @@ click
 = succeed '.' do
   %a{:href=&gt;&quot;thing&quot;} here
 %p baz
-- buffer.tabulation = 10
+- haml_buffer.tabulation = 10
 %p boom
 - concat &quot;foo\n&quot;
-- buffer.tabulation = 0
+- haml_buffer.tabulation = 0
 - def url_for(*stuff); stuff.join(' '); end
 -# The form URLs must be empty
 -# because of a weird bug that causes url_for to misbehave.
@@ -58,12 +58,12 @@ click
   - puts &quot;boom&quot;
   baz
   - puts &quot;boom, again&quot;
-- open :table do
-  - open :tr do
-    - open :td, {:class =&gt; 'cell'} do
-      - open :strong, &quot;strong!&quot;
+- haml_tag :table do
+  - haml_tag :tr do
+    - haml_tag :td, {:class =&gt; 'cell'} do
+      - haml_tag :strong, &quot;strong!&quot;
       - puts &quot;data&quot;
-    - open :td do
+    - haml_tag :td do
       - puts &quot;more_data&quot;
-- open :hr
-- open :div, ''
+- haml_tag :hr
+- haml_tag :div, ''</diff>
      <filename>vendor/plugins/haml/test/haml/templates/helpers.haml</filename>
    </modified>
    <modified>
      <diff>@@ -31,7 +31,6 @@
   \%p foo
   \yee\ha
 / Short comment
-/ This is a really long comment look how long it is it should be on a line of its own don't you think?
 /
   This is a block comment
   cool, huh?
@@ -75,4 +74,4 @@
 %p.qux{:class =&gt; 'quux'}[@article] Blump
 == #{&quot;Woah inner quotes&quot;}
 %p.dynamic_quote{:quotes =&gt; &quot;single '&quot;, :dyn =&gt; 1 + 2}
-%p.dynamic_atomic{:dyn =&gt; 1 + 2}/
+%p.dynamic_self_closing{:dyn =&gt; 1 + 2}/</diff>
      <filename>vendor/plugins/haml/test/haml/templates/just_stuff.haml</filename>
    </modified>
    <modified>
      <diff>@@ -19,6 +19,3 @@
   .foo16 e
   .123 f
   .foo2u g
-%div.broken
-  %foo&lt;{ :a =&gt; :b }
-  .foo&gt;{ :c =&gt; :d }</diff>
      <filename>vendor/plugins/haml/test/haml/templates/tag_parsing.haml</filename>
    </modified>
    <modified>
      <diff>@@ -5,53 +5,73 @@ require File.dirname(__FILE__) + '/../../lib/sass'
 require 'sass/engine'
 
 class SassEngineTest &lt; Test::Unit::TestCase
+  # A map of erroneous Sass documents to the error messages they should produce.
+  # The error messages may be arrays;
+  # if so, the second element should be the line number that should be reported for the error.
+  # If this isn't provided, the tests will assume the line number should be the last line of the document.
   EXCEPTION_MAP = {
-    &quot;!a = 1 + &quot; =&gt; 'Constant arithmetic error: &quot;1 +&quot;',
-    &quot;!a = 1 + 2 +&quot; =&gt; 'Constant arithmetic error: &quot;1 + 2 +&quot;',
-    &quot;!a = \&quot;b&quot; =&gt; 'Unterminated string: &quot;\\&quot;b&quot;',
-    &quot;!a = #aaa - a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa minus a&quot;',
-    &quot;!a = #aaa / a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa div a&quot;',
-    &quot;!a = #aaa * a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa times a&quot;',
-    &quot;!a = #aaa % a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa mod a&quot;',
-    &quot;!a = 1 - a&quot; =&gt; 'Undefined operation: &quot;1 minus a&quot;',
-    &quot;!a = 1 * a&quot; =&gt; 'Undefined operation: &quot;1 times a&quot;',
-    &quot;!a = 1 / a&quot; =&gt; 'Undefined operation: &quot;1 div a&quot;',
-    &quot;!a = 1 % a&quot; =&gt; 'Undefined operation: &quot;1 mod a&quot;',
-    &quot;:&quot; =&gt; 'Invalid attribute: &quot;:&quot;',
-    &quot;: a&quot; =&gt; 'Invalid attribute: &quot;: a&quot;',
-    &quot;:= a&quot; =&gt; 'Invalid attribute: &quot;:= a&quot;',
-    &quot;a\n  :b&quot; =&gt; 'Invalid attribute: &quot;:b &quot;',
-    &quot;a\n  :b: c&quot; =&gt; 'Invalid attribute: &quot;:b: c&quot;',
-    &quot;a\n  :b:c d&quot; =&gt; 'Invalid attribute: &quot;:b:c d&quot;',
-    &quot;a\n  :b=c d&quot; =&gt; 'Invalid attribute: &quot;:b=c d&quot;',
-    &quot;a\n  :b c;&quot; =&gt; 'Invalid attribute: &quot;:b c;&quot; (This isn\'t CSS!)',
-    &quot;a\n  b : c&quot; =&gt; 'Invalid attribute: &quot;b : c&quot;',
-    &quot;a\n  b=c: d&quot; =&gt; 'Invalid attribute: &quot;b=c: d&quot;',
+    &quot;!a = 1 + &quot; =&gt; 'Constant arithmetic error: &quot;1 +&quot;.',
+    &quot;!a = 1 + 2 +&quot; =&gt; 'Constant arithmetic error: &quot;1 + 2 +&quot;.',
+    &quot;!a = \&quot;b&quot; =&gt; 'Unterminated string: &quot;\\&quot;b&quot;.',
+    &quot;!a = #aaa - a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa minus a&quot;.',
+    &quot;!a = #aaa / a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa div a&quot;.',
+    &quot;!a = #aaa * a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa times a&quot;.',
+    &quot;!a = #aaa % a&quot; =&gt; 'Undefined operation: &quot;#aaaaaa mod a&quot;.',
+    &quot;!a = 1 - a&quot; =&gt; 'Undefined operation: &quot;1 minus a&quot;.',
+    &quot;!a = 1 * a&quot; =&gt; 'Undefined operation: &quot;1 times a&quot;.',
+    &quot;!a = 1 / a&quot; =&gt; 'Undefined operation: &quot;1 div a&quot;.',
+    &quot;!a = 1 % a&quot; =&gt; 'Undefined operation: &quot;1 mod a&quot;.',
+    &quot;:&quot; =&gt; 'Invalid attribute: &quot;:&quot;.',
+    &quot;: a&quot; =&gt; 'Invalid attribute: &quot;: a&quot;.',
+    &quot;:= a&quot; =&gt; 'Invalid attribute: &quot;:= a&quot;.',
+    &quot;a\n  :b&quot; =&gt; 'Invalid attribute: &quot;:b &quot;.',
+    &quot;a\n  :b: c&quot; =&gt; 'Invalid attribute: &quot;:b: c&quot;.',
+    &quot;a\n  :b:c d&quot; =&gt; 'Invalid attribute: &quot;:b:c d&quot;.',
+    &quot;a\n  :b=c d&quot; =&gt; 'Invalid attribute: &quot;:b=c d&quot;.',
+    &quot;a\n  :b c;&quot; =&gt; 'Invalid attribute: &quot;:b c;&quot; (This isn\'t CSS!).',
+    &quot;a\n  b : c&quot; =&gt; 'Invalid attribute: &quot;b : c&quot;.',
+    &quot;a\n  b=c: d&quot; =&gt; 'Invalid attribute: &quot;b=c: d&quot;.',
     &quot;:a&quot; =&gt; 'Attributes aren\'t allowed at the root of a document.',
-    &quot;!&quot; =&gt; 'Invalid constant: &quot;!&quot;',
-    &quot;!a&quot; =&gt; 'Invalid constant: &quot;!a&quot;',
-    &quot;! a&quot; =&gt; 'Invalid constant: &quot;! a&quot;',
-    &quot;!a b&quot; =&gt; 'Invalid constant: &quot;!a b&quot;',
-    &quot;a\n\t:b c&quot; =&gt; &quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;,
-    &quot;a\n :b c&quot; =&gt; &quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;,
-    &quot;a\n    :b c&quot; =&gt; &quot;Illegal Indentation: Only two space characters are allowed as tabulation.&quot;,
+    &quot;!&quot; =&gt; 'Invalid constant: &quot;!&quot;.',
+    &quot;!a&quot; =&gt; 'Invalid constant: &quot;!a&quot;.',
+    &quot;! a&quot; =&gt; 'Invalid constant: &quot;! a&quot;.',
+    &quot;!a b&quot; =&gt; 'Invalid constant: &quot;!a b&quot;.',
+    &quot;a\n\t:b c&quot; =&gt; &lt;&lt;END.strip,
+A tab character was used for indentation. Sass must be indented using two spaces.
+Are you sure you have soft tabs enabled in your editor?
+END
+    &quot;a\n :b c&quot; =&gt; &quot;1 space was used for indentation. Sass must be indented using two spaces.&quot;,
+    &quot;a\n    :b c&quot; =&gt; &quot;4 spaces were used for indentation. Sass must be indented using two spaces.&quot;,
     &quot;a\n  :b c\n  !d = 3&quot; =&gt; &quot;Constants may only be declared at the root of a document.&quot;,
-    &quot;!a = 1b + 2c&quot; =&gt; &quot;Incompatible units: b and c&quot;,
-    &quot;&amp; a\n  :b c&quot; =&gt; &quot;Base-level rules cannot contain the parent-selector-referencing character '&amp;'&quot;,
+    &quot;!a = 1b + 2c&quot; =&gt; &quot;Incompatible units: b and c.&quot;,
+    &quot;&amp; a\n  :b c&quot; =&gt; &quot;Base-level rules cannot contain the parent-selector-referencing character '&amp;'.&quot;,
     &quot;a\n  :b\n    c&quot; =&gt; &quot;Illegal nesting: Only attributes may be nested beneath attributes.&quot;,
     &quot;a,\n  :b c&quot; =&gt; &quot;Rules can\'t end in commas.&quot;,
+    &quot;a,&quot; =&gt; &quot;Rules can\'t end in commas.&quot;,
+    &quot;a,\n!b = c&quot; =&gt; &quot;Rules can\'t end in commas.&quot;,
     &quot;!a = b\n  :c d\n&quot; =&gt; &quot;Illegal nesting: Nothing may be nested beneath constants.&quot;,
-    &quot;@import foo.sass&quot; =&gt; &quot;File to import not found or unreadable: foo.sass&quot;,
+    &quot;@import foo.sass&quot; =&gt; &quot;File to import not found or unreadable: foo.sass.&quot;,
     &quot;@import templates/basic\n  foo&quot; =&gt; &quot;Illegal nesting: Nothing may be nested beneath import directives.&quot;,
     &quot;foo\n  @import templates/basic&quot; =&gt; &quot;Import directives may only be used at the root of a document.&quot;,
     &quot;!foo = bar baz !&quot; =&gt; &quot;Unterminated constant.&quot;,
     &quot;!foo = !(foo)&quot; =&gt; &quot;Invalid constant.&quot;,
+    &quot;=foo\n  :color red\n.bar\n  +bang&quot; =&gt; &quot;Undefined mixin 'bang'.&quot;,
+    &quot;.bar\n  =foo\n    :color red\n&quot; =&gt; &quot;Mixins may only be defined at the root of a document.&quot;,
+    &quot;=foo\n  :color red\n.bar\n  +foo\n    :color red&quot; =&gt; &quot;Illegal nesting: Nothing may be nested beneath mixin directives.&quot;,
+
+    # Regression tests
+    &quot;a\n  b:\n    c\n    d&quot; =&gt; [&quot;Illegal nesting: Only attributes may be nested beneath attributes.&quot;, 3]
   }
   
   def test_basic_render
     renders_correctly &quot;basic&quot;, { :style =&gt; :compact }
   end
 
+  def test_multiple_calls_to_render
+    sass = Sass::Engine.new(&quot;a\n  b: c&quot;)
+    assert_equal sass.render, sass.render
+  end
+
   def test_alternate_styles
     renders_correctly &quot;expanded&quot;, { :style =&gt; :expanded }
     renders_correctly &quot;compact&quot;, { :style =&gt; :compact }
@@ -64,8 +84,10 @@ class SassEngineTest &lt; Test::Unit::TestCase
       begin
         Sass::Engine.new(key).render
       rescue Sass::SyntaxError =&gt; err
-        assert_equal(value, err.message)
-        assert(err.sass_line, &quot;Line: #{key}&quot;)
+        value = [value] unless value.is_a?(Array)
+
+        assert_equal(value.first, err.message, &quot;Line: #{key}&quot;)
+        assert_equal(value[1] || key.split(&quot;\n&quot;).length, err.sass_line, &quot;Line: #{key}&quot;)
         assert_match(/\(sass\):[0-9]+/, err.backtrace[0], &quot;Line: #{key}&quot;)
       else
         assert(false, &quot;Exception not raised for\n#{key}&quot;)
@@ -98,16 +120,27 @@ class SassEngineTest &lt; Test::Unit::TestCase
     end
   end
 
+  def test_css_import
+    assert_equal(&quot;@import url(./fonts.css) screen;&quot;, render(&quot;@import url(./fonts.css) screen&quot;))
+    assert_equal(&quot;@import \&quot;./fonts.css\&quot; screen;&quot;, render(&quot;@import \&quot;./fonts.css\&quot; screen&quot;))
+  end
+
+  def test_sass_import
+    renders_correctly &quot;import&quot;, { :style =&gt; :compact, :load_paths =&gt; [File.dirname(__FILE__) + &quot;/templates&quot;] }
+  end
+
   def test_default_function
     assert_equal(&quot;foo {\n  bar: url(foo.png); }\n&quot;,
                  render(&quot;foo\n  bar = url(foo.png)\n&quot;));
   end
 
-  def test_multiline_selector
+  def test_basic_multiline_selector
     assert_equal(&quot;#foo #bar,\n#baz #boom {\n  foo: bar; }\n&quot;,
                  render(&quot;#foo #bar,\n#baz #boom\n  :foo bar&quot;))
     assert_equal(&quot;#foo #bar,\n#foo #baz {\n  foo: bar; }\n&quot;,
                  render(&quot;#foo\n  #bar,\n  #baz\n    :foo bar&quot;))
+    assert_equal(&quot;#foo,\n#bar {\n  foo: bar; }\n  #foo #baz,\n  #bar #baz {\n    foo: bar; }\n&quot;,
+                 render(&quot;#foo,\n#bar\n  :foo bar\n  #baz\n    :foo bar&quot;))
     assert_equal(&quot;#foo #bar, #baz #boom { foo: bar; }\n&quot;,
                  render(&quot;#foo #bar,\n#baz #boom\n  :foo bar&quot;, :style =&gt; :compact))
                  
@@ -115,6 +148,10 @@ class SassEngineTest &lt; Test::Unit::TestCase
                  render(&quot;#foo #bar,\n#baz #boom\n  :foo bar&quot;, :style =&gt; :compressed))
   end
 
+  def test_complex_multiline_selector
+    renders_correctly &quot;multiline&quot;
+  end
+
   def test_colon_only
     begin
       render(&quot;a\n  b: c&quot;, :attribute_syntax =&gt; :normal)
@@ -204,7 +241,20 @@ END
     assert_equal(&quot;:focus {\n  a: b; }\n&quot;, render(&quot;\\:focus\n  a: b&quot;))
     assert_equal(&quot;a {\n  b: c; }\n  a :focus {\n    d: e; }\n&quot;, render(&quot;\\a\n  b: c\n  \\:focus\n    d: e&quot;))
   end
+
+  def test_cr_newline
+    assert_equal(&quot;foo {\n  a: b;\n  c: d;\n  e: f; }\n&quot;, render(&quot;foo\r  a: b\r\n  c: d\n\r  e: f&quot;))
+  end
+
+  def test_or_eq
+    assert_equal(&quot;foo {\n  a: b; }\n&quot;, render(&quot;!foo = b\n!foo ||= c\nfoo\n  a = !foo&quot;))
+    assert_equal(&quot;foo {\n  a: b; }\n&quot;, render(&quot;!foo ||= b\nfoo\n  a = !foo&quot;))
+  end
   
+  def test_mixins
+    renders_correctly &quot;mixins&quot;, { :style =&gt; :expanded }
+  end
+
   private
 
   def render(sass, options = {})</diff>
      <filename>vendor/plugins/haml/test/sass/engine_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -58,7 +58,7 @@ class SassPluginTest &lt; Test::Unit::TestCase
     File.delete(tempfile_loc('bork'))
     Sass::Plugin.update_stylesheets
     File.open(tempfile_loc('bork')) do |file|
-      assert_equal(&quot;/*\nSass::SyntaxError: Undefined constant: \&quot;!bork\&quot;\non line 2 of #{File.dirname(__FILE__) + '/templates/bork.sass'}\n\n1: bork\n2:   :bork= !bork&quot;, file.read.split(&quot;\n&quot;)[0...6].join(&quot;\n&quot;))
+      assert_equal(&quot;/*\nSass::SyntaxError: Undefined constant: \&quot;!bork\&quot;.\non line 2 of #{File.dirname(__FILE__) + '/templates/bork.sass'}\n\n1: bork\n2:   :bork= !bork&quot;, file.read.split(&quot;\n&quot;)[0...6].join(&quot;\n&quot;))
     end
     File.delete(tempfile_loc('bork'))
   end</diff>
      <filename>vendor/plugins/haml/test/sass/plugin_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,4 @@
-imported { otherconst: hello; myconst: goodbye; }
+imported { otherconst: hello; myconst: goodbye; pre-mixin: here; }
 
 body { font: Arial; background: blue; }
 
@@ -26,4 +26,4 @@ body { font: Arial; background: blue; }
 @import url(../results/complex.css);
 #foo { background-color: #baf; }
 
-nonimported { myconst: hello; otherconst: goodbye; }
+nonimported { myconst: hello; otherconst: goodbye; post-mixin: here; }</diff>
      <filename>vendor/plugins/haml/test/sass/results/import.css</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,11 @@
 !preconst = hello
 
+=premixin
+  pre-mixin: here
+
 @import importee, basic, basic.css, ../results/complex.css, partial
 
 nonimported
   :myconst = !preconst
   :otherconst = !postconst
-
+  +postmixin</diff>
      <filename>vendor/plugins/haml/test/sass/templates/import.sass</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,12 @@
 !postconst = goodbye
 
+=postmixin
+  post-mixin: here
+
 imported
   :otherconst = !preconst
   :myconst = !postconst
+  +premixin
 
 @import basic
 </diff>
      <filename>vendor/plugins/haml/test/sass/templates/importee.sass</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>vendor/plugins/haml/README</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/haml/lib/haml/util.rb</filename>
    </removed>
    <removed>
      <filename>vendor/plugins/haml/test/haml/runner.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>589aa4ce34bcd337652dd9d9cb035188ef428461</id>
    </parent>
  </parents>
  <author>
    <name>Nathan Weizenbaum</name>
    <email>nex342@gmail.com</email>
  </author>
  <url>http://github.com/nex3/nex3-s-blog-engine/commit/cd0b1fe8646bb00a0f628505fa6a891712e28b85</url>
  <id>cd0b1fe8646bb00a0f628505fa6a891712e28b85</id>
  <committed-date>2008-05-11T17:00:53-07:00</committed-date>
  <authored-date>2008-05-11T17:00:53-07:00</authored-date>
  <message>Update to the latest Haml release.</message>
  <tree>0cbafc5795a27daefc8752c43734b820d90c43b6</tree>
  <committer>
    <name>Nathan Weizenbaum</name>
    <email>nex342@gmail.com</email>
  </committer>
</commit>
