diff --git a/Bloxstrap/UI/Elements/Controls/MarkdownTextBlock.cs b/Bloxstrap/UI/Elements/Controls/MarkdownTextBlock.cs index 6e1e0d7..bd97b8f 100644 --- a/Bloxstrap/UI/Elements/Controls/MarkdownTextBlock.cs +++ b/Bloxstrap/UI/Elements/Controls/MarkdownTextBlock.cs @@ -6,6 +6,7 @@ using System.Windows; using Markdig.Syntax; using Markdig.Syntax.Inlines; using Markdig; +using System.Windows.Media; namespace Bloxstrap.UI.Elements.Controls { @@ -19,15 +20,97 @@ namespace Bloxstrap.UI.Elements.Controls { public static readonly DependencyProperty MarkdownTextProperty = DependencyProperty.Register(nameof(MarkdownText), typeof(string), typeof(MarkdownTextBlock), - new FrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnTextMarkdownChanged)); + new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, OnTextMarkdownChanged)); [Localizability(LocalizationCategory.Text)] public string MarkdownText { - get => Inlines.ToString() ?? ""; + get => (string)GetValue(MarkdownTextProperty); set => SetValue(MarkdownTextProperty, value); } + /// Span, skip + private static (Span, int) GetInlineUntilEndTagDetected(Markdig.Syntax.Inlines.Inline? inline, string tagName) + { + string endTag = $"<{tagName}/>"; // TODO: better way of doing this + + var span = new Span(); + + int skip = 0; + var current = inline; + while (current is Markdig.Syntax.Inlines.Inline currentInline) + { + skip++; + + if (currentInline is HtmlInline html) + { + if (html.Tag == endTag) + return (span, skip); + } + + (var childInline, int childSkip) = GetWpfInlineFromMarkdownInline(currentInline); + if (childInline != null) + span.Inlines.Add(childInline); + + skip += childSkip; + + current = currentInline.NextSibling; + } + + throw new Exception("End tag not detected"); + } + + /// Inline, skip + private static (System.Windows.Documents.Inline?, int) GetWpfInlineFromMarkdownInline(Markdig.Syntax.Inlines.Inline? inline) + { + if (inline is LiteralInline literalInline) + { + return (new Run(literalInline.ToString()), 0); + } + else if (inline is LinkInline linkInline) + { + string? url = linkInline.Url; + var textInline = linkInline.FirstChild; + + if (string.IsNullOrEmpty(url)) + { + return GetWpfInlineFromMarkdownInline(textInline); + } + + (var childInline, int skip) = GetWpfInlineFromMarkdownInline(textInline); + + return (new Hyperlink(childInline) + { + Command = GlobalViewModel.OpenWebpageCommand, + CommandParameter = url + }, skip); + } + else if (inline is HtmlInline htmlInline) + { + string? tag = htmlInline.Tag; // TODO: parse tag + var nextInline = htmlInline.NextSibling; + + if (tag == "") + { + (var span, int skip) = GetInlineUntilEndTagDetected(nextInline, "highlight"); + span.Background = new SolidColorBrush(Color.FromArgb(50,255,255,255)); + return (span, skip); + } + } + + return (null, 0); + } + + /// Skip + private int AddMarkdownInline(Markdig.Syntax.Inlines.Inline? inline) + { + (var wpfInline, int skip) = GetWpfInlineFromMarkdownInline(inline); + if (wpfInline != null) + Inlines.Add(wpfInline); + + return skip; + } + private static void OnTextMarkdownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) { if (dependencyObject is not MarkdownTextBlock markdownTextBlock) @@ -43,26 +126,12 @@ namespace Bloxstrap.UI.Elements.Controls if (document.FirstOrDefault() is not ParagraphBlock paragraphBlock || paragraphBlock.Inline == null) return; - foreach (var inline in paragraphBlock.Inline) + for (int i = 0; i < paragraphBlock.Inline.Count(); i++) { - if (inline is LiteralInline literalInline) - { - markdownTextBlock.Inlines.Add(new Run(literalInline.ToString())); - } - else if (inline is LinkInline linkInline) - { - string? url = linkInline.Url; - string? text = linkInline.FirstChild?.ToString(); + var inline = paragraphBlock.Inline.ElementAt(i); - if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(text)) - continue; - - markdownTextBlock.Inlines.Add(new Hyperlink(new Run(text)) - { - Command = GlobalViewModel.OpenWebpageCommand, - CommandParameter = url - }); - } + int skip = markdownTextBlock.AddMarkdownInline(inline); + i += skip; } } }