@bytechain.cn/colamd 1.5.0 → 1.5.1-beta.2

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 (193) hide show
  1. package/.trae/specs/optimize-theme-loading/checklist.md +20 -0
  2. package/.trae/specs/optimize-theme-loading/spec.md +103 -0
  3. package/.trae/specs/optimize-theme-loading/tasks.md +40 -0
  4. package/CHANGELOG.md +323 -0
  5. package/CLAUDE.md +56 -0
  6. package/README.md +422 -26
  7. package/README_CN.md +480 -28
  8. package/android/app/build/.npmkeep +0 -0
  9. package/android/app/build.gradle +76 -0
  10. package/android/app/capacitor.build.gradle +24 -0
  11. package/android/app/proguard-rules.pro +21 -0
  12. package/android/app/release.keystore +0 -0
  13. package/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
  14. package/android/app/src/main/AndroidManifest.xml +64 -0
  15. package/android/app/src/main/java/cn/bytechain/colamd/MainActivity.java +180 -0
  16. package/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  17. package/android/app/src/main/res/drawable/splash.png +0 -0
  18. package/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  19. package/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  20. package/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  21. package/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  22. package/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  23. package/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  24. package/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  25. package/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  26. package/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  27. package/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  28. package/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
  29. package/android/app/src/main/res/layout/activity_main.xml +12 -0
  30. package/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  31. package/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  32. package/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  33. package/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  34. package/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  35. package/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  36. package/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  37. package/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  38. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  39. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  40. package/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  41. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  42. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  43. package/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  44. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  45. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  46. package/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  47. package/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
  48. package/android/app/src/main/res/values/strings.xml +7 -0
  49. package/android/app/src/main/res/values/styles.xml +22 -0
  50. package/android/app/src/main/res/xml/file_paths.xml +5 -0
  51. package/android/app/src/main/res/xml/network_security_config.xml +8 -0
  52. package/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
  53. package/android/build.gradle +29 -0
  54. package/android/capacitor.settings.gradle +21 -0
  55. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  56. package/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  57. package/android/gradle.properties +22 -0
  58. package/android/gradlew +248 -0
  59. package/android/gradlew.bat +92 -0
  60. package/android/settings.gradle +5 -0
  61. package/android/variables.gradle +16 -0
  62. package/bytechain.cn-colamd-1.5.1-beta.2.tgz +0 -0
  63. package/capacitor.config.js +29 -0
  64. package/capacitor.config.ts +30 -0
  65. package/demo.md +191 -484
  66. package/dist/main/index.js +77 -46
  67. package/dist/renderer/assets/{arc-tTbbM8LO.js → arc-CPdeInCG.js} +1 -1
  68. package/dist/renderer/assets/{architectureDiagram-3BPJPVTR-CEgYow6c.js → architectureDiagram-3BPJPVTR-BAbnaR9G.js} +4 -3
  69. package/dist/renderer/assets/{blockDiagram-GPEHLZMM-LHyVtPwW.js → blockDiagram-GPEHLZMM-CYSWjnJg.js} +5 -4
  70. package/dist/renderer/assets/{c4Diagram-AAUBKEIU-C1P1eJrf.js → c4Diagram-AAUBKEIU-Rb1tstnr.js} +3 -2
  71. package/dist/renderer/assets/{channel-upve91Tq.js → channel-DpG2A6fE.js} +1 -1
  72. package/dist/renderer/assets/{chunk-2J33WTMH-lag2vhq9.js → chunk-2J33WTMH-DFc0Jxy_.js} +1 -1
  73. package/dist/renderer/assets/{chunk-4BX2VUAB-BXJ8Ggh-.js → chunk-4BX2VUAB-BhRxDTNn.js} +1 -1
  74. package/dist/renderer/assets/{chunk-55IACEB6-CiBpxRa1.js → chunk-55IACEB6-DEgMVBk8.js} +1 -1
  75. package/dist/renderer/assets/{chunk-727SXJPM-ODeKQFXC.js → chunk-727SXJPM-bjBIfiz8.js} +5 -5
  76. package/dist/renderer/assets/{chunk-AQP2D5EJ-BK7xJolB.js → chunk-AQP2D5EJ-DwQMzTzD.js} +3 -3
  77. package/dist/renderer/assets/{chunk-FMBD7UC4-BxpCZPtz.js → chunk-FMBD7UC4-CkphwJzs.js} +1 -1
  78. package/dist/renderer/assets/{chunk-ND2GUHAM-CqqaU9Ue.js → chunk-ND2GUHAM-oU09z4y4.js} +1 -1
  79. package/dist/renderer/assets/{chunk-QZHKN3VN-Biq_K124.js → chunk-QZHKN3VN-rCbVuPBn.js} +1 -1
  80. package/dist/renderer/assets/{classDiagram-v2-Q7XG4LA2-Cq95X99o.js → classDiagram-4FO5ZUOK-DGS2faoM.js} +7 -6
  81. package/dist/renderer/assets/{classDiagram-4FO5ZUOK-Cq95X99o.js → classDiagram-v2-Q7XG4LA2-DGS2faoM.js} +7 -6
  82. package/dist/renderer/assets/{cose-bilkent-S5V4N54A-XasiD0bu.js → cose-bilkent-S5V4N54A-iqY6-EwA.js} +2 -1
  83. package/dist/renderer/assets/{dagre-BM42HDAG-Nq84Gfx4.js → dagre-BM42HDAG-5t3X5sDa.js} +4 -3
  84. package/dist/renderer/assets/{diagram-2AECGRRQ-DwuB1GWt.js → diagram-2AECGRRQ-DzHiYDPh.js} +4 -3
  85. package/dist/renderer/assets/{diagram-5GNKFQAL-C2tgeI1h.js → diagram-5GNKFQAL-BiNv6Keq.js} +5 -4
  86. package/dist/renderer/assets/{diagram-KO2AKTUF-D5KzjNBc.js → diagram-KO2AKTUF-ClzeDG6f.js} +4 -3
  87. package/dist/renderer/assets/{diagram-LMA3HP47-C12xHS1c.js → diagram-LMA3HP47-CGkw7wII.js} +4 -3
  88. package/dist/renderer/assets/{diagram-OG6HWLK6-CnxI9oEa.js → diagram-OG6HWLK6-Dl-Hyk1_.js} +5 -4
  89. package/dist/renderer/assets/{erDiagram-TEJ5UH35-D_uPaKwn.js → erDiagram-TEJ5UH35-BxUN79Qb.js} +5 -4
  90. package/dist/renderer/assets/{flowDiagram-I6XJVG4X-B6q_1-tE.js → flowDiagram-I6XJVG4X-CzFk-KNI.js} +7 -6
  91. package/dist/renderer/assets/{ganttDiagram-6RSMTGT7-CFo7ifF9.js → ganttDiagram-6RSMTGT7-C2xl6Igx.js} +3 -2
  92. package/dist/renderer/assets/{gitGraphDiagram-PVQCEYII-WSexHTnq.js → gitGraphDiagram-PVQCEYII-_fn7XCa7.js} +5 -4
  93. package/dist/renderer/assets/{graph-DyX_9f6d.js → graph-CDoHYrHm.js} +1 -1
  94. package/dist/renderer/assets/index-B4uDgADr.js +530 -0
  95. package/dist/renderer/assets/index-CBcVpA3d.js +30 -0
  96. package/dist/renderer/assets/index-CGj1spkU.js +27 -0
  97. package/dist/renderer/assets/{index-dyHEFYvY.css → index-CeFpoCKV.css} +443 -400
  98. package/dist/renderer/assets/index-D4CPFkph.js +9 -0
  99. package/dist/renderer/assets/{index-DW7LS8C1.js → index-DAlXyxzt.js} +1183 -346
  100. package/dist/renderer/assets/index-DxOzbfR-.js +110 -0
  101. package/dist/renderer/assets/index-Y89U1ptl.js +9 -0
  102. package/dist/renderer/assets/{infoDiagram-5YYISTIA-DaeJdLRq.js → infoDiagram-5YYISTIA-DL6XIxLz.js} +3 -2
  103. package/dist/renderer/assets/{ishikawaDiagram-YF4QCWOH-DDCZc35f.js → ishikawaDiagram-YF4QCWOH-BUZLjRo-.js} +2 -1
  104. package/dist/renderer/assets/{journeyDiagram-JHISSGLW-BEdmpAgl.js → journeyDiagram-JHISSGLW-C4rH_mQM.js} +5 -4
  105. package/dist/renderer/assets/{kanban-definition-UN3LZRKU-BEFtQcFb.js → kanban-definition-UN3LZRKU-DRbrBcWV.js} +3 -2
  106. package/dist/renderer/assets/{layout-CAJgQHdw.js → layout-DZl4n4qu.js} +2 -2
  107. package/dist/renderer/assets/{linear-B2ggJ8Am.js → linear-B0Krxg21.js} +1 -1
  108. package/dist/renderer/assets/{mindmap-definition-RKZ34NQL-DSxVgHB5.js → mindmap-definition-RKZ34NQL-DdmPsWrn.js} +4 -3
  109. package/dist/renderer/assets/{pieDiagram-4H26LBE5-CwYoJBuL.js → pieDiagram-4H26LBE5-BPZLqwG0.js} +5 -4
  110. package/dist/renderer/assets/preload-helper-tXtZnHb0.js +88 -0
  111. package/dist/renderer/assets/{quadrantDiagram-W4KKPZXB-CST9Fvg9.js → quadrantDiagram-W4KKPZXB-Dr-oWRk9.js} +3 -2
  112. package/dist/renderer/assets/{requirementDiagram-4Y6WPE33-DtrH52jS.js → requirementDiagram-4Y6WPE33-B6QZd0lo.js} +4 -3
  113. package/dist/renderer/assets/{sankeyDiagram-5OEKKPKP-ca1tPzJ_.js → sankeyDiagram-5OEKKPKP-Cyl9ojEt.js} +2 -1
  114. package/dist/renderer/assets/{sequenceDiagram-3UESZ5HK-Dfp1EJZ7.js → sequenceDiagram-3UESZ5HK-D48Yr9T6.js} +4 -3
  115. package/dist/renderer/assets/{stateDiagram-AJRCARHV-Bha2QoNB.js → stateDiagram-AJRCARHV-qyb8ETsa.js} +7 -6
  116. package/dist/renderer/assets/{stateDiagram-v2-BHNVJYJU-DWgFUYu1.js → stateDiagram-v2-BHNVJYJU-DmDOyyrJ.js} +5 -4
  117. package/dist/renderer/assets/{timeline-definition-PNZ67QCA-C3h_-OTj.js → timeline-definition-PNZ67QCA-C-KQxTi1.js} +3 -2
  118. package/dist/renderer/assets/{vennDiagram-CIIHVFJN-DFzjSrZi.js → vennDiagram-CIIHVFJN-BdaZlnH-.js} +2 -1
  119. package/dist/renderer/assets/{wardley-L42UT6IY-Cx-VbqoS.js → wardley-L42UT6IY-b-_GPpqL.js} +1 -1
  120. package/dist/renderer/assets/{wardleyDiagram-YWT4CUSO-S2D9XqX6.js → wardleyDiagram-YWT4CUSO-B2hBE-EE.js} +4 -3
  121. package/dist/renderer/assets/web-BKE0SH0E.js +36 -0
  122. package/dist/renderer/assets/web-CBsFp24u.js +564 -0
  123. package/dist/renderer/assets/web-Dc8YgoHP.js +24 -0
  124. package/dist/renderer/assets/web-TfDzToU7.js +58 -0
  125. package/dist/renderer/assets/{xychartDiagram-2RQKCTM6-Cfxigbts.js → xychartDiagram-2RQKCTM6-CSvswDTY.js} +3 -2
  126. package/dist/renderer/index.html +62 -3
  127. package/docs/academic-demo.md +566 -0
  128. package/docs/demo.html +748 -0
  129. package/docs/demo.md +546 -0
  130. package/docs/demo.pdf +0 -0
  131. package/docs/theme-paradigm.md +658 -0
  132. package/electron-builder.yml +7 -0
  133. package/electron.vite.config.js +31 -0
  134. package/electron.vite.config.ts +1 -1
  135. package/ios/App/App/AppDelegate.swift +49 -0
  136. package/ios/App/App/Assets.xcassets/AppIcon.appiconset/AppIcon-512@2x.png +0 -0
  137. package/ios/App/App/Assets.xcassets/AppIcon.appiconset/Contents.json +14 -0
  138. package/ios/App/App/Assets.xcassets/Contents.json +6 -0
  139. package/ios/App/App/Assets.xcassets/Splash.imageset/Contents.json +23 -0
  140. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-1.png +0 -0
  141. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732-2.png +0 -0
  142. package/ios/App/App/Assets.xcassets/Splash.imageset/splash-2732x2732.png +0 -0
  143. package/ios/App/App/Base.lproj/LaunchScreen.storyboard +32 -0
  144. package/ios/App/App/Base.lproj/Main.storyboard +19 -0
  145. package/ios/App/App/Info.plist +49 -0
  146. package/ios/App/App.xcodeproj/project.pbxproj +408 -0
  147. package/ios/App/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  148. package/ios/App/Podfile +28 -0
  149. package/package.json +23 -3
  150. package/resources/templates/slides/template-forest-ink.html +540 -0
  151. package/scripts/generate-icons.js +102 -0
  152. package/src/main/index.ts +87 -63
  153. package/src/preload/index.d.ts +51 -0
  154. package/src/preload/index.js +70 -0
  155. package/src/renderer/capacitor-api.ts +713 -0
  156. package/src/renderer/editor/editor.ts +87 -4
  157. package/src/renderer/editor/plugins/index.ts +24 -32
  158. package/src/renderer/editor/plugins/math-plugin.ts +1 -1
  159. package/src/renderer/editor/plugins/mermaid-plugin-custom.css +13 -398
  160. package/src/renderer/editor/plugins/mermaid-plugin.ts +62 -71
  161. package/src/renderer/editor/plugins/themes/base/dark.css +23 -0
  162. package/src/renderer/editor/plugins/themes/base/elegant.css +32 -0
  163. package/src/renderer/editor/plugins/themes/base/light.css +20 -0
  164. package/src/renderer/editor/plugins/themes/base/newsprint.css +27 -0
  165. package/src/renderer/editor/plugins/themes/components/mermaid/academic.css +43 -0
  166. package/src/renderer/editor/plugins/themes/components/mermaid/dark.css +20 -0
  167. package/src/renderer/editor/plugins/themes/components/mermaid/elegant.css +24 -0
  168. package/src/renderer/editor/plugins/themes/components/mermaid/light.css +21 -0
  169. package/src/renderer/editor/plugins/themes/components/mermaid/newsprint.css +26 -0
  170. package/src/renderer/editor/plugins/themes/components/mermaid/variables.css +592 -0
  171. package/src/renderer/editor/plugins/themes/foundation.css +143 -0
  172. package/src/renderer/editor/plugins/themes/theme-manager.ts +92 -0
  173. package/src/renderer/env.d.ts +4 -1
  174. package/src/renderer/index.html +59 -1
  175. package/src/renderer/main.ts +432 -57
  176. package/src/renderer/mobile.css +429 -0
  177. package/themes/README.md +3 -0
  178. package/themes/academic-paper.css +1321 -0
  179. package/themes/elegant.css +14 -7
  180. package/themes/forest-ink.css +664 -0
  181. package/themes/pixso-design.css +1261 -0
  182. package/themes/swiss-design.css +596 -0
  183. package/themes/template.css +498 -0
  184. package/tsconfig.main.json +1 -0
  185. package/tsconfig.main.tsbuildinfo +1 -0
  186. package/tsconfig.preload.json +1 -0
  187. package/tsconfig.preload.tsbuildinfo +1 -0
  188. package/tsconfig.renderer.json +1 -0
  189. package/tsconfig.renderer.tsbuildinfo +1 -0
  190. package/tsconfig.tsbuildinfo +1 -0
  191. package/.trae/documents/fix-mermaid-colors-and-sankey.md +0 -50
  192. package/src/renderer/themes/theme-manager.ts +0 -40
  193. /package/src/renderer/{themes → editor/plugins/themes}/base.css +0 -0
@@ -89,7 +89,7 @@ export async function createEditor(
89
89
  ctx.set(remarkPluginsCtx, [
90
90
  ...pluginModules.map((m) => m.info.remarkPlugin),
91
91
  { plugin: remarkBreaks, options: undefined },
92
- ])
92
+ ] as any)
93
93
  if (onChange) {
94
94
  ctx.get(listenerCtx).markdownUpdated((_ctx, markdown) => {
95
95
  onChange(markdown)
@@ -109,7 +109,38 @@ export async function createEditor(
109
109
  }
110
110
  }
111
111
 
112
- editorInstance = await builder.create()
112
+ try {
113
+ editorInstance = await builder.create()
114
+ } catch (e: any) {
115
+ if (e?.message?.includes('math_inline') || e?.message?.includes('math_block')) {
116
+ console.warn('[editor] Milkdown context error, retrying without math plugins:', e.message)
117
+ const filteredModules = pluginModules.filter((m) => m.info.id !== 'math')
118
+ builder = Editor.make()
119
+ .config((ctx) => {
120
+ ctx.set(rootCtx, root)
121
+ ctx.set(defaultValueCtx, defaultContent)
122
+ ctx.set(remarkPluginsCtx, [
123
+ ...filteredModules.map((m) => m.info.remarkPlugin),
124
+ { plugin: remarkBreaks, options: undefined },
125
+ ] as any)
126
+ if (onChange) ctx.get(listenerCtx).markdownUpdated((_ctx, markdown) => { onChange(markdown) })
127
+ })
128
+ .use(commonmark)
129
+ .use(gfm)
130
+ .use(history)
131
+ .use(listener)
132
+ .use(clipboard)
133
+ .use(htmlView)
134
+ for (const mod of filteredModules) {
135
+ for (const p of mod.milkdownPlugins) {
136
+ builder = builder.use(p)
137
+ }
138
+ }
139
+ editorInstance = await builder.create()
140
+ } else {
141
+ throw e
142
+ }
143
+ }
113
144
 
114
145
  editorInstance.action((ctx) => {
115
146
  const nvs = ctx.get(nodeViewCtx)
@@ -127,8 +158,9 @@ export async function createEditor(
127
158
  ctx.set(nodeViewCtx, fixed)
128
159
 
129
160
  const oldView = ctx.get(editorViewCtx)
130
- const rootEl = ctx.get(rootCtx)
161
+ const rootEl = ctx.get(rootCtx) as HTMLElement
131
162
  const nodeViews = Object.fromEntries(fixed)
163
+
132
164
  const newView = new EditorView(rootEl, {
133
165
  state: oldView.state,
134
166
  nodeViews,
@@ -142,6 +174,19 @@ export async function createEditor(
142
174
  root.addEventListener('copy', enhanceClipboard)
143
175
  root.addEventListener('cut', enhanceClipboard)
144
176
 
177
+ /*
178
+ * REMOVED: Custom IME composition handlers for mobile CJK input.
179
+ * ProseMirror handles IME composition natively via its DOM observer and input rules.
180
+ * These handlers dispatched synthetic input events that interfered with ProseMirror's
181
+ * internal state tracking, causing duplicated characters and broken undo history.
182
+ *
183
+ * Original code:
184
+ * if (/android|iphone|ipad/i.test(navigator.userAgent)) {
185
+ * root.addEventListener('compositionstart', () => { ... })
186
+ * root.addEventListener('compositionend', () => { ... })
187
+ * }
188
+ */
189
+
145
190
  root.addEventListener('click', (e) => {
146
191
  if (!(e.metaKey || e.ctrlKey)) return
147
192
  const link = (e.target as HTMLElement).closest('a')
@@ -149,7 +194,8 @@ export async function createEditor(
149
194
  const href = link.getAttribute('href')
150
195
  if (href) {
151
196
  e.preventDefault()
152
- window.electronAPI.openExternal(href)
197
+ window.electronAPI?.openExternal(href)
198
+ window.capacitorAPI?.openExternal(href)
153
199
  }
154
200
  })
155
201
 
@@ -167,6 +213,43 @@ export function getMarkdown(): string {
167
213
  return markdown
168
214
  }
169
215
 
216
+ /**
217
+ * Get HTML by cloning the live rendered DOM.
218
+ * Unlike {@link getHTML} which uses DOMSerializer (creating fresh nodes with
219
+ * "Rendering..." placeholders), this captures the actual rendered SVGs
220
+ * from mermaid, KaTeX math, etc. Used for PDF/HTML export.
221
+ */
222
+ export function getLiveHTML(): string {
223
+ const editorDom = document.querySelector('#editor .ProseMirror')
224
+ if (!editorDom) return ''
225
+ const clone = editorDom.cloneNode(true) as HTMLElement
226
+
227
+ // Inline computed background colors so export preserves exact editor appearance.
228
+ // CSS variables from the export template may not match the editor's cascade.
229
+ const styleTargets: Array<{ selector: string; prop: string }> = [
230
+ { selector: '.math-inline', prop: 'backgroundColor' },
231
+ { selector: '.math-block', prop: 'backgroundColor' },
232
+ { selector: '.mermaid-block', prop: 'backgroundColor' },
233
+ ]
234
+ for (const { selector, prop } of styleTargets) {
235
+ const originals = editorDom.querySelectorAll(selector)
236
+ const clones = clone.querySelectorAll(selector)
237
+ originals.forEach((orig, i) => {
238
+ const computed = getComputedStyle(orig)
239
+ const val = computed.getPropertyValue(prop === 'backgroundColor' ? 'background-color' : prop)
240
+ if (val && clones[i]) (clones[i] as HTMLElement).style.setProperty(prop, val)
241
+ })
242
+ }
243
+
244
+ // Remove source-mode textareas
245
+ clone.querySelectorAll('textarea.mermaid-source, .math-inline-raw, .math-block-raw')
246
+ .forEach(el => el.remove())
247
+ // Hide loading/error placeholders
248
+ clone.querySelectorAll('.mermaid-loading, .mermaid-error')
249
+ .forEach(el => (el as HTMLElement).style.display = 'none')
250
+ return clone.innerHTML
251
+ }
252
+
170
253
  export function getHTML(): string {
171
254
  if (!editorInstance) return ''
172
255
  let html = ''
@@ -12,11 +12,17 @@ export interface RendererPlugin {
12
12
  id: string
13
13
  name: string
14
14
  enabled: boolean
15
- remarkPlugin: { plugin: Plugin; options?: any }
16
- nodeTypes: string[]
15
+ remarkPlugin?: { plugin: Plugin<any[], any>; options?: any }
16
+ rehypePlugin?: Plugin<any[], any>
17
+ onMount?: (...args: any[]) => any
18
+ onBeforeMount?: (...args: any[]) => any
17
19
  onInit?: () => void
18
- onThemeChange?: (theme: string) => void
20
+ onThemeChange?: (theme: string, customCSS?: string) => void
21
+ css?: string
22
+ nodeTypes?: string[]
19
23
  exportCapabilities?: ExportCapability[]
24
+ renderStatus?: (container: HTMLElement) => Promise<{ ok: number; fail: number; total: number }>
25
+ ensureRendered?: () => Promise<void>
20
26
  }
21
27
 
22
28
  export interface PluginModule {
@@ -35,42 +41,28 @@ export function getAllPluginModules(): PluginModule[] {
35
41
  }
36
42
 
37
43
  export function getAllPlugins(): RendererPlugin[] {
38
- return modules.map(m => m.info)
44
+ return modules.map((m) => m.info)
39
45
  }
40
46
 
41
- export function getEnabledPlugins(): RendererPlugin[] {
42
- return modules.filter(m => m.info.enabled).map(m => m.info)
43
- }
44
-
45
- export function getPlugin(id: string): RendererPlugin | undefined {
46
- return modules.find(m => m.info.id === id)?.info
47
- }
48
-
49
- export function togglePlugin(id: string): void {
50
- const m = modules.find(m => m.info.id === id)
51
- if (m) m.info.enabled = !m.info.enabled
52
- }
53
-
54
- export function findPluginBySelector(selector: string): { plugin: RendererPlugin; capability: ExportCapability } | undefined {
55
- for (const m of modules) {
56
- if (!m.info.enabled || !m.info.exportCapabilities?.length) continue
57
- for (const nodeType of m.info.nodeTypes) {
58
- if (selector.includes(nodeType.replace(/_/g, '-'))) {
59
- return { plugin: m.info, capability: m.info.exportCapabilities[0] }
60
- }
61
- }
47
+ export function findPluginBySelector(selector: string): RendererPlugin | undefined {
48
+ const plugins = getAllPlugins()
49
+ if (selector.startsWith('node:')) {
50
+ const name = selector.slice(5)
51
+ return plugins.find((p) => p.nodeTypes?.includes(name))
62
52
  }
63
- return undefined
53
+ return plugins.find((p) => p.id === selector)
64
54
  }
65
55
 
66
- export function findExportCapabilities(selector: string): ExportCapability[] {
56
+ export function findExportCapabilities(className: string): ExportCapability[] {
67
57
  for (const m of modules) {
68
- if (!m.info.enabled || !m.info.exportCapabilities?.length) continue
69
- for (const nodeType of m.info.nodeTypes) {
70
- if (selector.includes(nodeType.replace(/_/g, '-'))) {
71
- return m.info.exportCapabilities
72
- }
58
+ if (m.info.enabled && m.info.exportCapabilities && m.info.nodeTypes?.some(nt => className.includes(nt.replace(/_/g, '-')))) {
59
+ return m.info.exportCapabilities
73
60
  }
74
61
  }
75
62
  return []
76
63
  }
64
+
65
+ export function togglePlugin(id: string, enabled: boolean): void {
66
+ const mod = modules.find((m) => m.info.id === id)
67
+ if (mod) mod.info.enabled = enabled
68
+ }
@@ -194,7 +194,7 @@ const mathBlockView = $view(mathBlockSchema, (_ctx): NodeViewConstructor => {
194
194
  div.addEventListener('focusout', (e) => {
195
195
  const target = e.target as HTMLElement
196
196
  if (!target.classList.contains('math-block-raw')) return
197
- const rawValue = (target as HTMLTextAreaElement).value
197
+ const rawValue = (e.target as HTMLTextAreaElement).value
198
198
  const newText = rawValue.replace(/^\$\$\s*\n?/, '').replace(/\n?\s*\$\$$/, '').trim()
199
199
  const pos = getPos()
200
200
  if (pos != null && node.attrs.text !== newText) {
@@ -1,21 +1,27 @@
1
+ /* === 字体 & 文字颜色基础定义 === */
1
2
  body.theme-custom .mermaid-preview svg text {
2
3
  fill: var(--mermaid-text-color, var(--text-color)) !important;
3
4
  font-family: var(--mermaid-font-family, inherit) !important;
4
5
  font-size: var(--mermaid-font-size, 12px) !important;
5
6
  }
6
7
 
7
- body.theme-custom .mermaid-preview svg .nodeLabel span,
8
- body.theme-custom .mermaid-preview svg .edgeLabel span {
9
- font-family: var(--mermaid-font-family, inherit) !important;
10
- font-size: var(--mermaid-font-size, 14px) !important;
11
- }
12
-
8
+ /* === ForeignObject 文字 === */
13
9
  body.theme-custom .mermaid-preview svg foreignObject span {
14
10
  color: var(--mermaid-text-color, var(--text-color)) !important;
15
11
  font-family: var(--mermaid-font-family, inherit) !important;
16
12
  font-size: var(--mermaid-font-size, 14px) !important;
17
13
  }
18
14
 
15
+ /* === Person-Man 强制白色 === */
16
+ body.theme-custom .mermaid-preview svg .person-man text {
17
+ fill: #ffffff !important;
18
+ }
19
+
20
+ body.theme-custom .mermaid-preview svg .person-man span {
21
+ color: #ffffff !important;
22
+ }
23
+
24
+ /* === 文字偏移样式(custom 主题特有) === */
19
25
  body.theme-custom .mermaid-preview svg .label text,
20
26
  body.theme-custom .mermaid-preview svg .nodeLabel text,
21
27
  body.theme-custom .mermaid-preview svg .state-title,
@@ -37,395 +43,4 @@ body.theme-custom .mermaid-preview svg .edgeLabel {
37
43
  display: inline-block !important;
38
44
  position: relative !important;
39
45
  top: -3px !important;
40
- }
41
-
42
- body.theme-custom .mermaid-preview svg .node rect,
43
- body.theme-custom .mermaid-preview svg .node circle,
44
- body.theme-custom .mermaid-preview svg .node ellipse,
45
- body.theme-custom .mermaid-preview svg .node polygon,
46
- body.theme-custom .mermaid-preview svg .node path {
47
- stroke: var(--mermaid-node-border, var(--border-color));
48
- }
49
-
50
- body.theme-custom .mermaid-preview svg .edgePath .path {
51
- stroke: var(--mermaid-line-color, var(--border-color));
52
- }
53
-
54
- body.theme-custom .mermaid-preview svg .cluster rect,
55
- body.theme-custom .mermaid-preview svg .cluster path {
56
- stroke: var(--mermaid-cluster-border, var(--border-color));
57
- }
58
-
59
- body.theme-custom .mermaid-preview svg defs marker path {
60
- fill: var(--mermaid-arrowhead-color, var(--mermaid-line-color, var(--border-color)));
61
- stroke: var(--mermaid-arrowhead-color, var(--mermaid-line-color, var(--border-color)));
62
- }
63
-
64
- body.theme-custom .mermaid-preview svg rect[stroke="#444444"] {
65
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
66
- }
67
-
68
- body.theme-custom .mermaid-preview svg path[stroke="#444444"] {
69
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
70
- }
71
-
72
- body.theme-custom .mermaid-preview svg rect[stroke="#000000"] {
73
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
74
- }
75
-
76
- body.theme-custom .mermaid-preview svg path[stroke="#000000"] {
77
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
78
- }
79
-
80
- body.theme-custom .mermaid-preview svg line[stroke="#444444"] {
81
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
82
- }
83
-
84
- body.theme-custom .mermaid-preview svg line[stroke="#000000"] {
85
- stroke: var(--mermaid-node-border, var(--border-color)) !important;
86
- }
87
-
88
- body.theme-custom .mermaid-preview svg .edgeLabel text {
89
- fill: var(--mermaid-text-color, var(--text-color)) !important;
90
- }
91
-
92
- body.theme-custom .mermaid-preview svg .edgeLabel rect {
93
- fill: var(--mermaid-edge-label-background, var(--code-block-bg)) !important;
94
- }
95
-
96
- body.theme-custom .mermaid-preview svg .edgeLabel span {
97
- color: var(--mermaid-text-color, var(--text-color)) !important;
98
- }
99
-
100
- body.theme-custom .mermaid-preview svg .label text {
101
- fill: var(--mermaid-text-color, var(--text-color)) !important;
102
- }
103
-
104
- body.theme-custom .mermaid-preview svg .nodeLabel text {
105
- fill: var(--mermaid-text-color, var(--text-color)) !important;
106
- }
107
-
108
- body.theme-custom .mermaid-preview svg .nodeLabel span {
109
- color: var(--mermaid-text-color, var(--text-color)) !important;
110
- }
111
-
112
- body.theme-custom .mermaid-preview svg .person rect,
113
- body.theme-custom .mermaid-preview svg .person path {
114
- stroke: var(--mermaid-person-border, var(--text-color));
115
- }
116
-
117
- body.theme-custom .mermaid-preview svg .person-man text {
118
- fill: #ffffff !important;
119
- }
120
-
121
- body.theme-custom .mermaid-preview svg .person-man span {
122
- color: #ffffff !important;
123
- }
124
-
125
- body.theme-custom .mermaid-preview svg .actor rect,
126
- body.theme-custom .mermaid-preview svg .actor path {
127
- stroke: var(--mermaid-node-border, var(--border-color));
128
- }
129
-
130
- body.theme-custom .mermaid-preview svg text.actor {
131
- fill: var(--mermaid-text-color, var(--text-color)) !important;
132
- }
133
-
134
- body.theme-custom .mermaid-preview svg .messageLine0,
135
- body.theme-custom .mermaid-preview svg .messageLine1 {
136
- stroke: var(--mermaid-line-color, var(--border-color)) !important;
137
- }
138
-
139
- body.theme-custom .mermaid-preview svg .messageText {
140
- fill: var(--mermaid-text-color, var(--text-color)) !important;
141
- }
142
-
143
- body.theme-custom .mermaid-preview svg .loopText,
144
- body.theme-custom .mermaid-preview svg .altText,
145
- body.theme-custom .mermaid-preview svg .optText {
146
- fill: var(--mermaid-text-color, var(--text-muted)) !important;
147
- }
148
-
149
- body.theme-custom .mermaid-preview svg .loopLine,
150
- body.theme-custom .mermaid-preview svg .altLine,
151
- body.theme-custom .mermaid-preview svg .optLine {
152
- stroke: var(--mermaid-line-color, var(--border-color)) !important;
153
- }
154
-
155
- body.theme-custom .mermaid-preview svg .labelBox {
156
- stroke: var(--mermaid-node-border, var(--border-color));
157
- }
158
-
159
- body.theme-custom .mermaid-preview svg .labelText {
160
- fill: var(--mermaid-text-color, var(--text-color)) !important;
161
- }
162
-
163
- body.theme-custom .mermaid-preview svg .loopText tspan,
164
- body.theme-custom .mermaid-preview svg .altText tspan,
165
- body.theme-custom .mermaid-preview svg .optText tspan {
166
- fill: var(--mermaid-text-color, var(--text-muted)) !important;
167
- }
168
-
169
- body.theme-custom .mermaid-preview svg .classBox rect,
170
- body.theme-custom .mermaid-preview svg .classBox path {
171
- stroke: var(--mermaid-node-border, var(--border-color));
172
- }
173
-
174
- body.theme-custom .mermaid-preview svg .classTitle text {
175
- fill: var(--mermaid-text-color, var(--text-color)) !important;
176
- }
177
-
178
- body.theme-custom .mermaid-preview svg .classTitle span {
179
- color: var(--mermaid-text-color, var(--text-color)) !important;
180
- }
181
-
182
- body.theme-custom .mermaid-preview svg .classText text {
183
- fill: var(--mermaid-text-color, var(--text-muted)) !important;
184
- }
185
-
186
- body.theme-custom .mermaid-preview svg .classText span {
187
- color: var(--mermaid-text-color, var(--text-muted)) !important;
188
- }
189
-
190
- body.theme-custom .mermaid-preview svg .divider {
191
- stroke: var(--mermaid-node-border, var(--border-color));
192
- }
193
-
194
- body.theme-custom .mermaid-preview svg .relation {
195
- stroke: var(--mermaid-line-color, var(--border-color));
196
- }
197
-
198
- body.theme-custom .mermaid-preview svg .statediagram-state rect,
199
- body.theme-custom .mermaid-preview svg .statediagram-state circle {
200
- stroke: var(--mermaid-node-border, var(--border-color));
201
- }
202
-
203
- body.theme-custom .mermaid-preview svg .statediagram-state .nodeLabel text,
204
- body.theme-custom .mermaid-preview svg .statediagram-state .nodeLabel span {
205
- fill: var(--mermaid-text-color, var(--text-color)) !important;
206
- color: var(--mermaid-text-color, var(--text-color)) !important;
207
- }
208
-
209
- body.theme-custom .mermaid-preview svg .statediagram-cluster rect {
210
- stroke: var(--mermaid-cluster-border, var(--border-color));
211
- }
212
-
213
- body.theme-custom .mermaid-preview svg .transition {
214
- stroke: var(--mermaid-line-color, var(--border-color));
215
- }
216
-
217
- body.theme-custom .mermaid-preview svg .edgeLabel .label text {
218
- fill: var(--mermaid-text-color, var(--text-color)) !important;
219
- }
220
-
221
- body.theme-custom .mermaid-preview svg .statediagram-cluster .outer-title text {
222
- fill: var(--mermaid-text-color, var(--text-color)) !important;
223
- }
224
-
225
- body.theme-custom .mermaid-preview svg .pieTitleText {
226
- fill: var(--mermaid-text-color, var(--text-color)) !important;
227
- }
228
-
229
- body.theme-custom .mermaid-preview svg .pieCircle {
230
- stroke: var(--mermaid-node-border, var(--border-color));
231
- }
232
-
233
- body.theme-custom .mermaid-preview svg .slice {
234
- stroke: var(--mermaid-node-border, var(--border-color));
235
- }
236
-
237
- body.theme-custom .mermaid-preview svg .legend text {
238
- fill: var(--mermaid-text-color, var(--text-color)) !important;
239
- }
240
-
241
- body.theme-custom .mermaid-preview svg .task {
242
- stroke: var(--mermaid-node-border, var(--border-color));
243
- }
244
-
245
- body.theme-custom .mermaid-preview svg .taskText,
246
- body.theme-custom .mermaid-preview svg .taskTextOutsideRight,
247
- body.theme-custom .mermaid-preview svg .taskTextOutsideLeft {
248
- fill: var(--mermaid-text-color, var(--text-color)) !important;
249
- }
250
-
251
- body.theme-custom .mermaid-preview svg .section rect {
252
- stroke: var(--mermaid-node-border, var(--border-color));
253
- }
254
-
255
- body.theme-custom .mermaid-preview svg .sectionText,
256
- body.theme-custom .mermaid-preview svg .sectionTitle {
257
- fill: var(--mermaid-text-color, var(--text-color)) !important;
258
- }
259
-
260
- body.theme-custom .mermaid-preview svg .today {
261
- stroke: var(--mermaid-line-color, var(--border-color)) !important;
262
- }
263
-
264
- body.theme-custom .mermaid-preview svg .grid .tick line {
265
- stroke: var(--mermaid-line-color, var(--border-color));
266
- }
267
-
268
- body.theme-custom .mermaid-preview svg .grid .domain {
269
- stroke: var(--mermaid-line-color, var(--border-color));
270
- }
271
-
272
- body.theme-custom .mermaid-preview svg .tick text {
273
- fill: var(--mermaid-text-color, var(--text-muted));
274
- }
275
-
276
- body.theme-custom .mermaid-preview svg .mindmap-node rect,
277
- body.theme-custom .mermaid-preview svg .mindmap-node circle,
278
- body.theme-custom .mermaid-preview svg .mindmap-node ellipse,
279
- body.theme-custom .mermaid-preview svg .mindmap-node polygon,
280
- body.theme-custom .mermaid-preview svg .mindmap-node path {
281
- stroke: var(--mermaid-node-border, var(--border-color));
282
- }
283
-
284
- body.theme-custom .mermaid-preview svg .mindmap-node text {
285
- fill: var(--mermaid-text-color, var(--text-color)) !important;
286
- }
287
-
288
- body.theme-custom .mermaid-preview svg .mindmap-node .nodeLabel text,
289
- body.theme-custom .mermaid-preview svg .mindmap-node .nodeLabel span {
290
- fill: var(--mermaid-text-color, var(--text-color)) !important;
291
- color: var(--mermaid-text-color, var(--text-color)) !important;
292
- }
293
-
294
- body.theme-custom .mermaid-preview svg .mindmap-edge {
295
- stroke: var(--mermaid-line-color, var(--border-color));
296
- }
297
-
298
- body.theme-custom .mermaid-preview svg .quadrant rect {
299
- stroke: var(--mermaid-node-border, var(--border-color));
300
- }
301
-
302
- body.theme-custom .mermaid-preview svg .quadrant text {
303
- fill: var(--mermaid-text-color, var(--text-color)) !important;
304
- }
305
-
306
- body.theme-custom .mermaid-preview svg .quadrant .titleText {
307
- fill: var(--mermaid-text-color, var(--text-color)) !important;
308
- }
309
-
310
- body.theme-custom .mermaid-preview svg .quadrant .axis text {
311
- fill: var(--mermaid-text-color, var(--text-muted)) !important;
312
- }
313
-
314
- body.theme-custom .mermaid-preview svg .quadrant .axis line,
315
- body.theme-custom .mermaid-preview svg .quadrant .axis path {
316
- stroke: var(--mermaid-line-color, var(--border-color));
317
- }
318
-
319
- body.theme-custom .mermaid-preview svg .quadrant .point {
320
- fill: var(--mermaid-primary-color, var(--link-color));
321
- stroke: var(--mermaid-node-border, var(--border-color));
322
- }
323
-
324
- body.theme-custom .mermaid-preview svg .xychart .axis text {
325
- fill: var(--mermaid-text-color, var(--text-muted)) !important;
326
- }
327
-
328
- body.theme-custom .mermaid-preview svg .xychart .axis line,
329
- body.theme-custom .mermaid-preview svg .xychart .axis path {
330
- stroke: var(--mermaid-line-color, var(--border-color));
331
- }
332
-
333
- body.theme-custom .mermaid-preview svg .xychart .plot rect {
334
- stroke: var(--mermaid-node-border, var(--border-color));
335
- }
336
-
337
- body.theme-custom .mermaid-preview svg .xychart .plot line {
338
- stroke: var(--mermaid-line-color, var(--border-color));
339
- }
340
-
341
- body.theme-custom .mermaid-preview svg .xychart .titleText {
342
- fill: var(--mermaid-text-color, var(--text-color)) !important;
343
- }
344
-
345
- body.theme-custom .mermaid-preview svg .sankey .link {
346
- stroke: var(--mermaid-line-color, var(--border-color));
347
- }
348
-
349
- body.theme-custom .mermaid-preview svg .sankey text {
350
- fill: var(--mermaid-text-color, var(--text-color)) !important;
351
- }
352
-
353
- body.theme-custom .mermaid-preview svg .block rect,
354
- body.theme-custom .mermaid-preview svg .block path {
355
- stroke: var(--mermaid-node-border, var(--border-color));
356
- }
357
-
358
- body.theme-custom .mermaid-preview svg .block text {
359
- fill: var(--mermaid-text-color, var(--text-color)) !important;
360
- }
361
-
362
- body.theme-custom .mermaid-preview svg .block .nodeLabel text,
363
- body.theme-custom .mermaid-preview svg .block .nodeLabel span {
364
- fill: var(--mermaid-text-color, var(--text-color)) !important;
365
- color: var(--mermaid-text-color, var(--text-color)) !important;
366
- }
367
-
368
- body.theme-custom .mermaid-preview svg .er .entityBox rect,
369
- body.theme-custom .mermaid-preview svg .er .entityBox path {
370
- stroke: var(--mermaid-node-border, var(--border-color));
371
- }
372
-
373
- body.theme-custom .mermaid-preview svg .er text {
374
- fill: var(--mermaid-text-color, var(--text-color)) !important;
375
- }
376
-
377
- body.theme-custom .mermaid-preview svg .er .relationshipLabel {
378
- fill: var(--mermaid-text-color, var(--text-color)) !important;
379
- }
380
-
381
- body.theme-custom .mermaid-preview svg .er .relationshipLine {
382
- stroke: var(--mermaid-line-color, var(--border-color));
383
- }
384
-
385
- body.theme-custom .mermaid-preview svg .git .commit rect,
386
- body.theme-custom .mermaid-preview svg .git .commit circle {
387
- stroke: var(--mermaid-node-border, var(--border-color));
388
- }
389
-
390
- body.theme-custom .mermaid-preview svg .git text {
391
- fill: var(--mermaid-text-color, var(--text-color)) !important;
392
- }
393
-
394
- body.theme-custom .mermaid-preview svg .git .branchLabel text {
395
- fill: var(--mermaid-text-color, var(--text-color)) !important;
396
- }
397
-
398
- body.theme-custom .mermaid-preview svg .journey .task rect {
399
- stroke: var(--mermaid-node-border, var(--border-color));
400
- }
401
-
402
- body.theme-custom .mermaid-preview svg .journey text {
403
- fill: var(--mermaid-text-color, var(--text-color)) !important;
404
- }
405
-
406
- body.theme-custom .mermaid-preview svg .timeline rect {
407
- stroke: var(--mermaid-node-border, var(--border-color));
408
- }
409
-
410
- body.theme-custom .mermaid-preview svg .timeline text {
411
- fill: var(--mermaid-text-color, var(--text-color)) !important;
412
- }
413
-
414
- body.theme-custom .mermaid-preview svg .c4 .person rect,
415
- body.theme-custom .mermaid-preview svg .c4 .person path,
416
- body.theme-custom .mermaid-preview svg .c4 .system rect,
417
- body.theme-custom .mermaid-preview svg .c4 .system path,
418
- body.theme-custom .mermaid-preview svg .c4 .container rect,
419
- body.theme-custom .mermaid-preview svg .c4 .container path,
420
- body.theme-custom .mermaid-preview svg .c4 .boundary rect,
421
- body.theme-custom .mermaid-preview svg .c4 .boundary path {
422
- stroke: var(--mermaid-node-border, var(--border-color));
423
- }
424
-
425
- body.theme-custom .mermaid-preview svg .c4 text {
426
- fill: var(--mermaid-text-color, var(--text-color)) !important;
427
- }
428
-
429
- body.theme-custom .mermaid-preview svg .c4 span {
430
- color: var(--mermaid-text-color, var(--text-color)) !important;
431
- }
46
+ }