Add Mermaid support and .mmd detection #1893
build / build (push) Has been cancelled
build / publish (push) Has been cancelled

This commit is contained in:
ema
2026-03-27 10:45:20 +08:00
parent 20df0b2889
commit ae67d5247c
4 changed files with 81 additions and 8 deletions
@@ -78,6 +78,7 @@ public class MarkdownPanel : WebpagePanel
var bytes = File.ReadAllBytes(path);
var encoding = CharsetDetector.DetectFromBytes(bytes).Detected?.Encoding ?? Encoding.Default;
var content = encoding.GetString(bytes);
content = PrepareMarkdownContent(path, content);
var template = ReadString("/md2html.html");
@@ -99,6 +100,75 @@ public class MarkdownPanel : WebpagePanel
return html;
}
private static string PrepareMarkdownContent(string path, string content)
{
var extension = Path.GetExtension(path);
if (extension.Equals(".mermaid", StringComparison.OrdinalIgnoreCase))
return WrapAsMermaidCodeFence(content);
if (extension.Equals(".mmd", StringComparison.OrdinalIgnoreCase)
&& IsLikelyMermaidDocument(content))
return WrapAsMermaidCodeFence(content);
return content;
}
private static string WrapAsMermaidCodeFence(string content)
{
var normalized = content.Replace("\r\n", "\n").Trim('\n');
return $"```mermaid\n{normalized}\n```";
}
private static bool IsLikelyMermaidDocument(string content)
{
if (string.IsNullOrWhiteSpace(content))
return false;
if (content.IndexOf("```mermaid", StringComparison.OrdinalIgnoreCase) >= 0)
return false;
using var reader = new StringReader(content);
string line;
while ((line = reader.ReadLine()) != null)
{
var trimmed = line.Trim();
if (trimmed.Length == 0 || trimmed.StartsWith("%%", StringComparison.Ordinal))
continue;
return trimmed.StartsWith("graph ", StringComparison.OrdinalIgnoreCase)
|| trimmed.Equals("graph", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("flowchart ", StringComparison.OrdinalIgnoreCase)
|| trimmed.Equals("flowchart", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("sequenceDiagram", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("classDiagram", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("stateDiagram", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("stateDiagram-v2", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("erDiagram", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("journey", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("gantt", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("pie", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("mindmap", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("timeline", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("gitGraph", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("quadrantChart", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("requirementDiagram", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("c4Context", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("c4Container", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("c4Component", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("c4Dynamic", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("c4Deployment", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("xychart-beta", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("block-beta", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("packet-beta", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("architecture-beta", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("kanban", StringComparison.OrdinalIgnoreCase)
|| trimmed.StartsWith("sankey-beta", StringComparison.OrdinalIgnoreCase);
}
return false;
}
protected override void WebView_WebResourceRequested(object sender, CoreWebView2WebResourceRequestedEventArgs args)
{
Debug.WriteLine($"[{args.Request.Method}] {args.Request.Uri}");