collabmd 0.1.48 → 0.1.51

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 (482) hide show
  1. package/README.md +15 -608
  2. package/bin/collabmd.js +39 -20
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-Crf9Y3Q6.js +1 -0
  4. package/dist/client/assets/abnfDiagram-VCTEODGH-PuinKbSQ.js +1 -0
  5. package/dist/client/assets/ar-SA-5WIASEJP-Di7OimCN.js +10 -0
  6. package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-46hPkrZv.js} +3 -3
  7. package/dist/client/assets/az-AZ-V5EUQD6C-C19OGTT_.js +1 -0
  8. package/dist/client/assets/bg-BG-EXASCMTR-BIt0xWyb.js +5 -0
  9. package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-C1S5Bzf8.js} +4 -4
  10. package/dist/client/assets/bn-BD-U4SYNFCO-CdNaPy4Q.js +3 -0
  11. package/dist/client/assets/bn-IN-HKDJIITE-CdNaPy4Q.js +3 -0
  12. package/dist/client/assets/{browser-BKLM0ThC-IxjwuOIz-BBqQnUEb.js → browser-BKLM0ThC-IxjwuOIz-DyJcVMFR.js} +1 -1
  13. package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
  14. package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-VAk1HPmz.js} +1 -1
  15. package/dist/client/assets/ca-ES-2KGUU5XB-C9t-c0cH.js +8 -0
  16. package/dist/client/assets/channel-jwdhnPiV.js +1 -0
  17. package/dist/client/assets/chunk-2E4U76K2-Ba8Wf22k.js +1 -0
  18. package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-Ht-73lsT.js} +20 -20
  19. package/dist/client/assets/chunk-5XKZK2GL-D4UAZSOJ.js +1 -0
  20. package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-B2cZexqK.js} +1 -1
  21. package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-Cmtx89ht.js} +1 -1
  22. package/dist/client/assets/chunk-DU6HZSFF-C6d6PJfE.js +127 -0
  23. package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-Dg3H6KLL.js} +1 -1
  24. package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-DUfjx_d5.js} +1 -1
  25. package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D1l7oRGR.js} +1 -1
  26. package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-3F6NhHUP.js} +2 -2
  27. package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-BmCVn4y-.js} +1 -1
  28. package/dist/client/assets/chunk-OSK3NFVY-CWHXAmfx.js +10 -0
  29. package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Du8EtwOa.js} +1 -1
  30. package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-B5yJIrZE.js} +1 -1
  31. package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-B3gML4ps.js} +1 -1
  32. package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BKaI8jZO.js} +5 -5
  33. package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-XlsB_ZMZ.js} +1 -1
  34. package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-Cpp2z8yK.js} +4 -4
  35. package/dist/client/assets/chunk-TLUHSLCS-Yl7B0Vrz.js +1 -0
  36. package/dist/client/assets/chunk-ZNVOA63L-BmCQjhx-.js +40 -0
  37. package/dist/client/assets/{chunk-FLYJHZSQ-Be7lKF17.js → chunk-ZPMXAHWN-Dt0TxJa6.js} +2 -2
  38. package/dist/client/assets/classDiagram-ZZMXUADV-BRw9vo8U.js +1 -0
  39. package/dist/client/assets/classDiagram-v2-VYDZK3BY-BRw9vo8U.js +1 -0
  40. package/dist/client/assets/comment-markdown-renderer-B9_vPc3F.js +1 -0
  41. package/dist/client/assets/comment-thread-store-NNHqRVsX.js +1 -0
  42. package/dist/client/assets/comment-threads-nJhK1yfc.js +4 -0
  43. package/dist/client/assets/cs-CZ-VUCGPRML-BfCoYAgj.js +7 -0
  44. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-BRoCEoZM.js} +1 -1
  45. package/dist/client/assets/da-DK-NNDP2IVP-DBw9ZNTR.js +2 -0
  46. package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-BSfKCfy7.js} +2 -2
  47. package/dist/client/assets/de-CH-I7RAVIZN-DYW18Vsr.js +11 -0
  48. package/dist/client/assets/de-DE-WBQ3DQLR-DYW18Vsr.js +11 -0
  49. package/dist/client/assets/deferred-collab-rBe4nuQ2.css +1 -0
  50. package/dist/client/assets/deferred-git-BHKtkFYi.css +1 -0
  51. package/dist/client/assets/deferred-preview-pe7Iwwx3.css +1 -0
  52. package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-D7KaM9yj.js} +2 -2
  53. package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-JevUZuYi.js} +1 -1
  54. package/dist/client/assets/diagram-VSXAHHWV-B3-U-Q2E.js +3 -0
  55. package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-pSD4HMh1.js} +1 -1
  56. package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D8r1_CIb.js} +1 -1
  57. package/dist/client/assets/{direct-engine-DdrQKpgq-CtKfQzCt.js → direct-engine-DdrQKpgq-B5zIoeQw.js} +1 -1
  58. package/dist/client/assets/dist-B3HdUPsK.js +1 -0
  59. package/dist/client/assets/{dist-Tw-Fxpeb.js → dist-B7XMN9AT.js} +1 -1
  60. package/dist/client/assets/dist-BIRygGYH.js +1 -0
  61. package/dist/client/assets/dist-BPyOlNLY.js +2 -0
  62. package/dist/client/assets/{dist-D5wCC32z.js → dist-BR81yxMt.js} +1 -1
  63. package/dist/client/assets/{dist-Bw3VIE_v.js → dist-B_B4XLmq.js} +1 -1
  64. package/dist/client/assets/dist-Bdy9ZRzd.js +9 -0
  65. package/dist/client/assets/{dist-netZOQtD.js → dist-Bfxzlnrf.js} +1 -1
  66. package/dist/client/assets/{dist-CietwTVS.js → dist-Bx3QkS-3.js} +1 -1
  67. package/dist/client/assets/{dist-mj2Ht75J.js → dist-By7ieqAf.js} +1 -1
  68. package/dist/client/assets/dist-ByhQbe-x.js +1 -0
  69. package/dist/client/assets/{dist-CdmKGRGr.js → dist-BzFSJM0U.js} +1 -1
  70. package/dist/client/assets/dist-C5NkYKAa.js +1 -0
  71. package/dist/client/assets/{dist-D3fehAZ2.js → dist-CELhfKzh.js} +1 -1
  72. package/dist/client/assets/dist-CEirJSxk.js +1 -0
  73. package/dist/client/assets/dist-CO0-4CuV.js +39 -0
  74. package/dist/client/assets/dist-CRnJ0D9h.js +1 -0
  75. package/dist/client/assets/{dist-DDUn5zTz.js → dist-CbDyXgCo.js} +1 -1
  76. package/dist/client/assets/{dist-BeajGMhO.js → dist-CqXVyYoH.js} +1 -1
  77. package/dist/client/assets/{dist-LQ4kDCKz.js → dist-CrWzIWEE.js} +1 -1
  78. package/dist/client/assets/dist-CyNrloSI.js +1 -0
  79. package/dist/client/assets/dist-D60_kdpQ.js +1 -0
  80. package/dist/client/assets/{dist-DuH3ZrHo.js → dist-DCpIH3-_.js} +1 -1
  81. package/dist/client/assets/{dist-BPHLJ09L.js → dist-DJAMplZI.js} +2 -2
  82. package/dist/client/assets/{dist-DGEbEfw4.js → dist-DVXzbeDx.js} +1 -1
  83. package/dist/client/assets/{dist-C5NgpdG5.js → dist-Drv_wZYC.js} +1 -1
  84. package/dist/client/assets/{dist-DVy5woUy.js → dist-EWJYvBK1.js} +1 -1
  85. package/dist/client/assets/dist-Hdhj3L3t.js +1 -0
  86. package/dist/client/assets/{dist-B_yQaEv_.js → dist-gRRhmB-2.js} +3 -3
  87. package/dist/client/assets/dist-kWb2d1CH.js +1 -0
  88. package/dist/client/assets/dist-kiD2GIsD.js +13 -0
  89. package/dist/client/assets/dist-l-56SowH.js +19 -0
  90. package/dist/client/assets/{dist-BK9QvQrc.js → dist-nxQErAaK.js} +2 -2
  91. package/dist/client/assets/dist-sLzRQQk7.js +1 -0
  92. package/dist/client/assets/{document-formatter-Dxl_a8XO.js → document-formatter-Qdiq9uJs.js} +1 -2
  93. package/dist/client/assets/drawioEditor-CHf1vtdQ.js +9 -0
  94. package/dist/client/assets/ebnfDiagram-PWID7BFC-UJ0Fz5ci.js +1 -0
  95. package/dist/client/assets/editor-session-4Bn81iWm.js +14 -0
  96. package/dist/client/assets/el-GR-TYQHVGXW-Dx82YYAS.js +7 -0
  97. package/dist/client/assets/embedded-editor-base-jK221GC8.css +1 -0
  98. package/dist/client/assets/{embedpdf-DA4bA119-BPqZxwjc.js → embedpdf-DA4bA119-E8wZ11J2.js} +2 -3
  99. package/dist/client/assets/{embedpdf-BmE13ZZ0.js → embedpdf-LUXDBD3-.js} +1 -1
  100. package/dist/client/assets/{en-SJ2YIMFF-CJBL3nkq.js → en-2RFA324Y-BsuNJTcL.js} +1 -1
  101. package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CWrH1UJ9.js} +2 -2
  102. package/dist/client/assets/es-ES-JEUOREKJ-Rx0NUQDl.js +12 -0
  103. package/dist/client/assets/eu-ES-SO5DEEAN-CDYm-BcK.js +8 -0
  104. package/dist/client/assets/excalidraw-element-link-iA6zo0_f.js +7 -0
  105. package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
  106. package/dist/client/assets/{excalidraw-editor-BbSbI80a.css → excalidrawEditor-DDE0n1Pk.css} +1 -1
  107. package/dist/client/assets/excalidrawEditor-WIuguTz7.js +9 -0
  108. package/dist/client/assets/export-page-AN-wI5p4.js +56 -0
  109. package/dist/client/assets/exportDocument-B7IagJhQ.css +1 -0
  110. package/dist/client/assets/exportDocument-B9xNKpQe.js +2 -0
  111. package/dist/client/assets/fa-IR-FIYUE2GQ-C865Nx3X.js +9 -0
  112. package/dist/client/assets/fi-FI-REAEF6HQ-BIpjJqIb.js +6 -0
  113. package/dist/client/assets/flowDiagram-HODETNUW-kb1lUSBo.js +1 -0
  114. package/dist/client/assets/fr-FR-SUCL7J6B-DGAKE8jH.js +12 -0
  115. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BBNzDfaV.js} +1 -1
  116. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Csf0Dm_1.js} +1 -1
  117. package/dist/client/assets/gl-ES-KHCSOGVH-DWKh0CMu.js +6 -0
  118. package/dist/client/assets/he-IL-JYXVXV2Q-zqbcM-4g.js +9 -0
  119. package/dist/client/assets/hi-IN-BU52H3BO-CY8v6eG9.js +3 -0
  120. package/dist/client/assets/highlight-theme-CzNkO-IJ.js +1 -0
  121. package/dist/client/assets/hu-HU-OWADXDQ3-CEl6Udfh.js +3 -0
  122. package/dist/client/assets/id-ID-EOMR5R3I-CGQwUjoL.js +8 -0
  123. package/dist/client/assets/image-2QKV3NAF-BUbX0y5Y.js +1 -0
  124. package/dist/client/assets/index-BAmZnTFV.css +1 -0
  125. package/dist/client/assets/index-mWiw418b.js +1111 -0
  126. package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-Bzy6kCbb.js} +1 -1
  127. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-CRy9vIS5.js} +1 -1
  128. package/dist/client/assets/it-IT-FC2VTM3L-KTijNcUe.js +12 -0
  129. package/dist/client/assets/ja-JP-JBNTKYP4-BflWlGhw.js +12 -0
  130. package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-D4ZR_s9J.js} +2 -2
  131. package/dist/client/assets/kaa-TC3VIB7V-B-xtZfy0.js +1 -0
  132. package/dist/client/assets/kab-KAB-UOUDSQKM-BmO0O4Y4.js +4 -0
  133. package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-CIDTmu5g.js} +4 -4
  134. package/dist/client/assets/kk-KZ-P5H2X7YS-CSQFB8IN.js +1 -0
  135. package/dist/client/assets/{km-KH-PCWDKPHP-DSmy5shj.js → km-KH-IHMV2US7-BxrjuEzr.js} +4 -4
  136. package/dist/client/assets/ko-KR-ZTMANIDF-BnNRXd5J.js +5 -0
  137. package/dist/client/assets/ku-TR-GPJTRB5G-BZM7f2aT.js +6 -0
  138. package/dist/client/assets/{line-BfTWJmgf.js → line-DSWLHgpx.js} +1 -1
  139. package/dist/client/assets/lobby-presence-Rdjnc0_0.js +1 -0
  140. package/dist/client/assets/lt-LT-V3XDOK3P-MVQBOHmF.js +3 -0
  141. package/dist/client/assets/lv-LV-DVQ3FADO-CrenwAhS.js +4 -0
  142. package/dist/client/assets/markdown-it-CocJWnjv.js +13 -0
  143. package/dist/client/assets/mermaid-parser.core-DrdLA3p0.js +3 -0
  144. package/dist/client/assets/mermaid.core-C_FK-7n4.js +1 -0
  145. package/dist/client/assets/mermaid.core-D0cMM4Rl.js +10 -0
  146. package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-DO8NB9VH.js} +8 -8
  147. package/dist/client/assets/mr-IN-VZ6HH5FE-B-PHPglH.js +9 -0
  148. package/dist/client/assets/my-MM-XYKWHRK6-Be5sYp5q.js +1 -0
  149. package/dist/client/assets/nb-NO-UNO2GGZJ-BvSKGdja.js +8 -0
  150. package/dist/client/assets/nl-NL-76EFHT4P-C2yNx1Cj.js +13 -0
  151. package/dist/client/assets/nn-NO-CFKD7ABE-4NsqlDRP.js +4 -0
  152. package/dist/client/assets/oc-FR-YBJTCJ3J-B4OTQsWW.js +4 -0
  153. package/dist/client/assets/pa-IN-SNOXSMRV-CKj_sOG7.js +4 -0
  154. package/dist/client/assets/pegDiagram-XKGWAZYB-DS6Ab21R.js +1 -0
  155. package/dist/client/assets/percentages-Q7USCRWZ-DWE6uvTs.js +1 -0
  156. package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-BbFe6Tgs.js} +1 -1
  157. package/dist/client/assets/pl-PL-BSY6YFZ3-CFuzA6L0.js +12 -0
  158. package/dist/client/assets/preload-helper-CtT0-S4g.js +1 -0
  159. package/dist/client/assets/preview-render-compiler-C_7J7eia.js +43 -0
  160. package/dist/client/assets/preview-render-compiler-DzJ1KR_M.js +1 -0
  161. package/dist/client/assets/preview-render-worker-1DoIDllV.js +59 -0
  162. package/dist/client/assets/prod-D5TxmmoB.js +1 -0
  163. package/dist/client/assets/prod-pbFU4TaM.js +145 -0
  164. package/dist/client/assets/pt-BR-CZDV62R3-CkPMtyNx.js +10 -0
  165. package/dist/client/assets/pt-PT-JO57XJJW-CBSnfGtF.js +12 -0
  166. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-fJE7iAxt.js} +1 -1
  167. package/dist/client/assets/quick-switcher-De4PjZFC.css +1 -0
  168. package/dist/client/assets/quick-switcher-controller-CUajuy78.js +1 -0
  169. package/dist/client/assets/railroadDiagram-O6MQD6OU-CUQKqbCK.js +1 -0
  170. package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-Balm0WW8.js} +2 -2
  171. package/dist/client/assets/ro-RO-UZ5ICYYN-BOuntc_r.js +12 -0
  172. package/dist/client/assets/room-DX7lIfnu.js +1 -0
  173. package/dist/client/assets/ru-RU-AN7JPREC-D-ow3SNR.js +10 -0
  174. package/dist/client/assets/runtime-config-BFVdhnJu.js +1 -0
  175. package/dist/client/assets/runtime-paths-Cn0snt_9.js +1 -0
  176. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-CcbMqrlQ.js} +1 -1
  177. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BL1j3Sn-.js} +6 -6
  178. package/dist/client/assets/si-LK-7CBLD6QQ-c91EepX0.js +1 -0
  179. package/dist/client/assets/sk-SK-SWR6DKBI-D5vFMIL6.js +7 -0
  180. package/dist/client/assets/sl-SI-JRML4FIH-D53L_0S2.js +6 -0
  181. package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-DNi924hh.js} +1 -1
  182. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-C62JEwak.js +1 -0
  183. package/dist/client/assets/sv-SE-4ZPKFFXF-DT-G7RCI.js +12 -0
  184. package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-ColgjSH4.js} +1 -1
  185. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-B9UZhEj4.js +8 -0
  186. package/dist/client/assets/ta-IN-V6NHHU6Z-D5jy7_AE.js +6 -0
  187. package/dist/client/assets/th-TH-P7CTMGDK-6sy0NO7K.js +1 -0
  188. package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-7pch5JAr.js} +1 -1
  189. package/dist/client/assets/tr-TR-GUFYG22B-ClVaf8h1.js +4 -0
  190. package/dist/client/assets/uk-UA-K6SV5NFQ-BLTTtyNB.js +6 -0
  191. package/dist/client/assets/uz-UZ-TVKTZO2G-Bm02Eg3D.js +1 -0
  192. package/dist/client/assets/vault-api-client-QjZ_T03l.js +7 -0
  193. package/dist/client/assets/vault-utils-Bct69Xw2.js +1 -0
  194. package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-C5taziCX.js} +1 -1
  195. package/dist/client/assets/vi-VN-7FKFXJNO-CL3WPhmG.js +7 -0
  196. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-BbSlUwuM.js} +1 -1
  197. package/dist/client/assets/wiki-link-resolver-C2P_WmTV.js +1 -0
  198. package/dist/client/assets/{worker-engine-m0rlHn8R-S8mpn_O0.js → worker-engine-m0rlHn8R-eSDcDGEI.js} +1 -1
  199. package/dist/client/assets/workspace-change-CVA9dVmy.js +1 -0
  200. package/dist/client/assets/workspace-sync-client-D4nblH_2.js +1 -0
  201. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-D06X1arY.js} +1 -1
  202. package/dist/client/assets/yjs-B41tM6Sz.js +4 -0
  203. package/dist/client/assets/yjs-provider-reset-guard-R43MnLNc.js +1 -0
  204. package/dist/client/assets/zh-CN-AOKVLNNK-DGidDH2b.js +11 -0
  205. package/dist/client/assets/zh-HK-CDKPF5DC-CRcNR3rk.js +1 -0
  206. package/dist/client/assets/zh-TW-ZVGYESGW-C7Qji1y6.js +13 -0
  207. package/dist/client/drawio-editor.html +12 -5
  208. package/dist/client/excalidraw-editor.html +46 -5
  209. package/dist/client/export-document.html +6 -8
  210. package/dist/client/index.html +79 -43
  211. package/package.json +39 -36
  212. package/src/client/app/drawio-editor.html +3 -3
  213. package/src/client/app/excalidraw-editor.html +3 -3
  214. package/src/client/app/export-document.html +2 -2
  215. package/src/client/app/index.html +77 -37
  216. package/src/client/app/main-entry.js +13 -17
  217. package/src/client/application/app-shell/chat-feature.js +7 -22
  218. package/src/client/application/app-shell/comments-feature.js +6 -0
  219. package/src/client/application/app-shell/git-feature.js +23 -5
  220. package/src/client/application/app-shell/presence-feature.js +8 -25
  221. package/src/client/application/app-shell/ui-feature-shell.js +172 -149
  222. package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
  223. package/src/client/application/app-shell/ui-feature-tab-activity.js +27 -9
  224. package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
  225. package/src/client/application/app-shell-elements.js +9 -0
  226. package/src/client/application/highlight-theme.js +16 -0
  227. package/src/client/application/preview-render-compiler.js +44 -107
  228. package/src/client/application/preview-render-executor.js +0 -26
  229. package/src/client/application/preview-render-scheduler.js +8 -24
  230. package/src/client/application/preview-renderer.js +26 -9
  231. package/src/client/application/webmcp-diagram-renderer.js +47 -0
  232. package/src/client/application/workspace-coordinator.js +23 -22
  233. package/src/client/application/workspace-route-controller.js +7 -0
  234. package/src/client/bootstrap/collabmd-app-shell.js +148 -35
  235. package/src/client/bootstrap/lazy-collab-clients.js +90 -0
  236. package/src/client/domain/excalidraw-element-link.js +73 -0
  237. package/src/client/domain/excalidraw-scene-reconcile.js +5 -2
  238. package/src/client/domain/excalidraw-scene.js +21 -0
  239. package/src/client/domain/hash-routes.js +13 -0
  240. package/src/client/domain/highlight-runtime.js +47 -0
  241. package/src/client/domain/lobby-chat.js +2 -0
  242. package/src/client/domain/room.js +1 -5
  243. package/src/client/domain/runtime-paths.js +61 -7
  244. package/src/client/domain/vault-utils.js +11 -0
  245. package/src/client/excalidraw-editor.js +155 -14
  246. package/src/client/export/export-host.js +3 -1
  247. package/src/client/export/export-pipeline.js +4 -17
  248. package/src/client/infrastructure/agent-connection-api-client.js +23 -0
  249. package/src/client/infrastructure/auth-client.js +4 -15
  250. package/src/client/infrastructure/browser-preferences-port.js +16 -0
  251. package/src/client/infrastructure/editor-session.js +11 -0
  252. package/src/client/infrastructure/editor-view-adapter.js +56 -8
  253. package/src/client/infrastructure/excalidraw-room-client.js +89 -2
  254. package/src/client/infrastructure/git-api-client.js +39 -33
  255. package/src/client/infrastructure/hosted-api-client.js +60 -0
  256. package/src/client/infrastructure/lobby-presence.js +4 -7
  257. package/src/client/infrastructure/runtime-config.js +14 -2
  258. package/src/client/infrastructure/tab-activity-lock.js +2 -5
  259. package/src/client/infrastructure/vault-api-client.js +33 -26
  260. package/src/client/infrastructure/webmcp-tool-registry.js +297 -0
  261. package/src/client/infrastructure/workspace-sync-client.js +6 -4
  262. package/src/client/presentation/agent-connection-controller.js +255 -0
  263. package/src/client/presentation/backlinks-panel.js +3 -0
  264. package/src/client/presentation/bases-preview-controller.js +27 -18
  265. package/src/client/presentation/comment-markdown-renderer.js +2 -14
  266. package/src/client/presentation/comment-overview-controller.js +1 -2
  267. package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
  268. package/src/client/presentation/comment-ui/comment-ui-shared.js +5 -2
  269. package/src/client/presentation/create-menu-presenter.js +19 -16
  270. package/src/client/presentation/excalidraw-embed-controller.js +164 -4
  271. package/src/client/presentation/file-explorer-controller.js +3 -0
  272. package/src/client/presentation/file-explorer-view.js +338 -182
  273. package/src/client/presentation/file-history-view-controller.js +13 -11
  274. package/src/client/presentation/git-diff-view-controller.js +35 -43
  275. package/src/client/presentation/git-panel-controller.js +78 -28
  276. package/src/client/presentation/hosted-workspace-gate-controller.js +180 -0
  277. package/src/client/presentation/image-lightbox-controller.js +20 -16
  278. package/src/client/presentation/layout-controller.js +13 -2
  279. package/src/client/presentation/quick-switcher-controller.js +20 -78
  280. package/src/client/presentation/quick-switcher-text-search.js +10 -14
  281. package/src/client/presentation/team-settings-controller.js +228 -0
  282. package/src/client/styles/components/navigation.css +1 -2
  283. package/src/client/styles/deferred-collab.css +5 -0
  284. package/src/client/styles/deferred-git.css +7 -0
  285. package/src/client/styles/deferred-preview.css +6 -0
  286. package/src/client/styles/features/agent-connection.css +202 -0
  287. package/src/client/styles/features/collaboration-chat.css +8 -1
  288. package/src/client/styles/features/collaboration-dialogs.css +16 -1
  289. package/src/client/styles/features/collaboration-presence.css +17 -4
  290. package/src/client/styles/features/diagram-preview.css +0 -15
  291. package/src/client/styles/features/diff-toolbar.css +1 -1
  292. package/src/client/styles/features/media-lightbox.css +12 -3
  293. package/src/client/styles/features/outline.css +4 -2
  294. package/src/client/styles/features/preview-markdown.css +25 -11
  295. package/src/client/styles/features/quick-switcher.css +20 -11
  296. package/src/client/styles/features/team-settings.css +162 -0
  297. package/src/client/styles/foundation/themes.css +2 -0
  298. package/src/client/styles/foundation/tokens.css +2 -2
  299. package/src/client/styles/layout/editor-page.css +25 -24
  300. package/src/client/styles/layout/overlays.css +16 -0
  301. package/src/client/styles/layout/responsive.css +7 -25
  302. package/src/client/styles/layout/shell.css +21 -1
  303. package/src/client/styles/layout/sidebar.css +99 -7
  304. package/src/client/styles/primitives/controls.css +21 -54
  305. package/src/client/styles/style.css +4 -19
  306. package/src/domain/agent-tool-definitions.js +872 -0
  307. package/src/domain/collabmd-content-capabilities.js +149 -0
  308. package/src/domain/collaboration-protocol.js +2 -0
  309. package/src/domain/comment-threads.js +3 -5
  310. package/src/domain/diagram-source.js +50 -0
  311. package/src/domain/editable-content-revision.js +10 -0
  312. package/src/domain/editable-text.js +3 -0
  313. package/src/domain/exact-text-edits.js +69 -0
  314. package/src/domain/excalidraw-agent-scene.js +624 -0
  315. package/src/domain/excalidraw-agent-verification.js +554 -0
  316. package/src/domain/excalidraw-room-codec.js +13 -6
  317. package/src/domain/literal-text-search.js +13 -0
  318. package/src/domain/video-embed.js +76 -0
  319. package/src/server/application/agent-connection-service.js +178 -0
  320. package/src/server/application/agent-content-service.js +841 -0
  321. package/src/server/application/workspace-reconciliation.js +5 -7
  322. package/src/server/config/env.js +147 -6
  323. package/src/server/create-app-server.js +47 -141
  324. package/src/server/domain/bases/base-query-service.js +1 -5
  325. package/src/server/domain/collaboration/collaboration-room.js +121 -25
  326. package/src/server/domain/collaboration/protocol.js +4 -0
  327. package/src/server/domain/hosted-workspace.js +31 -1
  328. package/src/server/domain/markdown-reference-extractor.js +15 -1
  329. package/src/server/domain/ripgrep-search-service.js +68 -21
  330. package/src/server/infrastructure/git/git-service.js +19 -1
  331. package/src/server/infrastructure/git/history-service.js +1 -1
  332. package/src/server/infrastructure/git/local-exclude.js +37 -0
  333. package/src/server/infrastructure/git/parsers.js +19 -17
  334. package/src/server/infrastructure/git/path-utils.js +0 -16
  335. package/src/server/infrastructure/git/status-service.js +1 -1
  336. package/src/server/infrastructure/git/untracked-files.js +12 -21
  337. package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
  338. package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
  339. package/src/server/infrastructure/http/create-hosted-api-handler.js +5 -0
  340. package/src/server/infrastructure/http/create-request-handler.js +123 -26
  341. package/src/server/infrastructure/http/create-static-handler.js +9 -0
  342. package/src/server/infrastructure/http/create-vault-api-query-handler.js +15 -2
  343. package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +200 -0
  344. package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
  345. package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
  346. package/src/server/infrastructure/persistence/sidecar-store.js +12 -5
  347. package/src/server/infrastructure/persistence/vault-file-store.js +11 -5
  348. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +48 -22
  349. package/src/server/shared/agent-tool-image.js +22 -0
  350. package/src/server/shared/agent-tool-rate-limiter.js +27 -0
  351. package/src/server/startup/git-remote-bootstrap.js +58 -79
  352. package/src/server/vault-registry.js +251 -0
  353. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
  354. package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
  355. package/dist/client/assets/ar-SA-PQUY64WN-xjXgbW6d.js +0 -10
  356. package/dist/client/assets/az-AZ-OXJXL76K-4JkO4Pca.js +0 -1
  357. package/dist/client/assets/base-CaIEJUF9.css +0 -1
  358. package/dist/client/assets/bg-BG-W2GKIJDF-DnkH_o81.js +0 -5
  359. package/dist/client/assets/bn-BD-TGL7M4PJ-CG4JkmtP.js +0 -3
  360. package/dist/client/assets/bn-IN-BKETKYEH-CG4JkmtP.js +0 -3
  361. package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
  362. package/dist/client/assets/ca-ES-LD5SCRVV-U6_TVMX9.js +0 -8
  363. package/dist/client/assets/channel-CaoKA_We.js +0 -1
  364. package/dist/client/assets/chunk-7XWMRXBY-CfMzEq80.js +0 -1
  365. package/dist/client/assets/chunk-CKBBP62Z-DG26UiBv.js +0 -2
  366. package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
  367. package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
  368. package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
  369. package/dist/client/assets/chunk-RM4UPSZO-CWRwxNWJ.js +0 -41
  370. package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
  371. package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
  372. package/dist/client/assets/comment-thread-store-CdcwrObc.js +0 -1
  373. package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
  374. package/dist/client/assets/comment-ui-shared-DuoyznXW.js +0 -7
  375. package/dist/client/assets/cs-CZ-OFPU5DBV-BmFAIhqX.js +0 -7
  376. package/dist/client/assets/da-DK-FRDJFYWF-H387Jw8B.js +0 -2
  377. package/dist/client/assets/de-CH-ZG7H3QK3-C_groygo.js +0 -11
  378. package/dist/client/assets/de-DE-SIJYH4IH-C_groygo.js +0 -11
  379. package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
  380. package/dist/client/assets/dist-73RPdcyU.js +0 -1
  381. package/dist/client/assets/dist-BJ1bJs33.js +0 -1
  382. package/dist/client/assets/dist-ByrG2qBA.js +0 -1
  383. package/dist/client/assets/dist-CH-sQu3r.js +0 -1
  384. package/dist/client/assets/dist-CKS_-are.js +0 -1
  385. package/dist/client/assets/dist-D37Hyu3h.js +0 -9
  386. package/dist/client/assets/dist-DZAAWTG-.js +0 -1
  387. package/dist/client/assets/dist-Dir5dDKZ.js +0 -1
  388. package/dist/client/assets/dist-Dl_tpDSr.js +0 -1
  389. package/dist/client/assets/dist-DutPuFmC.js +0 -1
  390. package/dist/client/assets/dist-RKBTaQMb.js +0 -13
  391. package/dist/client/assets/dist-eBx8q6Sy.js +0 -1
  392. package/dist/client/assets/drawio-editor-BVaNNtYp.js +0 -9
  393. package/dist/client/assets/drawioEditor-BkIBlXx0.js +0 -2
  394. package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
  395. package/dist/client/assets/editor-session-DMyVdHLj.js +0 -54
  396. package/dist/client/assets/el-GR-IEE2CGI2-BkT6YT54.js +0 -7
  397. package/dist/client/assets/embedded-editor-base-B3l6Xy65.css +0 -1
  398. package/dist/client/assets/es-ES-TVVPWKV5-CpPKJXTM.js +0 -12
  399. package/dist/client/assets/eu-ES-CGBMFQDT-Bu3N2493.js +0 -8
  400. package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +0 -9
  401. package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
  402. package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
  403. package/dist/client/assets/excalidrawEditor-ChqF_d82.js +0 -2
  404. package/dist/client/assets/export-page-Dyu0XCbu.js +0 -57
  405. package/dist/client/assets/exportDocument-CJBx4Xjx.css +0 -1
  406. package/dist/client/assets/exportDocument-Dgvfa2Sd.js +0 -2
  407. package/dist/client/assets/fa-IR-IE6XAPR4-BEvLCORD.js +0 -9
  408. package/dist/client/assets/fi-FI-P7TKNHRM-DI0q8iSX.js +0 -6
  409. package/dist/client/assets/file-icon-svg-Y_kpF957.js +0 -1
  410. package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
  411. package/dist/client/assets/fr-FR-QI2XZNT7-y8kXd8LA.js +0 -12
  412. package/dist/client/assets/gl-ES-TLYCNOZZ-Br-Fhff-.js +0 -6
  413. package/dist/client/assets/he-IL-ZX43XLGP-qKQq6V9X.js +0 -9
  414. package/dist/client/assets/hi-IN-UTYRMTUF-DOUcwrDO.js +0 -3
  415. package/dist/client/assets/hu-HU-AJOSEBW6-FqTyvHlD.js +0 -3
  416. package/dist/client/assets/id-ID-ETLTVG6C-CQqh3CLS.js +0 -8
  417. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
  418. package/dist/client/assets/index-CSNIMyOP.css +0 -1
  419. package/dist/client/assets/index-DG3N2Ps-.js +0 -2
  420. package/dist/client/assets/it-IT-B4B6TP6L-V-yK3SZz.js +0 -12
  421. package/dist/client/assets/ja-JP-IYKVURR5-BQKBXRpX.js +0 -12
  422. package/dist/client/assets/kaa-SE2BUIKX-CZ5kfwPg.js +0 -1
  423. package/dist/client/assets/kab-KAB-Y3GLKXLR-Do7GWfuN.js +0 -4
  424. package/dist/client/assets/kk-KZ-ABWUFVOH-BpqVciQz.js +0 -1
  425. package/dist/client/assets/ko-KR-7JQDXKGM-N42lep78.js +0 -5
  426. package/dist/client/assets/ku-TR-NAH2Q5B7-K8LLl9fk.js +0 -6
  427. package/dist/client/assets/lt-LT-VQFYRSNQ-BmOd0ALn.js +0 -3
  428. package/dist/client/assets/lv-LV-T62VSYUM-B22WdPhp.js +0 -4
  429. package/dist/client/assets/main-D0wCxpVn.js +0 -903
  430. package/dist/client/assets/mermaid-parser.core-Bl0efOMt.js +0 -4
  431. package/dist/client/assets/mermaid.core-BJRLUQZE.js +0 -11
  432. package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +0 -1
  433. package/dist/client/assets/mr-IN-V4FHLCJE-XX069tpm.js +0 -9
  434. package/dist/client/assets/my-MM-E3SQ6E54-cst_-5SB.js +0 -1
  435. package/dist/client/assets/nb-NO-MLNOFN5H-Bu2URWko.js +0 -8
  436. package/dist/client/assets/nl-NL-D5L3ZV4M-BqrV0btt.js +0 -13
  437. package/dist/client/assets/nn-NO-NNHDGPKB-DK-xZaWM.js +0 -4
  438. package/dist/client/assets/oc-FR-DWCRF55G-BZ5Po5R6.js +0 -4
  439. package/dist/client/assets/pa-IN-3JSAY44M-BZQSjKrS.js +0 -4
  440. package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
  441. package/dist/client/assets/percentages-ETZPVQEE-DFxFqXgH.js +0 -1
  442. package/dist/client/assets/pl-PL-ACURYKP3-qcEOSfCk.js +0 -12
  443. package/dist/client/assets/preload-helper-HclGiUj8.js +0 -1
  444. package/dist/client/assets/preview-render-compiler-CrJIooVD.js +0 -35
  445. package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +0 -1
  446. package/dist/client/assets/preview-render-profile-B4RWYWHt.js +0 -1
  447. package/dist/client/assets/preview-render-worker-_QTxqKvP.js +0 -60
  448. package/dist/client/assets/prod-BiYPMR1i.js +0 -177
  449. package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
  450. package/dist/client/assets/pt-BR-LOX7MLGD-DLueHSyZ.js +0 -10
  451. package/dist/client/assets/pt-PT-CZ2U2RFQ-BJ-GAEm6.js +0 -12
  452. package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +0 -1
  453. package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
  454. package/dist/client/assets/ro-RO-2HECL2X6-CJUvKAf0.js +0 -12
  455. package/dist/client/assets/ru-RU-HAYNXO46-BWSlvTrt.js +0 -10
  456. package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
  457. package/dist/client/assets/si-LK-W5KNS4H6-DGGCsn7k.js +0 -1
  458. package/dist/client/assets/sk-SK-7K2CFGDV-CY4uTYgQ.js +0 -7
  459. package/dist/client/assets/sl-SI-OXV2QZWW-2-weqaBY.js +0 -6
  460. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
  461. package/dist/client/assets/sv-SE-JTOBZRGL-9-IUtVkO.js +0 -12
  462. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
  463. package/dist/client/assets/ta-IN-KFAVKXGT-gHO6Q_DH.js +0 -6
  464. package/dist/client/assets/th-TH-VDMSCPDL-BvJuw6PJ.js +0 -1
  465. package/dist/client/assets/tr-TR-CEZ6GX45-CG6UU3Su.js +0 -4
  466. package/dist/client/assets/uk-UA-Q3H3OXQC-CSuIg_DY.js +0 -6
  467. package/dist/client/assets/uz-UZ-NGCSWWPX-mom7rxSP.js +0 -1
  468. package/dist/client/assets/vault-api-client-BkwdFjx0.js +0 -6
  469. package/dist/client/assets/vault-utils-DvoSftJT.js +0 -22
  470. package/dist/client/assets/vi-VN-P3NDEVPS-BB0Fu9ck.js +0 -7
  471. package/dist/client/assets/yjs-provider-reset-guard-DE0vINDP.js +0 -4
  472. package/dist/client/assets/zh-CN-SS3O57GA-Bj8wsiMe.js +0 -11
  473. package/dist/client/assets/zh-HK-LWJT3VCF-DOTquTCh.js +0 -1
  474. package/dist/client/assets/zh-TW-VJXC72RT-B48PRo-l.js +0 -13
  475. package/src/client/app/drawio-editor-entry.js +0 -1
  476. package/src/client/app/excalidraw-editor-entry.js +0 -1
  477. package/src/client/excalidraw-mermaid-stub.js +0 -7
  478. package/src/client/main.js +0 -16
  479. /package/dist/client/assets/{vault-api-client-C3mlS_4N.css → auth-gate-C3mlS_4N.css} +0 -0
  480. /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
  481. /package/dist/client/assets/{base-BYODPHdS.js → github.min-DBihDoic.js} +0 -0
  482. /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
@@ -58,8 +58,53 @@ function applyBasePath(basePath, pathValue) {
58
58
  return normalizedBasePath ? `${normalizedBasePath}/${normalizedPath}` : `/${normalizedPath}`;
59
59
  }
60
60
 
61
+ export const ACTIVE_VAULT_STORAGE_KEY = 'collabmd.activeVault';
62
+
63
+ // ponytail: agent/hosted/auth/plantuml/structurizr/test stay global; everything else is vault-scoped
64
+ const VAULT_UNSCOPED_API_PATHS = ['/auth/', '/hosted/', '/agent/', '/test/', '/plantuml/', '/structurizr/'];
65
+
66
+ function isVaultScopedApiPath(pathname) {
67
+ if (pathname === '/api' || pathname === '/api/' || pathname === '/api/vaults') {
68
+ return false;
69
+ }
70
+ const sub = pathname.startsWith('/api/') ? pathname.slice('/api'.length) : pathname;
71
+ return !VAULT_UNSCOPED_API_PATHS.some((prefix) => sub === prefix.slice(0, -1) || sub.startsWith(prefix));
72
+ }
73
+
74
+ export function getActiveVaultId(config = getClientRuntimeConfig()) {
75
+ const vaults = Array.isArray(config?.vaults) ? config.vaults.map((vault) => vault?.id).filter(Boolean) : [];
76
+ if (vaults.length === 0) {
77
+ return null;
78
+ }
79
+ try {
80
+ const stored = globalThis.window?.localStorage?.getItem(ACTIVE_VAULT_STORAGE_KEY);
81
+ if (stored && vaults.includes(stored)) {
82
+ return stored;
83
+ }
84
+ } catch {
85
+ // Ignore storage failures and fall back to the server default.
86
+ }
87
+ if (config?.activeVault && vaults.includes(config.activeVault)) {
88
+ return config.activeVault;
89
+ }
90
+ return vaults[0] ?? null;
91
+ }
92
+
93
+ export function setActiveVaultId(vaultId) {
94
+ try {
95
+ globalThis.window?.localStorage?.setItem(ACTIVE_VAULT_STORAGE_KEY, String(vaultId ?? ''));
96
+ } catch {
97
+ // Ignore storage failures; the server default still applies.
98
+ }
99
+ }
61
100
  export function getClientRuntimeConfig() {
62
101
  const rawConfig = {
102
+ activeVault: '',
103
+ agentAccess: {
104
+ enabled: false,
105
+ endpoint: '',
106
+ managed: false,
107
+ },
63
108
  auth: {
64
109
  enabled: false,
65
110
  implemented: true,
@@ -87,6 +132,7 @@ export function getClientRuntimeConfig() {
87
132
  version: '',
88
133
  },
89
134
  structurizrEnabled: false,
135
+ vaults: [],
90
136
  wikiLinkAutoCreate: true,
91
137
  wsBasePath: '/ws',
92
138
  ...(window.__COLLABMD_CONFIG__ ?? {}),
@@ -137,11 +183,17 @@ export function resolveApiUrl(pathValue = '/', config = getClientRuntimeConfig()
137
183
  return resolveAppPath('/api', config);
138
184
  }
139
185
 
140
- if (normalizedPath.startsWith('/api')) {
141
- return resolveAppPath(normalizedPath, config);
186
+ const apiPath = normalizedPath.startsWith('/api')
187
+ ? normalizedPath
188
+ : `/api${normalizedPath.startsWith('/') ? normalizedPath : `/${normalizedPath}`}`;
189
+ const queryIndex = apiPath.indexOf('?');
190
+ const pathname = queryIndex === -1 ? apiPath : apiPath.slice(0, queryIndex);
191
+ const query = queryIndex === -1 ? '' : apiPath.slice(queryIndex);
192
+ const vaultId = getActiveVaultId(config);
193
+ if (vaultId && isVaultScopedApiPath(pathname)) {
194
+ return resolveAppPath(`/api/v/${vaultId}${pathname.slice('/api'.length)}${query}`, config);
142
195
  }
143
-
144
- return resolveAppPath(`/api${normalizedPath.startsWith('/') ? normalizedPath : `/${normalizedPath}`}`, config);
196
+ return resolveAppPath(`${pathname}${query}`, config);
145
197
  }
146
198
 
147
199
  export function resolveWsServerOverride(config = getClientRuntimeConfig()) {
@@ -167,15 +219,17 @@ export function resolveWsServerOverride(config = getClientRuntimeConfig()) {
167
219
  }
168
220
 
169
221
  export function resolveWsBaseUrl(config = getClientRuntimeConfig()) {
222
+ const vaultId = getActiveVaultId(config);
223
+ const vaultSuffix = vaultId ? `/v/${vaultId}` : '';
170
224
  const serverOverride = resolveWsServerOverride(config);
171
225
  if (serverOverride) {
172
- return serverOverride;
226
+ return `${serverOverride}${vaultSuffix}`;
173
227
  }
174
228
 
175
229
  if (config.publicWsBaseUrl) {
176
- return trimTrailingSlash(config.publicWsBaseUrl);
230
+ return `${trimTrailingSlash(config.publicWsBaseUrl)}${vaultSuffix}`;
177
231
  }
178
232
 
179
233
  const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
180
- return `${protocol}//${window.location.host}${resolveAppPath(config.wsBasePath, config)}`;
234
+ return `${protocol}//${window.location.host}${resolveAppPath(`${config.wsBasePath}${vaultSuffix}`, config)}`;
181
235
  }
@@ -18,6 +18,17 @@ export function escapeHtml(text) {
18
18
  .replace(/'/g, ''');
19
19
  }
20
20
 
21
+ /**
22
+ * Builds a document fragment from an HTML string for a single
23
+ * replaceChildren() call. Escape untrusted parts before calling.
24
+ *
25
+ * @param {string} markup — trusted HTML markup
26
+ * @returns {DocumentFragment} parsed fragment
27
+ */
28
+ export function createFragment(markup) {
29
+ return document.createRange().createContextualFragment(markup);
30
+ }
31
+
21
32
  /**
22
33
  * Clamps a numeric value between a minimum and maximum bound.
23
34
  *
@@ -11,6 +11,7 @@ import {
11
11
  import { getElementBounds } from '@excalidraw/element';
12
12
  import '@excalidraw/excalidraw/index.css';
13
13
 
14
+ import { createEditableContentRevision } from '../domain/editable-content-revision.js';
14
15
  import {
15
16
  buildRenderableCollaboratorsMap,
16
17
  findCollaboratorByPeerId,
@@ -45,6 +46,11 @@ import {
45
46
  summarizeExcalidrawScene,
46
47
  } from './domain/excalidraw-diagnostics.js';
47
48
  import { isPlainQuickSwitcherShortcut } from './domain/keyboard-shortcuts.js';
49
+ import {
50
+ createExcalidrawElementLink,
51
+ parseExcalidrawElementLink,
52
+ } from './domain/excalidraw-element-link.js';
53
+ import { resolveAppPath, resolveAppUrl } from './domain/runtime-paths.js';
48
54
  import { ensureClientAuthenticated } from './infrastructure/auth-client.js';
49
55
  import {
50
56
  EXCALIDRAW_ROOM_CONNECTION_STATE,
@@ -58,6 +64,8 @@ const diagnostics = createExcalidrawDiagnosticRing({
58
64
  enabled: params.get('excalidrawDebug') === '1',
59
65
  });
60
66
  const parentOrigin = window.location.origin;
67
+ const appPath = resolveAppPath('/');
68
+ const appUrl = resolveAppUrl('/');
61
69
  const syncTimeoutMs = Number.parseInt(params.get('syncTimeoutMs') || '', 10);
62
70
 
63
71
  let currentDocument = {
@@ -71,9 +79,16 @@ let localAwarenessUser = resolveLocalAwarenessUser({
71
79
  storedUserName: localStorage.getItem('collabmd-user-name'),
72
80
  });
73
81
  let appliedSceneJson = '';
82
+ let appliedSceneRevisionPromise = createEditableContentRevision(appliedSceneJson);
83
+
84
+ function setAppliedSceneJson(value) {
85
+ appliedSceneJson = value;
86
+ appliedSceneRevisionPromise = createEditableContentRevision(value);
87
+ }
74
88
 
75
89
  let collabReady = false;
76
90
  let pendingRemoteSceneJson = '';
91
+ let pendingRemoteSceneAuthoritative = false;
77
92
  let pendingCollaborators = null;
78
93
  let activeCollaborators = new Map();
79
94
  let followedSocketId = null;
@@ -327,17 +342,34 @@ function getDiagramCommentMarkerPosition(thread, api = getMountedExcalidrawAPI()
327
342
  );
328
343
  }
329
344
 
330
- function focusDiagramCommentThread(thread) {
345
+ function getDiagramElementTargets(elementId, elementType = 'element', api = getMountedExcalidrawAPI()) {
346
+ const normalizedElementId = String(elementId ?? '').trim();
347
+ const elements = api?.getSceneElementsIncludingDeleted?.()
348
+ ?.filter((element) => !element.isDeleted) || [];
349
+ if (!normalizedElementId) {
350
+ return [];
351
+ }
352
+
353
+ if (elementType === 'group') {
354
+ const groupElements = elements.filter((element) => element.groupIds?.includes(normalizedElementId));
355
+ if (groupElements.length > 0) {
356
+ return groupElements;
357
+ }
358
+ }
359
+
360
+ return elements.filter((element) => element.id === normalizedElementId);
361
+ }
362
+
363
+ function focusDiagramElement(elementId, elementType = 'element') {
331
364
  const api = getMountedExcalidrawAPI();
332
- const element = api?.getSceneElementsIncludingDeleted?.()
333
- ?.find((candidate) => candidate.id === thread?.elementId && !candidate.isDeleted);
334
- if (!api || !element) {
365
+ const elements = getDiagramElementTargets(elementId, elementType, api);
366
+ if (!api || elements.length === 0) {
335
367
  return;
336
368
  }
337
369
 
338
370
  api.updateScene({
339
371
  appState: {
340
- selectedElementIds: { [element.id]: true },
372
+ selectedElementIds: Object.fromEntries(elements.map((element) => [element.id, true])),
341
373
  },
342
374
  captureUpdate: CaptureUpdateAction.NEVER,
343
375
  });
@@ -352,11 +384,16 @@ function focusDiagramCommentThread(thread) {
352
384
  animation: false,
353
385
  fit: 'contain',
354
386
  offsets: { ui: true },
355
- target: element,
387
+ target: elements,
356
388
  });
357
389
  } finally {
358
390
  releaseViewportBroadcastSuppressionAfterPaint();
359
391
  }
392
+
393
+ }
394
+
395
+ function focusDiagramCommentThread(thread) {
396
+ focusDiagramElement(thread?.elementId);
360
397
  }
361
398
 
362
399
  function applyDocumentMode(mode = currentDocument.mode) {
@@ -396,12 +433,12 @@ function createRoomClient(filePath) {
396
433
 
397
434
  handleRoomConnectionStateChange(event);
398
435
  },
399
- onRemoteSceneJson: (sceneJson) => {
436
+ onRemoteSceneJson: (sceneJson, { authoritative = false } = {}) => {
400
437
  if (generation !== roomClientGeneration) {
401
438
  return;
402
439
  }
403
440
 
404
- applySceneFromJson(sceneJson);
441
+ applySceneFromJson(sceneJson, { authoritative });
405
442
  },
406
443
  syncTimeoutMs: Number.isFinite(syncTimeoutMs) ? syncTimeoutMs : undefined,
407
444
  vaultClient: vaultApiClient,
@@ -413,6 +450,23 @@ function createRoomClient(filePath) {
413
450
  };
414
451
  }
415
452
 
453
+ function handleExcalidrawLinkOpen(element, event) {
454
+ if (window.parent === window) {
455
+ return;
456
+ }
457
+
458
+ const target = parseExcalidrawElementLink(element?.link, {
459
+ appPath,
460
+ origin: parentOrigin,
461
+ });
462
+ if (!target) {
463
+ return;
464
+ }
465
+
466
+ event?.preventDefault?.();
467
+ postToParent('open-element-link', { href: element.link });
468
+ }
469
+
416
470
  function buildExcalidrawProps({ initialData, renderTopRightUI, viewModeEnabled } = {}) {
417
471
  const props = {
418
472
  onMount: handleEditorMount,
@@ -431,11 +485,17 @@ function buildExcalidrawProps({ initialData, renderTopRightUI, viewModeEnabled }
431
485
  collabReady = false;
432
486
  },
433
487
  aiEnabled: false,
488
+ generateLinkForSelection: (elementId, elementType) => createExcalidrawElementLink(
489
+ currentDocument.filePath,
490
+ elementId,
491
+ { appUrl, elementType },
492
+ ),
434
493
  isCollaborating: true,
435
494
  onChange: (elements, appState, files) => {
436
495
  scheduleSyncToRoom(elements, appState, files);
437
496
  roomClient?.syncLocalSelectionAwareness(appState);
438
497
  },
498
+ onLinkOpen: handleExcalidrawLinkOpen,
439
499
  onPointerUpdate: (payload) => {
440
500
  roomClient?.scheduleLocalPointerAwareness(payload);
441
501
  },
@@ -1199,6 +1259,9 @@ if (isTestMode) {
1199
1259
  .map((element) => element.id)
1200
1260
  .sort() ?? []
1201
1261
  ),
1262
+ getSelectedElementIds: () => (
1263
+ Object.keys(getMountedExcalidrawAPI()?.getAppState?.()?.selectedElementIds || {}).sort()
1264
+ ),
1202
1265
  getElementStatus: (elementId) => (
1203
1266
  getMountedExcalidrawAPI()?.getSceneElementsIncludingDeleted?.()
1204
1267
  ?.find((entry) => entry.id === elementId && !entry.isDeleted)?.status ?? null
@@ -1331,14 +1394,18 @@ function flushPendingRemoteScene() {
1331
1394
  }
1332
1395
 
1333
1396
  const sceneJson = pendingRemoteSceneJson;
1397
+ const authoritative = pendingRemoteSceneAuthoritative;
1334
1398
  pendingRemoteSceneJson = '';
1399
+ pendingRemoteSceneAuthoritative = false;
1335
1400
  applySceneFromJson(sceneJson, {
1401
+ authoritative,
1336
1402
  force: true,
1337
1403
  });
1338
1404
  return true;
1339
1405
  }
1340
1406
 
1341
1407
  function applySceneFromJson(rawJson, {
1408
+ authoritative = false,
1342
1409
  force = false,
1343
1410
  } = {}) {
1344
1411
  const scene = parseSceneJson(rawJson);
@@ -1347,20 +1414,23 @@ function applySceneFromJson(rawJson, {
1347
1414
  return;
1348
1415
  }
1349
1416
 
1350
- appliedSceneJson = normalizedJson;
1417
+ setAppliedSceneJson(normalizedJson);
1351
1418
  recordSceneDiagnostic('remote-scene-received', {}, normalizedJson);
1352
1419
 
1353
1420
  if (!getMountedExcalidrawAPI() || !collabReady) {
1354
1421
  pendingRemoteSceneJson = normalizedJson;
1422
+ pendingRemoteSceneAuthoritative ||= authoritative;
1355
1423
  return;
1356
1424
  }
1357
1425
 
1358
1426
  if (!force && isEditingTextElement()) {
1359
1427
  pendingRemoteSceneJson = normalizedJson;
1428
+ pendingRemoteSceneAuthoritative ||= authoritative;
1360
1429
  return;
1361
1430
  }
1362
1431
 
1363
- updateApiScene(scene);
1432
+ pendingRemoteSceneAuthoritative = false;
1433
+ updateApiScene(scene, { authoritative });
1364
1434
  }
1365
1435
 
1366
1436
  function releaseViewportBroadcastSuppressionAfterPaint() {
@@ -1378,6 +1448,7 @@ function releaseViewportBroadcastSuppressionAfterPaint() {
1378
1448
  function buildApiSceneUpdate(scene, {
1379
1449
  appStateOverrides = {},
1380
1450
  api = getMountedExcalidrawAPI(),
1451
+ authoritative = false,
1381
1452
  } = {}) {
1382
1453
  if (!api) {
1383
1454
  return null;
@@ -1388,6 +1459,7 @@ function buildApiSceneUpdate(scene, {
1388
1459
 
1389
1460
  return buildReconciledExcalidrawSceneUpdate({
1390
1461
  appStateOverrides,
1462
+ authoritative,
1391
1463
  currentAppState,
1392
1464
  currentElements,
1393
1465
  documentViewState: getDocumentViewState(),
@@ -1423,7 +1495,7 @@ function requestEditorRemount(scene) {
1423
1495
  const normalizedScene = normalizeScene(scene);
1424
1496
  const normalizedJson = JSON.stringify(normalizedScene);
1425
1497
  pendingRemoteSceneJson = normalizedJson;
1426
- appliedSceneJson = normalizedJson;
1498
+ setAppliedSceneJson(normalizedJson);
1427
1499
  pendingCollaborators = activeCollaborators;
1428
1500
  initialViewportFitPending = true;
1429
1501
  clearPreviewViewportFitTimers();
@@ -1438,6 +1510,7 @@ function requestEditorRemount(scene) {
1438
1510
 
1439
1511
  function applySceneToMountedApi(scene, {
1440
1512
  appStateOverrides = {},
1513
+ authoritative = false,
1441
1514
  captureUpdate = CaptureUpdateAction.NEVER,
1442
1515
  trackedSharedSnapshot = false,
1443
1516
  } = {}) {
@@ -1449,6 +1522,7 @@ function applySceneToMountedApi(scene, {
1449
1522
  const nextSceneUpdate = buildApiSceneUpdate(scene, {
1450
1523
  appStateOverrides,
1451
1524
  api,
1525
+ authoritative,
1452
1526
  });
1453
1527
  let applyResult;
1454
1528
 
@@ -1483,11 +1557,13 @@ function applySceneToMountedApi(scene, {
1483
1557
 
1484
1558
  function updateApiScene(scene, {
1485
1559
  appStateOverrides = {},
1560
+ authoritative = false,
1486
1561
  captureUpdate = CaptureUpdateAction.NEVER,
1487
1562
  trackedSharedSnapshot = true,
1488
1563
  } = {}) {
1489
1564
  applySceneToMountedApi(scene, {
1490
1565
  appStateOverrides,
1566
+ authoritative,
1491
1567
  captureUpdate,
1492
1568
  trackedSharedSnapshot,
1493
1569
  });
@@ -1499,7 +1575,7 @@ function applyLocalScene(scene, {
1499
1575
  const normalizedScene = normalizeScene(scene);
1500
1576
  const normalizedJson = JSON.stringify(normalizedScene);
1501
1577
 
1502
- appliedSceneJson = normalizedJson;
1578
+ setAppliedSceneJson(normalizedJson);
1503
1579
 
1504
1580
  if (!getMountedExcalidrawAPI() || !collabReady) {
1505
1581
  pendingRemoteSceneJson = normalizedJson;
@@ -1845,6 +1921,36 @@ async function waitForPendingRoomWrites({
1845
1921
  }
1846
1922
  }
1847
1923
 
1924
+ function waitForAnimationFrame() {
1925
+ return new Promise((resolve) => requestAnimationFrame(resolve));
1926
+ }
1927
+
1928
+ async function waitForAppliedSceneRevision(revision, {
1929
+ afterRevision = '',
1930
+ maxWaitMs = 4500,
1931
+ } = {}) {
1932
+ const startedAt = performance.now();
1933
+ while ((performance.now() - startedAt) < maxWaitMs) {
1934
+ const appliedRevision = await appliedSceneRevisionPromise;
1935
+ if (
1936
+ !pendingRemoteSceneJson
1937
+ && (appliedRevision === revision || (afterRevision && appliedRevision !== afterRevision))
1938
+ ) {
1939
+ await waitForAnimationFrame();
1940
+ await waitForAnimationFrame();
1941
+ const paintedRevision = await appliedSceneRevisionPromise;
1942
+ if (
1943
+ !pendingRemoteSceneJson
1944
+ && (paintedRevision === revision || (afterRevision && paintedRevision !== afterRevision))
1945
+ ) {
1946
+ return paintedRevision;
1947
+ }
1948
+ }
1949
+ await new Promise((resolve) => window.setTimeout(resolve, 16));
1950
+ }
1951
+ return '';
1952
+ }
1953
+
1848
1954
  async function prepareRealtimeRoomDisconnect() {
1849
1955
  if (!roomClient) {
1850
1956
  return true;
@@ -1942,6 +2048,11 @@ window.addEventListener('message', (event) => {
1942
2048
  return;
1943
2049
  }
1944
2050
 
2051
+ if (message.type === 'focus-element') {
2052
+ focusDiagramElement(message.elementId, message.elementType);
2053
+ return;
2054
+ }
2055
+
1945
2056
  if (message.type === 'follow-user') {
1946
2057
  applyHostFollowRequest(message.peerId || null);
1947
2058
  return;
@@ -1952,6 +2063,34 @@ window.addEventListener('message', (event) => {
1952
2063
  return;
1953
2064
  }
1954
2065
 
2066
+ if (message.type === 'flush-agent-writes') {
2067
+ void (async () => {
2068
+ roomClient?.flushSceneSync();
2069
+ await waitForPendingRoomWrites({ maxWaitMs: 1000 });
2070
+ const serverFlush = await roomClient?.waitForServerFlush?.({ timeoutMs: 1000 });
2071
+ postToParent('agent-writes-flushed', {
2072
+ requestId: message.requestId || '',
2073
+ revision: await appliedSceneRevisionPromise,
2074
+ status: serverFlush?.status || 'unavailable',
2075
+ });
2076
+ })();
2077
+ return;
2078
+ }
2079
+
2080
+ if (message.type === 'wait-for-agent-revision') {
2081
+ void (async () => {
2082
+ const revision = String(message.revision || '');
2083
+ const paintedRevision = revision && await waitForAppliedSceneRevision(revision, {
2084
+ afterRevision: String(message.afterRevision || ''),
2085
+ });
2086
+ postToParent(paintedRevision ? 'agent-revision-painted' : 'agent-revision-not-painted', {
2087
+ requestId: message.requestId || '',
2088
+ revision: paintedRevision || revision,
2089
+ });
2090
+ })();
2091
+ return;
2092
+ }
2093
+
1955
2094
  if (message.type === 'prepare-disconnect') {
1956
2095
  void (async () => {
1957
2096
  const requestId = message.requestId || '';
@@ -2051,10 +2190,12 @@ function initializeEditor(api) {
2051
2190
  }));
2052
2191
 
2053
2192
  const sceneJson = pendingRemoteSceneJson || roomClient?.getLastSceneJson?.() || '';
2193
+ const authoritative = pendingRemoteSceneAuthoritative;
2054
2194
  const initialScene = parseSceneJson(sceneJson);
2055
2195
  pendingRemoteSceneJson = '';
2056
- appliedSceneJson = JSON.stringify(initialScene);
2057
- updateApiScene(initialScene);
2196
+ pendingRemoteSceneAuthoritative = false;
2197
+ setAppliedSceneJson(JSON.stringify(initialScene));
2198
+ updateApiScene(initialScene, { authoritative });
2058
2199
 
2059
2200
  if (pendingCollaborators) {
2060
2201
  const renderableCollaborators = buildRenderableCollaboratorsMap(pendingCollaborators);
@@ -8,7 +8,9 @@ const pendingJobs = new Map();
8
8
  let exportBridgeErrorHandler = null;
9
9
 
10
10
  function createJobId() {
11
- return `export-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
11
+ const id = globalThis.crypto?.randomUUID?.()
12
+ ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
13
+ return `export-${id}`;
12
14
  }
13
15
 
14
16
  function normalizeFormat(format) {
@@ -17,10 +17,11 @@ import { compilePreviewDocument } from '../application/preview-render-compiler.j
17
17
  import { isMarkdownFilePath, stripVaultFileExtension } from '../../domain/file-kind.js';
18
18
  import { resolveVaultRelativePath } from '../../domain/vault-paths.js';
19
19
  import { resolveWikiTargetPath } from '../../domain/wiki-link-resolver.js';
20
- import { parseSceneJson, sceneToInitialData } from '../domain/excalidraw-scene.js';
20
+ import { createExcalidrawExportOptions, parseSceneJson } from '../domain/excalidraw-scene.js';
21
21
  import { escapeHtml } from '../domain/vault-utils.js';
22
22
  import { downloadBlob } from '../browser-utils.js';
23
23
  import { resolveApiUrl, resolveAppUrl } from '../infrastructure/runtime-config.js';
24
+ import { parseApiResponse } from '../infrastructure/api-client-utils.js';
24
25
 
25
26
  const EXPORT_PAGE_SOURCE = 'collabmd-export-page';
26
27
  const EXPORT_HOST_SOURCE = 'collabmd-export-host';
@@ -355,11 +356,7 @@ async function fetchJson(url, init = {}) {
355
356
  },
356
357
  ...init,
357
358
  });
358
- const data = await response.json().catch(() => null);
359
- if (!response.ok) {
360
- throw new Error(data?.error || `Request failed: ${response.status}`);
361
- }
362
- return data;
359
+ return parseApiResponse(response, `Request failed: ${response.status}`);
363
360
  }
364
361
 
365
362
  async function fetchTextFile(filePath) {
@@ -820,17 +817,7 @@ async function renderPlantUmlToSvgMarkup(source) {
820
817
  async function renderExcalidrawToSvgMarkup(filePath) {
821
818
  const rawScene = await fetchTextFile(filePath);
822
819
  const scene = parseSceneJson(rawScene);
823
- const initialData = sceneToInitialData(scene, { theme: 'light' });
824
- const svgElement = await exportExcalidrawToSvg({
825
- appState: {
826
- ...initialData.appState,
827
- exportBackground: true,
828
- exportWithDarkMode: false,
829
- },
830
- elements: initialData.elements.filter((element) => !element.isDeleted),
831
- exportPadding: 24,
832
- files: initialData.files || null,
833
- });
820
+ const svgElement = await exportExcalidrawToSvg(createExcalidrawExportOptions(scene));
834
821
  return normalizeExportSvgMarkup(svgElement.outerHTML, { padding: 24 });
835
822
  }
836
823
 
@@ -0,0 +1,23 @@
1
+ import { resolveApiUrl } from '../domain/runtime-paths.js';
2
+ import { parseApiResponse } from './api-client-utils.js';
3
+
4
+ export const agentConnectionApiClient = {
5
+ listConnections() {
6
+ return fetch(resolveApiUrl('/agent/connections'))
7
+ .then((response) => parseApiResponse(response, 'Failed to load Agent Connections'));
8
+ },
9
+
10
+ createConnection(payload) {
11
+ return fetch(resolveApiUrl('/agent/connections'), {
12
+ body: JSON.stringify(payload),
13
+ headers: { 'Content-Type': 'application/json' },
14
+ method: 'POST',
15
+ }).then((response) => parseApiResponse(response, 'Failed to create Agent Connection'));
16
+ },
17
+
18
+ revokeConnection(connectionId) {
19
+ return fetch(resolveApiUrl(`/agent/connections/${encodeURIComponent(connectionId)}`), {
20
+ method: 'DELETE',
21
+ }).then((response) => parseApiResponse(response, 'Failed to revoke Agent Connection'));
22
+ },
23
+ };
@@ -1,6 +1,5 @@
1
- import '../styles/features/auth-gate.css';
2
-
3
1
  import { getHashParamsFromRaw } from '../domain/hash-routes.js';
2
+ import { parseApiResponse } from './api-client-utils.js';
4
3
  import { getRuntimeConfig } from './runtime-config.js';
5
4
 
6
5
  const DEFAULT_AUTH_CONFIG = {
@@ -66,12 +65,7 @@ async function fetchAuthStatus(config) {
66
65
  },
67
66
  });
68
67
 
69
- const payload = await response.json().catch(() => ({}));
70
- if (!response.ok) {
71
- throw new Error(payload.error || 'Failed to read auth status');
72
- }
73
-
74
- return payload;
68
+ return parseApiResponse(response, 'Failed to read auth status');
75
69
  }
76
70
 
77
71
  function syncOidcIdentityToLocalState(status) {
@@ -100,13 +94,7 @@ async function submitPassword(config, password) {
100
94
  },
101
95
  body: JSON.stringify({ password }),
102
96
  });
103
- const payload = await response.json().catch(() => ({}));
104
-
105
- if (!response.ok) {
106
- throw new Error(payload.error || 'Authentication failed');
107
- }
108
-
109
- return payload;
97
+ return parseApiResponse(response, 'Authentication failed');
110
98
  }
111
99
 
112
100
  function createOverlayShell() {
@@ -265,6 +253,7 @@ export async function ensureClientAuthenticated() {
265
253
  return { authenticated: true, auth: config };
266
254
  }
267
255
 
256
+ await import('../styles/features/auth-gate.css');
268
257
  const { card, overlay } = createOverlayShell();
269
258
  document.body.append(overlay);
270
259
  let pendingOidcError = consumeHashParam('auth_error');
@@ -23,6 +23,7 @@ export class BrowserPreferencesPort {
23
23
  lineWrappingKey,
24
24
  recentFilesKey = 'collabmd-recent-files',
25
25
  vimModeKey = 'collabmd-editor-vim-mode',
26
+ viewModeKey = 'collabmd-editor-view-mode',
26
27
  sidebarVisibleKey,
27
28
  userNameKey,
28
29
  storage = globalThis.localStorage,
@@ -33,6 +34,7 @@ export class BrowserPreferencesPort {
33
34
  this.sidebarVisibleKey = sidebarVisibleKey;
34
35
  this.storage = storage;
35
36
  this.userNameKey = userNameKey;
37
+ this.viewModeKey = viewModeKey;
36
38
  this.vimModeKey = vimModeKey;
37
39
  }
38
40
 
@@ -68,6 +70,20 @@ export class BrowserPreferencesPort {
68
70
  writeStorage(this.storage, this.vimModeKey, String(enabled));
69
71
  }
70
72
 
73
+ getViewMode() {
74
+ const value = readStorage(this.storage, this.viewModeKey, null);
75
+ if (value === 'editor' || value === 'preview' || value === 'split') {
76
+ return value;
77
+ }
78
+ return null;
79
+ }
80
+
81
+ setViewMode(view) {
82
+ if (view === 'editor' || view === 'preview' || view === 'split') {
83
+ writeStorage(this.storage, this.viewModeKey, view);
84
+ }
85
+ }
86
+
71
87
  getRecentFiles() {
72
88
  const stored = readStorage(this.storage, this.recentFilesKey, '[]');
73
89
  try {
@@ -290,6 +290,13 @@ export class EditorSession {
290
290
  return this.viewAdapter.insertText(text);
291
291
  }
292
292
 
293
+ applyTextReplacements(replacements) {
294
+ if (!this.collaborationClient.initialSyncComplete) {
295
+ throw new Error('The collaborative document is not synchronized');
296
+ }
297
+ return this.viewAdapter.applyTextReplacements(replacements);
298
+ }
299
+
293
300
  replaceText(text) {
294
301
  return this.viewAdapter.replaceText(text);
295
302
  }
@@ -306,6 +313,10 @@ export class EditorSession {
306
313
  return this.viewAdapter.flashRemoteRange(range);
307
314
  }
308
315
 
316
+ isInitialSyncComplete() {
317
+ return this.collaborationClient.initialSyncComplete;
318
+ }
319
+
309
320
  waitForInitialSync(timeoutMs = 1500) {
310
321
  return this.collaborationClient.waitForInitialSync(timeoutMs);
311
322
  }