diff --git a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
index 499c7cd9a0f..e2d8499d75a 100644
--- a/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
+++ b/src/BootstrapBlazor.Server/BootstrapBlazor.Server.csproj
@@ -49,6 +49,7 @@
+
diff --git a/src/BootstrapBlazor.Server/Components/Pages/Coms.razor b/src/BootstrapBlazor.Server/Components/Pages/Coms.razor
index f42765c165a..9b01b6ec053 100644
--- a/src/BootstrapBlazor.Server/Components/Pages/Coms.razor
+++ b/src/BootstrapBlazor.Server/Components/Pages/Coms.razor
@@ -120,6 +120,7 @@
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor b/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor
new file mode 100644
index 00000000000..35a3b084ae2
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor
@@ -0,0 +1,30 @@
+@page "/mermaid"
+@inject IStringLocalizer Localizer
+
+@Localizer["MermaidTitle"]
+
+@Localizer["MermaidDescription"]
+
+
+
+
+
+ @foreach (var diagram in Diagrams)
+ {
+
+ }
+
+
+
+
+
+
+
+
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor.cs
new file mode 100644
index 00000000000..1a73ac981ce
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Components/Samples/Mermaids.razor.cs
@@ -0,0 +1,211 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License
+// See the LICENSE file in the project root for more information.
+// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
+
+using System.ComponentModel;
+
+namespace BootstrapBlazor.Server.Components.Samples;
+
+///
+/// MermaidViews
+///
+public partial class Mermaids
+{
+ private MermaidType Options { get; set; } = new();
+
+ private string CustomStyleString { get; } = """
+ flowchart LR
+ A[start] -->
+ B{Whether the conditions are met?}
+ B -- yes --> C[Perform tasks 1]
+ B -- no --> D[Perform tasks 2]
+ C --> E{Condition checks}
+ D --> E
+ E -- The conditions are established --> F[Sub-processes]
+ F --> G[Complete the subprocess]
+ E -- The condition failed --> H[Error handling]
+ H --> I[Keep a log]
+ G --> J[end]
+ I --> J
+
+ style A fill:#ffe0b3,stroke:#ff9900,stroke-width:2px;
+ style B fill:#ffcccc,stroke:#ff0000,stroke-width:2px;
+ style C fill:#e6ffcc,stroke:#009933,stroke-width:2px;
+ style D fill:#cce6ff,stroke:#0033cc,stroke-width:2px;
+ style E fill:#ffccff,stroke:#9900cc,stroke-width:2px;
+ style F fill:#ccccff,stroke:#3300cc,stroke-width:2px;
+ style G fill:#b3ffff,stroke:#00cccc,stroke-width:2px;
+ style H fill:#ffd9b3,stroke:#ff6600,stroke-width:2px;
+ style I fill:#d9d9d9,stroke:#808080,stroke-width:2px;
+ style J fill:#ccffcc,stroke:#009900,stroke-width:2px;
+
+ linkStyle 0 stroke:#00cc00,stroke-width:2px;
+ linkStyle 1 fill:#006600,stroke:#009933,stroke-width:2px,font-size:12px;
+ linkStyle 2 fill:#990000,stroke:#ff3300,stroke-width:2px,font-size:12px;
+ linkStyle 3 stroke:#ff33cc,stroke-width:2px;
+ linkStyle 4 stroke:#cc33ff,stroke-width:2px;
+ linkStyle 5 stroke:#33ccff,stroke-width:2px;
+ linkStyle 6 stroke:#ff6600,stroke-width:2px,stroke-dasharray: 10,10;
+ linkStyle 7 stroke:#999999,stroke-width:2px;
+ linkStyle 8 stroke:#009900,stroke-width:2px;
+ linkStyle 9 stroke:#ff6600,stroke-width:2px;
+ """;
+
+ private Dictionary Diagrams { get; } = new Dictionary
+ {
+ { MermaidType.None,
+ """
+ flowchart LR
+
+ A[Hard] -->|Text| B(Round)
+ B --> C{Decision}
+ C -->|One| D[Result 1]
+ C -->|Two| E[Result 2]
+ """
+ },
+ { MermaidType.Flowchart,
+ """
+ A[Start] --> B{Is it working?}
+ B -- Yes --> C[Keep going]
+ B -- No --> D[Fix it]
+ D --> B
+ """
+ },
+ { MermaidType.SequenceDiagram,
+ """
+ participant Alice
+ participant Bob
+ Alice->>John: Hello John, how are you?
+ loop HealthCheck
+ John->>John: Fight against hypochondria
+ end
+ Note right of John: Rational thoughts
prevail!
+ John-->>Alice: Great!
+ John->>Bob: How about you?
+ Bob-->>John: Jolly good!
+ """
+ },
+ { MermaidType.ClassDiagram,
+ """
+ Class01 <|-- AveryLongClass : Cool
+ Class03 *-- Class04
+ Class05 o-- Class06
+ Class07 .. Class08
+ Class09 --> C2 : Where am i?
+ Class09 --* C3
+ Class09 --|> Class07
+ Class07 : equals()
+ Class07 : Object[] elementData
+ Class01 : size()
+ Class01 : int chimp
+ Class01 : int gorilla
+ Class08 <--> C2: Cool label
+ """
+ },
+ { MermaidType.StateDiagram,
+ """
+ [*] --> Still
+ Still --> [*]
+
+ Still --> Moving
+ Moving --> Still
+ Moving --> Crash
+ Crash --> [*]
+ """
+ },
+ { MermaidType.ErDiagram,
+ """
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
+ """
+ },
+ { MermaidType.Journey,
+ """
+ section Go to work
+ Make tea: 5: Me
+ Go upstairs: 3: Me
+ Do work: 1: Me, Cat
+ section Go home
+ Go downstairs: 5: Me
+ Sit down: 5: Me
+ """
+ },
+ { MermaidType.Gantt,
+ """
+ dateFormat YYYY-MM-DD
+ excludes weekdays 2014-01-10
+
+ section A section
+ Completed task :done, des1, 2014-01-06,2014-01-08
+ Active task :active, des2, 2014-01-09, 3d
+ Future task : des3, after des2, 5d
+ Future task2 : des4, after des3, 5d
+ """
+ },
+ { MermaidType.Pie,
+ """
+ "Dogs" : 386
+ "Cats" : 85
+ "Rats" : 15
+ """
+ }
+ };
+
+ ///
+ /// GetAttributes
+ ///
+ ///
+ private AttributeItem[] GetAttributes() =>
+ [
+ new()
+ {
+ Name = "DiagramString",
+ Description = Localizer["DiagramString"],
+ Type = "string",
+ ValueList = " — ",
+ DefaultValue = " — "
+ },
+
+ new()
+ {
+ Name = "Title",
+ Description = Localizer["Title"],
+ Type = "string",
+ ValueList = " — ",
+ DefaultValue = " — "
+ },
+ new()
+ {
+ Name = "Direction",
+ Description = Localizer["Direction"],
+ Type = "MermaidDirection",
+ ValueList = "TB / BT / LR / RL",
+ DefaultValue = "TB"
+ },
+ new()
+ {
+ Name = "Type",
+ Description = Localizer["Type"],
+ Type = "MermaidType",
+ ValueList = "None / Flowchart / SequenceDiagram / ClassDiagram / StateDiagram / ErDiagram / Journey / Gantt / Pie",
+ DefaultValue = "None"
+ }
+ ];
+
+ ///
+ /// Methods
+ ///
+ ///
+ private MethodItem[] GetMethods() =>
+ [
+ new()
+ {
+ Name = "ExportBase64MermaidAsync",
+ Description = Localizer["ExportBase64Mermaid"],
+ Parameters = " — ",
+ ReturnValue = "string"
+ }
+ ];
+}
diff --git a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
index f97d3f60ad3..c93338281a2 100644
--- a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
+++ b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
@@ -657,6 +657,11 @@ void AddData(DemoMenuItem item)
Url = "mind-map"
},
new()
+ {
+ Text = Localizer["Mermaid"],
+ Url = "mermaid"
+ },
+ new()
{
Text = Localizer["PdfReader"],
Url = "pdf-reader"
diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json
index cf20ef6f8a1..664730ddd15 100644
--- a/src/BootstrapBlazor.Server/Locales/en-US.json
+++ b/src/BootstrapBlazor.Server/Locales/en-US.json
@@ -1696,6 +1696,7 @@
"FileViewerText": "FileViewer",
"WebSerialText": "SerialService",
"MindMapText": "MindMap",
+ "MermaidText": "Mermaid",
"WebSpeechText": "WebSpeech",
"ImageCropperText": "ImageCropper",
"BarcodeGeneratorText": "BarcodeGenerator"
@@ -4768,6 +4769,7 @@
"QueryBuilder": "QueryBuilder",
"SerialService": "ISerialService",
"MindMap": "Mind Map",
+ "Mermaid": "Mermaid",
"Marquee": "Marquee",
"Stack": "Stack",
"Segmented": "Segmented",
@@ -6359,6 +6361,15 @@
"Layout": "Layout",
"Theme": "Theme"
},
+ "BootstrapBlazor.Server.Components.Samples.Mermaids": {
+ "MermaidTitle": "Mermaid",
+ "MermaidDescription": "This component renders Markdown-inspired text definitions to dynamically create and modify diagrams.",
+ "MermaidNormalTitle": "Basic usage",
+ "NormalIntro": "Mermaid basic style",
+ "MermaidStyleTitle": "Custom styles",
+ "MermaidStyleIntro": "",
+ "MermaidType": "Type"
+ },
"BootstrapBlazor.Server.Components.Samples.Speeches.WebSpeeches": {
"WebSpeechTitle": "Web Speech Api",
"WebSpeechSubTitle": "Provide speech recognition/synthesis services using browser interface functions",
diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json
index 9dbb3e0df12..2b11d8fb889 100644
--- a/src/BootstrapBlazor.Server/Locales/zh-CN.json
+++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json
@@ -1696,6 +1696,7 @@
"FileViewerText": "文件预览器 FileViewer",
"WebSerialText": "串口服务 ISerialService",
"MindMapText": "思维导图 Mind Map",
+ "MermaidText": "图表工具 Mermaid",
"WebSpeechText": "语音识别/合成 WebSpeech",
"ImageCropperText": "图像裁剪 ImageCropper",
"BarcodeGeneratorText": "条码生成器 BarcodeGenerator"
@@ -4768,6 +4769,7 @@
"QueryBuilder": "条件生成器 QueryBuilder",
"WebSerial": "串口服务 ISerialService",
"MindMap": "思维导图 MindMap",
+ "Mermaid": "图表工具 Mermaid",
"Marquee": "文字滚动 Marquee",
"Stack": "堆叠布局 Stack",
"Segmented": "分段控制器 Segmented",
@@ -6359,6 +6361,15 @@
"Layout": "布局",
"Theme": "主题"
},
+ "BootstrapBlazor.Server.Components.Samples.Mermaids": {
+ "MermaidTitle": "Mermaid 构图工具",
+ "MermaidDescription": "本组件可渲染 Markdown 启发的文本定义以动态创建和修改图表。",
+ "MermaidNormalTitle": "基本用法",
+ "MermaidNormalIntro": "Mermaid 基本样式",
+ "MermaidStyleTitle": "增加自定义样式",
+ "MermaidStyleIntro": "",
+ "MermaidType": "图表类型"
+ },
"BootstrapBlazor.Server.Components.Samples.Speeches.WebSpeeches": {
"WebSpeechTitle": "Web Speech Api 网页原生语音处理 API",
"WebSpeechSubTitle": "使用浏览器接口功能提供语音识别/合成服务",
diff --git a/src/BootstrapBlazor.Server/docs.json b/src/BootstrapBlazor.Server/docs.json
index 87b91f4b556..cd8baaa8c40 100644
--- a/src/BootstrapBlazor.Server/docs.json
+++ b/src/BootstrapBlazor.Server/docs.json
@@ -111,6 +111,7 @@
"menu": "Menus",
"message": "Messages",
"mind-map": "MindMaps",
+ "mermaid": "Mermaids",
"modal": "Modals",
"mouse-follower": "MouseFollowers",
"multi-select": "MultiSelects",
diff --git a/src/BootstrapBlazor.Server/wwwroot/images/Mermaid.png b/src/BootstrapBlazor.Server/wwwroot/images/Mermaid.png
new file mode 100644
index 00000000000..24e91a7a384
Binary files /dev/null and b/src/BootstrapBlazor.Server/wwwroot/images/Mermaid.png differ