diff --git a/app/helpers/html_helper.rb b/app/helpers/html_helper.rb index a3d0bbab3..7b1b2b298 100644 --- a/app/helpers/html_helper.rb +++ b/app/helpers/html_helper.rb @@ -1,5 +1,30 @@ module HtmlHelper def format_html(html) - Loofah::HTML5::DocumentFragment.parse(html).scrub!(AutoLinkScrubber.new).to_html.html_safe + fragment = Loofah::HTML5::DocumentFragment.parse(html).scrub!(AutoLinkScrubber.new) + wrap_tables(fragment) + fragment.to_html.html_safe end + + private + def wrap_tables(fragment) + # Collect tables first to avoid modifying the collection while iterating + tables = fragment.css("table").to_a + + tables.each do |table| + # Skip if already wrapped in a table-wrapper div + parent = table.parent + next if parent&.name == "div" && parent["class"]&.include?("table-wrapper") + + # Save a copy of the table before replacing + table_copy = table.dup + + # Create wrapper div + wrapper = Nokogiri::XML::Node.new("div", fragment.document) + wrapper["class"] = "table-wrapper" + wrapper.add_child(table_copy) + + # Replace the original table with the wrapper (which contains the copied table) + table.replace(wrapper) + end + end end diff --git a/test/helpers/html_helper_test.rb b/test/helpers/html_helper_test.rb index 1af507ddf..8880fbacc 100644 --- a/test/helpers/html_helper_test.rb +++ b/test/helpers/html_helper_test.rb @@ -119,4 +119,26 @@ class HtmlHelperTest < ActionView::TestCase assert_no_match(/
test
), + format_html("
test
") + end + + test "wrap multiple tables in separate table-wrapper divs" do + html = "
first

text

second
" + output = format_html(html) + + assert_match(/
.*?first.*?<\/table><\/div>/, output) + assert_match(/
.*?second.*?<\/table><\/div>/, output) + end + + test "don't wrap tables that are already wrapped" do + html = %(
test
) + output = format_html(html) + + # Should not create nested wrappers + assert_equal 1, output.scan(/class="table-wrapper"/).length + end end