From f04add6d9edda7bbdf080adc7e6959ee16e6f222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 4 Sep 2019 00:01:26 +0200 Subject: [PATCH] Add bracket handling to Markdown link format Allow users to put both balanced brackets, as well as unbalanced escaped ones, in Markdown link text. The implementation is the exact same as in the case of new format links. For completion's sake, tests also included. --- osu.Game.Tests/Chat/MessageFormatterTests.cs | 47 +++++++++++++++++++ .../Visual/Online/TestSceneChatLink.cs | 1 + osu.Game/Online/Chat/MessageFormatter.cs | 4 +- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Chat/MessageFormatterTests.cs b/osu.Game.Tests/Chat/MessageFormatterTests.cs index 1de6280531..198267d78a 100644 --- a/osu.Game.Tests/Chat/MessageFormatterTests.cs +++ b/osu.Game.Tests/Chat/MessageFormatterTests.cs @@ -179,6 +179,53 @@ public void TestMarkdownFormatLink() Assert.AreEqual(11, result.Links[0].Length); } + [Test] + public void TestMarkdownFormatLinkWithBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [tricky [one]](https://osu.ppy.sh)!" }); + + Assert.AreEqual("This is a tricky [one]!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(12, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithEscapedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is [another loose bracket \\]](https://osu.ppy.sh)." }); + + Assert.AreEqual("This is another loose bracket ].", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(8, result.Links[0].Index); + Assert.AreEqual(23, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatWithBackslashes() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This link [should end with a backslash \\](https://osu.ppy.sh)." }); + Assert.AreEqual("This link should end with a backslash \\.", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(29, result.Links[0].Length); + } + + [Test] + public void TestMarkdownFormatLinkWithEscapedAndBalancedBrackets() + { + Message result = MessageFormatter.FormatMessage(new Message { Content = "This is a [\\]super\\[\\[ tricky [one]](https://osu.ppy.sh)!" }); + + Assert.AreEqual("This is a ]super[[ tricky [one]!", result.DisplayContent); + Assert.AreEqual(1, result.Links.Count); + Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url); + Assert.AreEqual(10, result.Links[0].Index); + Assert.AreEqual(21, result.Links[0].Length); + } + [Test] public void TestChannelLink() { diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs index 056ccafe79..61c7d3f5b6 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneChatLink.cs @@ -128,6 +128,7 @@ private void testLinksGeneral() addMessageWithChecks("Let's (try)[https://osu.ppy.sh/home] [https://osu.ppy.sh/b/252238 multiple links] https://osu.ppy.sh/home", 3, expectedActions: new[] { LinkAction.External, LinkAction.OpenBeatmap, LinkAction.External }); addMessageWithChecks("[https://osu.ppy.sh/home New link format with escaped [and \\[ paired] braces]", expectedActions: LinkAction.External); + addMessageWithChecks("[Markdown link format with escaped [and \\[ paired] braces](https://osu.ppy.sh/home)", expectedActions: LinkAction.External); // note that there's 0 links here (they get removed if a channel is not found) addMessageWithChecks("#lobby or #osu would be blue (and work) in the ChatDisplay test (when a proper ChatOverlay is present)."); addMessageWithChecks("I am important!", 0, false, true); diff --git a/osu.Game/Online/Chat/MessageFormatter.cs b/osu.Game/Online/Chat/MessageFormatter.cs index 23b5cdc0a6..e40bb05381 100644 --- a/osu.Game/Online/Chat/MessageFormatter.cs +++ b/osu.Game/Online/Chat/MessageFormatter.cs @@ -20,7 +20,7 @@ public static class MessageFormatter private static readonly Regex new_link_regex = new Regex(@"\[(?[a-z]+://[^ ]+) (?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]"); // [test](https://osu.ppy.sh/b/1234) -> test (https://osu.ppy.sh/b/1234) aka correct markdown format - private static readonly Regex markdown_link_regex = new Regex(@"\[(?[^\]]*)\]\((?[a-z]+://[^ ]+)\)"); + private static readonly Regex markdown_link_regex = new Regex(@"\[(?(((?<=\\)[\[\]])|[^\[\]])*(((?\[)(((?<=\\)[\[\]])|[^\[\]])*)+((?\])(((?<=\\)[\[\]])|[^\[\]])*)+)*(?(open)(?!)))\]\((?[a-z]+://[^ ]+)\)"); // advanced, RFC-compatible regular expression that matches any possible URL, *but* allows certain invalid characters that are widely used // This is in the format (, [optional]): @@ -191,7 +191,7 @@ private static MessageFormatterResult format(string toFormat, int startIndex = 0 handleMatches(new_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the standard markdown []() format - handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex); + handleMatches(markdown_link_regex, "{1}", "{2}", result, startIndex, escapeChars: new[] { '[', ']' }); // handle the ()[] link format handleMatches(old_link_regex, "{1}", "{2}", result, startIndex);