#if WINDOWS using Aprillz.MewUI; using Aprillz.MewUI.Controls; namespace MeetingAssistant.Workflow; internal static class WorkflowRulesEditorMarkdownRenderer { public static UIElement CreateContent(string content) { var panel = new StackPanel() .Vertical() .Spacing(7); foreach (var block in WorkflowRulesEditorMarkdown.Parse(content)) { panel.Add(block switch { WorkflowRulesEditorMarkdownCodeBlock codeBlock => CreateCodeBlock(codeBlock), WorkflowRulesEditorMarkdownTable table => CreateTable(table), WorkflowRulesEditorMarkdownParagraph paragraph => CreateParagraph(paragraph), _ => new TextBlock() }); } return panel; } private static UIElement CreateParagraph(WorkflowRulesEditorMarkdownParagraph paragraph) { var lines = SplitInlineLines(paragraph.Inlines); if (lines.Count == 1) { return CreateParagraphLine(lines[0]); } var panel = new StackPanel() .Vertical() .Spacing(3); foreach (var line in lines) { panel.Add(CreateParagraphLine(line)); } return panel; } private static UIElement CreateParagraphLine(IReadOnlyList inlines) { var linePanel = new WrapPanel() .Spacing(1); foreach (var inline in inlines) { foreach (var element in CreateInlineElements(inline)) { linePanel.Add(element); } } return linePanel; } private static IEnumerable CreateInlineElements(WorkflowRulesEditorMarkdownInline inline) { if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Code) { yield return CreateInlineCode(inline.Text); yield break; } foreach (var token in SplitInlineText(inline.Text)) { var text = new TextBlock() .Text(token) .TextWrapping(TextWrapping.Wrap) .Foreground(Color.FromRgb(230, 235, 243)); if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Bold) { text.FontWeight(FontWeight.Bold); } else if (inline.Style == WorkflowRulesEditorMarkdownInlineStyle.Italic) { text.FontFamily("Segoe UI Italic"); } yield return text; } } private static IReadOnlyList> SplitInlineLines( IReadOnlyList inlines) { var lines = new List>(); var current = new List(); foreach (var inline in inlines) { var parts = inline.Text.Split('\n'); for (var index = 0; index < parts.Length; index++) { if (parts[index].Length > 0) { current.Add(inline with { Text = parts[index] }); } if (index < parts.Length - 1) { lines.Add(current); current = []; } } } lines.Add(current); return lines; } private static UIElement CreateInlineCode(string text) { return new Border() .Padding(4, 1, 4, 2) .Margin(1, 0, 1, 0) .CornerRadius(4) .BorderThickness(1) .BorderBrush(Color.FromRgb(86, 94, 108)) .Background(Color.FromRgb(24, 28, 35)) .Child(new TextBlock() .Text(text) .FontFamily("Consolas") .Foreground(Color.FromRgb(237, 241, 247))); } private static UIElement CreateTable(WorkflowRulesEditorMarkdownTable table) { var rows = table.Rows .Select(row => new MarkdownTableRow(PadCells(row, table.Header.Count))) .ToArray(); var gridView = new GridView() .HeaderHeight(30) .RowHeight(30) .CellPadding(new Thickness(8, 4, 8, 4)) .ShowGridLines(true) .ZebraStriping(true); for (var index = 0; index < table.Header.Count; index++) { var columnIndex = index; gridView.AddColumn( table.Header[index], GetMarkdownTableColumnWidth(table, index), _ => new TextBlock() .TextWrapping(TextWrapping.NoWrap) .Foreground(Color.FromRgb(230, 235, 243)), (element, row, _, _) => ((TextBlock)element).Text(row.GetCell(columnIndex)), minWidth: 64, resizable: true); } return gridView .ItemsSource(rows) .MinWidth(Math.Min(900, table.Header.Count * 120)) .Height(Math.Min(420, 30 + Math.Max(1, rows.Length) * 30)); } private static UIElement CreateCodeBlock(WorkflowRulesEditorMarkdownCodeBlock codeBlock) { return new Border() .Padding(9) .CornerRadius(6) .BorderThickness(1) .BorderBrush(Color.FromRgb(86, 94, 108)) .Background(Color.FromRgb(20, 24, 31)) .Child(new TextBlock() .Text(codeBlock.Text) .TextWrapping(TextWrapping.Wrap) .FontFamily("Consolas") .Foreground(Color.FromRgb(237, 241, 247))); } private static IEnumerable SplitInlineText(string text) { var start = 0; while (start < text.Length) { var end = start; var isWhitespace = char.IsWhiteSpace(text[start]); while (end < text.Length && char.IsWhiteSpace(text[end]) == isWhitespace) { end++; } var token = text[start..end]; if (token.Length > 0) { yield return token; } start = end; } } private static IReadOnlyList PadCells(IReadOnlyList cells, int count) { if (cells.Count >= count) { return cells; } return cells .Concat(Enumerable.Repeat("", count - cells.Count)) .ToArray(); } private static double GetMarkdownTableColumnWidth( WorkflowRulesEditorMarkdownTable table, int index) { var maxLength = new[] { table.Header[index].Length } .Concat(table.Rows.Select(row => index < row.Count ? row[index].Length : 0)) .DefaultIfEmpty(0) .Max(); return Math.Clamp(maxLength * 8 + 28, 72, 260); } private sealed record MarkdownTableRow(IReadOnlyList Cells) { public string GetCell(int index) { return index >= 0 && index < Cells.Count ? Cells[index] : ""; } } } #endif