collabmd 0.1.47 → 0.1.49
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.
- package/README.md +70 -11
- package/bin/collabmd.js +3 -0
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-C-nmgL5g.js +1 -0
- package/dist/client/assets/JetBrainsMono-Regular-BQaDgvhP.woff2 +0 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CdVZqicp.js +1 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-wUo0bXif.js} +3 -3
- package/dist/client/assets/babel-CY5KOv-I.js +16 -0
- package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-BRSK3m49.js} +4 -4
- package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
- package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-yD2poxqw.js} +1 -1
- package/dist/client/assets/channel-Fa4GS_-F.js +1 -0
- package/dist/client/assets/chunk-2E4U76K2-BPnTT-J3.js +2 -0
- package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-DStbIfJ1.js} +20 -20
- package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-C5pGd3W9.js} +1 -1
- package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-BMeArk03.js} +1 -1
- package/dist/client/assets/chunk-DU6HZSFF-Zkp69c6c.js +127 -0
- package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-D4xNct1r.js} +1 -1
- package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-NZ6WpDb8.js} +1 -1
- package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D8SDprfX.js} +1 -1
- package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-D8jEuU3Q.js} +2 -2
- package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-aijKP-eh.js} +1 -1
- package/dist/client/assets/chunk-OSK3NFVY-CCbLQAMa.js +10 -0
- package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Oag_FdCq.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-CYnpIgXT.js} +1 -1
- package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-JSNrcBmP.js} +1 -1
- package/dist/client/assets/{chunk-RM4UPSZO-CWRwxNWJ.js → chunk-RM4UPSZO-DOWllDY8.js} +4 -4
- package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BiQGljao.js} +5 -5
- package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-DB485R5x.js} +1 -1
- package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-8rAVvoS3.js} +4 -4
- package/dist/client/assets/{chunk-CKBBP62Z-DG26UiBv.js → chunk-TLUHSLCS-DTY5v0aj.js} +2 -2
- package/dist/client/assets/classDiagram-ZZMXUADV-BsQWoR3Q.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BsQWoR3Q.js +1 -0
- package/dist/client/assets/{comment-thread-store-CdcwrObc.js → comment-thread-store-CX98zR6q.js} +1 -1
- package/dist/client/assets/comment-threads-BnRwo5B9.js +4 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-rTz9RhFH.js} +1 -1
- package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-Cr67wLpQ.js} +2 -2
- package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-DywERe__.js} +2 -2
- package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-CNYlXtu4.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-0H1a61Bn.js +3 -0
- package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-CsJbsx5F.js} +1 -1
- package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D0mLxEgI.js} +1 -1
- package/dist/client/assets/dist--hk9I5HQ.js +1 -0
- package/dist/client/assets/{dist-DutPuFmC.js → dist-B1XEa-Zs.js} +1 -1
- package/dist/client/assets/dist-Bd1JucQF.js +1 -0
- package/dist/client/assets/{dist-DZAAWTG-.js → dist-C0G3AaXG.js} +1 -1
- package/dist/client/assets/dist-ChRoo3IB.js +9 -0
- package/dist/client/assets/dist-Dm4w5UId.js +1 -0
- package/dist/client/assets/{dist-B_yQaEv_.js → dist-DpYDHR9p.js} +1 -1
- package/dist/client/assets/{dist-CietwTVS.js → dist-DzNmC81X.js} +1 -1
- package/dist/client/assets/{dist-DDUn5zTz.js → dist-GvvCNBe4.js} +1 -1
- package/dist/client/assets/dist-JaU3aRlD.js +19 -0
- package/dist/client/assets/{dist-Bw3VIE_v.js → dist-TW8iFRyW.js} +1 -1
- package/dist/client/assets/{dist-Dir5dDKZ.js → dist-jVU5Be5P.js} +1 -1
- package/dist/client/assets/document-formatter-rDDjRfZ2.js +2 -0
- package/dist/client/assets/drawioEditor-JubEEha7.js +9 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-HeTxHpCU.js +1 -0
- package/dist/client/assets/editor-session-Bk6oIvSr.js +54 -0
- package/dist/client/assets/embedded-editor-base-BlCgz6mw.css +1 -0
- package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CbrDdd5P.js} +2 -2
- package/dist/client/assets/{es-CAsWR6hG.js → es-Bfdp096f.js} +13 -13
- package/dist/client/assets/estree-CuT_pB8K.js +44 -0
- package/dist/client/assets/excalidraw-element-link-YLIaTnVF.js +7 -0
- package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
- package/dist/client/assets/{excalidraw-editor-BlcN6umJ.css → excalidrawEditor-BbSbI80a.css} +1 -1
- package/dist/client/assets/excalidrawEditor-dBMbRX_S.js +9 -0
- package/dist/client/assets/export-page-CRRQ2NEl.js +57 -0
- package/dist/client/assets/exportDocument-BlQRd9_m.js +2 -0
- package/dist/client/assets/exportDocument-CNSbjZwu.css +1 -0
- package/dist/client/assets/{file-icon-svg-CQAjlWjK.js → file-icon-svg-Y_kpF957.js} +1 -1
- package/dist/client/assets/file-kind-BwMIcZbi.js +1 -0
- package/dist/client/assets/file-search-DDLyyLDU.js +1 -0
- package/dist/client/assets/flowDiagram-HODETNUW-D5Gy0wmg.js +1 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BHgOYiZz.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Dl__X3Sk.js} +1 -1
- package/dist/client/assets/html-Cdnr2qzU.js +25 -0
- package/dist/client/assets/image-ZVKINSPA-DgzW5zAy.js +1 -0
- package/dist/client/assets/index-D3RER1SZ.js +1023 -0
- package/dist/client/assets/index-DREVKl_K.css +1 -0
- package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-DBpoANC9.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-BMPC6hfp.js} +1 -1
- package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-B1sApUmM.js} +2 -2
- package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-C9yP4td1.js} +4 -4
- package/dist/client/assets/{line-BfTWJmgf.js → line-BFl3ujec.js} +1 -1
- package/dist/client/assets/markdown-CByV-4CU.js +70 -0
- package/dist/client/assets/{mermaid.core-CLZBlpIW.js → mermaid.core-BrY09czX.js} +5 -5
- package/dist/client/assets/mermaid.core-DfcNfOTv.js +1 -0
- package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-BUQHcYbK.js} +8 -8
- package/dist/client/assets/pegDiagram-XKGWAZYB-Bi2Iml7Z.js +1 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-_gYXnMoi.js} +1 -1
- package/dist/client/assets/preview-render-compiler-CfxJYldJ.js +41 -0
- package/dist/client/assets/preview-render-compiler-Cu8_i9iS.js +1 -0
- package/dist/client/assets/{preview-render-worker-BmN79bVc.js → preview-render-worker-c4Yi93qW.js} +41 -35
- package/dist/client/assets/prod-BiJL30sl.js +1 -0
- package/dist/client/assets/prod-qAk7rHa4.js +177 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-DwexhEhd.js} +1 -1
- package/dist/client/assets/quick-switcher-controller-BoIK_wuG.js +1 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BVA5UbMu.js +1 -0
- package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-C4cKwiIw.js} +2 -2
- package/dist/client/assets/runtime-config-DcmnGcXU.js +1 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-B5HHkRT2.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BX6jqJFD.js} +6 -6
- package/dist/client/assets/standalone-6z5x8CWe.js +29 -0
- package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-CmqxyRGx.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-zoLLQVyh.js +1 -0
- package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-Bmgb9Zld.js} +1 -1
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DS-KQN37.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-BA-lVH6P.js} +1 -1
- package/dist/client/assets/vault-api-client-iZLhMJKe.js +6 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-DNdUC_Xj.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-C2oY-YbF.js} +1 -1
- package/dist/client/assets/wiki-link-resolver-DFIwErjc.js +1 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-CoIR8CBX.js} +1 -1
- package/dist/client/assets/yaml-9ltHPDNO.js +154 -0
- package/dist/client/assets/{yjs-provider-reset-guard-DE0vINDP.js → yjs-provider-reset-guard-9ul1qF6k.js} +1 -1
- package/dist/client/drawio-editor.html +11 -3
- package/dist/client/excalidraw-editor.html +45 -2
- package/dist/client/export-document.html +3 -3
- package/dist/client/index.html +106 -52
- package/integrations/pi/index.ts +94 -0
- package/package.json +41 -29
- package/src/client/app/drawio-editor.html +2 -2
- package/src/client/app/excalidraw-editor.html +2 -2
- package/src/client/app/export-document.html +1 -1
- package/src/client/app/index.html +88 -50
- package/src/client/app/main-entry.js +15 -1
- package/src/client/application/app-shell/chat-feature.js +7 -22
- package/src/client/application/app-shell/export-feature.js +17 -1
- package/src/client/application/app-shell/git-feature.js +51 -14
- package/src/client/application/app-shell/presence-feature.js +8 -25
- package/src/client/application/app-shell/ui-feature-identity.js +13 -0
- package/src/client/application/app-shell/ui-feature-shell.js +199 -99
- package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
- package/src/client/application/app-shell/ui-feature-tab-activity.js +19 -6
- package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
- package/src/client/application/app-shell-elements.js +8 -0
- package/src/client/application/preview-render-compiler.js +1 -87
- package/src/client/application/preview-render-scheduler.js +8 -24
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/webmcp-diagram-renderer.js +47 -0
- package/src/client/application/workspace-coordinator.js +23 -4
- package/src/client/application/workspace-preview-controller.js +120 -2
- package/src/client/application/workspace-route-controller.js +11 -1
- package/src/client/assets/vendor/jetbrains-mono/JetBrainsMono-Regular.woff2 +0 -0
- package/src/client/assets/vendor/jetbrains-mono/OFL.txt +93 -0
- package/src/client/bootstrap/collabmd-app-shell.js +99 -6
- package/src/client/domain/document-formatter.js +193 -0
- package/src/client/domain/excalidraw-element-link.js +73 -0
- package/src/client/domain/excalidraw-scene.js +21 -0
- package/src/client/domain/file-search.js +73 -0
- package/src/client/domain/git-labels.js +5 -0
- package/src/client/domain/hash-routes.js +8 -0
- package/src/client/domain/room.js +1 -5
- package/src/client/domain/runtime-paths.js +5 -0
- package/src/client/domain/vault-paths.js +6 -4
- package/src/client/domain/wiki-link-completions.js +20 -20
- package/src/client/drawio-editor.js +8 -3
- package/src/client/excalidraw-editor.js +287 -16
- package/src/client/export/export-host.js +59 -36
- package/src/client/export/export-page.js +14 -4
- package/src/client/export/export-pipeline.js +270 -42
- package/src/client/infrastructure/agent-connection-api-client.js +23 -0
- package/src/client/infrastructure/auth-client.js +3 -13
- package/src/client/infrastructure/editor-session.js +15 -0
- package/src/client/infrastructure/editor-view-adapter.js +73 -14
- package/src/client/infrastructure/excalidraw-room-client.js +80 -1
- package/src/client/infrastructure/git-api-client.js +39 -33
- package/src/client/infrastructure/lobby-presence.js +2 -5
- package/src/client/infrastructure/runtime-config.js +11 -1
- package/src/client/infrastructure/tab-activity-lock.js +2 -5
- package/src/client/infrastructure/vault-api-client.js +33 -26
- package/src/client/infrastructure/webmcp-tool-registry.js +283 -0
- package/src/client/infrastructure/workspace-sync-client.js +6 -4
- package/src/client/presentation/agent-connection-controller.js +255 -0
- package/src/client/presentation/backlinks-panel.js +3 -0
- package/src/client/presentation/bases-preview-controller.js +59 -26
- package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
- package/src/client/presentation/create-menu-presenter.js +19 -16
- package/src/client/presentation/excalidraw-embed-controller.js +164 -4
- package/src/client/presentation/file-action-controller.js +15 -2
- package/src/client/presentation/file-explorer-controller.js +3 -0
- package/src/client/presentation/file-explorer-view.js +71 -12
- package/src/client/presentation/file-history-view-controller.js +19 -12
- package/src/client/presentation/file-tree-state.js +1 -11
- package/src/client/presentation/git-diff-view-controller.js +70 -53
- package/src/client/presentation/git-panel-controller.js +86 -32
- package/src/client/presentation/image-lightbox-controller.js +20 -16
- package/src/client/presentation/layout-controller.js +3 -1
- package/src/client/presentation/quick-switcher-controller.js +74 -232
- package/src/client/presentation/quick-switcher-text-search.js +10 -14
- package/src/client/styles/components/navigation.css +1 -2
- package/src/client/styles/components/scrollbars.css +10 -0
- package/src/client/styles/export-document.css +44 -29
- package/src/client/styles/features/agent-connection.css +202 -0
- package/src/client/styles/features/collaboration-chat.css +8 -1
- package/src/client/styles/features/collaboration-dialogs.css +16 -1
- package/src/client/styles/features/collaboration-presence.css +30 -5
- package/src/client/styles/features/diff-toolbar.css +1 -1
- package/src/client/styles/features/media-lightbox.css +12 -3
- package/src/client/styles/features/preview-markdown.css +54 -0
- package/src/client/styles/features/quick-switcher.css +20 -11
- package/src/client/styles/foundation/themes.css +2 -0
- package/src/client/styles/foundation/tokens.css +8 -0
- package/src/client/styles/layout/editor-page.css +25 -11
- package/src/client/styles/layout/responsive.css +2 -20
- package/src/client/styles/layout/shell.css +77 -24
- package/src/client/styles/layout/sidebar.css +7 -4
- package/src/client/styles/layout/view-modes.css +2 -0
- package/src/client/styles/overrides/codemirror.css +31 -19
- package/src/client/styles/primitives/controls.css +21 -54
- package/src/client/styles/style.css +1 -0
- package/src/client/styles/surfaces/excalidraw-editor.css +42 -0
- package/src/domain/agent-tool-definitions.js +796 -0
- package/src/domain/collabmd-content-capabilities.js +149 -0
- package/src/domain/collaboration-protocol.js +2 -0
- package/src/domain/comment-threads.js +3 -5
- package/src/domain/diagram-source.js +50 -0
- package/src/domain/editable-content-revision.js +10 -0
- package/src/domain/editable-text.js +3 -0
- package/src/domain/exact-text-edits.js +69 -0
- package/src/domain/excalidraw-agent-scene.js +522 -0
- package/src/domain/excalidraw-agent-verification.js +460 -0
- package/src/domain/excalidraw-room-codec.js +1 -5
- package/src/domain/file-kind.js +12 -1
- package/src/domain/video-embed.js +76 -0
- package/src/server/application/agent-connection-service.js +178 -0
- package/src/server/application/agent-content-service.js +773 -0
- package/src/server/application/workspace-reconciliation.js +5 -7
- package/src/server/config/env.js +51 -1
- package/src/server/create-app-server.js +36 -0
- package/src/server/domain/bases/base-query-service.js +1 -5
- package/src/server/domain/collaboration/collaboration-room.js +121 -25
- package/src/server/domain/collaboration/protocol.js +4 -0
- package/src/server/domain/hosted-workspace.js +21 -0
- package/src/server/domain/markdown-reference-extractor.js +15 -1
- package/src/server/domain/ripgrep-search-service.js +110 -37
- package/src/server/infrastructure/git/git-service.js +19 -1
- package/src/server/infrastructure/git/history-service.js +1 -1
- package/src/server/infrastructure/git/local-exclude.js +25 -0
- package/src/server/infrastructure/git/parsers.js +19 -17
- package/src/server/infrastructure/git/path-utils.js +0 -16
- package/src/server/infrastructure/git/status-service.js +1 -1
- package/src/server/infrastructure/git/untracked-files.js +12 -21
- package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
- package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
- package/src/server/infrastructure/http/create-request-handler.js +28 -0
- package/src/server/infrastructure/http/create-static-handler.js +6 -0
- package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +199 -0
- package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
- package/src/server/infrastructure/persistence/path-utils.js +10 -4
- package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
- package/src/server/infrastructure/persistence/vault-file-store.js +11 -2
- package/src/server/shared/agent-tool-image.js +22 -0
- package/src/server/shared/agent-tool-rate-limiter.js +20 -0
- package/src/server/startup/git-remote-bootstrap.js +5 -33
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
- package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
- package/dist/client/assets/channel-CaoKA_We.js +0 -1
- package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
- package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
- package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
- package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
- package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
- package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
- package/dist/client/assets/comment-ui-shared-DWkk9Vh3.js +0 -7
- package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
- package/dist/client/assets/dist-73RPdcyU.js +0 -1
- package/dist/client/assets/dist-CH-sQu3r.js +0 -1
- package/dist/client/assets/drawio-editor-BjrxTe3l.js +0 -9
- package/dist/client/assets/drawioEditor-DUVZjSSr.js +0 -2
- package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
- package/dist/client/assets/editor-session-DfZuRgB_.js +0 -54
- package/dist/client/assets/embedded-editor-base-DvMynhKu.css +0 -1
- package/dist/client/assets/excalidraw-editor-D7pnUCLH.js +0 -9
- package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
- package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
- package/dist/client/assets/excalidrawEditor-B0jOK3lv.js +0 -2
- package/dist/client/assets/export-page-Bs3xE1fg.js +0 -57
- package/dist/client/assets/exportDocument-Dg9MjkIk.js +0 -2
- package/dist/client/assets/exportDocument-PnYU3v1s.css +0 -1
- package/dist/client/assets/file-kind-BbqgGzpc.js +0 -1
- package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
- package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
- package/dist/client/assets/index-BIpgxyGZ.css +0 -1
- package/dist/client/assets/index-Z5sI0Bj-.js +0 -2
- package/dist/client/assets/main-Dwnj9Gaq.js +0 -903
- package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
- package/dist/client/assets/preview-render-compiler-BApvlLLo.js +0 -35
- package/dist/client/assets/preview-render-compiler-BQ_3h9vD.js +0 -1
- package/dist/client/assets/preview-render-profile-CE-5rVTC.js +0 -1
- package/dist/client/assets/prod-BiYPMR1i.js +0 -177
- package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
- package/dist/client/assets/quick-switcher-controller-ButWPmCI.js +0 -12
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
- package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
- package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
- package/dist/client/assets/vault-api-client-_LpV1aIn.js +0 -6
- package/dist/client/assets/vault-utils-wdQ0RNR9.js +0 -1
- package/src/client/app/drawio-editor-entry.js +0 -1
- package/src/client/app/excalidraw-editor-entry.js +0 -1
- package/src/client/excalidraw-mermaid-stub.js +0 -7
- package/src/client/main.js +0 -16
- /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
- /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { getElementBounds } from '@excalidraw/element';
|
|
12
12
|
import '@excalidraw/excalidraw/index.css';
|
|
13
13
|
|
|
14
|
+
import { createEditableContentRevision } from '../domain/editable-content-revision.js';
|
|
14
15
|
import {
|
|
15
16
|
buildRenderableCollaboratorsMap,
|
|
16
17
|
findCollaboratorByPeerId,
|
|
@@ -45,6 +46,11 @@ import {
|
|
|
45
46
|
summarizeExcalidrawScene,
|
|
46
47
|
} from './domain/excalidraw-diagnostics.js';
|
|
47
48
|
import { isPlainQuickSwitcherShortcut } from './domain/keyboard-shortcuts.js';
|
|
49
|
+
import {
|
|
50
|
+
createExcalidrawElementLink,
|
|
51
|
+
parseExcalidrawElementLink,
|
|
52
|
+
} from './domain/excalidraw-element-link.js';
|
|
53
|
+
import { resolveAppPath, resolveAppUrl } from './domain/runtime-paths.js';
|
|
48
54
|
import { ensureClientAuthenticated } from './infrastructure/auth-client.js';
|
|
49
55
|
import {
|
|
50
56
|
EXCALIDRAW_ROOM_CONNECTION_STATE,
|
|
@@ -58,6 +64,8 @@ const diagnostics = createExcalidrawDiagnosticRing({
|
|
|
58
64
|
enabled: params.get('excalidrawDebug') === '1',
|
|
59
65
|
});
|
|
60
66
|
const parentOrigin = window.location.origin;
|
|
67
|
+
const appPath = resolveAppPath('/');
|
|
68
|
+
const appUrl = resolveAppUrl('/');
|
|
61
69
|
const syncTimeoutMs = Number.parseInt(params.get('syncTimeoutMs') || '', 10);
|
|
62
70
|
|
|
63
71
|
let currentDocument = {
|
|
@@ -71,6 +79,12 @@ let localAwarenessUser = resolveLocalAwarenessUser({
|
|
|
71
79
|
storedUserName: localStorage.getItem('collabmd-user-name'),
|
|
72
80
|
});
|
|
73
81
|
let appliedSceneJson = '';
|
|
82
|
+
let appliedSceneRevisionPromise = createEditableContentRevision(appliedSceneJson);
|
|
83
|
+
|
|
84
|
+
function setAppliedSceneJson(value) {
|
|
85
|
+
appliedSceneJson = value;
|
|
86
|
+
appliedSceneRevisionPromise = createEditableContentRevision(value);
|
|
87
|
+
}
|
|
74
88
|
|
|
75
89
|
let collabReady = false;
|
|
76
90
|
let pendingRemoteSceneJson = '';
|
|
@@ -327,17 +341,34 @@ function getDiagramCommentMarkerPosition(thread, api = getMountedExcalidrawAPI()
|
|
|
327
341
|
);
|
|
328
342
|
}
|
|
329
343
|
|
|
330
|
-
function
|
|
344
|
+
function getDiagramElementTargets(elementId, elementType = 'element', api = getMountedExcalidrawAPI()) {
|
|
345
|
+
const normalizedElementId = String(elementId ?? '').trim();
|
|
346
|
+
const elements = api?.getSceneElementsIncludingDeleted?.()
|
|
347
|
+
?.filter((element) => !element.isDeleted) || [];
|
|
348
|
+
if (!normalizedElementId) {
|
|
349
|
+
return [];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (elementType === 'group') {
|
|
353
|
+
const groupElements = elements.filter((element) => element.groupIds?.includes(normalizedElementId));
|
|
354
|
+
if (groupElements.length > 0) {
|
|
355
|
+
return groupElements;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return elements.filter((element) => element.id === normalizedElementId);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
function focusDiagramElement(elementId, elementType = 'element') {
|
|
331
363
|
const api = getMountedExcalidrawAPI();
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
if (!api || !element) {
|
|
364
|
+
const elements = getDiagramElementTargets(elementId, elementType, api);
|
|
365
|
+
if (!api || elements.length === 0) {
|
|
335
366
|
return;
|
|
336
367
|
}
|
|
337
368
|
|
|
338
369
|
api.updateScene({
|
|
339
370
|
appState: {
|
|
340
|
-
selectedElementIds:
|
|
371
|
+
selectedElementIds: Object.fromEntries(elements.map((element) => [element.id, true])),
|
|
341
372
|
},
|
|
342
373
|
captureUpdate: CaptureUpdateAction.NEVER,
|
|
343
374
|
});
|
|
@@ -352,11 +383,16 @@ function focusDiagramCommentThread(thread) {
|
|
|
352
383
|
animation: false,
|
|
353
384
|
fit: 'contain',
|
|
354
385
|
offsets: { ui: true },
|
|
355
|
-
target:
|
|
386
|
+
target: elements,
|
|
356
387
|
});
|
|
357
388
|
} finally {
|
|
358
389
|
releaseViewportBroadcastSuppressionAfterPaint();
|
|
359
390
|
}
|
|
391
|
+
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function focusDiagramCommentThread(thread) {
|
|
395
|
+
focusDiagramElement(thread?.elementId);
|
|
360
396
|
}
|
|
361
397
|
|
|
362
398
|
function applyDocumentMode(mode = currentDocument.mode) {
|
|
@@ -413,6 +449,23 @@ function createRoomClient(filePath) {
|
|
|
413
449
|
};
|
|
414
450
|
}
|
|
415
451
|
|
|
452
|
+
function handleExcalidrawLinkOpen(element, event) {
|
|
453
|
+
if (window.parent === window) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const target = parseExcalidrawElementLink(element?.link, {
|
|
458
|
+
appPath,
|
|
459
|
+
origin: parentOrigin,
|
|
460
|
+
});
|
|
461
|
+
if (!target) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
event?.preventDefault?.();
|
|
466
|
+
postToParent('open-element-link', { href: element.link });
|
|
467
|
+
}
|
|
468
|
+
|
|
416
469
|
function buildExcalidrawProps({ initialData, renderTopRightUI, viewModeEnabled } = {}) {
|
|
417
470
|
const props = {
|
|
418
471
|
onMount: handleEditorMount,
|
|
@@ -431,11 +484,17 @@ function buildExcalidrawProps({ initialData, renderTopRightUI, viewModeEnabled }
|
|
|
431
484
|
collabReady = false;
|
|
432
485
|
},
|
|
433
486
|
aiEnabled: false,
|
|
487
|
+
generateLinkForSelection: (elementId, elementType) => createExcalidrawElementLink(
|
|
488
|
+
currentDocument.filePath,
|
|
489
|
+
elementId,
|
|
490
|
+
{ appUrl, elementType },
|
|
491
|
+
),
|
|
434
492
|
isCollaborating: true,
|
|
435
493
|
onChange: (elements, appState, files) => {
|
|
436
494
|
scheduleSyncToRoom(elements, appState, files);
|
|
437
495
|
roomClient?.syncLocalSelectionAwareness(appState);
|
|
438
496
|
},
|
|
497
|
+
onLinkOpen: handleExcalidrawLinkOpen,
|
|
439
498
|
onPointerUpdate: (payload) => {
|
|
440
499
|
roomClient?.scheduleLocalPointerAwareness(payload);
|
|
441
500
|
},
|
|
@@ -469,6 +528,32 @@ function buildExcalidrawProps({ initialData, renderTopRightUI, viewModeEnabled }
|
|
|
469
528
|
}
|
|
470
529
|
|
|
471
530
|
const diagramCommentsContext = React.createContext(null);
|
|
531
|
+
const presentationContext = React.createContext(null);
|
|
532
|
+
|
|
533
|
+
function PresentationToolbar() {
|
|
534
|
+
const context = React.useContext(presentationContext);
|
|
535
|
+
if (!context) {
|
|
536
|
+
return null;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const label = context.active ? 'Exit presentation' : 'Start presentation';
|
|
540
|
+
const icon = context.active ? '×' : '▶';
|
|
541
|
+
let title = context.active ? 'Exit presentation' : 'Present frames';
|
|
542
|
+
if (context.frameCount === 0) {
|
|
543
|
+
title = 'Add a frame to create slides';
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return React.createElement('button', {
|
|
547
|
+
'aria-label': label,
|
|
548
|
+
'aria-pressed': context.active,
|
|
549
|
+
className: `diagram-comment-button excalidraw-presentation-toggle sidebar-trigger${context.active ? ' is-active' : ''}`,
|
|
550
|
+
'data-testid': 'excalidraw-presentation-toggle',
|
|
551
|
+
disabled: context.frameCount === 0,
|
|
552
|
+
onClick: context.toggle,
|
|
553
|
+
title,
|
|
554
|
+
type: 'button',
|
|
555
|
+
}, React.createElement('span', { 'aria-hidden': 'true' }, icon));
|
|
556
|
+
}
|
|
472
557
|
|
|
473
558
|
function DiagramCommentsToolbar() {
|
|
474
559
|
const context = React.useContext(diagramCommentsContext);
|
|
@@ -518,7 +603,12 @@ function DiagramCommentsToolbar() {
|
|
|
518
603
|
|
|
519
604
|
const DiagramCommentsExcalidraw = React.memo(function DiagramCommentsExcalidraw({ initialData = null, renderKey = 0, viewModeEnabled }) {
|
|
520
605
|
const renderTopRightUI = React.useCallback(
|
|
521
|
-
() => React.createElement(
|
|
606
|
+
() => React.createElement('div', {
|
|
607
|
+
className: 'excalidraw-editor-toolbar',
|
|
608
|
+
}, [
|
|
609
|
+
React.createElement(PresentationToolbar, { key: 'presentation' }),
|
|
610
|
+
React.createElement(DiagramCommentsToolbar, { key: 'comments' }),
|
|
611
|
+
]),
|
|
522
612
|
[],
|
|
523
613
|
);
|
|
524
614
|
|
|
@@ -566,7 +656,13 @@ function DiagramCommentsEditor({ apiId = '', canWrite = false, focusRequest = nu
|
|
|
566
656
|
const [drawerOpen, setDrawerOpen] = React.useState(false);
|
|
567
657
|
const [draft, setDraft] = React.useState('');
|
|
568
658
|
const [replyDraft, setReplyDraft] = React.useState('');
|
|
659
|
+
const [presentationFrameId, setPresentationFrameId] = React.useState(null);
|
|
569
660
|
const [, setViewportRevision] = React.useState(0);
|
|
661
|
+
const presentationFrames = (
|
|
662
|
+
getMountedExcalidrawAPI()?.getSceneElementsIncludingDeleted?.() || []
|
|
663
|
+
).filter((element) => element?.type === 'frame' && !element.isDeleted);
|
|
664
|
+
const presentationIndex = presentationFrames.findIndex((frame) => frame.id === presentationFrameId);
|
|
665
|
+
const presentationMode = presentationFrameId !== null;
|
|
570
666
|
|
|
571
667
|
React.useEffect(() => {
|
|
572
668
|
const api = getMountedExcalidrawAPI();
|
|
@@ -588,6 +684,76 @@ function DiagramCommentsEditor({ apiId = '', canWrite = false, focusRequest = nu
|
|
|
588
684
|
|
|
589
685
|
useCloseDiagramCommentsOnCanvas(drawerOpen, setDrawerOpen);
|
|
590
686
|
|
|
687
|
+
const goToPresentationFrame = React.useCallback((index) => {
|
|
688
|
+
const targetIndex = Math.min(Math.max(index, 0), presentationFrames.length - 1);
|
|
689
|
+
const frame = presentationFrames[targetIndex];
|
|
690
|
+
const api = getMountedExcalidrawAPI();
|
|
691
|
+
if (!api || !frame) {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
setPresentationFrameId(frame.id);
|
|
696
|
+
api.setViewport({
|
|
697
|
+
animation: true,
|
|
698
|
+
fit: 'contain',
|
|
699
|
+
offsets: { ui: true },
|
|
700
|
+
target: frame,
|
|
701
|
+
});
|
|
702
|
+
}, [presentationFrames]);
|
|
703
|
+
|
|
704
|
+
const togglePresentation = React.useCallback(() => {
|
|
705
|
+
if (presentationMode) {
|
|
706
|
+
setPresentationFrameId(null);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
setDrawerOpen(false);
|
|
711
|
+
setComposerOpen(false);
|
|
712
|
+
setActiveThreadId(null);
|
|
713
|
+
goToPresentationFrame(0);
|
|
714
|
+
}, [goToPresentationFrame, presentationMode]);
|
|
715
|
+
|
|
716
|
+
React.useEffect(() => {
|
|
717
|
+
if (!presentationFrameId || presentationIndex >= 0) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
if (presentationFrames.length > 0) {
|
|
722
|
+
goToPresentationFrame(0);
|
|
723
|
+
} else {
|
|
724
|
+
setPresentationFrameId(null);
|
|
725
|
+
}
|
|
726
|
+
}, [goToPresentationFrame, presentationFrameId, presentationFrames.length, presentationIndex]);
|
|
727
|
+
|
|
728
|
+
React.useEffect(() => {
|
|
729
|
+
if (!presentationMode) {
|
|
730
|
+
return undefined;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const handlePresentationKeyDown = (event) => {
|
|
734
|
+
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.altKey) {
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
if (event.key === 'Escape') {
|
|
739
|
+
event.preventDefault();
|
|
740
|
+
event.stopPropagation();
|
|
741
|
+
setPresentationFrameId(null);
|
|
742
|
+
} else if (event.key === 'ArrowRight') {
|
|
743
|
+
event.preventDefault();
|
|
744
|
+
event.stopPropagation();
|
|
745
|
+
goToPresentationFrame(presentationIndex + 1);
|
|
746
|
+
} else if (event.key === 'ArrowLeft') {
|
|
747
|
+
event.preventDefault();
|
|
748
|
+
event.stopPropagation();
|
|
749
|
+
goToPresentationFrame(presentationIndex - 1);
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
|
|
753
|
+
document.addEventListener('keydown', handlePresentationKeyDown, true);
|
|
754
|
+
return () => document.removeEventListener('keydown', handlePresentationKeyDown, true);
|
|
755
|
+
}, [goToPresentationFrame, presentationIndex, presentationMode]);
|
|
756
|
+
|
|
591
757
|
React.useEffect(() => {
|
|
592
758
|
if (activeThreadId && !threads.some((thread) => thread.id === activeThreadId)) {
|
|
593
759
|
setActiveThreadId(null);
|
|
@@ -833,7 +999,8 @@ function DiagramCommentsEditor({ apiId = '', canWrite = false, focusRequest = nu
|
|
|
833
999
|
]);
|
|
834
1000
|
};
|
|
835
1001
|
|
|
836
|
-
const
|
|
1002
|
+
const commentsVisible = visible && !presentationMode;
|
|
1003
|
+
const renderCommentsOverlay = commentsVisible && room
|
|
837
1004
|
? React.createElement('div', {
|
|
838
1005
|
'aria-label': 'Diagram comments overlay',
|
|
839
1006
|
className: 'diagram-comments-overlay',
|
|
@@ -865,7 +1032,44 @@ function DiagramCommentsEditor({ apiId = '', canWrite = false, focusRequest = nu
|
|
|
865
1032
|
])
|
|
866
1033
|
: null;
|
|
867
1034
|
|
|
868
|
-
|
|
1035
|
+
const renderPresentationNavigation = presentationMode
|
|
1036
|
+
? React.createElement('div', {
|
|
1037
|
+
'aria-label': 'Presentation navigation',
|
|
1038
|
+
className: 'excalidraw-presentation-navigation',
|
|
1039
|
+
key: 'presentation-navigation',
|
|
1040
|
+
role: 'toolbar',
|
|
1041
|
+
}, [
|
|
1042
|
+
React.createElement('button', {
|
|
1043
|
+
'aria-label': 'Previous slide',
|
|
1044
|
+
className: 'diagram-comment-button',
|
|
1045
|
+
disabled: presentationIndex <= 0,
|
|
1046
|
+
key: 'previous',
|
|
1047
|
+
onClick: () => goToPresentationFrame(presentationIndex - 1),
|
|
1048
|
+
type: 'button',
|
|
1049
|
+
}, '←'),
|
|
1050
|
+
React.createElement('span', {
|
|
1051
|
+
'aria-live': 'polite',
|
|
1052
|
+
className: 'excalidraw-presentation-status',
|
|
1053
|
+
key: 'status',
|
|
1054
|
+
}, `${presentationFrames[presentationIndex]?.name || `Slide ${presentationIndex + 1}`} · ${presentationIndex + 1} / ${presentationFrames.length}`),
|
|
1055
|
+
React.createElement('button', {
|
|
1056
|
+
'aria-label': 'Next slide',
|
|
1057
|
+
className: 'diagram-comment-button',
|
|
1058
|
+
disabled: presentationIndex >= presentationFrames.length - 1,
|
|
1059
|
+
key: 'next',
|
|
1060
|
+
onClick: () => goToPresentationFrame(presentationIndex + 1),
|
|
1061
|
+
type: 'button',
|
|
1062
|
+
}, '→'),
|
|
1063
|
+
])
|
|
1064
|
+
: null;
|
|
1065
|
+
|
|
1066
|
+
return React.createElement(presentationContext.Provider, {
|
|
1067
|
+
value: {
|
|
1068
|
+
active: presentationMode,
|
|
1069
|
+
frameCount: presentationFrames.length,
|
|
1070
|
+
toggle: togglePresentation,
|
|
1071
|
+
},
|
|
1072
|
+
}, React.createElement(diagramCommentsContext.Provider, {
|
|
869
1073
|
value: {
|
|
870
1074
|
canWrite,
|
|
871
1075
|
drawerOpen,
|
|
@@ -874,17 +1078,18 @@ function DiagramCommentsEditor({ apiId = '', canWrite = false, focusRequest = nu
|
|
|
874
1078
|
selectedElement,
|
|
875
1079
|
threads,
|
|
876
1080
|
toggleDrawer: () => setDrawerOpen((open) => !open),
|
|
877
|
-
visible,
|
|
1081
|
+
visible: commentsVisible,
|
|
878
1082
|
},
|
|
879
1083
|
}, [
|
|
880
1084
|
React.createElement(DiagramCommentsExcalidraw, {
|
|
881
1085
|
initialData,
|
|
882
1086
|
key: 'excalidraw',
|
|
883
1087
|
renderKey: editorRenderKey,
|
|
884
|
-
viewModeEnabled: getDocumentViewState().viewModeEnabled,
|
|
1088
|
+
viewModeEnabled: presentationMode || getDocumentViewState().viewModeEnabled,
|
|
885
1089
|
}),
|
|
886
1090
|
renderCommentsOverlay,
|
|
887
|
-
|
|
1091
|
+
renderPresentationNavigation,
|
|
1092
|
+
]));
|
|
888
1093
|
}
|
|
889
1094
|
|
|
890
1095
|
function renderExcalidrawApp({ initialData } = {}) {
|
|
@@ -1053,6 +1258,9 @@ if (isTestMode) {
|
|
|
1053
1258
|
.map((element) => element.id)
|
|
1054
1259
|
.sort() ?? []
|
|
1055
1260
|
),
|
|
1261
|
+
getSelectedElementIds: () => (
|
|
1262
|
+
Object.keys(getMountedExcalidrawAPI()?.getAppState?.()?.selectedElementIds || {}).sort()
|
|
1263
|
+
),
|
|
1056
1264
|
getElementStatus: (elementId) => (
|
|
1057
1265
|
getMountedExcalidrawAPI()?.getSceneElementsIncludingDeleted?.()
|
|
1058
1266
|
?.find((entry) => entry.id === elementId && !entry.isDeleted)?.status ?? null
|
|
@@ -1201,7 +1409,7 @@ function applySceneFromJson(rawJson, {
|
|
|
1201
1409
|
return;
|
|
1202
1410
|
}
|
|
1203
1411
|
|
|
1204
|
-
|
|
1412
|
+
setAppliedSceneJson(normalizedJson);
|
|
1205
1413
|
recordSceneDiagnostic('remote-scene-received', {}, normalizedJson);
|
|
1206
1414
|
|
|
1207
1415
|
if (!getMountedExcalidrawAPI() || !collabReady) {
|
|
@@ -1277,7 +1485,7 @@ function requestEditorRemount(scene) {
|
|
|
1277
1485
|
const normalizedScene = normalizeScene(scene);
|
|
1278
1486
|
const normalizedJson = JSON.stringify(normalizedScene);
|
|
1279
1487
|
pendingRemoteSceneJson = normalizedJson;
|
|
1280
|
-
|
|
1488
|
+
setAppliedSceneJson(normalizedJson);
|
|
1281
1489
|
pendingCollaborators = activeCollaborators;
|
|
1282
1490
|
initialViewportFitPending = true;
|
|
1283
1491
|
clearPreviewViewportFitTimers();
|
|
@@ -1353,7 +1561,7 @@ function applyLocalScene(scene, {
|
|
|
1353
1561
|
const normalizedScene = normalizeScene(scene);
|
|
1354
1562
|
const normalizedJson = JSON.stringify(normalizedScene);
|
|
1355
1563
|
|
|
1356
|
-
|
|
1564
|
+
setAppliedSceneJson(normalizedJson);
|
|
1357
1565
|
|
|
1358
1566
|
if (!getMountedExcalidrawAPI() || !collabReady) {
|
|
1359
1567
|
pendingRemoteSceneJson = normalizedJson;
|
|
@@ -1699,6 +1907,36 @@ async function waitForPendingRoomWrites({
|
|
|
1699
1907
|
}
|
|
1700
1908
|
}
|
|
1701
1909
|
|
|
1910
|
+
function waitForAnimationFrame() {
|
|
1911
|
+
return new Promise((resolve) => requestAnimationFrame(resolve));
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
async function waitForAppliedSceneRevision(revision, {
|
|
1915
|
+
afterRevision = '',
|
|
1916
|
+
maxWaitMs = 4500,
|
|
1917
|
+
} = {}) {
|
|
1918
|
+
const startedAt = performance.now();
|
|
1919
|
+
while ((performance.now() - startedAt) < maxWaitMs) {
|
|
1920
|
+
const appliedRevision = await appliedSceneRevisionPromise;
|
|
1921
|
+
if (
|
|
1922
|
+
!pendingRemoteSceneJson
|
|
1923
|
+
&& (appliedRevision === revision || (afterRevision && appliedRevision !== afterRevision))
|
|
1924
|
+
) {
|
|
1925
|
+
await waitForAnimationFrame();
|
|
1926
|
+
await waitForAnimationFrame();
|
|
1927
|
+
const paintedRevision = await appliedSceneRevisionPromise;
|
|
1928
|
+
if (
|
|
1929
|
+
!pendingRemoteSceneJson
|
|
1930
|
+
&& (paintedRevision === revision || (afterRevision && paintedRevision !== afterRevision))
|
|
1931
|
+
) {
|
|
1932
|
+
return paintedRevision;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
await new Promise((resolve) => window.setTimeout(resolve, 16));
|
|
1936
|
+
}
|
|
1937
|
+
return '';
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1702
1940
|
async function prepareRealtimeRoomDisconnect() {
|
|
1703
1941
|
if (!roomClient) {
|
|
1704
1942
|
return true;
|
|
@@ -1796,6 +2034,11 @@ window.addEventListener('message', (event) => {
|
|
|
1796
2034
|
return;
|
|
1797
2035
|
}
|
|
1798
2036
|
|
|
2037
|
+
if (message.type === 'focus-element') {
|
|
2038
|
+
focusDiagramElement(message.elementId, message.elementType);
|
|
2039
|
+
return;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
1799
2042
|
if (message.type === 'follow-user') {
|
|
1800
2043
|
applyHostFollowRequest(message.peerId || null);
|
|
1801
2044
|
return;
|
|
@@ -1806,6 +2049,34 @@ window.addEventListener('message', (event) => {
|
|
|
1806
2049
|
return;
|
|
1807
2050
|
}
|
|
1808
2051
|
|
|
2052
|
+
if (message.type === 'flush-agent-writes') {
|
|
2053
|
+
void (async () => {
|
|
2054
|
+
roomClient?.flushSceneSync();
|
|
2055
|
+
await waitForPendingRoomWrites({ maxWaitMs: 1000 });
|
|
2056
|
+
const serverFlush = await roomClient?.waitForServerFlush?.({ timeoutMs: 1000 });
|
|
2057
|
+
postToParent('agent-writes-flushed', {
|
|
2058
|
+
requestId: message.requestId || '',
|
|
2059
|
+
revision: await appliedSceneRevisionPromise,
|
|
2060
|
+
status: serverFlush?.status || 'unavailable',
|
|
2061
|
+
});
|
|
2062
|
+
})();
|
|
2063
|
+
return;
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
if (message.type === 'wait-for-agent-revision') {
|
|
2067
|
+
void (async () => {
|
|
2068
|
+
const revision = String(message.revision || '');
|
|
2069
|
+
const paintedRevision = revision && await waitForAppliedSceneRevision(revision, {
|
|
2070
|
+
afterRevision: String(message.afterRevision || ''),
|
|
2071
|
+
});
|
|
2072
|
+
postToParent(paintedRevision ? 'agent-revision-painted' : 'agent-revision-not-painted', {
|
|
2073
|
+
requestId: message.requestId || '',
|
|
2074
|
+
revision: paintedRevision || revision,
|
|
2075
|
+
});
|
|
2076
|
+
})();
|
|
2077
|
+
return;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
1809
2080
|
if (message.type === 'prepare-disconnect') {
|
|
1810
2081
|
void (async () => {
|
|
1811
2082
|
const requestId = message.requestId || '';
|
|
@@ -1907,7 +2178,7 @@ function initializeEditor(api) {
|
|
|
1907
2178
|
const sceneJson = pendingRemoteSceneJson || roomClient?.getLastSceneJson?.() || '';
|
|
1908
2179
|
const initialScene = parseSceneJson(sceneJson);
|
|
1909
2180
|
pendingRemoteSceneJson = '';
|
|
1910
|
-
|
|
2181
|
+
setAppliedSceneJson(JSON.stringify(initialScene));
|
|
1911
2182
|
updateApiScene(initialScene);
|
|
1912
2183
|
|
|
1913
2184
|
if (pendingCollaborators) {
|
|
@@ -3,43 +3,43 @@ import { resolveAppUrl } from '../infrastructure/runtime-config.js';
|
|
|
3
3
|
const EXPORT_PAGE_SOURCE = 'collabmd-export-page';
|
|
4
4
|
const EXPORT_HOST_SOURCE = 'collabmd-export-host';
|
|
5
5
|
const EXPORT_JOB_CLOSE_POLL_MS = 500;
|
|
6
|
-
const EXPORT_JOB_TIMEOUT_MS =
|
|
6
|
+
const EXPORT_JOB_TIMEOUT_MS = 300_000;
|
|
7
7
|
const pendingJobs = new Map();
|
|
8
8
|
let exportBridgeErrorHandler = null;
|
|
9
9
|
|
|
10
10
|
function createJobId() {
|
|
11
|
-
|
|
11
|
+
const id = globalThis.crypto?.randomUUID?.()
|
|
12
|
+
?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
13
|
+
return `export-${id}`;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
function normalizeFormat(format) {
|
|
15
17
|
return ['html', 'pdf'].includes(format) ? format : 'docx';
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
function buildExportUrl({ filePath, format, jobId }) {
|
|
19
|
-
const url = new URL(resolveAppUrl('/export-document.html'), window.location.origin);
|
|
20
|
-
url.searchParams.set('action', normalizeFormat(format));
|
|
21
|
-
url.searchParams.set('job', jobId);
|
|
22
|
-
if (filePath) {
|
|
23
|
-
url.searchParams.set('file', filePath);
|
|
24
|
-
}
|
|
25
|
-
return url.toString();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
20
|
function createBootstrapPayload({
|
|
21
|
+
currentFilePath = '',
|
|
22
|
+
currentMarkdownText = '',
|
|
23
|
+
directoryPath = '',
|
|
29
24
|
fileList = [],
|
|
30
25
|
filePath,
|
|
31
26
|
format,
|
|
32
27
|
jobId,
|
|
33
28
|
markdownText = '',
|
|
29
|
+
theme = 'light',
|
|
34
30
|
title = '',
|
|
35
31
|
}) {
|
|
36
32
|
return {
|
|
37
33
|
action: normalizeFormat(format),
|
|
34
|
+
currentFilePath: String(currentFilePath ?? ''),
|
|
35
|
+
currentMarkdownText: String(currentMarkdownText ?? ''),
|
|
36
|
+
directoryPath: String(directoryPath ?? ''),
|
|
38
37
|
fileList: Array.isArray(fileList) ? fileList.slice() : [],
|
|
39
38
|
filePath: String(filePath ?? ''),
|
|
40
39
|
jobId,
|
|
41
40
|
markdownText: String(markdownText ?? ''),
|
|
42
41
|
source: EXPORT_HOST_SOURCE,
|
|
42
|
+
theme: theme === 'dark' ? 'dark' : 'light',
|
|
43
43
|
title: String(title ?? ''),
|
|
44
44
|
type: 'bootstrap',
|
|
45
45
|
};
|
|
@@ -136,26 +136,9 @@ export function initializeExportBridge({
|
|
|
136
136
|
window.__collabmdExportBridgeInitialized = true;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
fileList = [],
|
|
141
|
-
filePath,
|
|
142
|
-
format,
|
|
143
|
-
markdownText = '',
|
|
144
|
-
title = '',
|
|
145
|
-
} = {}) {
|
|
146
|
-
const normalizedFilePath = String(filePath ?? '').trim();
|
|
147
|
-
if (!normalizedFilePath) {
|
|
148
|
-
throw new Error('No markdown note is open');
|
|
149
|
-
}
|
|
150
|
-
|
|
139
|
+
async function startExport(payload) {
|
|
151
140
|
const jobId = createJobId();
|
|
152
|
-
const
|
|
153
|
-
filePath: normalizedFilePath,
|
|
154
|
-
format,
|
|
155
|
-
jobId,
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
const exportWindow = window.open(url, '_blank');
|
|
141
|
+
const exportWindow = globalThis.open('', jobId);
|
|
159
142
|
if (!exportWindow) {
|
|
160
143
|
throw new Error('Export popup was blocked');
|
|
161
144
|
}
|
|
@@ -172,12 +155,9 @@ export async function exportDocument({
|
|
|
172
155
|
});
|
|
173
156
|
}, EXPORT_JOB_CLOSE_POLL_MS),
|
|
174
157
|
payload: createBootstrapPayload({
|
|
175
|
-
|
|
176
|
-
filePath: normalizedFilePath,
|
|
177
|
-
format,
|
|
158
|
+
...payload,
|
|
178
159
|
jobId,
|
|
179
|
-
|
|
180
|
-
title,
|
|
160
|
+
theme: document.documentElement.dataset.theme,
|
|
181
161
|
}),
|
|
182
162
|
timeoutId: window.setTimeout(() => {
|
|
183
163
|
finishPendingJob(jobId, {
|
|
@@ -188,6 +168,49 @@ export async function exportDocument({
|
|
|
188
168
|
window: exportWindow,
|
|
189
169
|
});
|
|
190
170
|
|
|
171
|
+
exportWindow.location.replace(resolveAppUrl('/export-document.html'));
|
|
191
172
|
exportWindow.focus?.();
|
|
192
173
|
return jobId;
|
|
193
174
|
}
|
|
175
|
+
|
|
176
|
+
export async function exportDirectory({
|
|
177
|
+
currentFilePath = '',
|
|
178
|
+
currentMarkdownText = '',
|
|
179
|
+
directoryPath,
|
|
180
|
+
fileList = [],
|
|
181
|
+
format,
|
|
182
|
+
} = {}) {
|
|
183
|
+
const normalizedDirectoryPath = String(directoryPath ?? '').replace(/\\/gu, '/').replace(/^\/+|\/+$/gu, '').trim();
|
|
184
|
+
if (!normalizedDirectoryPath) {
|
|
185
|
+
throw new Error('No folder was selected');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return startExport({
|
|
189
|
+
currentFilePath,
|
|
190
|
+
currentMarkdownText,
|
|
191
|
+
directoryPath: normalizedDirectoryPath,
|
|
192
|
+
fileList,
|
|
193
|
+
format,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export async function exportDocument({
|
|
198
|
+
fileList = [],
|
|
199
|
+
filePath,
|
|
200
|
+
format,
|
|
201
|
+
markdownText = '',
|
|
202
|
+
title = '',
|
|
203
|
+
} = {}) {
|
|
204
|
+
const normalizedFilePath = String(filePath ?? '').trim();
|
|
205
|
+
if (!normalizedFilePath) {
|
|
206
|
+
throw new Error('No markdown note is open');
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return startExport({
|
|
210
|
+
fileList,
|
|
211
|
+
filePath: normalizedFilePath,
|
|
212
|
+
format,
|
|
213
|
+
markdownText,
|
|
214
|
+
title,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
postExportPageMessage,
|
|
3
|
+
prepareDirectoryExportSnapshot,
|
|
3
4
|
prepareExportSnapshot,
|
|
4
5
|
runExportAdapter,
|
|
5
6
|
waitForBootstrapPayload,
|
|
@@ -7,6 +8,10 @@ import {
|
|
|
7
8
|
} from './export-pipeline.js';
|
|
8
9
|
import { groupHeadingWithFollowingBlock } from './export-print-layout.js';
|
|
9
10
|
|
|
11
|
+
function getExportJobId() {
|
|
12
|
+
return new URLSearchParams(window.location.search).get('job') || window.name || '';
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
function setStatus(message) {
|
|
11
16
|
const status = document.getElementById('exportStatus');
|
|
12
17
|
if (status) {
|
|
@@ -38,7 +43,8 @@ function renderSnapshot(snapshot) {
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
document.title = `${snapshot.title} — Export`;
|
|
41
|
-
|
|
46
|
+
const parsed = new DOMParser().parseFromString(`<body>${snapshot.html}</body>`, 'text/html');
|
|
47
|
+
mount.replaceChildren(...parsed.body.childNodes);
|
|
42
48
|
groupHeadingWithFollowingBlock(mount);
|
|
43
49
|
renderWarnings(snapshot);
|
|
44
50
|
return mount;
|
|
@@ -48,7 +54,11 @@ async function bootstrap() {
|
|
|
48
54
|
try {
|
|
49
55
|
setStatus('Loading export content…');
|
|
50
56
|
const payload = await waitForBootstrapPayload();
|
|
51
|
-
|
|
57
|
+
document.documentElement.dataset.theme = payload.theme;
|
|
58
|
+
document.body.dataset.theme = payload.theme;
|
|
59
|
+
const snapshot = payload.directoryPath
|
|
60
|
+
? await prepareDirectoryExportSnapshot(payload)
|
|
61
|
+
: await prepareExportSnapshot(payload);
|
|
52
62
|
const mount = renderSnapshot(snapshot);
|
|
53
63
|
snapshot.html = await waitForRenderedExportContent(mount);
|
|
54
64
|
setStatus(payload.action === 'pdf'
|
|
@@ -58,12 +68,12 @@ async function bootstrap() {
|
|
|
58
68
|
setStatus(payload.action === 'pdf'
|
|
59
69
|
? 'Print dialog opened.'
|
|
60
70
|
: `${payload.action.toUpperCase()} download started.`);
|
|
61
|
-
postExportPageMessage('complete', { jobId:
|
|
71
|
+
postExportPageMessage('complete', { jobId: getExportJobId() });
|
|
62
72
|
} catch (error) {
|
|
63
73
|
const message = error instanceof Error ? error.message : 'Export failed';
|
|
64
74
|
setStatus(message);
|
|
65
75
|
postExportPageMessage('error', {
|
|
66
|
-
jobId:
|
|
76
|
+
jobId: getExportJobId(),
|
|
67
77
|
message,
|
|
68
78
|
});
|
|
69
79
|
}
|