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", "
First
second
", "

One

Two

", + "", "
Quoted
", + "
one\n  two
", "
onetwo
", + "
Unclosed", "😄🤘", "
Hi #{mention_attachment_for(:david)}
" ] + bodies.each do |html| + message = Message.new(body: html) + assert_equal message.body.to_plain_text, message.plain_text_body, html.inspect + end + end + + test "plain text follows body replacement and does not expose mutable cached text" do + message = Message.new(body: "

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: "
Hey #{mention_attachment_for(:david)}
", creator: users(:jason), client_message_id: "earth" assert_equal [ users(:david) ], message.mentionees