@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,297 @@
1
+ import { $nodeSchema, $view } from '@milkdown/utils'
2
+ import type { NodeViewConstructor } from '@milkdown/prose/view'
3
+ import type { RendererPlugin } from './index'
4
+ import { registerPluginModule } from './index'
5
+ import katex from 'katex'
6
+ import remarkMath from 'remark-math'
7
+ import 'katex/dist/katex.min.css'
8
+
9
+ ;(window as any).katex = katex
10
+
11
+ const mathInlineSchema = $nodeSchema('math_inline', () => ({
12
+ group: 'inline',
13
+ inline: true,
14
+ atom: true,
15
+ priority: 60,
16
+ attrs: {
17
+ text: { default: '', validate: 'string' },
18
+ mode: { default: 'rendered' as 'rendered' | 'raw' },
19
+ },
20
+ parseDOM: [
21
+ { tag: 'span.math-inline', getAttrs: (dom) => ({ text: (dom as HTMLElement).dataset.math || '' }) },
22
+ ],
23
+ toDOM: (node) => {
24
+ const span = document.createElement('span')
25
+ span.className = 'math-inline'
26
+ span.dataset.math = node.attrs.text as string
27
+ const text = (node.attrs.text as string) || ''
28
+ if (node.attrs.mode === 'raw') {
29
+ span.innerHTML = '<code class="math-raw" data-math="' + text + '">$' + text + '$</code>'
30
+ return { dom: span }
31
+ }
32
+ const katexLib = (window as any).katex
33
+ if (katexLib && text) {
34
+ try {
35
+ span.innerHTML = katexLib.renderToString(text, { throwOnError: false, displayMode: false })
36
+ } catch {
37
+ span.textContent = '$' + text + '$'
38
+ }
39
+ } else {
40
+ span.textContent = '$' + text + '$'
41
+ }
42
+ return { dom: span }
43
+ },
44
+ parseMarkdown: {
45
+ match: (node) => node.type === 'inlineMath',
46
+ runner: (state, node, type) => {
47
+ state.addNode(type, { text: (node.value as string) || '' })
48
+ },
49
+ },
50
+ toMarkdown: {
51
+ match: (node) => node.type.name === 'math_inline',
52
+ runner: (state, node) => {
53
+ state.addNode('inlineMath', undefined, node.attrs.text as string)
54
+ },
55
+ },
56
+ }))
57
+
58
+ function renderMathInline(dom: HTMLElement, text: string, mode: string): void {
59
+ dom.dataset.math = text
60
+ dom.innerHTML = ''
61
+ if (mode === 'raw') {
62
+ const input = document.createElement('input')
63
+ input.type = 'text'
64
+ input.className = 'math-inline-raw'
65
+ input.value = '$' + text + '$'
66
+ input.dataset.math = text
67
+ dom.appendChild(input)
68
+ } else {
69
+ const katexLib = (window as any).katex
70
+ if (katexLib) {
71
+ try {
72
+ dom.innerHTML = katexLib.renderToString(text, { throwOnError: false, displayMode: false })
73
+ } catch {
74
+ dom.textContent = '$' + text + '$'
75
+ }
76
+ } else {
77
+ dom.textContent = '$' + text + '$'
78
+ }
79
+ }
80
+ }
81
+
82
+ const mathInlineView = $view(mathInlineSchema, (_ctx): NodeViewConstructor => {
83
+ return (node, view, getPos) => {
84
+ const span = document.createElement('span')
85
+ span.className = 'math-inline'
86
+ renderMathInline(span, node.attrs.text as string, node.attrs.mode as string)
87
+
88
+ span.addEventListener('focusout', (e) => {
89
+ const target = e.target as HTMLElement
90
+ if (!target.classList.contains('math-inline-raw')) return
91
+ const rawValue = (target as HTMLInputElement).value
92
+ const m = rawValue.match(/^\$(.*)\$$/)
93
+ const newText = m ? m[1].trim() : rawValue
94
+ const pos = getPos()
95
+ if (pos != null && node.attrs.text !== newText) {
96
+ view.dispatch(view.state.tr.setNodeMarkup(pos, undefined, { ...node.attrs, text: newText }))
97
+ }
98
+ })
99
+
100
+ return {
101
+ dom: span,
102
+ update: (updatedNode) => {
103
+ if (updatedNode.type !== node.type) return false
104
+ if (updatedNode.sameMarkup(node)) return true
105
+ node = updatedNode
106
+ renderMathInline(span, node.attrs.text as string, node.attrs.mode as string)
107
+ return true
108
+ },
109
+ stopEvent: (e) => {
110
+ return (e.target as HTMLElement).matches('input, textarea')
111
+ },
112
+ ignoreMutation: () => true,
113
+ destroy: () => { span.remove() },
114
+ }
115
+ }
116
+ })
117
+
118
+ const mathBlockSchema = $nodeSchema('math_block', () => ({
119
+ group: 'block',
120
+ atom: true,
121
+ priority: 60,
122
+ attrs: {
123
+ text: { default: '', validate: 'string' },
124
+ mode: { default: 'rendered' as 'rendered' | 'raw' },
125
+ },
126
+ parseDOM: [
127
+ { tag: 'div.math-block', getAttrs: (dom) => ({ text: (dom as HTMLElement).dataset.math || '' }) },
128
+ ],
129
+ toDOM: (node) => {
130
+ const div = document.createElement('div')
131
+ div.className = 'math-block'
132
+ div.dataset.math = node.attrs.text as string
133
+ const text = (node.attrs.text as string) || ''
134
+ if (node.attrs.mode === 'raw') {
135
+ div.innerHTML = '<pre class="math-raw" data-math="' + text + '">$$\n' + text + '\n$$</pre>'
136
+ return { dom: div }
137
+ }
138
+ const katexLib = (window as any).katex
139
+ if (katexLib && text) {
140
+ try {
141
+ div.innerHTML = katexLib.renderToString(text, { throwOnError: false, displayMode: true })
142
+ } catch {
143
+ div.textContent = '$$\n' + text + '\n$$'
144
+ }
145
+ } else {
146
+ div.textContent = '$$\n' + text + '\n$$'
147
+ }
148
+ return { dom: div }
149
+ },
150
+ parseMarkdown: {
151
+ match: (node) => node.type === 'math',
152
+ runner: (state, node, type) => {
153
+ state.addNode(type, { text: (node.value as string) || '' })
154
+ },
155
+ },
156
+ toMarkdown: {
157
+ match: (node) => node.type.name === 'math_block',
158
+ runner: (state, node) => {
159
+ state.addNode('math', undefined, node.attrs.text as string)
160
+ },
161
+ },
162
+ }))
163
+
164
+ function renderMathBlock(dom: HTMLElement, text: string, mode: string): void {
165
+ dom.dataset.math = text
166
+ dom.innerHTML = ''
167
+ if (mode === 'raw') {
168
+ const textarea = document.createElement('textarea')
169
+ textarea.className = 'math-block-raw'
170
+ textarea.dataset.math = text
171
+ textarea.value = '$$\n' + text + '\n$$'
172
+ textarea.rows = Math.min(10, (text.match(/\n/g) || []).length + 2)
173
+ dom.appendChild(textarea)
174
+ } else {
175
+ const katexLib = (window as any).katex
176
+ if (katexLib) {
177
+ try {
178
+ dom.innerHTML = katexLib.renderToString(text, { throwOnError: false, displayMode: true })
179
+ } catch {
180
+ dom.textContent = '$$\n' + text + '\n$$'
181
+ }
182
+ } else {
183
+ dom.textContent = '$$\n' + text + '\n$$'
184
+ }
185
+ }
186
+ }
187
+
188
+ const mathBlockView = $view(mathBlockSchema, (_ctx): NodeViewConstructor => {
189
+ return (node, view, getPos) => {
190
+ const div = document.createElement('div')
191
+ div.className = 'math-block'
192
+ renderMathBlock(div, node.attrs.text as string, node.attrs.mode as string)
193
+
194
+ div.addEventListener('focusout', (e) => {
195
+ const target = e.target as HTMLElement
196
+ if (!target.classList.contains('math-block-raw')) return
197
+ const rawValue = (target as HTMLTextAreaElement).value
198
+ const newText = rawValue.replace(/^\$\$\s*\n?/, '').replace(/\n?\s*\$\$$/, '').trim()
199
+ const pos = getPos()
200
+ if (pos != null && node.attrs.text !== newText) {
201
+ view.dispatch(view.state.tr.setNodeMarkup(pos, undefined, { ...node.attrs, text: newText }))
202
+ }
203
+ })
204
+
205
+ return {
206
+ dom: div,
207
+ update: (updatedNode) => {
208
+ if (updatedNode.type !== node.type) return false
209
+ if (updatedNode.sameMarkup(node)) return true
210
+ node = updatedNode
211
+ renderMathBlock(div, node.attrs.text as string, node.attrs.mode as string)
212
+ return true
213
+ },
214
+ stopEvent: (e) => {
215
+ return (e.target as HTMLElement).matches('input, textarea')
216
+ },
217
+ ignoreMutation: () => true,
218
+ destroy: () => { div.remove() },
219
+ }
220
+ }
221
+ })
222
+
223
+ function getKatexCSS(): string {
224
+ const sheets: string[] = []
225
+ for (const sheet of document.styleSheets) {
226
+ try {
227
+ if (sheet.href && sheet.href.includes('katex')) {
228
+ const rules = []
229
+ for (const rule of sheet.cssRules) {
230
+ rules.push(rule.cssText)
231
+ }
232
+ if (rules.length) sheets.push(rules.join('\n'))
233
+ }
234
+ } catch { /* cross-origin sheets throw */ }
235
+ }
236
+ return sheets.join('\n')
237
+ }
238
+
239
+ function mathHtmlToPngDataUrl(element: HTMLElement, scale = 2): Promise<string> {
240
+ const w = element.offsetWidth + 32
241
+ const h = element.offsetHeight + 32
242
+ const canvas = document.createElement('canvas')
243
+ canvas.width = w * scale
244
+ canvas.height = h * scale
245
+ const ctx = canvas.getContext('2d')!
246
+ ctx.scale(scale, scale)
247
+ ctx.fillStyle = '#ffffff'
248
+ ctx.fillRect(0, 0, w, h)
249
+ const katexCSS = getKatexCSS()
250
+ const xml = new XMLSerializer().serializeToString(element)
251
+ const imgSrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(
252
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">` +
253
+ `<style>${katexCSS}</style>` +
254
+ `<foreignObject width="100%" height="100%" style="background:#fff;padding:16px">` +
255
+ xml +
256
+ `</foreignObject></svg>`
257
+ )))
258
+ return new Promise((resolve, reject) => {
259
+ const img = document.createElement('img')
260
+ img.onload = () => {
261
+ ctx.drawImage(img, 16, 16)
262
+ resolve(canvas.toDataURL('image/png'))
263
+ }
264
+ img.onerror = () => reject(new Error('Failed to render equation to image'))
265
+ img.src = imgSrc
266
+ })
267
+ }
268
+
269
+ export const mathPlugin: RendererPlugin = {
270
+ id: 'math',
271
+ name: 'Math Rendering',
272
+ enabled: true,
273
+ remarkPlugin: { plugin: remarkMath, options: undefined },
274
+ nodeTypes: ['math_inline', 'math_block'],
275
+ // TODO: KaTeX CSS 在 SVG foreignObject 中丢失,导致导出 PNG 二次内容/空白
276
+ // 后续需解决样式注入问题后重新启用
277
+ // exportCapabilities: [
278
+ // {
279
+ // label: 'Save Equation as PNG',
280
+ // defaultName: 'equation.png',
281
+ // filter: { name: 'PNG Image', extensions: ['png'] },
282
+ // execute: async (element: HTMLElement): Promise<string | null> => {
283
+ // if (element.classList.contains('math-block')) {
284
+ // return mathHtmlToPngDataUrl(element)
285
+ // }
286
+ // return null
287
+ // },
288
+ // },
289
+ // ],
290
+ }
291
+
292
+ registerPluginModule({
293
+ info: mathPlugin,
294
+ milkdownPlugins: [mathInlineSchema, mathBlockSchema, mathInlineView, mathBlockView],
295
+ })
296
+
297
+ export { mathInlineSchema, mathBlockSchema, mathInlineView, mathBlockView }