Resolve link-in-link edge case

Testing with #6542 surfaced a crash scenario, caused by formatted links
that had URLs in the display text, for example

    [mean example - https://osu.ppy.sh](https://osu.ppy.sh)

In that case the outer Markdown link would get picked up once, and then
reduced to the link text when looking for other links, leading to it
being picked up again the second time when the raw link is found.

Add a check in the raw link parsing path that ensures that the found
URL is not a part of a bigger, pre-existing link.
This commit is contained in:
Bartłomiej Dach 2019-10-22 01:01:37 +02:00
parent 24b7160522
commit cbd99cc767
2 changed files with 25 additions and 5 deletions

View File

@ -309,6 +309,18 @@ public void TestMarkdownFormatLinkWithUrlInTextAndInlineTitle()
Assert.AreEqual(18, result.Links[0].Length);
}
[Test]
public void TestMarkdownFormatLinkWithUrlAndTextInTitle()
{
Message result = MessageFormatter.FormatMessage(new Message { Content = "I haven't seen [oh no, text here! https://osu.ppy.sh](https://osu.ppy.sh) before..." });
Assert.AreEqual("I haven't seen oh no, text here! https://osu.ppy.sh before...", result.DisplayContent);
Assert.AreEqual(1, result.Links.Count);
Assert.AreEqual("https://osu.ppy.sh", result.Links[0].Url);
Assert.AreEqual(15, result.Links[0].Index);
Assert.AreEqual(36, result.Links[0].Length);
}
[Test]
public void TestMarkdownFormatLinkWithMisleadingUrlInText()
{

View File

@ -1,4 +1,4 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
@ -95,11 +95,17 @@ private static void handleAdvanced(Regex regex, MessageFormatterResult result, i
foreach (Match m in regex.Matches(result.Text, startIndex))
{
var index = m.Index;
var link = m.Groups["link"].Value;
var indexLength = link.Length;
var linkText = m.Groups["link"].Value;
var indexLength = linkText.Length;
var details = getLinkDetails(link);
result.Links.Add(new Link(link, index, indexLength, details.Action, details.Argument));
var details = getLinkDetails(linkText);
var link = new Link(linkText, index, indexLength, details.Action, details.Argument);
// sometimes an already-processed formatted link can reduce to a simple URL, too
// (example: [mean example - https://osu.ppy.sh](https://osu.ppy.sh))
// therefore we need to check if any of the pre-existing links contains the raw one we found
if (result.Links.All(existingLink => !existingLink.Contains(link)))
result.Links.Add(link);
}
}
@ -292,6 +298,8 @@ public Link(string url, int startIndex, int length, LinkAction action, string ar
Argument = argument;
}
public bool Contains(Link otherLink) => otherLink.Index >= Index && otherLink.Index + otherLink.Length <= Index + Length;
public int CompareTo(Link otherLink) => Index > otherLink.Index ? 1 : -1;
}
}