From c214b28f88c1b1cbce37d87c6e0276a122841712 Mon Sep 17 00:00:00 2001
From: Jess Hottenstein <jess@splitwise.com>
Date: Wed, 8 May 2024 16:11:35 -0400
Subject: [PATCH 1/2] Add new scrubber suitable for strip tags but adding
 whitespace

---
 lib/rails/html/scrubbers.rb | 28 ++++++++++++++++++++++++++++
 test/scrubbers_test.rb      | 14 ++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/lib/rails/html/scrubbers.rb b/lib/rails/html/scrubbers.rb
index a1317ad..7afd7c0 100644
--- a/lib/rails/html/scrubbers.rb
+++ b/lib/rails/html/scrubbers.rb
@@ -195,5 +195,33 @@ def scrub(node)
         end
       end
     end
+
+    # === Rails::HTML::SpaceBlockElementScrubber
+    #
+    # +Rails::HTML::SpaceBlockElementScrubber+ removes all undisplayable tags and contents.
+    #
+    # It preserves text contents and inserts a space around block level elements.
+    class SpaceBlockElementScrubber < Loofah::Scrubber # :nodoc:
+      def initialize
+        @direction = :bottom_up
+      end
+
+      def scrub(node)
+        if Loofah::Elements::LINEBREAKERS.include?(node.name)
+          replacement = if Loofah::Elements::INLINE_LINE_BREAK.include?(node.name)
+                          " "
+                        else
+                          " #{node.content} "
+                        end
+          node.add_next_sibling(Nokogiri::XML::Text.new(replacement, node.document))
+          node.remove
+        elsif node.text?
+          return CONTINUE
+        else
+          node.before node.children
+          node.remove
+        end
+      end
+    end
   end
 end
diff --git a/test/scrubbers_test.rb b/test/scrubbers_test.rb
index 8db2d85..ac979b6 100644
--- a/test/scrubbers_test.rb
+++ b/test/scrubbers_test.rb
@@ -200,6 +200,20 @@ def test_skips_text_nodes
   end
 end
 
+class SpaceBlockElementScrubberTest < ScrubberTest
+  def setup
+    @scrubber = Rails::HTML::SpaceBlockElementScrubber.new
+  end
+
+  def test_removes_all_tags_and_keeps_the_text_content_and_adds_spaces
+    assert_scrubbed %(<div><h1>A list!</h1><ul><li>An element!</li></ul><script>alert("hi!")</script></div>), "  A list!   An element!   "
+  end
+
+  def test_skips_text_nodes
+    assert_node_skipped("some text")
+  end
+end
+
 class ReturningStopFromScrubNodeTest < ScrubberTest
   class ScrubStopper < Rails::HTML::PermitScrubber
     def scrub_node(node)

From bd5ea3a5f6c6517fa664779456c485c816547478 Mon Sep 17 00:00:00 2001
From: Mike Dalessio <mike.dalessio@gmail.com>
Date: Sun, 19 May 2024 17:26:22 -0400
Subject: [PATCH 2/2] style: rubocop autocorrects

---
 lib/rails/html/scrubbers.rb | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/rails/html/scrubbers.rb b/lib/rails/html/scrubbers.rb
index 7afd7c0..e074e65 100644
--- a/lib/rails/html/scrubbers.rb
+++ b/lib/rails/html/scrubbers.rb
@@ -209,14 +209,14 @@ def initialize
       def scrub(node)
         if Loofah::Elements::LINEBREAKERS.include?(node.name)
           replacement = if Loofah::Elements::INLINE_LINE_BREAK.include?(node.name)
-                          " "
-                        else
-                          " #{node.content} "
-                        end
+            " "
+          else
+            " #{node.content} "
+          end
           node.add_next_sibling(Nokogiri::XML::Text.new(replacement, node.document))
           node.remove
         elsif node.text?
-          return CONTINUE
+          CONTINUE
         else
           node.before node.children
           node.remove