diff --git a/app/models/message.rb b/app/models/message.rb index 5d019b5..2f65888 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -21,7 +21,15 @@ class Message < ApplicationRecord scope :with_presentation, -> { with_creator.with_attachment_details.with_boosts.preload(:room) } def plain_text_body - body.to_plain_text.presence || attachment&.filename&.to_s || "" + content = body.body + text = if content && content.fragment.find_all(ActionText::Attachment.tag_name).empty? + # ActionText::Content#to_plain_text duplicates the fragment to replace + # attachments. Without them, reuse its native Fragment conversion instead. + content.fragment.to_plain_text.dup + else + body.to_plain_text + end + text.presence || attachment&.filename&.to_s || "" end def content_type diff --git a/test/models/message_test.rb b/test/models/message_test.rb index a5b73f0..533b1f8 100644 --- a/test/models/message_test.rb +++ b/test/models/message_test.rb @@ -17,6 +17,28 @@ class MessageTest < ActiveSupport::TestCase assert_not Message.new(body: "🔥 💯").plain_text_body.all_emoji? end + test "plain text keeps Action Text formatting and attachment conversion" do + bodies = [ nil, "", "Hello & goodbye", "
One
Two
", + "Quoted", + "
one\n two", "| one | two |
First
") + message.plain_text_body.replace("Caller edit") + assert_equal "First", message.plain_text_body + message.body = "Replacement
" + assert_equal "Replacement", message.plain_text_body + message = messages(:first) + message.update!(body: "Reloaded body
") + assert_equal message.body.to_plain_text, message.reload.plain_text_body + end + test "mentionees" do message = Message.new room: rooms(:pets), body: "