collabmd 0.1.34 → 0.1.35

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 (266) hide show
  1. package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-Bg0dawOb.js → CodeMirrorEditor-UCMRAMCV-CvLFeHXu.js} +1 -1
  2. package/dist/client/assets/_baseFor-Bfo4esZ5.js +1 -0
  3. package/dist/client/assets/arc-tRoMuWFi.js +1 -0
  4. package/dist/client/assets/architecture-YZFGNWBL-CtU43_5T.js +1 -0
  5. package/dist/client/assets/{architectureDiagram-2XIMDMQ5-kYbOThe4.js → architectureDiagram-Q4EWVU46-CVdcOotN.js} +4 -4
  6. package/dist/client/assets/blockDiagram-DXYQGD6D-B_gNUKQ4.js +132 -0
  7. package/dist/client/assets/c4Diagram-AHTNJAMY-BSDwfduG.js +10 -0
  8. package/dist/client/assets/channel-BDb1g_mJ.js +1 -0
  9. package/dist/client/assets/chunk-2KRD3SAO-C6u8y11R.js +1 -0
  10. package/dist/client/assets/chunk-336JU56O-Ch9X5KoM.js +2 -0
  11. package/dist/client/assets/{chunk-HHEYEP7N-DlevL8bq.js → chunk-426QAEUC-CwJ7loGf.js} +1 -1
  12. package/dist/client/assets/chunk-4TB4RGXK-BEsauZP5.js +206 -0
  13. package/dist/client/assets/chunk-5FUZZQ4R-6x8SlhH9.js +62 -0
  14. package/dist/client/assets/chunk-5PVQY5BW-R5SE6dhE.js +2 -0
  15. package/dist/client/assets/chunk-67CJDMHE-CjXw5hFa.js +1 -0
  16. package/dist/client/assets/chunk-7N4EOEYR-DNHyuswJ.js +1 -0
  17. package/dist/client/assets/chunk-AA7GKIK3-DayE4IF_.js +1 -0
  18. package/dist/client/assets/chunk-BSJP7CBP-CexlYBxB.js +1 -0
  19. package/dist/client/assets/chunk-CIAEETIT-CkDJ4DYI.js +1 -0
  20. package/dist/client/assets/{chunk-KX2RTZJC-BTiOJb7N.js → chunk-EDXVE4YY-BVR_nF3y.js} +1 -1
  21. package/dist/client/assets/chunk-ENJZ2VHE-CFVWytAB.js +10 -0
  22. package/dist/client/assets/chunk-FOC6F5B3-DzCiCLGs.js +1 -0
  23. package/dist/client/assets/chunk-ICPOFSXX-B9LPHgU7.js +122 -0
  24. package/dist/client/assets/chunk-K5T4RW27-kmGSebVE.js +94 -0
  25. package/dist/client/assets/chunk-KGLVRYIC-DVjPRsaR.js +1 -0
  26. package/dist/client/assets/chunk-LIHQZDEY-DKFj13sC.js +1 -0
  27. package/dist/client/assets/chunk-NU2UP6EN-UVL-wkIc.js +35 -0
  28. package/dist/client/assets/chunk-ORNJ4GCN-D0uTAC-5.js +1 -0
  29. package/dist/client/assets/{chunk-NQ4KR5QH-CMJKI6Oj.js → chunk-OYMX7WX6-nWiNHNyD.js} +25 -14
  30. package/dist/client/assets/{chunk-PU5JKC2W-D_6N6t8f.js → chunk-U2HBQHQK-Bue4Ufzn.js} +6 -6
  31. package/dist/client/assets/{chunk-PQ6SQG4A-D1AbThjy.js → chunk-X2U36JSP-CRE6lp7n.js} +1 -1
  32. package/dist/client/assets/{chunk-XPW4576I-DJr4_4Yy.js → chunk-XPW4576I-BL5M-tF8.js} +1 -1
  33. package/dist/client/assets/{chunk-JSJVCQXG-DPQ9cPJt.js → chunk-YZCP3GAM-D7Z5wUWA.js} +1 -1
  34. package/dist/client/assets/chunk-ZZ45TVLE-CBbl1Qec.js +1 -0
  35. package/dist/client/assets/classDiagram-6PBFFD2Q-MIbgV5UL.js +1 -0
  36. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Bb70vg2O.js +1 -0
  37. package/dist/client/assets/clike-BFTLRaGS.js +1 -0
  38. package/dist/client/assets/clone-D6JWrlxJ.js +1 -0
  39. package/dist/client/assets/{coffeescript-B_7eyHAa.js → coffeescript-B7GZajzV.js} +1 -1
  40. package/dist/client/assets/{cose-bilkent-S5V4N54A-DASO2hrk.js → cose-bilkent-S5V4N54A-xxgR5OJ-.js} +1 -1
  41. package/dist/client/assets/{cypher-DE6I2lIA.js → cypher-DEGl2llJ.js} +1 -1
  42. package/dist/client/assets/cytoscape.esm-B3PRdePO.js +321 -0
  43. package/dist/client/assets/{d-BNkKjn0o.js → d-BspB0dox.js} +1 -1
  44. package/dist/client/assets/dagre-KV5264BT-C2K9mFg1.js +4 -0
  45. package/dist/client/assets/dagre-VaFYRFbD.js +1 -0
  46. package/dist/client/assets/diagram-5BDNPKRD-DE0M0jaM.js +10 -0
  47. package/dist/client/assets/diagram-G4DWMVQ6-BfaRuSTT.js +24 -0
  48. package/dist/client/assets/diagram-MMDJMWI5-91Bly_hN.js +43 -0
  49. package/dist/client/assets/diagram-TYMM5635-fBkLwZGN.js +24 -0
  50. package/dist/client/assets/{dist-BzpfHRaE.js → dist-74GtnE06.js} +1 -1
  51. package/dist/client/assets/dist-B3lARV_e.js +1 -0
  52. package/dist/client/assets/{dist-O1z0Ayg0.js → dist-BCvzlTeb.js} +1 -1
  53. package/dist/client/assets/{dist-DsL7sqZR.js → dist-BMlUxhOz.js} +1 -1
  54. package/dist/client/assets/dist-BSED50tI.js +13 -0
  55. package/dist/client/assets/{dist-B-02vKOA.js → dist-Bkn7JaJv.js} +1 -1
  56. package/dist/client/assets/dist-Bq8Z0WUT.js +1 -0
  57. package/dist/client/assets/{dist-E_jPb93e.js → dist-Bzb9nPam.js} +1 -1
  58. package/dist/client/assets/{dist-CL-jjdvG.js → dist-C0e9kfNh.js} +1 -1
  59. package/dist/client/assets/dist-C8wdW7W4.js +1 -0
  60. package/dist/client/assets/dist-CDUQ5ELn.js +1 -0
  61. package/dist/client/assets/dist-CHSg_nUM.js +1 -0
  62. package/dist/client/assets/dist-CSAH9iuE.js +6 -0
  63. package/dist/client/assets/{dist-CxfohGIV.js → dist-CSNMpi-w.js} +1 -1
  64. package/dist/client/assets/dist-CZPTvk_g2.js +1 -0
  65. package/dist/client/assets/{dist-k47-Io7D.js → dist-Co8HE14w.js} +1 -1
  66. package/dist/client/assets/{dist-Bc2ND6i3.js → dist-CqU98NzX.js} +1 -1
  67. package/dist/client/assets/{dist-BzbYwa8m.js → dist-D0dQAc9b.js} +1 -1
  68. package/dist/client/assets/{dist-Dyt7n5Ui.js → dist-D1-dK0Dk.js} +1 -1
  69. package/dist/client/assets/{dist-B4uQVR_X.js → dist-DAKGEzm0.js} +1 -1
  70. package/dist/client/assets/dist-DBzteOlY.js +1 -0
  71. package/dist/client/assets/{dist-CjII8VDS.js → dist-DSRCADL9.js} +1 -1
  72. package/dist/client/assets/{dist-lDhnP-K1.js → dist-DdR2aYqj.js} +1 -1
  73. package/dist/client/assets/{dist-DUvaQ-Bj.js → dist-DidT3Jay.js} +1 -1
  74. package/dist/client/assets/dist-Doo91MTa.js +1 -0
  75. package/dist/client/assets/{dist-BLAlZer_.js → dist-Dwy75xI6.js} +1 -1
  76. package/dist/client/assets/{dist-3uAMa5w5.js → dist-FC9LftvP.js} +1 -1
  77. package/dist/client/assets/{dist-CGV1S_as.js → dist-PPAeaw4t.js} +1 -1
  78. package/dist/client/assets/{dist-BtnXjRx0.js → dist-VPEWg0Ob.js} +1 -1
  79. package/dist/client/assets/{dist-CXpKYW9s.js → dist-cQSK4Xor.js} +1 -1
  80. package/dist/client/assets/{dist-rMhng5DK.js → dist-r5I9Jgww.js} +1 -1
  81. package/dist/client/assets/drawio-editor-CWLEpwps.js +9 -0
  82. package/dist/client/assets/{drawioEditor-D6clB5OH.js → drawioEditor-5rJhxjA4.js} +2 -2
  83. package/dist/client/assets/{ecl-M7Iek4lq.js → ecl-D9rhJ9-u.js} +1 -1
  84. package/dist/client/assets/{editor-session-Dzy_85Wp.js → editor-session-CLOuvy37.js} +3 -3
  85. package/dist/client/assets/{erDiagram-INFDFZHY-DlIf-fb7.js → erDiagram-SMLLAGMA-DUQcqEQ1.js} +33 -18
  86. package/dist/client/assets/excalidraw-editor-ukEKPqGJ.js +9 -0
  87. package/dist/client/assets/{excalidraw-mermaid-stub-Bwe-bKcT.js → excalidraw-mermaid-stub-Df0Q2qkW.js} +1 -1
  88. package/dist/client/assets/excalidraw-scene-CDK3oDnm.js +176 -0
  89. package/dist/client/assets/excalidrawEditor-BJ8QLmWc.js +2 -0
  90. package/dist/client/assets/{export-page-PeexH2QK.js → export-page-D2rCmrUH.js} +2 -2
  91. package/dist/client/assets/exportDocument-Dunnjgii.js +2 -0
  92. package/dist/client/assets/{fcl-BWKK0S4-.js → fcl-CUXJFJn1.js} +1 -1
  93. package/dist/client/assets/flatten-CX_XvnUf.js +1 -0
  94. package/dist/client/assets/flowDiagram-DWJPFMVM-B_A5JyId.js +162 -0
  95. package/dist/client/assets/ganttDiagram-T4ZO3ILL-HM3CD7bk.js +292 -0
  96. package/dist/client/assets/gitGraph-7Q5UKJZL-BrBlB49D.js +1 -0
  97. package/dist/client/assets/gitGraphDiagram-UUTBAWPF-Dw7twZDm.js +106 -0
  98. package/dist/client/assets/graphlib-DDD4Vdye.js +1 -0
  99. package/dist/client/assets/{groovy-BEKazBrO.js → groovy-Di--Vb9Z.js} +1 -1
  100. package/dist/client/assets/{haxe-BY9d_5nB.js → haxe-CcPA1xnA.js} +1 -1
  101. package/dist/client/assets/image-XLNPCCAD-BFNybKza.js +1 -0
  102. package/dist/client/assets/{image-blob-reduce.esm-DriR2zT9.js → image-blob-reduce.esm-DiuPkovC.js} +1 -1
  103. package/dist/client/assets/{index-BLrtj9YM.js → index-BbziNMqE.js} +2 -2
  104. package/dist/client/assets/info-OMHHGYJF-BcmgcSx1.js +1 -0
  105. package/dist/client/assets/{infoDiagram-LFFYTUFH-DFTI0nfs.js → infoDiagram-42DDH7IO-DX-d3DMp.js} +1 -1
  106. package/dist/client/assets/isEmpty-BKDbo1FH.js +1 -0
  107. package/dist/client/assets/ishikawaDiagram-UXIWVN3A-BHmsxpMs.js +70 -0
  108. package/dist/client/assets/{javascript-CdiVhQeA.js → javascript-gTK9fxz6.js} +1 -1
  109. package/dist/client/assets/javascript-qUBHINSy.js +1 -0
  110. package/dist/client/assets/{journeyDiagram-4ABVD52K-DDur6iHm.js → journeyDiagram-VCZTEJTY-jxDSjgE1.js} +2 -2
  111. package/dist/client/assets/{jsx-runtime-C2p7wRmT.js → jsx-runtime-B_8UNt-W.js} +1 -1
  112. package/dist/client/assets/{kanban-definition-K7BYSVSG-dA6NPLsg.js → kanban-definition-6JOO6SKY-od3qY1mE.js} +2 -2
  113. package/dist/client/assets/line-CZsGUM4H.js +1 -0
  114. package/dist/client/assets/{lua-kutgyRGY.js → lua-Cg0FqIlO.js} +1 -1
  115. package/dist/client/assets/main-CN0kbtGk.js +1369 -0
  116. package/dist/client/assets/mermaid-parser.core-DtIbxv6L.js +4 -0
  117. package/dist/client/assets/mermaid-runtime-vVJfjscE.js +11 -0
  118. package/dist/client/assets/{mindmap-definition-YRQLILUH-DjQcsPoe.js → mindmap-definition-QFDTVHPH-C9qrdAqo.js} +39 -11
  119. package/dist/client/assets/packet-4T2RLAQJ-DYYSvRuJ.js +1 -0
  120. package/dist/client/assets/pica-BEurQXMu.js +2 -0
  121. package/dist/client/assets/pie-ZZUOXDRM-cG65Mc64.js +1 -0
  122. package/dist/client/assets/pieDiagram-DEJITSTG-BHXxj7wl.js +30 -0
  123. package/dist/client/assets/{preview-render-compiler-BjLlHmiQ.js → preview-render-compiler-BHeDhYho.js} +2 -2
  124. package/dist/client/assets/preview-render-compiler-D3QM1Ryz.js +1 -0
  125. package/dist/client/assets/{preview-render-profile-CR4dJZrp.js → preview-render-profile-BF6os3x9.js} +5 -5
  126. package/dist/client/assets/{preview-render-worker-B4dH2yxj.js → preview-render-worker-C4AFtMIr.js} +6 -6
  127. package/dist/client/assets/{pug-DkUcLYWt.js → pug-lkTEco3G.js} +1 -1
  128. package/dist/client/assets/{python-CZtTmYkS.js → python-BUyhM0Ew.js} +1 -1
  129. package/dist/client/assets/{q-I27iQntV.js → q-Dls1OX0D.js} +1 -1
  130. package/dist/client/assets/{quadrantDiagram-337W2JSQ-CYKgdx7K.js → quadrantDiagram-34T5L4WZ-CWW7LORF.js} +1 -1
  131. package/dist/client/assets/{quick-switcher-controller-DcyllYpm.js → quick-switcher-controller-B1erSgJ1.js} +1 -1
  132. package/dist/client/assets/{r-DN_EydfL.js → r-DeZ8Mdev.js} +1 -1
  133. package/dist/client/assets/radar-PYXPWWZC-Bmpup_xw.js +1 -0
  134. package/dist/client/assets/reduce-C6FuFJbE.js +1 -0
  135. package/dist/client/assets/requirementDiagram-MS252O5E-CTljNdQH.js +84 -0
  136. package/dist/client/assets/{room-yJaBAoEU.js → room-DI7DXGeS.js} +1 -1
  137. package/dist/client/assets/{sankeyDiagram-WA2Y5GQK-CfHe3D6R.js → sankeyDiagram-XADWPNL6-CCfFkC74.js} +1 -1
  138. package/dist/client/assets/sequenceDiagram-FGHM5R23-BD9vj6WG.js +157 -0
  139. package/dist/client/assets/{sparql-BOvq0dv7.js → sparql-vm8qNO8J.js} +1 -1
  140. package/dist/client/assets/sql-GL7dVWcd.js +1 -0
  141. package/dist/client/assets/stateDiagram-FHFEXIEX-CpiX3KPd.js +1 -0
  142. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-D_5ufPqT.js +1 -0
  143. package/dist/client/assets/{swift-BCxe4-cw.js → swift-CKcKnWv9.js} +1 -1
  144. package/dist/client/assets/timeline-definition-GMOUNBTQ-BafRAkSF.js +120 -0
  145. package/dist/client/assets/treeView-SZITEDCU-NbjhK5cw.js +1 -0
  146. package/dist/client/assets/treemap-W4RFUUIX-DJzRbb-x.js +1 -0
  147. package/dist/client/assets/{turtle-GBz_E4RG.js → turtle-BkP3ExOG.js} +1 -1
  148. package/dist/client/assets/{vault-api-client-p7h7cXKM.js → vault-api-client-DSx3mWkH.js} +1 -1
  149. package/dist/client/assets/{vault-utils-5Xr0MXCb.js → vault-utils-CRpy8MQz.js} +1 -1
  150. package/dist/client/assets/vennDiagram-DHZGUBPP-DSngq_Zj.js +34 -0
  151. package/dist/client/assets/{verilog-C4wTycyo.js → verilog-DSARZZPc.js} +1 -1
  152. package/dist/client/assets/{vhdl-Bwndeg44.js → vhdl-CnYyYTpa.js} +1 -1
  153. package/dist/client/assets/wardley-RL74JXVD-DTNoH_BY.js +1 -0
  154. package/dist/client/assets/wardleyDiagram-NUSXRM2D-CAEd2kJG.js +20 -0
  155. package/dist/client/assets/{xychartDiagram-JWTSCODW-C3vA70iJ.js → xychartDiagram-5P7HB3ND-BScQpnru.js} +6 -6
  156. package/dist/client/assets/{yjs-provider-reset-guard-CtERLBID.js → yjs-provider-reset-guard-_Q3mj6tP.js} +1 -1
  157. package/dist/client/drawio-editor.html +1 -1
  158. package/dist/client/excalidraw-editor.html +1 -1
  159. package/dist/client/export-document.html +1 -1
  160. package/dist/client/index.html +1 -1
  161. package/package.json +11 -11
  162. package/src/client/application/app-shell/ui-feature-shell.js +5 -2
  163. package/src/client/application/quick-switcher-loader.js +39 -0
  164. package/src/client/bootstrap/collabmd-app-shell.js +16 -20
  165. package/src/client/domain/keyboard-shortcuts.js +8 -0
  166. package/src/client/drawio-editor.js +13 -0
  167. package/src/client/excalidraw-editor.js +13 -0
  168. package/src/client/infrastructure/excalidraw-room-client.js +1 -1
  169. package/src/client/infrastructure/workspace-sync-client.js +26 -3
  170. package/src/client/presentation/comment-ui/comment-ui-card.js +83 -3
  171. package/src/client/presentation/comment-ui/comment-ui-state.js +25 -2
  172. package/src/client/presentation/drawio-embed-controller.js +18 -0
  173. package/src/client/presentation/excalidraw-embed-controller.js +7 -0
  174. package/src/client/presentation/git-panel-controller.js +2 -0
  175. package/src/server/domain/backlink-index.js +33 -72
  176. package/src/server/domain/bases/base-index-snapshot-store.js +46 -62
  177. package/src/server/domain/markdown-reference-extractor.js +233 -0
  178. package/src/server/infrastructure/persistence/vault-file-store.js +39 -4
  179. package/src/server/infrastructure/workspace/file-system-sync-service.js +37 -11
  180. package/dist/client/assets/_basePickBy-Dv0sK1l7.js +0 -1
  181. package/dist/client/assets/_baseUniq-DKYX57ji.js +0 -1
  182. package/dist/client/assets/arc-DrfYGhWk.js +0 -1
  183. package/dist/client/assets/architecture-PBZL5I3N-DiglIZi9.js +0 -1
  184. package/dist/client/assets/blockDiagram-WCTKOSBZ-GIgTqnhk.js +0 -132
  185. package/dist/client/assets/c4Diagram-IC4MRINW-CkHO1i_L.js +0 -10
  186. package/dist/client/assets/channel-CgsU9TSN.js +0 -1
  187. package/dist/client/assets/chunk-7E7YKBS2-TdU92i9i.js +0 -1
  188. package/dist/client/assets/chunk-7R4GIKGN-mqd2GwMg.js +0 -80
  189. package/dist/client/assets/chunk-C72U2L5F-CJKQWBtz.js +0 -1
  190. package/dist/client/assets/chunk-EGIJ26TM-C4nq20om.js +0 -1
  191. package/dist/client/assets/chunk-GEFDOKGD-Bs7FmFox.js +0 -2
  192. package/dist/client/assets/chunk-GLR3WWYH-qQe2O5VQ.js +0 -2
  193. package/dist/client/assets/chunk-KYZI473N-CTSCuqRb.js +0 -53
  194. package/dist/client/assets/chunk-L3YUKLVL-CJZMBtKF.js +0 -1
  195. package/dist/client/assets/chunk-MX3YWQON-DQpSwRf6.js +0 -1
  196. package/dist/client/assets/chunk-NU2UP6EN-DlUENSHU.js +0 -35
  197. package/dist/client/assets/chunk-O4XLMI2P-CcVxZh41.js +0 -7
  198. package/dist/client/assets/chunk-OZEHJAEY-DjBZbgu0.js +0 -1
  199. package/dist/client/assets/chunk-R5LLSJPH-CkjKXM73.js +0 -1
  200. package/dist/client/assets/chunk-WL4C6EOR-axcuKSup.js +0 -189
  201. package/dist/client/assets/chunk-XIRO2GV7-4wqVHjs_.js +0 -1
  202. package/dist/client/assets/chunk-XZSTWKYB-C8Y_hIKZ.js +0 -94
  203. package/dist/client/assets/chunk-YBOYWFTD-CKg4ymFF.js +0 -1
  204. package/dist/client/assets/classDiagram-VBA2DB6C-BHZpvOxK.js +0 -1
  205. package/dist/client/assets/classDiagram-v2-RAHNMMFH-DA7HMUUs.js +0 -1
  206. package/dist/client/assets/clike-1_ZsiVV8.js +0 -1
  207. package/dist/client/assets/clone-Dgi8Z4IL.js +0 -1
  208. package/dist/client/assets/cytoscape.esm-Czjc507F.js +0 -321
  209. package/dist/client/assets/dagre-CfB3Fw33.js +0 -1
  210. package/dist/client/assets/dagre-KLK3FWXG-CC7tq2Ky.js +0 -4
  211. package/dist/client/assets/diagram-E7M64L7V-CMt7BN5M.js +0 -24
  212. package/dist/client/assets/diagram-IFDJBPK2-BFMBUGpd.js +0 -43
  213. package/dist/client/assets/diagram-P4PSJMXO-CviA1xXr.js +0 -24
  214. package/dist/client/assets/dist-3bQB_we3.js +0 -1
  215. package/dist/client/assets/dist-8Igu3Ee_2.js +0 -1
  216. package/dist/client/assets/dist-BU8uusJX.js +0 -1
  217. package/dist/client/assets/dist-BVB8rn7o.js +0 -1
  218. package/dist/client/assets/dist-D5QOYy7y.js +0 -6
  219. package/dist/client/assets/dist-DIi0uqLJ.js +0 -1
  220. package/dist/client/assets/dist-DJ16N7ol.js +0 -1
  221. package/dist/client/assets/dist-DWJL3_bF.js +0 -13
  222. package/dist/client/assets/dist-OQE68wIX.js +0 -1
  223. package/dist/client/assets/dist-x7PIEmJu.js +0 -1
  224. package/dist/client/assets/drawio-editor-BMTwP5mD.js +0 -9
  225. package/dist/client/assets/excalidraw-editor-CAP9F8CB.js +0 -9
  226. package/dist/client/assets/excalidraw-scene-BF_bT1OL.js +0 -176
  227. package/dist/client/assets/excalidrawEditor-DD4AvzYP.js +0 -2
  228. package/dist/client/assets/exportDocument-Zfwq1XVx.js +0 -2
  229. package/dist/client/assets/flowDiagram-PKNHOUZH-C_t-mkwb.js +0 -162
  230. package/dist/client/assets/ganttDiagram-A5KZAMGK-BtK9Tb--.js +0 -292
  231. package/dist/client/assets/gitGraph-HDMCJU4V-CT7YfbD3.js +0 -1
  232. package/dist/client/assets/gitGraphDiagram-K3NZZRJ6-DULDLGiJ.js +0 -65
  233. package/dist/client/assets/graphlib-BgRST-Qg.js +0 -1
  234. package/dist/client/assets/image-XLNPCCAD-CFiKwiWK.js +0 -1
  235. package/dist/client/assets/info-3K5VOQVL-DUpNyDC-.js +0 -1
  236. package/dist/client/assets/isArrayLikeObject-BId_dPHM.js +0 -1
  237. package/dist/client/assets/isEmpty-CVvRj8fj.js +0 -1
  238. package/dist/client/assets/ishikawaDiagram-PHBUUO56-DpBuDpC6.js +0 -70
  239. package/dist/client/assets/javascript-UJe68_xi.js +0 -1
  240. package/dist/client/assets/line-B2GMovaI.js +0 -1
  241. package/dist/client/assets/main-CfSHaGes.js +0 -1368
  242. package/dist/client/assets/math-B-LMBwub.js +0 -1
  243. package/dist/client/assets/mermaid-parser.core-B1ogGcR8.js +0 -4
  244. package/dist/client/assets/mermaid-runtime-Bn8A6DGx.js +0 -11
  245. package/dist/client/assets/packet-RMMSAZCW-DEwNbIrA.js +0 -1
  246. package/dist/client/assets/pica-C1TdTz-C.js +0 -2
  247. package/dist/client/assets/pie-UPGHQEXC-D5M_lSjo.js +0 -1
  248. package/dist/client/assets/pieDiagram-SKSYHLDU-jhHouFpk.js +0 -30
  249. package/dist/client/assets/preview-render-compiler-Duy_3IcP.js +0 -1
  250. package/dist/client/assets/radar-KQ55EAFF-AU1qh3Bw.js +0 -1
  251. package/dist/client/assets/requirementDiagram-Z7DCOOCP-D9SHxoW7.js +0 -73
  252. package/dist/client/assets/sequenceDiagram-2WXFIKYE-CZsMMqAJ.js +0 -145
  253. package/dist/client/assets/sql-DDFeQNTK.js +0 -1
  254. package/dist/client/assets/stateDiagram-RAJIS63D-CoNZjTYV.js +0 -1
  255. package/dist/client/assets/stateDiagram-v2-FVOUBMTO-1zOw6NmQ.js +0 -1
  256. package/dist/client/assets/timeline-definition-YZTLITO2-DSe2mrG8.js +0 -61
  257. package/dist/client/assets/treemap-KZPCXAKY-C9UI2fwP.js +0 -1
  258. package/dist/client/assets/vennDiagram-LZ73GAT5-xSzaIpy1.js +0 -34
  259. /package/dist/client/assets/{chunk-55IACEB6-CpncB3ru.js → chunk-55IACEB6-DLqevMSj.js} +0 -0
  260. /package/dist/client/assets/{chunk-QZHKN3VN-CgLPFSk5.js → chunk-QZHKN3VN-BnOS2iQW.js} +0 -0
  261. /package/dist/client/assets/{drawio-room-DEivFyNV.js → drawio-room-1i6Nn0_Z.js} +0 -0
  262. /package/dist/client/assets/{excalidraw-mermaid-stub-BZPU4ZhU.js → excalidraw-mermaid-stub-DzxtBcQW.js} +0 -0
  263. /package/dist/client/assets/{file-kind-DBptLlF_.js → file-kind-DmKq2MvD.js} +0 -0
  264. /package/dist/client/assets/{preview-diagram-utils-COt-IYMD.js → preview-diagram-utils-D8VypUft.js} +0 -0
  265. /package/dist/client/assets/{rough.esm-DE_lJ5Ge.js → rough.esm-BU2knLt9.js} +0 -0
  266. /package/dist/client/assets/{runtime-config-CqhchMC4.js → runtime-config-DWTejofP.js} +0 -0
@@ -15,7 +15,7 @@
15
15
  document.documentElement.setAttribute('data-initial-file-requested', 'true');
16
16
  }
17
17
  </script>
18
- <script type="module" crossorigin src="./assets/index-BLrtj9YM.js"></script>
18
+ <script type="module" crossorigin src="./assets/index-BbziNMqE.js"></script>
19
19
  <link rel="modulepreload" crossorigin href="./assets/runtime-config-loader-_D2KZKn-.js">
20
20
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-Bo9GmnuQ.js">
21
21
  <link rel="modulepreload" crossorigin href="./assets/base-h1uscjTi.js">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "collabmd",
3
- "version": "0.1.34",
3
+ "version": "0.1.35",
4
4
  "type": "module",
5
5
  "description": "Collaborative markdown vault — like Obsidian, but online. Serve any directory of markdown files for realtime collaborative editing.",
6
6
  "repository": {
@@ -69,7 +69,7 @@
69
69
  "@codemirror/search": "^6.6.0",
70
70
  "@codemirror/state": "^6.6.0",
71
71
  "@codemirror/theme-one-dark": "^6.1.3",
72
- "@codemirror/view": "^6.40.0",
72
+ "@codemirror/view": "^6.41.0",
73
73
  "@excalidraw/excalidraw": "0.18.0-4a5c9e9",
74
74
  "@fontsource-variable/inter": "^5.2.8",
75
75
  "@fontsource/jetbrains-mono": "^5.2.8",
@@ -80,10 +80,10 @@
80
80
  "lib0": "^0.2.117",
81
81
  "lit-html": "^3.3.2",
82
82
  "markdown-it": "^14.1.1",
83
- "mermaid": "^11.13.0",
83
+ "mermaid": "^11.14.0",
84
84
  "openid-client": "^6.8.2",
85
- "react": "^19.2.4",
86
- "react-dom": "^19.2.4",
85
+ "react": "^19.2.5",
86
+ "react-dom": "^19.2.5",
87
87
  "sharp": "^0.34.5",
88
88
  "ws": "^8.20.0",
89
89
  "y-codemirror.next": "^0.3.5",
@@ -98,12 +98,12 @@
98
98
  },
99
99
  "devDependencies": {
100
100
  "@eslint/js": "^10.0.1",
101
- "@playwright/test": "^1.58.2",
102
- "@vitest/browser": "^4.1.2",
103
- "@vitest/browser-playwright": "^4.1.2",
104
- "eslint": "^10.1.0",
101
+ "@playwright/test": "^1.59.1",
102
+ "@vitest/browser": "^4.1.4",
103
+ "@vitest/browser-playwright": "^4.1.4",
104
+ "eslint": "^10.2.0",
105
105
  "globals": "^17.4.0",
106
- "vite": "^8.0.3",
107
- "vitest": "^4.1.2"
106
+ "vite": "^8.0.8",
107
+ "vitest": "^4.1.4"
108
108
  }
109
109
  }
@@ -1,4 +1,5 @@
1
1
  import { supportsBacklinksForFilePath } from '../../../domain/file-kind.js';
2
+ import { isPlainQuickSwitcherShortcut } from '../../domain/keyboard-shortcuts.js';
2
3
 
3
4
  const VERSION_RELOAD_TOAST_DURATION_MS = 0;
4
5
 
@@ -313,7 +314,7 @@ function bindEvents() {
313
314
 
314
315
  document.addEventListener('keydown', (event) => {
315
316
  this.handleDocumentKeydown(event);
316
- });
317
+ }, { capture: true });
317
318
  }
318
319
 
319
320
  /** @this {UiShellContext} */
@@ -351,8 +352,9 @@ function handleDocumentKeydown(event) {
351
352
  return;
352
353
  }
353
354
 
354
- if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
355
+ if (isPlainQuickSwitcherShortcut(event)) {
355
356
  event.preventDefault();
357
+ event.stopPropagation();
356
358
  void this.toggleQuickSwitcher();
357
359
  }
358
360
  }
@@ -548,6 +550,7 @@ export const uiFeatureShellMethods = {
548
550
  initialize,
549
551
  initializeVisualViewportBinding,
550
552
  initializeVersionMonitoring,
553
+ isPlainQuickSwitcherShortcut,
551
554
  promptForVersionReload,
552
555
  scheduleBacklinkRefresh,
553
556
  setToolbarOverflowOpen,
@@ -0,0 +1,39 @@
1
+ export async function ensureQuickSwitcherInstance(host) {
2
+ if (host.quickSwitcher) {
3
+ return host.quickSwitcher;
4
+ }
5
+
6
+ if (!host.quickSwitcherModulePromise) {
7
+ host.quickSwitcherModulePromise = host.loadQuickSwitcherController();
8
+ }
9
+
10
+ let QuickSwitcherController;
11
+ try {
12
+ QuickSwitcherController = await host.quickSwitcherModulePromise;
13
+ } catch (error) {
14
+ host.quickSwitcherModulePromise = null;
15
+ console.error('[quick-switcher] Failed to load file search.', error);
16
+ host.toastController?.show?.('Failed to load file search. Try again.', {
17
+ dismissible: true,
18
+ });
19
+ throw error;
20
+ }
21
+
22
+ if (!host.quickSwitcher) {
23
+ host.quickSwitcher = new QuickSwitcherController({
24
+ getFileList: () => host.fileExplorer.flatFiles,
25
+ onFileSelect: (filePath) => host.handleFileSelection(filePath, { closeSidebarOnMobile: true }),
26
+ });
27
+ }
28
+
29
+ return host.quickSwitcher;
30
+ }
31
+
32
+ export async function toggleQuickSwitcherInstance(host) {
33
+ try {
34
+ const quickSwitcher = await ensureQuickSwitcherInstance(host);
35
+ quickSwitcher.toggle();
36
+ } catch {
37
+ // ensureQuickSwitcherInstance reports the load failure and resets the cached import.
38
+ }
39
+ }
@@ -1,4 +1,5 @@
1
1
  import { PreviewRenderer } from '../application/preview-renderer.js';
2
+ import { ensureQuickSwitcherInstance, toggleQuickSwitcherInstance } from '../application/quick-switcher-loader.js';
2
3
  import { WorkspaceRouteController } from '../application/workspace-route-controller.js';
3
4
  import { WikiLinkFileController } from '../application/wiki-link-file-controller.js';
4
5
  import { WorkspacePreviewController } from '../application/workspace-preview-controller.js';
@@ -112,6 +113,8 @@ export class CollabMdAppShell {
112
113
  closeToolbarOverflowMenu(...args) { return uiFeature.closeToolbarOverflowMenu.apply(this, args); }
113
114
  getStoredLineWrapping(...args) { return uiFeature.getStoredLineWrapping.apply(this, args); }
114
115
  handleConnectionChange(...args) { return uiFeature.handleConnectionChange.apply(this, args); }
116
+ handleDocumentKeydown(...args) { return uiFeature.handleDocumentKeydown.apply(this, args); }
117
+ handleDocumentPointerDown(...args) { return uiFeature.handleDocumentPointerDown.apply(this, args); }
115
118
  handlePreviewContentClick(...args) { return uiFeature.handlePreviewContentClick.apply(this, args); }
116
119
  handleThemeChange(...args) { return uiFeature.handleThemeChange.apply(this, args); }
117
120
  hideEditorLoading(...args) { return uiFeature.hideEditorLoading.apply(this, args); }
@@ -390,6 +393,9 @@ export class CollabMdAppShell {
390
393
  getLocalUser: () => this.lobby.getLocalUser(),
391
394
  getTheme: () => this.themeController.getTheme(),
392
395
  onOpenFile: (filePath) => filePath && this.navigation.navigateToFile(filePath),
396
+ onToggleQuickSwitcher: () => {
397
+ void this.toggleQuickSwitcher();
398
+ },
393
399
  previewContainer: this.elements.previewContainer,
394
400
  previewElement: this.elements.previewContent,
395
401
  toastController: this.toastController,
@@ -399,6 +405,9 @@ export class CollabMdAppShell {
399
405
  getTheme: () => this.themeController.getTheme(),
400
406
  onOpenFile: (filePath) => filePath && this.navigation.navigateToFile(filePath),
401
407
  onOpenTextFile: (filePath) => filePath && this.navigation.navigateToFile(filePath, { drawioMode: 'text' }),
408
+ onToggleQuickSwitcher: () => {
409
+ void this.toggleQuickSwitcher();
410
+ },
402
411
  previewContainer: this.elements.previewContainer,
403
412
  previewElement: this.elements.previewContent,
404
413
  toastController: this.toastController,
@@ -771,29 +780,16 @@ export class CollabMdAppShell {
771
780
  this._editorSessionPrewarmHandle = window.setTimeout(runPrewarm, 0);
772
781
  }
773
782
 
774
- async ensureQuickSwitcher() {
775
- if (this.quickSwitcher) {
776
- return this.quickSwitcher;
777
- }
778
-
779
- if (!this.quickSwitcherModulePromise) {
780
- this.quickSwitcherModulePromise = import('../presentation/quick-switcher-controller.js')
781
- .then((module) => module.QuickSwitcherController);
782
- }
783
-
784
- const QuickSwitcherController = await this.quickSwitcherModulePromise;
785
- if (!this.quickSwitcher) {
786
- this.quickSwitcher = new QuickSwitcherController({
787
- getFileList: () => this.fileExplorer.flatFiles,
788
- onFileSelect: (filePath) => this.handleFileSelection(filePath, { closeSidebarOnMobile: true }),
789
- });
790
- }
783
+ loadQuickSwitcherController() {
784
+ return import('../presentation/quick-switcher-controller.js')
785
+ .then((module) => module.QuickSwitcherController);
786
+ }
791
787
 
792
- return this.quickSwitcher;
788
+ async ensureQuickSwitcher() {
789
+ return ensureQuickSwitcherInstance(this);
793
790
  }
794
791
 
795
792
  async toggleQuickSwitcher() {
796
- const quickSwitcher = await this.ensureQuickSwitcher();
797
- quickSwitcher.toggle();
793
+ return toggleQuickSwitcherInstance(this);
798
794
  }
799
795
  }
@@ -0,0 +1,8 @@
1
+ export function isPlainQuickSwitcherShortcut(event) {
2
+ if (!event || event.repeat || (!event.metaKey && !event.ctrlKey) || event.shiftKey || event.altKey) {
3
+ return false;
4
+ }
5
+
6
+ const key = String(event.key ?? '').toLowerCase();
7
+ return key === 'k' || event.code === 'KeyK';
8
+ }
@@ -2,6 +2,7 @@ import './styles/surfaces/embedded-editor-base.css';
2
2
  import './styles/surfaces/drawio-editor.css';
3
3
 
4
4
  import { ensureClientAuthenticated } from './infrastructure/auth-client.js';
5
+ import { isPlainQuickSwitcherShortcut } from './domain/keyboard-shortcuts.js';
5
6
  import { DrawioLeaseClient } from './infrastructure/drawio-lease-client.js';
6
7
  import { getRuntimeConfig } from './infrastructure/runtime-config.js';
7
8
  import { vaultApiClient } from './infrastructure/vault-api-client.js';
@@ -76,6 +77,16 @@ function postToParent(type, payload = {}) {
76
77
  window.parent.postMessage({ source: 'drawio-editor', instanceId, type, ...payload }, parentOrigin);
77
78
  }
78
79
 
80
+ function handleQuickSwitcherKeyDown(event) {
81
+ if (!isPlainQuickSwitcherShortcut(event)) {
82
+ return;
83
+ }
84
+
85
+ event.preventDefault();
86
+ event.stopPropagation();
87
+ postToParent('request-toggle-quick-switcher');
88
+ }
89
+
79
90
  function parseMessagePayload(rawValue) {
80
91
  if (typeof rawValue === 'string') {
81
92
  try {
@@ -418,6 +429,8 @@ async function claimEdit() {
418
429
  drawioLeaseClient.tryAcquireLease();
419
430
  }
420
431
 
432
+ window.addEventListener('keydown', handleQuickSwitcherKeyDown, { capture: true });
433
+
421
434
  async function init() {
422
435
  setBodyTheme(currentTheme);
423
436
 
@@ -24,6 +24,7 @@ import {
24
24
  import {
25
25
  normalizeDocumentMode,
26
26
  } from './domain/excalidraw-document-switch.js';
27
+ import { isPlainQuickSwitcherShortcut } from './domain/keyboard-shortcuts.js';
27
28
  import { ensureClientAuthenticated } from './infrastructure/auth-client.js';
28
29
  import { ExcalidrawRoomClient } from './infrastructure/excalidraw-room-client.js';
29
30
  import { vaultApiClient } from './infrastructure/vault-api-client.js';
@@ -440,6 +441,16 @@ function postToParent(type, payload = {}) {
440
441
  window.parent.postMessage({ source: 'excalidraw-editor', type, ...payload }, parentOrigin);
441
442
  }
442
443
 
444
+ function handleQuickSwitcherKeyDown(event) {
445
+ if (!isPlainQuickSwitcherShortcut(event)) {
446
+ return;
447
+ }
448
+
449
+ event.preventDefault();
450
+ event.stopPropagation();
451
+ postToParent('request-toggle-quick-switcher');
452
+ }
453
+
443
454
  function getSceneElementsForPreviewFit() {
444
455
  return (
445
456
  excalidrawAPI?.getSceneElementsIncludingDeleted?.()
@@ -757,6 +768,8 @@ function handleEditorMount({ excalidrawAPI: api }) {
757
768
  excalidrawAPI = api;
758
769
  }
759
770
 
771
+ window.addEventListener('keydown', handleQuickSwitcherKeyDown, { capture: true });
772
+
760
773
  async function init() {
761
774
  const loadingElement = document.getElementById('loadingState');
762
775
 
@@ -210,7 +210,7 @@ export class ExcalidrawRoomClient {
210
210
  let initialJson = this.getStructuredSceneJson();
211
211
  let usedApiFallback = false;
212
212
  if (!initialJson) {
213
- const sceneFromApi = await this.loadSceneFromApi();
213
+ const sceneFromApi = await this.loadSceneFromApi({ createIfMissing: false });
214
214
  const syncedJson = this.getStructuredSceneJson();
215
215
  if (syncedJson) {
216
216
  initialJson = syncedJson;
@@ -6,6 +6,29 @@ import { WORKSPACE_ROOM_NAME } from '../../domain/workspace-room.js';
6
6
  import { resolveWsBaseUrl } from '../domain/runtime-paths.js';
7
7
  import { stopReconnectOnControlledClose } from './yjs-provider-reset-guard.js';
8
8
 
9
+ function normalizeWorkspacePath(pathValue = '') {
10
+ return String(pathValue ?? '')
11
+ .trim()
12
+ .replace(/\\/g, '/')
13
+ .split('/')
14
+ .filter(Boolean)
15
+ .join('/');
16
+ }
17
+
18
+ function getParentDirectoryPath(pathValue = '') {
19
+ const normalizedPath = normalizeWorkspacePath(pathValue);
20
+ if (!normalizedPath) {
21
+ return '';
22
+ }
23
+
24
+ const separatorIndex = normalizedPath.lastIndexOf('/');
25
+ return separatorIndex >= 0 ? normalizedPath.slice(0, separatorIndex) : '';
26
+ }
27
+
28
+ function getEntryParentPath(entry = {}) {
29
+ return getParentDirectoryPath(entry?.path ?? '');
30
+ }
31
+
9
32
  function createNode(entry) {
10
33
  if (!entry?.path || !entry?.type) {
11
34
  return null;
@@ -87,7 +110,7 @@ class WorkspaceTreeModel {
87
110
  sortPathsByDepth(Array.from(this.nodesByPath.keys())).forEach((pathValue) => {
88
111
  const node = this.nodesByPath.get(pathValue);
89
112
  if (node) {
90
- this.attachNode(pathValue, node, this.entriesByPath.get(pathValue)?.parentPath || '');
113
+ this.attachNode(pathValue, node, getEntryParentPath(this.entriesByPath.get(pathValue)));
91
114
  }
92
115
  });
93
116
 
@@ -170,7 +193,7 @@ class WorkspaceTreeModel {
170
193
  }
171
194
 
172
195
  this.entriesByPath.set(pathValue, entry);
173
- this.attachNode(pathValue, node, entry.parentPath || '');
196
+ this.attachNode(pathValue, node, getEntryParentPath(entry));
174
197
 
175
198
  if (node.type === 'directory') {
176
199
  this.rehomeChildren(pathValue);
@@ -214,7 +237,7 @@ class WorkspaceTreeModel {
214
237
 
215
238
  rehomeChildren(parentPath) {
216
239
  this.entriesByPath.forEach((entry, pathValue) => {
217
- if (entry?.parentPath !== parentPath) {
240
+ if (getEntryParentPath(entry) !== parentPath) {
218
241
  return;
219
242
  }
220
243
 
@@ -43,6 +43,7 @@ function openComposerForSelection(origin = 'editor', sourceRect = null) {
43
43
  : this.session?.getCommentAnchorClientRect?.(anchor));
44
44
  this.activeCard = {
45
45
  anchor,
46
+ composerDraft: null,
46
47
  mode: 'create',
47
48
  origin: nextOrigin,
48
49
  replyThreadId: null,
@@ -57,8 +58,10 @@ function openThreadGroup(group, { anchor, origin, sourceRect }) {
57
58
  this.activeCard = {
58
59
  anchor,
59
60
  groupKey: group.key,
61
+ groupThreadIds: group.threads.map((thread) => thread.id),
60
62
  mode: 'group',
61
63
  origin,
64
+ replyDrafts: {},
62
65
  replyThreadId: null,
63
66
  sourceRect,
64
67
  };
@@ -97,9 +100,59 @@ function updateCardSourceRect() {
97
100
  return this.activeCard.sourceRect;
98
101
  }
99
102
 
103
+ /** @this {any} */
104
+ function createTextareaDraft(textarea) {
105
+ if (!(textarea instanceof HTMLTextAreaElement)) {
106
+ return null;
107
+ }
108
+
109
+ return {
110
+ selectionDirection: textarea.selectionDirection ?? 'none',
111
+ selectionEnd: textarea.selectionEnd,
112
+ selectionStart: textarea.selectionStart,
113
+ value: textarea.value,
114
+ };
115
+ }
116
+
117
+ /** @this {any} */
118
+ function captureActiveCardDraft() {
119
+ if (!this.activeCard) {
120
+ return;
121
+ }
122
+
123
+ const textarea = this.cardRoot?.querySelector('.comment-card-input');
124
+ const draft = createTextareaDraft(textarea);
125
+ if (!draft) {
126
+ return;
127
+ }
128
+
129
+ if (this.activeCard.mode === 'create') {
130
+ this.activeCard.composerDraft = draft;
131
+ return;
132
+ }
133
+
134
+ if (this.activeCard.mode === 'group' && this.activeCard.replyThreadId) {
135
+ this.activeCard.replyDrafts = {
136
+ ...(this.activeCard.replyDrafts ?? {}),
137
+ [this.activeCard.replyThreadId]: draft,
138
+ };
139
+ }
140
+ }
141
+
142
+ /** @this {any} */
143
+ function createPendingFocusTarget(element, draft = null) {
144
+ return {
145
+ element,
146
+ selectionDirection: draft?.selectionDirection ?? 'none',
147
+ selectionEnd: Number.isInteger(draft?.selectionEnd) ? draft.selectionEnd : null,
148
+ selectionStart: Number.isInteger(draft?.selectionStart) ? draft.selectionStart : null,
149
+ };
150
+ }
151
+
100
152
  /** @this {any} */
101
153
  function renderCard() {
102
154
  const root = this.ensureCardRoot();
155
+ this.captureActiveCardDraft();
103
156
  root.replaceChildren();
104
157
  root.classList.toggle('hidden', !this.activeCard);
105
158
  if (!this.activeCard) {
@@ -245,6 +298,7 @@ function createComposer() {
245
298
  textarea.rows = 4;
246
299
  textarea.maxLength = COMMENT_BODY_MAX_LENGTH;
247
300
  textarea.placeholder = 'Add context, feedback, or a question...';
301
+ textarea.value = this.activeCard?.composerDraft?.value ?? '';
248
302
 
249
303
  const actions = document.createElement('div');
250
304
  actions.className = 'ui-record-actions comment-card-actions';
@@ -277,7 +331,7 @@ function createComposer() {
277
331
  this.closeCard();
278
332
  });
279
333
 
280
- this.pendingCardFocusElement = textarea;
334
+ this.pendingCardFocusElement = createPendingFocusTarget(textarea, this.activeCard?.composerDraft);
281
335
  return form;
282
336
  }
283
337
 
@@ -329,6 +383,9 @@ function createThreadElement(thread) {
329
383
  reply.setAttribute('aria-label', isReplying ? 'Cancel reply' : 'Reply to thread');
330
384
  reply.title = isReplying ? 'Cancel reply' : 'Reply to thread';
331
385
  reply.addEventListener('click', () => {
386
+ if (isReplying && this.activeCard?.replyDrafts?.[thread.id]) {
387
+ delete this.activeCard.replyDrafts[thread.id];
388
+ }
332
389
  this.activeCard = {
333
390
  ...this.activeCard,
334
391
  replyThreadId: isReplying ? null : thread.id,
@@ -517,12 +574,14 @@ function createReactionPickerButton(thread, message, emoji) {
517
574
  function createReplyComposer(thread) {
518
575
  const form = document.createElement('form');
519
576
  form.className = 'comment-reply-form';
577
+ const draft = this.activeCard?.replyDrafts?.[thread.id] ?? null;
520
578
 
521
579
  const textarea = document.createElement('textarea');
522
580
  textarea.className = inputClassNames({ extra: 'comment-card-input' });
523
581
  textarea.rows = 3;
524
582
  textarea.maxLength = COMMENT_BODY_MAX_LENGTH;
525
583
  textarea.placeholder = 'Reply to thread...';
584
+ textarea.value = draft?.value ?? '';
526
585
 
527
586
  const actions = document.createElement('div');
528
587
  actions.className = 'ui-record-actions comment-card-actions';
@@ -532,6 +591,9 @@ function createReplyComposer(thread) {
532
591
  cancel.className = buttonClassNames({ variant: 'secondary' });
533
592
  cancel.textContent = 'Cancel';
534
593
  cancel.addEventListener('click', () => {
594
+ if (this.activeCard?.replyDrafts?.[thread.id]) {
595
+ delete this.activeCard.replyDrafts[thread.id];
596
+ }
535
597
  this.activeCard = {
536
598
  ...this.activeCard,
537
599
  replyThreadId: null,
@@ -546,7 +608,7 @@ function createReplyComposer(thread) {
546
608
 
547
609
  actions.append(cancel, submit);
548
610
  form.append(textarea, actions);
549
- this.pendingCardFocusElement = textarea;
611
+ this.pendingCardFocusElement = createPendingFocusTarget(textarea, draft);
550
612
 
551
613
  form.addEventListener('submit', async (event) => {
552
614
  event.preventDefault();
@@ -556,6 +618,9 @@ function createReplyComposer(thread) {
556
618
  return;
557
619
  }
558
620
 
621
+ if (this.activeCard?.replyDrafts?.[thread.id]) {
622
+ delete this.activeCard.replyDrafts[thread.id];
623
+ }
559
624
  this.activeCard = {
560
625
  ...this.activeCard,
561
626
  replyThreadId: null,
@@ -597,7 +662,8 @@ function positionCard(card) {
597
662
 
598
663
  /** @this {any} */
599
664
  function flushPendingCardFocus() {
600
- const element = this.pendingCardFocusElement;
665
+ const pendingTarget = this.pendingCardFocusElement;
666
+ const element = pendingTarget instanceof HTMLElement ? pendingTarget : pendingTarget?.element;
601
667
  if (!(element instanceof HTMLElement) || !element.isConnected) {
602
668
  this.pendingCardFocusElement = null;
603
669
  return;
@@ -615,6 +681,17 @@ function flushPendingCardFocus() {
615
681
  }
616
682
 
617
683
  element.focus({ preventScroll: true });
684
+ if (
685
+ element instanceof HTMLTextAreaElement
686
+ && Number.isInteger(pendingTarget?.selectionStart)
687
+ && Number.isInteger(pendingTarget?.selectionEnd)
688
+ ) {
689
+ element.setSelectionRange(
690
+ pendingTarget.selectionStart,
691
+ pendingTarget.selectionEnd,
692
+ pendingTarget.selectionDirection ?? 'none',
693
+ );
694
+ }
618
695
  };
619
696
 
620
697
  focusElement();
@@ -633,14 +710,17 @@ function flushPendingCardFocus() {
633
710
  }
634
711
 
635
712
  export const commentUiCardMethods = {
713
+ captureActiveCardDraft,
636
714
  closeCard,
637
715
  createComposer,
716
+ createPendingFocusTarget,
638
717
  createMessageElement,
639
718
  createQuickReactionButton,
640
719
  createReactionBar,
641
720
  createReactionPicker,
642
721
  createReactionPickerButton,
643
722
  createReplyComposer,
723
+ createTextareaDraft,
644
724
  createThreadElement,
645
725
  ensureCardRoot,
646
726
  flushPendingCardFocus,
@@ -165,11 +165,34 @@ function handleEditorContentChange() {
165
165
  /** @this {CommentUiStateContext} */
166
166
  function setThreads(threads = []) {
167
167
  this.threads = sortThreads(threads);
168
+ const groups = this.getThreadGroups();
168
169
  if (
169
170
  this.activeCard?.mode === 'group'
170
- && !this.getThreadGroups().some((group) => group.key === this.activeCard.groupKey)
171
171
  ) {
172
- this.activeCard = null;
172
+ const activeThreadIds = Array.isArray(this.activeCard.groupThreadIds)
173
+ ? this.activeCard.groupThreadIds
174
+ : [];
175
+ const matchingGroup = groups.find((group) => group.key === this.activeCard.groupKey)
176
+ ?? groups.find((group) => (
177
+ group.threads.length === activeThreadIds.length
178
+ && group.threads.every((thread) => activeThreadIds.includes(thread.id))
179
+ ));
180
+ if (!matchingGroup) {
181
+ this.activeCard = null;
182
+ } else {
183
+ this.activeCard = {
184
+ ...this.activeCard,
185
+ anchor: matchingGroup.anchor,
186
+ groupKey: matchingGroup.key,
187
+ groupThreadIds: matchingGroup.threads.map((thread) => thread.id),
188
+ };
189
+ if (
190
+ this.activeCard.replyThreadId
191
+ && !matchingGroup.threads.some((thread) => thread.id === this.activeCard.replyThreadId)
192
+ ) {
193
+ this.activeCard.replyThreadId = null;
194
+ }
195
+ }
173
196
  }
174
197
  if (
175
198
  this.reactionPicker
@@ -98,6 +98,7 @@ export class DrawioEmbedController {
98
98
  getTheme,
99
99
  onOpenFile = null,
100
100
  onOpenTextFile = null,
101
+ onToggleQuickSwitcher = null,
101
102
  previewContainer,
102
103
  previewElement,
103
104
  toastController,
@@ -106,6 +107,7 @@ export class DrawioEmbedController {
106
107
  this.getTheme = getTheme;
107
108
  this.onOpenFile = onOpenFile;
108
109
  this.onOpenTextFile = onOpenTextFile;
110
+ this.onToggleQuickSwitcher = onToggleQuickSwitcher;
109
111
  this.previewContainer = previewContainer;
110
112
  this.previewElement = previewElement;
111
113
  this.toastController = toastController;
@@ -585,7 +587,15 @@ export class DrawioEmbedController {
585
587
  return null;
586
588
  }
587
589
 
590
+ _isMessageFromEntry(event, entry) {
591
+ return Boolean(entry?.iframe?.contentWindow && event.source === entry.iframe.contentWindow);
592
+ }
593
+
588
594
  _onMessage(event) {
595
+ if (event.origin !== window.location.origin) {
596
+ return;
597
+ }
598
+
589
599
  const payload = event.data;
590
600
  if (!payload || payload.source !== 'drawio-editor') {
591
601
  return;
@@ -595,6 +605,9 @@ export class DrawioEmbedController {
595
605
  if (!entry) {
596
606
  return;
597
607
  }
608
+ if (!this._isMessageFromEntry(event, entry)) {
609
+ return;
610
+ }
598
611
 
599
612
  if (payload.type === 'fallback-text') {
600
613
  if (entry.mode === 'view') {
@@ -616,6 +629,11 @@ export class DrawioEmbedController {
616
629
 
617
630
  if (payload.type === 'request-open-file') {
618
631
  this.onOpenFile?.(entry.filePath);
632
+ return;
633
+ }
634
+
635
+ if (payload.type === 'request-toggle-quick-switcher') {
636
+ this.onToggleQuickSwitcher?.();
619
637
  }
620
638
  }
621
639
 
@@ -55,6 +55,7 @@ export class ExcalidrawEmbedController {
55
55
  getTheme,
56
56
  getLocalUser,
57
57
  onOpenFile = null,
58
+ onToggleQuickSwitcher = null,
58
59
  previewContainer,
59
60
  previewElement,
60
61
  toastController,
@@ -62,6 +63,7 @@ export class ExcalidrawEmbedController {
62
63
  this.getTheme = getTheme;
63
64
  this.getLocalUser = getLocalUser;
64
65
  this.onOpenFile = onOpenFile;
66
+ this.onToggleQuickSwitcher = onToggleQuickSwitcher;
65
67
  this.previewContainer = previewContainer;
66
68
  this.previewElement = previewElement;
67
69
  this.toastController = toastController;
@@ -1197,6 +1199,11 @@ export class ExcalidrawEmbedController {
1197
1199
  return;
1198
1200
  }
1199
1201
 
1202
+ if (msg.type === 'request-toggle-quick-switcher') {
1203
+ this.onToggleQuickSwitcher?.();
1204
+ return;
1205
+ }
1206
+
1200
1207
  if (msg.type === 'error') {
1201
1208
  if (entry.isParked) {
1202
1209
  return;
@@ -730,6 +730,7 @@ export class GitPanelController {
730
730
  && this.selection.scope === file.scope;
731
731
  const dirPath = getPathDir(file.path);
732
732
  const displayName = getPathLeaf(file.path);
733
+ const fullPath = String(file.path || '');
733
734
  const statusClass = badgeClass(file.status);
734
735
  const stageAction = file.scope === 'staged'
735
736
  ? { label: 'Unstage', value: 'unstage' }
@@ -746,6 +747,7 @@ export class GitPanelController {
746
747
  type="button"
747
748
  data-git-path="${escapeHtml(file.path)}"
748
749
  data-git-scope="${escapeHtml(file.scope)}"
750
+ title="${escapeHtml(fullPath)}"
749
751
  >
750
752
  ${fileIconSvg()}
751
753
  <span class="ui-item-copy git-file-copy">