more robust markdowntextblock

This commit is contained in:
bluepilledgreat 2024-01-29 20:10:43 +00:00
parent 75fe43f57d
commit 8d0aa5249c

View File

@ -6,6 +6,7 @@ using System.Windows;
using Markdig.Syntax; using Markdig.Syntax;
using Markdig.Syntax.Inlines; using Markdig.Syntax.Inlines;
using Markdig; using Markdig;
using System.Windows.Media;
namespace Bloxstrap.UI.Elements.Controls namespace Bloxstrap.UI.Elements.Controls
{ {
@ -24,10 +25,92 @@ namespace Bloxstrap.UI.Elements.Controls
[Localizability(LocalizationCategory.Text)] [Localizability(LocalizationCategory.Text)]
public string MarkdownText public string MarkdownText
{ {
get => Inlines.ToString() ?? ""; get => (string)GetValue(MarkdownTextProperty);
set => SetValue(MarkdownTextProperty, value); set => SetValue(MarkdownTextProperty, value);
} }
/// <returns>Span, skip</returns>
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");
}
/// <returns>Inline, skip</returns>
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 == "<highlight>")
{
(var span, int skip) = GetInlineUntilEndTagDetected(nextInline, "highlight");
span.Background = new SolidColorBrush(Color.FromArgb(50,255,255,255));
return (span, skip);
}
}
return (null, 0);
}
/// <returns>Skip</returns>
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) private static void OnTextMarkdownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{ {
if (dependencyObject is not MarkdownTextBlock markdownTextBlock) 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) if (document.FirstOrDefault() is not ParagraphBlock paragraphBlock || paragraphBlock.Inline == null)
return; return;
foreach (var inline in paragraphBlock.Inline) for (int i = 0; i < paragraphBlock.Inline.Count(); i++)
{ {
if (inline is LiteralInline literalInline) var inline = paragraphBlock.Inline.ElementAt(i);
{
markdownTextBlock.Inlines.Add(new Run(literalInline.ToString()));
}
else if (inline is LinkInline linkInline)
{
string? url = linkInline.Url;
string? text = linkInline.FirstChild?.ToString();
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(text)) int skip = markdownTextBlock.AddMarkdownInline(inline);
continue; i += skip;
markdownTextBlock.Inlines.Add(new Hyperlink(new Run(text))
{
Command = GlobalViewModel.OpenWebpageCommand,
CommandParameter = url
});
}
} }
} }
} }