From 8a998b0fa7523c2c8eb6d0cf56e40408bf6e9b2e Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <santiago@wyeworks.com>
Date: Tue, 5 Jan 2016 16:48:09 -0300
Subject: Add Html template handler that wraps Raw output in an OutputBuffer

This fixes the case when you try to render an html you know safe and the
file is named something.html. With this commit the content of the html
won't be escaped anymore because AV won't use Raw handler and choose
Html handler instead.
---
 actionview/lib/action_view/template/handlers.rb          | 4 +++-
 actionview/lib/action_view/template/handlers/html.rb     | 9 +++++++++
 actionview/test/fixtures/layouts/render_partial_html.erb | 2 ++
 actionview/test/fixtures/test/_partialhtml.html          | 1 +
 actionview/test/template/render_test.rb                  | 7 ++++++-
 5 files changed, 21 insertions(+), 2 deletions(-)
 create mode 100644 actionview/lib/action_view/template/handlers/html.rb
 create mode 100644 actionview/test/fixtures/layouts/render_partial_html.erb
 create mode 100644 actionview/test/fixtures/test/_partialhtml.html

diff --git a/actionview/lib/action_view/template/handlers.rb b/actionview/lib/action_view/template/handlers.rb
index 0105e88a49..ad4c353608 100644
--- a/actionview/lib/action_view/template/handlers.rb
+++ b/actionview/lib/action_view/template/handlers.rb
@@ -2,13 +2,15 @@ module ActionView #:nodoc:
   # = Action View Template Handlers
   class Template
     module Handlers #:nodoc:
+      autoload :Raw, 'action_view/template/handlers/raw'
       autoload :ERB, 'action_view/template/handlers/erb'
+      autoload :Html, 'action_view/template/handlers/html'
       autoload :Builder, 'action_view/template/handlers/builder'
-      autoload :Raw, 'action_view/template/handlers/raw'
 
       def self.extended(base)
         base.register_default_template_handler :raw, Raw.new
         base.register_template_handler :erb, ERB.new
+        base.register_template_handler :html, Html.new
         base.register_template_handler :builder, Builder.new
         base.register_template_handler :ruby, :source.to_proc
       end
diff --git a/actionview/lib/action_view/template/handlers/html.rb b/actionview/lib/action_view/template/handlers/html.rb
new file mode 100644
index 0000000000..ccaa8d1469
--- /dev/null
+++ b/actionview/lib/action_view/template/handlers/html.rb
@@ -0,0 +1,9 @@
+module ActionView
+  module Template::Handlers
+    class Html < Raw
+      def call(template)
+        "ActionView::OutputBuffer.new #{super}"
+      end
+    end
+  end
+end
diff --git a/actionview/test/fixtures/layouts/render_partial_html.erb b/actionview/test/fixtures/layouts/render_partial_html.erb
new file mode 100644
index 0000000000..d4dbb6c76c
--- /dev/null
+++ b/actionview/test/fixtures/layouts/render_partial_html.erb
@@ -0,0 +1,2 @@
+<%= render :partial => 'test/partialhtml' %>
+<%= yield %>
diff --git a/actionview/test/fixtures/test/_partialhtml.html b/actionview/test/fixtures/test/_partialhtml.html
new file mode 100644
index 0000000000..afe39b730a
--- /dev/null
+++ b/actionview/test/fixtures/test/_partialhtml.html
@@ -0,0 +1 @@
+<h1>partial html</h1>
\ No newline at end of file
diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb
index 994fd44c52..b63c315a33 100644
--- a/actionview/test/template/render_test.rb
+++ b/actionview/test/template/render_test.rb
@@ -71,7 +71,7 @@ module RenderTestCases
     e = assert_raise ActionView::Template::Error do
       @view.render(:template => "with_format", :formats => [:json])
     end
-    assert_includes(e.message, "Missing partial /_missing with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :builder, :ruby]}.")
+    assert_includes(e.message, "Missing partial /_missing with {:locale=>[:en], :formats=>[:json], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby]}.")
   end
 
   def test_render_file_with_locale
@@ -467,6 +467,11 @@ module RenderTestCases
       @view.render(:file => "test/hello_world", :layout => "layouts/yield_with_render_partial_inside")
   end
 
+  def test_render_partial_with_html_only_extension
+    assert_equal %(<h1>partial html</h1>\nHello world!\n),
+      @view.render(:file => "test/hello_world", :layout => "layouts/render_partial_html")
+  end
+
   def test_render_layout_with_block_and_yield
     assert_equal %(Content from block!\n),
       @view.render(:layout => "layouts/yield_only") { "Content from block!" }
-- 
cgit v1.2.3