using System.Collections.Generic; using Avalonia.Controls; using Avalonia.Media; using Markdig; using Markdig.Syntax; using Markdig.Syntax.Inlines; using System.Text; namespace Logof_Client.Wiki; public static class MarkdownRenderer { public static Control Render(string markdown) { var panel = new StackPanel { Spacing = 6 }; if (string.IsNullOrWhiteSpace(markdown)) return panel; var doc = Markdown.Parse(markdown); foreach (var block in doc) { switch (block) { case HeadingBlock hb: { var text = GetInlineText(hb.Inline); var tb = new TextBlock { Text = text, FontWeight = FontWeight.Bold, Margin = new Avalonia.Thickness(0, hb.Level == 1 ? 6 : 2, 0, 2) }; tb.FontSize = hb.Level switch { 1 => 22, 2 => 18, 3 => 16, _ => 14 }; panel.Children.Add(tb); break; } case ParagraphBlock pb: { var text = GetInlineText(pb.Inline); var tb = new TextBlock { Text = text, TextWrapping = Avalonia.Media.TextWrapping.Wrap }; panel.Children.Add(tb); break; } case FencedCodeBlock cb: { var sb = new StringBuilder(); foreach (var line in cb.Lines.Lines) { sb.Append(line.ToString()); } var codeBox = new TextBox { Text = sb.ToString(), FontFamily = "Consolas, monospace", IsReadOnly = true, AcceptsReturn = true }; panel.Children.Add(codeBox); break; } case ListBlock lb: { var sp = new StackPanel { Spacing = 2 }; var number = 1; foreach (var item in lb) { if (item is ListItemBlock lib) { var itemText = new StringBuilder(); foreach (var sub in lib) { if (sub is ParagraphBlock pp) itemText.Append(GetInlineText(pp.Inline)); } var tb = new TextBlock { Text = (lb.IsOrdered ? (number++ + ". ") : "• ") + itemText.ToString() }; sp.Children.Add(tb); } } panel.Children.Add(sp); break; } default: { // fallback: raw text panel.Children.Add(new TextBlock { Text = block.ToString() }); break; } } } return panel; } private static string GetInlineText(ContainerInline? container) { if (container == null) return string.Empty; var sb = new StringBuilder(); foreach (var inline in container) { switch (inline) { case LiteralInline li: sb.Append(li.Content.ToString()); break; case EmphasisInline ei: sb.Append(GetInlineText(ei)); break; case CodeInline ci: sb.Append(ci.Content); break; case LinkInline li: sb.Append(GetInlineText(li)); break; default: sb.Append(inline.ToString()); break; } } return sb.ToString(); } }