collabmd 0.1.35 → 0.1.36

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 (279) hide show
  1. package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-CvLFeHXu.js → CodeMirrorEditor-UCMRAMCV-DnBV8gCm.js} +1 -1
  2. package/dist/client/assets/{_baseFor-Bfo4esZ5.js → _baseFor-BSErPbF2.js} +1 -1
  3. package/dist/client/assets/{ar-SA-NXDWD63E-WivLHHDW.js → ar-SA-NXDWD63E-CTf_wpt3.js} +1 -1
  4. package/dist/client/assets/{arc-tRoMuWFi.js → arc-DD8jaAGl.js} +1 -1
  5. package/dist/client/assets/architecture-YZFGNWBL-DWWrde02.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-Q4EWVU46-CVdcOotN.js → architectureDiagram-Q4EWVU46-BftXiJA8.js} +1 -1
  7. package/dist/client/assets/{az-AZ-MXSORGZV-DOdq1TKC.js → az-AZ-MXSORGZV-C_C9i9u3.js} +1 -1
  8. package/dist/client/assets/{bg-BG-O6MV2KSF-CYucKuDS.js → bg-BG-O6MV2KSF-YmfvQf63.js} +1 -1
  9. package/dist/client/assets/{blockDiagram-DXYQGD6D-B_gNUKQ4.js → blockDiagram-DXYQGD6D-6UN-nR8-.js} +1 -1
  10. package/dist/client/assets/{bn-IN-MMW2ORAC-DYr8kqNL.js → bn-BD-T2VJNT7N-BD0ob0JE.js} +1 -1
  11. package/dist/client/assets/{bn-BD-T2VJNT7N-2OKWLCYa.js → bn-IN-MMW2ORAC-BTEFR4Ed.js} +1 -1
  12. package/dist/client/assets/{c4Diagram-AHTNJAMY-BSDwfduG.js → c4Diagram-AHTNJAMY-Gz7ZAK0d.js} +1 -1
  13. package/dist/client/assets/{ca-ES-MKBCGNOG-B9Aeb43I.js → ca-ES-MKBCGNOG-aLX_cjA0.js} +1 -1
  14. package/dist/client/assets/channel-XGCkuPi6.js +1 -0
  15. package/dist/client/assets/{chunk-2KRD3SAO-C6u8y11R.js → chunk-2KRD3SAO-CFcF2aNP.js} +1 -1
  16. package/dist/client/assets/{chunk-336JU56O-Ch9X5KoM.js → chunk-336JU56O-DvrrHsJT.js} +2 -2
  17. package/dist/client/assets/chunk-426QAEUC-CEbmCgux.js +1 -0
  18. package/dist/client/assets/{chunk-4BX2VUAB-2e7V-uuE.js → chunk-4BX2VUAB-D5YiFdu1.js} +1 -1
  19. package/dist/client/assets/{chunk-4TB4RGXK-BEsauZP5.js → chunk-4TB4RGXK-CoouNThi.js} +2 -2
  20. package/dist/client/assets/{chunk-55IACEB6-DLqevMSj.js → chunk-55IACEB6-VHgZjidg.js} +1 -1
  21. package/dist/client/assets/{chunk-5FUZZQ4R-6x8SlhH9.js → chunk-5FUZZQ4R-CxIIxXPy.js} +1 -1
  22. package/dist/client/assets/{chunk-5PVQY5BW-R5SE6dhE.js → chunk-5PVQY5BW-ciE7eHID.js} +1 -1
  23. package/dist/client/assets/{chunk-67CJDMHE-CjXw5hFa.js → chunk-67CJDMHE-CW-fbgQB.js} +1 -1
  24. package/dist/client/assets/{chunk-7N4EOEYR-DNHyuswJ.js → chunk-7N4EOEYR-DbAW6XnF.js} +1 -1
  25. package/dist/client/assets/{chunk-AA7GKIK3-DayE4IF_.js → chunk-AA7GKIK3-ClDHDAza.js} +1 -1
  26. package/dist/client/assets/{chunk-BSJP7CBP-CexlYBxB.js → chunk-BSJP7CBP-D2KkrA_B.js} +1 -1
  27. package/dist/client/assets/{chunk-CIAEETIT-CkDJ4DYI.js → chunk-CIAEETIT-BnB8a6HR.js} +1 -1
  28. package/dist/client/assets/{chunk-EDXVE4YY-BVR_nF3y.js → chunk-EDXVE4YY-M4QxyGNt.js} +1 -1
  29. package/dist/client/assets/{chunk-ENJZ2VHE-CFVWytAB.js → chunk-ENJZ2VHE-BQj_1YA_.js} +1 -1
  30. package/dist/client/assets/{chunk-FMBD7UC4-CMahlBa_.js → chunk-FMBD7UC4-qQT7MtX2.js} +1 -1
  31. package/dist/client/assets/{chunk-FOC6F5B3-DzCiCLGs.js → chunk-FOC6F5B3-Bw6XfKDP.js} +1 -1
  32. package/dist/client/assets/{chunk-ICPOFSXX-B9LPHgU7.js → chunk-ICPOFSXX-DqJi89rc.js} +1 -1
  33. package/dist/client/assets/{chunk-K5T4RW27-kmGSebVE.js → chunk-K5T4RW27-CQtjKF2g.js} +7 -7
  34. package/dist/client/assets/{chunk-KGLVRYIC-DVjPRsaR.js → chunk-KGLVRYIC-BWSPiKjp.js} +1 -1
  35. package/dist/client/assets/{chunk-LIHQZDEY-DKFj13sC.js → chunk-LIHQZDEY-DtYrHuCi.js} +1 -1
  36. package/dist/client/assets/{chunk-AXZTUZBK-DuMiJYO9.js → chunk-LOOWOR4L-C5BUwXgZ.js} +2 -2
  37. package/dist/client/assets/{chunk-ORNJ4GCN-D0uTAC-5.js → chunk-ORNJ4GCN-Csga44e5.js} +1 -1
  38. package/dist/client/assets/{chunk-OYMX7WX6-nWiNHNyD.js → chunk-OYMX7WX6-DvtmCasj.js} +1 -1
  39. package/dist/client/assets/chunk-QZHKN3VN-CHVH9_3S.js +1 -0
  40. package/dist/client/assets/{chunk-SRAX5OIU-CLVBQRWC.js → chunk-SRAX5OIU-yDw8XRsi.js} +1 -1
  41. package/dist/client/assets/{chunk-U2HBQHQK-Bue4Ufzn.js → chunk-U2HBQHQK-BBXgsocS.js} +1 -1
  42. package/dist/client/assets/{chunk-X2U36JSP-CRE6lp7n.js → chunk-X2U36JSP-D3OEPG7k.js} +1 -1
  43. package/dist/client/assets/{chunk-XPW4576I-BL5M-tF8.js → chunk-XPW4576I-BUfyrOtN.js} +1 -1
  44. package/dist/client/assets/chunk-YHkbxXgt.js +1 -0
  45. package/dist/client/assets/chunk-YKPWT25G-GISHuloq.js +35 -0
  46. package/dist/client/assets/{chunk-YZCP3GAM-D7Z5wUWA.js → chunk-YZCP3GAM-D1jf1WUI.js} +1 -1
  47. package/dist/client/assets/{chunk-Z5NKEFVG-HOkYqaKa.js → chunk-Z5NKEFVG-Vu8zBV4H.js} +1 -1
  48. package/dist/client/assets/{chunk-ZZ45TVLE-CBbl1Qec.js → chunk-ZZ45TVLE-DGIhE_ST.js} +1 -1
  49. package/dist/client/assets/classDiagram-6PBFFD2Q-D1KhAUL3.js +1 -0
  50. package/dist/client/assets/classDiagram-v2-HSJHXN6E-BSyyJpnR.js +1 -0
  51. package/dist/client/assets/clone-DI0bYZ1L.js +1 -0
  52. package/dist/client/assets/{cose-bilkent-S5V4N54A-xxgR5OJ-.js → cose-bilkent-S5V4N54A-A8ssRFyt.js} +1 -1
  53. package/dist/client/assets/{cs-CZ-V77HGUP7-BDg-F0CJ.js → cs-CZ-V77HGUP7-Du3y53BB.js} +1 -1
  54. package/dist/client/assets/{cytoscape.esm-B3PRdePO.js → cytoscape.esm-BurByw8X.js} +2 -2
  55. package/dist/client/assets/{da-DK-I5RFNTM4-wtSQ0Jxa.js → da-DK-I5RFNTM4-CDJtjf5s.js} +1 -1
  56. package/dist/client/assets/{dagre-VaFYRFbD.js → dagre-Dn6rkrte.js} +1 -1
  57. package/dist/client/assets/{dagre-KV5264BT-C2K9mFg1.js → dagre-KV5264BT-COzej2en.js} +1 -1
  58. package/dist/client/assets/{de-CH-WLRDEVBV-C1swvmZy.js → de-CH-WLRDEVBV-CLV2tVw6.js} +1 -1
  59. package/dist/client/assets/{de-DE-DTI4WUSC-C0L6Nz8X.js → de-DE-DTI4WUSC-B53J0BQ8.js} +1 -1
  60. package/dist/client/assets/{diagram-5BDNPKRD-DE0M0jaM.js → diagram-5BDNPKRD-BuK-UBuN.js} +1 -1
  61. package/dist/client/assets/{diagram-G4DWMVQ6-BfaRuSTT.js → diagram-G4DWMVQ6-CbswIU9X.js} +1 -1
  62. package/dist/client/assets/{diagram-MMDJMWI5-91Bly_hN.js → diagram-MMDJMWI5-BE-yOVGX.js} +1 -1
  63. package/dist/client/assets/{diagram-TYMM5635-fBkLwZGN.js → diagram-TYMM5635-CT8BdT4s.js} +1 -1
  64. package/dist/client/assets/{dist-FC9LftvP.js → dist-B98fHn5m.js} +1 -1
  65. package/dist/client/assets/{dist-VPEWg0Ob.js → dist-BE8C_ouo.js} +1 -1
  66. package/dist/client/assets/{dist-r5I9Jgww.js → dist-BEKQo64E.js} +1 -1
  67. package/dist/client/assets/{dist-BMlUxhOz.js → dist-BOP-dC-R.js} +1 -1
  68. package/dist/client/assets/{dist-DidT3Jay.js → dist-BPEi1dEF.js} +1 -1
  69. package/dist/client/assets/{dist-DAKGEzm0.js → dist-BScEL4VP.js} +1 -1
  70. package/dist/client/assets/dist-BfVljg0L2.js +1 -0
  71. package/dist/client/assets/{dist-PPAeaw4t.js → dist-BiCgLddE.js} +1 -1
  72. package/dist/client/assets/{dist-CSNMpi-w.js → dist-Bn8WRPs1.js} +1 -1
  73. package/dist/client/assets/{dist-CSAH9iuE.js → dist-Brrlevif.js} +1 -1
  74. package/dist/client/assets/{dist-Dwy75xI6.js → dist-CBEw2W2P.js} +1 -1
  75. package/dist/client/assets/{dist-Bkn7JaJv.js → dist-CJWCCWEW.js} +1 -1
  76. package/dist/client/assets/{dist-D1-dK0Dk.js → dist-CQVTTk81.js} +1 -1
  77. package/dist/client/assets/{dist-BSED50tI.js → dist-CaMl1R6P.js} +3 -3
  78. package/dist/client/assets/dist-CcG3Y7Wp.js +1 -0
  79. package/dist/client/assets/dist-CghBwrO3.js +1 -0
  80. package/dist/client/assets/dist-Csbx9lQ-.js +1 -0
  81. package/dist/client/assets/dist-D34Xzrah.js +1 -0
  82. package/dist/client/assets/dist-DLyohOXi.js +1 -0
  83. package/dist/client/assets/{dist-CqU98NzX.js → dist-DPCUH5MO.js} +1 -1
  84. package/dist/client/assets/{dist-74GtnE06.js → dist-DQiph4qx.js} +1 -1
  85. package/dist/client/assets/{dist-C0e9kfNh.js → dist-DWRyOl2w.js} +1 -1
  86. package/dist/client/assets/{dist-cQSK4Xor.js → dist-DZ2t5lUX.js} +1 -1
  87. package/dist/client/assets/{dist-D0dQAc9b.js → dist-Dbg8P4C5.js} +1 -1
  88. package/dist/client/assets/{dist-Co8HE14w.js → dist-DdAqzGFU.js} +1 -1
  89. package/dist/client/assets/{dist-CDUQ5ELn.js → dist-DwvSvkOE.js} +1 -1
  90. package/dist/client/assets/{dist-Doo91MTa.js → dist-WXLmfDGg.js} +1 -1
  91. package/dist/client/assets/{dist-DdR2aYqj.js → dist-aE0_04fl.js} +1 -1
  92. package/dist/client/assets/{dist-Bzb9nPam.js → dist-mPPUaHhq.js} +1 -1
  93. package/dist/client/assets/{dist-DSRCADL9.js → dist-v3i1ifes.js} +1 -1
  94. package/dist/client/assets/{dist-DBzteOlY.js → dist-wkd-N1L5.js} +1 -1
  95. package/dist/client/assets/{drawio-editor-CWLEpwps.js → drawio-editor-D4Qoluwz.js} +1 -1
  96. package/dist/client/assets/{drawioEditor-5rJhxjA4.js → drawioEditor-B65FWq-b.js} +2 -2
  97. package/dist/client/assets/{editor-session-CLOuvy37.js → editor-session-DV80PhYL.js} +3 -3
  98. package/dist/client/assets/{el-GR-ZXDJ2OS4-BH0saXds.js → el-GR-ZXDJ2OS4-DFmRQv0o.js} +1 -1
  99. package/dist/client/assets/{en-IQZW2TQM-CzlcEpq3.js → en-CMP6EMR6-D9x8hVSu.js} +1 -1
  100. package/dist/client/assets/{erDiagram-SMLLAGMA-DUQcqEQ1.js → erDiagram-SMLLAGMA-6VFZA3Qb.js} +1 -1
  101. package/dist/client/assets/{es-ES-DYQHAD43-CyzL9Mni.js → es-ES-DYQHAD43-BiGWIrBG.js} +1 -1
  102. package/dist/client/assets/{eu-ES-QDSYU5Y3-D2-x316S.js → eu-ES-QDSYU5Y3-BjwS0kZi.js} +1 -1
  103. package/dist/client/assets/excalidraw-editor-BZCE9ydu.css +1 -0
  104. package/dist/client/assets/excalidraw-editor-hiJQt1cX.js +9 -0
  105. package/dist/client/assets/excalidraw-scene-MyNAJi2A.js +176 -0
  106. package/dist/client/assets/excalidrawEditor-BnbblxK4.js +2 -0
  107. package/dist/client/assets/{export-page-D2rCmrUH.js → export-page-BKDarp9x.js} +3 -3
  108. package/dist/client/assets/exportDocument-CULEGKmb.js +2 -0
  109. package/dist/client/assets/{fa-IR-26LZG4PM-D8-trU2x.js → fa-IR-26LZG4PM-BgANg2TD.js} +1 -1
  110. package/dist/client/assets/{fi-FI-6YS4KDE4-CCdRVFDQ.js → fi-FI-6YS4KDE4-CBL5f3oN.js} +1 -1
  111. package/dist/client/assets/{flatten-CX_XvnUf.js → flatten-DjXjUsvv.js} +1 -1
  112. package/dist/client/assets/{flowDiagram-DWJPFMVM-B_A5JyId.js → flowDiagram-DWJPFMVM-DO9RH8YQ.js} +1 -1
  113. package/dist/client/assets/{fr-FR-BRLLPTZC-Dqq-O5T_.js → fr-FR-BRLLPTZC-CRibNSLG.js} +1 -1
  114. package/dist/client/assets/{ganttDiagram-T4ZO3ILL-HM3CD7bk.js → ganttDiagram-T4ZO3ILL-B-NMvHWN.js} +1 -1
  115. package/dist/client/assets/gitGraph-7Q5UKJZL-DWNinXu4.js +1 -0
  116. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-Dw7twZDm.js → gitGraphDiagram-UUTBAWPF-B95qkCUx.js} +1 -1
  117. package/dist/client/assets/{gl-ES-OKUZTLYG-BK7pbLbm.js → gl-ES-OKUZTLYG-DEDwa_xt.js} +1 -1
  118. package/dist/client/assets/{graphlib-DDD4Vdye.js → graphlib-CAwOVCJc.js} +1 -1
  119. package/dist/client/assets/{he-IL-26MGYIU7-C3BuYKyY.js → he-IL-26MGYIU7-47wxy70N.js} +1 -1
  120. package/dist/client/assets/{hi-IN-Q4ZOGTP2-BEvXWXnH.js → hi-IN-Q4ZOGTP2-bhV7c3dK.js} +1 -1
  121. package/dist/client/assets/{hu-HU-P2OXPSN5-BWWZeJNp.js → hu-HU-P2OXPSN5-xG-gBMzE.js} +1 -1
  122. package/dist/client/assets/{id-ID-2EIKXYN6-DxSKi_aJ.js → id-ID-2EIKXYN6-MQuYaNHo.js} +1 -1
  123. package/dist/client/assets/image-J2CAS7OM-DD4DaQTs.js +1 -0
  124. package/dist/client/assets/{image-blob-reduce.esm-DiuPkovC.js → image-blob-reduce.esm-D8JQdTFk.js} +1 -1
  125. package/dist/client/assets/{index-BbziNMqE.js → index-BjdYZiBM.js} +2 -2
  126. package/dist/client/assets/{index-BIt5EZXz.css → index-BryqP9QY.css} +1 -1
  127. package/dist/client/assets/info-OMHHGYJF-DtYG_rX0.js +1 -0
  128. package/dist/client/assets/{infoDiagram-42DDH7IO-DX-d3DMp.js → infoDiagram-42DDH7IO-C77Pt7T1.js} +1 -1
  129. package/dist/client/assets/{isEmpty-BKDbo1FH.js → isEmpty-CpfhGGBo.js} +1 -1
  130. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BHmsxpMs.js → ishikawaDiagram-UXIWVN3A-Cy1fwvvg.js} +1 -1
  131. package/dist/client/assets/{it-IT-4CFKVXI2-BmA8wW6q.js → it-IT-4CFKVXI2-v2kj-y7j.js} +1 -1
  132. package/dist/client/assets/{ja-JP-MAND2Z4V-CLS1jI9o.js → ja-JP-MAND2Z4V-BahXSQz-.js} +1 -1
  133. package/dist/client/assets/{journeyDiagram-VCZTEJTY-jxDSjgE1.js → journeyDiagram-VCZTEJTY-CYWaI6re.js} +1 -1
  134. package/dist/client/assets/{jsx-runtime-B_8UNt-W.js → jsx-runtime-1KUJVfx8.js} +1 -1
  135. package/dist/client/assets/{kaa-HQRTCXTJ-W15DEDPz.js → kaa-HQRTCXTJ-BF26ydFa.js} +1 -1
  136. package/dist/client/assets/{kab-KAB-JKIKKTGH-MLh1inqS.js → kab-KAB-JKIKKTGH-CEIH0F80.js} +1 -1
  137. package/dist/client/assets/{kanban-definition-6JOO6SKY-od3qY1mE.js → kanban-definition-6JOO6SKY-DY1xE7tm.js} +1 -1
  138. package/dist/client/assets/{kk-KZ-HXQ63ZFC-BtFrPeLs.js → kk-KZ-HXQ63ZFC-CxWjc9Sf.js} +1 -1
  139. package/dist/client/assets/{km-KH-PKL3LSGX-xO5FyM9T.js → km-KH-PKL3LSGX-DJlCteEp.js} +1 -1
  140. package/dist/client/assets/{ko-KR-KXLREZX3-NZFoRybS.js → ko-KR-KXLREZX3-B1gtI_ci.js} +1 -1
  141. package/dist/client/assets/{ku-TR-MJ4IER3X-B5eVPIpK.js → ku-TR-MJ4IER3X-Bf41y2v2.js} +1 -1
  142. package/dist/client/assets/{line-CZsGUM4H.js → line-BCItEgq3.js} +1 -1
  143. package/dist/client/assets/{linear-B2dOdA24.js → linear-dsIQT_iU.js} +1 -1
  144. package/dist/client/assets/{lt-LT-H6WFQ6FJ-D_7_OeJD.js → lt-LT-H6WFQ6FJ-DA1or-Eo.js} +1 -1
  145. package/dist/client/assets/{lv-LV-GOCK6SJW-CnpKr0oQ.js → lv-LV-GOCK6SJW-qa0BoYMm.js} +1 -1
  146. package/dist/client/assets/main-QJcxyvDa.js +1404 -0
  147. package/dist/client/assets/{mermaid-parser.core-DtIbxv6L.js → mermaid-parser.core-CsTVsPcD.js} +2 -2
  148. package/dist/client/assets/{mermaid-runtime-vVJfjscE.js → mermaid-runtime-BGlnoUXY.js} +3 -3
  149. package/dist/client/assets/{mindmap-definition-QFDTVHPH-C9qrdAqo.js → mindmap-definition-QFDTVHPH-DB_M5r-j.js} +1 -1
  150. package/dist/client/assets/{mr-IN-IXVLDMEQ-Pht2X_GK.js → mr-IN-IXVLDMEQ-DXFRgvgb.js} +1 -1
  151. package/dist/client/assets/{my-MM-YG6MYTTD-Cgq4HhPO.js → my-MM-YG6MYTTD-BKDIfalJ.js} +1 -1
  152. package/dist/client/assets/{nb-NO-XGWJISD2-Bn_Bk2un.js → nb-NO-XGWJISD2-DbwbopH8.js} +1 -1
  153. package/dist/client/assets/{nl-NL-XVDVCPNC-YkWSJS94.js → nl-NL-XVDVCPNC-ChSneTSU.js} +1 -1
  154. package/dist/client/assets/{nn-NO-EMX5MJX5-DhP5eZJ7.js → nn-NO-EMX5MJX5-Cf7ZWKWZ.js} +1 -1
  155. package/dist/client/assets/{oc-FR-ROEINTVO-D3udMPnr.js → oc-FR-ROEINTVO-lM7Nl7hD.js} +1 -1
  156. package/dist/client/assets/{pa-IN-ZYN6SUDY-CR5YzFig.js → pa-IN-ZYN6SUDY-C9WNUTeR.js} +1 -1
  157. package/dist/client/assets/packet-4T2RLAQJ-CUVefhAv.js +1 -0
  158. package/dist/client/assets/percentages-5DKR754L-DuhOjTM2.js +1 -0
  159. package/dist/client/assets/{pica-BEurQXMu.js → pica-CgGaIJly.js} +1 -1
  160. package/dist/client/assets/pie-ZZUOXDRM-BHBJ1dLX.js +1 -0
  161. package/dist/client/assets/{pieDiagram-DEJITSTG-BHXxj7wl.js → pieDiagram-DEJITSTG-BOo-WzjZ.js} +1 -1
  162. package/dist/client/assets/{pl-PL-6VTG7PHC-_wZuoIDM.js → pl-PL-6VTG7PHC-DqRVepnC.js} +1 -1
  163. package/dist/client/assets/{preview-diagram-utils-D8VypUft.js → preview-diagram-utils-Nqpp4FNV.js} +1 -1
  164. package/dist/client/assets/preview-render-compiler-BCB8u6iM.js +1 -0
  165. package/dist/client/assets/{preview-render-compiler-BHeDhYho.js → preview-render-compiler-Tkc6JX1O.js} +1 -1
  166. package/dist/client/assets/{preview-render-profile-BF6os3x9.js → preview-render-profile-Bf6R7v4w.js} +2 -2
  167. package/dist/client/assets/{preview-render-worker-C4AFtMIr.js → preview-render-worker-1LBLqgKu.js} +2 -2
  168. package/dist/client/assets/{pt-BR-5YFKRR5G-M7gIm2Hi.js → pt-BR-5YFKRR5G-CopLYEA6.js} +1 -1
  169. package/dist/client/assets/{pt-PT-GEIXXZ67-CcxWpkGj.js → pt-PT-GEIXXZ67-BjZ_Lphg.js} +1 -1
  170. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-CWW7LORF.js → quadrantDiagram-34T5L4WZ-2vfo0l5S.js} +1 -1
  171. package/dist/client/assets/radar-PYXPWWZC-2jR4qZNU.js +1 -0
  172. package/dist/client/assets/{reduce-C6FuFJbE.js → reduce-ChpYjEUB.js} +1 -1
  173. package/dist/client/assets/{requirementDiagram-MS252O5E-CTljNdQH.js → requirementDiagram-MS252O5E-CtUIQnWa.js} +1 -1
  174. package/dist/client/assets/{ro-RO-E2P6TFZI-qR9noVzP.js → ro-RO-E2P6TFZI-DakDz5Xu.js} +1 -1
  175. package/dist/client/assets/{room-DI7DXGeS.js → room-z2w9b96b.js} +1 -1
  176. package/dist/client/assets/{ru-RU-YBIIY43T-CE4S_RX8.js → ru-RU-YBIIY43T-BMvCT-XT.js} +1 -1
  177. package/dist/client/assets/{sankeyDiagram-XADWPNL6-CCfFkC74.js → sankeyDiagram-XADWPNL6-tcSeuifE.js} +1 -1
  178. package/dist/client/assets/{sequenceDiagram-FGHM5R23-BD9vj6WG.js → sequenceDiagram-FGHM5R23-DtF-1Kt2.js} +1 -1
  179. package/dist/client/assets/{si-LK-673C2CI2-Bv6Avh3z.js → si-LK-673C2CI2-hGdH1S9E.js} +1 -1
  180. package/dist/client/assets/{sk-SK-CKZHQ4AP-Cnlpp55z.js → sk-SK-CKZHQ4AP-DiRA-fj8.js} +1 -1
  181. package/dist/client/assets/{sl-SI-557H2GWM-BfGq7AQF.js → sl-SI-557H2GWM-DN94n_1-.js} +1 -1
  182. package/dist/client/assets/src-BuiVcSz-.js +1 -0
  183. package/dist/client/assets/{stateDiagram-FHFEXIEX-CpiX3KPd.js → stateDiagram-FHFEXIEX-DKk7Sb0f.js} +1 -1
  184. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DJUaiADr.js +1 -0
  185. package/dist/client/assets/subset-shared.chunk-CWNYNLru.js +1 -0
  186. package/dist/client/assets/{subset-worker.chunk-BSCP6IiC.js → subset-worker.chunk-kj1e3wjW.js} +1 -1
  187. package/dist/client/assets/{sv-SE-XOPKKDWS-B2_Vk-sp.js → sv-SE-XOPKKDWS-CkHUNABj.js} +1 -1
  188. package/dist/client/assets/{ta-IN-XBH7DQI3-BXQMZZIx.js → ta-IN-XBH7DQI3-W-157oVK.js} +1 -1
  189. package/dist/client/assets/{th-TH-TOCWH3R4-C-ZIYMfH.js → th-TH-TOCWH3R4-BsU-Pydr.js} +1 -1
  190. package/dist/client/assets/{timeline-definition-GMOUNBTQ-BafRAkSF.js → timeline-definition-GMOUNBTQ-Bs6U53Mo.js} +1 -1
  191. package/dist/client/assets/{tr-TR-GXW6CYY5-dl702PMA.js → tr-TR-GXW6CYY5-CTddyq89.js} +1 -1
  192. package/dist/client/assets/treeView-SZITEDCU-DN5dP2ol.js +1 -0
  193. package/dist/client/assets/treemap-W4RFUUIX-Dva7DBJR.js +1 -0
  194. package/dist/client/assets/{uk-UA-IJKTNUDG-CUYQvSSF.js → uk-UA-IJKTNUDG-1LzXkII3.js} +1 -1
  195. package/dist/client/assets/{uz-UZ-TBZZEA4V-B9qw0PXX.js → uz-UZ-TBZZEA4V-kqm-qcUj.js} +1 -1
  196. package/dist/client/assets/{vennDiagram-DHZGUBPP-DSngq_Zj.js → vennDiagram-DHZGUBPP-DNnIjRae.js} +1 -1
  197. package/dist/client/assets/{vi-VN-MULSGNVB-DqxZ_sVc.js → vi-VN-MULSGNVB-C3H2AUhm.js} +1 -1
  198. package/dist/client/assets/wardley-RL74JXVD-CDZW5uzY.js +1 -0
  199. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-CAEd2kJG.js → wardleyDiagram-NUSXRM2D-C-scJfPY.js} +1 -1
  200. package/dist/client/assets/{xychartDiagram-5P7HB3ND-BScQpnru.js → xychartDiagram-5P7HB3ND-D3nQoxhz.js} +1 -1
  201. package/dist/client/assets/{yjs-provider-reset-guard-_Q3mj6tP.js → yjs-provider-reset-guard-DSPzcvAO.js} +2 -2
  202. package/dist/client/assets/{zh-CN-MVX3E32U-BM0aLuGc.js → zh-CN-MVX3E32U-BULPbsyl.js} +1 -1
  203. package/dist/client/assets/{zh-HK-JNU5RLIE-dmG_YD0d.js → zh-HK-JNU5RLIE-bNGmeSaW.js} +1 -1
  204. package/dist/client/assets/{zh-TW-LENVCA6T-LFgbiOi3.js → zh-TW-LENVCA6T-CQDp064P.js} +1 -1
  205. package/dist/client/drawio-editor.html +1 -1
  206. package/dist/client/excalidraw-editor.html +1 -1
  207. package/dist/client/export-document.html +1 -1
  208. package/dist/client/index.html +2 -2
  209. package/package.json +11 -11
  210. package/src/client/application/app-shell/presence-feature.js +265 -34
  211. package/src/client/application/app-shell/ui-feature-shell.js +26 -3
  212. package/src/client/application/app-shell/ui-feature-tab-activity.js +1 -0
  213. package/src/client/application/app-shell/workspace-feature.js +5 -2
  214. package/src/client/application/app-shell-elements.js +3 -0
  215. package/src/client/application/diagram-preview-export.js +304 -0
  216. package/src/client/application/mermaid-preview-hydrator.js +153 -23
  217. package/src/client/application/plantuml-preview-hydrator.js +155 -20
  218. package/src/client/application/preview-diagram-utils.js +48 -8
  219. package/src/client/application/preview-renderer.js +2 -0
  220. package/src/client/application/quick-switcher-loader.js +4 -1
  221. package/src/client/application/workspace-route-controller.js +35 -2
  222. package/src/client/application/workspace-state-store.js +1 -0
  223. package/src/client/bootstrap/collabmd-app-shell.js +9 -0
  224. package/src/client/domain/diagram-action-icons.js +21 -0
  225. package/src/client/domain/excalidraw-api-scene-sync.js +70 -0
  226. package/src/client/excalidraw-editor.js +106 -18
  227. package/src/client/infrastructure/excalidraw-room-client.js +41 -4
  228. package/src/client/presentation/app-shell-template.js +18 -1
  229. package/src/client/presentation/file-explorer-controller.js +10 -0
  230. package/src/client/presentation/file-explorer-view.js +6 -0
  231. package/src/client/presentation/image-lightbox-controller.js +290 -29
  232. package/src/client/styles/features/collaboration-presence.css +212 -0
  233. package/src/client/styles/features/diagram-preview.css +71 -4
  234. package/src/client/styles/features/embedded-preview.css +4 -6
  235. package/src/client/styles/features/media-lightbox.css +2 -0
  236. package/src/server/config/env.js +4 -0
  237. package/src/server/create-app-server.js +2 -0
  238. package/src/server/domain/bases/base-query-service.js +89 -7
  239. package/src/server/domain/collaboration/collaboration-room.js +10 -1
  240. package/src/server/infrastructure/http/create-request-handler.js +1 -0
  241. package/src/server/infrastructure/http/create-vault-api-handler.js +2 -0
  242. package/src/server/infrastructure/http/create-vault-api-query-handler.js +100 -26
  243. package/src/server/infrastructure/persistence/vault-file-store.js +136 -0
  244. package/src/server/infrastructure/workspace/file-system-sync-service.js +9 -11
  245. package/dist/client/assets/architecture-YZFGNWBL-CtU43_5T.js +0 -1
  246. package/dist/client/assets/channel-BDb1g_mJ.js +0 -1
  247. package/dist/client/assets/chunk-426QAEUC-CwJ7loGf.js +0 -1
  248. package/dist/client/assets/chunk-DpHwWhuW.js +0 -1
  249. package/dist/client/assets/chunk-NU2UP6EN-UVL-wkIc.js +0 -35
  250. package/dist/client/assets/chunk-QZHKN3VN-BnOS2iQW.js +0 -1
  251. package/dist/client/assets/classDiagram-6PBFFD2Q-MIbgV5UL.js +0 -1
  252. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Bb70vg2O.js +0 -1
  253. package/dist/client/assets/clone-D6JWrlxJ.js +0 -1
  254. package/dist/client/assets/dist-B3lARV_e.js +0 -1
  255. package/dist/client/assets/dist-BCvzlTeb.js +0 -1
  256. package/dist/client/assets/dist-Bq8Z0WUT.js +0 -1
  257. package/dist/client/assets/dist-C8wdW7W4.js +0 -1
  258. package/dist/client/assets/dist-CHSg_nUM.js +0 -1
  259. package/dist/client/assets/dist-CZPTvk_g2.js +0 -1
  260. package/dist/client/assets/excalidraw-editor-Dj3i59LW.css +0 -1
  261. package/dist/client/assets/excalidraw-editor-ukEKPqGJ.js +0 -9
  262. package/dist/client/assets/excalidraw-scene-CDK3oDnm.js +0 -176
  263. package/dist/client/assets/excalidrawEditor-BJ8QLmWc.js +0 -2
  264. package/dist/client/assets/exportDocument-Dunnjgii.js +0 -2
  265. package/dist/client/assets/gitGraph-7Q5UKJZL-BrBlB49D.js +0 -1
  266. package/dist/client/assets/image-XLNPCCAD-BFNybKza.js +0 -1
  267. package/dist/client/assets/info-OMHHGYJF-BcmgcSx1.js +0 -1
  268. package/dist/client/assets/main-CN0kbtGk.js +0 -1369
  269. package/dist/client/assets/packet-4T2RLAQJ-DYYSvRuJ.js +0 -1
  270. package/dist/client/assets/percentages-5DKR754L-D7n4T776.js +0 -1
  271. package/dist/client/assets/pie-ZZUOXDRM-cG65Mc64.js +0 -1
  272. package/dist/client/assets/preview-render-compiler-D3QM1Ryz.js +0 -1
  273. package/dist/client/assets/radar-PYXPWWZC-Bmpup_xw.js +0 -1
  274. package/dist/client/assets/src-Pgt9Gp65.js +0 -1
  275. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-D_5ufPqT.js +0 -1
  276. package/dist/client/assets/subset-shared.chunk-C9HjwTXy.js +0 -1
  277. package/dist/client/assets/treeView-SZITEDCU-NbjhK5cw.js +0 -1
  278. package/dist/client/assets/treemap-W4RFUUIX-DJzRbb-x.js +0 -1
  279. package/dist/client/assets/wardley-RL74JXVD-DTNoH_BY.js +0 -1
@@ -1,5 +1,12 @@
1
1
  import { clamp } from '../domain/vault-utils.js';
2
2
  import { setDiagramActionButtonIcon } from '../domain/diagram-action-icons.js';
3
+ import {
4
+ createDiagramExportFileNames,
5
+ downloadBlob,
6
+ exportSvgMarkupFromElement,
7
+ rasterizeSvgMarkupToPngBlob,
8
+ writeBlobToClipboard,
9
+ } from './diagram-preview-export.js';
3
10
  import { DiagramPreviewHydrator } from './diagram-preview-hydrator.js';
4
11
  import {
5
12
  createPlantUmlPlaceholderCard,
@@ -36,6 +43,8 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
36
43
  this.svgCache = new Map();
37
44
  this.svgInflightRequests = new Map();
38
45
  this.shellRefits = new WeakMap();
46
+ this.shellResizeObservers = new WeakMap();
47
+ this.resizeObservers = new Set();
39
48
  this.activeMaximizedShell = null;
40
49
  this.maximizedRoot = null;
41
50
  this.resizeFrameId = null;
@@ -49,10 +58,41 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
49
58
  cancelAnimationFrame(this.resizeFrameId);
50
59
  this.resizeFrameId = null;
51
60
  }
61
+ this.disconnectResizeObservers();
52
62
  this.maximizedRoot?.remove();
53
63
  this.maximizedRoot = null;
54
64
  }
55
65
 
66
+ disconnectResizeObservers() {
67
+ this.resizeObservers.forEach((observer) => observer.disconnect());
68
+ this.resizeObservers.clear();
69
+ this.shellResizeObservers = new WeakMap();
70
+ }
71
+
72
+ disconnectShellResizeObserver(shell) {
73
+ const observer = this.shellResizeObservers.get(shell);
74
+ if (!observer) {
75
+ return;
76
+ }
77
+
78
+ observer.disconnect();
79
+ this.resizeObservers.delete(observer);
80
+ this.shellResizeObservers.delete(shell);
81
+ }
82
+
83
+ attachShellResizeObserver(shell, frame, onResize) {
84
+ this.disconnectShellResizeObserver(shell);
85
+ if (typeof ResizeObserver !== 'function' || !shell?.isConnected || !(frame instanceof HTMLElement)) {
86
+ return;
87
+ }
88
+
89
+ const observer = new ResizeObserver(() => onResize());
90
+ observer.observe(frame);
91
+ observer.observe(shell);
92
+ this.shellResizeObservers.set(shell, observer);
93
+ this.resizeObservers.add(observer);
94
+ }
95
+
56
96
  clearActiveShell() {
57
97
  this.activeMaximizedShell = null;
58
98
  if (this.maximizedRoot && this.maximizedRoot.childElementCount === 0) {
@@ -228,6 +268,7 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
228
268
  this.svgInflightRequests.delete(source);
229
269
  }
230
270
 
271
+ this.disconnectShellResizeObserver(shell);
231
272
  this.shellRefits.delete(shell);
232
273
  if (this.activeMaximizedShell === shell) {
233
274
  this.restoreShellMount(shell);
@@ -261,27 +302,38 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
261
302
 
262
303
  const toolbar = document.createElement('div');
263
304
  toolbar.className = 'plantuml-toolbar diagram-preview-toolbar';
305
+ const leftGroup = document.createElement('div');
306
+ leftGroup.className = 'diagram-preview-toolbar-group diagram-preview-toolbar-group--zoom';
307
+ const rightGroup = document.createElement('div');
308
+ rightGroup.className = 'diagram-preview-toolbar-group diagram-preview-toolbar-group--actions';
264
309
 
265
310
  const frame = document.createElement('div');
266
311
  frame.className = 'plantuml-frame diagram-preview-frame';
267
312
  const decreaseButton = this.createToolButton('−', 'Zoom out');
268
313
  const increaseButton = this.createToolButton('+', 'Zoom in');
269
- const resetButton = this.createToolButton('Reset', 'Reset zoom');
270
- const reloadButton = this.createToolButton('Reload', 'Reload diagram');
271
- const maximizeButton = this.createToolButton('Max', 'Maximize diagram');
314
+ const resetButton = this.createToolButton('', 'Reset zoom', { icon: 'fit' });
315
+ const copyButton = this.createToolButton('', 'Copy image', { icon: 'copy' });
316
+ const downloadButton = this.createToolButton('', 'Download SVG', { icon: 'download' });
317
+ const reloadButton = this.createToolButton('', 'Reload diagram', { icon: 'refresh' });
318
+ const maximizeButton = this.createToolButton('', 'Maximize diagram', { icon: 'maximize' });
272
319
  maximizeButton.classList.add('plantuml-maximize-btn');
273
- setDiagramActionButtonIcon(reloadButton, 'refresh');
274
- setDiagramActionButtonIcon(maximizeButton, 'maximize');
275
320
  const zoomLabel = document.createElement('span');
276
321
  zoomLabel.className = 'plantuml-zoom-label diagram-preview-zoom-label';
277
322
  zoomLabel.setAttribute('aria-live', 'polite');
278
323
 
279
- toolbar.append(decreaseButton, zoomLabel, resetButton, increaseButton, reloadButton, maximizeButton);
324
+ leftGroup.append(decreaseButton, zoomLabel, resetButton, increaseButton);
325
+ rightGroup.append(copyButton, downloadButton, reloadButton, maximizeButton);
326
+ toolbar.append(leftGroup, rightGroup);
280
327
 
281
328
  const { width: baseWidth, height: baseHeight } = getSvgSize(svg);
282
329
  let currentZoom = PLANTUML_ZOOM.default;
283
330
  let defaultZoom = 1;
284
331
  let zoomAnimationFrameId = null;
332
+ let resetZoomFrameId = null;
333
+ let layoutFrameId = null;
334
+ let hasManualZoom = false;
335
+ let lastAutoFitViewportWidth = 0;
336
+ let shouldForceScheduledReset = false;
285
337
  let isPanning = false;
286
338
  let activePointerId = null;
287
339
  let panStartX = 0;
@@ -293,6 +345,15 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
293
345
  svg.style.margin = '0 auto';
294
346
  svg.style.maxWidth = 'none';
295
347
 
348
+ const exportSvgMarkup = () => exportSvgMarkupFromElement(svg);
349
+
350
+ const exportFileNames = () => createDiagramExportFileNames({
351
+ currentFilePath: this.renderer.getSourceFilePath?.() ?? '',
352
+ diagramKind: 'plantuml',
353
+ sourceLine: shell.getAttribute('data-source-line') || '',
354
+ targetPath: shell.dataset.plantumlTarget || '',
355
+ });
356
+
296
357
  const calculateDefaultZoom = () => {
297
358
  const viewport = getFrameViewportSize(frame);
298
359
  if (!Number.isFinite(baseWidth) || baseWidth <= 0 || viewport.width <= 0) {
@@ -369,11 +430,14 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
369
430
  };
370
431
 
371
432
  const zoomBy = (delta) => {
433
+ hasManualZoom = true;
372
434
  animateZoomTo(currentZoom + delta);
373
435
  };
374
436
 
375
437
  const resetZoomToFit = ({ animate = false } = {}) => {
376
438
  defaultZoom = calculateDefaultZoom();
439
+ hasManualZoom = false;
440
+ lastAutoFitViewportWidth = getFrameViewportSize(frame).width;
377
441
 
378
442
  if (animate && Math.abs(defaultZoom - currentZoom) > 0.001) {
379
443
  animateZoomTo(defaultZoom);
@@ -390,28 +454,73 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
390
454
  frame.scrollTop = 0;
391
455
  };
392
456
 
393
- let resetZoomFrameId = null;
394
- const scheduleResetZoomToFit = () => {
457
+ const scheduleResetZoomToFit = ({ force = false } = {}) => {
458
+ shouldForceScheduledReset = shouldForceScheduledReset || force;
395
459
  if (resetZoomFrameId) {
396
460
  cancelAnimationFrame(resetZoomFrameId);
397
461
  }
462
+ if (layoutFrameId) {
463
+ cancelAnimationFrame(layoutFrameId);
464
+ }
398
465
 
399
466
  resetZoomFrameId = requestAnimationFrame(() => {
400
- resetZoomFrameId = null;
401
- if (!shell.isConnected) {
402
- return;
403
- }
404
-
405
- resetZoomToFit();
467
+ layoutFrameId = requestAnimationFrame(() => {
468
+ layoutFrameId = requestAnimationFrame(() => {
469
+ layoutFrameId = null;
470
+ resetZoomFrameId = null;
471
+ if (!shell.isConnected) {
472
+ return;
473
+ }
474
+
475
+ const shouldForce = shouldForceScheduledReset;
476
+ shouldForceScheduledReset = false;
477
+ const viewportWidth = getFrameViewportSize(frame).width;
478
+ const viewportChanged = Math.abs(viewportWidth - lastAutoFitViewportWidth) > 1;
479
+ if (!shouldForce && hasManualZoom) {
480
+ return;
481
+ }
482
+ if (!shouldForce && viewportWidth > 0 && lastAutoFitViewportWidth > 0 && !viewportChanged) {
483
+ return;
484
+ }
485
+
486
+ resetZoomToFit();
487
+ });
488
+ });
406
489
  });
407
490
  };
408
491
 
409
492
  this.shellRefits.set(shell, scheduleResetZoomToFit);
493
+ this.attachShellResizeObserver(shell, frame, () => scheduleResetZoomToFit());
410
494
 
411
495
  decreaseButton.addEventListener('click', () => zoomBy(-PLANTUML_ZOOM.step));
412
496
  increaseButton.addEventListener('click', () => zoomBy(PLANTUML_ZOOM.step));
413
497
  resetButton.addEventListener('click', () => {
414
- resetZoomToFit({ animate: true });
498
+ scheduleResetZoomToFit({ force: true });
499
+ });
500
+ copyButton.addEventListener('click', async () => {
501
+ try {
502
+ const { pngFileName } = exportFileNames();
503
+ const pngBlob = await rasterizeSvgMarkupToPngBlob(exportSvgMarkup());
504
+ try {
505
+ await writeBlobToClipboard(pngBlob);
506
+ this.renderer.toastController?.show?.('Diagram copied');
507
+ } catch {
508
+ downloadBlob(pngBlob, pngFileName);
509
+ this.renderer.toastController?.show?.('Clipboard image copy is unavailable here. Downloaded PNG instead.');
510
+ }
511
+ } catch {
512
+ this.renderer.toastController?.show?.('Failed to copy diagram');
513
+ }
514
+ });
515
+ downloadButton.addEventListener('click', () => {
516
+ try {
517
+ const { svgFileName } = exportFileNames();
518
+ const svgBlob = new Blob([exportSvgMarkup()], { type: 'image/svg+xml;charset=utf-8' });
519
+ downloadBlob(svgBlob, svgFileName);
520
+ this.renderer.toastController?.show?.('Diagram download started');
521
+ } catch {
522
+ this.renderer.toastController?.show?.('Failed to download diagram');
523
+ }
415
524
  });
416
525
 
417
526
  const syncMaximizeButtonState = () => {
@@ -445,7 +554,7 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
445
554
  this.activeMaximizedShell = shell;
446
555
  document.body.classList.add('plantuml-maximized-open');
447
556
  syncMaximizeButtonState();
448
- scheduleResetZoomToFit();
557
+ scheduleResetZoomToFit({ force: true });
449
558
  return;
450
559
  }
451
560
 
@@ -458,7 +567,7 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
458
567
  document.body.classList.remove('plantuml-maximized-open');
459
568
  }
460
569
  syncMaximizeButtonState();
461
- scheduleResetZoomToFit();
570
+ scheduleResetZoomToFit({ force: true });
462
571
  };
463
572
 
464
573
  reloadButton.addEventListener('click', () => {
@@ -481,6 +590,12 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
481
590
 
482
591
  isPanning = false;
483
592
  frame.classList.remove('is-dragging');
593
+ window.removeEventListener('pointerup', stopPanning, true);
594
+ window.removeEventListener('pointercancel', stopPanning, true);
595
+ window.removeEventListener('mouseup', stopPanning, true);
596
+ window.removeEventListener('touchend', stopPanning, true);
597
+ window.removeEventListener('touchcancel', stopPanning, true);
598
+ window.removeEventListener('blur', stopPanning, true);
484
599
 
485
600
  if (activePointerId !== null && typeof frame.releasePointerCapture === 'function') {
486
601
  try {
@@ -511,7 +626,19 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
511
626
  panStartScrollTop = frame.scrollTop;
512
627
 
513
628
  frame.classList.add('is-dragging');
514
- frame.setPointerCapture?.(event.pointerId);
629
+ window.addEventListener('pointerup', stopPanning, true);
630
+ window.addEventListener('pointercancel', stopPanning, true);
631
+ window.addEventListener('mouseup', stopPanning, true);
632
+ window.addEventListener('touchend', stopPanning, true);
633
+ window.addEventListener('touchcancel', stopPanning, true);
634
+ window.addEventListener('blur', stopPanning, true);
635
+ if (typeof frame.setPointerCapture === 'function') {
636
+ try {
637
+ frame.setPointerCapture(event.pointerId);
638
+ } catch {
639
+ // Safari can reject pointer capture during rapid layout transitions.
640
+ }
641
+ }
515
642
  event.preventDefault();
516
643
  });
517
644
 
@@ -527,6 +654,10 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
527
654
  frame.addEventListener('pointerup', stopPanning);
528
655
  frame.addEventListener('pointercancel', stopPanning);
529
656
  frame.addEventListener('lostpointercapture', stopPanning);
657
+ frame.addEventListener('mouseleave', stopPanning);
658
+ frame.addEventListener('mouseup', stopPanning);
659
+ frame.addEventListener('touchend', stopPanning);
660
+ frame.addEventListener('touchcancel', stopPanning);
530
661
 
531
662
  frame.appendChild(svg);
532
663
  const sourceNode = shell.querySelector('.plantuml-source');
@@ -541,13 +672,17 @@ export class PlantUmlPreviewHydrator extends DiagramPreviewHydrator {
541
672
  applyZoom(defaultZoom);
542
673
  }
543
674
 
544
- createToolButton(label, ariaLabel) {
675
+ createToolButton(label, ariaLabel, { icon = '' } = {}) {
545
676
  const button = document.createElement('button');
546
677
  button.type = 'button';
547
678
  button.className = 'plantuml-tool-btn ui-preview-action';
548
679
  button.setAttribute('aria-label', ariaLabel);
549
680
  button.title = ariaLabel;
550
- button.textContent = label;
681
+ if (icon) {
682
+ setDiagramActionButtonIcon(button, icon);
683
+ } else {
684
+ button.textContent = label;
685
+ }
551
686
  return button;
552
687
  }
553
688
  }
@@ -165,20 +165,30 @@ export function createPlantUmlPlaceholderCard(key, message = 'Renders server-sid
165
165
  return card;
166
166
  }
167
167
 
168
- export function sanitizeSvgMarkup(svgMarkup) {
169
- const parser = new DOMParser();
170
- const documentNode = parser.parseFromString(svgMarkup, 'image/svg+xml');
171
- const svg = documentNode.documentElement;
168
+ const SHOW_COMMENT_NODE = 128;
169
+
170
+ function removeSvgComments(rootElement) {
171
+ const walker = rootElement.ownerDocument.createTreeWalker(rootElement, SHOW_COMMENT_NODE);
172
+ const comments = [];
173
+
174
+ while (walker.nextNode()) {
175
+ comments.push(walker.currentNode);
176
+ }
172
177
 
173
- if (!svg || svg.nodeName.toLowerCase() !== 'svg') {
178
+ comments.forEach((comment) => comment.remove());
179
+ }
180
+
181
+ export function sanitizeSvgElement(svgElement) {
182
+ if (!(svgElement instanceof SVGSVGElement)) {
174
183
  throw new Error('Renderer returned invalid SVG');
175
184
  }
176
185
 
177
- documentNode.querySelectorAll('script, foreignObject').forEach((node) => {
186
+ removeSvgComments(svgElement);
187
+ svgElement.querySelectorAll('script, foreignObject').forEach((node) => {
178
188
  node.remove();
179
189
  });
180
190
 
181
- Array.from(documentNode.querySelectorAll('*')).forEach((element) => {
191
+ [svgElement, ...Array.from(svgElement.querySelectorAll('*'))].forEach((element) => {
182
192
  Array.from(element.attributes).forEach((attribute) => {
183
193
  const name = attribute.name.toLowerCase();
184
194
  const value = attribute.value || '';
@@ -193,7 +203,37 @@ export function sanitizeSvgMarkup(svgMarkup) {
193
203
  });
194
204
  });
195
205
 
196
- return svg.outerHTML;
206
+ return svgElement;
207
+ }
208
+
209
+ export function serializeSvgElement(svgElement) {
210
+ const sanitizedSvg = sanitizeSvgElement(svgElement);
211
+ return new XMLSerializer().serializeToString(sanitizedSvg);
212
+ }
213
+
214
+ function parseSvgMarkup(svgMarkup) {
215
+ const normalizedMarkup = String(svgMarkup ?? '')
216
+ .replace(/<!--[\s\S]*?-->/gu, '')
217
+ .replace(/&nbsp;/giu, '&#160;');
218
+
219
+ const parser = new DOMParser();
220
+ const documentNode = parser.parseFromString(normalizedMarkup, 'image/svg+xml');
221
+ const svg = documentNode.documentElement;
222
+ if (svg?.nodeName.toLowerCase() === 'svg' && !documentNode.querySelector('parsererror')) {
223
+ return svg;
224
+ }
225
+
226
+ const fallbackDocument = parser.parseFromString(normalizedMarkup, 'text/html');
227
+ return fallbackDocument.querySelector('svg');
228
+ }
229
+
230
+ export function sanitizeSvgMarkup(svgMarkup) {
231
+ const svg = parseSvgMarkup(svgMarkup);
232
+ if (!(svg instanceof SVGSVGElement)) {
233
+ throw new Error('Renderer returned invalid SVG');
234
+ }
235
+
236
+ return serializeSvgElement(svg);
197
237
  }
198
238
 
199
239
  export function shouldPreserveHydratedDiagram({ nextSource = '', nextTarget = '', preservedSource = '', preservedTarget = '' } = {}) {
@@ -20,6 +20,7 @@ export class PreviewRenderer {
20
20
  plantUmlRenderClient = null,
21
21
  previewContainer,
22
22
  previewElement,
23
+ toastController = null,
23
24
  }) {
24
25
  this.getContent = getContent;
25
26
  this.getFileList = getFileList;
@@ -33,6 +34,7 @@ export class PreviewRenderer {
33
34
  this.plantUmlRenderClient = plantUmlRenderClient;
34
35
  this.previewContainer = previewContainer;
35
36
  this.previewElement = previewElement;
37
+ this.toastController = toastController;
36
38
  this.renderHost = null;
37
39
 
38
40
  this.pendingRenderVersion = 0;
@@ -22,7 +22,10 @@ export async function ensureQuickSwitcherInstance(host) {
22
22
  if (!host.quickSwitcher) {
23
23
  host.quickSwitcher = new QuickSwitcherController({
24
24
  getFileList: () => host.fileExplorer.flatFiles,
25
- onFileSelect: (filePath) => host.handleFileSelection(filePath, { closeSidebarOnMobile: true }),
25
+ onFileSelect: (filePath) => host.handleFileSelection(filePath, {
26
+ closeSidebarOnMobile: true,
27
+ revealInTree: true,
28
+ }),
26
29
  });
27
30
  }
28
31
 
@@ -24,6 +24,7 @@ export class WorkspaceRouteController {
24
24
  setSession,
25
25
  setSessionLoadToken,
26
26
  setSidebarTab,
27
+ setSidebarVisibility,
27
28
  setCurrentFilePath,
28
29
  showGitCommit,
29
30
  showGitDiff,
@@ -59,6 +60,7 @@ export class WorkspaceRouteController {
59
60
  this.setSession = setSession;
60
61
  this.setSessionLoadToken = setSessionLoadToken;
61
62
  this.setSidebarTab = setSidebarTab;
63
+ this.setSidebarVisibility = setSidebarVisibility ?? (() => {});
62
64
  this.setCurrentFilePath = setCurrentFilePath;
63
65
  this.showGitCommit = showGitCommit;
64
66
  this.showGitDiff = showGitDiff;
@@ -69,6 +71,7 @@ export class WorkspaceRouteController {
69
71
  this.videoEmbed = videoEmbed;
70
72
  this.workspaceCoordinator = workspaceCoordinator;
71
73
  this.layoutController = layoutController;
74
+ this.pendingTreeRevealPath = null;
72
75
  }
73
76
 
74
77
  async handleHashChange() {
@@ -246,6 +249,11 @@ export class WorkspaceRouteController {
246
249
  }
247
250
 
248
251
  async openFile(filePath, options = {}) {
252
+ const shouldRevealInTree = this.pendingTreeRevealPath === filePath;
253
+ if (shouldRevealInTree) {
254
+ this.pendingTreeRevealPath = null;
255
+ }
256
+
249
257
  this.imageLightbox?.close?.();
250
258
  this.gitPanel.setSelection();
251
259
  this.gitDiffView.hide();
@@ -254,6 +262,10 @@ export class WorkspaceRouteController {
254
262
  this.syncMainChrome({ mode: 'editor' });
255
263
  await this.workspaceCoordinator.openFile(filePath, options);
256
264
  this.setSession(this.workspaceCoordinator.getSession());
265
+
266
+ if (shouldRevealInTree) {
267
+ this.revealFileInTree(filePath, { clearSearch: true });
268
+ }
257
269
  }
258
270
 
259
271
  cleanupSession() {
@@ -261,14 +273,35 @@ export class WorkspaceRouteController {
261
273
  this.setSession(this.workspaceCoordinator.getSession());
262
274
  }
263
275
 
264
- handleFileSelection(filePath, { closeSidebarOnMobile = false } = {}) {
265
- if (closeSidebarOnMobile) {
276
+ handleFileSelection(filePath, { closeSidebarOnMobile = false, revealInTree = false } = {}) {
277
+ const currentRoute = this.navigation.getHashRoute?.() ?? null;
278
+ const isCanonicalCurrentFileRoute = (
279
+ currentRoute?.type === 'file'
280
+ && currentRoute.filePath === filePath
281
+ && !currentRoute.drawioMode
282
+ );
283
+ if (revealInTree) {
284
+ this.pendingTreeRevealPath = filePath;
285
+ if (isCanonicalCurrentFileRoute) {
286
+ this.pendingTreeRevealPath = null;
287
+ this.revealFileInTree(filePath, { clearSearch: true });
288
+ return;
289
+ }
290
+ }
291
+
292
+ if (closeSidebarOnMobile && !revealInTree) {
266
293
  this.closeSidebarOnMobile();
267
294
  }
268
295
 
269
296
  this.navigation.navigateToFile(filePath);
270
297
  }
271
298
 
299
+ revealFileInTree(filePath, { clearSearch = false } = {}) {
300
+ this.setSidebarTab('files');
301
+ this.setSidebarVisibility(true);
302
+ this.fileExplorer.revealFile?.(filePath, { clearSearch });
303
+ }
304
+
272
305
  resetPreviewSurface() {
273
306
  this.imageLightbox?.close?.();
274
307
  this.previewRenderer.setHydrationPaused(false);
@@ -17,6 +17,7 @@ export class WorkspaceStateStore {
17
17
  gitRepoAvailable: false,
18
18
  globalUsers: [],
19
19
  isTabActive: false,
20
+ presencePanelOpen: false,
20
21
  sessionLoadToken: 0,
21
22
  ...initialState,
22
23
  };
@@ -100,9 +100,14 @@ export class CollabMdAppShell {
100
100
  handleGitCommitSubmit(...args) { return gitFeature.handleGitCommitSubmit.apply(this, args); }
101
101
  updateGlobalUsers(...args) { return presenceFeature.updateGlobalUsers.apply(this, args); }
102
102
  updateFileAwareness(...args) { return presenceFeature.updateFileAwareness.apply(this, args); }
103
+ closePresencePanel(...args) { return presenceFeature.closePresencePanel.apply(this, args); }
104
+ openPresencePanel(...args) { return presenceFeature.openPresencePanel.apply(this, args); }
103
105
  renderPresence(...args) { return presenceFeature.renderPresence.apply(this, args); }
104
106
  renderAvatars(...args) { return presenceFeature.renderAvatars.apply(this, args); }
107
+ renderPresencePanel(...args) { return presenceFeature.renderPresencePanel.apply(this, args); }
108
+ startFollowingUser(...args) { return presenceFeature.startFollowingUser.apply(this, args); }
105
109
  toggleFollowUser(...args) { return presenceFeature.toggleFollowUser.apply(this, args); }
110
+ togglePresencePanel(...args) { return presenceFeature.togglePresencePanel.apply(this, args); }
106
111
  stopFollowingUser(...args) { return presenceFeature.stopFollowingUser.apply(this, args); }
107
112
  syncFollowedUser(...args) { return presenceFeature.syncFollowedUser.apply(this, args); }
108
113
  followUserCursor(...args) { return presenceFeature.followUserCursor.apply(this, args); }
@@ -368,6 +373,7 @@ export class CollabMdAppShell {
368
373
  plantUmlRenderClient: this.plantUmlApiClient,
369
374
  previewContainer: this.elements.previewContainer,
370
375
  previewElement: this.elements.previewContent,
376
+ toastController: this.toastController,
371
377
  });
372
378
  this.themeController = new ThemeController({ onChange: (theme) => this.handleThemeChange(theme) });
373
379
  this.layoutController = new LayoutController({
@@ -649,6 +655,7 @@ export class CollabMdAppShell {
649
655
  this.sessionLoadToken = value;
650
656
  },
651
657
  setSidebarTab: (value) => this.setSidebarTab(value),
658
+ setSidebarVisibility: (showSidebar) => this.setSidebarVisibility(showSidebar),
652
659
  showGitCommit: (route) => this.showGitCommit(route),
653
660
  showGitDiff: (route) => this.showGitDiff(route),
654
661
  showGitFileHistory: (route) => this.showGitFileHistory(route),
@@ -696,6 +703,8 @@ export class CollabMdAppShell {
696
703
  set gitRepoAvailable(value) { this.stateStore.set('gitRepoAvailable', value); }
697
704
  get activeSidebarTab() { return this.stateStore.get('activeSidebarTab'); }
698
705
  set activeSidebarTab(value) { this.stateStore.set('activeSidebarTab', value); }
706
+ get presencePanelOpen() { return this.stateStore.get('presencePanelOpen'); }
707
+ set presencePanelOpen(value) { this.stateStore.set('presencePanelOpen', value); }
699
708
  get followedUserClientId() { return this.stateStore.get('followedUserClientId'); }
700
709
  set followedUserClientId(value) { this.stateStore.set('followedUserClientId', value); }
701
710
  get followedCursorSignature() { return this.stateStore.get('followedCursorSignature'); }
@@ -1,10 +1,29 @@
1
1
  const DIAGRAM_ACTION_ICONS = {
2
+ copy: `
3
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
4
+ <path d="M5.5 5.5h6.8v8h-6.8z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
5
+ <path d="M3.7 10.5H3a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v.7" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
6
+ </svg>
7
+ `,
8
+ download: `
9
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
10
+ <path d="M8 2.2v7.2" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
11
+ <path d="M5.3 7.2 8 10l2.7-2.8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
12
+ <path d="M3 12.8h10" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
13
+ </svg>
14
+ `,
2
15
  edit: `
3
16
  <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
4
17
  <path d="M11.8 1.8a1.5 1.5 0 0 1 2.1 2.1l-7.2 7.2-3.2.9.9-3.2z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
5
18
  <path d="M10.7 2.9l2.4 2.4" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
6
19
  </svg>
7
20
  `,
21
+ fit: `
22
+ <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
23
+ <path d="M5.5 6.2V3H2.3M10.5 6.2V3h3.2M10.5 9.8V13h3.2M5.5 9.8V13H2.3" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
24
+ <path d="M5.5 6.2h5M5.5 9.8h5" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
25
+ </svg>
26
+ `,
8
27
  maximize: `
9
28
  <svg viewBox="0 0 16 16" aria-hidden="true" focusable="false">
10
29
  <path d="M6 2H2v4M10 2h4v4M14 10v4h-4M2 10v4h4" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4"/>
@@ -32,10 +51,12 @@ export function setDiagramActionButtonIcon(button, iconName) {
32
51
  const markup = DIAGRAM_ACTION_ICONS[iconName];
33
52
  if (!markup) {
34
53
  button.classList.remove('is-icon-only');
54
+ button.classList.remove('ui-preview-action--icon-only');
35
55
  return;
36
56
  }
37
57
 
38
58
  button.classList.add('is-icon-only');
59
+ button.classList.add('ui-preview-action--icon-only');
39
60
  button.dataset.icon = iconName;
40
61
  button.innerHTML = markup.trim();
41
62
  }
@@ -0,0 +1,70 @@
1
+ function normalizeBinaryFileVersion(value) {
2
+ return Number.isFinite(Number(value)) ? Number(value) : null;
3
+ }
4
+
5
+ function normalizeBinaryFileDataUrl(value) {
6
+ return typeof value === 'string' ? value : '';
7
+ }
8
+
9
+ export function hasBinaryFilePayloadConflict(currentFile, nextFile) {
10
+ return (
11
+ normalizeBinaryFileVersion(currentFile?.version) !== normalizeBinaryFileVersion(nextFile?.version)
12
+ || normalizeBinaryFileDataUrl(currentFile?.dataURL) !== normalizeBinaryFileDataUrl(nextFile?.dataURL)
13
+ );
14
+ }
15
+
16
+ export function buildExcalidrawFileSyncPlan(currentFiles = {}, nextFiles = {}) {
17
+ const missingFiles = [];
18
+ const conflictingFileIds = [];
19
+
20
+ Object.entries(nextFiles || {}).forEach(([fileId, nextFile]) => {
21
+ const currentFile = currentFiles?.[fileId];
22
+ if (!currentFile) {
23
+ missingFiles.push(nextFile);
24
+ return;
25
+ }
26
+
27
+ if (hasBinaryFilePayloadConflict(currentFile, nextFile)) {
28
+ conflictingFileIds.push(fileId);
29
+ }
30
+ });
31
+
32
+ return {
33
+ conflictingFileIds,
34
+ missingFiles,
35
+ requiresRemount: conflictingFileIds.length > 0,
36
+ };
37
+ }
38
+
39
+ export function applySceneUpdateWithFiles(api, {
40
+ captureUpdate,
41
+ files = {},
42
+ sceneUpdate,
43
+ } = {}, {
44
+ onFileConflict = () => {},
45
+ } = {}) {
46
+ const currentFiles = api?.getFiles?.() || {};
47
+ const syncPlan = buildExcalidrawFileSyncPlan(currentFiles, files);
48
+
49
+ if (syncPlan.requiresRemount) {
50
+ onFileConflict(syncPlan);
51
+ return {
52
+ ...syncPlan,
53
+ applied: false,
54
+ };
55
+ }
56
+
57
+ if (syncPlan.missingFiles.length > 0) {
58
+ api.addFiles(syncPlan.missingFiles);
59
+ }
60
+
61
+ api.updateScene({
62
+ ...sceneUpdate,
63
+ captureUpdate,
64
+ });
65
+
66
+ return {
67
+ ...syncPlan,
68
+ applied: true,
69
+ };
70
+ }