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
+7 -6
View File
@@ -10,8 +10,9 @@
> Nevertheless, QuickLook has chosen to continue with an up-to-date update strategy.
>
> If you encounter any issues, you can refer to [#1362](https://github.com/QL-Win/QuickLook/issues/1362) and consider downgrading your LAVFilters version.
- Improve LRC handling by merging duplicate timestamps [#1858](https://github.com/QL-Win/QuickLook/issues/1858)
- Improve the translation of Simplified Chinese by [@stxttkx](https://github.com/stxttkx)
- Add PKCS7 extensions to supported file types (`.p7s` and `.pkcs7`)
- Add support Fortran95 (`.f90`, `.f95`, `.f03`), GDScript (`.gd`), Diff (`.patch`, `.rej`), Razor (`.cshtml`, `.razor`), ActionScript (`.as`, `.mx`), Assembly (`.asm`), Ada (`.ada`, `.ads`, `.adb`), AutoHotkey (`.ahk`), Rhai (`.rhai`), C++ ( `.cu`, `.cuh`, `.hip`), Python (`.pyx`), PlantUML (`.puml`, `.plantuml`, `.pu`, `.uml`, `.iuml`, `.wsd`), Zig (`.zig`), Moji (`.moji`), GraphQL (`.graphql`, `.gql`, `.gqls`), Mermaid (`.mmd`, `.mermaid`), KQL (`.kql`), PromQL (`.promql`), ANTLR, Boo, Ceylon, ChucK, Clojure, Cocoa, CoffeeScript, Cool, and others syntax highlighting, including the dark mode theme
- Add support Chromium `.pak` viewer and file extraction
@@ -19,17 +20,17 @@
- Add `.cursorignore` extension to GitIgnore syntax
- Add support for Python `.whl` and `.egg` archives
- Add support `.psv` parsing in CsvViewer
- Add Mermaid (`.mermaid`) support and `.mmd` detection [#1893](https://github.com/QL-Win/QuickLook/issues/1893)
- Add plugin icon registration and include `QLPlugin.ico` designed by [@Shomnipotence](https://github.com/Shomnipotence)
- Add DICOM image support to ImageViewer plugin [#1866](https://github.com/QL-Win/QuickLook/issues/1866) `This is not a long-lasting built-in plugin`
- Add Romanian translation by [@Laszlo19](https://github.com/Laszlo19)
- Fix markdown not supporting absolute resource paths
- Fix option `<UseTransparency>False</UseTransparency>` not taking effect in Windows 10 [#1542](https://github.com/QL-Win/QuickLook/issues/1542)
- Fix loop toggle resuming paused video playback [#1852](https://github.com/QL-Win/QuickLook/issues/1852)
- Fix unhandled Exception with XLSX and CSV files in OfficeViewer resize with `RPC_E_CANTCALLOUT_ININPUTSYNCCALL` [#1854](https://github.com/QL-Win/QuickLook/issues/1854)
- Fix command line relative path resolution [#1857](https://github.com/QL-Win/QuickLook/issues/1857)
- Fix taskbar icon intermittently missing after Explorer restart [#1864](https://github.com/QL-Win/QuickLook/issues/1864)
- Fix `{Desktop composition is disabled}` exceptions in GetMonitorColorProfileFromWindow [#4](https://github.com/QL-Win/QuickLook.Common/pull/4)
- Add plugin icon registration and include `QLPlugin.ico` designed by [@Shomnipotence](https://github.com/Shomnipotence)
- Add DICOM image support to ImageViewer plugin [#1866](https://github.com/QL-Win/QuickLook/issues/1866) `This is not a long-lasting built-in plugin`
- Add Romanian translation by [@Laszlo19](https://github.com/Laszlo19)
- Updated the translation of Simplified Chinese by [@stxttkx](https://github.com/stxttkx)
- Fix `{Desktop composition is disabled}` exceptions in `GetMonitorColorProfileFromWindow` [#4](https://github.com/QL-Win/QuickLook.Common/pull/4)
## 4.4.0
@@ -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}");
@@ -35,7 +35,8 @@ public sealed class Plugin : IViewer
[
".md", ".markdown", // The most common Markdown extensions
".mdx", // MDX (Markdown + JSX), used in React ecosystems
".mmd", // MultiMarkdown (MMD), an extended version of Markdown
".mmd", // MultiMarkdown (MMD), an extended version of Markdown or Mermaid diagram source file
".mermaid", // Mermaid diagram source file
".mkd", ".mdwn", ".mdown", // Early Markdown variants, used by different parsers like Pandoc, Gitit, and Hakyll
".mdc", // A Markdown variant used by Cursor AI [Repeated format from ImageViewer]
".qmd", // Quarto Markdown, developed by RStudio for scientific computing and reproducible reports
+2 -1
View File
@@ -224,7 +224,8 @@ Update not completed yet...
### Markdown files
- `.md`, `.markdown` (Markdown)
- `.mdx` (MDX: Markdown + JSX)
- `.mmd` (MultiMarkdown)
- `.mmd` (MultiMarkdown or Mermaid diagram source)
- `.mermaid` (Mermaid diagram source)
- `.mkd`, `.mdwn`, `.mdown` (Markdown variants)
- `.mdc` (Cursor AI Markdown)
- `.qmd` (Quarto Markdown)