Skip to content

Commit 7a733d7

Browse files
KevinJumpclaude
andauthored
Inline legacy local link parsing to drop obsolete HtmlLocalLinkParser API (#1004)
HtmlLocalLinkParser.FindLegacyLocalLinkIds and its LocalLinkTag model are obsolete (CS0618) and scheduled for removal in Umbraco 18, but uSync still needs to detect un-migrated {localLink:x} references when mapping RTE content. Copies the regex and parsing logic directly into SyncLocalLinkProcessor (verified against the Umbraco 18 source) so we own it going forward instead of depending on removed API surface. Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 57b86f8 commit 7a733d7

1 file changed

Lines changed: 62 additions & 8 deletions

File tree

uSync.Core/Versions/18.0/SyncLocalLinkProcessor.cs

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Text;
5+
using System.Text.RegularExpressions;
46

57
using Umbraco.Cms.Core;
68
using Umbraco.Cms.Core.Models;
79
using Umbraco.Cms.Core.Services;
8-
using Umbraco.Cms.Core.Templates;
910

1011
namespace uSync.Core.Versions._18._0;
1112

@@ -18,19 +19,27 @@ public interface ISyncTypedLocalLinkProcessor
1819
public Func<object?, Func<object?, bool>, Func<string, string>, bool> Process { get; }
1920
}
2021

21-
22-
public class SyncLocalLinkProcessor
22+
/// <summary>
23+
/// Finds and replaces the legacy {localLink:x} syntax within values, mapping ids/UDIs to keys.
24+
/// </summary>
25+
/// <remarks>
26+
/// Umbraco's own <c>HtmlLocalLinkParser.FindLegacyLocalLinkIds</c> (and its <c>LocalLinkTag</c> model)
27+
/// are obsolete and scheduled for removal in Umbraco 18, but uSync still needs to detect these
28+
/// legacy (un-migrated) links when mapping content, so the parsing logic lives here instead.
29+
/// </remarks>
30+
public partial class SyncLocalLinkProcessor
2331
{
24-
private readonly HtmlLocalLinkParser _localLinkParser;
32+
// copied from Umbraco.Cms.Core.Templates.HtmlLocalLinkParser.LocalLinkPattern
33+
[GeneratedRegex(@"href=['""](?<locallink>\/?(?:\{|\%7B)localLink:(?<guid>[a-zA-Z0-9-://]+)(?:\}|\%7D))", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace, "en-GB")]
34+
private static partial Regex LegacyLocalLinkPattern();
35+
2536
private readonly IIdKeyMap _idKeyMap;
2637
private readonly IEnumerable<ISyncTypedLocalLinkProcessor> _localLinkProcessors;
2738

2839
public SyncLocalLinkProcessor(
29-
HtmlLocalLinkParser localLinkParser,
3040
IIdKeyMap idKeyMap,
3141
IEnumerable<ISyncTypedLocalLinkProcessor> localLinkProcessors)
3242
{
33-
_localLinkParser = localLinkParser;
3443
_idKeyMap = idKeyMap;
3544
_localLinkProcessors = localLinkProcessors;
3645
}
@@ -49,9 +58,9 @@ public bool ProcessToEditorValue(object? editorValue)
4958
public string ProcessStringValue(string input)
5059
{
5160
// find all legacy tags
52-
var tags = _localLinkParser.FindLegacyLocalLinkIds(input).ToList();
61+
var tags = FindLegacyLocalLinkIds(input).ToList();
5362

54-
foreach (HtmlLocalLinkParser.LocalLinkTag tag in tags)
63+
foreach (LocalLinkTag tag in tags)
5564
{
5665
string newTagHref;
5766
if (tag.Udi is not null)
@@ -101,4 +110,49 @@ public string ProcessStringValue(string input)
101110
return null;
102111
}
103112

113+
// copied from Umbraco.Cms.Core.Templates.HtmlLocalLinkParser.FindLegacyLocalLinkIds
114+
private static IEnumerable<LocalLinkTag> FindLegacyLocalLinkIds(string text)
115+
{
116+
MatchCollection tags = LegacyLocalLinkPattern().Matches(text);
117+
foreach (Match tag in tags)
118+
{
119+
if (tag.Groups.Count <= 0)
120+
{
121+
continue;
122+
}
123+
124+
var id = tag.Groups["guid"].Value;
125+
126+
// The id could be an int or a UDI
127+
if (UdiParser.TryParse(id, out Udi? udi))
128+
{
129+
if (udi is GuidUdi guidUdi)
130+
{
131+
yield return new LocalLinkTag(null, guidUdi, tag.Groups["locallink"].Value);
132+
}
133+
}
134+
135+
if (int.TryParse(id, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intId))
136+
{
137+
yield return new LocalLinkTag(intId, null, tag.Groups["locallink"].Value);
138+
}
139+
}
140+
}
141+
142+
// copied from Umbraco.Cms.Core.Templates.HtmlLocalLinkParser.LocalLinkTag
143+
private sealed class LocalLinkTag
144+
{
145+
public LocalLinkTag(int? intId, GuidUdi? udi, string tagHref)
146+
{
147+
IntId = intId;
148+
Udi = udi;
149+
TagHref = tagHref;
150+
}
151+
152+
public int? IntId { get; }
153+
154+
public GuidUdi? Udi { get; }
155+
156+
public string TagHref { get; }
157+
}
104158
}

0 commit comments

Comments
 (0)