orbitchat 2.14.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/ChartRenderer-B1mYF_kk.js +80 -0
- package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/MermaidRenderer-Dhffx5mc.js +260 -0
- package/dist/assets/MusicRenderer-DbXJ8e4-.js +18 -0
- package/dist/assets/SVGRenderer-EhamRX_K.js +6 -0
- package/dist/assets/_basePickBy-C2AibBqo.js +1 -0
- package/dist/assets/_baseUniq-D52pUSvn.js +1 -0
- package/dist/assets/arc-BSnyvXPh.js +1 -0
- package/dist/assets/architectureDiagram-VXUJARFQ-BLMvVsZu.js +36 -0
- package/dist/assets/band-CquvqAHh.js +1 -0
- package/dist/assets/blockDiagram-VD42YOAC-CTz0dv5u.js +122 -0
- package/dist/assets/c4Diagram-YG6GDRKO-BjbN-GGh.js +10 -0
- package/dist/assets/channel-ryTtfXZE.js +1 -0
- package/dist/assets/chunk-4BX2VUAB-DEMWGIsU.js +1 -0
- package/dist/assets/chunk-55IACEB6-BYaauHLT.js +1 -0
- package/dist/assets/chunk-B4BG7PRW-D3_GFcfd.js +165 -0
- package/dist/assets/chunk-DI55MBZ5-Dy2EuzfA.js +220 -0
- package/dist/assets/{chunk-FMBD7UC4-dPK7Boav-Cz7OoDLR.js → chunk-FMBD7UC4-C9XHmwza.js} +2 -2
- package/dist/assets/chunk-QN33PNHL-BOCltIi9.js +1 -0
- package/dist/assets/chunk-QZHKN3VN-CvA964eQ.js +1 -0
- package/dist/assets/chunk-TZMSLE5B-B-3rZz90.js +1 -0
- package/dist/assets/classDiagram-2ON5EDUG-VbShFIzz.js +1 -0
- package/dist/assets/classDiagram-v2-WZHVMYZB-VbShFIzz.js +1 -0
- package/dist/assets/clone-BlhdKVDQ.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-CzPip3he.js +1 -0
- package/dist/assets/cytoscape.esm-CyJtwmzi.js +331 -0
- package/dist/assets/dagre-6UL2VRFP-CfCXYus3.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-PSM6KHXK-DyI2eDqp.js +24 -0
- package/dist/assets/diagram-QEK2KX5R-DuakIh40.js +43 -0
- package/dist/assets/diagram-S2PKOQOG-C3-4IORM.js +24 -0
- package/dist/assets/erDiagram-Q2GNP2WA-Dt-nZEaD.js +60 -0
- package/dist/assets/flowDiagram-NV44I4VS-B-2wjyTQ.js +162 -0
- package/dist/assets/ganttDiagram-JELNMOA3-CHTvjPq0.js +267 -0
- package/dist/assets/gitGraphDiagram-V2S2FVAM-d5GWmgY4.js +65 -0
- package/dist/assets/graph-COgkbiU8.js +1 -0
- package/dist/assets/index-DN2bBcCs.js +134 -0
- package/dist/assets/index-DtztdW2a.js +643 -0
- package/dist/assets/index-lGqyWNWb.css +1 -0
- package/dist/assets/infoDiagram-HS3SLOUP-30Hn0iLj.js +2 -0
- package/dist/assets/init-Dmth1JHB.js +1 -0
- package/dist/assets/journeyDiagram-XKPGCS4Q-CMOYXQ79.js +139 -0
- package/dist/assets/kanban-definition-3W4ZIXB7-dt3376cq.js +89 -0
- package/dist/assets/layout-DH97sy5g.js +1 -0
- package/dist/assets/linear-CKzVTQ0r.js +1 -0
- package/dist/assets/mindmap-definition-VGOIOE7T-BcZHPAlA.js +68 -0
- package/dist/assets/ordinal-DILIJJjt.js +1 -0
- package/dist/assets/pieDiagram-ADFJNKIX-DXjvgcgl.js +30 -0
- package/dist/assets/purify.es-A66Cw1IH.js +2 -0
- package/dist/assets/quadrantDiagram-AYHSOK5B-CICk2FdS.js +7 -0
- package/dist/assets/requirementDiagram-UZGBJVZJ-BdtxpQRA.js +64 -0
- package/dist/assets/sankeyDiagram-TZEHDZUN-BVNS9BQJ.js +10 -0
- package/dist/assets/sequenceDiagram-WL72ISMW-DF4fJTM7.js +145 -0
- package/dist/assets/stateDiagram-FKZM4ZOC-C8H8HujX.js +1 -0
- package/dist/assets/stateDiagram-v2-4FDKWEC3-DwtU033b.js +1 -0
- package/dist/assets/step-EjIQ8UIn.js +1 -0
- package/dist/assets/time-h5EapSZu.js +1 -0
- package/dist/assets/timeline-definition-IT6M3QCI-DUSG5Vfy.js +61 -0
- package/dist/assets/treemap-GDKQZRPO-1PI2PY4S.js +160 -0
- package/dist/assets/xychartDiagram-PRI3JC2R-CFPJj8WK.js +7 -0
- package/dist/favicon.svg +3 -1
- package/dist/index.html +2 -2
- package/markdown-renderer/LICENSE +201 -0
- package/markdown-renderer/src/CodeBlock.tsx +332 -0
- package/markdown-renderer/src/MarkdownComponents.tsx +233 -0
- package/markdown-renderer/src/MarkdownStyles.css +668 -0
- package/markdown-renderer/src/css.d.ts +4 -0
- package/markdown-renderer/src/index.ts +32 -0
- package/markdown-renderer/src/preprocessing.ts +519 -0
- package/markdown-renderer/src/renderers/ChartRenderer.tsx +1434 -0
- package/markdown-renderer/src/renderers/MermaidRenderer.tsx +474 -0
- package/markdown-renderer/src/renderers/MusicRenderer.tsx +394 -0
- package/markdown-renderer/src/renderers/SVGRenderer.tsx +307 -0
- package/markdown-renderer/src/types.ts +174 -0
- package/package.json +25 -3
- package/dist/assets/_baseUniq-BRKsqoH--68FUaYxk.js +0 -1
- package/dist/assets/arc-pab_su9s-BuY-VRZt.js +0 -1
- package/dist/assets/architectureDiagram-VXUJARFQ-DqQ8r_6g-C5b5VsO8.js +0 -36
- package/dist/assets/blockDiagram-VD42YOAC-B-dKfcH3-DVjqMJ-3.js +0 -122
- package/dist/assets/c4Diagram-YG6GDRKO-DMUPaBEl-o6ghjFV9.js +0 -10
- package/dist/assets/channel-HKsfPa5q-rOME8XF8.js +0 -1
- package/dist/assets/chunk-4BX2VUAB-CX67kh_B-Dl0Loq_e.js +0 -1
- package/dist/assets/chunk-55IACEB6-BocSyyvr-DYW83vZR.js +0 -1
- package/dist/assets/chunk-B4BG7PRW-CO8QAyfE-CsF1OX4R.js +0 -165
- package/dist/assets/chunk-DI55MBZ5-Dw1L6Eos-Dl1shJzL.js +0 -220
- package/dist/assets/chunk-QN33PNHL-vP2PqfVG-BuQNN8G2.js +0 -1
- package/dist/assets/chunk-QZHKN3VN-Bcidzu63-Bud1NKOb.js +0 -1
- package/dist/assets/chunk-TZMSLE5B-BtljMjlg-BKLxPJ-x.js +0 -1
- package/dist/assets/classDiagram-2ON5EDUG-C7cYN9hv-BHg-LSxQ.js +0 -1
- package/dist/assets/classDiagram-v2-WZHVMYZB-C7cYN9hv-BHg-LSxQ.js +0 -1
- package/dist/assets/clone-DoPb9X13-DejjKfXe.js +0 -1
- package/dist/assets/cose-bilkent-S5V4N54A-BGzO4EsH-rofdToAx.js +0 -1
- package/dist/assets/cytoscape.esm-CjI2IsL8-Da6dFVsf.js +0 -331
- package/dist/assets/dagre-6UL2VRFP-TzNvXCds-Ls1mVyc7.js +0 -4
- package/dist/assets/diagram-PSM6KHXK-BqY4RpUg-BJmYXUei.js +0 -24
- package/dist/assets/diagram-QEK2KX5R-CTjgBsne-dz-VLadE.js +0 -43
- package/dist/assets/diagram-S2PKOQOG-BqrhTIpA-ikxUE9Dj.js +0 -24
- package/dist/assets/erDiagram-Q2GNP2WA-B2hsi_Tl-B5gu6Jrx.js +0 -60
- package/dist/assets/flowDiagram-NV44I4VS-C03vtt_F-C9LVdVvn.js +0 -162
- package/dist/assets/ganttDiagram-JELNMOA3-B3hAg964-CYO6ZcQ8.js +0 -267
- package/dist/assets/gitGraphDiagram-NY62KEGX-ByhMH0yZ-BvO0WGzP.js +0 -65
- package/dist/assets/graph-BmNkcFEM-Bl2fiTgr.js +0 -1
- package/dist/assets/index-BXexqYFc-CFPIFV8r.js +0 -134
- package/dist/assets/index-KsGsuMGp.css +0 -1
- package/dist/assets/index-nqhgVFEP.js +0 -1010
- package/dist/assets/infoDiagram-WHAUD3N6-is6Ho4-T-D6tHdi3J.js +0 -2
- package/dist/assets/journeyDiagram-XKPGCS4Q-CRTOL26C-CL4DFaQP.js +0 -139
- package/dist/assets/kanban-definition-3W4ZIXB7-CNnO_t6O-DZBlsSao.js +0 -89
- package/dist/assets/layout-C0kZPebx-DiUdszUx.js +0 -1
- package/dist/assets/min-7Gb0pNxh-DsojA8pm.js +0 -1
- package/dist/assets/mindmap-definition-VGOIOE7T-CJZ2wTTa-Cd46k2jT.js +0 -68
- package/dist/assets/pieDiagram-ADFJNKIX-C9OSknjr-BGVcHmss.js +0 -30
- package/dist/assets/quadrantDiagram-AYHSOK5B-CW8yuAqv-CrCYjmJT.js +0 -7
- package/dist/assets/requirementDiagram-UZGBJVZJ-nGPhruO1-BzOGHXGi.js +0 -64
- package/dist/assets/sankeyDiagram-TZEHDZUN-CmL90u-m-BWp9STLO.js +0 -10
- package/dist/assets/sequenceDiagram-WL72ISMW-B02VRcnM-DB4Adljk.js +0 -145
- package/dist/assets/stateDiagram-FKZM4ZOC-DjoyLUdz-pDyQ50aU.js +0 -1
- package/dist/assets/stateDiagram-v2-4FDKWEC3-Bq76BTB7-C3j4gDpN.js +0 -1
- package/dist/assets/timeline-definition-IT6M3QCI-CTn0Gm3T-O1FhSixZ.js +0 -61
- package/dist/assets/treemap-KMMF4GRG-BjgLKKyi-DG8IQefJ.js +0 -128
- package/dist/assets/xychartDiagram-PRI3JC2R-Cgg6Uija-CPVch5-l.js +0 -7
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import mermaid from 'mermaid';
|
|
3
|
+
import type { MermaidRendererProps } from '../types';
|
|
4
|
+
|
|
5
|
+
type MermaidTheme = 'light' | 'dark';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_THEME_VARIABLES: Record<MermaidTheme, Record<string, string>> = {
|
|
8
|
+
light: {
|
|
9
|
+
background: '#ffffff',
|
|
10
|
+
primaryColor: '#e0e7ff',
|
|
11
|
+
secondaryColor: '#ddd6fe',
|
|
12
|
+
tertiaryColor: '#fce7f3',
|
|
13
|
+
primaryTextColor: '#111827',
|
|
14
|
+
secondaryTextColor: '#4b5563',
|
|
15
|
+
primaryBorderColor: '#6366f1',
|
|
16
|
+
lineColor: '#111827',
|
|
17
|
+
// Pie chart specific
|
|
18
|
+
pie1: '#3b82f6',
|
|
19
|
+
pie2: '#8b5cf6',
|
|
20
|
+
pie3: '#ec4899',
|
|
21
|
+
pie4: '#f59e0b',
|
|
22
|
+
pie5: '#10b981',
|
|
23
|
+
pie6: '#06b6d4',
|
|
24
|
+
pie7: '#6366f1',
|
|
25
|
+
pie8: '#ef4444',
|
|
26
|
+
pieStrokeColor: '#ffffff',
|
|
27
|
+
pieStrokeWidth: '2px',
|
|
28
|
+
pieTitleTextColor: '#111827',
|
|
29
|
+
pieLegendTextColor: '#374151',
|
|
30
|
+
},
|
|
31
|
+
dark: {
|
|
32
|
+
background: '#1e293b',
|
|
33
|
+
primaryColor: '#3b82f6',
|
|
34
|
+
secondaryColor: '#8b5cf6',
|
|
35
|
+
tertiaryColor: '#6366f1',
|
|
36
|
+
primaryTextColor: '#f1f5f9',
|
|
37
|
+
secondaryTextColor: '#cbd5e1',
|
|
38
|
+
primaryBorderColor: '#60a5fa',
|
|
39
|
+
lineColor: '#f1f5f9',
|
|
40
|
+
// Pie chart specific - brighter colors for dark mode
|
|
41
|
+
pie1: '#60a5fa',
|
|
42
|
+
pie2: '#a78bfa',
|
|
43
|
+
pie3: '#f472b6',
|
|
44
|
+
pie4: '#fbbf24',
|
|
45
|
+
pie5: '#34d399',
|
|
46
|
+
pie6: '#22d3ee',
|
|
47
|
+
pie7: '#818cf8',
|
|
48
|
+
pie8: '#f87171',
|
|
49
|
+
pieStrokeColor: '#1e293b',
|
|
50
|
+
pieStrokeWidth: '2px',
|
|
51
|
+
pieTitleTextColor: '#f1f5f9',
|
|
52
|
+
pieLegendTextColor: '#e2e8f0',
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Initialize mermaid once
|
|
57
|
+
let mermaidInitialized = false;
|
|
58
|
+
const initializeMermaid = () => {
|
|
59
|
+
if (typeof window === 'undefined' || mermaidInitialized) return;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
mermaid.initialize({
|
|
63
|
+
startOnLoad: false,
|
|
64
|
+
theme: 'default',
|
|
65
|
+
securityLevel: 'loose',
|
|
66
|
+
themeVariables: DEFAULT_THEME_VARIABLES.light,
|
|
67
|
+
});
|
|
68
|
+
mermaidInitialized = true;
|
|
69
|
+
} catch (err) {
|
|
70
|
+
console.warn('Failed to initialize Mermaid:', err);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const formatMermaidError = (err: unknown): string => {
|
|
75
|
+
let errorMessage = 'Failed to render Mermaid diagram';
|
|
76
|
+
|
|
77
|
+
if (err instanceof Error) {
|
|
78
|
+
const message = err.message || '';
|
|
79
|
+
|
|
80
|
+
if (message.includes('Syntax error')) {
|
|
81
|
+
const lineMatch = message.match(/line\s+(\d+)/i);
|
|
82
|
+
const tokenMatch = message.match(/token\s+['"]([^'"]+)['"]/i);
|
|
83
|
+
const details = [];
|
|
84
|
+
|
|
85
|
+
if (lineMatch) details.push(`Line ${lineMatch[1]}`);
|
|
86
|
+
if (tokenMatch) details.push(`Unexpected token: ${tokenMatch[1]}`);
|
|
87
|
+
|
|
88
|
+
errorMessage = `Syntax error${details.length ? ` (${details.join(', ')})` : ''}`;
|
|
89
|
+
} else if (message) {
|
|
90
|
+
errorMessage = message.length > 160 ? `${message.substring(0, 157)}...` : message;
|
|
91
|
+
}
|
|
92
|
+
} else if (typeof err === 'string') {
|
|
93
|
+
errorMessage = err;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return errorMessage;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const readCSSVariable = (element: Element | null, name: string): string | undefined => {
|
|
100
|
+
if (typeof window === 'undefined' || !element) return undefined;
|
|
101
|
+
const value = window.getComputedStyle(element).getPropertyValue(name);
|
|
102
|
+
if (!value) return undefined;
|
|
103
|
+
const trimmed = value.trim();
|
|
104
|
+
return trimmed.length ? trimmed : undefined;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const resolveThemeVariables = (theme: MermaidTheme, element: Element | null) => {
|
|
108
|
+
const fallback = DEFAULT_THEME_VARIABLES[theme];
|
|
109
|
+
if (typeof window === 'undefined' || !element) {
|
|
110
|
+
return fallback;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const overrides: Record<string, string | undefined> = {
|
|
114
|
+
background: readCSSVariable(element, '--md-bg-primary'),
|
|
115
|
+
primaryColor: readCSSVariable(element, '--md-bg-secondary'),
|
|
116
|
+
secondaryColor: readCSSVariable(element, '--md-bg-tertiary'),
|
|
117
|
+
tertiaryColor: readCSSVariable(element, '--md-bg-primary'),
|
|
118
|
+
primaryTextColor: readCSSVariable(element, '--md-text-primary'),
|
|
119
|
+
secondaryTextColor: readCSSVariable(element, '--md-text-secondary'),
|
|
120
|
+
primaryBorderColor: readCSSVariable(element, '--md-border-color'),
|
|
121
|
+
lineColor: readCSSVariable(element, '--md-text-primary'),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const filteredEntries = Object.entries(overrides).filter(
|
|
125
|
+
([, value]) => typeof value === 'string' && value.length
|
|
126
|
+
) as Array<[string, string]>;
|
|
127
|
+
|
|
128
|
+
return filteredEntries.length ? { ...fallback, ...Object.fromEntries(filteredEntries) } : fallback;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const detectThemeFromElement = (element: Element | null): MermaidTheme | null => {
|
|
132
|
+
if (!element) return null;
|
|
133
|
+
|
|
134
|
+
const attr = element.getAttribute('data-theme');
|
|
135
|
+
if (attr === 'dark') return 'dark';
|
|
136
|
+
if (attr === 'light') return 'light';
|
|
137
|
+
|
|
138
|
+
if (element.classList.contains('dark')) return 'dark';
|
|
139
|
+
if (element.classList.contains('light')) return 'light';
|
|
140
|
+
|
|
141
|
+
return null;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const MermaidRenderer: React.FC<MermaidRendererProps> = ({ code }) => {
|
|
145
|
+
const hostRef = useRef<HTMLDivElement>(null);
|
|
146
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
147
|
+
const renderIdRef = useRef(0);
|
|
148
|
+
|
|
149
|
+
const [error, setError] = useState<string | null>(null);
|
|
150
|
+
const [svg, setSvg] = useState<string | null>(null);
|
|
151
|
+
const [bindFunctions, setBindFunctions] = useState<((element: Element) => void) | null>(null);
|
|
152
|
+
const [showErrorDetails, setShowErrorDetails] = useState(false);
|
|
153
|
+
const [theme, setTheme] = useState<MermaidTheme>('light');
|
|
154
|
+
const lastThemeRef = useRef<MermaidTheme>('light');
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (typeof window === 'undefined') return;
|
|
158
|
+
const host = hostRef.current;
|
|
159
|
+
if (!host) return;
|
|
160
|
+
|
|
161
|
+
const markdownRoot = host.closest('.markdown-content') ?? host;
|
|
162
|
+
const prefersDarkQuery = window.matchMedia?.('(prefers-color-scheme: dark)');
|
|
163
|
+
|
|
164
|
+
const readTheme = (): MermaidTheme => {
|
|
165
|
+
const prefersDark = Boolean(prefersDarkQuery?.matches);
|
|
166
|
+
return (
|
|
167
|
+
detectThemeFromElement(markdownRoot) ??
|
|
168
|
+
detectThemeFromElement(document.documentElement) ??
|
|
169
|
+
(prefersDark ? 'dark' : 'light')
|
|
170
|
+
);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const updateTheme = () => {
|
|
174
|
+
const next = readTheme();
|
|
175
|
+
// Only update if theme actually changed to prevent re-render loops
|
|
176
|
+
if (next !== lastThemeRef.current) {
|
|
177
|
+
lastThemeRef.current = next;
|
|
178
|
+
setTheme(next);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
updateTheme();
|
|
183
|
+
|
|
184
|
+
const observer = new MutationObserver(updateTheme);
|
|
185
|
+
observer.observe(markdownRoot, { attributes: true, attributeFilter: ['class', 'data-theme'] });
|
|
186
|
+
|
|
187
|
+
let docObserver: MutationObserver | null = null;
|
|
188
|
+
if (markdownRoot !== document.documentElement) {
|
|
189
|
+
docObserver = new MutationObserver(updateTheme);
|
|
190
|
+
docObserver.observe(document.documentElement, {
|
|
191
|
+
attributes: true,
|
|
192
|
+
attributeFilter: ['class', 'data-theme'],
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const handleMediaChange = () => updateTheme();
|
|
197
|
+
prefersDarkQuery?.addEventListener('change', handleMediaChange);
|
|
198
|
+
|
|
199
|
+
return () => {
|
|
200
|
+
observer.disconnect();
|
|
201
|
+
docObserver?.disconnect();
|
|
202
|
+
prefersDarkQuery?.removeEventListener('change', handleMediaChange);
|
|
203
|
+
};
|
|
204
|
+
}, []);
|
|
205
|
+
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if (!code.trim()) {
|
|
208
|
+
setSvg(null);
|
|
209
|
+
setError(null);
|
|
210
|
+
setBindFunctions(null);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const renderDiagram = async () => {
|
|
215
|
+
const currentRenderId = ++renderIdRef.current;
|
|
216
|
+
try {
|
|
217
|
+
initializeMermaid();
|
|
218
|
+
|
|
219
|
+
const diagramId = `mermaid-${Math.random().toString(36).substring(2, 11)}`;
|
|
220
|
+
|
|
221
|
+
// Parse early to provide clearer syntax errors and avoid throwing during render
|
|
222
|
+
await mermaid.parse(code);
|
|
223
|
+
|
|
224
|
+
const themeTarget = hostRef.current?.closest('.markdown-content') ?? hostRef.current;
|
|
225
|
+
const themeVariables = resolveThemeVariables(theme, themeTarget);
|
|
226
|
+
|
|
227
|
+
// Re-initialize mermaid with current theme before rendering
|
|
228
|
+
mermaid.initialize({
|
|
229
|
+
startOnLoad: false,
|
|
230
|
+
theme: theme === 'dark' ? 'dark' : 'default',
|
|
231
|
+
securityLevel: 'loose',
|
|
232
|
+
themeVariables,
|
|
233
|
+
// Optimized diagram settings for readability and compact display
|
|
234
|
+
flowchart: {
|
|
235
|
+
useMaxWidth: true,
|
|
236
|
+
htmlLabels: true,
|
|
237
|
+
curve: 'basis',
|
|
238
|
+
padding: 15,
|
|
239
|
+
nodeSpacing: 50,
|
|
240
|
+
rankSpacing: 50,
|
|
241
|
+
},
|
|
242
|
+
sequence: {
|
|
243
|
+
useMaxWidth: true,
|
|
244
|
+
diagramMarginX: 30,
|
|
245
|
+
diagramMarginY: 15,
|
|
246
|
+
actorMargin: 50,
|
|
247
|
+
width: 120,
|
|
248
|
+
height: 40,
|
|
249
|
+
boxMargin: 8,
|
|
250
|
+
boxTextMargin: 4,
|
|
251
|
+
noteMargin: 10,
|
|
252
|
+
messageMargin: 35,
|
|
253
|
+
mirrorActors: true,
|
|
254
|
+
actorFontSize: 13,
|
|
255
|
+
messageFontSize: 12,
|
|
256
|
+
noteFontSize: 12,
|
|
257
|
+
wrap: true,
|
|
258
|
+
wrapPadding: 10,
|
|
259
|
+
},
|
|
260
|
+
gantt: {
|
|
261
|
+
useMaxWidth: true,
|
|
262
|
+
barHeight: 24,
|
|
263
|
+
barGap: 4,
|
|
264
|
+
topPadding: 40,
|
|
265
|
+
leftPadding: 80,
|
|
266
|
+
gridLineStartPadding: 40,
|
|
267
|
+
fontSize: 12,
|
|
268
|
+
sectionFontSize: 13,
|
|
269
|
+
numberSectionStyles: 4,
|
|
270
|
+
},
|
|
271
|
+
er: {
|
|
272
|
+
useMaxWidth: true,
|
|
273
|
+
fontSize: 12,
|
|
274
|
+
entityPadding: 15,
|
|
275
|
+
},
|
|
276
|
+
pie: {
|
|
277
|
+
useMaxWidth: true,
|
|
278
|
+
textPosition: 0.75,
|
|
279
|
+
},
|
|
280
|
+
journey: {
|
|
281
|
+
useMaxWidth: true,
|
|
282
|
+
diagramMarginX: 30,
|
|
283
|
+
diagramMarginY: 20,
|
|
284
|
+
leftMargin: 100,
|
|
285
|
+
width: 120,
|
|
286
|
+
height: 50,
|
|
287
|
+
boxMargin: 8,
|
|
288
|
+
boxTextMargin: 4,
|
|
289
|
+
noteMargin: 10,
|
|
290
|
+
messageMargin: 30,
|
|
291
|
+
},
|
|
292
|
+
gitGraph: {
|
|
293
|
+
useMaxWidth: true,
|
|
294
|
+
diagramPadding: 8,
|
|
295
|
+
nodeLabel: {
|
|
296
|
+
width: 75,
|
|
297
|
+
height: 100,
|
|
298
|
+
x: -25,
|
|
299
|
+
y: 0,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
class: {
|
|
303
|
+
useMaxWidth: true,
|
|
304
|
+
padding: 10,
|
|
305
|
+
},
|
|
306
|
+
state: {
|
|
307
|
+
useMaxWidth: true,
|
|
308
|
+
padding: 8,
|
|
309
|
+
dividerMargin: 10,
|
|
310
|
+
},
|
|
311
|
+
mindmap: {
|
|
312
|
+
useMaxWidth: true,
|
|
313
|
+
padding: 10,
|
|
314
|
+
},
|
|
315
|
+
timeline: {
|
|
316
|
+
useMaxWidth: true,
|
|
317
|
+
padding: 10,
|
|
318
|
+
},
|
|
319
|
+
quadrantChart: {
|
|
320
|
+
useMaxWidth: true,
|
|
321
|
+
},
|
|
322
|
+
sankey: {
|
|
323
|
+
useMaxWidth: true,
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const result = await mermaid.render(diagramId, code);
|
|
328
|
+
|
|
329
|
+
if (renderIdRef.current !== currentRenderId) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
setSvg(result.svg);
|
|
334
|
+
setBindFunctions(() => (result.bindFunctions ? result.bindFunctions : null));
|
|
335
|
+
setError(null);
|
|
336
|
+
} catch (err) {
|
|
337
|
+
if (renderIdRef.current !== currentRenderId) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
setError(formatMermaidError(err));
|
|
342
|
+
setSvg(null);
|
|
343
|
+
setBindFunctions(null);
|
|
344
|
+
setShowErrorDetails(false); // Reset details visibility on new error
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
renderDiagram();
|
|
349
|
+
|
|
350
|
+
return () => {
|
|
351
|
+
renderIdRef.current += 1;
|
|
352
|
+
};
|
|
353
|
+
}, [code, theme]);
|
|
354
|
+
|
|
355
|
+
useEffect(() => {
|
|
356
|
+
if (!svg || !bindFunctions || !containerRef.current) return;
|
|
357
|
+
|
|
358
|
+
try {
|
|
359
|
+
bindFunctions(containerRef.current);
|
|
360
|
+
} catch (err) {
|
|
361
|
+
console.warn('Failed to bind Mermaid interactions:', err);
|
|
362
|
+
}
|
|
363
|
+
}, [svg, bindFunctions]);
|
|
364
|
+
|
|
365
|
+
const renderError = () => (
|
|
366
|
+
<div className="graph-error">
|
|
367
|
+
<div className="graph-error-header">
|
|
368
|
+
<div className="graph-error-icon">⚠️</div>
|
|
369
|
+
<div className="graph-error-content">
|
|
370
|
+
<div className="graph-error-title">Mermaid Diagram Error</div>
|
|
371
|
+
<div className="graph-error-message">{error}</div>
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
<button
|
|
375
|
+
className="graph-error-toggle"
|
|
376
|
+
onClick={() => setShowErrorDetails(!showErrorDetails)}
|
|
377
|
+
type="button"
|
|
378
|
+
>
|
|
379
|
+
{showErrorDetails ? 'Hide' : 'Show'} Details
|
|
380
|
+
</button>
|
|
381
|
+
{showErrorDetails && (
|
|
382
|
+
<details className="graph-error-details" open>
|
|
383
|
+
<summary style={{ cursor: 'pointer', marginBottom: '8px', fontWeight: 500 }}>
|
|
384
|
+
Mermaid Code
|
|
385
|
+
</summary>
|
|
386
|
+
<pre
|
|
387
|
+
style={{
|
|
388
|
+
marginTop: '8px',
|
|
389
|
+
fontSize: '0.8em',
|
|
390
|
+
opacity: 0.8,
|
|
391
|
+
padding: '8px',
|
|
392
|
+
background: 'rgba(0, 0, 0, 0.05)',
|
|
393
|
+
borderRadius: '4px',
|
|
394
|
+
overflow: 'auto',
|
|
395
|
+
maxHeight: '200px',
|
|
396
|
+
}}
|
|
397
|
+
>
|
|
398
|
+
<code>{code}</code>
|
|
399
|
+
</pre>
|
|
400
|
+
</details>
|
|
401
|
+
)}
|
|
402
|
+
</div>
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
const renderContent = () => {
|
|
406
|
+
if (error) {
|
|
407
|
+
return renderError();
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (!svg) {
|
|
411
|
+
return (
|
|
412
|
+
<div style={{
|
|
413
|
+
display: 'flex',
|
|
414
|
+
flexDirection: 'column',
|
|
415
|
+
alignItems: 'center',
|
|
416
|
+
justifyContent: 'center',
|
|
417
|
+
padding: '30px 20px',
|
|
418
|
+
color: 'var(--md-text-secondary, #6b7280)',
|
|
419
|
+
minHeight: '120px',
|
|
420
|
+
}}>
|
|
421
|
+
<svg
|
|
422
|
+
style={{
|
|
423
|
+
animation: 'spin 1s linear infinite',
|
|
424
|
+
marginBottom: '10px',
|
|
425
|
+
width: '28px',
|
|
426
|
+
height: '28px',
|
|
427
|
+
}}
|
|
428
|
+
viewBox="0 0 24 24"
|
|
429
|
+
fill="none"
|
|
430
|
+
>
|
|
431
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="2" strokeDasharray="32" strokeLinecap="round" />
|
|
432
|
+
</svg>
|
|
433
|
+
<span style={{ fontWeight: 500, fontSize: '14px' }}>
|
|
434
|
+
Rendering diagram...
|
|
435
|
+
</span>
|
|
436
|
+
<style>{`
|
|
437
|
+
@keyframes spin {
|
|
438
|
+
from { transform: rotate(0deg); }
|
|
439
|
+
to { transform: rotate(360deg); }
|
|
440
|
+
}
|
|
441
|
+
`}</style>
|
|
442
|
+
</div>
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return (
|
|
447
|
+
<div
|
|
448
|
+
ref={containerRef}
|
|
449
|
+
className="mermaid-svg-container"
|
|
450
|
+
style={{
|
|
451
|
+
display: 'flex',
|
|
452
|
+
justifyContent: 'center',
|
|
453
|
+
alignItems: 'center',
|
|
454
|
+
width: '100%',
|
|
455
|
+
overflow: 'auto',
|
|
456
|
+
}}
|
|
457
|
+
dangerouslySetInnerHTML={{ __html: svg }}
|
|
458
|
+
/>
|
|
459
|
+
);
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
return (
|
|
463
|
+
<div
|
|
464
|
+
className="graph-container mermaid-container"
|
|
465
|
+
ref={hostRef}
|
|
466
|
+
style={{
|
|
467
|
+
padding: '16px',
|
|
468
|
+
minHeight: '100px',
|
|
469
|
+
}}
|
|
470
|
+
>
|
|
471
|
+
{renderContent()}
|
|
472
|
+
</div>
|
|
473
|
+
);
|
|
474
|
+
};
|