@bytechain.cn/colamd 1.5.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.
Files changed (157) hide show
  1. package/.github/workflows/release.yml +66 -0
  2. package/.trae/documents/fix-mermaid-colors-and-sankey.md +50 -0
  3. package/CLAUDE.md +87 -0
  4. package/LICENSE +21 -0
  5. package/README.md +540 -0
  6. package/README_CN.md +543 -0
  7. package/demo.md +486 -0
  8. package/dist/main/index.js +735 -0
  9. package/dist/preload/index.js +71 -0
  10. package/dist/renderer/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  11. package/dist/renderer/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  12. package/dist/renderer/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  13. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  14. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  15. package/dist/renderer/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  16. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  17. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  18. package/dist/renderer/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  19. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  20. package/dist/renderer/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  21. package/dist/renderer/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  22. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  23. package/dist/renderer/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  24. package/dist/renderer/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  25. package/dist/renderer/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  26. package/dist/renderer/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  27. package/dist/renderer/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  28. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  29. package/dist/renderer/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  30. package/dist/renderer/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  31. package/dist/renderer/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  32. package/dist/renderer/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  33. package/dist/renderer/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  34. package/dist/renderer/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  35. package/dist/renderer/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  36. package/dist/renderer/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  37. package/dist/renderer/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  38. package/dist/renderer/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  39. package/dist/renderer/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  40. package/dist/renderer/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  41. package/dist/renderer/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  42. package/dist/renderer/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  43. package/dist/renderer/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  44. package/dist/renderer/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  45. package/dist/renderer/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  46. package/dist/renderer/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  47. package/dist/renderer/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  48. package/dist/renderer/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  49. package/dist/renderer/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  50. package/dist/renderer/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  51. package/dist/renderer/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  52. package/dist/renderer/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  53. package/dist/renderer/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  54. package/dist/renderer/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  55. package/dist/renderer/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  56. package/dist/renderer/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  57. package/dist/renderer/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  58. package/dist/renderer/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  59. package/dist/renderer/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  60. package/dist/renderer/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  61. package/dist/renderer/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  62. package/dist/renderer/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  63. package/dist/renderer/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  64. package/dist/renderer/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  65. package/dist/renderer/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  66. package/dist/renderer/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  67. package/dist/renderer/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  68. package/dist/renderer/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  69. package/dist/renderer/assets/arc-tTbbM8LO.js +131 -0
  70. package/dist/renderer/assets/architectureDiagram-3BPJPVTR-CEgYow6c.js +8720 -0
  71. package/dist/renderer/assets/blockDiagram-GPEHLZMM-LHyVtPwW.js +3825 -0
  72. package/dist/renderer/assets/c4Diagram-AAUBKEIU-C1P1eJrf.js +2482 -0
  73. package/dist/renderer/assets/channel-upve91Tq.js +7 -0
  74. package/dist/renderer/assets/chunk-2J33WTMH-lag2vhq9.js +24 -0
  75. package/dist/renderer/assets/chunk-4BX2VUAB-BXJ8Ggh-.js +16 -0
  76. package/dist/renderer/assets/chunk-55IACEB6-CiBpxRa1.js +13 -0
  77. package/dist/renderer/assets/chunk-727SXJPM-ODeKQFXC.js +2016 -0
  78. package/dist/renderer/assets/chunk-AQP2D5EJ-BK7xJolB.js +1953 -0
  79. package/dist/renderer/assets/chunk-FMBD7UC4-BxpCZPtz.js +19 -0
  80. package/dist/renderer/assets/chunk-ND2GUHAM-CqqaU9Ue.js +116 -0
  81. package/dist/renderer/assets/chunk-QZHKN3VN-Biq_K124.js +19 -0
  82. package/dist/renderer/assets/classDiagram-4FO5ZUOK-Cq95X99o.js +23 -0
  83. package/dist/renderer/assets/classDiagram-v2-Q7XG4LA2-Cq95X99o.js +23 -0
  84. package/dist/renderer/assets/cose-bilkent-S5V4N54A-XasiD0bu.js +4942 -0
  85. package/dist/renderer/assets/cytoscape.esm-CpHeHM5e.js +30269 -0
  86. package/dist/renderer/assets/dagre-BM42HDAG-Nq84Gfx4.js +705 -0
  87. package/dist/renderer/assets/defaultLocale-B2RvLBDe.js +206 -0
  88. package/dist/renderer/assets/diagram-2AECGRRQ-DwuB1GWt.js +301 -0
  89. package/dist/renderer/assets/diagram-5GNKFQAL-C2tgeI1h.js +169 -0
  90. package/dist/renderer/assets/diagram-KO2AKTUF-D5KzjNBc.js +632 -0
  91. package/dist/renderer/assets/diagram-LMA3HP47-C12xHS1c.js +212 -0
  92. package/dist/renderer/assets/diagram-OG6HWLK6-CnxI9oEa.js +851 -0
  93. package/dist/renderer/assets/erDiagram-TEJ5UH35-D_uPaKwn.js +1227 -0
  94. package/dist/renderer/assets/flowDiagram-I6XJVG4X-B6q_1-tE.js +2332 -0
  95. package/dist/renderer/assets/ganttDiagram-6RSMTGT7-CFo7ifF9.js +3720 -0
  96. package/dist/renderer/assets/gitGraphDiagram-PVQCEYII-WSexHTnq.js +1373 -0
  97. package/dist/renderer/assets/graph-DyX_9f6d.js +1988 -0
  98. package/dist/renderer/assets/index-DW7LS8C1.js +72292 -0
  99. package/dist/renderer/assets/index-dyHEFYvY.css +2184 -0
  100. package/dist/renderer/assets/infoDiagram-5YYISTIA-DaeJdLRq.js +31 -0
  101. package/dist/renderer/assets/init-ZxktEp_H.js +16 -0
  102. package/dist/renderer/assets/ishikawaDiagram-YF4QCWOH-DDCZc35f.js +967 -0
  103. package/dist/renderer/assets/journeyDiagram-JHISSGLW-BEdmpAgl.js +1255 -0
  104. package/dist/renderer/assets/kanban-definition-UN3LZRKU-BEFtQcFb.js +1052 -0
  105. package/dist/renderer/assets/layout-CAJgQHdw.js +2610 -0
  106. package/dist/renderer/assets/linear-B2ggJ8Am.js +340 -0
  107. package/dist/renderer/assets/mindmap-definition-RKZ34NQL-DSxVgHB5.js +1180 -0
  108. package/dist/renderer/assets/ordinal-DSZU4PqD.js +76 -0
  109. package/dist/renderer/assets/pieDiagram-4H26LBE5-CwYoJBuL.js +246 -0
  110. package/dist/renderer/assets/quadrantDiagram-W4KKPZXB-CST9Fvg9.js +1344 -0
  111. package/dist/renderer/assets/requirementDiagram-4Y6WPE33-DtrH52jS.js +1204 -0
  112. package/dist/renderer/assets/sankeyDiagram-5OEKKPKP-ca1tPzJ_.js +1274 -0
  113. package/dist/renderer/assets/sequenceDiagram-3UESZ5HK-Dfp1EJZ7.js +4514 -0
  114. package/dist/renderer/assets/stateDiagram-AJRCARHV-Bha2QoNB.js +450 -0
  115. package/dist/renderer/assets/stateDiagram-v2-BHNVJYJU-DWgFUYu1.js +21 -0
  116. package/dist/renderer/assets/timeline-definition-PNZ67QCA-C3h_-OTj.js +1596 -0
  117. package/dist/renderer/assets/vennDiagram-CIIHVFJN-DFzjSrZi.js +2486 -0
  118. package/dist/renderer/assets/wardley-L42UT6IY-Cx-VbqoS.js +30699 -0
  119. package/dist/renderer/assets/wardleyDiagram-YWT4CUSO-S2D9XqX6.js +975 -0
  120. package/dist/renderer/assets/xychartDiagram-2RQKCTM6-Cfxigbts.js +1932 -0
  121. package/dist/renderer/index.html +19 -0
  122. package/docs/agent-diff-view.md +48 -0
  123. package/electron-builder.yml +57 -0
  124. package/electron.vite.config.ts +30 -0
  125. package/package.json +40 -0
  126. package/resources/entitlements.mac.plist +12 -0
  127. package/resources/icon.icns +0 -0
  128. package/resources/icon.png +0 -0
  129. package/resources/icon.svg +23 -0
  130. package/resources/templates/slides/icon.png +0 -0
  131. package/resources/templates/slides/slides-template.md +74 -0
  132. package/resources/templates/slides/template.html +535 -0
  133. package/scripts/afterPack.js +13 -0
  134. package/src/main/index.ts +881 -0
  135. package/src/preload/index.ts +110 -0
  136. package/src/renderer/editor/editor.ts +204 -0
  137. package/src/renderer/editor/html-view.ts +15 -0
  138. package/src/renderer/editor/plugins/index.ts +76 -0
  139. package/src/renderer/editor/plugins/math-plugin.ts +297 -0
  140. package/src/renderer/editor/plugins/mermaid-plugin-custom.css +431 -0
  141. package/src/renderer/editor/plugins/mermaid-plugin-dark.css +428 -0
  142. package/src/renderer/editor/plugins/mermaid-plugin-elegant.css +443 -0
  143. package/src/renderer/editor/plugins/mermaid-plugin-newsprint.css +208 -0
  144. package/src/renderer/editor/plugins/mermaid-plugin.css +111 -0
  145. package/src/renderer/editor/plugins/mermaid-plugin.ts +679 -0
  146. package/src/renderer/env.d.ts +7 -0
  147. package/src/renderer/index.html +18 -0
  148. package/src/renderer/main.ts +303 -0
  149. package/src/renderer/themes/base.css +509 -0
  150. package/src/renderer/themes/theme-manager.ts +40 -0
  151. package/themes/README.md +280 -0
  152. package/themes/elegant.css +664 -0
  153. package/themes/guizang.css +732 -0
  154. package/tsconfig.json +14 -0
  155. package/tsconfig.main.json +11 -0
  156. package/tsconfig.preload.json +11 -0
  157. package/tsconfig.renderer.json +12 -0
@@ -0,0 +1,679 @@
1
+ import { $nodeSchema, $view, $inputRule } from '@milkdown/utils'
2
+ import { InputRule } from '@milkdown/prose/inputrules'
3
+ import type { NodeViewConstructor } from '@milkdown/prose/view'
4
+ import type { Plugin } from 'unified'
5
+ import type { RendererPlugin } from './index'
6
+ import { registerPluginModule } from './index'
7
+ import mermaid from 'mermaid'
8
+ import './mermaid-plugin.css'
9
+ import './mermaid-plugin-dark.css'
10
+ import './mermaid-plugin-elegant.css'
11
+ import './mermaid-plugin-newsprint.css'
12
+ import './mermaid-plugin-custom.css'
13
+
14
+ ;(window as any).mermaid = mermaid
15
+
16
+ function getMermaidTheme(): string {
17
+ const cls = document.body.className
18
+ if (cls.includes('theme-dark')) return 'dark'
19
+ if (cls.includes('theme-newsprint')) return 'neutral'
20
+ if (cls.includes('theme-custom')) {
21
+ const style = getComputedStyle(document.body)
22
+ if (style.getPropertyValue('--mermaid-dark-mode').trim() === 'true') return 'dark'
23
+ return 'base'
24
+ }
25
+ return 'default'
26
+ }
27
+
28
+ function readCustomVar(name: string, fallback: string): string {
29
+ const style = getComputedStyle(document.body)
30
+ return style.getPropertyValue(name).trim() || fallback
31
+ }
32
+
33
+ function getCustomMermaidFontSize(): number {
34
+ const raw = readCustomVar('--mermaid-font-size', '')
35
+ const n = parseInt(raw, 10)
36
+ return Number.isFinite(n) && n > 0 ? n : 12
37
+ }
38
+
39
+ function getCustomMermaidThemeVariables(): Record<string, string> {
40
+ const v = (name: string, fallback: string) => readCustomVar(name, fallback)
41
+ const baseFont = '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif'
42
+ const font = v('--mermaid-font-family', baseFont)
43
+ const darkMode = v('--mermaid-dark-mode', 'false')
44
+ const result: Record<string, string> = {
45
+ darkMode,
46
+ background: v('--mermaid-background', v('--bg-color', '#ffffff')),
47
+ primaryColor: v('--mermaid-primary-color', v('--code-block-bg', '#f6f8fa')),
48
+ primaryBorderColor: v('--mermaid-primary-border-color', v('--border-color', '#d0d7de')),
49
+ primaryTextColor: v('--mermaid-primary-text-color', v('--text-color', '#24292f')),
50
+ secondaryColor: v('--mermaid-secondary-color', v('--code-bg', '#f6f8fa')),
51
+ secondaryBorderColor: v('--mermaid-secondary-border-color', v('--border-color', '#d0d7de')),
52
+ secondaryTextColor: v('--mermaid-primary-text-color', v('--text-color', '#24292f')),
53
+ tertiaryColor: v('--mermaid-tertiary-color', v('--bg-color', '#ffffff')),
54
+ tertiaryBorderColor: v('--mermaid-tertiary-border-color', v('--border-color', '#d0d7de')),
55
+ tertiaryTextColor: v('--mermaid-tertiary-text-color', v('--text-color', '#24292f')),
56
+ lineColor: v('--mermaid-line-color', v('--border-color', '#d0d7de')),
57
+ textColor: v('--mermaid-text-color', v('--text-color', '#24292f')),
58
+ mainBkg: v('--mermaid-main-bkg', v('--code-block-bg', '#f6f8fa')),
59
+ secondBkg: v('--mermaid-second-bkg', v('--code-bg', '#f6f8fa')),
60
+ mainContrastColor: v('--mermaid-primary-text-color', v('--text-color', '#24292f')),
61
+ labelBackground: v('--mermaid-label-background', v('--code-block-bg', '#f6f8fa')),
62
+ labelTextColor: v('--mermaid-label-text-color', v('--text-color', '#24292f')),
63
+ nodeBorder: v('--mermaid-node-border', v('--border-color', '#d0d7de')),
64
+ nodeBkg: v('--mermaid-node-bkg', v('--code-block-bg', '#f6f8fa')),
65
+ clusterBkg: v('--mermaid-cluster-bkg', v('--code-bg', '#f6f8fa')),
66
+ clusterBorder: v('--mermaid-cluster-border', v('--border-color', '#d0d7de')),
67
+ defaultLinkColor: v('--mermaid-line-color', v('--border-color', '#d0d7de')),
68
+ edgeLabelBackground: v('--mermaid-edge-label-background', v('--code-block-bg', '#f6f8fa')),
69
+ arrowheadColor: v('--mermaid-arrowhead-color', v('--mermaid-line-color', v('--border-color', '#d0d7de'))),
70
+ personBorder: v('--mermaid-person-border', v('--border-color', '#d0d7de')),
71
+ personBkg: v('--mermaid-person-bkg', v('--code-block-bg', '#f6f8fa')),
72
+ fontFamily: font,
73
+ cScale0: v('--mermaid-cscale0', '#2d5f8a'),
74
+ cScale1: v('--mermaid-cscale1', '#3d7a5a'),
75
+ cScale2: v('--mermaid-cscale2', '#8a6b3c'),
76
+ cScale3: v('--mermaid-cscale3', '#6b4a7a'),
77
+ cScale4: v('--mermaid-cscale4', '#3c7a6b'),
78
+ cScale5: v('--mermaid-cscale5', '#7a4a4a'),
79
+ cScale6: v('--mermaid-cscale6', '#4a6b8a'),
80
+ cScale7: v('--mermaid-cscale7', '#5a7a3c'),
81
+ cScale8: v('--mermaid-cscale8', '#7a3c6b'),
82
+ cScale9: v('--mermaid-cscale9', '#3c8a5a'),
83
+ cScale10: v('--mermaid-cscale10', '#8a5a3c'),
84
+ cScale11: v('--mermaid-cscale11', '#3c5a8a'),
85
+ }
86
+ return result
87
+ }
88
+
89
+ function getCustomMermaidC4Config(): Record<string, string> {
90
+ const v = (name: string, fallback: string) => readCustomVar(name, fallback)
91
+ const baseFont = '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif'
92
+ const font = v('--mermaid-font-family', baseFont)
93
+ return {
94
+ personFontFamily: font,
95
+ systemFontFamily: font,
96
+ containerFontFamily: font,
97
+ componentFontFamily: font,
98
+ boundaryFontFamily: font,
99
+ messageFontFamily: font,
100
+ person_bg_color: v('--mermaid-c4-person-bg', '#2d5f8a'),
101
+ person_border_color: v('--mermaid-c4-person-border', '#4a7aaa'),
102
+ external_person_bg_color: v('--mermaid-c4-ext-person-bg', '#4a5568'),
103
+ external_person_border_color: v('--mermaid-c4-ext-person-border', '#6b7a8a'),
104
+ system_bg_color: v('--mermaid-c4-system-bg', '#3d7a5a'),
105
+ system_border_color: v('--mermaid-c4-system-border', '#5a9a7a'),
106
+ system_db_bg_color: v('--mermaid-c4-system-bg', '#3d7a5a'),
107
+ system_db_border_color: v('--mermaid-c4-system-border', '#5a9a7a'),
108
+ system_queue_bg_color: v('--mermaid-c4-system-bg', '#3d7a5a'),
109
+ system_queue_border_color: v('--mermaid-c4-system-border', '#5a9a7a'),
110
+ external_system_bg_color: v('--mermaid-c4-ext-system-bg', '#6b4a7a'),
111
+ external_system_border_color: v('--mermaid-c4-ext-system-border', '#8a6a9a'),
112
+ external_system_db_bg_color: v('--mermaid-c4-ext-system-bg', '#6b4a7a'),
113
+ external_system_db_border_color: v('--mermaid-c4-ext-system-border', '#8a6a9a'),
114
+ external_system_queue_bg_color: v('--mermaid-c4-ext-system-bg', '#6b4a7a'),
115
+ external_system_queue_border_color: v('--mermaid-c4-ext-system-border', '#8a6a9a'),
116
+ container_bg_color: v('--mermaid-c4-container-bg', '#8a6b3c'),
117
+ container_border_color: v('--mermaid-c4-container-border', '#aa8a5c'),
118
+ container_db_bg_color: v('--mermaid-c4-container-bg', '#8a6b3c'),
119
+ container_db_border_color: v('--mermaid-c4-container-border', '#aa8a5c'),
120
+ container_queue_bg_color: v('--mermaid-c4-container-bg', '#8a6b3c'),
121
+ container_queue_border_color: v('--mermaid-c4-container-border', '#aa8a5c'),
122
+ external_container_bg_color: v('--mermaid-c4-ext-container-bg', '#5a5a6a'),
123
+ external_container_border_color: v('--mermaid-c4-ext-container-border', '#7a7a8a'),
124
+ external_container_db_bg_color: v('--mermaid-c4-ext-container-bg', '#5a5a6a'),
125
+ external_container_db_border_color: v('--mermaid-c4-ext-container-border', '#7a7a8a'),
126
+ external_container_queue_bg_color: v('--mermaid-c4-ext-container-bg', '#5a5a6a'),
127
+ external_container_queue_border_color: v('--mermaid-c4-ext-container-border', '#7a7a8a'),
128
+ component_bg_color: v('--mermaid-c4-component-bg', '#3c7a6b'),
129
+ component_border_color: v('--mermaid-c4-component-border', '#5c9a8b'),
130
+ component_db_bg_color: v('--mermaid-c4-component-bg', '#3c7a6b'),
131
+ component_db_border_color: v('--mermaid-c4-component-border', '#5c9a8b'),
132
+ component_queue_bg_color: v('--mermaid-c4-component-bg', '#3c7a6b'),
133
+ component_queue_border_color: v('--mermaid-c4-component-border', '#5c9a8b'),
134
+ external_component_bg_color: v('--mermaid-c4-ext-component-bg', '#6a6a6a'),
135
+ external_component_border_color: v('--mermaid-c4-ext-component-border', '#8a8a8a'),
136
+ external_component_db_bg_color: v('--mermaid-c4-ext-component-bg', '#6a6a6a'),
137
+ external_component_db_border_color: v('--mermaid-c4-ext-component-border', '#8a8a8a'),
138
+ external_component_queue_bg_color: v('--mermaid-c4-ext-component-bg', '#6a6a6a'),
139
+ external_component_queue_border_color: v('--mermaid-c4-ext-component-border', '#8a8a8a'),
140
+ }
141
+ }
142
+
143
+ function getMermaidThemeVariables(): Record<string, string> {
144
+ const cls = document.body.className
145
+ if (cls.includes('theme-dark')) {
146
+ return {
147
+ darkMode: 'true',
148
+ background: '#0d1117',
149
+ primaryColor: '#1c2128',
150
+ primaryBorderColor: '#8b949e',
151
+ primaryTextColor: '#e6edf3',
152
+ secondaryColor: '#21262d',
153
+ secondaryBorderColor: '#8b949e',
154
+ secondaryTextColor: '#e6edf3',
155
+ tertiaryColor: '#1c2128',
156
+ tertiaryBorderColor: '#8b949e',
157
+ tertiaryTextColor: '#e6edf3',
158
+ lineColor: '#8b949e',
159
+ textColor: '#e6edf3',
160
+ mainBkg: '#1c2128',
161
+ secondBkg: '#21262d',
162
+ mainContrastColor: '#e6edf3',
163
+ labelBackground: '#161b22',
164
+ labelTextColor: '#e6edf3',
165
+ nodeBorder: '#8b949e',
166
+ nodeBkg: '#1c2128',
167
+ clusterBkg: '#21262d',
168
+ clusterBorder: '#8b949e',
169
+ defaultLinkColor: '#8b949e',
170
+ edgeLabelBackground: '#161b22',
171
+ arrowheadColor: '#8b949e',
172
+ personBorder: '#8b949e',
173
+ personBkg: '#1c2128',
174
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif',
175
+ cScale0: '#2d5f8a',
176
+ cScale1: '#3d7a5a',
177
+ cScale2: '#8a6b3c',
178
+ cScale3: '#6b4a7a',
179
+ cScale4: '#3c7a6b',
180
+ cScale5: '#7a4a4a',
181
+ cScale6: '#4a6b8a',
182
+ cScale7: '#5a7a3c',
183
+ cScale8: '#7a3c6b',
184
+ cScale9: '#3c8a5a',
185
+ cScale10: '#8a5a3c',
186
+ cScale11: '#3c5a8a',
187
+ }
188
+ }
189
+ if (cls.includes('theme-elegant')) {
190
+ return {
191
+ darkMode: 'false',
192
+ background: '#e8e2db',
193
+ primaryColor: '#ddd5cb',
194
+ primaryBorderColor: '#b0a89f',
195
+ primaryTextColor: '#3d3530',
196
+ secondaryColor: '#e0d8cf',
197
+ secondaryBorderColor: '#c4bbb0',
198
+ secondaryTextColor: '#3d3530',
199
+ tertiaryColor: '#e8e2db',
200
+ tertiaryBorderColor: '#d0c8ba',
201
+ tertiaryTextColor: '#3d3530',
202
+ lineColor: '#b0a89f',
203
+ textColor: '#3d3530',
204
+ mainBkg: '#ddd5cb',
205
+ secondBkg: '#e0d8cf',
206
+ mainContrastColor: '#3d3530',
207
+ labelBackground: '#e8e2db',
208
+ labelTextColor: '#3d3530',
209
+ nodeBorder: '#b0a89f',
210
+ nodeBkg: '#ddd5cb',
211
+ clusterBkg: '#e0d8cf',
212
+ clusterBorder: '#b0a89f',
213
+ defaultLinkColor: '#b0a89f',
214
+ edgeLabelBackground: '#e8e2db',
215
+ arrowheadColor: '#b0a89f',
216
+ personBorder: '#b0a89f',
217
+ personBkg: '#ddd5cb',
218
+ fontFamily: '"LXGW WenKai", "Noto Serif SC", "Source Han Serif SC", "Songti SC", Georgia, serif',
219
+ cScale0: '#e8a898',
220
+ cScale1: '#c4b8a8',
221
+ cScale2: '#a8c4b8',
222
+ cScale3: '#c8b098',
223
+ cScale4: '#b8a8c4',
224
+ cScale5: '#98c4b0',
225
+ cScale6: '#d4a888',
226
+ cScale7: '#a8b8c8',
227
+ cScale8: '#c4a898',
228
+ cScale9: '#98b8a8',
229
+ cScale10: '#b8c4a8',
230
+ cScale11: '#a898b8',
231
+ }
232
+ }
233
+ if (cls.includes('theme-newsprint')) {
234
+ return {
235
+ fontFamily: '"PT Serif", Georgia, serif',
236
+ cScale0: '#2c5f8a',
237
+ cScale1: '#5a7a4a',
238
+ cScale2: '#8a6b3c',
239
+ cScale3: '#6b4a7a',
240
+ cScale4: '#3c7a6b',
241
+ cScale5: '#7a3c3c',
242
+ cScale6: '#4a6b8a',
243
+ cScale7: '#6b7a3c',
244
+ cScale8: '#5a3c7a',
245
+ cScale9: '#3c8a5a',
246
+ cScale10: '#8a5a3c',
247
+ cScale11: '#3c5a8a',
248
+ }
249
+ }
250
+ if (cls.includes('theme-custom')) {
251
+ return getCustomMermaidThemeVariables()
252
+ }
253
+ return {
254
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif',
255
+ }
256
+ }
257
+
258
+ function getMermaidC4Config(): Record<string, string> {
259
+ const cls = document.body.className
260
+ if (cls.includes('theme-custom')) {
261
+ return getCustomMermaidC4Config()
262
+ }
263
+ const font = cls.includes('theme-elegant')
264
+ ? '"LXGW WenKai", "Noto Serif SC", Georgia, serif'
265
+ : cls.includes('theme-newsprint')
266
+ ? '"PT Serif", Georgia, serif'
267
+ : '-apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif'
268
+ if (cls.includes('theme-dark')) {
269
+ return {
270
+ personFontFamily: font,
271
+ systemFontFamily: font,
272
+ containerFontFamily: font,
273
+ componentFontFamily: font,
274
+ boundaryFontFamily: font,
275
+ messageFontFamily: font,
276
+ person_bg_color: '#2d5f8a',
277
+ person_border_color: '#4a7aaa',
278
+ external_person_bg_color: '#4a5568',
279
+ external_person_border_color: '#6b7a8a',
280
+ system_bg_color: '#3d7a5a',
281
+ system_border_color: '#5a9a7a',
282
+ system_db_bg_color: '#3d7a5a',
283
+ system_db_border_color: '#5a9a7a',
284
+ system_queue_bg_color: '#3d7a5a',
285
+ system_queue_border_color: '#5a9a7a',
286
+ external_system_bg_color: '#6b4a7a',
287
+ external_system_border_color: '#8a6a9a',
288
+ external_system_db_bg_color: '#6b4a7a',
289
+ external_system_db_border_color: '#8a6a9a',
290
+ external_system_queue_bg_color: '#6b4a7a',
291
+ external_system_queue_border_color: '#8a6a9a',
292
+ container_bg_color: '#8a6b3c',
293
+ container_border_color: '#aa8a5c',
294
+ container_db_bg_color: '#8a6b3c',
295
+ container_db_border_color: '#aa8a5c',
296
+ container_queue_bg_color: '#8a6b3c',
297
+ container_queue_border_color: '#aa8a5c',
298
+ external_container_bg_color: '#5a5a6a',
299
+ external_container_border_color: '#7a7a8a',
300
+ external_container_db_bg_color: '#5a5a6a',
301
+ external_container_db_border_color: '#7a7a8a',
302
+ external_container_queue_bg_color: '#5a5a6a',
303
+ external_container_queue_border_color: '#7a7a8a',
304
+ component_bg_color: '#3c7a6b',
305
+ component_border_color: '#5c9a8b',
306
+ component_db_bg_color: '#3c7a6b',
307
+ component_db_border_color: '#5c9a8b',
308
+ component_queue_bg_color: '#3c7a6b',
309
+ component_queue_border_color: '#5c9a8b',
310
+ external_component_bg_color: '#6a6a6a',
311
+ external_component_border_color: '#8a8a8a',
312
+ external_component_db_bg_color: '#6a6a6a',
313
+ external_component_db_border_color: '#8a8a8a',
314
+ external_component_queue_bg_color: '#6a6a6a',
315
+ external_component_queue_border_color: '#8a8a8a',
316
+ }
317
+ }
318
+ if (cls.includes('theme-elegant')) {
319
+ return {
320
+ personFontFamily: font,
321
+ systemFontFamily: font,
322
+ containerFontFamily: font,
323
+ componentFontFamily: font,
324
+ boundaryFontFamily: font,
325
+ messageFontFamily: font,
326
+ person_bg_color: '#c44b2b',
327
+ person_border_color: '#a03a1e',
328
+ external_person_bg_color: '#8b7b6a',
329
+ external_person_border_color: '#7a6a5a',
330
+ system_bg_color: '#5a7a6b',
331
+ system_border_color: '#4a6a5b',
332
+ system_db_bg_color: '#5a7a6b',
333
+ system_db_border_color: '#4a6a5b',
334
+ system_queue_bg_color: '#5a7a6b',
335
+ system_queue_border_color: '#4a6a5b',
336
+ external_system_bg_color: '#8b6b4a',
337
+ external_system_border_color: '#7a5a3a',
338
+ external_system_db_bg_color: '#8b6b4a',
339
+ external_system_db_border_color: '#7a5a3a',
340
+ external_system_queue_bg_color: '#8b6b4a',
341
+ external_system_queue_border_color: '#7a5a3a',
342
+ container_bg_color: '#6b5a7a',
343
+ container_border_color: '#5a4a6a',
344
+ container_db_bg_color: '#6b5a7a',
345
+ container_db_border_color: '#5a4a6a',
346
+ container_queue_bg_color: '#6b5a7a',
347
+ container_queue_border_color: '#5a4a6a',
348
+ external_container_bg_color: '#a09080',
349
+ external_container_border_color: '#8a7a6a',
350
+ external_container_db_bg_color: '#a09080',
351
+ external_container_db_border_color: '#8a7a6a',
352
+ external_container_queue_bg_color: '#a09080',
353
+ external_container_queue_border_color: '#8a7a6a',
354
+ component_bg_color: '#4a7a6b',
355
+ component_border_color: '#3a6a5b',
356
+ component_db_bg_color: '#4a7a6b',
357
+ component_db_border_color: '#3a6a5b',
358
+ component_queue_bg_color: '#4a7a6b',
359
+ component_queue_border_color: '#3a6a5b',
360
+ external_component_bg_color: '#9a8a7a',
361
+ external_component_border_color: '#8a7a6a',
362
+ external_component_db_bg_color: '#9a8a7a',
363
+ external_component_db_border_color: '#8a7a6a',
364
+ external_component_queue_bg_color: '#9a8a7a',
365
+ external_component_queue_border_color: '#8a7a6a',
366
+ }
367
+ }
368
+ return {
369
+ personFontFamily: font,
370
+ systemFontFamily: font,
371
+ containerFontFamily: font,
372
+ componentFontFamily: font,
373
+ boundaryFontFamily: font,
374
+ messageFontFamily: font,
375
+ }
376
+ }
377
+
378
+ let renderCounter = 0
379
+
380
+ function adjustNodeHeights(svg: SVGSVGElement): void {
381
+ const isCustom = document.body.className.includes('theme-custom')
382
+ const PAD = isCustom ? 8 : 6
383
+ svg.querySelectorAll('.node > rect').forEach((el) => {
384
+ const h = parseFloat(el.getAttribute('height') || '0')
385
+ if (h > 0) el.setAttribute('height', String(h + PAD))
386
+ })
387
+ svg.querySelectorAll('.label > foreignObject').forEach((el) => {
388
+ const h = parseFloat(el.getAttribute('height') || '0')
389
+ if (h > 0) el.setAttribute('height', String(h + PAD))
390
+ })
391
+ svg.querySelectorAll('.node > .label').forEach((el) => {
392
+ const t = el.getAttribute('transform') || ''
393
+ const m = t.match(/translate\(\s*([\d.]+)\s*,\s*([\d.]+)\s*\)/)
394
+ if (m) el.setAttribute('transform', `translate(${m[1]}, ${parseFloat(m[2]) - PAD / 2})`)
395
+ })
396
+ }
397
+
398
+ const remarkMermaid: Plugin = function () {
399
+ return (tree: any) => {
400
+ const walk = (node: any) => {
401
+ if (node.children) {
402
+ for (let i = 0; i < node.children.length; i++) {
403
+ const child = node.children[i]
404
+ if (child.type === 'code' && child.lang === 'mermaid') {
405
+ node.children[i] = {
406
+ type: 'mermaidCode',
407
+ value: child.value,
408
+ position: child.position,
409
+ }
410
+ } else {
411
+ walk(child)
412
+ }
413
+ }
414
+ }
415
+ }
416
+ walk(tree)
417
+ }
418
+ }
419
+
420
+ const mermaidBlockSchema = $nodeSchema('mermaid_block', () => ({
421
+ group: 'block',
422
+ atom: true,
423
+ priority: 60,
424
+ attrs: {
425
+ text: { default: '', validate: 'string' },
426
+ mode: { default: 'rendered' as 'rendered' | 'raw' },
427
+ },
428
+ parseDOM: [
429
+ { tag: 'div.mermaid-block', getAttrs: (dom) => ({ text: (dom as HTMLElement).dataset.mermaid || '' }) },
430
+ { tag: 'pre.mermaid-raw', getAttrs: (dom) => ({ text: (dom as HTMLElement).dataset.mermaid || '', mode: 'raw' }) },
431
+ ],
432
+ toDOM: (node) => {
433
+ const container = document.createElement('div')
434
+ container.className = 'mermaid-block'
435
+ container.dataset.mermaid = node.attrs.text as string
436
+
437
+ const text = (node.attrs.text as string || '').trim()
438
+
439
+ if (node.attrs.mode === 'raw') {
440
+ const el = document.createElement('pre')
441
+ el.className = 'mermaid-raw'
442
+ el.dataset.mermaid = text
443
+ el.textContent = '```mermaid\n' + text + '\n```'
444
+ return { dom: el }
445
+ }
446
+
447
+ if (!text) {
448
+ container.innerHTML = '<div class="mermaid-preview"><div class="mermaid-loading">Empty diagram</div></div>'
449
+ return { dom: container }
450
+ }
451
+
452
+ const mermaidLib = (window as any).mermaid
453
+ if (!mermaidLib || typeof mermaidLib.render !== 'function') {
454
+ container.innerHTML = '<div class="mermaid-preview"><div class="mermaid-error">Mermaid not loaded</div></div>'
455
+ return { dom: container }
456
+ }
457
+
458
+ container.innerHTML = '<div class="mermaid-preview"><div class="mermaid-loading">Rendering...</div></div>'
459
+ const id = 'mermaid-' + (++renderCounter)
460
+ try {
461
+ mermaidLib.render(id, text).then((result: { svg: string; bindFunctions?: (el: Element) => void }) => {
462
+ const preview = container.querySelector('.mermaid-preview')
463
+ if (preview) {
464
+ preview.innerHTML = result.svg
465
+ const svg = preview.querySelector('svg') as SVGSVGElement | null
466
+ if (svg) adjustNodeHeights(svg)
467
+ if (result.bindFunctions) result.bindFunctions(container)
468
+ }
469
+ }).catch((e: Error) => {
470
+ const preview = container.querySelector('.mermaid-preview')
471
+ if (preview) {
472
+ const msg = e.message.replace(/&/g, '&amp;').replace(/</g, '&lt;')
473
+ preview.innerHTML = '<div class="mermaid-error">Error: ' + msg + '</div>'
474
+ }
475
+ })
476
+ } catch (e: any) {
477
+ container.innerHTML = '<div class="mermaid-preview"><div class="mermaid-error">' + String(e.message || e) + '</div></div>'
478
+ }
479
+
480
+ return { dom: container }
481
+ },
482
+ parseMarkdown: {
483
+ match: (node) => node.type === 'mermaidCode',
484
+ runner: (state, node, type) => {
485
+ state.addNode(type, { text: (node.value as string) || '' })
486
+ },
487
+ },
488
+ toMarkdown: {
489
+ match: (node) => node.type.name === 'mermaid_block',
490
+ runner: (state, node) => {
491
+ state.addNode('code', undefined, node.attrs.text as string, { lang: 'mermaid' })
492
+ },
493
+ },
494
+ }))
495
+
496
+ const mermaidBlockInputRule = $inputRule((ctx) => {
497
+ return new InputRule(/^```mermaid[\s\n]$/, (state, _match, start, end) => {
498
+ const { tr } = state
499
+ tr.replaceWith(start, end, mermaidBlockSchema.type(ctx).create({ text: '' }))
500
+ return tr
501
+ })
502
+ })
503
+
504
+ function renderMermaidBlock(dom: HTMLElement, node: any, renderIdRef: { current: number }): void {
505
+ const text = (node.attrs.text as string || '').trim()
506
+ dom.dataset.mermaid = text
507
+ const currentRenderId = ++renderIdRef.current
508
+
509
+ dom.innerHTML = ''
510
+
511
+ if (node.attrs.mode === 'raw') {
512
+ const textarea = document.createElement('textarea')
513
+ textarea.className = 'mermaid-source'
514
+ textarea.dataset.mermaid = text
515
+ textarea.value = '```mermaid\n' + text + '\n```'
516
+ textarea.rows = Math.min(16, (text.match(/\n/g) || []).length + 3)
517
+ dom.appendChild(textarea)
518
+ return
519
+ }
520
+
521
+ if (!text) {
522
+ dom.innerHTML = '<div class="mermaid-preview"><div class="mermaid-loading">Empty diagram</div></div>'
523
+ return
524
+ }
525
+
526
+ const mermaidLib = (window as any).mermaid
527
+ if (!mermaidLib || typeof mermaidLib.render !== 'function') {
528
+ dom.innerHTML = '<div class="mermaid-preview"><div class="mermaid-error">Mermaid not loaded</div></div>'
529
+ return
530
+ }
531
+
532
+ dom.innerHTML = '<div class="mermaid-preview"><div class="mermaid-loading">Rendering...</div></div>'
533
+ const id = 'mermaid-' + (++renderCounter)
534
+
535
+ mermaidLib.render(id, text).then((result: { svg: string; bindFunctions?: (el: Element) => void }) => {
536
+ if (currentRenderId !== renderIdRef.current) return
537
+ const preview = dom.querySelector('.mermaid-preview')
538
+ if (preview) {
539
+ preview.innerHTML = result.svg
540
+ const svg = preview.querySelector('svg') as SVGSVGElement | null
541
+ if (svg) adjustNodeHeights(svg)
542
+ if (result.bindFunctions) result.bindFunctions(dom)
543
+ }
544
+ }).catch((e: Error) => {
545
+ if (currentRenderId !== renderIdRef.current) return
546
+ const preview = dom.querySelector('.mermaid-preview')
547
+ if (preview) {
548
+ const msg = e.message.replace(/&/g, '&amp;').replace(/</g, '&lt;')
549
+ preview.innerHTML = '<div class="mermaid-error">Error: ' + msg + '</div>'
550
+ }
551
+ })
552
+ }
553
+
554
+ const mermaidBlockView = $view(mermaidBlockSchema, (_ctx): NodeViewConstructor => {
555
+ return (node, view, getPos) => {
556
+ const container = document.createElement('div')
557
+ container.className = 'mermaid-block'
558
+ const renderIdRef = { current: 0 }
559
+ renderMermaidBlock(container, node, renderIdRef)
560
+
561
+ container.addEventListener('focusout', (e) => {
562
+ const target = e.target as HTMLElement
563
+ if (!target.classList.contains('mermaid-source')) return
564
+ const rawValue = (target as HTMLTextAreaElement).value
565
+ const newText = rawValue.replace(/^```mermaid\s*\n?/, '').replace(/\n?\s*```$/, '').trim()
566
+ const pos = getPos()
567
+ if (pos != null && node.attrs.text !== newText) {
568
+ view.dispatch(view.state.tr.setNodeMarkup(pos, undefined, { ...node.attrs, text: newText }))
569
+ }
570
+ })
571
+
572
+ return {
573
+ dom: container,
574
+ update: (updatedNode) => {
575
+ if (updatedNode.type !== node.type) return false
576
+ if (updatedNode.sameMarkup(node)) return true
577
+ node = updatedNode
578
+ renderMermaidBlock(container, node, renderIdRef)
579
+ return true
580
+ },
581
+ stopEvent: (e) => {
582
+ return (e.target as HTMLElement).matches('input, textarea')
583
+ },
584
+ ignoreMutation: () => true,
585
+ destroy: () => { container.remove() },
586
+ }
587
+ }
588
+ })
589
+
590
+ function svgToPngDataUrl(svgEl: SVGSVGElement, scale = 2): Promise<string> {
591
+ const clone = svgEl.cloneNode(true) as SVGSVGElement
592
+ const vb = clone.getAttribute('viewBox')
593
+ let svgW = clone.getAttribute('width')
594
+ let svgH = clone.getAttribute('height')
595
+ if ((!svgW || !svgH) && vb) {
596
+ const parts = vb.split(/[\s,]+/)
597
+ if (parts.length === 4) {
598
+ if (!svgW) svgW = parts[2]
599
+ if (!svgH) svgH = parts[3]
600
+ }
601
+ }
602
+ if (svgW) clone.setAttribute('width', svgW)
603
+ if (svgH) clone.setAttribute('height', svgH)
604
+ clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
605
+ const svgData = new XMLSerializer().serializeToString(clone)
606
+ const svgBase64 = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgData)))
607
+ return new Promise((resolve, reject) => {
608
+ const img = new Image()
609
+ img.onload = () => {
610
+ const w = img.naturalWidth || img.width || parseFloat(svgW || '0')
611
+ const h = img.naturalHeight || img.height || parseFloat(svgH || '0')
612
+ if (!w || !h) { reject(new Error('SVG image has zero dimensions')); return }
613
+ const canvas = document.createElement('canvas')
614
+ canvas.width = w * scale
615
+ canvas.height = h * scale
616
+ const ctx = canvas.getContext('2d')!
617
+ ctx.scale(scale, scale)
618
+ ctx.fillStyle = '#ffffff'
619
+ ctx.fillRect(0, 0, w, h)
620
+ ctx.drawImage(img, 0, 0)
621
+ resolve(canvas.toDataURL('image/png'))
622
+ }
623
+ img.onerror = () => { reject(new Error('Failed to load SVG as image')) }
624
+ img.src = svgBase64
625
+ })
626
+ }
627
+
628
+ export const mermaidPlugin: RendererPlugin = {
629
+ id: 'mermaid',
630
+ name: 'Mermaid Diagrams',
631
+ enabled: true,
632
+ remarkPlugin: { plugin: remarkMermaid, options: undefined },
633
+ nodeTypes: ['mermaid_block'],
634
+ exportCapabilities: [
635
+ {
636
+ label: 'Save Diagram as PNG',
637
+ defaultName: 'diagram.png',
638
+ filter: { name: 'PNG Image', extensions: ['png'] },
639
+ execute: async (element: HTMLElement): Promise<string | null> => {
640
+ const svg = element.querySelector('.mermaid-preview svg')
641
+ if (!svg) return null
642
+ return svgToPngDataUrl(svg as SVGSVGElement)
643
+ },
644
+ },
645
+ ],
646
+ onInit: () => {
647
+ const cls = document.body.className
648
+ const isCustom = cls.includes('theme-custom')
649
+ const fontSize = isCustom ? getCustomMermaidFontSize() : 14
650
+ mermaid.initialize({
651
+ startOnLoad: false,
652
+ theme: getMermaidTheme(),
653
+ themeVariables: getMermaidThemeVariables(),
654
+ c4: getMermaidC4Config(),
655
+ securityLevel: 'loose',
656
+ fontSize,
657
+ })
658
+ },
659
+ onThemeChange: () => {
660
+ const cls = document.body.className
661
+ const isCustom = cls.includes('theme-custom')
662
+ const fontSize = isCustom ? getCustomMermaidFontSize() : 16
663
+ mermaid.initialize({
664
+ startOnLoad: false,
665
+ theme: getMermaidTheme(),
666
+ themeVariables: getMermaidThemeVariables(),
667
+ c4: getMermaidC4Config(),
668
+ securityLevel: 'loose',
669
+ fontSize,
670
+ })
671
+ },
672
+ }
673
+
674
+ registerPluginModule({
675
+ info: mermaidPlugin,
676
+ milkdownPlugins: [mermaidBlockSchema, mermaidBlockInputRule, mermaidBlockView],
677
+ })
678
+
679
+ export { mermaidBlockSchema, mermaidBlockInputRule, mermaidBlockView, remarkMermaid }
@@ -0,0 +1,7 @@
1
+ import type { ElectronAPI } from '../preload/index'
2
+
3
+ declare global {
4
+ interface Window {
5
+ electronAPI: ElectronAPI
6
+ }
7
+ }