From 4b4f64498742389621fb58b23d5afbc690fd054c Mon Sep 17 00:00:00 2001 From: MiguelGuedelha Date: Sat, 15 Nov 2025 22:53:54 +0000 Subject: [PATCH 1/3] add content key and type to link info on RTE delivery API data. Fix tests to accomodate changes --- .../DeliveryApi/ApiRichTextElementParser.cs | 3 ++- .../DeliveryApi/ApiRichTextMarkupParser.cs | 5 ++++- .../DeliveryApi/ApiRichTextParserBase.cs | 10 +++++----- .../DeliveryApi/RichTextParserTests.cs | 19 ++++++++++++++++--- .../ApiRichTextMarkupParserTests.cs | 10 +++++----- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs index b54976ff4067..45e49890b3d4 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs @@ -143,8 +143,9 @@ private void ReplaceLocalLinks(IPublishedContentCache contentCache, IPublishedMe mediaCache, href, type, - route => + (route, contentId) => { + attributes["content-id"] = contentId; attributes["route"] = route; attributes.Remove("href"); }, diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs index 3712a4b6c5cc..cbec62dc04ac 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs @@ -58,17 +58,20 @@ private void ReplaceLocalLinks(HtmlDocument doc, IPublishedContentCache contentC mediaCache, link.GetAttributeValue("href", string.Empty), link.GetAttributeValue("type", "unknown"), - route => + (route, contentId) => { link.SetAttributeValue("href", $"{route.Path}{route.QueryString}"); + link.SetAttributeValue("data-content-id", contentId.ToString("D")); link.SetAttributeValue("data-start-item-path", route.StartItem.Path); link.SetAttributeValue("data-start-item-id", route.StartItem.Id.ToString("D")); link.Attributes["type"]?.Remove(); + link.SetAttributeValue("data-content-type", Constants.UdiEntityType.Document); }, url => { link.SetAttributeValue("href", url); link.Attributes["type"]?.Remove(); + link.SetAttributeValue("data-content-type", Constants.UdiEntityType.Media); }, () => { diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextParserBase.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextParserBase.cs index d1cf1b5b3ae8..64a55ba3d3d3 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextParserBase.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextParserBase.cs @@ -21,7 +21,7 @@ protected ApiRichTextParserBase(IApiContentRouteBuilder apiContentRouteBuilder, _apiMediaUrlProvider = apiMediaUrlProvider; } - protected void ReplaceLocalLinks(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, string type, Action handleContentRoute, Action handleMediaUrl, Action handleInvalidLink) + protected void ReplaceLocalLinks(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, string type, Action handleContentRoute, Action handleMediaUrl, Action handleInvalidLink) { ReplaceStatus replaceAttempt = ReplaceLocalLink(contentCache, mediaCache, href, type, handleContentRoute, handleMediaUrl); if (replaceAttempt == ReplaceStatus.Success) @@ -35,7 +35,7 @@ protected void ReplaceLocalLinks(IPublishedContentCache contentCache, IPublished } } - private ReplaceStatus ReplaceLocalLink(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, string type, Action handleContentRoute, Action handleMediaUrl) + private ReplaceStatus ReplaceLocalLink(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, string type, Action handleContentRoute, Action handleMediaUrl) { Match match = LocalLinkRegex().Match(href); if (match.Success is false) @@ -60,7 +60,7 @@ private ReplaceStatus ReplaceLocalLink(IPublishedContentCache contentCache, IPub if (route != null) { route.QueryString = match.Groups["query"].Value.NullOrWhiteSpaceAsNull(); - handleContentRoute(route); + handleContentRoute(route, guid); return ReplaceStatus.Success; } @@ -79,7 +79,7 @@ private ReplaceStatus ReplaceLocalLink(IPublishedContentCache contentCache, IPub return ReplaceStatus.InvalidEntityType; } - private ReplaceStatus ReplaceLegacyLocalLink(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, Action handleContentRoute, Action handleMediaUrl) + private ReplaceStatus ReplaceLegacyLocalLink(IPublishedContentCache contentCache, IPublishedMediaCache mediaCache, string href, Action handleContentRoute, Action handleMediaUrl) { Match match = LegacyLocalLinkRegex().Match(href); if (match.Success is false) @@ -108,7 +108,7 @@ private ReplaceStatus ReplaceLegacyLocalLink(IPublishedContentCache contentCache if (route != null) { route.QueryString = match.Groups["query"].Value.NullOrWhiteSpaceAsNull(); - handleContentRoute(route); + handleContentRoute(route, guidUdi.Guid); return ReplaceStatus.Success; } diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs index 2acab6caced3..be00af45f555 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs @@ -141,9 +141,12 @@ public void ParseElement_CanParseContentLink(string? postfix) var link = element.Elements.OfType().Single().Elements.Single() as RichTextGenericElement; Assert.IsNotNull(link); Assert.AreEqual("a", link.Tag); - Assert.AreEqual(1, link.Attributes.Count); - Assert.AreEqual("route", link.Attributes.First().Key); - var route = link.Attributes.First().Value as IApiContentRoute; + Assert.AreEqual(2, link.Attributes.Count); + Assert.IsNotNull(link.Attributes["route"]); + Assert.IsNotNull(link.Attributes["content-id"]); + var id = (Guid)link.Attributes["content-id"]; + Assert.AreEqual(_contentKey, id); + var route = link.Attributes["route"] as IApiContentRoute; Assert.IsNotNull(route); Assert.AreEqual("/some-content-path", route.Path); Assert.AreEqual(postfix.NullOrWhiteSpaceAsNull(), route.QueryString); @@ -482,8 +485,10 @@ public void ParseMarkup_CanParseContentLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-content-path\"")); + Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); + Assert.IsTrue(result.Contains("data-content-type=\"document\"")); } [Test] @@ -493,8 +498,10 @@ public void ParseMarkup_CanParseLegacyContentLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-content-path\"")); + Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); + Assert.IsTrue(result.Contains("data-content-type=\"document\"")); } [TestCase("#some-anchor")] @@ -507,8 +514,10 @@ public void ParseMarkup_CanParseContentLink_WithPostfix(string postfix) var result = parser.Parse($"

"); Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\"")); + Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); + Assert.IsTrue(result.Contains("data-content-type=\"document\"")); } [TestCase("#some-anchor")] @@ -521,8 +530,10 @@ public void ParseMarkup_CanParseLegacyContentLink_WithPostfix(string postfix) var result = parser.Parse($"

"); Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\"")); + Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); + Assert.IsTrue(result.Contains("data-content-type=\"document\"")); } [Test] @@ -532,6 +543,8 @@ public void ParseMarkup_CanParseMediaLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-media-url\"")); + Assert.IsTrue(result.Contains("data-content-type=\"media\"")); + } [TestCase("{localLink:umb://document/fe5bf80d37db4373adb9b206896b4a3b}")] diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs index 90e8e11df262..236d443ac62c 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs @@ -36,7 +36,7 @@ public void Can_Parse_Legacy_LocalLinks() "

link to another page

"; var expectedOutput = - "

link to another page

"; + $"

link to another page

"; var parsedHtml = parser.Parse(legacyHtml); @@ -71,8 +71,8 @@ public void Can_Parse_LocalLinks()

and to the other page

"; var expectedOutput = - @"

Rich text outside of the blocks with a link to itself

-

and to the other page

"; + $@"

Rich text outside of the blocks with a link to itself

+

and to the other page

"; var parsedHtml = parser.Parse(html); @@ -110,8 +110,8 @@ public void Can_Parse_LocalLinks_With_Postfix(string postfix)

and to the other page

"; var expectedOutput = - $@"

Rich text outside of the blocks with a link to itself

-

and to the other page

"; + $@"

Rich text outside of the blocks with a link to itself

+

and to the other page

"; var parsedHtml = parser.Parse(html); From ba31bacd77cd768b01733c16f720fb673c3e659b Mon Sep 17 00:00:00 2001 From: MiguelGuedelha Date: Mon, 17 Nov 2025 18:16:20 +0000 Subject: [PATCH 2/3] convert field type content-id -> destination-id. convert field type content-type -> link-type and use LinkType enum instead. --- .../DeliveryApi/ApiRichTextElementParser.cs | 4 +- .../DeliveryApi/ApiRichTextMarkupParser.cs | 9 ++-- .../DeliveryApi/RichTextParserTests.cs | 43 ++++++++++--------- .../ApiRichTextMarkupParserTests.cs | 11 ++--- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs index 45e49890b3d4..f6cfe1b233c0 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs @@ -145,7 +145,7 @@ private void ReplaceLocalLinks(IPublishedContentCache contentCache, IPublishedMe type, (route, contentId) => { - attributes["content-id"] = contentId; + attributes["destination-id"] = contentId; attributes["route"] = route; attributes.Remove("href"); }, @@ -179,7 +179,7 @@ private static void CleanUpBlocks(string tag, Dictionary attribu return; } - attributes["content-id"] = key; + attributes["destination-id"] = key; attributes.Remove(BlockContentKeyAttribute); } diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs index cbec62dc04ac..50239d16340c 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging; using Umbraco.Cms.Core; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Extensions; @@ -61,17 +62,17 @@ private void ReplaceLocalLinks(HtmlDocument doc, IPublishedContentCache contentC (route, contentId) => { link.SetAttributeValue("href", $"{route.Path}{route.QueryString}"); - link.SetAttributeValue("data-content-id", contentId.ToString("D")); + link.SetAttributeValue("data-destination-id", contentId.ToString("D")); link.SetAttributeValue("data-start-item-path", route.StartItem.Path); link.SetAttributeValue("data-start-item-id", route.StartItem.Id.ToString("D")); link.Attributes["type"]?.Remove(); - link.SetAttributeValue("data-content-type", Constants.UdiEntityType.Document); + link.SetAttributeValue("data-link-type", nameof(LinkType.Content)); }, url => { link.SetAttributeValue("href", url); link.Attributes["type"]?.Remove(); - link.SetAttributeValue("data-content-type", Constants.UdiEntityType.Media); + link.SetAttributeValue("data-link-type", nameof(LinkType.Media)); }, () => { @@ -123,7 +124,7 @@ private void CleanUpBlocks(HtmlDocument doc) // swap the content UDI for the content ID block.Attributes.Remove(BlockContentKeyAttribute); - block.SetAttributeValue("data-content-id", key.ToString("D")); + block.SetAttributeValue("data-destination-id", key.ToString("D")); // remove the inner comment placed by the RTE block.RemoveAllChildren(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs index be00af45f555..71811ac0350e 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.Blocks; using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; @@ -143,8 +144,8 @@ public void ParseElement_CanParseContentLink(string? postfix) Assert.AreEqual("a", link.Tag); Assert.AreEqual(2, link.Attributes.Count); Assert.IsNotNull(link.Attributes["route"]); - Assert.IsNotNull(link.Attributes["content-id"]); - var id = (Guid)link.Attributes["content-id"]; + Assert.IsNotNull(link.Attributes["destination-id"]); + var id = (Guid)link.Attributes["destination-id"]; Assert.AreEqual(_contentKey, id); var route = link.Attributes["route"] as IApiContentRoute; Assert.IsNotNull(route); @@ -291,8 +292,8 @@ public void ParseElement_CleansUpBlocks(bool inlineBlock) Assert.IsNotNull(block); Assert.AreEqual(tagName, block.Tag); Assert.AreEqual(1, block.Attributes.Count); - Assert.IsTrue(block.Attributes.ContainsKey("content-id")); - Assert.AreEqual(id, block.Attributes["content-id"]); + Assert.IsTrue(block.Attributes.ContainsKey("destination-id")); + Assert.AreEqual(id, block.Attributes["destination-id"]); Assert.IsEmpty(block.Elements); } @@ -329,12 +330,12 @@ public void ParseElement_AppendsBlocks(bool inlineBlock) var block1Element = paragraph.Elements.First() as RichTextGenericElement; Assert.IsNotNull(block1Element); Assert.AreEqual(tagName, block1Element.Tag); - Assert.AreEqual(block1ContentId, block1Element.Attributes["content-id"]); + Assert.AreEqual(block1ContentId, block1Element.Attributes["destination-id"]); var block2Element = paragraph.Elements.Last() as RichTextGenericElement; Assert.IsNotNull(block2Element); Assert.AreEqual(tagName, block2Element.Tag); - Assert.AreEqual(block2ContentId, block2Element.Attributes["content-id"]); + Assert.AreEqual(block2ContentId, block2Element.Attributes["destination-id"]); Assert.AreEqual(2, element.Blocks.Count()); @@ -368,16 +369,16 @@ public void ParseElement_CanHandleMixedInlineAndBlockLevelBlocks() Assert.IsNotNull(inlineBlock); Assert.AreEqual("umb-rte-block-inline", inlineBlock.Tag); Assert.AreEqual(1, inlineBlock.Attributes.Count); - Assert.IsTrue(inlineBlock.Attributes.ContainsKey("content-id")); - Assert.AreEqual(id1, inlineBlock.Attributes["content-id"]); + Assert.IsTrue(inlineBlock.Attributes.ContainsKey("destination-id")); + Assert.AreEqual(id1, inlineBlock.Attributes["destination-id"]); Assert.IsEmpty(inlineBlock.Elements); var blockLevelBlock = element.Elements.Last() as RichTextGenericElement; Assert.IsNotNull(blockLevelBlock); Assert.AreEqual("umb-rte-block", blockLevelBlock.Tag); Assert.AreEqual(1, blockLevelBlock.Attributes.Count); - Assert.IsTrue(blockLevelBlock.Attributes.ContainsKey("content-id")); - Assert.AreEqual(id2, blockLevelBlock.Attributes["content-id"]); + Assert.IsTrue(blockLevelBlock.Attributes.ContainsKey("destination-id")); + Assert.AreEqual(id2, blockLevelBlock.Attributes["destination-id"]); Assert.IsEmpty(blockLevelBlock.Elements); } @@ -485,10 +486,10 @@ public void ParseMarkup_CanParseContentLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-content-path\"")); - Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); + Assert.IsTrue(result.Contains($"data-destination-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); - Assert.IsTrue(result.Contains("data-content-type=\"document\"")); + Assert.IsTrue(result.Contains($"data-link-type=\"{LinkType.Content}\"")); } [Test] @@ -498,10 +499,10 @@ public void ParseMarkup_CanParseLegacyContentLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-content-path\"")); - Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); + Assert.IsTrue(result.Contains($"data-destination-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); - Assert.IsTrue(result.Contains("data-content-type=\"document\"")); + Assert.IsTrue(result.Contains($"data-link-type=\"{LinkType.Content}\"")); } [TestCase("#some-anchor")] @@ -514,10 +515,10 @@ public void ParseMarkup_CanParseContentLink_WithPostfix(string postfix) var result = parser.Parse($"

"); Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\"")); - Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); + Assert.IsTrue(result.Contains($"data-destination-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); - Assert.IsTrue(result.Contains("data-content-type=\"document\"")); + Assert.IsTrue(result.Contains($"data-link-type=\"{LinkType.Content}\"")); } [TestCase("#some-anchor")] @@ -530,10 +531,10 @@ public void ParseMarkup_CanParseLegacyContentLink_WithPostfix(string postfix) var result = parser.Parse($"

"); Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\"")); - Assert.IsTrue(result.Contains($"data-content-id=\"{_contentKey:D}\"")); + Assert.IsTrue(result.Contains($"data-destination-id=\"{_contentKey:D}\"")); Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\"")); Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\"")); - Assert.IsTrue(result.Contains("data-content-type=\"document\"")); + Assert.IsTrue(result.Contains($"data-link-type=\"{LinkType.Content}\"")); } [Test] @@ -543,7 +544,7 @@ public void ParseMarkup_CanParseMediaLink() var result = parser.Parse($"

"); Assert.IsTrue(result.Contains("href=\"/some-media-url\"")); - Assert.IsTrue(result.Contains("data-content-type=\"media\"")); + Assert.IsTrue(result.Contains($"data-link-type=\"{LinkType.Media}\"")); } @@ -608,7 +609,7 @@ public void ParseMarkup_CleansUpBlocks(bool inlineBlock) var tagName = $"umb-rte-block{(inlineBlock ? "-inline" : string.Empty)}"; var result = parser.Parse($"

<{tagName} data-content-key=\"{id:N}\">

"); - Assert.AreEqual($"

<{tagName} data-content-id=\"{id:D}\">

", result); + Assert.AreEqual($"

<{tagName} data-destination-id=\"{id:D}\">

", result); } [Test] @@ -619,7 +620,7 @@ public void ParseMarkup_CanHandleMixedInlineAndBlockLevelBlocks() var id2 = Guid.NewGuid(); var result = parser.Parse($"

"); - Assert.AreEqual($"

", result); + Assert.AreEqual($"

", result); } private ApiRichTextElementParser CreateRichTextElementParser() diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs index 236d443ac62c..e03a0bc9e0b8 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParserTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Umbraco.Cms.Core; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.DeliveryApi; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; @@ -36,7 +37,7 @@ public void Can_Parse_Legacy_LocalLinks() "

link to another page

"; var expectedOutput = - $"

link to another page

"; + $"

link to another page

"; var parsedHtml = parser.Parse(legacyHtml); @@ -71,8 +72,8 @@ public void Can_Parse_LocalLinks()

and to the other page

"; var expectedOutput = - $@"

Rich text outside of the blocks with a link to itself

-

and to the other page

"; + $@"

Rich text outside of the blocks with a link to itself

+

and to the other page

"; var parsedHtml = parser.Parse(html); @@ -110,8 +111,8 @@ public void Can_Parse_LocalLinks_With_Postfix(string postfix)

and to the other page

"; var expectedOutput = - $@"

Rich text outside of the blocks with a link to itself

-

and to the other page

"; + $@"

Rich text outside of the blocks with a link to itself

+

and to the other page

"; var parsedHtml = parser.Parse(html); From 7ad2c3d7ed106df81f2d0d3824360721898f527c Mon Sep 17 00:00:00 2001 From: MiguelGuedelha Date: Mon, 17 Nov 2025 18:23:27 +0000 Subject: [PATCH 3/3] revert unintended find and replace changes --- .../DeliveryApi/ApiRichTextElementParser.cs | 2 +- .../DeliveryApi/ApiRichTextMarkupParser.cs | 2 +- .../DeliveryApi/RichTextParserTests.cs | 20 +++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs index f6cfe1b233c0..02a3d323c7cb 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextElementParser.cs @@ -179,7 +179,7 @@ private static void CleanUpBlocks(string tag, Dictionary attribu return; } - attributes["destination-id"] = key; + attributes["content-id"] = key; attributes.Remove(BlockContentKeyAttribute); } diff --git a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs index 50239d16340c..95dbd8a1c7d9 100644 --- a/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs +++ b/src/Umbraco.Infrastructure/DeliveryApi/ApiRichTextMarkupParser.cs @@ -124,7 +124,7 @@ private void CleanUpBlocks(HtmlDocument doc) // swap the content UDI for the content ID block.Attributes.Remove(BlockContentKeyAttribute); - block.SetAttributeValue("data-destination-id", key.ToString("D")); + block.SetAttributeValue("data-content-id", key.ToString("D")); // remove the inner comment placed by the RTE block.RemoveAllChildren(); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs index 71811ac0350e..de634f3df36d 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/DeliveryApi/RichTextParserTests.cs @@ -292,8 +292,8 @@ public void ParseElement_CleansUpBlocks(bool inlineBlock) Assert.IsNotNull(block); Assert.AreEqual(tagName, block.Tag); Assert.AreEqual(1, block.Attributes.Count); - Assert.IsTrue(block.Attributes.ContainsKey("destination-id")); - Assert.AreEqual(id, block.Attributes["destination-id"]); + Assert.IsTrue(block.Attributes.ContainsKey("content-id")); + Assert.AreEqual(id, block.Attributes["content-id"]); Assert.IsEmpty(block.Elements); } @@ -330,12 +330,12 @@ public void ParseElement_AppendsBlocks(bool inlineBlock) var block1Element = paragraph.Elements.First() as RichTextGenericElement; Assert.IsNotNull(block1Element); Assert.AreEqual(tagName, block1Element.Tag); - Assert.AreEqual(block1ContentId, block1Element.Attributes["destination-id"]); + Assert.AreEqual(block1ContentId, block1Element.Attributes["content-id"]); var block2Element = paragraph.Elements.Last() as RichTextGenericElement; Assert.IsNotNull(block2Element); Assert.AreEqual(tagName, block2Element.Tag); - Assert.AreEqual(block2ContentId, block2Element.Attributes["destination-id"]); + Assert.AreEqual(block2ContentId, block2Element.Attributes["content-id"]); Assert.AreEqual(2, element.Blocks.Count()); @@ -369,16 +369,16 @@ public void ParseElement_CanHandleMixedInlineAndBlockLevelBlocks() Assert.IsNotNull(inlineBlock); Assert.AreEqual("umb-rte-block-inline", inlineBlock.Tag); Assert.AreEqual(1, inlineBlock.Attributes.Count); - Assert.IsTrue(inlineBlock.Attributes.ContainsKey("destination-id")); - Assert.AreEqual(id1, inlineBlock.Attributes["destination-id"]); + Assert.IsTrue(inlineBlock.Attributes.ContainsKey("content-id")); + Assert.AreEqual(id1, inlineBlock.Attributes["content-id"]); Assert.IsEmpty(inlineBlock.Elements); var blockLevelBlock = element.Elements.Last() as RichTextGenericElement; Assert.IsNotNull(blockLevelBlock); Assert.AreEqual("umb-rte-block", blockLevelBlock.Tag); Assert.AreEqual(1, blockLevelBlock.Attributes.Count); - Assert.IsTrue(blockLevelBlock.Attributes.ContainsKey("destination-id")); - Assert.AreEqual(id2, blockLevelBlock.Attributes["destination-id"]); + Assert.IsTrue(blockLevelBlock.Attributes.ContainsKey("content-id")); + Assert.AreEqual(id2, blockLevelBlock.Attributes["content-id"]); Assert.IsEmpty(blockLevelBlock.Elements); } @@ -609,7 +609,7 @@ public void ParseMarkup_CleansUpBlocks(bool inlineBlock) var tagName = $"umb-rte-block{(inlineBlock ? "-inline" : string.Empty)}"; var result = parser.Parse($"

<{tagName} data-content-key=\"{id:N}\">

"); - Assert.AreEqual($"

<{tagName} data-destination-id=\"{id:D}\">

", result); + Assert.AreEqual($"

<{tagName} data-content-id=\"{id:D}\">

", result); } [Test] @@ -620,7 +620,7 @@ public void ParseMarkup_CanHandleMixedInlineAndBlockLevelBlocks() var id2 = Guid.NewGuid(); var result = parser.Parse($"

"); - Assert.AreEqual($"

", result); + Assert.AreEqual($"

", result); } private ApiRichTextElementParser CreateRichTextElementParser()