collabmd 0.1.45 → 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 (190) 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/comment-thread-store-CdcwrObc.js +1 -0
  7. package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
  8. package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +7 -0
  9. package/dist/client/assets/dist-B5HTH2BO.js +1 -0
  10. package/dist/client/assets/{dist-DhLvC8DS.js → dist-B5Jf1SLZ.js} +2 -2
  11. package/dist/client/assets/{dist-CnL7Y2sM.js → dist-BDt3rz7l.js} +1 -1
  12. package/dist/client/assets/dist-BEwK4csK.js +1 -0
  13. package/dist/client/assets/dist-BKW4PALF.js +1 -0
  14. package/dist/client/assets/dist-BWcHHOx-.js +1 -0
  15. package/dist/client/assets/{dist-CYZmbokb.js → dist-BalScOwZ.js} +9 -9
  16. package/dist/client/assets/dist-Bf8f4HmM.js +6 -0
  17. package/dist/client/assets/dist-BjHJDtyU.js +1 -0
  18. package/dist/client/assets/dist-Bm6pf9Bl.js +1 -0
  19. package/dist/client/assets/dist-BoVBdSjk.js +1 -0
  20. package/dist/client/assets/dist-CC5IrQMG.js +1 -0
  21. package/dist/client/assets/{dist-C11hHqv_.js → dist-CCP_AKPG.js} +12 -12
  22. package/dist/client/assets/dist-CZgOmxK6.js +1 -0
  23. package/dist/client/assets/{dist-D2AQ-76g.js → dist-Cqhv5LAk.js} +1 -1
  24. package/dist/client/assets/{dist-MvcV4190.js → dist-D-Z6FLem.js} +1 -1
  25. package/dist/client/assets/dist-DLMiIsNC.js +11 -0
  26. package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZKu9Cs8.js} +1 -1
  27. package/dist/client/assets/dist-DaYdhcVs.js +1 -0
  28. package/dist/client/assets/dist-FWJsgGYI.js +1 -0
  29. package/dist/client/assets/dist-Kh2COra_.js +1 -0
  30. package/dist/client/assets/{dist-JYEDRrPT.js → dist-PDZ3bSqm.js} +1 -1
  31. package/dist/client/assets/{dist-Drp8uu5J.js → dist-TjMh8n1u.js} +1 -1
  32. package/dist/client/assets/{dist-DGb27Dl6.js → dist-dtAdgL39.js} +1 -1
  33. package/dist/client/assets/dist-jv4WdPnK.js +9 -0
  34. package/dist/client/assets/{dist-DK5Gs2wa.js → dist-rGBmqxC7.js} +1 -1
  35. package/dist/client/assets/{dist-DCzuX1AF.js → dist-shrl6K_0.js} +1 -1
  36. package/dist/client/assets/dist-tOaegDYS2.js +1 -0
  37. package/dist/client/assets/dist-ule2n6ak.js +1 -0
  38. package/dist/client/assets/dist-xElaxbia.js +1 -0
  39. package/dist/client/assets/{drawio-editor-ClE8jpoG.js → drawio-editor-FzY1cVw8.js} +1 -1
  40. package/dist/client/assets/drawioEditor-BjiKJqlc.js +2 -0
  41. package/dist/client/assets/editor-session-Cm9ekeNo.js +54 -0
  42. package/dist/client/assets/embedded-editor-base-CwTkk911.css +1 -0
  43. package/dist/client/assets/{preview-render-profile-BZzGSg6K.js → es-DXGV3RHd.js} +13 -13
  44. package/dist/client/assets/excalidraw-editor-B46zsTFI.js +9 -0
  45. package/dist/client/assets/{excalidraw-editor-CyGwOhLz.css → excalidraw-editor-Bt7gMSoh.css} +1 -1
  46. package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
  47. package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +2 -0
  48. package/dist/client/assets/{export-page-CUfws2T-.js → export-page-A7NHawJY.js} +3 -3
  49. package/dist/client/assets/exportDocument-B2L8fe34.css +1 -0
  50. package/dist/client/assets/exportDocument-BaqcOAAW.js +2 -0
  51. package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
  52. package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
  53. package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +1 -0
  54. package/dist/client/assets/index-ClbjMBVt.js +2 -0
  55. package/dist/client/assets/index-Pum8ET-5.css +1 -0
  56. package/dist/client/assets/main-B3uPyqic.js +893 -0
  57. package/dist/client/assets/pdf-BL9Pr2D5.js +54 -0
  58. package/dist/client/assets/pdf.worker-CLesOks4.mjs +64857 -0
  59. package/dist/client/assets/pdf_viewer-FVkkThnz.js +551 -0
  60. package/dist/client/assets/{preview-render-compiler-BSaQO_p3.js → preview-render-compiler-BD-XhkS2.js} +2 -2
  61. package/dist/client/assets/preview-render-compiler-BKedaMxx.js +1 -0
  62. package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
  63. package/dist/client/assets/{preview-render-worker-B42LWvrD.js → preview-render-worker-CiPqc9n6.js} +20 -20
  64. package/dist/client/assets/prod-Dy20X7eT.js +1 -0
  65. package/dist/client/assets/prod-hnwh7wRM.js +177 -0
  66. package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +12 -0
  67. package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
  68. package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
  69. package/dist/client/drawio-editor.html +1 -1
  70. package/dist/client/excalidraw-editor.html +1 -1
  71. package/dist/client/export-document.html +2 -2
  72. package/dist/client/index.html +15 -3
  73. package/docker-compose.yml +42 -0
  74. package/package.json +17 -4
  75. package/scripts/local-structurizr-compose.mjs +101 -0
  76. package/src/client/app/index.html +13 -1
  77. package/src/client/application/app-shell/comments-feature.js +19 -10
  78. package/src/client/application/app-shell/git-feature.js +12 -0
  79. package/src/client/application/app-shell/presence-feature.js +2 -1
  80. package/src/client/application/app-shell/ui-feature-shell.js +45 -2
  81. package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
  82. package/src/client/application/app-shell/workspace-feature.js +5 -1
  83. package/src/client/application/app-shell-elements.js +2 -0
  84. package/src/client/application/pdf-preview-controller.js +992 -0
  85. package/src/client/application/structurizr-preview-controller.js +395 -0
  86. package/src/client/application/workspace-coordinator.js +25 -3
  87. package/src/client/application/workspace-preview-controller.js +91 -2
  88. package/src/client/bootstrap/collabmd-app-shell.js +31 -5
  89. package/src/client/browser-utils.js +44 -0
  90. package/src/client/domain/runtime-paths.js +26 -5
  91. package/src/client/domain/structurizr-language.js +99 -0
  92. package/src/client/domain/vault-paths.js +48 -0
  93. package/src/client/excalidraw-editor.js +833 -51
  94. package/src/client/infrastructure/browser-preferences-port.js +10 -0
  95. package/src/client/infrastructure/comment-thread-store.js +34 -13
  96. package/src/client/infrastructure/editor-session.js +10 -0
  97. package/src/client/infrastructure/editor-view-adapter.js +46 -2
  98. package/src/client/infrastructure/excalidraw-room-client.js +103 -14
  99. package/src/client/infrastructure/git-api-client.js +5 -0
  100. package/src/client/infrastructure/vault-api-client.js +26 -0
  101. package/src/client/presentation/comment-ui/comment-ui-shared.js +4 -0
  102. package/src/client/presentation/drawio-embed-controller.js +9 -102
  103. package/src/client/presentation/drawio-viewer.js +118 -0
  104. package/src/client/presentation/excalidraw-embed-controller.js +74 -8
  105. package/src/client/presentation/file-action-controller.js +102 -0
  106. package/src/client/presentation/file-explorer-view.js +10 -29
  107. package/src/client/presentation/file-icon-svg.js +40 -0
  108. package/src/client/presentation/file-tree-state.js +2 -0
  109. package/src/client/presentation/git-diff-view-controller.js +731 -3
  110. package/src/client/presentation/outline-controller.js +86 -0
  111. package/src/client/presentation/quick-switcher-controller.js +25 -13
  112. package/src/client/presentation/quick-switcher-text-search.js +1 -1
  113. package/src/client/styles/components/navigation.css +11 -1
  114. package/src/client/styles/features/diagram-preview.css +76 -0
  115. package/src/client/styles/features/diff-special.css +309 -0
  116. package/src/client/styles/foundation/themes.css +6 -0
  117. package/src/client/styles/layout/shell.css +358 -1
  118. package/src/client/styles/layout/view-modes.css +1 -0
  119. package/src/client/styles/style.css +1 -0
  120. package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
  121. package/src/domain/comment-threads.js +63 -5
  122. package/src/domain/excalidraw-room-codec.js +6 -4
  123. package/src/domain/file-kind.js +35 -3
  124. package/src/server/config/env.js +79 -0
  125. package/src/server/create-app-server.js +12 -0
  126. package/src/server/domain/bases/base-definition.js +1 -1
  127. package/src/server/domain/bases/base-expression-runtime.js +1 -4
  128. package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
  129. package/src/server/domain/bases/base-transform.js +1 -4
  130. package/src/server/domain/collaboration/collaboration-room.js +55 -21
  131. package/src/server/domain/comment-overview.js +15 -5
  132. package/src/server/domain/ripgrep-search-service.js +4 -0
  133. package/src/server/infrastructure/git/diff-service.js +5 -0
  134. package/src/server/infrastructure/git/git-service.js +21 -0
  135. package/src/server/infrastructure/git/history-service.js +54 -0
  136. package/src/server/infrastructure/git/image-mime.js +14 -0
  137. package/src/server/infrastructure/git/untracked-files.js +28 -1
  138. package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
  139. package/src/server/infrastructure/http/create-request-handler.js +16 -23
  140. package/src/server/infrastructure/http/create-static-handler.js +5 -2
  141. package/src/server/infrastructure/http/create-structurizr-api-handler.js +145 -0
  142. package/src/server/infrastructure/http/create-vault-api-command-handler.js +66 -4
  143. package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
  144. package/src/server/infrastructure/http/http-request-helpers.js +22 -0
  145. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  146. package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
  147. package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
  148. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +374 -0
  149. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
  150. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
  151. package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
  152. package/dist/client/assets/chunk-ERSWUTIN-ME9RVNel.js +0 -41
  153. package/dist/client/assets/comment-threads-DDegmaFO.js +0 -4
  154. package/dist/client/assets/dist-BH87JoHx.js +0 -11
  155. package/dist/client/assets/dist-BIkPRZO7.js +0 -6
  156. package/dist/client/assets/dist-BqCsFpx4.js +0 -1
  157. package/dist/client/assets/dist-C2JHCt8U.js +0 -1
  158. package/dist/client/assets/dist-CZjTtmTu.js +0 -1
  159. package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
  160. package/dist/client/assets/dist-CqQEC8gR.js +0 -1
  161. package/dist/client/assets/dist-D4Rzqod1.js +0 -1
  162. package/dist/client/assets/dist-D5sn-mwk.js +0 -9
  163. package/dist/client/assets/dist-D7G-n87v.js +0 -1
  164. package/dist/client/assets/dist-DRqOrNgN.js +0 -1
  165. package/dist/client/assets/dist-DetkMS_4.js +0 -1
  166. package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
  167. package/dist/client/assets/dist-DtbjNB28.js +0 -1
  168. package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
  169. package/dist/client/assets/dist-GrygD2zE.js +0 -1
  170. package/dist/client/assets/dist-HmEpWUow.js +0 -1
  171. package/dist/client/assets/dist-RTa81Km7.js +0 -1
  172. package/dist/client/assets/drawioEditor-CXaTM9Ds.js +0 -2
  173. package/dist/client/assets/editor-session-GTwZS6Df.js +0 -16
  174. package/dist/client/assets/embedded-editor-base-CiNEc8vy.css +0 -1
  175. package/dist/client/assets/excalidraw-editor-BZVM81BO.js +0 -9
  176. package/dist/client/assets/excalidraw-scene-C8n9CHsK.js +0 -176
  177. package/dist/client/assets/excalidrawEditor-DxJanCze.js +0 -2
  178. package/dist/client/assets/exportDocument-BCuxqXDY.js +0 -2
  179. package/dist/client/assets/exportDocument-DV-OX74E.css +0 -1
  180. package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
  181. package/dist/client/assets/image-QXRYHUNP-lfTHE3bb.js +0 -1
  182. package/dist/client/assets/index-C3YnUgMD.css +0 -1
  183. package/dist/client/assets/index-D2wXraJ1.js +0 -2
  184. package/dist/client/assets/main-DtiGz7uI.js +0 -795
  185. package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
  186. package/dist/client/assets/quick-switcher-controller-shW_6vPY.js +0 -12
  187. package/dist/client/assets/room-CQLoqtMo.js +0 -1
  188. package/dist/client/assets/runtime-config-DSGmGE9V.js +0 -1
  189. package/dist/client/assets/vault-api-client-C6bcGwy-.js +0 -5
  190. package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
package/README.md CHANGED
@@ -14,13 +14,13 @@ Realtime collaboration for Markdown folders, diagrams, and git-backed docs, with
14
14
 
15
15
  CollabMD turns a local Markdown folder, Obsidian-style vault, or docs repo into a collaborative workspace you can open in the browser.
16
16
 
17
- Throughout this guide, **vault** simply means a regular folder on your computer that contains Markdown files.
17
+ Throughout this guide, **vault** simply means a regular folder on your computer that contains Markdown, diagram, and attachment files.
18
18
 
19
19
  - No migration: your files stay on disk
20
20
  - Your filesystem stays the source of truth: CollabMD does not move, rename, or delete files unless you explicitly do that in the app
21
21
  - Realtime editing with Yjs
22
22
  - External filesystem edits sync back into the app and connected browsers
23
- - Mermaid, PlantUML, Excalidraw, and draw.io support
23
+ - Mermaid, PlantUML, Structurizr DSL, Excalidraw, and draw.io support
24
24
  - Source-anchored comments, chat, and presence
25
25
  - Works with plain folders, Obsidian-style vaults, and git-backed docs
26
26
 
@@ -65,11 +65,12 @@ Prefer video? [Open the WebM demo](https://raw.githubusercontent.com/andes90/col
65
65
  - **Local-files-first** — your filesystem remains the source of truth
66
66
  - **Realtime collaboration** — multiple people can edit the same file at the same time via Yjs
67
67
  - **External edit sync** — changes made from tools like Obsidian or direct file writes are reflected back into open documents and the file explorer
68
+ - **File upload** — import multiple supported Markdown, Base, diagram, image, and PDF files into the vault from the file explorer
68
69
  - **Markdown with context** — live preview, wiki-links, backlinks, outline, quick switcher, and scroll sync
69
70
  - **Global text search** — search text across supported vault files with ripgrep-backed results grouped by file
70
- - **Source-anchored comments** — comment on lines or selected text with inline markers, preview bubbles, and thread cards
71
+ - **Source-anchored comments** — comment on lines or selected text with inline markers and preview bubbles, or pin threads to Excalidraw elements
71
72
  - **Collaboration built in** — collaborator presence, follow mode, and team chat
72
- - **Diagram-friendly** — Mermaid fences and standalone `.mmd` / `.mermaid`, PlantUML `.puml` / `.plantuml`, `.excalidraw`, `.drawio`, and public video embeds in Markdown
73
+ - **Diagram-friendly** — Mermaid fences and standalone `.mmd` / `.mermaid`, PlantUML `.puml` / `.plantuml`, Structurizr `.dsl` C4 workspaces, `.excalidraw`, `.drawio`, readonly PDF previews, and public video embeds in Markdown
73
74
  - **Easy browser access** — optional Cloudflare Tunnel support makes a running session easy to share
74
75
 
75
76
  ## Best fit for
@@ -168,7 +169,7 @@ Then share the printed URL and password with your collaborator. If `cloudflared`
168
169
  - Single-instance deployment only: collaboration room state is kept in-process and is not shared across replicas
169
170
  - `oidc` currently supports Google only
170
171
  - Hosted workspace mode currently provides the backend/API surface; Team Settings UI, invitation email delivery, GitHub callback redirect polish, and GitHub App checkout/publish wiring are still pending
171
- - Source-anchored comments currently support markdown, Mermaid, and PlantUML text files, but not `.excalidraw` or `.drawio`
172
+ - Text-anchored comments support markdown, Mermaid, PlantUML, and Structurizr DSL files. Excalidraw supports element-anchored threads; draw.io comments are not supported
172
173
  - Windows use is supported via WSL2 rather than native Windows execution
173
174
 
174
175
  ## How it works
@@ -179,16 +180,16 @@ collabmd ~/my-vault --no-tunnel
179
180
 
180
181
  CollabMD starts a local server, scans the vault, and opens a browser-based editor with:
181
182
 
182
- - **File explorer sidebar** — browse, create, rename, and delete `.md`, `.mmd`, `.mermaid`, `.puml`, `.plantuml`, `.excalidraw`, and `.drawio` files plus folders
183
- - **Live preview** — rendered as you type, with syntax-highlighted code blocks, public video embeds, plus Mermaid and PlantUML diagrams
184
- - **Anchored comments** — add comments from the editor, open threads from inline markers or preview bubbles, and review them from the comments drawer
183
+ - **File explorer sidebar** — upload, browse, create, rename, and delete `.md`, `.markdown`, `.mdx`, `.base`, `.mmd`, `.mermaid`, `.puml`, `.plantuml`, `.dsl`, `.excalidraw`, `.drawio`, `.pdf`, and supported image files plus folders
184
+ - **Live preview** — rendered as you type, with syntax-highlighted code blocks, public video embeds, plus Mermaid, PlantUML, and Structurizr diagrams
185
+ - **Anchored comments** — add comments from the editor or selected Excalidraw elements, reopen threads in context, and review them from the comments drawer
185
186
  - **`[[wiki-links]]` + backlinks** — jump between notes and inspect linked mentions
186
187
  - **Room chat** — discuss changes without leaving the workspace
187
188
  - **Presence + follow mode** — see who is online and follow another collaborator's active cursor
188
189
  - **Quick switcher, global text search, and outline** — move around large vaults and long documents faster
189
- - **Standalone diagram files** — open `.mmd` / `.mermaid` or `.puml` / `.plantuml` files in side-by-side editor + preview, `.excalidraw` files in direct preview mode, and `.drawio` files in an embedded diagrams.net editor/viewer
190
+ - **Standalone diagram files** — open `.mmd` / `.mermaid`, `.puml` / `.plantuml`, or `.dsl` files in side-by-side editor + preview; Structurizr workspaces provide context → container → component navigation; `.excalidraw` files use direct preview mode, `.drawio` files use an embedded diagrams.net editor/viewer, and `.pdf` files use a readonly browser preview
190
191
 
191
- Comment threads are source-anchored and currently supported for markdown, Mermaid, and PlantUML text files. You can comment on a whole line or a text selection, then reopen the thread from either the editor marker or the preview bubble. Excalidraw and draw.io files are currently excluded from comments.
192
+ Text comment threads are source-anchored for markdown, Mermaid, PlantUML, and Structurizr DSL files. You can comment on a whole line or a text selection, then reopen the thread from either the editor marker or preview bubble. Excalidraw threads attach to selected canvas elements and also appear in the workspace overview. Draw.io comments are not supported.
192
193
 
193
194
  Draw.io files use the diagrams.net embed/runtime. Opening a `.drawio` file directly mounts an interactive editor in the preview pane. Markdown embeds such as `![[architecture.drawio]]` use the diagrams.net viewer for a lighter inline preview and include an `Open` action to jump into the full file view.
194
195
 
@@ -196,7 +197,7 @@ Draw.io collaboration is intentionally conservative in this release: one connect
196
197
 
197
198
  Markdown video embeds are opt-in and use standard image syntax such as `![Video](https://www.youtube.com/watch?v=...)` or `![Video](https://cdn.example.com/demo.webm)`. The preview currently supports public YouTube URLs plus direct public `https` video files ending in `.mp4`, `.webm`, or `.ogg`. The editor toolbar also includes a `Video` action that inserts the same Markdown syntax for you.
198
199
 
199
- Your filesystem is the source of truth. CollabMD reads files from disk, uses Yjs for realtime collaboration, and continuously writes plain text back to disk as you type. External changes from tools like Obsidian, direct file writes, or git-driven file updates are watched and reconciled back into live rooms and the explorer.
200
+ Your filesystem is the source of truth. CollabMD reads files from disk, uses Yjs for realtime collaboration, and continuously writes plain text back to disk as you type. External changes from tools like Obsidian, direct file writes, or git-driven file updates are watched and reconciled back into live rooms and the explorer. The file explorer can import multiple supported vault files at once; uploads preserve their names and bytes, reject duplicates, and include PDF files for readonly preview.
200
201
 
201
202
  ## Usage
202
203
 
@@ -219,6 +220,7 @@ collabmd [directory] [options]
219
220
  | `--auth` | Auth strategy: `none`, `password`, `oidc` | `none` |
220
221
  | `--auth-password` | Password for `--auth password` | generated per run |
221
222
  | `--local-plantuml` | Start the bundled local docker-compose PlantUML service | off |
223
+ | `--local-structurizr` | Start the bundled local Structurizr renderer | off |
222
224
  | `--no-tunnel` | Don't start Cloudflare Tunnel | tunnel on |
223
225
  | `-v, --version` | Show version | |
224
226
  | `-h, --help` | Show help | |
@@ -250,6 +252,9 @@ collabmd --auth oidc --no-tunnel
250
252
  # Use the local docker-compose PlantUML service
251
253
  collabmd --local-plantuml
252
254
 
255
+ # Use the local Structurizr renderer for .dsl workspaces
256
+ collabmd --local-structurizr
257
+
253
258
  # Serve an Obsidian vault
254
259
  collabmd ~/Documents/Obsidian/MyVault
255
260
  ```
@@ -396,11 +401,13 @@ For the full runtime env var reference, see the `Environment variables` details
396
401
 
397
402
  Published image: `ghcr.io/andes90/collabmd:latest`
398
403
 
404
+ From the vault directory:
405
+
399
406
  ```bash
400
- docker run -p 1234:1234 -v /path/to/vault:/data ghcr.io/andes90/collabmd:latest
407
+ docker run --rm -p 1234:1234 -v "$PWD:/data" ghcr.io/andes90/collabmd:latest
401
408
  ```
402
409
 
403
- The published Docker image includes `ripgrep`, so global text search works without installing extra packages in the container.
410
+ Open `http://localhost:1234`. The published Docker image includes `ripgrep`, so global text search works without installing extra packages in the container.
404
411
 
405
412
  The container listens on `0.0.0.0:1234` and stores vault files at `/data`.
406
413
 
@@ -459,9 +466,9 @@ docker run \
459
466
  ghcr.io/andes90/collabmd:latest
460
467
  ```
461
468
 
462
- ### Local docker-compose with a private PlantUML server
469
+ ### Local docker-compose with private diagram renderers
463
470
 
464
- The included `docker-compose.yml` runs a prebuilt CollabMD image together with a local `plantuml/plantuml-server:jetty` container and points `PLANTUML_SERVER_URL` at the private service automatically.
471
+ The included `docker-compose.yml` runs a prebuilt CollabMD image together with local PlantUML and Structurizr containers. PlantUML SVG rendering and Structurizr `workspace.dsl` previews stay on the private Docker network automatically.
465
472
 
466
473
  ```bash
467
474
  mkdir -p data/vault
@@ -495,10 +502,13 @@ docker build -t collabmd:local .
495
502
  COLLABMD_IMAGE=collabmd:local docker compose up
496
503
  ```
497
504
 
498
- The PlantUML container is also published on loopback by default at `http://127.0.0.1:18080`, so the host-based CLI can reuse it with:
505
+ The PlantUML container is published on loopback by default at `http://127.0.0.1:18080`, and Structurizr is published at `http://127.0.0.1:19090` for host-based CLI use:
499
506
 
500
507
  ```bash
501
508
  npm run start:local-plantuml
509
+
510
+ # Start CollabMD with Structurizr DSL support
511
+ npm run start:local-structurizr -- --no-tunnel
502
512
  ```
503
513
 
504
514
  To use an existing vault on your machine instead of `./data/vault`:
@@ -579,6 +589,7 @@ npm run dev:client # Start the Vite dev server with API/WebSocket pro
579
589
  npm run dev:server # Start only the backend server for local frontend development
580
590
  npm run start # Build + start server
581
591
  npm run start:local-plantuml # Build + start server with local docker-compose PlantUML
592
+ npm run start:local-structurizr # Build + start server with local Structurizr
582
593
  npm run start:prod # Start server (expects previous build)
583
594
  npm run test # Run unit + e2e tests
584
595
  npm run test:unit # Fast Node-based unit tests
@@ -586,6 +597,8 @@ npm run test:e2e # Playwright browser tests
586
597
  npm run tunnel # Start only the Cloudflare tunnel
587
598
  npm run plantuml:up # Start only the local docker-compose PlantUML service
588
599
  npm run plantuml:down # Stop only the local docker-compose PlantUML service
600
+ npm run structurizr:up # Start only the local Structurizr renderer
601
+ npm run structurizr:down # Stop only the local Structurizr renderer
589
602
  npm run capture:readme-assets # Regenerate the README screenshot and demo assets
590
603
  ```
591
604
 
@@ -678,8 +691,14 @@ vite.config.mjs Vite multi-page build and dev-server proxy config
678
691
  | `COLLABMD_GITHUB_HTML_BASE_URL` | GitHub web base URL for installation setup | `https://github.com` |
679
692
  | `COLLABMD_GITHUB_SETUP_FLOW_COOKIE_NAME` | Signed cookie name for the GitHub App setup callback flow | `collabmd_github_setup_flow` |
680
693
  | `PLANTUML_SERVER_URL` | Upstream PlantUML server base URL used for server-side SVG rendering | `https://www.plantuml.com/plantuml` |
694
+ | `STRUCTURIZR_SERVER_URL` | Structurizr Local-compatible sidecar base URL used for `.dsl` previews | disabled |
695
+ | `COLLABMD_STRUCTURIZR_MIRROR_DIR` | Writable disposable mirror directory passed to Structurizr | `<vault>/.collabmd/structurizr` |
696
+ | `COLLABMD_STRUCTURIZR_TRUSTED_EXECUTABLE_DSL` | Allow Structurizr `!script` and `!plugin` directives; keep false for untrusted vaults | `false` |
681
697
  | `COLLABMD_DRAWIO_BASE_URL` | diagrams.net base URL used for `.drawio` viewing and editing | `https://embed.diagrams.net` |
682
698
  | `COLLABMD_WIKI_LINK_AUTO_CREATE` | Create missing markdown files when clicking unresolved wiki-links; set to `false` to disable | `true` |
699
+ | `COLLABMD_SEARCH_MAX_FILE_SIZE` | Maximum size of each file considered by global text search; supports bytes or `K`, `M`, and `G` suffixes | `1M` |
700
+ | `COLLABMD_SEARCH_MAX_BUFFER_BYTES` | Maximum ripgrep output buffer for one global text search | `2097152` |
701
+ | `COLLABMD_MAX_PDF_UPLOAD_BYTES` | Maximum size of a PDF upload in bytes; other uploads remain limited to the default 8 MiB request-body limit | `52428800` |
683
702
  | `COLLABMD_VAULT_DIR` | Vault directory path | CLI: current directory, server entrypoint: `data/vault`, Docker: `/data` |
684
703
  | `COLLABMD_GIT_ENABLED` | Enable or disable git integration in the UI and API | `true` |
685
704
  | `COLLABMD_GIT_REPO_URL` | Remote git repository used to bootstrap the vault checkout | |
@@ -718,10 +737,11 @@ cp .env.example .env
718
737
  - If `COLLABMD_GIT_SSH_KNOWN_HOSTS_FILE` is not set, SSH falls back to `StrictHostKeyChecking=accept-new`.
719
738
  - External filesystem edits are reconciled back into active rooms and the explorer. Ambiguous watcher bursts still fall back to batched workspace reconciliation.
720
739
  - `.obsidian`, `.git`, `.trash`, and `node_modules` directories are ignored.
721
- - Only `.md`, `.markdown`, and `.mdx` files are indexed.
740
+ - Markdown, Base, Mermaid, PlantUML, Structurizr DSL, draw.io, Excalidraw, PDF, and image files are tracked by the vault tree; global text search indexes supported text formats.
722
741
  - PlantUML preview rendering is server-side and uses `PLANTUML_SERVER_URL`; point it at a self-hosted renderer if you do not want to use the public PlantUML service.
723
- - `docker compose up` uses the included local PlantUML service and avoids the public renderer by default. The initial git clone may also require a longer health-check grace period than a purely local vault.
724
- - `collabmd --local-plantuml` and `npm run start:local-plantuml` will start the local PlantUML compose service first, then run CollabMD against `http://127.0.0.1:${PLANTUML_HOST_PORT:-18080}`.
742
+ - Structurizr previews use a read-only official Local sidecar and a disposable `.collabmd/structurizr` mirror; the authoritative vault is never mounted into the renderer as its data directory.
743
+ - `docker compose up` uses the included local PlantUML and Structurizr services and avoids public diagram renderers by default. The initial git clone may also require a longer health-check grace period than a purely local vault.
744
+ - `collabmd --local-plantuml` and `npm run start:local-plantuml` start the local PlantUML compose service. `collabmd --local-structurizr` starts Structurizr Local against `http://127.0.0.1:${STRUCTURIZR_HOST_PORT:-19090}`.
725
745
 
726
746
  ## License
727
747
 
package/bin/collabmd.js CHANGED
@@ -16,6 +16,7 @@ const { values, positionals } = parseArgs({
16
16
  'auth-password': { type: 'string' },
17
17
  help: { type: 'boolean', short: 'h', default: false },
18
18
  'local-plantuml': { type: 'boolean', default: false },
19
+ 'local-structurizr': { type: 'boolean', default: false },
19
20
  port: { type: 'string', short: 'p', default: '1234' },
20
21
  host: { type: 'string' },
21
22
  'no-tunnel': { type: 'boolean', default: false },
@@ -45,6 +46,7 @@ if (values.help) {
45
46
  --auth <strategy> Auth strategy: none, password, oidc (default: none)
46
47
  --auth-password <pw> Password for --auth password (default: generated per run)
47
48
  --local-plantuml Start the bundled docker-compose PlantUML service and use it
49
+ --local-structurizr Start the bundled Structurizr Local service and use it
48
50
  --no-tunnel Don't start Cloudflare Tunnel
49
51
  -v, --version Show version
50
52
  -h, --help Show this help
@@ -55,6 +57,7 @@ if (values.help) {
55
57
  collabmd --port 3000 Use a custom port
56
58
  collabmd --auth password Require a generated password to join
57
59
  collabmd --local-plantuml Use the local docker-compose PlantUML server
60
+ collabmd --local-structurizr Use the local docker-compose Structurizr renderer
58
61
  collabmd --no-tunnel Local only, no tunnel
59
62
  `);
60
63
  process.exit(0);
@@ -64,6 +67,7 @@ const port = parseInt(values.port ?? process.env.PORT ?? '1234', 10) || 1234;
64
67
  const host = values.host || process.env.HOST || '127.0.0.1';
65
68
  const enableTunnel = !values['no-tunnel'];
66
69
  const useLocalPlantUml = values['local-plantuml'];
70
+ const useLocalStructurizr = values['local-structurizr'];
67
71
 
68
72
  const { resolveCliVaultDir, loadConfig } = await import('../src/server/config/env.js');
69
73
  const vaultPath = resolveCliVaultDir(positionals);
@@ -101,6 +105,27 @@ if (useLocalPlantUml) {
101
105
  }
102
106
  }
103
107
 
108
+ if (useLocalStructurizr) {
109
+ const {
110
+ getLocalStructurizrServerUrl,
111
+ startLocalStructurizrComposeService,
112
+ } = await import('../scripts/local-structurizr-compose.mjs');
113
+
114
+ try {
115
+ const localStructurizrUrl = getLocalStructurizrServerUrl();
116
+ console.log(` Structurizr: starting local docker-compose service at ${localStructurizrUrl}...`);
117
+ await startLocalStructurizrComposeService({ vaultDir: vaultPath });
118
+ process.env.STRUCTURIZR_SERVER_URL = localStructurizrUrl;
119
+ } catch (error) {
120
+ if (error.code === 'ENOENT') {
121
+ console.error('Error: Docker is not available. Install Docker Desktop or Docker Engine first.');
122
+ } else {
123
+ console.error(`Error: Failed to start local Structurizr service: ${error.message}`);
124
+ }
125
+ process.exit(1);
126
+ }
127
+ }
128
+
104
129
  const { createAppServer } = await import('../src/server/create-app-server.js');
105
130
  const { prepareConfigForStartup } = await import('../src/server/startup/git-remote-bootstrap.js');
106
131
 
@@ -185,9 +210,10 @@ try {
185
210
  console.log(` ║${bannerLine}║`);
186
211
  console.log(' ╚══════════════════════════════════════╝');
187
212
  console.log('');
188
- console.log(` Vault: ${vaultPath} (${fileCount} markdown files)`);
213
+ console.log(` Vault: ${vaultPath} (${fileCount} files)`);
189
214
  console.log(` Local: http://${info.host}:${info.port}`);
190
215
  console.log(` PlantUML: ${config.plantumlServerUrl}`);
216
+ console.log(` Structurizr: ${config.structurizr?.enabled ? config.structurizr.serverUrl : 'disabled'}`);
191
217
  if (config.auth.strategy === 'password') {
192
218
  console.log(` Auth: password`);
193
219
  console.log(` Secret: ${config.auth.password}`);
@@ -0,0 +1 @@
1
+ import{i as e}from"./rolldown-runtime-Dd_uD5pT.js";import{B as t,L as n,N as r,Q as i,R as a,W as o,Z as s,c,dt as l,et as u,pt as d,t as f}from"./dist-CCP_AKPG.js";import"./chunk-SRAX5OIU-KFQikY-4.js";import{n as p,t as m}from"./jsx-runtime-BpzPEenQ.js";import{a as h,o as g,p as _,s as v}from"./dist-xElaxbia.js";var y=e(p(),1),b=m(),x=c.define({token(e){return e.match(/^%%.*$/)?`comment`:e.match(/^"(?:[^"\\]|\\.)*"/)?`string`:e.match(/^(flowchart|graph|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|journey|gitGraph|timeline|quadrantChart|sankey|xychart)\b/i)||e.match(/^(TB|TD|BT|RL|LR)\b/)||e.match(/^(subgraph|end|participant|actor|loop|alt|else|opt|par|critical|break|rect|note|over|activate|deactivate|title|section|class|style|linkStyle|classDef|click)\b/i)?`keyword`:e.match(/^[-.=<>|ox]+>/)||e.match(/^<[-.=<>|ox]+/)||e.match(/^--+|\.\.+|==+/)?`operator`:e.match(/^[[\](){}|<>]/)?`bracket`:e.match(/^[A-Za-z_][A-Za-z0-9_]*/)?`variableName`:e.match(/^\d+(\.\d+)?/)?`number`:e.match(/^[,:;]/)?`punctuation`:(e.eatSpace()||e.next(),null)}});function S(){return x}var C=t.theme({"&":{backgroundColor:`#1e1e1e`,color:`#d4d4d4`},".cm-content":{caretColor:`#fff`},".cm-cursor":{borderLeftColor:`#fff`},".cm-gutters":{backgroundColor:`#1e1e1e`,color:`#858585`,border:`none`},".cm-activeLineGutter":{backgroundColor:`#2a2a2a`},".cm-activeLine":{backgroundColor:`#2a2a2a`},".cm-errorLine":{backgroundColor:`rgba(255, 0, 0, 0.15)`}},{dark:!0}),w=f.define([{tag:n.keyword,color:`#569cd6`},{tag:n.string,color:`#ce9178`},{tag:n.comment,color:`#6a9955`},{tag:n.number,color:`#b5cea8`},{tag:n.operator,color:`#d4d4d4`},{tag:n.punctuation,color:`#d4d4d4`},{tag:n.variableName,color:`#9cdcfe`},{tag:n.bracket,color:`#ffd700`}]),T=t.theme({"&":{backgroundColor:`#ffffff`,color:`#1e1e1e`},".cm-content":{caretColor:`#000`},".cm-cursor":{borderLeftColor:`#000`},".cm-gutters":{backgroundColor:`#fff`,color:`#999`,border:`none`},".cm-activeLineGutter":{backgroundColor:`#e8e8e8`},".cm-activeLine":{backgroundColor:`#e8e8e8`},".cm-errorLine":{backgroundColor:`rgba(255, 0, 0, 0.1)`}}),E=f.define([{tag:n.keyword,color:`#0000ff`},{tag:n.string,color:`#a31515`},{tag:n.comment,color:`#008000`},{tag:n.number,color:`#098658`},{tag:n.operator,color:`#1e1e1e`},{tag:n.punctuation,color:`#1e1e1e`},{tag:n.variableName,color:`#001080`},{tag:n.bracket,color:`#af00db`}]),D=a.line({class:`cm-errorLine`}),O=(e,n)=>{if(!e||e<1||e>n.lines)return t.decorations.of(a.none);let r=n.line(e);return t.decorations.of(a.set([D.range(r.from)]))},k=e=>e===`dark`?[C,r(w)]:[T,r(E)],A=({value:e,onChange:n,onKeyboardSubmit:r,placeholder:a,theme:c,errorLine:f})=>{let p=(0,y.useRef)(null),m=(0,y.useRef)(null),x=(0,y.useRef)(n),C=(0,y.useRef)(r),w=(0,y.useRef)(new l),T=(0,y.useRef)(new l);return x.current=n,C.current=r,(0,y.useEffect)(()=>{if(!p.current)return;let n=w.current,r=new t({state:d.create({doc:e,extensions:[s.of([{key:`Mod-Enter`,run:()=>(C.current?.(),!0)},{key:`Mod-Shift-z`,run:_,preventDefault:!0}]),t.updateListener.of(e=>{e.docChanged&&x.current(e.state.doc.toString())}),g(),s.of([...h,...v]),i(),t.lineWrapping,n.of(k(c)),T.current.of([]),S(),o({drawRangeCursor:!0}),...a?[u(a)]:[]]}),parent:p.current});return m.current=r,r.focus(),()=>{r.destroy(),m.current=null}},[]),(0,y.useEffect)(()=>{let e=m.current;e&&e.dispatch({effects:w.current.reconfigure(k(c))})},[c]),(0,y.useEffect)(()=>{let e=m.current;e&&e.dispatch({effects:T.current.reconfigure(O(f,e.state.doc))})},[f]),(0,y.useEffect)(()=>{let t=m.current;if(!t)return;let n=t.state.doc.toString();e!==n&&t.dispatch({changes:{from:0,to:n.length,insert:e}})},[e]),(0,b.jsx)(`div`,{ref:p,className:`ttd-dialog-input ttd-dialog-input--codemirror`})};export{A as default};
@@ -0,0 +1 @@
1
+ function e(){return typeof window>`u`?globalThis:window}function t({accept:t=``,multiple:n=!1}={}){return new Promise(r=>{let i=document.createElement(`input`),a=e();i.type=`file`,i.accept=t,i.multiple=n,i.style.position=`fixed`,i.style.left=`-9999px`,document.body.appendChild(i);let o=!1,s=null,c=(e=[])=>{o||(o=!0,s&&a.clearTimeout(s),a.removeEventListener(`focus`,l),i.remove(),r(Array.from(e??[])))},l=()=>{s=a.setTimeout(()=>{o||i.files?.length||c()},250)};i.addEventListener(`change`,()=>c(i.files),{once:!0}),i.addEventListener(`cancel`,()=>c(),{once:!0}),a.addEventListener(`focus`,l,{once:!0}),i.click()})}function n(t,n){let r=e();return typeof r.requestIdleCallback==`function`?r.requestIdleCallback(t,{timeout:n}):r.setTimeout(()=>t({didTimeout:!1,timeRemaining:()=>0}),1)}function r(t){if(t===null)return;let n=e();if(typeof n.cancelIdleCallback==`function`){n.cancelIdleCallback(t);return}n.clearTimeout(t)}function i(e,t,n){if(!e||!t)return!1;let r=t.getBoundingClientRect(),i=e.getBoundingClientRect();return i.bottom>=r.top-n&&i.top<=r.bottom+n}function a(t,n,{removeDelayMs:r=3e4,revokeDelayMs:i=r}={}){let a=e(),o=URL.createObjectURL(t),s=document.createElement(`a`);s.href=o,s.download=n,s.style&&(s.style.display=`none`),document.body.appendChild(s),s.click(),r>0?a.setTimeout(()=>s.remove(),r):s.remove(),a.setTimeout(()=>URL.revokeObjectURL(o),i)}function o(e=``,t=`download`){let n=String(e).match(/filename\*=UTF-8''([^;]+)/iu);if(n)try{return decodeURIComponent(n[1])}catch{return t}return String(e).match(/filename="([^"]+)"/iu)?.[1]||t}export{t as a,o as i,a as n,n as o,i as r,r as t};