@using System.Text.RegularExpressions @namespace Chrono.Components @if (Doc != null) {
@if (Doc.Syndicates != null) { foreach (var syn in Doc.Syndicates) { } }

@Doc.Title

@if (!string.IsNullOrWhiteSpace(Doc.Content)) {
@RenderDescription(Doc.Content)
}
} @code { [Parameter] public DocData? Doc { get; set; } [Parameter] public EventCallback OnClose { get; set; } [Parameter] public EventCallback OnNavigate { get; set; } private void HandleClose() { _ = OnClose.InvokeAsync(); } private void HandleBackdropClick() { _ = OnClose.InvokeAsync(); } private void Navigate(CardData card) { _ = OnNavigate.InvokeAsync(card); } private static CardData? LookupCard(string cardName) { return CardDatabase.Cards.FirstOrDefault(c => string.Equals(c.Name, cardName, StringComparison.OrdinalIgnoreCase)); } private RenderFragment RenderDescription(string description) { return builder => { var cardNames = CardDatabase.Cards .Select(c => c.Name) .Where(n => !string.IsNullOrWhiteSpace(n)) .OrderByDescending(n => n.Length) .ToList(); var seq = 0; var remaining = description; while (!string.IsNullOrEmpty(remaining)) { var bestIdx = -1; string? bestName = null; foreach (var name in cardNames) { var pattern = $@"\b{Regex.Escape(name)}\b"; var match = Regex.Match(remaining, pattern, RegexOptions.IgnoreCase); if (match.Success) { if (bestIdx == -1 || match.Index < bestIdx) { bestIdx = match.Index; bestName = match.Value; } } } // Also check for [[Card Name]] format which is common in docs var bracketMatch = Regex.Match(remaining, @"\[\[(.*?)\]\]"); if (bracketMatch.Success) { if (bestIdx == -1 || bracketMatch.Index < bestIdx) { bestIdx = bracketMatch.Index; bestName = bracketMatch.Value; } } if (bestIdx != -1 && bestName != null) { if (bestIdx > 0) builder.AddContent(seq++, remaining[..bestIdx]); var cleanName = bestName.StartsWith("[[") && bestName.EndsWith("]]") ? bestName.Substring(2, bestName.Length - 4) : bestName; var card = LookupCard(cleanName); if (card != null) { builder.OpenElement(seq++, "button"); builder.AddAttribute(seq++, "class", "inline-card-btn"); builder.AddAttribute(seq++, "onclick", EventCallback.Factory.Create(this, () => Navigate(card))); builder.AddContent(seq++, cleanName); builder.CloseElement(); } else { builder.AddContent(seq++, cleanName); } remaining = remaining[(bestIdx + bestName.Length)..]; } else { builder.AddContent(seq++, remaining); remaining = ""; } } }; } }