Removed Type attribute from parsed local links (#16780)
* Removed type attribute from processed local links improved code readabilty by using multi return type to private class * Removed type attribute from processed locallinks in delivery api * Removed type attribute from expected output regarding locallink parsing * Cleanup * Fixed spacing bug * Added 2 more edge test cases --------- Co-authored-by: Elitsa <elm@umbraco.dk>
This commit is contained in:
@@ -35,11 +35,11 @@ public sealed class HtmlLocalLinkParser
|
||||
|
||||
public IEnumerable<Udi?> FindUdisFromLocalLinks(string text)
|
||||
{
|
||||
foreach ((var intId, GuidUdi? udi, var tagValue) in FindLocalLinkIds(text))
|
||||
foreach (LocalLinkTag tagData in FindLocalLinkIds(text))
|
||||
{
|
||||
if (udi is not null)
|
||||
if (tagData.Udi is not null)
|
||||
{
|
||||
yield return udi; // In v8, we only care abuot UDIs
|
||||
yield return tagData.Udi; // In v8, we only care about UDIs
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,38 +80,41 @@ public sealed class HtmlLocalLinkParser
|
||||
throw new InvalidOperationException("Could not parse internal links, there is no current UmbracoContext");
|
||||
}
|
||||
|
||||
foreach ((var intId, GuidUdi? udi, var tagValue) in FindLocalLinkIds(text))
|
||||
foreach (LocalLinkTag tagData in FindLocalLinkIds(text))
|
||||
{
|
||||
if (udi is not null)
|
||||
if (tagData.Udi is not null)
|
||||
{
|
||||
var newLink = "#";
|
||||
if (udi?.EntityType == Constants.UdiEntityType.Document)
|
||||
if (tagData.Udi?.EntityType == Constants.UdiEntityType.Document)
|
||||
{
|
||||
newLink = _publishedUrlProvider.GetUrl(udi.Guid);
|
||||
newLink = _publishedUrlProvider.GetUrl(tagData.Udi.Guid);
|
||||
}
|
||||
else if (udi?.EntityType == Constants.UdiEntityType.Media)
|
||||
else if (tagData.Udi?.EntityType == Constants.UdiEntityType.Media)
|
||||
{
|
||||
newLink = _publishedUrlProvider.GetMediaUrl(udi.Guid);
|
||||
newLink = _publishedUrlProvider.GetMediaUrl(tagData.Udi.Guid);
|
||||
}
|
||||
|
||||
if (newLink == null)
|
||||
{
|
||||
newLink = "#";
|
||||
}
|
||||
|
||||
text = text.Replace(tagValue, "href=\"" + newLink);
|
||||
text = StripTypeAttributeFromTag(text, tagData.Udi!.EntityType);
|
||||
text = text.Replace(tagData.TagHref, "href=\"" + newLink);
|
||||
}
|
||||
else if (intId.HasValue)
|
||||
else if (tagData.IntId.HasValue)
|
||||
{
|
||||
var newLink = _publishedUrlProvider.GetUrl(intId.Value);
|
||||
text = text.Replace(tagValue, "href=\"" + newLink);
|
||||
var newLink = _publishedUrlProvider.GetUrl(tagData.IntId.Value);
|
||||
text = text.Replace(tagData.TagHref, "href=\"" + newLink);
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private IEnumerable<(int? intId, GuidUdi? udi, string tagValue)> FindLocalLinkIds(string text)
|
||||
// under normal circumstances, the type attribute is preceded by a space
|
||||
// to cover the rare occasion where it isn't, we first replace with a a space and then without.
|
||||
private string StripTypeAttributeFromTag(string tag, string type) =>
|
||||
tag.Replace($" type=\"{type}\"", string.Empty)
|
||||
.Replace($"type=\"{type}\"", string.Empty);
|
||||
|
||||
private IEnumerable<LocalLinkTag> FindLocalLinkIds(string text)
|
||||
{
|
||||
MatchCollection localLinkTagMatches = LocalLinkTagPattern.Matches(text);
|
||||
foreach (Match linkTag in localLinkTagMatches)
|
||||
@@ -126,18 +129,22 @@ public sealed class HtmlLocalLinkParser
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return (null, new GuidUdi(linkTag.Groups["type"].Value, guid), linkTag.Groups["locallink"].Value);
|
||||
yield return new LocalLinkTag(
|
||||
null,
|
||||
new GuidUdi(linkTag.Groups["type"].Value, guid),
|
||||
linkTag.Groups["locallink"].Value,
|
||||
linkTag.Value);
|
||||
}
|
||||
|
||||
// also return legacy results for values that have not been migrated
|
||||
foreach ((int? intId, GuidUdi? udi, string tagValue) legacyResult in FindLegacyLocalLinkIds(text))
|
||||
foreach (LocalLinkTag legacyResult in FindLegacyLocalLinkIds(text))
|
||||
{
|
||||
yield return legacyResult;
|
||||
}
|
||||
}
|
||||
|
||||
// todo remove at some point?
|
||||
private IEnumerable<(int? intId, GuidUdi? udi, string tagValue)> FindLegacyLocalLinkIds(string text)
|
||||
private IEnumerable<LocalLinkTag> FindLegacyLocalLinkIds(string text)
|
||||
{
|
||||
// Parse internal links
|
||||
MatchCollection tags = LocalLinkPattern.Matches(text);
|
||||
@@ -153,15 +160,41 @@ public sealed class HtmlLocalLinkParser
|
||||
var guidUdi = udi as GuidUdi;
|
||||
if (guidUdi is not null)
|
||||
{
|
||||
yield return (null, guidUdi, tag.Value);
|
||||
yield return new LocalLinkTag(null, guidUdi, tag.Value, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
|
||||
{
|
||||
yield return (intId, null, tag.Value);
|
||||
yield return new LocalLinkTag (intId, null, tag.Value, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class LocalLinkTag
|
||||
{
|
||||
public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref)
|
||||
{
|
||||
IntId = intId;
|
||||
Udi = udi;
|
||||
TagHref = tagHref;
|
||||
}
|
||||
|
||||
public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref, string? fullTag)
|
||||
{
|
||||
IntId = intId;
|
||||
Udi = udi;
|
||||
TagHref = tagHref;
|
||||
FullTag = fullTag;
|
||||
}
|
||||
|
||||
public int? IntId { get; }
|
||||
|
||||
public GuidUdi? Udi { get; }
|
||||
|
||||
public string TagHref { get; }
|
||||
|
||||
public string? FullTag { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ internal sealed class ApiRichTextMarkupParser : ApiRichTextParserBase, IApiRichT
|
||||
link.SetAttributeValue("href", route.Path);
|
||||
link.SetAttributeValue("data-start-item-path", route.StartItem.Path);
|
||||
link.SetAttributeValue("data-start-item-id", route.StartItem.Id.ToString("D"));
|
||||
link.Attributes["type"]?.Remove();
|
||||
},
|
||||
url => link.SetAttributeValue("href", url),
|
||||
() => link.Attributes.Remove("href"));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
@@ -13,7 +12,6 @@ using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Templates;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
using Umbraco.Cms.Tests.UnitTests.TestHelpers.Objects;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Templates;
|
||||
|
||||
@@ -111,10 +109,16 @@ public class HtmlLocalLinkParserTests
|
||||
// current
|
||||
[TestCase(
|
||||
"<a type=\"document\" href=\"/{localLink:9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" title=\"world\">world</a>",
|
||||
"<a type=\"document\" href=\"/my-test-url\" title=\"world\">world</a>")]
|
||||
"<a href=\"/my-test-url\" title=\"world\">world</a>")]
|
||||
[TestCase(
|
||||
"<a type=\"media\" href=\"/{localLink:9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" title=\"world\">world</a>",
|
||||
"<a type=\"media\" href=\"/media/1001/my-image.jpg\" title=\"world\">world</a>")]
|
||||
"<a href=\"/media/1001/my-image.jpg\" title=\"world\">world</a>")]
|
||||
[TestCase(
|
||||
"<a href=\"/{localLink:9931BDE0-AAC3-4BAB-B838-909A7B47570E}\"type=\"document\" title=\"world\">world</a>",
|
||||
"<a href=\"/my-test-url\" title=\"world\">world</a>")]
|
||||
[TestCase(
|
||||
"<a href=\"/{localLink:9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" title=\"world\"type=\"media\">world</a>",
|
||||
"<a href=\"/media/1001/my-image.jpg\" title=\"world\">world</a>")]
|
||||
// legacy
|
||||
[TestCase(
|
||||
"hello href=\"{localLink:1234}\" world ",
|
||||
|
||||
@@ -72,8 +72,8 @@ public class ApiRichTextMarkupParserTests
|
||||
<p>and to the <a type=""document"" href=""/{localLink:cc143afe-4cbf-46e5-b399-c9f451384373}"" title=""other page"">other page</a></p>";
|
||||
|
||||
var expectedOutput =
|
||||
@"<p>Rich text outside of the blocks with a link to <a type=""document"" href=""/self/"" title=""itself"" data-start-item-path=""self"" data-start-item-id=""eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f"">itself</a><br><br></p>
|
||||
<p>and to the <a type=""document"" href=""/other/"" title=""other page"" data-start-item-path=""other"" data-start-item-id=""cc143afe-4cbf-46e5-b399-c9f451384373"">other page</a></p>";
|
||||
@"<p>Rich text outside of the blocks with a link to <a href=""/self/"" title=""itself"" data-start-item-path=""self"" data-start-item-id=""eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f"">itself</a><br><br></p>
|
||||
<p>and to the <a href=""/other/"" title=""other page"" data-start-item-path=""other"" data-start-item-id=""cc143afe-4cbf-46e5-b399-c9f451384373"">other page</a></p>";
|
||||
|
||||
var parsedHtml = parser.Parse(html);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user