collabmd 0.1.45 → 0.1.47

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 (356) hide show
  1. package/README.md +40 -19
  2. package/bin/collabmd.js +27 -1
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +1 -0
  4. package/dist/client/assets/{abnfDiagram-N423BO3Z-CUMTFJhI.js → abnfDiagram-VCTEODGH-BNDLzJ7L.js} +1 -1
  5. package/dist/client/assets/architecture-7GRP2DOG-BMOPAkUC.js +1 -0
  6. package/dist/client/assets/{architectureDiagram-T3A2C74G-w25m71oV.js → architectureDiagram-5GKGNRK7-I39sYjHI.js} +1 -1
  7. package/dist/client/assets/base-BYODPHdS.js +1 -0
  8. package/dist/client/assets/blockDiagram-NRAW4CY4-C6DtJy5Y.js +129 -0
  9. package/dist/client/assets/browser-BKLM0ThC-IxjwuOIz-BBqQnUEb.js +1 -0
  10. package/dist/client/assets/browser-utils--H_DkyEF.js +1 -0
  11. package/dist/client/assets/c4Diagram-UCG6FXSJ-CtWtxS9_.js +38 -0
  12. package/dist/client/assets/channel-CaoKA_We.js +1 -0
  13. package/dist/client/assets/{chunk-U6XO7XAA-BFxjP5U3.js → chunk-2ZTRR5NV-C2qZJila.js} +1 -1
  14. package/dist/client/assets/{chunk-YOTPTUD7-D0vRKqYp.js → chunk-3Z5EZCMW-DMniOlPd.js} +1 -1
  15. package/dist/client/assets/{chunk-BIQX33UG-DZEsGuSn.js → chunk-5V3GS4D5-i-ZDOEnP.js} +1 -1
  16. package/dist/client/assets/{chunk-MOZMSUNE-XVucA-n6.js → chunk-6AZGARVD-BB6FqMl-.js} +1 -1
  17. package/dist/client/assets/{chunk-5JV3BV7I-Cy5pj3QY.js → chunk-6EIED4P4-DdUJkP0f.js} +1 -1
  18. package/dist/client/assets/{chunk-R7FJI6CG-Cnn3gE-Y.js → chunk-6K3QC6MW-CqVsVn-y.js} +1 -1
  19. package/dist/client/assets/{chunk-OSBZ3O6U-CrKZOUOr.js → chunk-6TQVIW2G-DKlLbNIP.js} +1 -1
  20. package/dist/client/assets/{chunk-JG7HCLWE-BYfiSaVt.js → chunk-747NJXEK-BFkZPlab.js} +1 -1
  21. package/dist/client/assets/{chunk-NSK5VX7P-TLH37VXI.js → chunk-75Z2AOVW-CdFSaPjz.js} +1 -1
  22. package/dist/client/assets/chunk-CKBBP62Z-DG26UiBv.js +2 -0
  23. package/dist/client/assets/{chunk-3NCLNEKW-Y2Jf_LI-.js → chunk-CLGD4ZFX-DQLgbQrv.js} +1 -1
  24. package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +2 -0
  25. package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +127 -0
  26. package/dist/client/assets/{chunk-2GRJ4B5K-DhnlUv3F.js → chunk-F27PBJKO-CNHIFhjo.js} +1 -1
  27. package/dist/client/assets/{chunk-YGJVY4SA-CjSe7Bx7.js → chunk-FLYJHZSQ-Be7lKF17.js} +1 -1
  28. package/dist/client/assets/{chunk-KEIR6QF5-BICK3FdT.js → chunk-FOHPRMQF-DHwB1DNv.js} +2 -2
  29. package/dist/client/assets/{chunk-5RXB4S5H-BWrwFqMI.js → chunk-G27WJ6UU-D9-eg537.js} +2 -2
  30. package/dist/client/assets/chunk-GMAD6QVW-CbcBqPM5.js +72 -0
  31. package/dist/client/assets/{chunk-QBLGF6JB-CxAyS2mW.js → chunk-I5DQTOEV-Hm2LfiYI.js} +1 -1
  32. package/dist/client/assets/{chunk-5FCAYU7R-Dh5nylU8.js → chunk-ICYGCRZG-749o-pGJ.js} +1 -1
  33. package/dist/client/assets/{chunk-CQNSW5MT-B8S09OIh.js → chunk-IH6LHLGP-CC6I9F3i.js} +1 -1
  34. package/dist/client/assets/chunk-JQ64N6SF-DSFNH4bh.js +1 -0
  35. package/dist/client/assets/{chunk-CYSBUYHQ-C1Rf4art.js → chunk-KI3K4JFJ-Rma-0k_M.js} +1 -1
  36. package/dist/client/assets/{chunk-GF5L2VYU-DkJpO7ff.js → chunk-LCL6LL3I-DmDkVukh.js} +1 -1
  37. package/dist/client/assets/chunk-LNGE3PJU-DWpGwHrW.js +34 -0
  38. package/dist/client/assets/chunk-OBVCFTLP-BJR7u1jh.js +1 -0
  39. package/dist/client/assets/{chunk-5TONJI2A-DQOY3q1H.js → chunk-OUJLGHUK-D0j2JRSg.js} +1 -1
  40. package/dist/client/assets/chunk-P2QGCYS3-BRpqY32H.js +1 -0
  41. package/dist/client/assets/{chunk-KBJHAD2P-CB_3zWUf.js → chunk-POPQ4Y6H-Cb4SlVZF.js} +1 -1
  42. package/dist/client/assets/{chunk-4I5QYGJK-CCB2YcIH.js → chunk-PWAF6VOD-Cz8IwBB5.js} +1 -1
  43. package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +10 -0
  44. package/dist/client/assets/chunk-RHFEMEQ7-CWY8cf4H.js +168 -0
  45. package/dist/client/assets/chunk-RM4UPSZO-CWRwxNWJ.js +41 -0
  46. package/dist/client/assets/{chunk-6Q2QTUOP-CPlWzBtc.js → chunk-SVP7TREG-CyHOmcac.js} +1 -1
  47. package/dist/client/assets/chunk-TEH6E4GO-DVayPj-q.js +62 -0
  48. package/dist/client/assets/{chunk-EMLP6XTP-RLD4nXpI.js → chunk-UY3FDG6J-CnmaAkG5.js} +1 -1
  49. package/dist/client/assets/{chunk-5HE753X5-Bw-yg4kO.js → chunk-XHIXRSVI-BFQ6B8BE.js} +1 -1
  50. package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +1 -0
  51. package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +1 -0
  52. package/dist/client/assets/comment-thread-store-CdcwrObc.js +1 -0
  53. package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
  54. package/dist/client/assets/comment-ui-shared-DWkk9Vh3.js +7 -0
  55. package/dist/client/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
  56. package/dist/client/assets/{cynefinDiagram-MW4NZA55-CJxXfJek.js → cynefinDiagram-5FMLGOSQ-CdTPi2yO.js} +1 -1
  57. package/dist/client/assets/dagre-3AP2YEHR-5gtJtd0O.js +4 -0
  58. package/dist/client/assets/dagre-PrKaheQc.js +1 -0
  59. package/dist/client/assets/{diagram-7IWD3JNH-B2d2Bm15.js → diagram-S7CK7UJ4-BudWz9WU.js} +4 -4
  60. package/dist/client/assets/{diagram-UB23O5K3-DJcKCwv9.js → diagram-UQ7AKVKN-3v4rbH-s.js} +1 -1
  61. package/dist/client/assets/{diagram-B4RE2ZJO-NP4UAwjR.js → diagram-VSXAHHWV-CQRVEZR7.js} +1 -1
  62. package/dist/client/assets/{diagram-Q27KOJAE-DylDuwor.js → diagram-VX7I27RA-C_-rj0sw.js} +1 -1
  63. package/dist/client/assets/{diagram-LBJQPF4R-D1FJQV8t.js → diagram-Z3DM3KII-B4yxavgj.js} +1 -1
  64. package/dist/client/assets/direct-engine-DdrQKpgq-CtKfQzCt.js +5 -0
  65. package/dist/client/assets/dist-73RPdcyU.js +1 -0
  66. package/dist/client/assets/dist-BJ1bJs33.js +1 -0
  67. package/dist/client/assets/{dist-CYZmbokb.js → dist-BK9QvQrc.js} +9 -9
  68. package/dist/client/assets/dist-BPHLJ09L.js +11 -0
  69. package/dist/client/assets/dist-B_yQaEv_.js +6 -0
  70. package/dist/client/assets/dist-BeajGMhO.js +1 -0
  71. package/dist/client/assets/{dist-JYEDRrPT.js → dist-Bw3VIE_v.js} +1 -1
  72. package/dist/client/assets/dist-ByrG2qBA.js +1 -0
  73. package/dist/client/assets/dist-C5NgpdG5.js +1 -0
  74. package/dist/client/assets/dist-CH-sQu3r.js +1 -0
  75. package/dist/client/assets/dist-CKS_-are.js +1 -0
  76. package/dist/client/assets/{dist-MvcV4190.js → dist-CdmKGRGr.js} +1 -1
  77. package/dist/client/assets/{dist-DGb27Dl6.js → dist-CietwTVS.js} +1 -1
  78. package/dist/client/assets/dist-D37Hyu3h.js +9 -0
  79. package/dist/client/assets/dist-D3fehAZ2.js +2 -0
  80. package/dist/client/assets/dist-D5wCC32z.js +1 -0
  81. package/dist/client/assets/{dist-DCzuX1AF.js → dist-DDUn5zTz.js} +1 -1
  82. package/dist/client/assets/dist-DGEbEfw4.js +1 -0
  83. package/dist/client/assets/dist-DVy5woUy.js +1 -0
  84. package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZAAWTG-.js} +1 -1
  85. package/dist/client/assets/{dist-Drp8uu5J.js → dist-Dir5dDKZ.js} +1 -1
  86. package/dist/client/assets/dist-Dl_tpDSr.js +1 -0
  87. package/dist/client/assets/dist-DuH3ZrHo.js +1 -0
  88. package/dist/client/assets/dist-DutPuFmC.js +1 -0
  89. package/dist/client/assets/{dist-D2AQ-76g.js → dist-LQ4kDCKz.js} +1 -1
  90. package/dist/client/assets/{dist-C11hHqv_.js → dist-RKBTaQMb.js} +12 -12
  91. package/dist/client/assets/dist-Tw-Fxpeb.js +1 -0
  92. package/dist/client/assets/dist-eBx8q6Sy.js +1 -0
  93. package/dist/client/assets/{dist-DK5Gs2wa.js → dist-mj2Ht75J.js} +1 -1
  94. package/dist/client/assets/{dist-CnL7Y2sM.js → dist-netZOQtD.js} +1 -1
  95. package/dist/client/assets/{drawio-editor-ClE8jpoG.js → drawio-editor-BjrxTe3l.js} +1 -1
  96. package/dist/client/assets/drawioEditor-DUVZjSSr.js +2 -0
  97. package/dist/client/assets/{ebnfDiagram-BXEA7PRR-nw0wmA6y.js → ebnfDiagram-PWID7BFC-OXa8VEp1.js} +1 -1
  98. package/dist/client/assets/editor-session-DfZuRgB_.js +54 -0
  99. package/dist/client/assets/embedded-editor-base-DvMynhKu.css +1 -0
  100. package/dist/client/assets/embedpdf-BmE13ZZ0.js +1 -0
  101. package/dist/client/assets/embedpdf-DA4bA119-BPqZxwjc.js +2363 -0
  102. package/dist/client/assets/{en-7NFCYGKX-BrgYZAEe.js → en-SJ2YIMFF-CJBL3nkq.js} +1 -1
  103. package/dist/client/assets/erDiagram-SSCWMZ5O-C-iy6VkX.js +99 -0
  104. package/dist/client/assets/es-CAsWR6hG.js +22 -0
  105. package/dist/client/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
  106. package/dist/client/assets/excalidraw-editor-BlcN6umJ.css +1 -0
  107. package/dist/client/assets/excalidraw-editor-D7pnUCLH.js +9 -0
  108. package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
  109. package/dist/client/assets/excalidrawEditor-B0jOK3lv.js +2 -0
  110. package/dist/client/assets/export-page-Bs3xE1fg.js +57 -0
  111. package/dist/client/assets/exportDocument-Dg9MjkIk.js +2 -0
  112. package/dist/client/assets/exportDocument-PnYU3v1s.css +1 -0
  113. package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
  114. package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
  115. package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +1 -0
  116. package/dist/client/assets/{ganttDiagram-PKOTCBZU-BnM97BCT.js → ganttDiagram-EL5Y4UJY-DtKHAbez.js} +1 -1
  117. package/dist/client/assets/gitGraph-4MIJSDKK-DYlXv_yJ.js +1 -0
  118. package/dist/client/assets/{gitGraphDiagram-DS77QQ5N-BQpQhjuN.js → gitGraphDiagram-WWUBYQGX-oue8fQ5o.js} +1 -1
  119. package/dist/client/assets/github-dark.min-BV82VuKq.css +1 -0
  120. package/dist/client/assets/github.min-v3dd8CNH.css +1 -0
  121. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +1 -0
  122. package/dist/client/assets/index-BIpgxyGZ.css +1 -0
  123. package/dist/client/assets/index-Z5sI0Bj-.js +2 -0
  124. package/dist/client/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
  125. package/dist/client/assets/{infoDiagram-6WML65LV-DYB8HCDQ.js → infoDiagram-RXCK75RN-BMzo6KIn.js} +1 -1
  126. package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-Coz_P3t6.js → ishikawaDiagram-5VMMS53U-BIM3h287.js} +1 -1
  127. package/dist/client/assets/{journeyDiagram-NVQOT4AX-B6edChce.js → journeyDiagram-EYS64GPL-mF6Lh8O-.js} +1 -1
  128. package/dist/client/assets/{kanban-definition-27J2QSJJ-BFd9-cLc.js → kanban-definition-3QL26DDD-DLN2NyoR.js} +2 -2
  129. package/dist/client/assets/{line-B_S_S8kV.js → line-BfTWJmgf.js} +1 -1
  130. package/dist/client/assets/main-Dwnj9Gaq.js +903 -0
  131. package/dist/client/assets/{mermaid-parser.core-CUVdebAV.js → mermaid-parser.core-Bl0efOMt.js} +2 -2
  132. package/dist/client/assets/mermaid.core-CLZBlpIW.js +11 -0
  133. package/dist/client/assets/{mindmap-definition-FAOFIHXS-C9PQ38Al.js → mindmap-definition-FBJOCRG2-CRyHaHTk.js} +1 -1
  134. package/dist/client/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
  135. package/dist/client/assets/pdfium-RAgkpwfK.wasm +0 -0
  136. package/dist/client/assets/{pegDiagram-VL7TDLO6-BMZUrSaU.js → pegDiagram-XKGWAZYB-B31fKPR2.js} +1 -1
  137. package/dist/client/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
  138. package/dist/client/assets/{pieDiagram-7S7Q4E2Y-h8kbCL9o.js → pieDiagram-E7YTZNPT-B5OZPb88.js} +1 -1
  139. package/dist/client/assets/preview-render-compiler-BApvlLLo.js +35 -0
  140. package/dist/client/assets/preview-render-compiler-BQ_3h9vD.js +1 -0
  141. package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
  142. package/dist/client/assets/preview-render-worker-BmN79bVc.js +60 -0
  143. package/dist/client/assets/prod-BiYPMR1i.js +177 -0
  144. package/dist/client/assets/prod-VxdGZ5Ly.js +1 -0
  145. package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-CkElyfMi.js → quadrantDiagram-AXDQQJYC-Drrw14YH.js} +1 -1
  146. package/dist/client/assets/quick-switcher-controller-ButWPmCI.js +12 -0
  147. package/dist/client/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
  148. package/dist/client/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
  149. package/dist/client/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
  150. package/dist/client/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
  151. package/dist/client/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
  152. package/dist/client/assets/{railroadDiagram-AXF67PYL-c75gnikD.js → railroadDiagram-O6MQD6OU-BPifP0MB.js} +1 -1
  153. package/dist/client/assets/{requirementDiagram-LRYGKXZP-mNxKLuHS.js → requirementDiagram-EFPCY7ZU-CRZG6mRB.js} +2 -2
  154. package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
  155. package/dist/client/assets/{sankeyDiagram-W5VNT64P-0OhplksI.js → sankeyDiagram-P5KCCOFB-DvarEJpo.js} +1 -1
  156. package/dist/client/assets/{sequenceDiagram-SI44F4Z6-BJ_yAocC.js → sequenceDiagram-WJ2MYXX4-B4oWlb-w.js} +1 -1
  157. package/dist/client/assets/{stateDiagram-OKZ733FA-Cc83O86s.js → stateDiagram-HBIQ2CUA-qbHIIqRZ.js} +1 -1
  158. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +1 -0
  159. package/dist/client/assets/swimlanes-XN3QIQJK-xB6CtUGj.js +1 -0
  160. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +8 -0
  161. package/dist/client/assets/{timeline-definition-Z64GVDOM-BWDAGTHz.js → timeline-definition-24CTP7MA-Lj_yTNlY.js} +1 -1
  162. package/dist/client/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
  163. package/dist/client/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
  164. package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
  165. package/dist/client/assets/{vennDiagram-T6HMQDX7-LOSsnlMB.js → vennDiagram-4TSXK5OY-BekRp5Y0.js} +1 -1
  166. package/dist/client/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
  167. package/dist/client/assets/{wardleyDiagram-T6FBY63Y-BxII3foY.js → wardleyDiagram-VM6X3IG4-kdnV_Hdm.js} +1 -1
  168. package/dist/client/assets/worker-engine-m0rlHn8R-S8mpn_O0.js +17369 -0
  169. package/dist/client/assets/{xychartDiagram-ELKLHX3M-B-pTEjju.js → xychartDiagram-S5SC5T6Z-DufGwNSB.js} +3 -3
  170. package/dist/client/drawio-editor.html +1 -1
  171. package/dist/client/excalidraw-editor.html +1 -1
  172. package/dist/client/export-document.html +3 -3
  173. package/dist/client/index.html +30 -8
  174. package/docker-compose.yml +42 -0
  175. package/package.json +32 -18
  176. package/scripts/local-structurizr-compose.mjs +101 -0
  177. package/src/client/app/index.html +27 -5
  178. package/src/client/application/app-shell/comments-feature.js +21 -13
  179. package/src/client/application/app-shell/git-feature.js +14 -2
  180. package/src/client/application/app-shell/presence-feature.js +4 -3
  181. package/src/client/application/app-shell/ui-feature-shell.js +109 -2
  182. package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
  183. package/src/client/application/app-shell/workspace-feature.js +5 -1
  184. package/src/client/application/app-shell-elements.js +3 -0
  185. package/src/client/application/pdf-preview-controller.js +75 -0
  186. package/src/client/application/preview-render-compiler.js +3 -0
  187. package/src/client/application/quick-switcher-loader.js +1 -1
  188. package/src/client/application/structurizr-preview-controller.js +395 -0
  189. package/src/client/application/workspace-coordinator.js +25 -3
  190. package/src/client/application/workspace-preview-controller.js +88 -2
  191. package/src/client/assets/vendor/highlight/github-dark.min.css +2 -10
  192. package/src/client/assets/vendor/highlight/github.min.css +2 -10
  193. package/src/client/bootstrap/collabmd-app-shell.js +39 -6
  194. package/src/client/browser-utils.js +44 -0
  195. package/src/client/domain/runtime-paths.js +26 -5
  196. package/src/client/domain/structurizr-language.js +99 -0
  197. package/src/client/domain/vault-paths.js +48 -0
  198. package/src/client/excalidraw-editor.js +844 -51
  199. package/src/client/export/export-host.js +1 -1
  200. package/src/client/export/export-page.js +6 -2
  201. package/src/client/export/export-pipeline.js +60 -1
  202. package/src/client/infrastructure/browser-preferences-port.js +10 -0
  203. package/src/client/infrastructure/comment-thread-store.js +34 -13
  204. package/src/client/infrastructure/editor-session.js +10 -0
  205. package/src/client/infrastructure/editor-view-adapter.js +46 -2
  206. package/src/client/infrastructure/excalidraw-room-client.js +103 -14
  207. package/src/client/infrastructure/git-api-client.js +5 -0
  208. package/src/client/infrastructure/vault-api-client.js +26 -0
  209. package/src/client/presentation/comment-ui/comment-ui-render.js +4 -0
  210. package/src/client/presentation/comment-ui/comment-ui-shared.js +4 -0
  211. package/src/client/presentation/comment-ui-controller.js +2 -0
  212. package/src/client/presentation/drawio-embed-controller.js +9 -102
  213. package/src/client/presentation/drawio-viewer.js +118 -0
  214. package/src/client/presentation/excalidraw-embed-controller.js +81 -8
  215. package/src/client/presentation/file-action-controller.js +102 -0
  216. package/src/client/presentation/file-explorer-controller.js +0 -5
  217. package/src/client/presentation/file-explorer-view.js +51 -73
  218. package/src/client/presentation/file-icon-svg.js +40 -0
  219. package/src/client/presentation/file-tree-state.js +6 -3
  220. package/src/client/presentation/git-diff-view-controller.js +731 -3
  221. package/src/client/presentation/git-panel-controller.js +2 -2
  222. package/src/client/presentation/outline-controller.js +86 -0
  223. package/src/client/presentation/quick-switcher-controller.js +73 -22
  224. package/src/client/presentation/quick-switcher-text-search.js +1 -1
  225. package/src/client/styles/components/navigation.css +11 -1
  226. package/src/client/styles/features/diagram-preview.css +76 -0
  227. package/src/client/styles/features/diff-special.css +309 -0
  228. package/src/client/styles/features/preview-markdown.css +25 -0
  229. package/src/client/styles/features/quick-switcher.css +8 -0
  230. package/src/client/styles/foundation/themes.css +7 -0
  231. package/src/client/styles/layout/shell.css +40 -1
  232. package/src/client/styles/layout/sidebar.css +42 -4
  233. package/src/client/styles/layout/view-modes.css +1 -0
  234. package/src/client/styles/overrides/highlightjs.css +20 -4
  235. package/src/client/styles/style.css +1 -0
  236. package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
  237. package/src/domain/comment-threads.js +63 -5
  238. package/src/domain/excalidraw-room-codec.js +6 -4
  239. package/src/domain/file-kind.js +35 -3
  240. package/src/server/config/env.js +79 -0
  241. package/src/server/create-app-server.js +12 -0
  242. package/src/server/domain/bases/base-definition.js +1 -1
  243. package/src/server/domain/bases/base-expression-runtime.js +1 -4
  244. package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
  245. package/src/server/domain/bases/base-transform.js +1 -4
  246. package/src/server/domain/collaboration/collaboration-room.js +55 -21
  247. package/src/server/domain/comment-overview.js +15 -5
  248. package/src/server/domain/ripgrep-search-service.js +4 -0
  249. package/src/server/infrastructure/git/diff-service.js +5 -0
  250. package/src/server/infrastructure/git/git-service.js +44 -11
  251. package/src/server/infrastructure/git/history-service.js +54 -0
  252. package/src/server/infrastructure/git/image-mime.js +14 -0
  253. package/src/server/infrastructure/git/untracked-files.js +28 -1
  254. package/src/server/infrastructure/http/create-git-api-command-handler.js +3 -1
  255. package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
  256. package/src/server/infrastructure/http/create-request-handler.js +16 -23
  257. package/src/server/infrastructure/http/create-static-handler.js +5 -2
  258. package/src/server/infrastructure/http/create-structurizr-api-handler.js +147 -0
  259. package/src/server/infrastructure/http/create-vault-api-command-handler.js +66 -4
  260. package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
  261. package/src/server/infrastructure/http/http-request-helpers.js +22 -0
  262. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  263. package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
  264. package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
  265. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +400 -0
  266. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
  267. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
  268. package/dist/client/assets/architecture-TIHT7OUA-CsHfPErM.js +0 -1
  269. package/dist/client/assets/base-CxPEiHuy.js +0 -1
  270. package/dist/client/assets/blockDiagram-VBNYF7ZC-CipJt9Jl.js +0 -132
  271. package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
  272. package/dist/client/assets/c4Diagram-5PPSVZJV-B5ktVx6g.js +0 -10
  273. package/dist/client/assets/channel-4Jkmq93I.js +0 -1
  274. package/dist/client/assets/chunk-7BUUIJ7U-Bb538aSH.js +0 -1
  275. package/dist/client/assets/chunk-7Z6QIM7H-BP9Pdsm9.js +0 -10
  276. package/dist/client/assets/chunk-ERSWUTIN-ME9RVNel.js +0 -41
  277. package/dist/client/assets/chunk-I66GZJ75-CVFiiffQ.js +0 -127
  278. package/dist/client/assets/chunk-J7OUQ5F2-4CEb7pvH.js +0 -2
  279. package/dist/client/assets/chunk-JQJVKLGR-cx8X_24v.js +0 -156
  280. package/dist/client/assets/chunk-QR6OTTB3-CDAA_5Ib.js +0 -62
  281. package/dist/client/assets/chunk-RYQCIY6F-D-a0zH8K.js +0 -1
  282. package/dist/client/assets/chunk-UBXNYLIW-Bhk-PbFK.js +0 -1
  283. package/dist/client/assets/chunk-W5SLKNZC-BdNSCxZ9.js +0 -1
  284. package/dist/client/assets/chunk-WRU74C26-h6_XkD3_.js +0 -70
  285. package/dist/client/assets/chunk-ZIRB5QZD-O39ZBUk3.js +0 -32
  286. package/dist/client/assets/classDiagram-JCYQIIEL-L7lsyW_w.js +0 -1
  287. package/dist/client/assets/classDiagram-v2-OCEON4UE-L7lsyW_w.js +0 -1
  288. package/dist/client/assets/comment-threads-DDegmaFO.js +0 -4
  289. package/dist/client/assets/cynefin-VYW2F7L2-Ds2Fw2Y0.js +0 -1
  290. package/dist/client/assets/dagre-Buvkdvvj.js +0 -1
  291. package/dist/client/assets/dagre-VZM6K2ZE-L1xArOGs.js +0 -4
  292. package/dist/client/assets/dist-BH87JoHx.js +0 -11
  293. package/dist/client/assets/dist-BIkPRZO7.js +0 -6
  294. package/dist/client/assets/dist-BqCsFpx4.js +0 -1
  295. package/dist/client/assets/dist-C2JHCt8U.js +0 -1
  296. package/dist/client/assets/dist-CZjTtmTu.js +0 -1
  297. package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
  298. package/dist/client/assets/dist-CqQEC8gR.js +0 -1
  299. package/dist/client/assets/dist-D4Rzqod1.js +0 -1
  300. package/dist/client/assets/dist-D5sn-mwk.js +0 -9
  301. package/dist/client/assets/dist-D7G-n87v.js +0 -1
  302. package/dist/client/assets/dist-DRqOrNgN.js +0 -1
  303. package/dist/client/assets/dist-DetkMS_4.js +0 -1
  304. package/dist/client/assets/dist-DhLvC8DS.js +0 -2
  305. package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
  306. package/dist/client/assets/dist-DtbjNB28.js +0 -1
  307. package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
  308. package/dist/client/assets/dist-GrygD2zE.js +0 -1
  309. package/dist/client/assets/dist-HmEpWUow.js +0 -1
  310. package/dist/client/assets/dist-RTa81Km7.js +0 -1
  311. package/dist/client/assets/drawioEditor-CXaTM9Ds.js +0 -2
  312. package/dist/client/assets/editor-session-GTwZS6Df.js +0 -16
  313. package/dist/client/assets/embedded-editor-base-CiNEc8vy.css +0 -1
  314. package/dist/client/assets/erDiagram-JOGREHBK-cYUpEKpf.js +0 -85
  315. package/dist/client/assets/eventmodeling-45OFAUF4-CLEiVx5s.js +0 -1
  316. package/dist/client/assets/excalidraw-editor-BZVM81BO.js +0 -9
  317. package/dist/client/assets/excalidraw-editor-CyGwOhLz.css +0 -1
  318. package/dist/client/assets/excalidraw-scene-C8n9CHsK.js +0 -176
  319. package/dist/client/assets/excalidrawEditor-DxJanCze.js +0 -2
  320. package/dist/client/assets/export-page-CUfws2T-.js +0 -39
  321. package/dist/client/assets/exportDocument-BCuxqXDY.js +0 -2
  322. package/dist/client/assets/exportDocument-DV-OX74E.css +0 -1
  323. package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
  324. package/dist/client/assets/flowDiagram-UKHOOZJN-D0ypP0Ez.js +0 -1
  325. package/dist/client/assets/gitGraph-TEB2WS4Q-CZFBqwW-.js +0 -1
  326. package/dist/client/assets/github-dark.min-Z5exjX_n.css +0 -1
  327. package/dist/client/assets/github.min-D2BCvnWf.css +0 -1
  328. package/dist/client/assets/image-QXRYHUNP-lfTHE3bb.js +0 -1
  329. package/dist/client/assets/index-C3YnUgMD.css +0 -1
  330. package/dist/client/assets/index-D2wXraJ1.js +0 -2
  331. package/dist/client/assets/info-DKCQHKI2--1InqQeT.js +0 -1
  332. package/dist/client/assets/main-DtiGz7uI.js +0 -795
  333. package/dist/client/assets/map-BaFkSB1l.js +0 -1
  334. package/dist/client/assets/mermaid.core-DN-lF51U.js +0 -11
  335. package/dist/client/assets/packet-7NZHBO7P-BGMXB0XL.js +0 -1
  336. package/dist/client/assets/pie-RZYD4A2V-DgYg3tCt.js +0 -1
  337. package/dist/client/assets/preview-render-compiler-BSaQO_p3.js +0 -35
  338. package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
  339. package/dist/client/assets/preview-render-profile-BZzGSg6K.js +0 -22
  340. package/dist/client/assets/preview-render-worker-B42LWvrD.js +0 -60
  341. package/dist/client/assets/quick-switcher-controller-shW_6vPY.js +0 -12
  342. package/dist/client/assets/radar-I7S5WNFK-Ag-zp_Rq.js +0 -1
  343. package/dist/client/assets/railroad-3IZDKUUU-aibJDIDV.js +0 -1
  344. package/dist/client/assets/railroad-abnf-AHOZXSZD-BBMEuvIl.js +0 -1
  345. package/dist/client/assets/railroad-ebnf-EBAXGLYW-Be1nseej.js +0 -1
  346. package/dist/client/assets/railroad-peg-LSFZ7HO6-DIvD-Eyb.js +0 -1
  347. package/dist/client/assets/room-CQLoqtMo.js +0 -1
  348. package/dist/client/assets/runtime-config-DSGmGE9V.js +0 -1
  349. package/dist/client/assets/stateDiagram-v2-UEYNNEHI-B1-BufUk.js +0 -1
  350. package/dist/client/assets/swimlanes-SLNWSIFB-oVTWEJIj.js +0 -2
  351. package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-C5OTVwEu.js +0 -8
  352. package/dist/client/assets/treeView-QDETBFTQ-uHZ-3Fz8.js +0 -1
  353. package/dist/client/assets/treemap-6X3UGDF4-BnUKyy3l.js +0 -1
  354. package/dist/client/assets/vault-api-client-C6bcGwy-.js +0 -5
  355. package/dist/client/assets/wardley-OPB4EBWU-Da7TLC2F.js +0 -1
  356. package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
@@ -31,6 +31,300 @@ body[data-surface='excalidraw-editor'][data-document-mode='preview'] .disable-vi
31
31
  pointer-events: none;
32
32
  }
33
33
 
34
+ .diagram-comments-overlay {
35
+ position: absolute;
36
+ z-index: 25;
37
+ inset: 0;
38
+ pointer-events: none;
39
+ }
40
+
41
+ .diagram-comments-toolbar {
42
+ display: inline-flex;
43
+ align-items: center;
44
+ gap: var(--space-2);
45
+ pointer-events: auto;
46
+ }
47
+
48
+ .diagram-comment-button,
49
+ .diagram-comment-close,
50
+ .diagram-comment-back,
51
+ .diagram-comment-marker {
52
+ border: 0;
53
+ font: inherit;
54
+ cursor: pointer;
55
+ }
56
+
57
+ .diagram-comment-button {
58
+ display: inline-flex;
59
+ align-items: center;
60
+ justify-content: center;
61
+ gap: var(--space-2);
62
+ min-height: var(--control-h-sm);
63
+ padding: 0 var(--space-3);
64
+ border: 1px solid transparent;
65
+ border-radius: var(--radius-md);
66
+ background: transparent;
67
+ color: var(--color-text);
68
+ box-shadow: none;
69
+ transition: transform var(--transition-interactive), background var(--transition-interactive), border-color var(--transition-interactive), color var(--transition-interactive);
70
+ }
71
+
72
+ .diagram-comment-button:hover:not(:disabled),
73
+ .diagram-comment-back:hover {
74
+ border-color: var(--color-comment);
75
+ }
76
+
77
+ .diagram-comment-button:hover:not(:disabled),
78
+ .diagram-comment-button.is-active {
79
+ background: var(--color-surface-raised);
80
+ }
81
+
82
+ .diagram-comment-button:active:not(:disabled),
83
+ .diagram-comment-add:active:not(:disabled) {
84
+ transform: translateY(1px);
85
+ }
86
+
87
+ .diagram-comment-button:focus-visible,
88
+ .diagram-comment-add:focus-visible,
89
+ .diagram-comment-close:focus-visible,
90
+ .diagram-comment-back:focus-visible,
91
+ .diagram-comment-marker:focus-visible {
92
+ outline: 2px solid var(--color-primary);
93
+ outline-offset: 2px;
94
+ }
95
+
96
+ .diagram-comment-icon {
97
+ width: 15px;
98
+ height: 15px;
99
+ flex: 0 0 auto;
100
+ }
101
+
102
+ .diagram-comments-toolbar .diagram-comment-button,
103
+ .diagram-comments-toolbar .diagram-comment-add {
104
+ position: relative;
105
+ }
106
+
107
+ .diagram-comment-count {
108
+ position: absolute;
109
+ top: -4px;
110
+ right: -4px;
111
+ display: inline-flex;
112
+ align-items: center;
113
+ justify-content: center;
114
+ box-sizing: border-box;
115
+ min-width: 1.125rem;
116
+ height: 1.125rem;
117
+ padding: 0 0.25rem;
118
+ border: 2px solid var(--color-surface);
119
+ border-radius: var(--radius-full);
120
+ background: var(--color-comment);
121
+ color: var(--color-primary-contrast);
122
+ font-family: inherit;
123
+ font-size: var(--text-caption);
124
+ font-variant-numeric: tabular-nums;
125
+ font-weight: 700;
126
+ line-height: 1;
127
+ text-align: center;
128
+ pointer-events: none;
129
+ }
130
+
131
+ .diagram-comment-add {
132
+ display: inline-flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ width: var(--control-h-sm);
136
+ min-width: var(--control-h-sm);
137
+ height: var(--control-h-sm);
138
+ padding: 0;
139
+ border: 1px solid var(--border-comment-soft);
140
+ border-radius: var(--radius-md);
141
+ background: var(--color-comment-soft);
142
+ color: var(--color-comment-text);
143
+ cursor: pointer;
144
+ transition: transform var(--transition-interactive), background var(--transition-interactive), border-color var(--transition-interactive), color var(--transition-interactive);
145
+ }
146
+
147
+ .diagram-comment-add:hover:not(:disabled) {
148
+ border-color: var(--border-comment-active);
149
+ background: var(--surface-comment-offset-active);
150
+ }
151
+
152
+ .diagram-comment-button.is-primary {
153
+ border-color: var(--color-primary);
154
+ background: var(--color-primary);
155
+ color: var(--color-primary-contrast);
156
+ }
157
+
158
+ .diagram-comment-button.is-danger {
159
+ color: var(--color-error);
160
+ }
161
+
162
+ .diagram-comment-button:disabled {
163
+ cursor: not-allowed;
164
+ opacity: 0.5;
165
+ }
166
+
167
+ .diagram-comment-add:disabled {
168
+ cursor: not-allowed;
169
+ opacity: 0.5;
170
+ }
171
+
172
+ .diagram-comment-markers {
173
+ position: absolute;
174
+ inset: 0;
175
+ pointer-events: none;
176
+ }
177
+
178
+ .diagram-comment-marker {
179
+ position: absolute;
180
+ display: inline-flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ width: 24px;
184
+ height: 24px;
185
+ padding: 0;
186
+ border: 2px solid var(--color-surface);
187
+ border-radius: 50%;
188
+ background: var(--color-comment);
189
+ color: var(--color-primary-contrast);
190
+ box-shadow: var(--shadow-accent-ring);
191
+ pointer-events: auto;
192
+ transform: translate(-50%, -50%);
193
+ }
194
+
195
+ .diagram-comment-marker.is-active {
196
+ box-shadow: var(--shadow-accent-ring-strong);
197
+ }
198
+
199
+ .diagram-comments-drawer {
200
+ position: absolute;
201
+ top: 4.5rem;
202
+ right: var(--space-3);
203
+ bottom: var(--space-3);
204
+ display: flex;
205
+ flex-direction: column;
206
+ width: min(22rem, calc(100vw - (2 * var(--space-3))));
207
+ border: 1px solid var(--color-divider);
208
+ border-radius: var(--radius-lg);
209
+ background: var(--color-surface);
210
+ box-shadow: var(--shadow-lg);
211
+ color: var(--color-text);
212
+ pointer-events: auto;
213
+ overflow: hidden;
214
+ }
215
+
216
+ .diagram-comments-drawer-header {
217
+ display: flex;
218
+ align-items: center;
219
+ justify-content: space-between;
220
+ padding: var(--space-3);
221
+ border-bottom: 1px solid var(--color-divider);
222
+ background: var(--color-surface);
223
+ }
224
+
225
+ .diagram-comments-drawer-header-actions {
226
+ display: flex;
227
+ align-items: center;
228
+ gap: var(--space-1);
229
+ }
230
+
231
+ .diagram-comment-close {
232
+ width: 28px;
233
+ height: 28px;
234
+ border-radius: var(--radius-full);
235
+ background: transparent;
236
+ color: var(--color-text-muted);
237
+ font-size: 22px;
238
+ }
239
+
240
+ .diagram-comments-drawer-content {
241
+ display: flex;
242
+ flex: 1;
243
+ flex-direction: column;
244
+ gap: var(--space-3);
245
+ padding: var(--space-3);
246
+ overflow: auto;
247
+ }
248
+
249
+ .diagram-comment-message-body {
250
+ margin: 0;
251
+ color: var(--color-text-muted);
252
+ white-space: pre-wrap;
253
+ overflow-wrap: anywhere;
254
+ }
255
+
256
+ .diagram-comment-message-meta {
257
+ color: var(--color-comment-text);
258
+ font-weight: 650;
259
+ }
260
+
261
+ .diagram-comments-drawer-content.is-list {
262
+ gap: 0;
263
+ padding: var(--space-2) var(--space-2) var(--space-4);
264
+ }
265
+
266
+ .diagram-comment-anchor-label {
267
+ margin: 0;
268
+ color: var(--color-text-muted);
269
+ font-size: var(--text-ui-sm);
270
+ }
271
+
272
+ .diagram-comment-back {
273
+ align-self: flex-start;
274
+ padding: 0;
275
+ background: transparent;
276
+ color: var(--color-comment-text);
277
+ }
278
+
279
+ .diagram-comment-messages {
280
+ display: grid;
281
+ gap: var(--space-2);
282
+ }
283
+
284
+ .diagram-comment-message {
285
+ padding: var(--space-3);
286
+ border: 1px solid var(--border-comment-soft);
287
+ border-radius: var(--radius-md);
288
+ background: var(--color-surface-2);
289
+ }
290
+
291
+ .diagram-comment-form {
292
+ display: grid;
293
+ gap: var(--space-3);
294
+ }
295
+
296
+ .diagram-comment-input {
297
+ width: 100%;
298
+ box-sizing: border-box;
299
+ resize: vertical;
300
+ padding: var(--space-2) var(--space-3);
301
+ border: 1px solid var(--color-border);
302
+ border-radius: var(--radius-md);
303
+ background: var(--color-surface);
304
+ color: var(--color-text);
305
+ font: inherit;
306
+ }
307
+
308
+ .diagram-comment-input:focus {
309
+ border-color: var(--color-primary);
310
+ outline: none;
311
+ box-shadow: var(--shadow-focus-compact);
312
+ }
313
+
314
+ .diagram-comment-form-actions {
315
+ display: flex;
316
+ justify-content: flex-end;
317
+ gap: var(--space-2);
318
+ }
319
+
320
+ @media (max-width: 600px) {
321
+ .diagram-comments-drawer {
322
+ top: var(--space-3);
323
+ right: var(--space-3);
324
+ bottom: 4.25rem;
325
+ }
326
+ }
327
+
34
328
  .loading-state {
35
329
  display: flex;
36
330
  align-items: center;
@@ -5,7 +5,7 @@ export const COMMENT_EXCERPT_MAX_LENGTH = 160;
5
5
  export const COMMENT_ANCHOR_QUOTE_MAX_LENGTH = 280;
6
6
  export const COMMENT_REACTION_EMOJI_MAX_LENGTH = 16;
7
7
 
8
- const COMMENT_ANCHOR_KINDS = new Set(['line', 'text']);
8
+ const COMMENT_ANCHOR_KINDS = new Set(['diagram-element', 'line', 'text']);
9
9
 
10
10
  function asFiniteNumber(value) {
11
11
  return Number.isFinite(value) ? value : null;
@@ -55,6 +55,38 @@ function normalizeAnchorKind(value) {
55
55
  return COMMENT_ANCHOR_KINDS.has(value) ? value : null;
56
56
  }
57
57
 
58
+ function normalizeDiagramElementId(value) {
59
+ const normalized = asString(value).trim().slice(0, 240);
60
+ return normalized || null;
61
+ }
62
+
63
+ function normalizeDiagramAnchorPoint(value) {
64
+ const point = asObject(value);
65
+ const x = asFiniteNumber(point?.x);
66
+ const y = asFiniteNumber(point?.y);
67
+ return x === null || y === null ? null : { x, y };
68
+ }
69
+
70
+ function normalizeDiagramAnchorSnapshot(value) {
71
+ const snapshot = asObject(value);
72
+ const x = asFiniteNumber(snapshot?.x);
73
+ const y = asFiniteNumber(snapshot?.y);
74
+ const width = asFiniteNumber(snapshot?.width);
75
+ const height = asFiniteNumber(snapshot?.height);
76
+ if (x === null || y === null || width === null || height === null) {
77
+ return null;
78
+ }
79
+
80
+ return {
81
+ height,
82
+ text: normalizeCommentQuote(snapshot?.text),
83
+ type: asString(snapshot?.type).trim() || 'element',
84
+ width,
85
+ x,
86
+ y,
87
+ };
88
+ }
89
+
58
90
  export function normalizeCommentBody(value) {
59
91
  const normalized = String(value ?? '')
60
92
  .replace(/\r\n?/g, '\n')
@@ -196,6 +228,23 @@ export function createCommentId(prefix = 'comment') {
196
228
 
197
229
  export function normalizeCommentAnchor(record = {}) {
198
230
  const anchorKind = normalizeAnchorKind(record.anchorKind);
231
+ if (anchorKind === 'diagram-element') {
232
+ const anchorPoint = normalizeDiagramAnchorPoint(record.anchorPoint);
233
+ const anchorSnapshot = normalizeDiagramAnchorSnapshot(record.anchorSnapshot);
234
+ const elementId = normalizeDiagramElementId(record.elementId);
235
+ if (!anchorPoint || !anchorSnapshot || !elementId) {
236
+ return null;
237
+ }
238
+
239
+ return {
240
+ anchorKind,
241
+ anchorPoint,
242
+ anchorQuote: normalizeCommentQuote(record.anchorQuote || anchorSnapshot.text),
243
+ anchorSnapshot,
244
+ elementId,
245
+ };
246
+ }
247
+
199
248
  const anchorStart = asObject(record.anchorStart);
200
249
  const anchorEnd = asObject(record.anchorEnd);
201
250
  const anchorStartLine = asFiniteNumber(record.anchorStartLine);
@@ -235,12 +284,18 @@ export function createCommentThreadSharedType(record = {}) {
235
284
  messages.push(normalizedMessages.length > 0 ? normalizedMessages : [initialMessage]);
236
285
 
237
286
  const thread = new Y.Map();
238
- thread.set('anchorEnd', anchor.anchorEnd);
239
- thread.set('anchorEndLine', anchor.anchorEndLine);
240
287
  thread.set('anchorKind', anchor.anchorKind);
241
288
  thread.set('anchorQuote', anchor.anchorQuote);
242
- thread.set('anchorStart', anchor.anchorStart);
243
- thread.set('anchorStartLine', anchor.anchorStartLine);
289
+ if (anchor.anchorKind === 'diagram-element') {
290
+ thread.set('anchorPoint', anchor.anchorPoint);
291
+ thread.set('anchorSnapshot', anchor.anchorSnapshot);
292
+ thread.set('elementId', anchor.elementId);
293
+ } else {
294
+ thread.set('anchorEnd', anchor.anchorEnd);
295
+ thread.set('anchorEndLine', anchor.anchorEndLine);
296
+ thread.set('anchorStart', anchor.anchorStart);
297
+ thread.set('anchorStartLine', anchor.anchorStartLine);
298
+ }
244
299
  thread.set('createdAt', asFiniteNumber(record.createdAt) ?? Date.now());
245
300
  thread.set('createdByColor', asString(record.createdByColor));
246
301
  thread.set('createdByName', asString(record.createdByName) || initialMessage.userName);
@@ -266,6 +321,9 @@ export function serializeCommentThread(thread) {
266
321
  anchorQuote: readThreadValue(thread, 'anchorQuote'),
267
322
  anchorStart: readThreadValue(thread, 'anchorStart'),
268
323
  anchorStartLine: readThreadValue(thread, 'anchorStartLine'),
324
+ anchorPoint: readThreadValue(thread, 'anchorPoint'),
325
+ anchorSnapshot: readThreadValue(thread, 'anchorSnapshot'),
326
+ elementId: readThreadValue(thread, 'elementId'),
269
327
  });
270
328
  const messages = serializeMessages(readThreadValue(thread, 'messages'));
271
329
 
@@ -98,13 +98,15 @@ function compareElementVersions(left, right) {
98
98
  }
99
99
 
100
100
  function compareElementIndex(left, right) {
101
- const leftIndex = left?.index ?? '';
102
- const rightIndex = right?.index ?? '';
101
+ const leftIndex = String(left?.index ?? '');
102
+ const rightIndex = String(right?.index ?? '');
103
103
  if (leftIndex !== rightIndex) {
104
- return String(leftIndex).localeCompare(String(rightIndex));
104
+ return leftIndex < rightIndex ? -1 : 1;
105
105
  }
106
106
 
107
- return String(left?.id || '').localeCompare(String(right?.id || ''));
107
+ const leftId = String(left?.id || '');
108
+ const rightId = String(right?.id || '');
109
+ return leftId < rightId ? -1 : leftId > rightId ? 1 : 0;
108
110
  }
109
111
 
110
112
  function getNestedMapValue(map, key, { create = false } = {}) {
@@ -4,20 +4,25 @@ const EXCALIDRAW_FILE_EXTENSION = '.excalidraw';
4
4
  const DRAWIO_FILE_EXTENSION = '.drawio';
5
5
  const MERMAID_FILE_EXTENSIONS = Object.freeze(['.mmd', '.mermaid']);
6
6
  const PLANTUML_FILE_EXTENSIONS = Object.freeze(['.puml', '.plantuml']);
7
+ const STRUCTURIZR_FILE_EXTENSION = '.dsl';
8
+ const STRUCTURIZR_FILE_EXTENSIONS = Object.freeze([STRUCTURIZR_FILE_EXTENSION]);
9
+ const PDF_FILE_EXTENSION = '.pdf';
7
10
  const IMAGE_ATTACHMENT_EXTENSIONS = Object.freeze(['.png', '.jpg', '.jpeg', '.webp', '.gif', '.svg']);
8
11
  const DIAGRAM_FILE_EXTENSIONS = Object.freeze([
9
12
  EXCALIDRAW_FILE_EXTENSION,
10
13
  DRAWIO_FILE_EXTENSION,
11
14
  ...MERMAID_FILE_EXTENSIONS,
12
15
  ...PLANTUML_FILE_EXTENSIONS,
16
+ ...STRUCTURIZR_FILE_EXTENSIONS,
13
17
  ]);
14
18
  const VAULT_FILE_EXTENSIONS = Object.freeze([
15
19
  ...MARKDOWN_FILE_EXTENSIONS,
16
20
  BASE_FILE_EXTENSION,
17
21
  ...DIAGRAM_FILE_EXTENSIONS,
22
+ PDF_FILE_EXTENSION,
18
23
  ...IMAGE_ATTACHMENT_EXTENSIONS,
19
24
  ]);
20
- const STRIP_VAULT_EXTENSION_PATTERN = /\.(?:md|markdown|mdx|base|excalidraw|drawio|mmd|mermaid|puml|plantuml|png|jpe?g|webp|gif|svg)$/i;
25
+ const STRIP_VAULT_EXTENSION_PATTERN = /\.(?:md|markdown|mdx|base|excalidraw|drawio|mmd|mermaid|puml|plantuml|dsl|pdf|png|jpe?g|webp|gif|svg)$/i;
21
26
 
22
27
  function normalizeFilePath(filePath) {
23
28
  return String(filePath ?? '').trim().toLowerCase();
@@ -36,7 +41,10 @@ export {
36
41
  IMAGE_ATTACHMENT_EXTENSIONS,
37
42
  MARKDOWN_FILE_EXTENSIONS,
38
43
  MERMAID_FILE_EXTENSIONS,
44
+ PDF_FILE_EXTENSION,
39
45
  PLANTUML_FILE_EXTENSIONS,
46
+ STRUCTURIZR_FILE_EXTENSION,
47
+ STRUCTURIZR_FILE_EXTENSIONS,
40
48
  VAULT_FILE_EXTENSIONS,
41
49
  };
42
50
 
@@ -65,6 +73,14 @@ export function getVaultFileKind(filePath) {
65
73
  return 'plantuml';
66
74
  }
67
75
 
76
+ if (hasFileExtension(filePath, STRUCTURIZR_FILE_EXTENSIONS)) {
77
+ return 'structurizr';
78
+ }
79
+
80
+ if (hasFileExtension(filePath, [PDF_FILE_EXTENSION])) {
81
+ return 'pdf';
82
+ }
83
+
68
84
  if (hasFileExtension(filePath, IMAGE_ATTACHMENT_EXTENSIONS)) {
69
85
  return 'image';
70
86
  }
@@ -118,13 +134,25 @@ export function isPlantUmlFilePath(filePath) {
118
134
  return getVaultFileKind(filePath) === 'plantuml';
119
135
  }
120
136
 
137
+ export function isStructurizrFilePath(filePath) {
138
+ return getVaultFileKind(filePath) === 'structurizr';
139
+ }
140
+
141
+ export function isPdfFilePath(filePath) {
142
+ return getVaultFileKind(filePath) === 'pdf';
143
+ }
144
+
121
145
  export function isImageAttachmentFilePath(filePath) {
122
146
  return getVaultFileKind(filePath) === 'image';
123
147
  }
124
148
 
125
149
  export function isDiagramFilePath(filePath) {
126
150
  const kind = getVaultFileKind(filePath);
127
- return kind === 'excalidraw' || kind === 'drawio' || kind === 'mermaid' || kind === 'plantuml';
151
+ return kind === 'excalidraw'
152
+ || kind === 'drawio'
153
+ || kind === 'mermaid'
154
+ || kind === 'plantuml'
155
+ || kind === 'structurizr';
128
156
  }
129
157
 
130
158
  export function isVaultFilePath(filePath) {
@@ -133,7 +161,11 @@ export function isVaultFilePath(filePath) {
133
161
 
134
162
  export function supportsCommentsForFilePath(filePath) {
135
163
  const kind = getVaultFileKind(filePath);
136
- return kind === 'markdown' || kind === 'mermaid' || kind === 'plantuml';
164
+ return kind === 'markdown'
165
+ || kind === 'mermaid'
166
+ || kind === 'plantuml'
167
+ || kind === 'structurizr'
168
+ || kind === 'excalidraw';
137
169
  }
138
170
 
139
171
  export function supportsBacklinksForFilePath(filePath) {
@@ -13,11 +13,28 @@ import {
13
13
  import { loadBuildInfo } from './build-info.js';
14
14
  import { isPerfLoggingEnabled } from './perf-logging.js';
15
15
 
16
+ const DEFAULT_SEARCH_MAX_BUFFER_BYTES = 2 * 1024 * 1024;
17
+ const DEFAULT_SEARCH_MAX_FILE_SIZE = '1M';
18
+ const DEFAULT_PDF_UPLOAD_BYTES = 50 * 1024 * 1024;
19
+
16
20
  function parsePositiveInt(rawValue, fallbackValue) {
17
21
  const parsed = Number.parseInt(rawValue ?? '', 10);
18
22
  return Number.isInteger(parsed) && parsed > 0 ? parsed : fallbackValue;
19
23
  }
20
24
 
25
+ function normalizeSearchMaxFileSize(rawValue, fallbackValue = DEFAULT_SEARCH_MAX_FILE_SIZE) {
26
+ const normalized = String(rawValue ?? '').trim();
27
+ if (!normalized) {
28
+ return fallbackValue;
29
+ }
30
+
31
+ if (!/^[1-9]\d*(?:[KMG])?$/iu.test(normalized)) {
32
+ throw new Error('COLLABMD_SEARCH_MAX_FILE_SIZE must be a positive byte count with an optional K, M, or G suffix.');
33
+ }
34
+
35
+ return normalized.toUpperCase();
36
+ }
37
+
21
38
  function parseOptionalPositiveInt(rawValue, {
22
39
  fallbackValue = null,
23
40
  variableName = 'value',
@@ -56,6 +73,30 @@ function resolveDrawioBaseUrl(value) {
56
73
  return normalizeOptionalString(value) || 'https://embed.diagrams.net';
57
74
  }
58
75
 
76
+ function resolveStructurizrServerUrl(value) {
77
+ const normalized = normalizeOptionalString(value);
78
+ if (!normalized) {
79
+ return '';
80
+ }
81
+
82
+ let parsedUrl;
83
+ try {
84
+ parsedUrl = new URL(normalized);
85
+ } catch {
86
+ throw new Error('STRUCTURIZR_SERVER_URL must be an absolute HTTP or HTTPS URL.');
87
+ }
88
+
89
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
90
+ throw new Error('STRUCTURIZR_SERVER_URL must use HTTP or HTTPS.');
91
+ }
92
+
93
+ if (parsedUrl.search || parsedUrl.hash) {
94
+ throw new Error('STRUCTURIZR_SERVER_URL must not include a query string or hash.');
95
+ }
96
+
97
+ return normalized.replace(/\/+$/u, '');
98
+ }
99
+
59
100
  function normalizeAppBasePath(basePath) {
60
101
  const normalized = normalizeOptionalString(basePath);
61
102
  if (!normalized || normalized === '/') {
@@ -278,6 +319,31 @@ function loadOidcConfig(overrides = {}, { basePath = '' } = {}) {
278
319
  };
279
320
  }
280
321
 
322
+ function loadStructurizrConfig(overrides = {}, { vaultDir } = {}) {
323
+ const serverUrl = resolveStructurizrServerUrl(
324
+ overrides.serverUrl
325
+ ?? process.env.COLLABMD_STRUCTURIZR_SERVER_URL
326
+ ?? process.env.STRUCTURIZR_SERVER_URL,
327
+ );
328
+ const mirrorDir = resolveOptionalPath(
329
+ overrides.mirrorDir
330
+ ?? process.env.COLLABMD_STRUCTURIZR_MIRROR_DIR
331
+ ?? process.env.STRUCTURIZR_MIRROR_DIR,
332
+ ) || resolve(vaultDir, '.collabmd/structurizr');
333
+
334
+ return {
335
+ enabled: Boolean(serverUrl),
336
+ mirrorDir,
337
+ serverUrl,
338
+ trustedExecutableDsl: overrides.trustedExecutableDsl
339
+ ?? parseBooleanFlag(
340
+ process.env.COLLABMD_STRUCTURIZR_TRUSTED_EXECUTABLE_DSL
341
+ ?? process.env.STRUCTURIZR_TRUSTED_EXECUTABLE_DSL,
342
+ false,
343
+ ),
344
+ };
345
+ }
346
+
281
347
  function loadHostedConfig(overrides = {}, { authStrategy, vaultDir } = {}) {
282
348
  const enabled = overrides.enabled ?? parseBooleanFlag(process.env.COLLABMD_HOSTED_ENABLED, false);
283
349
  const metadataDbPath = resolveOptionalPath(
@@ -361,6 +427,7 @@ export function loadConfig(overrides = {}) {
361
427
  : null;
362
428
  const git = loadGitConfig(overrides.git);
363
429
  const hosted = loadHostedConfig(overrides.hosted, { authStrategy, vaultDir });
430
+ const structurizr = loadStructurizrConfig(overrides.structurizr, { vaultDir });
364
431
  const build = loadBuildInfo({
365
432
  explicitBuildId: process.env.COLLABMD_BUILD_ID,
366
433
  projectRoot,
@@ -396,6 +463,18 @@ export function loadConfig(overrides = {}) {
396
463
  maxBaseQueryRows: parsePositiveInt(process.env.COLLABMD_MAX_BASE_QUERY_ROWS, 5_000),
397
464
  maxDownloadFileBytes: parsePositiveInt(process.env.COLLABMD_MAX_DOWNLOAD_FILE_BYTES, 268_435_456),
398
465
  maxInitialSyncBytes: parsePositiveInt(process.env.COLLABMD_MAX_INITIAL_SYNC_BYTES, 16_777_216),
466
+ maxPdfUploadBytes: parsePositiveInt(
467
+ overrides.maxPdfUploadBytes ?? process.env.COLLABMD_MAX_PDF_UPLOAD_BYTES,
468
+ DEFAULT_PDF_UPLOAD_BYTES,
469
+ ),
470
+ searchMaxBufferBytes: parsePositiveInt(
471
+ overrides.searchMaxBufferBytes ?? process.env.COLLABMD_SEARCH_MAX_BUFFER_BYTES,
472
+ DEFAULT_SEARCH_MAX_BUFFER_BYTES,
473
+ ),
474
+ searchMaxFileSize: normalizeSearchMaxFileSize(
475
+ overrides.searchMaxFileSize ?? process.env.COLLABMD_SEARCH_MAX_FILE_SIZE,
476
+ ),
477
+ structurizr,
399
478
  perfLoggingEnabled: overrides.perfLoggingEnabled ?? isPerfLoggingEnabled(process.env.COLLABMD_PERF_LOGGING),
400
479
  port: parsePositiveInt(process.env.PORT, 1234),
401
480
  nodeEnv,
@@ -1,4 +1,5 @@
1
1
  import { createServer } from 'http';
2
+ import { resolve } from 'node:path';
2
3
 
3
4
  import { loadConfig } from './config/env.js';
4
5
  import { createAuthService } from './auth/create-auth-service.js';
@@ -13,6 +14,7 @@ import { GitHubAppClient } from './infrastructure/github/github-app-client.js';
13
14
  import { GitHubSetupFlow } from './infrastructure/github/github-setup-flow.js';
14
15
  import { HostedWorkspaceService } from './domain/hosted-workspace.js';
15
16
  import { PlantUmlRenderer } from './infrastructure/plantuml/plantuml-renderer.js';
17
+ import { StructurizrWorkspaceService } from './infrastructure/structurizr/structurizr-workspace-service.js';
16
18
  import { RoomRegistry } from './domain/collaboration/room-registry.js';
17
19
  import { RipgrepSearchService } from './domain/ripgrep-search-service.js';
18
20
  import { createRequestHandler } from './infrastructure/http/create-request-handler.js';
@@ -83,12 +85,20 @@ export function createAppServer(config = loadConfig()) {
83
85
  const plantUmlRenderer = new PlantUmlRenderer({
84
86
  serverUrl: config.plantumlServerUrl,
85
87
  });
88
+ const structurizrWorkspaceService = new StructurizrWorkspaceService({
89
+ mirrorDir: config.structurizr?.mirrorDir || resolve(config.vaultDir, '.collabmd/structurizr'),
90
+ serverUrl: config.structurizr?.serverUrl || '',
91
+ trustedExecutableDsl: config.structurizr?.trustedExecutableDsl,
92
+ vaultDir: config.vaultDir,
93
+ });
86
94
  const gitService = new GitService({
87
95
  commandEnv: config.git?.commandEnv,
88
96
  enabled: config.gitEnabled,
89
97
  vaultDir: config.vaultDir,
90
98
  });
91
99
  const searchService = new RipgrepSearchService({
100
+ maxBufferBytes: config.searchMaxBufferBytes,
101
+ maxFileSize: config.searchMaxFileSize,
92
102
  perfLoggingEnabled: config.perfLoggingEnabled,
93
103
  vaultDir: config.vaultDir,
94
104
  });
@@ -153,6 +163,7 @@ export function createAppServer(config = loadConfig()) {
153
163
  fileSystemSyncService,
154
164
  hostedWorkspaceService,
155
165
  githubSetupFlow,
166
+ structurizrWorkspaceService,
156
167
  );
157
168
  const httpServer = createServer((req, res) => {
158
169
  requestHandler(req, res).catch((error) => {
@@ -315,6 +326,7 @@ export function createAppServer(config = loadConfig()) {
315
326
  gitService,
316
327
  hostedWorkspaceService,
317
328
  searchService,
329
+ structurizrWorkspaceService,
318
330
  setTestHydrateDelayMs(delayMs = 0) {
319
331
  testControls.wsRoomHydrateDelayMs = Math.max(0, Number(delayMs) || 0);
320
332
  },
@@ -2,7 +2,7 @@ import { dump as dumpYaml, loadAll as loadAllYaml } from 'js-yaml';
2
2
 
3
3
  const SUPPORTED_VIEW_TYPES = new Set(['cards', 'list', 'table']);
4
4
 
5
- function isPlainObject(value) {
5
+ export function isPlainObject(value) {
6
6
  return Object.prototype.toString.call(value) === '[object Object]';
7
7
  }
8
8
 
@@ -1,9 +1,6 @@
1
1
  import { isImageAttachmentFilePath } from '../../../domain/file-kind.js';
2
2
  import { resolveVaultRelativePath } from '../../../domain/vault-paths.js';
3
-
4
- function isPlainObject(value) {
5
- return Object.prototype.toString.call(value) === '[object Object]';
6
- }
3
+ import { isPlainObject } from './base-definition.js';
7
4
 
8
5
  export function createLinkValue(target, {
9
6
  display = '',