collabmd 0.1.46 → 0.1.48

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 (317) hide show
  1. package/README.md +9 -5
  2. package/dist/client/assets/{CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js → CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js} +1 -1
  3. package/dist/client/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -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/babel-CY5KOv-I.js +16 -0
  8. package/dist/client/assets/base-BYODPHdS.js +1 -0
  9. package/dist/client/assets/blockDiagram-NRAW4CY4-C6DtJy5Y.js +129 -0
  10. package/dist/client/assets/browser-BKLM0ThC-IxjwuOIz-BBqQnUEb.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-ui-shared-DuoyznXW.js +7 -0
  53. package/dist/client/assets/cynefin-OW5HDTMX-7tP7QfM3.js +1 -0
  54. package/dist/client/assets/{cynefinDiagram-MW4NZA55-CJxXfJek.js → cynefinDiagram-5FMLGOSQ-CdTPi2yO.js} +1 -1
  55. package/dist/client/assets/dagre-3AP2YEHR-5gtJtd0O.js +4 -0
  56. package/dist/client/assets/dagre-PrKaheQc.js +1 -0
  57. package/dist/client/assets/{diagram-7IWD3JNH-B2d2Bm15.js → diagram-S7CK7UJ4-BudWz9WU.js} +4 -4
  58. package/dist/client/assets/{diagram-UB23O5K3-DJcKCwv9.js → diagram-UQ7AKVKN-3v4rbH-s.js} +1 -1
  59. package/dist/client/assets/{diagram-B4RE2ZJO-NP4UAwjR.js → diagram-VSXAHHWV-CQRVEZR7.js} +1 -1
  60. package/dist/client/assets/{diagram-Q27KOJAE-DylDuwor.js → diagram-VX7I27RA-C_-rj0sw.js} +1 -1
  61. package/dist/client/assets/{diagram-LBJQPF4R-D1FJQV8t.js → diagram-Z3DM3KII-B4yxavgj.js} +1 -1
  62. package/dist/client/assets/direct-engine-DdrQKpgq-CtKfQzCt.js +5 -0
  63. package/dist/client/assets/dist-73RPdcyU.js +1 -0
  64. package/dist/client/assets/{dist-Bm6pf9Bl.js → dist-BJ1bJs33.js} +1 -1
  65. package/dist/client/assets/{dist-BalScOwZ.js → dist-BK9QvQrc.js} +1 -1
  66. package/dist/client/assets/{dist-DLMiIsNC.js → dist-BPHLJ09L.js} +1 -1
  67. package/dist/client/assets/{dist-Bf8f4HmM.js → dist-B_yQaEv_.js} +1 -1
  68. package/dist/client/assets/{dist-CC5IrQMG.js → dist-BeajGMhO.js} +1 -1
  69. package/dist/client/assets/{dist-PDZ3bSqm.js → dist-Bw3VIE_v.js} +1 -1
  70. package/dist/client/assets/{dist-xElaxbia.js → dist-ByrG2qBA.js} +1 -1
  71. package/dist/client/assets/{dist-ule2n6ak.js → dist-C5NgpdG5.js} +1 -1
  72. package/dist/client/assets/dist-CH-sQu3r.js +1 -0
  73. package/dist/client/assets/dist-CKS_-are.js +1 -0
  74. package/dist/client/assets/{dist-D-Z6FLem.js → dist-CdmKGRGr.js} +1 -1
  75. package/dist/client/assets/dist-ChRoo3IB.js +9 -0
  76. package/dist/client/assets/{dist-dtAdgL39.js → dist-CietwTVS.js} +1 -1
  77. package/dist/client/assets/{dist-jv4WdPnK.js → dist-D37Hyu3h.js} +1 -1
  78. package/dist/client/assets/dist-D3fehAZ2.js +2 -0
  79. package/dist/client/assets/{dist-BEwK4csK.js → dist-D5wCC32z.js} +1 -1
  80. package/dist/client/assets/{dist-shrl6K_0.js → dist-DDUn5zTz.js} +1 -1
  81. package/dist/client/assets/{dist-CZgOmxK6.js → dist-DGEbEfw4.js} +1 -1
  82. package/dist/client/assets/{dist-B5HTH2BO.js → dist-DVy5woUy.js} +1 -1
  83. package/dist/client/assets/{dist-DZKu9Cs8.js → dist-DZAAWTG-.js} +1 -1
  84. package/dist/client/assets/{dist-TjMh8n1u.js → dist-Dir5dDKZ.js} +1 -1
  85. package/dist/client/assets/dist-Dl_tpDSr.js +1 -0
  86. package/dist/client/assets/{dist-FWJsgGYI.js → dist-DuH3ZrHo.js} +1 -1
  87. package/dist/client/assets/{dist-BjHJDtyU.js → dist-DutPuFmC.js} +1 -1
  88. package/dist/client/assets/{dist-Cqhv5LAk.js → dist-LQ4kDCKz.js} +1 -1
  89. package/dist/client/assets/{dist-CCP_AKPG.js → dist-RKBTaQMb.js} +1 -1
  90. package/dist/client/assets/{dist-BoVBdSjk.js → dist-Tw-Fxpeb.js} +1 -1
  91. package/dist/client/assets/dist-eBx8q6Sy.js +1 -0
  92. package/dist/client/assets/{dist-rGBmqxC7.js → dist-mj2Ht75J.js} +1 -1
  93. package/dist/client/assets/{dist-BDt3rz7l.js → dist-netZOQtD.js} +1 -1
  94. package/dist/client/assets/document-formatter-Dxl_a8XO.js +2 -0
  95. package/dist/client/assets/{drawio-editor-FzY1cVw8.js → drawio-editor-BVaNNtYp.js} +2 -2
  96. package/dist/client/assets/{drawioEditor-BjiKJqlc.js → drawioEditor-BkIBlXx0.js} +2 -2
  97. package/dist/client/assets/{ebnfDiagram-BXEA7PRR-nw0wmA6y.js → ebnfDiagram-PWID7BFC-OXa8VEp1.js} +1 -1
  98. package/dist/client/assets/editor-session-DMyVdHLj.js +54 -0
  99. package/dist/client/assets/embedded-editor-base-B3l6Xy65.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/estree-CuT_pB8K.js +44 -0
  105. package/dist/client/assets/eventmodeling-NTZA5JFV-BR2FzK4R.js +1 -0
  106. package/dist/client/assets/excalidraw-editor-BbSbI80a.css +1 -0
  107. package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +9 -0
  108. package/dist/client/assets/excalidrawEditor-ChqF_d82.js +2 -0
  109. package/dist/client/assets/export-page-Dyu0XCbu.js +57 -0
  110. package/dist/client/assets/exportDocument-CJBx4Xjx.css +1 -0
  111. package/dist/client/assets/exportDocument-Dgvfa2Sd.js +2 -0
  112. package/dist/client/assets/{file-icon-svg-CQAjlWjK.js → file-icon-svg-Y_kpF957.js} +1 -1
  113. package/dist/client/assets/file-kind-BwMIcZbi.js +1 -0
  114. package/dist/client/assets/file-search-DDLyyLDU.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/html-Cdnr2qzU.js +25 -0
  122. package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +1 -0
  123. package/dist/client/assets/index-CSNIMyOP.css +1 -0
  124. package/dist/client/assets/index-DG3N2Ps-.js +2 -0
  125. package/dist/client/assets/info-A6RAGUB7-BlU-8_xu.js +1 -0
  126. package/dist/client/assets/{infoDiagram-6WML65LV-DYB8HCDQ.js → infoDiagram-RXCK75RN-BMzo6KIn.js} +1 -1
  127. package/dist/client/assets/{ishikawaDiagram-WSZJBQD7-Coz_P3t6.js → ishikawaDiagram-5VMMS53U-BIM3h287.js} +1 -1
  128. package/dist/client/assets/{journeyDiagram-NVQOT4AX-B6edChce.js → journeyDiagram-EYS64GPL-mF6Lh8O-.js} +1 -1
  129. package/dist/client/assets/{kanban-definition-27J2QSJJ-BFd9-cLc.js → kanban-definition-3QL26DDD-DLN2NyoR.js} +2 -2
  130. package/dist/client/assets/{line-B_S_S8kV.js → line-BfTWJmgf.js} +1 -1
  131. package/dist/client/assets/main-D0wCxpVn.js +903 -0
  132. package/dist/client/assets/markdown-CByV-4CU.js +70 -0
  133. package/dist/client/assets/{mermaid-parser.core-CUVdebAV.js → mermaid-parser.core-Bl0efOMt.js} +2 -2
  134. package/dist/client/assets/mermaid.core-BJRLUQZE.js +11 -0
  135. package/dist/client/assets/{mindmap-definition-FAOFIHXS-C9PQ38Al.js → mindmap-definition-FBJOCRG2-CRyHaHTk.js} +1 -1
  136. package/dist/client/assets/packet-AYTQ26CC-BSJEH9Lb.js +1 -0
  137. package/dist/client/assets/pdfium-RAgkpwfK.wasm +0 -0
  138. package/dist/client/assets/{pegDiagram-VL7TDLO6-BMZUrSaU.js → pegDiagram-XKGWAZYB-B31fKPR2.js} +1 -1
  139. package/dist/client/assets/pie-WAS4IAKB-qxv01Y8W.js +1 -0
  140. package/dist/client/assets/{pieDiagram-7S7Q4E2Y-h8kbCL9o.js → pieDiagram-E7YTZNPT-B5OZPb88.js} +1 -1
  141. package/dist/client/assets/preview-render-compiler-CrJIooVD.js +35 -0
  142. package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +1 -0
  143. package/dist/client/assets/{preview-render-profile-CE-5rVTC.js → preview-render-profile-B4RWYWHt.js} +1 -1
  144. package/dist/client/assets/preview-render-worker-_QTxqKvP.js +60 -0
  145. package/dist/client/assets/prod-BiYPMR1i.js +177 -0
  146. package/dist/client/assets/prod-VxdGZ5Ly.js +1 -0
  147. package/dist/client/assets/{quadrantDiagram-CIZ2JOQS-CkElyfMi.js → quadrantDiagram-AXDQQJYC-Drrw14YH.js} +1 -1
  148. package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +1 -0
  149. package/dist/client/assets/radar-RG4KPBEZ-B6h6pWOs.js +1 -0
  150. package/dist/client/assets/railroad-74A4TZTK-CGtTWdGc.js +1 -0
  151. package/dist/client/assets/railroad-abnf-HS5TGJTU-Cq7y22IA.js +1 -0
  152. package/dist/client/assets/railroad-ebnf-LZEXJU2U-V0aQVv9m.js +1 -0
  153. package/dist/client/assets/railroad-peg-WCYAUIDC-BQiIsX_p.js +1 -0
  154. package/dist/client/assets/{railroadDiagram-AXF67PYL-c75gnikD.js → railroadDiagram-O6MQD6OU-BPifP0MB.js} +1 -1
  155. package/dist/client/assets/{requirementDiagram-LRYGKXZP-mNxKLuHS.js → requirementDiagram-EFPCY7ZU-CRZG6mRB.js} +2 -2
  156. package/dist/client/assets/{sankeyDiagram-W5VNT64P-0OhplksI.js → sankeyDiagram-P5KCCOFB-DvarEJpo.js} +1 -1
  157. package/dist/client/assets/{sequenceDiagram-SI44F4Z6-BJ_yAocC.js → sequenceDiagram-WJ2MYXX4-B4oWlb-w.js} +1 -1
  158. package/dist/client/assets/standalone-6z5x8CWe.js +29 -0
  159. package/dist/client/assets/{stateDiagram-OKZ733FA-Cc83O86s.js → stateDiagram-HBIQ2CUA-qbHIIqRZ.js} +1 -1
  160. package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +1 -0
  161. package/dist/client/assets/swimlanes-XN3QIQJK-xB6CtUGj.js +1 -0
  162. package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +8 -0
  163. package/dist/client/assets/{timeline-definition-Z64GVDOM-BWDAGTHz.js → timeline-definition-24CTP7MA-Lj_yTNlY.js} +1 -1
  164. package/dist/client/assets/treeView-Q6P3EWNA-BTTYcvrF.js +1 -0
  165. package/dist/client/assets/treemap-WGGIJYW6-Cg7tyfH8.js +1 -0
  166. package/dist/client/assets/{vault-api-client-_LpV1aIn.js → vault-api-client-BkwdFjx0.js} +2 -2
  167. package/dist/client/assets/vault-utils-DvoSftJT.js +22 -0
  168. package/dist/client/assets/{vennDiagram-T6HMQDX7-LOSsnlMB.js → vennDiagram-4TSXK5OY-BekRp5Y0.js} +1 -1
  169. package/dist/client/assets/wardley-WFR3VGLG-C6N1rULY.js +1 -0
  170. package/dist/client/assets/{wardleyDiagram-T6FBY63Y-BxII3foY.js → wardleyDiagram-VM6X3IG4-kdnV_Hdm.js} +1 -1
  171. package/dist/client/assets/worker-engine-m0rlHn8R-S8mpn_O0.js +17369 -0
  172. package/dist/client/assets/{xychartDiagram-ELKLHX3M-B-pTEjju.js → xychartDiagram-S5SC5T6Z-DufGwNSB.js} +3 -3
  173. package/dist/client/assets/yaml-9ltHPDNO.js +154 -0
  174. package/dist/client/drawio-editor.html +1 -1
  175. package/dist/client/excalidraw-editor.html +1 -1
  176. package/dist/client/export-document.html +3 -3
  177. package/dist/client/index.html +56 -24
  178. package/package.json +22 -18
  179. package/src/client/app/index.html +53 -21
  180. package/src/client/application/app-shell/comments-feature.js +2 -3
  181. package/src/client/application/app-shell/export-feature.js +17 -1
  182. package/src/client/application/app-shell/git-feature.js +30 -11
  183. package/src/client/application/app-shell/presence-feature.js +2 -2
  184. package/src/client/application/app-shell/ui-feature-identity.js +13 -0
  185. package/src/client/application/app-shell/ui-feature-shell.js +228 -9
  186. package/src/client/application/app-shell-elements.js +5 -0
  187. package/src/client/application/pdf-preview-controller.js +53 -970
  188. package/src/client/application/preview-render-compiler.js +3 -0
  189. package/src/client/application/quick-switcher-loader.js +1 -1
  190. package/src/client/application/workspace-coordinator.js +21 -4
  191. package/src/client/application/workspace-preview-controller.js +120 -5
  192. package/src/client/application/workspace-route-controller.js +4 -1
  193. package/src/client/assets/vendor/highlight/github-dark.min.css +2 -10
  194. package/src/client/assets/vendor/highlight/github.min.css +2 -10
  195. package/src/client/assets/vendor/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
  196. package/src/client/assets/vendor/jetbrains-mono/OFL.txt +93 -0
  197. package/src/client/bootstrap/collabmd-app-shell.js +31 -8
  198. package/src/client/domain/document-formatter.js +193 -0
  199. package/src/client/domain/file-search.js +73 -0
  200. package/src/client/domain/git-labels.js +5 -0
  201. package/src/client/domain/vault-paths.js +6 -4
  202. package/src/client/domain/wiki-link-completions.js +20 -20
  203. package/src/client/drawio-editor.js +8 -3
  204. package/src/client/excalidraw-editor.js +163 -6
  205. package/src/client/export/export-host.js +57 -36
  206. package/src/client/export/export-page.js +20 -6
  207. package/src/client/export/export-pipeline.js +322 -22
  208. package/src/client/infrastructure/editor-session.js +4 -0
  209. package/src/client/infrastructure/editor-view-adapter.js +60 -14
  210. package/src/client/presentation/bases-preview-controller.js +35 -11
  211. package/src/client/presentation/comment-ui/comment-ui-render.js +4 -0
  212. package/src/client/presentation/comment-ui-controller.js +2 -0
  213. package/src/client/presentation/excalidraw-embed-controller.js +7 -0
  214. package/src/client/presentation/file-action-controller.js +15 -2
  215. package/src/client/presentation/file-explorer-controller.js +3 -5
  216. package/src/client/presentation/file-explorer-view.js +43 -45
  217. package/src/client/presentation/file-history-view-controller.js +6 -1
  218. package/src/client/presentation/file-tree-state.js +5 -14
  219. package/src/client/presentation/git-diff-view-controller.js +36 -11
  220. package/src/client/presentation/git-panel-controller.js +12 -8
  221. package/src/client/presentation/quick-switcher-controller.js +92 -153
  222. package/src/client/styles/components/scrollbars.css +10 -0
  223. package/src/client/styles/export-document.css +44 -29
  224. package/src/client/styles/features/collaboration-presence.css +13 -1
  225. package/src/client/styles/features/preview-markdown.css +79 -0
  226. package/src/client/styles/features/quick-switcher.css +8 -0
  227. package/src/client/styles/foundation/themes.css +1 -0
  228. package/src/client/styles/foundation/tokens.css +8 -0
  229. package/src/client/styles/layout/shell.css +73 -339
  230. package/src/client/styles/layout/sidebar.css +42 -4
  231. package/src/client/styles/layout/view-modes.css +2 -0
  232. package/src/client/styles/overrides/codemirror.css +31 -19
  233. package/src/client/styles/overrides/highlightjs.css +20 -4
  234. package/src/client/styles/surfaces/excalidraw-editor.css +42 -0
  235. package/src/domain/file-kind.js +12 -1
  236. package/src/server/domain/ripgrep-search-service.js +110 -37
  237. package/src/server/infrastructure/git/git-service.js +23 -11
  238. package/src/server/infrastructure/http/create-git-api-command-handler.js +3 -1
  239. package/src/server/infrastructure/http/create-structurizr-api-handler.js +4 -2
  240. package/src/server/infrastructure/persistence/path-utils.js +10 -4
  241. package/src/server/infrastructure/persistence/vault-file-store.js +2 -0
  242. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +33 -7
  243. package/dist/client/assets/architecture-TIHT7OUA-CsHfPErM.js +0 -1
  244. package/dist/client/assets/base-CxPEiHuy.js +0 -1
  245. package/dist/client/assets/blockDiagram-VBNYF7ZC-CipJt9Jl.js +0 -132
  246. package/dist/client/assets/c4Diagram-5PPSVZJV-B5ktVx6g.js +0 -10
  247. package/dist/client/assets/channel-4Jkmq93I.js +0 -1
  248. package/dist/client/assets/chunk-7BUUIJ7U-Bb538aSH.js +0 -1
  249. package/dist/client/assets/chunk-7Z6QIM7H-BP9Pdsm9.js +0 -10
  250. package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +0 -41
  251. package/dist/client/assets/chunk-I66GZJ75-CVFiiffQ.js +0 -127
  252. package/dist/client/assets/chunk-J7OUQ5F2-4CEb7pvH.js +0 -2
  253. package/dist/client/assets/chunk-JQJVKLGR-cx8X_24v.js +0 -156
  254. package/dist/client/assets/chunk-QR6OTTB3-CDAA_5Ib.js +0 -62
  255. package/dist/client/assets/chunk-RYQCIY6F-D-a0zH8K.js +0 -1
  256. package/dist/client/assets/chunk-UBXNYLIW-Bhk-PbFK.js +0 -1
  257. package/dist/client/assets/chunk-W5SLKNZC-BdNSCxZ9.js +0 -1
  258. package/dist/client/assets/chunk-WRU74C26-h6_XkD3_.js +0 -70
  259. package/dist/client/assets/chunk-ZIRB5QZD-O39ZBUk3.js +0 -32
  260. package/dist/client/assets/classDiagram-JCYQIIEL-L7lsyW_w.js +0 -1
  261. package/dist/client/assets/classDiagram-v2-OCEON4UE-L7lsyW_w.js +0 -1
  262. package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +0 -7
  263. package/dist/client/assets/cynefin-VYW2F7L2-Ds2Fw2Y0.js +0 -1
  264. package/dist/client/assets/dagre-Buvkdvvj.js +0 -1
  265. package/dist/client/assets/dagre-VZM6K2ZE-L1xArOGs.js +0 -4
  266. package/dist/client/assets/dist-B5Jf1SLZ.js +0 -2
  267. package/dist/client/assets/dist-BKW4PALF.js +0 -1
  268. package/dist/client/assets/dist-BWcHHOx-.js +0 -1
  269. package/dist/client/assets/dist-DaYdhcVs.js +0 -1
  270. package/dist/client/assets/dist-Kh2COra_.js +0 -1
  271. package/dist/client/assets/dist-tOaegDYS2.js +0 -1
  272. package/dist/client/assets/editor-session-Cm9ekeNo.js +0 -54
  273. package/dist/client/assets/embedded-editor-base-CwTkk911.css +0 -1
  274. package/dist/client/assets/erDiagram-JOGREHBK-cYUpEKpf.js +0 -85
  275. package/dist/client/assets/es-DXGV3RHd.js +0 -22
  276. package/dist/client/assets/eventmodeling-45OFAUF4-CLEiVx5s.js +0 -1
  277. package/dist/client/assets/excalidraw-editor-B46zsTFI.js +0 -9
  278. package/dist/client/assets/excalidraw-editor-Bt7gMSoh.css +0 -1
  279. package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +0 -2
  280. package/dist/client/assets/export-page-A7NHawJY.js +0 -39
  281. package/dist/client/assets/exportDocument-B2L8fe34.css +0 -1
  282. package/dist/client/assets/exportDocument-BaqcOAAW.js +0 -2
  283. package/dist/client/assets/file-kind-BbqgGzpc.js +0 -1
  284. package/dist/client/assets/flowDiagram-UKHOOZJN-D0ypP0Ez.js +0 -1
  285. package/dist/client/assets/gitGraph-TEB2WS4Q-CZFBqwW-.js +0 -1
  286. package/dist/client/assets/github-dark.min-Z5exjX_n.css +0 -1
  287. package/dist/client/assets/github.min-D2BCvnWf.css +0 -1
  288. package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +0 -1
  289. package/dist/client/assets/index-ClbjMBVt.js +0 -2
  290. package/dist/client/assets/index-Pum8ET-5.css +0 -1
  291. package/dist/client/assets/info-DKCQHKI2--1InqQeT.js +0 -1
  292. package/dist/client/assets/main-B3uPyqic.js +0 -893
  293. package/dist/client/assets/map-BaFkSB1l.js +0 -1
  294. package/dist/client/assets/mermaid.core-DN-lF51U.js +0 -11
  295. package/dist/client/assets/packet-7NZHBO7P-BGMXB0XL.js +0 -1
  296. package/dist/client/assets/pdf-BL9Pr2D5.js +0 -54
  297. package/dist/client/assets/pdf.worker-CLesOks4.mjs +0 -64857
  298. package/dist/client/assets/pdf_viewer-FVkkThnz.js +0 -551
  299. package/dist/client/assets/pie-RZYD4A2V-DgYg3tCt.js +0 -1
  300. package/dist/client/assets/preview-render-compiler-BD-XhkS2.js +0 -35
  301. package/dist/client/assets/preview-render-compiler-BKedaMxx.js +0 -1
  302. package/dist/client/assets/preview-render-worker-CiPqc9n6.js +0 -60
  303. package/dist/client/assets/prod-Dy20X7eT.js +0 -1
  304. package/dist/client/assets/prod-hnwh7wRM.js +0 -177
  305. package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +0 -12
  306. package/dist/client/assets/radar-I7S5WNFK-Ag-zp_Rq.js +0 -1
  307. package/dist/client/assets/railroad-3IZDKUUU-aibJDIDV.js +0 -1
  308. package/dist/client/assets/railroad-abnf-AHOZXSZD-BBMEuvIl.js +0 -1
  309. package/dist/client/assets/railroad-ebnf-EBAXGLYW-Be1nseej.js +0 -1
  310. package/dist/client/assets/railroad-peg-LSFZ7HO6-DIvD-Eyb.js +0 -1
  311. package/dist/client/assets/stateDiagram-v2-UEYNNEHI-B1-BufUk.js +0 -1
  312. package/dist/client/assets/swimlanes-SLNWSIFB-oVTWEJIj.js +0 -2
  313. package/dist/client/assets/swimlanesDiagram-ULZ7WXOC-C5OTVwEu.js +0 -8
  314. package/dist/client/assets/treeView-QDETBFTQ-uHZ-3Fz8.js +0 -1
  315. package/dist/client/assets/treemap-6X3UGDF4-BnUKyy3l.js +0 -1
  316. package/dist/client/assets/vault-utils-wdQ0RNR9.js +0 -1
  317. package/dist/client/assets/wardley-OPB4EBWU-Da7TLC2F.js +0 -1
@@ -38,6 +38,7 @@ body[data-surface='excalidraw-editor'][data-document-mode='preview'] .disable-vi
38
38
  pointer-events: none;
39
39
  }
40
40
 
41
+ .excalidraw-editor-toolbar,
41
42
  .diagram-comments-toolbar {
42
43
  display: inline-flex;
43
44
  align-items: center;
@@ -45,6 +46,47 @@ body[data-surface='excalidraw-editor'][data-document-mode='preview'] .disable-vi
45
46
  pointer-events: auto;
46
47
  }
47
48
 
49
+ .excalidraw-presentation-toggle {
50
+ width: var(--control-h-md);
51
+ min-width: var(--control-h-md);
52
+ height: var(--control-h-md);
53
+ }
54
+
55
+ .excalidraw-presentation-navigation {
56
+ position: absolute;
57
+ z-index: 30;
58
+ bottom: var(--space-4);
59
+ left: 50%;
60
+ display: flex;
61
+ align-items: center;
62
+ gap: var(--space-2);
63
+ padding: var(--space-2);
64
+ border: 1px solid var(--color-border);
65
+ border-radius: var(--radius-lg);
66
+ background: var(--color-surface-raised);
67
+ box-shadow: var(--shadow-md);
68
+ color: var(--color-text);
69
+ transform: translateX(-50%);
70
+ }
71
+
72
+ .excalidraw-presentation-navigation .diagram-comment-button {
73
+ width: var(--control-h-sm);
74
+ min-width: var(--control-h-sm);
75
+ height: var(--control-h-sm);
76
+ padding: 0;
77
+ }
78
+
79
+ .excalidraw-presentation-status {
80
+ min-width: 7rem;
81
+ max-width: min(20rem, 55vw);
82
+ color: var(--color-text-muted);
83
+ font-size: var(--text-ui-sm);
84
+ text-align: center;
85
+ overflow: hidden;
86
+ text-overflow: ellipsis;
87
+ white-space: nowrap;
88
+ }
89
+
48
90
  .diagram-comment-button,
49
91
  .diagram-comment-close,
50
92
  .diagram-comment-back,
@@ -1,4 +1,5 @@
1
1
  const MARKDOWN_FILE_EXTENSIONS = Object.freeze(['.md', '.markdown', '.mdx']);
2
+ const HTML_FILE_EXTENSIONS = Object.freeze(['.html', '.htm']);
2
3
  const BASE_FILE_EXTENSION = '.base';
3
4
  const EXCALIDRAW_FILE_EXTENSION = '.excalidraw';
4
5
  const DRAWIO_FILE_EXTENSION = '.drawio';
@@ -17,12 +18,13 @@ const DIAGRAM_FILE_EXTENSIONS = Object.freeze([
17
18
  ]);
18
19
  const VAULT_FILE_EXTENSIONS = Object.freeze([
19
20
  ...MARKDOWN_FILE_EXTENSIONS,
21
+ ...HTML_FILE_EXTENSIONS,
20
22
  BASE_FILE_EXTENSION,
21
23
  ...DIAGRAM_FILE_EXTENSIONS,
22
24
  PDF_FILE_EXTENSION,
23
25
  ...IMAGE_ATTACHMENT_EXTENSIONS,
24
26
  ]);
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;
27
+ const STRIP_VAULT_EXTENSION_PATTERN = /\.(?:md|markdown|mdx|html?|base|excalidraw|drawio|mmd|mermaid|puml|plantuml|dsl|pdf|png|jpe?g|webp|gif|svg)$/i;
26
28
 
27
29
  function normalizeFilePath(filePath) {
28
30
  return String(filePath ?? '').trim().toLowerCase();
@@ -38,6 +40,7 @@ export {
38
40
  DIAGRAM_FILE_EXTENSIONS,
39
41
  DRAWIO_FILE_EXTENSION,
40
42
  EXCALIDRAW_FILE_EXTENSION,
43
+ HTML_FILE_EXTENSIONS,
41
44
  IMAGE_ATTACHMENT_EXTENSIONS,
42
45
  MARKDOWN_FILE_EXTENSIONS,
43
46
  MERMAID_FILE_EXTENSIONS,
@@ -53,6 +56,10 @@ export function getVaultFileKind(filePath) {
53
56
  return 'markdown';
54
57
  }
55
58
 
59
+ if (hasFileExtension(filePath, HTML_FILE_EXTENSIONS)) {
60
+ return 'html';
61
+ }
62
+
56
63
  if (hasFileExtension(filePath, [BASE_FILE_EXTENSION])) {
57
64
  return 'base';
58
65
  }
@@ -114,6 +121,10 @@ export function isMarkdownFilePath(filePath) {
114
121
  return getVaultFileKind(filePath) === 'markdown';
115
122
  }
116
123
 
124
+ export function isHtmlFilePath(filePath) {
125
+ return getVaultFileKind(filePath) === 'html';
126
+ }
127
+
117
128
  export function isExcalidrawFilePath(filePath) {
118
129
  return getVaultFileKind(filePath) === 'excalidraw';
119
130
  }
@@ -1,4 +1,6 @@
1
1
  import { execFile as execFileCallback } from 'node:child_process';
2
+ import { glob, readFile, stat } from 'node:fs/promises';
3
+ import { join } from 'node:path';
2
4
  import { promisify } from 'node:util';
3
5
 
4
6
  import { getVaultFileKind } from '../../domain/file-kind.js';
@@ -17,6 +19,8 @@ const TEXT_SEARCH_GLOBS = Object.freeze([
17
19
  '*.md',
18
20
  '*.markdown',
19
21
  '*.mdx',
22
+ '*.html',
23
+ '*.htm',
20
24
  '*.base',
21
25
  '*.mmd',
22
26
  '*.mermaid',
@@ -24,9 +28,15 @@ const TEXT_SEARCH_GLOBS = Object.freeze([
24
28
  '*.plantuml',
25
29
  '*.dsl',
26
30
  '*.drawio',
27
- '*.excalidraw',
28
31
  ]);
29
32
 
33
+ function parseByteLimit(value) {
34
+ const match = String(value ?? '').trim().match(/^(\d+)([KMG])?$/iu);
35
+ if (!match) return 1024 * 1024;
36
+ const multipliers = { K: 1024, M: 1024 ** 2, G: 1024 ** 3 };
37
+ return Number(match[1]) * (multipliers[match[2]?.toUpperCase()] ?? 1);
38
+ }
39
+
30
40
  function normalizePositiveInt(value, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
31
41
  const parsed = Number.parseInt(value ?? '', 10);
32
42
  if (!Number.isInteger(parsed) || parsed < min) {
@@ -216,6 +226,72 @@ export function parseRipgrepJson(stdout, {
216
226
  };
217
227
  }
218
228
 
229
+ async function searchExcalidrawText({ maxFileSize, maxFiles, maxSnippetsPerFile, query, signal, vaultDir }) {
230
+ const files = [];
231
+ let matchCount = 0;
232
+ let truncated = false;
233
+ const normalizedQuery = query.toLocaleLowerCase();
234
+ const paths = glob('**/*.excalidraw', {
235
+ cwd: vaultDir,
236
+ exclude: ['**/.*', '**/node_modules/**'],
237
+ });
238
+
239
+ for await (const filePath of paths) {
240
+ signal?.throwIfAborted?.();
241
+ const absolutePath = join(vaultDir, filePath);
242
+ if ((await stat(absolutePath)).size > parseByteLimit(maxFileSize)) continue;
243
+
244
+ let scene;
245
+ try {
246
+ scene = JSON.parse(await readFile(absolutePath, 'utf8'));
247
+ } catch {
248
+ continue;
249
+ }
250
+
251
+ const snippets = [];
252
+ let fileMatchCount = 0;
253
+ for (const element of Array.isArray(scene?.elements) ? scene.elements : []) {
254
+ if (element?.isDeleted || element?.type !== 'text' || typeof element.text !== 'string') continue;
255
+ const text = element.text;
256
+ const normalizedText = text.toLocaleLowerCase();
257
+ let matchStart = normalizedText.indexOf(normalizedQuery);
258
+ while (matchStart >= 0) {
259
+ fileMatchCount += 1;
260
+ matchCount += 1;
261
+ if (snippets.length < maxSnippetsPerFile) {
262
+ const snippet = createSnippet(text, matchStart, matchStart + query.length);
263
+ snippets.push({
264
+ column: matchStart + 1,
265
+ line: 1,
266
+ matchEnd: snippet.matchEnd,
267
+ matchStart: snippet.matchStart,
268
+ text: snippet.text,
269
+ });
270
+ } else {
271
+ truncated = true;
272
+ }
273
+ matchStart = normalizedText.indexOf(normalizedQuery, matchStart + Math.max(query.length, 1));
274
+ }
275
+ }
276
+
277
+ if (fileMatchCount > 0) {
278
+ if (files.length >= maxFiles) {
279
+ truncated = true;
280
+ continue;
281
+ }
282
+ files.push({
283
+ file: filePath.replaceAll('\\', '/'),
284
+ kind: 'excalidraw',
285
+ matchCount: fileMatchCount,
286
+ snippets,
287
+ truncated: fileMatchCount > snippets.length,
288
+ });
289
+ }
290
+ }
291
+
292
+ return { files, matchCount, truncated };
293
+ }
294
+
219
295
  export class RipgrepSearchService {
220
296
  constructor({
221
297
  execFileImpl = execFile,
@@ -307,7 +383,7 @@ export class RipgrepSearchService {
307
383
  maxFileSize: this.maxFileSize,
308
384
  maxSnippetsPerFile: this.maxSnippetsPerFile,
309
385
  });
310
-
386
+ let parsed;
311
387
  try {
312
388
  const result = await this.execFileImpl('rg', args, {
313
389
  cwd: this.vaultDir,
@@ -316,56 +392,53 @@ export class RipgrepSearchService {
316
392
  ...(signal ? { signal } : {}),
317
393
  timeout: this.timeoutMs,
318
394
  });
319
- const parsed = parseRipgrepJson(result.stdout, {
395
+ parsed = parseRipgrepJson(result.stdout, {
320
396
  maxFiles,
321
397
  maxSnippetsPerFile: this.maxSnippetsPerFile,
322
398
  query: normalizedQuery,
323
399
  });
324
- parsed.search = this.getClientConfig();
325
-
326
- logPerfEvent(this.perfLoggingEnabled, 'search-query', {
327
- durationMs: Date.now() - startedAt,
328
- fileCount: parsed.files.length,
329
- matchCount: parsed.matchCount,
330
- truncated: parsed.truncated,
331
- });
332
- return parsed;
333
400
  } catch (error) {
334
401
  if (error?.code === 1) {
335
- const empty = createEmptySearchResult({
402
+ parsed = createEmptySearchResult({
336
403
  query: normalizedQuery,
337
404
  searchAvailable: this.available,
338
405
  });
339
- empty.search = this.getClientConfig();
340
- logPerfEvent(this.perfLoggingEnabled, 'search-query', {
341
- durationMs: Date.now() - startedAt,
342
- fileCount: 0,
343
- matchCount: 0,
344
- truncated: false,
406
+ } else {
407
+ const isMaxBuffer = error?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER';
408
+ parsed = parseRipgrepJson(error?.stdout ?? '', {
409
+ maxFiles,
410
+ maxSnippetsPerFile: this.maxSnippetsPerFile,
411
+ query: normalizedQuery,
345
412
  });
346
- return empty;
413
+ if (isMaxBuffer && parsed.files.length > 0) {
414
+ parsed.truncated = true;
415
+ } else {
416
+ error.statusCode = error?.signal === 'SIGTERM' ? 504 : 500;
417
+ throw error;
418
+ }
347
419
  }
420
+ }
348
421
 
349
- const isMaxBuffer = error?.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER';
350
- const parsed = parseRipgrepJson(error?.stdout ?? '', {
351
- maxFiles,
422
+ if (parsed.files.length < maxFiles) {
423
+ const excalidraw = await searchExcalidrawText({
424
+ maxFileSize: this.maxFileSize,
425
+ maxFiles: maxFiles - parsed.files.length,
352
426
  maxSnippetsPerFile: this.maxSnippetsPerFile,
353
427
  query: normalizedQuery,
428
+ signal,
429
+ vaultDir: this.vaultDir,
354
430
  });
355
- if (isMaxBuffer && parsed.files.length > 0) {
356
- parsed.search = this.getClientConfig();
357
- parsed.truncated = true;
358
- logPerfEvent(this.perfLoggingEnabled, 'search-query', {
359
- durationMs: Date.now() - startedAt,
360
- fileCount: parsed.files.length,
361
- matchCount: parsed.matchCount,
362
- truncated: true,
363
- });
364
- return parsed;
365
- }
366
-
367
- error.statusCode = error?.signal === 'SIGTERM' ? 504 : 500;
368
- throw error;
431
+ parsed.files.push(...excalidraw.files);
432
+ parsed.matchCount += excalidraw.matchCount;
433
+ parsed.truncated ||= excalidraw.truncated;
369
434
  }
435
+ parsed.search = this.getClientConfig();
436
+ logPerfEvent(this.perfLoggingEnabled, 'search-query', {
437
+ durationMs: Date.now() - startedAt,
438
+ fileCount: parsed.files.length,
439
+ matchCount: parsed.matchCount,
440
+ truncated: parsed.truncated,
441
+ });
442
+ return parsed;
370
443
  }
371
444
  }
@@ -203,7 +203,7 @@ export class GitService {
203
203
  };
204
204
  }
205
205
 
206
- async pullBranch() {
206
+ async pullBranch({ author = null } = {}) {
207
207
  const status = await this.getStatus({ force: true });
208
208
  if (status.branch?.detached) {
209
209
  throw createGitRequestError(409, 'Cannot pull from a detached HEAD');
@@ -220,16 +220,22 @@ export class GitService {
220
220
  throw createGitRequestError(409, 'Unable to resolve upstream branch for pull');
221
221
  }
222
222
 
223
- if (!(await this.canFastForwardTo(targetRef))) {
223
+ const mergeBaseRef = beforeRef
224
+ ? await this.resolveMergeBase(beforeRef, targetRef)
225
+ : null;
226
+ if (beforeRef && !mergeBaseRef) {
227
+ throw createGitRequestError(409, 'Cannot pull because local and remote histories are unrelated');
228
+ }
229
+ if (beforeRef && !(await this.canMergeWith(targetRef))) {
224
230
  throw createGitRequestError(
225
231
  409,
226
- 'Cannot pull because local and remote commits have diverged; fast-forward only pull is not possible.',
227
- { requestCode: 'pull_diverged_ff_only' },
232
+ 'Cannot pull automatically because local and remote commits conflict.',
233
+ { requestCode: 'pull_conflicted_commits' },
228
234
  );
229
235
  }
230
236
 
231
237
  const dirtyEntries = this.collectDirtyEntries(status);
232
- const upstreamWorkspaceChange = await this.createWorkspaceChangeFromRefs(beforeRef, targetRef);
238
+ const upstreamWorkspaceChange = await this.createWorkspaceChangeFromRefs(mergeBaseRef, targetRef);
233
239
  const overlappingEntries = this.findOverlappingDirtyEntries({
234
240
  dirtyEntries,
235
241
  workspaceChange: upstreamWorkspaceChange,
@@ -247,7 +253,9 @@ export class GitService {
247
253
 
248
254
  let output;
249
255
  try {
250
- output = await this.commandRunner.execGit(['pull', '--ff-only', '--autostash']);
256
+ output = await this.commandRunner.execGit(['merge', '--no-edit', '--autostash', targetRef], {
257
+ env: buildAuthorEnv(author),
258
+ });
251
259
  } catch (error) {
252
260
  throw await this.classifyPullError(error);
253
261
  }
@@ -339,14 +347,18 @@ export class GitService {
339
347
  : ['fetch', '--prune']);
340
348
  }
341
349
 
342
- async canFastForwardTo(targetRef) {
343
- const headRef = await this.resolveRef('HEAD');
344
- if (!headRef || !targetRef || headRef === targetRef) {
345
- return true;
350
+ async resolveMergeBase(leftRef, rightRef) {
351
+ try {
352
+ const output = await this.commandRunner.execGit(['merge-base', leftRef, rightRef]);
353
+ return output.trim() || null;
354
+ } catch {
355
+ return null;
346
356
  }
357
+ }
347
358
 
359
+ async canMergeWith(targetRef) {
348
360
  try {
349
- await this.commandRunner.execGit(['merge-base', '--is-ancestor', headRef, targetRef]);
361
+ await this.commandRunner.execGit(['merge-tree', '--write-tree', '--quiet', 'HEAD', targetRef]);
350
362
  return true;
351
363
  } catch (error) {
352
364
  if (error?.code === 1) {
@@ -130,7 +130,9 @@ export function createGitApiCommandHandler({
130
130
  action: 'pull',
131
131
  req,
132
132
  responsePayload: await workspaceMutationCoordinator.runManagedWorkspaceMutation(
133
- () => gitService.pullBranch(),
133
+ () => gitService.pullBranch({
134
+ author: authService?.getAuthenticatedUser?.(req) ?? null,
135
+ }),
134
136
  ),
135
137
  workspaceMutationCoordinator,
136
138
  }));
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
2
2
 
3
3
  import { getRequestErrorStatusCode } from './http-errors.js';
4
4
  import { jsonResponse, sendResponse, textResponse } from './http-response.js';
5
- import { parseJsonBody } from './request-body.js';
5
+ import { parseJsonBody, readBinaryRequestBody } from './request-body.js';
6
6
 
7
7
  const EMBED_STYLESHEET_PATH = new URL('../structurizr/structurizr-embed.css', import.meta.url);
8
8
 
@@ -101,13 +101,15 @@ export function createStructurizrApiHandler({ basePath = '', service = null } =
101
101
  return false;
102
102
  }
103
103
 
104
- if (req.method !== 'GET' && req.method !== 'HEAD') {
104
+ const isThumbnailPut = req.method === 'PUT' && service.isThumbnailPath(requestUrl.pathname);
105
+ if (req.method !== 'GET' && req.method !== 'HEAD' && !isThumbnailPut) {
105
106
  textResponse(req, res, 405, 'Method Not Allowed', { Allow: 'GET, HEAD' });
106
107
  return true;
107
108
  }
108
109
 
109
110
  try {
110
111
  const response = await service.proxy(requestUrl, {
112
+ body: isThumbnailPut ? await readBinaryRequestBody(req) : null,
111
113
  headers: req.headers,
112
114
  method: req.method,
113
115
  });
@@ -3,7 +3,7 @@ import { isAbsolute, normalize, relative, resolve } from 'path';
3
3
  import { isVaultFilePath } from '../../../domain/file-kind.js';
4
4
 
5
5
  export const IGNORED_DIRECTORIES = new Set(['.git', '.obsidian', '.trash', 'node_modules', '.DS_Store']);
6
- export const VAULT_FILE_PATH_REQUIREMENT = '.md, .markdown, .mdx, .base, .excalidraw, .drawio, .mmd, .mermaid, .puml, .plantuml, .dsl, .png, .jpg, .jpeg, .webp, .gif, or .svg';
6
+ export const VAULT_FILE_PATH_REQUIREMENT = '.md, .markdown, .mdx, .html, .htm, .base, .excalidraw, .drawio, .mmd, .mermaid, .puml, .plantuml, .dsl, .pdf, .png, .jpg, .jpeg, .webp, .gif, or .svg';
7
7
  export const INVALID_VAULT_FILE_PATH_ERROR = `Invalid file path — must end in ${VAULT_FILE_PATH_REQUIREMENT}`;
8
8
  export const INVALID_DIRECTORY_PATH_ERROR = 'Invalid directory path';
9
9
 
@@ -12,12 +12,18 @@ export function isIgnoredVaultEntry(name) {
12
12
  }
13
13
 
14
14
  function normalizeRequestedPath(requestedPath) {
15
- const normalized = normalize(String(requestedPath ?? '').trim().replace(/\\/g, '/'));
16
- if (!normalized || normalized === '.') {
15
+ const value = String(requestedPath ?? '').trim().replace(/\\/g, '/');
16
+ const segments = value.split('/');
17
+ if (
18
+ !value
19
+ || isAbsolute(value)
20
+ || segments.some((segment) => segment === '.' || segment === '..')
21
+ ) {
17
22
  return '';
18
23
  }
19
24
 
20
- return normalized;
25
+ const normalized = normalize(value);
26
+ return normalized === '.' ? '' : normalized;
21
27
  }
22
28
 
23
29
  export function sanitizeVaultPath(vaultDir, requestedPath) {
@@ -28,6 +28,7 @@ const EDITABLE_VAULT_CONTENT_PATH_ERRORS = {
28
28
  base: 'Invalid file path — must end in .base',
29
29
  drawio: 'Invalid file path — must end in .drawio',
30
30
  excalidraw: 'Invalid file path — must end in .excalidraw',
31
+ html: 'Invalid file path — must end in .html or .htm',
31
32
  markdown: 'Invalid file path',
32
33
  mermaid: 'Invalid file path — must end in .mmd or .mermaid',
33
34
  plantuml: 'Invalid file path — must end in .puml or .plantuml',
@@ -66,6 +67,7 @@ const TEXT_FILE_MIME_TYPES = Object.freeze({
66
67
  base: 'text/yaml; charset=utf-8',
67
68
  drawio: 'application/xml; charset=utf-8',
68
69
  excalidraw: 'application/json; charset=utf-8',
70
+ html: 'text/html; charset=utf-8',
69
71
  markdown: 'text/markdown; charset=utf-8',
70
72
  mermaid: 'text/plain; charset=utf-8',
71
73
  pdf: 'application/pdf',
@@ -12,6 +12,7 @@ const MANIFEST_FILE_NAME = '.collabmd-manifest.json';
12
12
  const WORKSPACE_DSL_FILE_NAME = 'workspace.dsl';
13
13
  const WORKSPACE_JSON_FILE_NAME = 'workspace.json';
14
14
  const SIDECAR_TIMEOUT_MS = 15_000;
15
+ const THUMBNAIL_FALLBACK_PATH = '/static/img/thumbnail-not-available.png';
15
16
 
16
17
  function createServiceError(message, statusCode, code) {
17
18
  const error = new Error(message);
@@ -193,6 +194,10 @@ export class StructurizrWorkspaceService {
193
194
  );
194
195
  }
195
196
 
197
+ isThumbnailPath(pathname) {
198
+ return /^\/workspace\/1\/images\/(?:[^/]+-)?thumbnail(?:-dark)?\.png$/u.test(pathname);
199
+ }
200
+
196
201
  async sync({ content, rootPath }) {
197
202
  if (!this.isEnabled()) {
198
203
  throw createServiceError('Structurizr renderer is not configured.', 503, 'STRUCTURIZR_NOT_CONFIGURED');
@@ -336,21 +341,26 @@ export class StructurizrWorkspaceService {
336
341
  }
337
342
  }
338
343
 
339
- async proxy(requestUrl, { method = 'GET', headers = {} } = {}) {
344
+ async proxy(requestUrl, { body = null, method = 'GET', headers = {} } = {}) {
340
345
  if (!this.isProxyPath(requestUrl.pathname)) {
341
346
  return null;
342
347
  }
343
348
 
344
349
  const upstreamUrl = `${this.serverUrl}${requestUrl.pathname}${requestUrl.search}`;
345
350
  let response;
351
+ const proxyHeaders = {
352
+ Accept: headers.accept || '*/*',
353
+ };
354
+ if (headers['content-type']) {
355
+ proxyHeaders['Content-Type'] = headers['content-type'];
356
+ }
357
+ if (headers.range) {
358
+ proxyHeaders.Range = headers.range;
359
+ }
360
+
346
361
  try {
347
- const proxyHeaders = {
348
- Accept: headers.accept || '*/*',
349
- };
350
- if (headers.range) {
351
- proxyHeaders.Range = headers.range;
352
- }
353
362
  response = await fetch(upstreamUrl, {
363
+ body,
354
364
  headers: proxyHeaders,
355
365
  method,
356
366
  redirect: 'follow',
@@ -364,6 +374,22 @@ export class StructurizrWorkspaceService {
364
374
  );
365
375
  }
366
376
 
377
+ if (response.status === 404 && method === 'GET' && this.isThumbnailPath(requestUrl.pathname)) {
378
+ try {
379
+ const fallbackResponse = await fetch(`${this.serverUrl}${THUMBNAIL_FALLBACK_PATH}`, {
380
+ headers: { Accept: 'image/png' },
381
+ method: 'GET',
382
+ redirect: 'follow',
383
+ signal: AbortSignal.timeout(SIDECAR_TIMEOUT_MS),
384
+ });
385
+ if (fallbackResponse.ok) {
386
+ response = fallbackResponse;
387
+ }
388
+ } catch {
389
+ // Keep the original 404 when the optional placeholder is unavailable.
390
+ }
391
+ }
392
+
367
393
  return {
368
394
  body: Buffer.from(await response.arrayBuffer()),
369
395
  contentType: response.headers.get('content-type') || 'application/octet-stream',
@@ -1 +0,0 @@
1
- import"./chunk-KEIR6QF5-BICK3FdT.js";import{n as e}from"./chunk-MOZMSUNE-XVucA-n6.js";export{e as createArchitectureServices};
@@ -1 +0,0 @@
1
- var e=``+new URL(`github.min-D2BCvnWf.css`,import.meta.url).href;export{e as t};