Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_15_0_0.LocalLinks;
public static partial class RteBlockHelper
{
/// <summary>
/// Returns a <see cref="Regex"/> that matches <c>umb-rte-block</c> elements containing a <c>data-content-udi</c> attribute in the input HTML.
/// Returns a <see cref="Regex"/> that matches <c>umb-rte-block</c> and <c>umb-rte-block-inline</c>
/// elements containing a <c>data-content-udi</c> attribute in the input HTML.
/// </summary>
/// <returns>A <see cref="Regex"/> instance for identifying <c>umb-rte-block</c> elements with a <c>data-content-udi</c> attribute.</returns>
// Non-greedy on both [^>]*? and .*? so consecutive sibling <umb-rte-block> elements are matched
// individually rather than collapsed into one span (which left all-but-last sibling UDIs un-converted).
[GeneratedRegex("<umb-rte-block\\b[^>]*?(?<attribute>data-content-udi)=\"(?<udi>[^\"]+)\"[^>]*>.*?<\\/umb-rte-block>")]
/// <returns>A <see cref="Regex"/> instance for identifying <c>umb-rte-block</c>/<c>umb-rte-block-inline</c> elements with a <c>data-content-udi</c> attribute.</returns>
// Non-greedy on both [^>]*? and .*? so consecutive sibling blocks are matched individually rather
// than collapsed into one span (which left all-but-last sibling UDIs un-converted). The (?:-inline)?
// on both the opening and closing tag lets .*? stop at the nearest close of either variant, so a
// mix of block and inline siblings never collapse together and isolated inline blocks still match.
[GeneratedRegex("<umb-rte-block(?:-inline)?\\b[^>]*?(?<attribute>data-content-udi)=\"(?<udi>[^\"]+)\"[^>]*>.*?<\\/umb-rte-block(?:-inline)?>")]
public static partial Regex BlockRegex();

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,114 @@ public void ConvertBlockUdisToKeys_BlockWithMalformedUdi_IsDroppedFromOutput()
result);
}

/// <summary>
/// An isolated inline block (<c>&lt;umb-rte-block-inline&gt;</c>) must be converted. The v13 RTE
/// emits both block and inline variants, and the closing tag differs (<c>&lt;/umb-rte-block-inline&gt;</c>).
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_SingleInlineBlock_ConvertsUdiToHyphenatedGuidKey()
{
var input = @"<p>before</p><umb-rte-block-inline data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline><p>after</p>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<p>before</p><umb-rte-block-inline data-content-key=""5e499fc2-37be-4b1d-9746-70526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline><p>after</p>",
result);
}

/// <summary>
/// An inline block immediately followed by a block-level block must convert each independently —
/// the inline closing tag must not let the match span across into the next block's closing tag.
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_InlineFollowedByBlock_ConvertsEachIndividually()
{
var input =
@"<umb-rte-block-inline data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<umb-rte-block data-content-udi=""umb://element/9db16c0d251e414c874967090f2cf3cc""><!--Umbraco-Block--></umb-rte-block>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<umb-rte-block-inline data-content-key=""5e499fc2-37be-4b1d-9746-70526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<umb-rte-block data-content-key=""9db16c0d-251e-414c-8749-67090f2cf3cc""><!--Umbraco-Block--></umb-rte-block>",
result);
StringAssert.DoesNotContain("umb://element/", result);
}

/// <summary>
/// A block-level block immediately followed by an inline block must convert each independently.
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_BlockFollowedByInline_ConvertsEachIndividually()
{
var input =
@"<umb-rte-block data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block>" +
@"<umb-rte-block-inline data-content-udi=""umb://element/9db16c0d251e414c874967090f2cf3cc""><!--Umbraco-Block--></umb-rte-block-inline>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<umb-rte-block data-content-key=""5e499fc2-37be-4b1d-9746-70526f3b00b7""><!--Umbraco-Block--></umb-rte-block>" +
@"<umb-rte-block-inline data-content-key=""9db16c0d-251e-414c-8749-67090f2cf3cc""><!--Umbraco-Block--></umb-rte-block-inline>",
result);
StringAssert.DoesNotContain("umb://element/", result);
}

/// <summary>
/// Two direct-sibling inline blocks must each be converted independently — the inline parallel to
/// <see cref="ConvertBlockUdisToKeys_TwoConsecutiveSiblingBlocks_ConvertsEachIndividually"/>.
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_TwoConsecutiveInlineSiblings_ConvertsEachIndividually()
{
var input =
@"<umb-rte-block-inline data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<umb-rte-block-inline data-content-udi=""umb://element/9db16c0d251e414c874967090f2cf3cc""><!--Umbraco-Block--></umb-rte-block-inline>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<umb-rte-block-inline data-content-key=""5e499fc2-37be-4b1d-9746-70526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<umb-rte-block-inline data-content-key=""9db16c0d-251e-414c-8749-67090f2cf3cc""><!--Umbraco-Block--></umb-rte-block-inline>",
result);
StringAssert.DoesNotContain("umb://element/", result);
}

/// <summary>
/// An inline block carrying an optional <c>class</c> attribute must be converted, preserving the class.
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_InlineBlockWithClassAttribute_ConvertsUdiToKey()
{
var input = @"<umb-rte-block-inline class=""some-class"" data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<umb-rte-block-inline class=""some-class"" data-content-key=""5e499fc2-37be-4b1d-9746-70526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>",
result);
}

/// <summary>
/// When an inline block's UDI fails to parse, the block is dropped — consistent with block-level behaviour.
/// </summary>
[Test]
public void ConvertBlockUdisToKeys_MalformedUdiInlineBlock_IsDroppedFromOutput()
{
var input =
@"<p>before</p>" +
@"<umb-rte-block-inline data-content-udi=""not-a-valid-udi""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<p>after</p>";

var result = RteBlockHelper.ConvertBlockUdisToKeys(input);

Assert.AreEqual(
@"<p>before</p><p>after</p>",
result);
}

[Test]
public void ConvertBlockUdisToKeys_MarkupWithoutBlocks_ReturnsUnchanged()
{
Expand Down Expand Up @@ -172,5 +280,19 @@ public void BlockRegex_ThreeConsecutiveSiblingBlocks_ProducesOneMatchPerBlock()

Assert.AreEqual(3, RteBlockHelper.BlockRegex().Matches(input).Count);
}

/// <summary>
/// A mix of block-level and inline sibling blocks produces one match per element (no collapsing).
/// </summary>
[Test]
public void BlockRegex_MixedBlockAndInlineSiblings_ProducesOneMatchPerBlock()
{
var input =
@"<umb-rte-block-inline data-content-udi=""umb://element/5e499fc237be4b1d974670526f3b00b7""><!--Umbraco-Block--></umb-rte-block-inline>" +
@"<umb-rte-block data-content-udi=""umb://element/9db16c0d251e414c874967090f2cf3cc""><!--Umbraco-Block--></umb-rte-block>" +
@"<umb-rte-block-inline data-content-udi=""umb://element/c2c956b94a0945f29a1a366ad488545b""><!--Umbraco-Block--></umb-rte-block-inline>";

Assert.AreEqual(3, RteBlockHelper.BlockRegex().Matches(input).Count);
}
}
#pragma warning restore CS0618
Loading