diff --git a/app/lib/advanced_text_formatter.rb b/app/lib/advanced_text_formatter.rb
index 3ba4c92be37585..0d5ddf9731f281 100644
--- a/app/lib/advanced_text_formatter.rb
+++ b/app/lib/advanced_text_formatter.rb
@@ -98,6 +98,8 @@ def rewrite
private
def format_markdown(html)
+ # Force escape underscores in mentions, custom emojis and hashtags before formatting
+ html = html.gsub(/#{Account::MENTION_RE}|#{CustomEmoji::SCAN_RE}|#{Tag::HASHTAG_RE}/o) { |re| re.gsub('_', '\\_') }
html = markdown_formatter.render(html)
html.delete("\r").delete("\n")
end
diff --git a/spec/lib/advanced_text_formatter_spec.rb b/spec/lib/advanced_text_formatter_spec.rb
index f92385219615fe..465f508b9dd427 100644
--- a/spec/lib/advanced_text_formatter_spec.rb
+++ b/spec/lib/advanced_text_formatter_spec.rb
@@ -75,6 +75,15 @@
it 'creates a mention link' do
expect(subject).to include '@alice'
end
+
+ context 'when username contains underscores' do
+ let(:preloaded_accounts) { [Fabricate(:account, username: '_bob_')] }
+ let(:text) { '@_bob_' }
+
+ it 'creates a mention link' do
+ expect(subject).to include '@_bob_'
+ end
+ end
end
context 'with text containing unlinkable mentions' do
@@ -272,6 +281,14 @@
end
end
+ context 'with text containing a hashtag with underscores' do
+ let(:text) { '#_hashtag_' }
+
+ it 'creates a hashtag link' do
+ expect(subject).to include '/tags/_hashtag_" class="mention hashtag" rel="tag">#_hashtag_'
+ end
+ end
+
context 'with text with a stand-alone xmpp: URI' do
let(:text) { 'xmpp:user@instance.com' }