collabmd 0.1.44 → 0.1.46

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 (291) hide show
  1. package/README.md +39 -19
  2. package/bin/collabmd.js +27 -1
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js +1 -0
  4. package/dist/client/assets/browser-utils--H_DkyEF.js +1 -0
  5. package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +41 -0
  6. package/dist/client/assets/{chunk-CZQZEIFA-DT3N9fo7.js → chunk-YGJVY4SA-CjSe7Bx7.js} +2 -2
  7. package/dist/client/assets/comment-thread-store-CdcwrObc.js +1 -0
  8. package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
  9. package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +7 -0
  10. package/dist/client/assets/dist-B5HTH2BO.js +1 -0
  11. package/dist/client/assets/{dist-DhLvC8DS.js → dist-B5Jf1SLZ.js} +2 -2
  12. package/dist/client/assets/{dist-CnL7Y2sM.js → dist-BDt3rz7l.js} +1 -1
  13. package/dist/client/assets/dist-BEwK4csK.js +1 -0
  14. package/dist/client/assets/dist-BKW4PALF.js +1 -0
  15. package/dist/client/assets/dist-BWcHHOx-.js +1 -0
  16. package/dist/client/assets/{dist-CYZmbokb.js → dist-BalScOwZ.js} +9 -9
  17. package/dist/client/assets/dist-Bf8f4HmM.js +6 -0
  18. package/dist/client/assets/dist-BjHJDtyU.js +1 -0
  19. package/dist/client/assets/dist-Bm6pf9Bl.js +1 -0
  20. package/dist/client/assets/dist-BoVBdSjk.js +1 -0
  21. package/dist/client/assets/dist-CC5IrQMG.js +1 -0
  22. package/dist/client/assets/{dist-C11hHqv_.js → dist-CCP_AKPG.js} +12 -12
  23. package/dist/client/assets/dist-CZgOmxK6.js +1 -0
  24. package/dist/client/assets/{dist-D2AQ-76g.js → dist-Cqhv5LAk.js} +1 -1
  25. package/dist/client/assets/{dist-MvcV4190.js → dist-D-Z6FLem.js} +1 -1
  26. package/dist/client/assets/dist-DLMiIsNC.js +11 -0
  27. package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZKu9Cs8.js} +1 -1
  28. package/dist/client/assets/dist-DaYdhcVs.js +1 -0
  29. package/dist/client/assets/dist-FWJsgGYI.js +1 -0
  30. package/dist/client/assets/dist-Kh2COra_.js +1 -0
  31. package/dist/client/assets/{dist-JYEDRrPT.js → dist-PDZ3bSqm.js} +1 -1
  32. package/dist/client/assets/{dist-Drp8uu5J.js → dist-TjMh8n1u.js} +1 -1
  33. package/dist/client/assets/{dist-DGb27Dl6.js → dist-dtAdgL39.js} +1 -1
  34. package/dist/client/assets/dist-jv4WdPnK.js +9 -0
  35. package/dist/client/assets/{dist-DK5Gs2wa.js → dist-rGBmqxC7.js} +1 -1
  36. package/dist/client/assets/{dist-DCzuX1AF.js → dist-shrl6K_0.js} +1 -1
  37. package/dist/client/assets/dist-tOaegDYS2.js +1 -0
  38. package/dist/client/assets/dist-ule2n6ak.js +1 -0
  39. package/dist/client/assets/dist-xElaxbia.js +1 -0
  40. package/dist/client/assets/drawio-editor-FzY1cVw8.js +9 -0
  41. package/dist/client/assets/drawioEditor-BjiKJqlc.js +2 -0
  42. package/dist/client/assets/editor-session-Cm9ekeNo.js +54 -0
  43. package/dist/client/assets/embedded-editor-base-CwTkk911.css +1 -0
  44. package/dist/client/assets/{en-GADW4C6J-DQ6zyCEM.js → en-7NFCYGKX-BrgYZAEe.js} +1 -1
  45. package/dist/client/assets/{preview-render-profile-BZzGSg6K.js → es-DXGV3RHd.js} +13 -13
  46. package/dist/client/assets/excalidraw-editor-B46zsTFI.js +9 -0
  47. package/dist/client/assets/excalidraw-editor-Bt7gMSoh.css +1 -0
  48. package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
  49. package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +2 -0
  50. package/dist/client/assets/export-page-A7NHawJY.js +39 -0
  51. package/dist/client/assets/exportDocument-B2L8fe34.css +1 -0
  52. package/dist/client/assets/exportDocument-BaqcOAAW.js +2 -0
  53. package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
  54. package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
  55. package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +1 -0
  56. package/dist/client/assets/index-ClbjMBVt.js +2 -0
  57. package/dist/client/assets/index-Pum8ET-5.css +1 -0
  58. package/dist/client/assets/main-B3uPyqic.js +893 -0
  59. package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
  60. package/dist/client/assets/pdf-BL9Pr2D5.js +54 -0
  61. package/dist/client/assets/pdf.worker-CLesOks4.mjs +64857 -0
  62. package/dist/client/assets/pdf_viewer-FVkkThnz.js +551 -0
  63. package/dist/client/assets/preview-diagram-utils-txBCoW8d.js +1 -0
  64. package/dist/client/assets/{preview-render-compiler-BSaQO_p3.js → preview-render-compiler-BD-XhkS2.js} +2 -2
  65. package/dist/client/assets/preview-render-compiler-BKedaMxx.js +1 -0
  66. package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
  67. package/dist/client/assets/{preview-render-worker-B42LWvrD.js → preview-render-worker-CiPqc9n6.js} +20 -20
  68. package/dist/client/assets/prod-Dy20X7eT.js +1 -0
  69. package/dist/client/assets/prod-hnwh7wRM.js +177 -0
  70. package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +12 -0
  71. package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
  72. package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
  73. package/dist/client/assets/{yjs-provider-reset-guard-Cox4nxwu.js → yjs-provider-reset-guard-DE0vINDP.js} +1 -1
  74. package/dist/client/drawio-editor.html +3 -2
  75. package/dist/client/excalidraw-editor.html +3 -2
  76. package/dist/client/export-document.html +4 -3
  77. package/dist/client/index.html +109 -27
  78. package/docker-compose.yml +42 -0
  79. package/package.json +26 -15
  80. package/scripts/local-structurizr-compose.mjs +101 -0
  81. package/src/client/app/drawio-editor-entry.js +0 -3
  82. package/src/client/app/drawio-editor.html +1 -0
  83. package/src/client/app/excalidraw-editor-entry.js +0 -3
  84. package/src/client/app/excalidraw-editor.html +1 -0
  85. package/src/client/app/export-document-entry.js +0 -3
  86. package/src/client/app/export-document.html +1 -0
  87. package/src/client/app/index.html +106 -24
  88. package/src/client/app/main-entry.js +0 -5
  89. package/src/client/application/app-shell/chat-feature.js +180 -124
  90. package/src/client/application/app-shell/comments-feature.js +20 -11
  91. package/src/client/application/app-shell/git-feature.js +16 -9
  92. package/src/client/application/app-shell/presence-feature.js +18 -11
  93. package/src/client/application/app-shell/ui-feature-shell.js +78 -17
  94. package/src/client/application/app-shell/ui-feature-sidebar.js +74 -1
  95. package/src/client/application/app-shell/ui-feature-tab-activity.js +2 -2
  96. package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
  97. package/src/client/application/app-shell/workspace-feature.js +27 -84
  98. package/src/client/application/app-shell-elements.js +9 -1
  99. package/src/client/application/diagram-chrome.js +161 -166
  100. package/src/client/application/diagram-preview-export.js +7 -34
  101. package/src/client/application/diagram-preview-hydrator.js +1 -19
  102. package/src/client/application/markdown-frontmatter.js +0 -2
  103. package/src/client/application/mermaid-preview-hydrator.js +1 -14
  104. package/src/client/application/pdf-preview-controller.js +992 -0
  105. package/src/client/application/plantuml-preview-hydrator.js +0 -10
  106. package/src/client/application/preview-diagram-utils.js +31 -2
  107. package/src/client/application/preview-render-compiler.js +2 -1
  108. package/src/client/application/preview-renderer.js +2 -2
  109. package/src/client/application/quick-switcher-loader.js +3 -1
  110. package/src/client/application/structurizr-preview-controller.js +395 -0
  111. package/src/client/application/workspace-coordinator.js +25 -3
  112. package/src/client/application/workspace-preview-controller.js +91 -5
  113. package/src/client/bootstrap/collabmd-app-shell.js +155 -43
  114. package/src/client/browser-utils.js +44 -0
  115. package/src/client/domain/excalidraw-collaboration.js +0 -2
  116. package/src/client/domain/room.js +38 -0
  117. package/src/client/domain/runtime-paths.js +26 -5
  118. package/src/client/domain/structurizr-language.js +99 -0
  119. package/src/client/domain/vault-paths.js +48 -0
  120. package/src/client/excalidraw-editor.js +833 -51
  121. package/src/client/export/export-pipeline.js +6 -34
  122. package/src/client/infrastructure/auth-client.js +4 -10
  123. package/src/client/infrastructure/browser-notification-port.js +33 -20
  124. package/src/client/infrastructure/browser-preferences-port.js +46 -9
  125. package/src/client/infrastructure/comment-thread-store.js +34 -13
  126. package/src/client/infrastructure/editor-session.js +10 -0
  127. package/src/client/infrastructure/editor-view-adapter.js +133 -5
  128. package/src/client/infrastructure/excalidraw-room-client.js +103 -14
  129. package/src/client/infrastructure/git-api-client.js +5 -0
  130. package/src/client/infrastructure/lobby-presence.js +1 -0
  131. package/src/client/infrastructure/vault-api-client.js +51 -0
  132. package/src/client/infrastructure/workspace-sync-client.js +13 -1
  133. package/src/client/presentation/comment-overview-controller.js +18 -53
  134. package/src/client/presentation/comment-ui/comment-ui-card.js +1 -12
  135. package/src/client/presentation/comment-ui/comment-ui-layout.js +242 -219
  136. package/src/client/presentation/comment-ui/comment-ui-render.js +32 -45
  137. package/src/client/presentation/comment-ui/comment-ui-shared.js +68 -13
  138. package/src/client/presentation/comment-ui-controller.js +5 -1
  139. package/src/client/presentation/drawio-embed-controller.js +9 -102
  140. package/src/client/presentation/drawio-viewer.js +118 -0
  141. package/src/client/presentation/excalidraw-embed-controller.js +74 -8
  142. package/src/client/presentation/file-action-controller.js +134 -0
  143. package/src/client/presentation/file-explorer-controller.js +33 -3
  144. package/src/client/presentation/file-explorer-view.js +59 -34
  145. package/src/client/presentation/file-icon-svg.js +40 -0
  146. package/src/client/presentation/file-tree-state.js +12 -4
  147. package/src/client/presentation/git-diff-view-controller.js +731 -3
  148. package/src/client/presentation/outline-controller.js +86 -0
  149. package/src/client/presentation/quick-switcher-controller.js +257 -74
  150. package/src/client/presentation/quick-switcher-text-search.js +3 -3
  151. package/src/client/presentation/toast-controller.js +3 -0
  152. package/src/client/styles/components/feedback.css +6 -0
  153. package/src/client/styles/components/navigation.css +11 -1
  154. package/src/client/styles/features/collaboration-chat.css +49 -53
  155. package/src/client/styles/features/collaboration-presence.css +9 -7
  156. package/src/client/styles/features/comment-card.css +25 -11
  157. package/src/client/styles/features/comment-overlays.css +0 -4
  158. package/src/client/styles/features/comment-overview.css +44 -21
  159. package/src/client/styles/features/comments-drawer.css +2 -100
  160. package/src/client/styles/features/diagram-preview.css +81 -18
  161. package/src/client/styles/features/diff-special.css +309 -0
  162. package/src/client/styles/features/embedded-preview.css +8 -33
  163. package/src/client/styles/features/quick-switcher.css +8 -0
  164. package/src/client/styles/foundation/themes.css +6 -0
  165. package/src/client/styles/foundation/tokens.css +1 -0
  166. package/src/client/styles/layout/editor-page.css +40 -0
  167. package/src/client/styles/layout/responsive.css +31 -1
  168. package/src/client/styles/layout/shell.css +383 -7
  169. package/src/client/styles/layout/sidebar.css +47 -15
  170. package/src/client/styles/layout/view-modes.css +1 -0
  171. package/src/client/styles/overrides/codemirror.css +217 -15
  172. package/src/client/styles/style.css +1 -0
  173. package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
  174. package/src/domain/comment-threads.js +63 -5
  175. package/src/domain/excalidraw-room-codec.js +6 -4
  176. package/src/domain/file-kind.js +35 -3
  177. package/src/server/application/workspace-reconciliation.js +1 -1
  178. package/src/server/config/env.js +79 -0
  179. package/src/server/create-app-server.js +14 -3
  180. package/src/server/domain/bases/base-definition.js +1 -1
  181. package/src/server/domain/bases/base-expression-runtime.js +1 -4
  182. package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
  183. package/src/server/domain/bases/base-query-service.js +1 -77
  184. package/src/server/domain/bases/base-transform.js +1 -4
  185. package/src/server/domain/collaboration/collaboration-room.js +55 -21
  186. package/src/server/domain/comment-overview.js +25 -8
  187. package/src/server/domain/docx-exporter.js +24 -33
  188. package/src/server/domain/ripgrep-search-service.js +7 -1
  189. package/src/server/domain/workspace-state.js +32 -11
  190. package/src/server/infrastructure/git/diff-service.js +29 -13
  191. package/src/server/infrastructure/git/git-service.js +61 -10
  192. package/src/server/infrastructure/git/history-service.js +96 -29
  193. package/src/server/infrastructure/git/image-mime.js +14 -0
  194. package/src/server/infrastructure/git/path-utils.js +1 -1
  195. package/src/server/infrastructure/git/responses.js +0 -95
  196. package/src/server/infrastructure/git/untracked-files.js +28 -1
  197. package/src/server/infrastructure/github/github-app-client.js +22 -15
  198. package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
  199. package/src/server/infrastructure/http/create-request-handler.js +18 -31
  200. package/src/server/infrastructure/http/create-static-handler.js +5 -2
  201. package/src/server/infrastructure/http/create-structurizr-api-handler.js +145 -0
  202. package/src/server/infrastructure/http/create-vault-api-command-handler.js +70 -8
  203. package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
  204. package/src/server/infrastructure/http/http-errors.js +7 -1
  205. package/src/server/infrastructure/http/http-request-helpers.js +22 -0
  206. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  207. package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
  208. package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
  209. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +374 -0
  210. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
  211. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
  212. package/dist/client/assets/bases-preview-controller-2pLHk0uk.js +0 -143
  213. package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
  214. package/dist/client/assets/button-BCEiw4Rw.js +0 -1
  215. package/dist/client/assets/chunk-AXR3VHVW-0GTk_evH.js +0 -41
  216. package/dist/client/assets/comment-threads-D-iKphIp.js +0 -4
  217. package/dist/client/assets/diagram-action-icons-aa_KOv9h.js +0 -36
  218. package/dist/client/assets/dist-BH87JoHx.js +0 -11
  219. package/dist/client/assets/dist-BIkPRZO7.js +0 -6
  220. package/dist/client/assets/dist-BqCsFpx4.js +0 -1
  221. package/dist/client/assets/dist-C2JHCt8U.js +0 -1
  222. package/dist/client/assets/dist-CZjTtmTu.js +0 -1
  223. package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
  224. package/dist/client/assets/dist-CqQEC8gR.js +0 -1
  225. package/dist/client/assets/dist-D4Rzqod1.js +0 -1
  226. package/dist/client/assets/dist-D5sn-mwk.js +0 -9
  227. package/dist/client/assets/dist-D7G-n87v.js +0 -1
  228. package/dist/client/assets/dist-DRqOrNgN.js +0 -1
  229. package/dist/client/assets/dist-DetkMS_4.js +0 -1
  230. package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
  231. package/dist/client/assets/dist-DtbjNB28.js +0 -1
  232. package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
  233. package/dist/client/assets/dist-GrygD2zE.js +0 -1
  234. package/dist/client/assets/dist-HmEpWUow.js +0 -1
  235. package/dist/client/assets/dist-RTa81Km7.js +0 -1
  236. package/dist/client/assets/drawio-editor-DDvFoarP.js +0 -9
  237. package/dist/client/assets/drawio-embed-controller-BD1GTRwn.js +0 -1
  238. package/dist/client/assets/drawioEditor-Bu5grlH5.js +0 -2
  239. package/dist/client/assets/editor-session-DGlpiAsK.js +0 -16
  240. package/dist/client/assets/embedded-editor-base-C9roKYpW.css +0 -1
  241. package/dist/client/assets/excalidraw-editor-BHu6k8d4.js +0 -9
  242. package/dist/client/assets/excalidraw-editor-Cr_184EF.css +0 -1
  243. package/dist/client/assets/excalidraw-embed-controller-y2fenN_g.js +0 -1
  244. package/dist/client/assets/excalidraw-embed-reconciler-DGiagExg.js +0 -1
  245. package/dist/client/assets/excalidraw-scene-BvsQ6mLP.js +0 -176
  246. package/dist/client/assets/excalidrawEditor-4vFE--Uw.js +0 -2
  247. package/dist/client/assets/export-page-Cby8JzPO.js +0 -39
  248. package/dist/client/assets/exportDocument-C9v-bc7I.css +0 -1
  249. package/dist/client/assets/exportDocument-CRHCfsdo.js +0 -2
  250. package/dist/client/assets/file-history-view-controller-BDjEV9xJ.js +0 -112
  251. package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
  252. package/dist/client/assets/git-diff-view-controller-DgdM1aqb.js +0 -150
  253. package/dist/client/assets/git-panel-controller-BDTR2HVp.js +0 -207
  254. package/dist/client/assets/image-XGD7JQR6-XDUWHRpO.js +0 -1
  255. package/dist/client/assets/index-7xOyXDhP.css +0 -1
  256. package/dist/client/assets/index-Bz1KuQ6y.js +0 -2
  257. package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  258. package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  259. package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  260. package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  261. package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  262. package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  263. package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  264. package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  265. package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  266. package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  267. package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  268. package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  269. package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  270. package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  271. package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  272. package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  273. package/dist/client/assets/main-Ci07m9oP.js +0 -152
  274. package/dist/client/assets/preview-diagram-utils-n_bbJA9V.js +0 -1
  275. package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
  276. package/dist/client/assets/quick-switcher-controller-CoiYvllm.js +0 -12
  277. package/dist/client/assets/room-CDrmIdDt.js +0 -1
  278. package/dist/client/assets/runtime-config-CDgeuPWN.js +0 -1
  279. package/dist/client/assets/runtime-config-loader-BHGniHP5.js +0 -1
  280. package/dist/client/assets/runtime-paths-DvpihCEq.js +0 -1
  281. package/dist/client/assets/segmented-control-DJrHSz8M.js +0 -1
  282. package/dist/client/assets/vault-api-client-sLB2bo56.js +0 -1
  283. package/dist/client/assets/vault-paths-CVkuh0j-.js +0 -5
  284. package/src/client/bootstrap/lazy-controller-feature.js +0 -433
  285. package/src/client/infrastructure/backlinks-api-client.js +0 -16
  286. package/src/client/infrastructure/plantuml-api-client.js +0 -19
  287. package/src/client/infrastructure/runtime-config-loader.js +0 -56
  288. package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
  289. package/src/server/infrastructure/git/command-runner.js +0 -49
  290. package/src/server/infrastructure/git/errors.js +0 -8
  291. package/src/server/infrastructure/http/create-esm-proxy-handler.js +0 -130
@@ -1,4 +1,5 @@
1
1
  const DOCX_EXPORTER_CREATOR = 'CollabMD';
2
+ let converterPromise = null;
2
3
 
3
4
  function normalizeDocxBuffer(result) {
4
5
  if (Buffer.isBuffer(result)) {
@@ -16,47 +17,37 @@ function normalizeDocxBuffer(result) {
16
17
  throw new Error('DOCX exporter returned an unsupported payload');
17
18
  }
18
19
 
19
- export class DocxExporter {
20
- constructor({
21
- loadConverter = () => import('@turbodocx/html-to-docx'),
22
- } = {}) {
23
- this.loadConverter = loadConverter;
24
- this.converterPromise = null;
25
- }
26
-
27
- async ensureConverter() {
28
- if (this.converterPromise) {
29
- return this.converterPromise;
30
- }
31
-
32
- this.converterPromise = this.loadConverter().then((module) => {
20
+ async function ensureConverter() {
21
+ if (!converterPromise) {
22
+ converterPromise = import('@turbodocx/html-to-docx').then((module) => {
33
23
  const converter = module?.default ?? module?.HTMLToDOCX ?? module;
34
24
  if (typeof converter !== 'function') {
35
25
  throw new Error('DOCX converter failed to load');
36
26
  }
37
27
  return converter;
38
28
  });
39
- return this.converterPromise;
40
29
  }
41
30
 
42
- async render({
43
- html,
44
- title = '',
45
- } = {}) {
46
- const converter = await this.ensureConverter();
47
- const result = await converter(String(html ?? ''), null, {
48
- creator: DOCX_EXPORTER_CREATOR,
49
- font: 'Arial',
50
- footer: false,
51
- pageNumber: false,
52
- table: {
53
- row: {
54
- cantSplit: true,
55
- },
31
+ return converterPromise;
32
+ }
33
+
34
+ export async function renderDocx({
35
+ html,
36
+ title = '',
37
+ } = {}) {
38
+ const converter = await ensureConverter();
39
+ const result = await converter(String(html ?? ''), null, {
40
+ creator: DOCX_EXPORTER_CREATOR,
41
+ font: 'Arial',
42
+ footer: false,
43
+ pageNumber: false,
44
+ table: {
45
+ row: {
46
+ cantSplit: true,
56
47
  },
57
- title: String(title ?? ''),
58
- });
48
+ },
49
+ title: String(title ?? ''),
50
+ });
59
51
 
60
- return normalizeDocxBuffer(result);
61
- }
52
+ return normalizeDocxBuffer(result);
62
53
  }
@@ -22,7 +22,9 @@ const TEXT_SEARCH_GLOBS = Object.freeze([
22
22
  '*.mermaid',
23
23
  '*.puml',
24
24
  '*.plantuml',
25
+ '*.dsl',
25
26
  '*.drawio',
27
+ '*.excalidraw',
26
28
  ]);
27
29
 
28
30
  function normalizePositiveInt(value, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
@@ -106,7 +108,7 @@ function createRipgrepArgs(query, {
106
108
  '--max-filesize',
107
109
  String(maxFileSize || DEFAULT_MAX_FILE_SIZE),
108
110
  '--max-count',
109
- String(maxSnippetsPerFile),
111
+ String(Math.max(Number(maxSnippetsPerFile) || DEFAULT_MAX_SNIPPETS_PER_FILE, 1) + 1),
110
112
  '--glob',
111
113
  '!.git/**',
112
114
  '--glob',
@@ -171,6 +173,7 @@ export function parseRipgrepJson(stdout, {
171
173
  kind: getVaultFileKind(filePath) ?? 'text',
172
174
  matchCount: 0,
173
175
  snippets: [],
176
+ truncated: false,
174
177
  };
175
178
  filesByPath.set(filePath, fileGroup);
176
179
  files.push(fileGroup);
@@ -187,6 +190,7 @@ export function parseRipgrepJson(stdout, {
187
190
  matchCount += 1;
188
191
 
189
192
  if (fileGroup.snippets.length >= maxSnippetsPerFile) {
193
+ fileGroup.truncated = true;
190
194
  truncated = true;
191
195
  continue;
192
196
  }
@@ -276,6 +280,7 @@ export class RipgrepSearchService {
276
280
  async search({
277
281
  limit = DEFAULT_MAX_FILES,
278
282
  query = '',
283
+ signal = null,
279
284
  } = {}) {
280
285
  const normalizedQuery = String(query ?? '').trim();
281
286
  const maxFiles = normalizePositiveInt(limit, this.maxFiles, {
@@ -308,6 +313,7 @@ export class RipgrepSearchService {
308
313
  cwd: this.vaultDir,
309
314
  encoding: 'utf8',
310
315
  maxBuffer: this.maxBufferBytes,
316
+ ...(signal ? { signal } : {}),
311
317
  timeout: this.timeoutMs,
312
318
  });
313
319
  const parsed = parseRipgrepJson(result.stdout, {
@@ -42,6 +42,20 @@ export function createWorkspaceMetadata(pathValue, type, info = {}) {
42
42
  };
43
43
  }
44
44
 
45
+ function enrichWorkspaceEntries(entries, metadata) {
46
+ const enrichedEntries = new Map(entries);
47
+ metadata.forEach((entryMetadata, pathValue) => {
48
+ const entry = enrichedEntries.get(pathValue);
49
+ const mtimeMs = Number(entryMetadata?.mtimeMs);
50
+ if (!entry || !Number.isFinite(mtimeMs) || entry.mtimeMs === mtimeMs) {
51
+ return;
52
+ }
53
+
54
+ enrichedEntries.set(pathValue, { ...entry, mtimeMs });
55
+ });
56
+ return enrichedEntries;
57
+ }
58
+
45
59
  export function collectWorkspaceStateStats(entries = new Map(), metadata = new Map()) {
46
60
  const filePaths = [];
47
61
  const markdownPaths = [];
@@ -75,8 +89,11 @@ export function collectWorkspaceStateStats(entries = new Map(), metadata = new M
75
89
  export function createWorkspaceStateSnapshot(entries = new Map(), metadata = new Map(), {
76
90
  scannedAt = Date.now(),
77
91
  } = {}) {
78
- const normalizedEntries = entries instanceof Map ? entries : new Map(entries ?? []);
79
92
  const normalizedMetadata = metadata instanceof Map ? metadata : new Map(metadata ?? []);
93
+ const normalizedEntries = enrichWorkspaceEntries(
94
+ entries instanceof Map ? entries : new Map(entries ?? []),
95
+ normalizedMetadata,
96
+ );
80
97
  const stats = collectWorkspaceStateStats(normalizedEntries, normalizedMetadata);
81
98
 
82
99
  return {
@@ -385,21 +402,24 @@ export function createWorkspaceTree(entries = new Map()) {
385
402
  return;
386
403
  }
387
404
 
388
- if (entry?.type === 'directory' || entry?.nodeType === 'directory') {
389
- nodesByPath.set(normalizedPath, {
405
+ const mtimeMs = Number(entry?.mtimeMs);
406
+ const node = entry?.type === 'directory' || entry?.nodeType === 'directory'
407
+ ? {
390
408
  children: [],
391
409
  name: entry?.name ?? basename(normalizedPath),
392
410
  path: normalizedPath,
393
411
  type: 'directory',
394
- });
395
- return;
396
- }
412
+ }
413
+ : {
414
+ name: entry?.name ?? basename(normalizedPath),
415
+ path: normalizedPath,
416
+ type: entry?.type ?? getVaultTreeNodeType(normalizedPath),
417
+ };
397
418
 
398
- nodesByPath.set(normalizedPath, {
399
- name: entry?.name ?? basename(normalizedPath),
400
- path: normalizedPath,
401
- type: entry?.type ?? getVaultTreeNodeType(normalizedPath),
402
- });
419
+ if (node.type !== 'directory' && Number.isFinite(mtimeMs)) {
420
+ node.mtimeMs = mtimeMs;
421
+ }
422
+ nodesByPath.set(normalizedPath, node);
403
423
  });
404
424
 
405
425
  nodesByPath.forEach((node, pathValue) => {
@@ -423,6 +443,7 @@ export function workspaceEntriesEqual(left = {}, right = {}) {
423
443
  && left.nodeType === right.nodeType
424
444
  && left.parentPath === right.parentPath
425
445
  && left.path === right.path
446
+ && left.mtimeMs === right.mtimeMs
426
447
  && left.type === right.type
427
448
  );
428
449
  }
@@ -1,5 +1,6 @@
1
1
  import { countPatchLines, parseNumstatOutput, parseUnifiedDiff } from './parsers.js';
2
- import { createDiffResponse, createEmptyStats } from './responses.js';
2
+ import { createEmptyStats } from './responses.js';
3
+ import { getVaultFileKind } from '../../../domain/file-kind.js';
3
4
 
4
5
  function createSectionMap(sections = []) {
5
6
  return new Map(sections.map((section) => [section.key, section]));
@@ -33,6 +34,7 @@ function mergeScopedFile(existingFile, nextFile, scope) {
33
34
  return {
34
35
  ...nextFile,
35
36
  ...nextFlags,
37
+ fileKind: nextFile.fileKind || getVaultFileKind(nextFile.path),
36
38
  scope,
37
39
  stats: createEmptyStats(),
38
40
  };
@@ -44,6 +46,7 @@ function mergeScopedFile(existingFile, nextFile, scope) {
44
46
  return {
45
47
  ...existingFile,
46
48
  ...nextFile,
49
+ fileKind: existingFile.fileKind || getVaultFileKind(nextFile.path),
47
50
  hasStagedChanges: existingFile.hasStagedChanges || nextFlags.hasStagedChanges,
48
51
  hasUntrackedChanges: existingFile.hasUntrackedChanges || nextFlags.hasUntrackedChanges,
49
52
  hasWorkingTreeChanges: existingFile.hasWorkingTreeChanges || nextFlags.hasWorkingTreeChanges,
@@ -54,6 +57,7 @@ function mergeScopedFile(existingFile, nextFile, scope) {
54
57
 
55
58
  return {
56
59
  ...existingFile,
60
+ fileKind: existingFile.fileKind || getVaultFileKind(nextFile.path),
57
61
  hasStagedChanges: existingFile.hasStagedChanges || nextFlags.hasStagedChanges,
58
62
  hasUntrackedChanges: existingFile.hasUntrackedChanges || nextFlags.hasUntrackedChanges,
59
63
  hasWorkingTreeChanges: existingFile.hasWorkingTreeChanges || nextFlags.hasWorkingTreeChanges,
@@ -162,12 +166,18 @@ export class GitDiffService {
162
166
  async getDiff({ allowLargePatch = false, metaOnly = false, path = null, scope = 'working-tree' } = {}) {
163
167
  const isGitRepo = await this.commandRunner.isGitRepo();
164
168
  if (!isGitRepo) {
165
- return createDiffResponse({
169
+ return {
166
170
  files: [],
167
171
  isGitRepo: false,
168
172
  metaOnly,
173
+ path: null,
169
174
  scope,
170
- });
175
+ summary: {
176
+ additions: 0,
177
+ deletions: 0,
178
+ filesChanged: 0,
179
+ },
180
+ };
171
181
  }
172
182
 
173
183
  const resolvedScope = scope === 'staged' || scope === 'all'
@@ -214,13 +224,14 @@ export class GitDiffService {
214
224
  scope,
215
225
  });
216
226
 
217
- return createDiffResponse({
227
+ return {
218
228
  files: scopedFiles,
229
+ isGitRepo: true,
219
230
  metaOnly: true,
220
231
  path,
221
232
  scope,
222
233
  summary: scopeSummary,
223
- });
234
+ };
224
235
  }
225
236
 
226
237
  const isSinglePathRequest = Boolean(path);
@@ -234,7 +245,7 @@ export class GitDiffService {
234
245
  };
235
246
 
236
247
  if (!allowLargePatch && fileLineCount > this.maxInitialPatchLines) {
237
- return createDiffResponse({
248
+ return {
238
249
  files: [{
239
250
  ...currentFile,
240
251
  canLoadFullPatch: true,
@@ -246,11 +257,12 @@ export class GitDiffService {
246
257
  },
247
258
  tooLarge: true,
248
259
  }],
260
+ isGitRepo: true,
249
261
  metaOnly: false,
250
262
  path,
251
263
  scope,
252
264
  summary,
253
- });
265
+ };
254
266
  }
255
267
 
256
268
  const syntheticFiles = await this.untrackedFileService.buildSyntheticDiffs([currentFile]);
@@ -263,7 +275,7 @@ export class GitDiffService {
263
275
  },
264
276
  };
265
277
 
266
- return createDiffResponse({
278
+ return {
267
279
  files: [{
268
280
  ...currentFile,
269
281
  ...detail,
@@ -271,11 +283,12 @@ export class GitDiffService {
271
283
  patchLineCount: countPatchLines(detail),
272
284
  tooLarge: false,
273
285
  }],
286
+ isGitRepo: true,
274
287
  metaOnly: false,
275
288
  path,
276
289
  scope,
277
290
  summary,
278
- });
291
+ };
279
292
  }
280
293
 
281
294
  let singleFileSummary = null;
@@ -293,7 +306,7 @@ export class GitDiffService {
293
306
  && singleFileSummary.filesChanged > 0
294
307
  && (singleFileSummary.additions + singleFileSummary.deletions) > this.maxInitialPatchLines
295
308
  ) {
296
- return createDiffResponse({
309
+ return {
297
310
  files: [{
298
311
  ...currentFile,
299
312
  canLoadFullPatch: true,
@@ -305,11 +318,12 @@ export class GitDiffService {
305
318
  },
306
319
  tooLarge: true,
307
320
  }],
321
+ isGitRepo: true,
308
322
  metaOnly: false,
309
323
  path,
310
324
  scope,
311
325
  summary: singleFileSummary,
312
- });
326
+ };
313
327
  }
314
328
  }
315
329
 
@@ -362,6 +376,7 @@ export class GitDiffService {
362
376
  return {
363
377
  ...file,
364
378
  ...detail,
379
+ fileKind: file.fileKind || detail.fileKind || getVaultFileKind(file.path),
365
380
  canLoadFullPatch: false,
366
381
  patchLineCount,
367
382
  tooLarge: false,
@@ -378,12 +393,13 @@ export class GitDiffService {
378
393
  filesChanged: 0,
379
394
  });
380
395
 
381
- return createDiffResponse({
396
+ return {
382
397
  files: mergedFiles,
398
+ isGitRepo: true,
383
399
  metaOnly: false,
384
400
  path,
385
401
  scope,
386
402
  summary: isSinglePathRequest ? singleFileSummary ?? summary : summary,
387
- });
403
+ };
388
404
  }
389
405
  }
@@ -1,6 +1,10 @@
1
- import { createGitRequestError } from './errors.js';
1
+ import { execFile as execFileCallback } from 'node:child_process';
2
+ import { access } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { promisify } from 'node:util';
5
+
6
+ import { createRequestError as createGitRequestError } from '../http/http-errors.js';
2
7
  import { normalizeRelativeGitPath } from './path-utils.js';
3
- import { GitCommandRunner } from './command-runner.js';
4
8
  import { GitDiffService } from './diff-service.js';
5
9
  import { GitHistoryService } from './history-service.js';
6
10
  import { parseNameStatusOutput } from './parsers.js';
@@ -9,6 +13,8 @@ import { GitStatusService } from './status-service.js';
9
13
  import { GitUntrackedFileService } from './untracked-files.js';
10
14
  import { PullBackupStore } from '../persistence/pull-backup-store.js';
11
15
 
16
+ const execFile = promisify(execFileCallback);
17
+
12
18
  function buildAuthorEnv(author = null) {
13
19
  const name = String(author?.name ?? '').trim();
14
20
  const email = String(author?.email ?? '').trim();
@@ -35,12 +41,53 @@ export class GitService {
35
41
  statusCacheTtlMs = 2_000,
36
42
  vaultDir,
37
43
  }) {
38
- this.commandRunner = new GitCommandRunner({
39
- commandEnv,
40
- enabled,
41
- execFileImpl,
42
- vaultDir,
43
- });
44
+ const gitExecFile = execFileImpl ?? execFile;
45
+ this.commandRunner = {
46
+ async isGitRepo() {
47
+ if (!enabled) {
48
+ return false;
49
+ }
50
+
51
+ try {
52
+ await access(join(vaultDir, '.git'));
53
+ return true;
54
+ } catch {
55
+ return false;
56
+ }
57
+ },
58
+ async execGit(args, { env = null } = {}) {
59
+ const result = await gitExecFile('git', ['-c', 'core.quotepath=false', ...args], {
60
+ cwd: vaultDir,
61
+ encoding: 'utf8',
62
+ env: {
63
+ ...process.env,
64
+ ...(commandEnv ?? {}),
65
+ ...(env ?? {}),
66
+ },
67
+ maxBuffer: 5 * 1024 * 1024,
68
+ timeout: 10_000,
69
+ });
70
+
71
+ return String(result.stdout ?? '');
72
+ },
73
+ async execGitBuffer(args, { env = null } = {}) {
74
+ const result = await gitExecFile('git', ['-c', 'core.quotepath=false', ...args], {
75
+ cwd: vaultDir,
76
+ encoding: null,
77
+ env: {
78
+ ...process.env,
79
+ ...(commandEnv ?? {}),
80
+ ...(env ?? {}),
81
+ },
82
+ maxBuffer: 5 * 1024 * 1024,
83
+ timeout: 10_000,
84
+ });
85
+
86
+ return Buffer.isBuffer(result.stdout)
87
+ ? result.stdout
88
+ : Buffer.from(result.stdout ?? '');
89
+ },
90
+ };
44
91
  this.untrackedFileService = new GitUntrackedFileService({ vaultDir });
45
92
  this.statusService = new GitStatusService({
46
93
  commandRunner: this.commandRunner,
@@ -177,7 +224,7 @@ export class GitService {
177
224
  throw createGitRequestError(
178
225
  409,
179
226
  'Cannot pull because local and remote commits have diverged; fast-forward only pull is not possible.',
180
- 'pull_diverged_ff_only',
227
+ { requestCode: 'pull_diverged_ff_only' },
181
228
  );
182
229
  }
183
230
 
@@ -263,6 +310,10 @@ export class GitService {
263
310
  return this.historyService.getFileSnapshot({ hash, path });
264
311
  }
265
312
 
313
+ async getFileAttachment({ hash, path } = {}) {
314
+ return this.historyService.getFileAttachment({ hash, path });
315
+ }
316
+
266
317
  async pathExistsAtRef(ref, path) {
267
318
  try {
268
319
  await this.commandRunner.execGit(['cat-file', '-e', `${ref}:${path}`]);
@@ -431,7 +482,7 @@ export class GitService {
431
482
  return createGitRequestError(
432
483
  409,
433
484
  'Pull applied remote updates, but reapplying local changes caused conflicts. Review the conflicted files and the pull backup summary.',
434
- 'pull_conflicted_after_autostash',
485
+ { requestCode: 'pull_conflicted_after_autostash' },
435
486
  );
436
487
  }
437
488