From f0878cda0f4b8b2432068489ee6da72a888b1a89 Mon Sep 17 00:00:00 2001 From: Julian KOUNE Date: Thu, 13 Jul 2023 16:06:17 +0200 Subject: [PATCH 1/2] fix: remove url markdown on messages This Closes #221 --- lib/pages/chat/events/message_content.dart | 3 +- lib/utils/string_extension.dart | 33 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/pages/chat/events/message_content.dart b/lib/pages/chat/events/message_content.dart index fee2ae9845..f64efacdd2 100644 --- a/lib/pages/chat/events/message_content.dart +++ b/lib/pages/chat/events/message_content.dart @@ -192,7 +192,8 @@ class MessageContent extends StatelessWidget { if (AppConfig.renderHtml && !event.redacted && event.isRichMessage) { - var html = event.formattedText; + var html = event.formattedText.unMarkdownLinks(event.text); + if (event.messageType == MessageTypes.Emote) { html = '* $html'; } diff --git a/lib/utils/string_extension.dart b/lib/utils/string_extension.dart index 652ca1a69c..4287f53e6f 100644 --- a/lib/utils/string_extension.dart +++ b/lib/utils/string_extension.dart @@ -89,4 +89,37 @@ extension StringCasingExtension on String { final String? firstValidLink = matches.firstWhere((link) => AnyLinkPreview.isValidLink(link!)); return firstValidLink; } + + // Removes markdowned links from a string based on the unformatted text + // Workaround for content['formatted_body'] which formats urls in a way that makes them unusable + String unMarkdownLinks(String unformattedText) { + final RegExp regex = RegExp(r'https:\/\/[^\s]+'); + + final Iterable formattedLinksMatches = regex.allMatches(this); + final Iterable unformattedLinksMatches = regex.allMatches(unformattedText); + + if (formattedLinksMatches.isEmpty || + unformattedLinksMatches.isEmpty || + formattedLinksMatches.length != unformattedLinksMatches.length) { + return this; + } + + var unMarkdownedText = this; + + final Iterator formattedIterator = formattedLinksMatches.iterator; + final Iterator unformattedIterator = unformattedLinksMatches.iterator; + + // Replace respectively all formatted links with unformatted links + while (formattedIterator.moveNext() && unformattedIterator.moveNext()) { + final Match formattedLinkMatch = formattedIterator.current; + final Match unformattedLinkMatch = unformattedIterator.current; + + final String formattedLink = formattedLinkMatch.group(0)!; + final String unformattedLink = unformattedLinkMatch.group(0)!; + + unMarkdownedText = unMarkdownedText.replaceFirst(formattedLink, unformattedLink); + } + + return unMarkdownedText; + } } From bef00c4944a785331bd165ef08bae49d1b4fb717 Mon Sep 17 00:00:00 2001 From: Julian KOUNE Date: Mon, 17 Jul 2023 19:54:15 +0200 Subject: [PATCH 2/2] test: add unmarkdownLinks tests --- test/string_extension_test.dart | 92 +++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/test/string_extension_test.dart b/test/string_extension_test.dart index 1b49b096fc..16d1e188ad 100644 --- a/test/string_extension_test.dart +++ b/test/string_extension_test.dart @@ -45,4 +45,96 @@ void main() { expect(result, isEmpty); }); + + test('unMarkdownLinks should replace links when there is only one link', () { + const unMarkdownMessageWithOnlyLink = "https://superman.com/this-is-a-*superman*-link"; + const markdownMessageWithOnlyLink = "https://superman.com/this-is-a-superman-link"; + + final result = markdownMessageWithOnlyLink.unMarkdownLinks(unMarkdownMessageWithOnlyLink); + + expect(result, equals(unMarkdownMessageWithOnlyLink)); + }); + + test('unMarkdownLinks should replace links when there are multiple links', () { + const unMarkdownMessageWith2Links = "https://superman.com/this-is-a-*superman*-link https://batman.com/this-is-a-*batman*-link"; + const markdownMessageWith2Links = "https://superman.com/this-is-a-superman-link https://batman.com/this-is-a-batman-link"; + + final result = markdownMessageWith2Links.unMarkdownLinks(unMarkdownMessageWith2Links); + + expect(result, equals(unMarkdownMessageWith2Links)); + }); + + test('unMarkdownLinks should replace links when there are links and text', () { + const unMarkdownMessageWithLinksAndTexts = "is this serious https://superman.com/this-is-a-*superman*-link hello guys https://batman.com/this-is-a-*batman*-link"; + const markdownMessageWithLinksAndTexts = "is this serious https://superman.com/this-is-a-superman-link hello guys https://batman.com/this-is-a-batman-link"; + + final result = markdownMessageWithLinksAndTexts.unMarkdownLinks(unMarkdownMessageWithLinksAndTexts); + expect(result, equals(unMarkdownMessageWithLinksAndTexts)); + }); + + test('unMarkdownLinks should replace links when there is link starting with text', () { + const unMarkdownMessageWithLinkStartingWithText = "is this serious https://superman.com/this-is-a-*superman*-link"; + const markdownMessageWithLinkStartingWithText = "is this serious https://superman.com/this-is-a-superman-link"; + + final result = markdownMessageWithLinkStartingWithText.unMarkdownLinks(unMarkdownMessageWithLinkStartingWithText); + expect(result, equals(unMarkdownMessageWithLinkStartingWithText)); + }); + + test('unMarkdownLinks should not replace links when the link is not valid', () { + const unMarkdownMessageWithUnvalidLink = "is this serious-https://superman.com/this-is-a-superman-link"; + const markdownMessageWithUnvalidLink = "is this serious-https://superman.com/this-is-a-superman-link"; + + final result = markdownMessageWithUnvalidLink.unMarkdownLinks(unMarkdownMessageWithUnvalidLink); + expect(result, equals(unMarkdownMessageWithUnvalidLink)); + }); + + test('unMarkdownLinks should return formatted text when there is no link', () { + const unMarkdownMessageWithNoLink = "hello guys"; + const markdownMessageWithNoLink = "hello guys"; + + final result = markdownMessageWithNoLink.unMarkdownLinks(unMarkdownMessageWithNoLink); + + expect(result, equals(unMarkdownMessageWithNoLink)); + }); + + test('unMarkdownLinks should replace links when there is link ending with text', () { + const unMarkdownMessageWithLinkEndingWithText = "https://superman.com/this-is-a-*superman*-link hello guys"; + const markdownMessageWithLinkEndingWithText = "https://superman.com/this-is-a-superman-link hello guys"; + + final result = markdownMessageWithLinkEndingWithText.unMarkdownLinks(unMarkdownMessageWithLinkEndingWithText); + expect(result, equals(unMarkdownMessageWithLinkEndingWithText)); + }); + + test('unMarkdownLinks should replace links when there is link ending with incomplete markdown', () { + const unMarkdownMessageWithIncompleteMarkdownLink = "https://superman.com/this-is-a-*supe hello guys"; + const markdownMessageWithIncompleteMarkdownLink = "https://superman.com/this-is-a-supe hello guys"; + + final result = markdownMessageWithIncompleteMarkdownLink.unMarkdownLinks(unMarkdownMessageWithIncompleteMarkdownLink); + expect(result, equals(unMarkdownMessageWithIncompleteMarkdownLink)); + }); + + test('unMarkdownLinks should replace links when there are text and unusable links', () { + const unMarkdownMessageWithUnusableLinks = "https://superman.com/this-is-a-*superman*-link hello guys https://bat"; + const markdownMessageWithUnusableLinks = "https://superman.com/this-is-a-superman-link hello guys https://bat"; + + final result = markdownMessageWithUnusableLinks.unMarkdownLinks(unMarkdownMessageWithUnusableLinks); + expect(result, equals(unMarkdownMessageWithUnusableLinks)); + }); + + test('unMarkdownLinks should replace links when there are markdown and unmarkdown links', () { + const unMarkdownMessageWithMarkdownAndUnMarkdownLinks = "https://superman.com/this-is-a-*superman*-link hello guys https://batman.com/this-"; + const markdownMessageWithMarkdownAndUnMarkdownLinks = "https://superman.com/this-is-a-superman-link hello guys https://batman.com/this-"; + + final result = markdownMessageWithMarkdownAndUnMarkdownLinks.unMarkdownLinks(unMarkdownMessageWithMarkdownAndUnMarkdownLinks); + expect(result, equals(unMarkdownMessageWithMarkdownAndUnMarkdownLinks)); + }); + + test('unMarkdownLinks should return formatted link when the unformatted text has no link', () { + const messageWithNoLinkUnMarkdowned = "hello guys"; + const messageWithNoLinkMarkdowned = "hello guys https://superman.com/this-is-a-*superman*-link"; + + final result = messageWithNoLinkMarkdowned.unMarkdownLinks(messageWithNoLinkUnMarkdowned); + + expect(result, equals(messageWithNoLinkMarkdowned)); + }); } \ No newline at end of file