[feat:] include Markdown.Avalonia for better rendering

This commit is contained in:
2026-06-08 09:05:12 +02:00
parent acaf0856ed
commit a2d0b72899
4 changed files with 157 additions and 156 deletions
+1
View File
@@ -21,6 +21,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="ISO3166" Version="1.0.4" /> <PackageReference Include="ISO3166" Version="1.0.4" />
<PackageReference Include="Lucide.Avalonia" Version="0.1.35" /> <PackageReference Include="Lucide.Avalonia" Version="0.1.35" />
<PackageReference Include="Markdown.Avalonia" Version="11.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="PdfSharp" Version="6.1.1" /> <PackageReference Include="PdfSharp" Version="6.1.1" />
</ItemGroup> </ItemGroup>
+2 -3
View File
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:md="https://github.com/whistyun/Markdown.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
MinWidth="1000" MinHeight="600" IsVisible="False" MinWidth="1000" MinHeight="600" IsVisible="False"
x:Class="Logof_Client.MainWindow" WindowState="Maximized" Icon="assets/icon.ico" x:Class="Logof_Client.MainWindow" WindowState="Maximized" Icon="assets/icon.ico"
@@ -370,9 +371,7 @@
</StackPanel> </StackPanel>
<Border Grid.Row="1" Margin="8" BorderBrush="#DDD" BorderThickness="1" CornerRadius="4"> <Border Grid.Row="1" Margin="8" BorderBrush="#DDD" BorderThickness="1" CornerRadius="4">
<ScrollViewer> <md:MarkdownScrollViewer x:Name="MsvWikiView"/>
<StackPanel Name="PreviewPanel" Margin="8" />
</ScrollViewer>
</Border> </Border>
</Grid> </Grid>
</Grid> </Grid>
+13 -12
View File
@@ -230,18 +230,19 @@ public partial class MainWindow : Window
{ {
_selectedWikiFilePath = item.Path; _selectedWikiFilePath = item.Path;
var text = await _wikiService.LoadFileContentAsync(item.Path); var text = await _wikiService.LoadFileContentAsync(item.Path);
try MsvWikiView.Markdown = text;
{ // try
PreviewPanel.Children.Clear(); // {
var rendered = MarkdownRenderer.Render(text ?? string.Empty); // PreviewPanel.Children.Clear();
PreviewPanel.Children.Add(rendered); // var rendered = MarkdownRenderer.Render(text ?? string.Empty);
} // PreviewPanel.Children.Add(rendered);
catch (Exception ex) // }
{ // catch (Exception ex)
Logger.Log($"Error while rendering markdown: {ex.Message}", Logger.LogType.Error); // {
PreviewPanel.Children.Clear(); // Logger.Log($"Error while rendering markdown: {ex.Message}", Logger.LogType.Error);
PreviewPanel.Children.Add(new TextBlock { Text = text ?? string.Empty }); // PreviewPanel.Children.Clear();
} // PreviewPanel.Children.Add(new TextBlock { Text = text ?? string.Empty });
// }
EditButton.IsEnabled = true; EditButton.IsEnabled = true;
} }
+126 -126
View File
@@ -11,130 +11,130 @@ namespace Logof_Client.Wiki;
public static class MarkdownRenderer public static class MarkdownRenderer
{ {
public static Control Render(string markdown) // public static Control Render(string markdown)
{ // {
try // try
{ // {
var panel = new StackPanel { Spacing = 6 }; // var panel = new StackPanel { Spacing = 6 };
if (string.IsNullOrWhiteSpace(markdown)) return panel; // if (string.IsNullOrWhiteSpace(markdown)) return panel;
//
var doc = Markdown.Parse(markdown); // var doc = Markdown.Parse(markdown);
//
foreach (var block in doc) // foreach (var block in doc)
{ // {
switch (block) // switch (block)
{ // {
case HeadingBlock hb: // case HeadingBlock hb:
{ // {
var text = GetInlineText(hb.Inline); // var text = GetInlineText(hb.Inline);
var tb = new TextBlock // var tb = new TextBlock
{ // {
Text = text, // Text = text,
FontWeight = FontWeight.Bold, // FontWeight = FontWeight.Bold,
Margin = new Avalonia.Thickness(0, hb.Level == 1 ? 6 : 2, 0, 2) // Margin = new Avalonia.Thickness(0, hb.Level == 1 ? 6 : 2, 0, 2)
}; // };
tb.FontSize = hb.Level switch { 1 => 22, 2 => 18, 3 => 16, _ => 14 }; // tb.FontSize = hb.Level switch { 1 => 22, 2 => 18, 3 => 16, _ => 14 };
panel.Children.Add(tb); // panel.Children.Add(tb);
break; // break;
} // }
//
case ParagraphBlock pb: // case ParagraphBlock pb:
{ // {
var text = GetInlineText(pb.Inline); // var text = GetInlineText(pb.Inline);
var tb = new TextBlock { Text = text, TextWrapping = Avalonia.Media.TextWrapping.Wrap }; // var tb = new TextBlock { Text = text, TextWrapping = Avalonia.Media.TextWrapping.Wrap };
panel.Children.Add(tb); // panel.Children.Add(tb);
break; // break;
} // }
//
case FencedCodeBlock cb: // case FencedCodeBlock cb:
{ // {
var sb = new StringBuilder(); // var sb = new StringBuilder();
foreach (var line in cb.Lines.Lines) // foreach (var line in cb.Lines.Lines)
{ // {
sb.Append(line.ToString()); // sb.Append(line.ToString());
} // }
var codeBox = new TextBox // var codeBox = new TextBox
{ // {
Text = sb.ToString(), // Text = sb.ToString(),
FontFamily = "Consolas, monospace", // FontFamily = "Consolas, monospace",
IsReadOnly = true, // IsReadOnly = true,
AcceptsReturn = true // AcceptsReturn = true
}; // };
panel.Children.Add(codeBox); // panel.Children.Add(codeBox);
break; // break;
} // }
//
case ListBlock lb: // case ListBlock lb:
{ // {
var sp = new StackPanel { Spacing = 2 }; // var sp = new StackPanel { Spacing = 2 };
var number = 1; // var number = 1;
foreach (var item in lb) // foreach (var item in lb)
{ // {
if (item is ListItemBlock lib) // if (item is ListItemBlock lib)
{ // {
var itemText = new StringBuilder(); // var itemText = new StringBuilder();
foreach (var sub in lib) // foreach (var sub in lib)
{ // {
if (sub is ParagraphBlock pp) // if (sub is ParagraphBlock pp)
itemText.Append(GetInlineText(pp.Inline)); // itemText.Append(GetInlineText(pp.Inline));
} // }
var tb = new TextBlock { Text = (lb.IsOrdered ? (number++ + ". ") : "• ") + itemText.ToString() }; // var tb = new TextBlock { Text = (lb.IsOrdered ? (number++ + ". ") : "• ") + itemText.ToString() };
sp.Children.Add(tb); // sp.Children.Add(tb);
} // }
} // }
panel.Children.Add(sp); // panel.Children.Add(sp);
break; // break;
} // }
//
default: // default:
{ // {
// fallback: raw text // // fallback: raw text
panel.Children.Add(new TextBlock { Text = block.ToString() }); // panel.Children.Add(new TextBlock { Text = block.ToString() });
break; // break;
} // }
} // }
} // }
//
return panel; // return panel;
} catch (Exception ex) { Logger.Log($"Error while : {ex.Message}",Logger.LogType.Error);} // } catch (Exception ex) { Logger.Log($"Error while : {ex.Message}",Logger.LogType.Error);}
//
return new Panel(); // return new Panel();
} // }
//
private static string GetInlineText(ContainerInline? container) // private static string GetInlineText(ContainerInline? container)
{ // {
try // try
{ // {
if (container == null) return string.Empty; // if (container == null) return string.Empty;
var sb = new StringBuilder(); // var sb = new StringBuilder();
foreach (var inline in container) // foreach (var inline in container)
{ // {
switch (inline) // switch (inline)
{ // {
case LiteralInline li: // case LiteralInline li:
sb.Append(li.Content.ToString()); // sb.Append(li.Content.ToString());
break; // break;
case EmphasisInline ei: // case EmphasisInline ei:
sb.Append(GetInlineText(ei)); // sb.Append(GetInlineText(ei));
break; // break;
case CodeInline ci: // case CodeInline ci:
sb.Append(ci.Content); // sb.Append(ci.Content);
break; // break;
case LinkInline li: // case LinkInline li:
sb.Append(GetInlineText(li)); // sb.Append(GetInlineText(li));
break; // break;
case LineBreakInline: // case LineBreakInline:
sb.Append("\n"); // sb.Append("\n");
break; // break;
default: // default:
sb.Append(inline.ToString()); // sb.Append(inline.ToString());
break; // break;
} // }
} // }
//
return sb.ToString(); // return sb.ToString();
} catch (Exception ex) { Logger.Log($"Error while : {ex.Message}",Logger.LogType.Error);} // } catch (Exception ex) { Logger.Log($"Error while : {ex.Message}",Logger.LogType.Error);}
//
return null; // return null;
} // }
} }