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.
- package/README.md +39 -19
- package/bin/collabmd.js +27 -1
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js +1 -0
- package/dist/client/assets/browser-utils--H_DkyEF.js +1 -0
- package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +41 -0
- package/dist/client/assets/{chunk-CZQZEIFA-DT3N9fo7.js → chunk-YGJVY4SA-CjSe7Bx7.js} +2 -2
- package/dist/client/assets/comment-thread-store-CdcwrObc.js +1 -0
- package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
- package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +7 -0
- package/dist/client/assets/dist-B5HTH2BO.js +1 -0
- package/dist/client/assets/{dist-DhLvC8DS.js → dist-B5Jf1SLZ.js} +2 -2
- package/dist/client/assets/{dist-CnL7Y2sM.js → dist-BDt3rz7l.js} +1 -1
- package/dist/client/assets/dist-BEwK4csK.js +1 -0
- package/dist/client/assets/dist-BKW4PALF.js +1 -0
- package/dist/client/assets/dist-BWcHHOx-.js +1 -0
- package/dist/client/assets/{dist-CYZmbokb.js → dist-BalScOwZ.js} +9 -9
- package/dist/client/assets/dist-Bf8f4HmM.js +6 -0
- package/dist/client/assets/dist-BjHJDtyU.js +1 -0
- package/dist/client/assets/dist-Bm6pf9Bl.js +1 -0
- package/dist/client/assets/dist-BoVBdSjk.js +1 -0
- package/dist/client/assets/dist-CC5IrQMG.js +1 -0
- package/dist/client/assets/{dist-C11hHqv_.js → dist-CCP_AKPG.js} +12 -12
- package/dist/client/assets/dist-CZgOmxK6.js +1 -0
- package/dist/client/assets/{dist-D2AQ-76g.js → dist-Cqhv5LAk.js} +1 -1
- package/dist/client/assets/{dist-MvcV4190.js → dist-D-Z6FLem.js} +1 -1
- package/dist/client/assets/dist-DLMiIsNC.js +11 -0
- package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZKu9Cs8.js} +1 -1
- package/dist/client/assets/dist-DaYdhcVs.js +1 -0
- package/dist/client/assets/dist-FWJsgGYI.js +1 -0
- package/dist/client/assets/dist-Kh2COra_.js +1 -0
- package/dist/client/assets/{dist-JYEDRrPT.js → dist-PDZ3bSqm.js} +1 -1
- package/dist/client/assets/{dist-Drp8uu5J.js → dist-TjMh8n1u.js} +1 -1
- package/dist/client/assets/{dist-DGb27Dl6.js → dist-dtAdgL39.js} +1 -1
- package/dist/client/assets/dist-jv4WdPnK.js +9 -0
- package/dist/client/assets/{dist-DK5Gs2wa.js → dist-rGBmqxC7.js} +1 -1
- package/dist/client/assets/{dist-DCzuX1AF.js → dist-shrl6K_0.js} +1 -1
- package/dist/client/assets/dist-tOaegDYS2.js +1 -0
- package/dist/client/assets/dist-ule2n6ak.js +1 -0
- package/dist/client/assets/dist-xElaxbia.js +1 -0
- package/dist/client/assets/drawio-editor-FzY1cVw8.js +9 -0
- package/dist/client/assets/drawioEditor-BjiKJqlc.js +2 -0
- package/dist/client/assets/editor-session-Cm9ekeNo.js +54 -0
- package/dist/client/assets/embedded-editor-base-CwTkk911.css +1 -0
- package/dist/client/assets/{en-GADW4C6J-DQ6zyCEM.js → en-7NFCYGKX-BrgYZAEe.js} +1 -1
- package/dist/client/assets/{preview-render-profile-BZzGSg6K.js → es-DXGV3RHd.js} +13 -13
- package/dist/client/assets/excalidraw-editor-B46zsTFI.js +9 -0
- package/dist/client/assets/excalidraw-editor-Bt7gMSoh.css +1 -0
- package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
- package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +2 -0
- package/dist/client/assets/export-page-A7NHawJY.js +39 -0
- package/dist/client/assets/exportDocument-B2L8fe34.css +1 -0
- package/dist/client/assets/exportDocument-BaqcOAAW.js +2 -0
- package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
- package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
- package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +1 -0
- package/dist/client/assets/index-ClbjMBVt.js +2 -0
- package/dist/client/assets/index-Pum8ET-5.css +1 -0
- package/dist/client/assets/main-B3uPyqic.js +893 -0
- package/dist/client/assets/modulepreload-polyfill-P2Xu9kJm.js +1 -0
- package/dist/client/assets/pdf-BL9Pr2D5.js +54 -0
- package/dist/client/assets/pdf.worker-CLesOks4.mjs +64857 -0
- package/dist/client/assets/pdf_viewer-FVkkThnz.js +551 -0
- package/dist/client/assets/preview-diagram-utils-txBCoW8d.js +1 -0
- package/dist/client/assets/{preview-render-compiler-BSaQO_p3.js → preview-render-compiler-BD-XhkS2.js} +2 -2
- package/dist/client/assets/preview-render-compiler-BKedaMxx.js +1 -0
- package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
- package/dist/client/assets/{preview-render-worker-B42LWvrD.js → preview-render-worker-CiPqc9n6.js} +20 -20
- package/dist/client/assets/prod-Dy20X7eT.js +1 -0
- package/dist/client/assets/prod-hnwh7wRM.js +177 -0
- package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +12 -0
- package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
- package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
- package/dist/client/assets/{yjs-provider-reset-guard-Cox4nxwu.js → yjs-provider-reset-guard-DE0vINDP.js} +1 -1
- package/dist/client/drawio-editor.html +3 -2
- package/dist/client/excalidraw-editor.html +3 -2
- package/dist/client/export-document.html +4 -3
- package/dist/client/index.html +109 -27
- package/docker-compose.yml +42 -0
- package/package.json +26 -15
- package/scripts/local-structurizr-compose.mjs +101 -0
- package/src/client/app/drawio-editor-entry.js +0 -3
- package/src/client/app/drawio-editor.html +1 -0
- package/src/client/app/excalidraw-editor-entry.js +0 -3
- package/src/client/app/excalidraw-editor.html +1 -0
- package/src/client/app/export-document-entry.js +0 -3
- package/src/client/app/export-document.html +1 -0
- package/src/client/app/index.html +106 -24
- package/src/client/app/main-entry.js +0 -5
- package/src/client/application/app-shell/chat-feature.js +180 -124
- package/src/client/application/app-shell/comments-feature.js +20 -11
- package/src/client/application/app-shell/git-feature.js +16 -9
- package/src/client/application/app-shell/presence-feature.js +18 -11
- package/src/client/application/app-shell/ui-feature-shell.js +78 -17
- package/src/client/application/app-shell/ui-feature-sidebar.js +74 -1
- package/src/client/application/app-shell/ui-feature-tab-activity.js +2 -2
- package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
- package/src/client/application/app-shell/workspace-feature.js +27 -84
- package/src/client/application/app-shell-elements.js +9 -1
- package/src/client/application/diagram-chrome.js +161 -166
- package/src/client/application/diagram-preview-export.js +7 -34
- package/src/client/application/diagram-preview-hydrator.js +1 -19
- package/src/client/application/markdown-frontmatter.js +0 -2
- package/src/client/application/mermaid-preview-hydrator.js +1 -14
- package/src/client/application/pdf-preview-controller.js +992 -0
- package/src/client/application/plantuml-preview-hydrator.js +0 -10
- package/src/client/application/preview-diagram-utils.js +31 -2
- package/src/client/application/preview-render-compiler.js +2 -1
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/quick-switcher-loader.js +3 -1
- package/src/client/application/structurizr-preview-controller.js +395 -0
- package/src/client/application/workspace-coordinator.js +25 -3
- package/src/client/application/workspace-preview-controller.js +91 -5
- package/src/client/bootstrap/collabmd-app-shell.js +155 -43
- package/src/client/browser-utils.js +44 -0
- package/src/client/domain/excalidraw-collaboration.js +0 -2
- package/src/client/domain/room.js +38 -0
- package/src/client/domain/runtime-paths.js +26 -5
- package/src/client/domain/structurizr-language.js +99 -0
- package/src/client/domain/vault-paths.js +48 -0
- package/src/client/excalidraw-editor.js +833 -51
- package/src/client/export/export-pipeline.js +6 -34
- package/src/client/infrastructure/auth-client.js +4 -10
- package/src/client/infrastructure/browser-notification-port.js +33 -20
- package/src/client/infrastructure/browser-preferences-port.js +46 -9
- package/src/client/infrastructure/comment-thread-store.js +34 -13
- package/src/client/infrastructure/editor-session.js +10 -0
- package/src/client/infrastructure/editor-view-adapter.js +133 -5
- package/src/client/infrastructure/excalidraw-room-client.js +103 -14
- package/src/client/infrastructure/git-api-client.js +5 -0
- package/src/client/infrastructure/lobby-presence.js +1 -0
- package/src/client/infrastructure/vault-api-client.js +51 -0
- package/src/client/infrastructure/workspace-sync-client.js +13 -1
- package/src/client/presentation/comment-overview-controller.js +18 -53
- package/src/client/presentation/comment-ui/comment-ui-card.js +1 -12
- package/src/client/presentation/comment-ui/comment-ui-layout.js +242 -219
- package/src/client/presentation/comment-ui/comment-ui-render.js +32 -45
- package/src/client/presentation/comment-ui/comment-ui-shared.js +68 -13
- package/src/client/presentation/comment-ui-controller.js +5 -1
- package/src/client/presentation/drawio-embed-controller.js +9 -102
- package/src/client/presentation/drawio-viewer.js +118 -0
- package/src/client/presentation/excalidraw-embed-controller.js +74 -8
- package/src/client/presentation/file-action-controller.js +134 -0
- package/src/client/presentation/file-explorer-controller.js +33 -3
- package/src/client/presentation/file-explorer-view.js +59 -34
- package/src/client/presentation/file-icon-svg.js +40 -0
- package/src/client/presentation/file-tree-state.js +12 -4
- package/src/client/presentation/git-diff-view-controller.js +731 -3
- package/src/client/presentation/outline-controller.js +86 -0
- package/src/client/presentation/quick-switcher-controller.js +257 -74
- package/src/client/presentation/quick-switcher-text-search.js +3 -3
- package/src/client/presentation/toast-controller.js +3 -0
- package/src/client/styles/components/feedback.css +6 -0
- package/src/client/styles/components/navigation.css +11 -1
- package/src/client/styles/features/collaboration-chat.css +49 -53
- package/src/client/styles/features/collaboration-presence.css +9 -7
- package/src/client/styles/features/comment-card.css +25 -11
- package/src/client/styles/features/comment-overlays.css +0 -4
- package/src/client/styles/features/comment-overview.css +44 -21
- package/src/client/styles/features/comments-drawer.css +2 -100
- package/src/client/styles/features/diagram-preview.css +81 -18
- package/src/client/styles/features/diff-special.css +309 -0
- package/src/client/styles/features/embedded-preview.css +8 -33
- package/src/client/styles/features/quick-switcher.css +8 -0
- package/src/client/styles/foundation/themes.css +6 -0
- package/src/client/styles/foundation/tokens.css +1 -0
- package/src/client/styles/layout/editor-page.css +40 -0
- package/src/client/styles/layout/responsive.css +31 -1
- package/src/client/styles/layout/shell.css +383 -7
- package/src/client/styles/layout/sidebar.css +47 -15
- package/src/client/styles/layout/view-modes.css +1 -0
- package/src/client/styles/overrides/codemirror.css +217 -15
- package/src/client/styles/style.css +1 -0
- package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
- package/src/domain/comment-threads.js +63 -5
- package/src/domain/excalidraw-room-codec.js +6 -4
- package/src/domain/file-kind.js +35 -3
- package/src/server/application/workspace-reconciliation.js +1 -1
- package/src/server/config/env.js +79 -0
- package/src/server/create-app-server.js +14 -3
- package/src/server/domain/bases/base-definition.js +1 -1
- package/src/server/domain/bases/base-expression-runtime.js +1 -4
- package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
- package/src/server/domain/bases/base-query-service.js +1 -77
- package/src/server/domain/bases/base-transform.js +1 -4
- package/src/server/domain/collaboration/collaboration-room.js +55 -21
- package/src/server/domain/comment-overview.js +25 -8
- package/src/server/domain/docx-exporter.js +24 -33
- package/src/server/domain/ripgrep-search-service.js +7 -1
- package/src/server/domain/workspace-state.js +32 -11
- package/src/server/infrastructure/git/diff-service.js +29 -13
- package/src/server/infrastructure/git/git-service.js +61 -10
- package/src/server/infrastructure/git/history-service.js +96 -29
- package/src/server/infrastructure/git/image-mime.js +14 -0
- package/src/server/infrastructure/git/path-utils.js +1 -1
- package/src/server/infrastructure/git/responses.js +0 -95
- package/src/server/infrastructure/git/untracked-files.js +28 -1
- package/src/server/infrastructure/github/github-app-client.js +22 -15
- package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
- package/src/server/infrastructure/http/create-request-handler.js +18 -31
- package/src/server/infrastructure/http/create-static-handler.js +5 -2
- package/src/server/infrastructure/http/create-structurizr-api-handler.js +145 -0
- package/src/server/infrastructure/http/create-vault-api-command-handler.js +70 -8
- package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
- package/src/server/infrastructure/http/http-errors.js +7 -1
- package/src/server/infrastructure/http/http-request-helpers.js +22 -0
- package/src/server/infrastructure/persistence/path-utils.js +1 -1
- package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
- package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
- package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +374 -0
- package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
- package/dist/client/assets/bases-preview-controller-2pLHk0uk.js +0 -143
- package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
- package/dist/client/assets/button-BCEiw4Rw.js +0 -1
- package/dist/client/assets/chunk-AXR3VHVW-0GTk_evH.js +0 -41
- package/dist/client/assets/comment-threads-D-iKphIp.js +0 -4
- package/dist/client/assets/diagram-action-icons-aa_KOv9h.js +0 -36
- package/dist/client/assets/dist-BH87JoHx.js +0 -11
- package/dist/client/assets/dist-BIkPRZO7.js +0 -6
- package/dist/client/assets/dist-BqCsFpx4.js +0 -1
- package/dist/client/assets/dist-C2JHCt8U.js +0 -1
- package/dist/client/assets/dist-CZjTtmTu.js +0 -1
- package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
- package/dist/client/assets/dist-CqQEC8gR.js +0 -1
- package/dist/client/assets/dist-D4Rzqod1.js +0 -1
- package/dist/client/assets/dist-D5sn-mwk.js +0 -9
- package/dist/client/assets/dist-D7G-n87v.js +0 -1
- package/dist/client/assets/dist-DRqOrNgN.js +0 -1
- package/dist/client/assets/dist-DetkMS_4.js +0 -1
- package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
- package/dist/client/assets/dist-DtbjNB28.js +0 -1
- package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
- package/dist/client/assets/dist-GrygD2zE.js +0 -1
- package/dist/client/assets/dist-HmEpWUow.js +0 -1
- package/dist/client/assets/dist-RTa81Km7.js +0 -1
- package/dist/client/assets/drawio-editor-DDvFoarP.js +0 -9
- package/dist/client/assets/drawio-embed-controller-BD1GTRwn.js +0 -1
- package/dist/client/assets/drawioEditor-Bu5grlH5.js +0 -2
- package/dist/client/assets/editor-session-DGlpiAsK.js +0 -16
- package/dist/client/assets/embedded-editor-base-C9roKYpW.css +0 -1
- package/dist/client/assets/excalidraw-editor-BHu6k8d4.js +0 -9
- package/dist/client/assets/excalidraw-editor-Cr_184EF.css +0 -1
- package/dist/client/assets/excalidraw-embed-controller-y2fenN_g.js +0 -1
- package/dist/client/assets/excalidraw-embed-reconciler-DGiagExg.js +0 -1
- package/dist/client/assets/excalidraw-scene-BvsQ6mLP.js +0 -176
- package/dist/client/assets/excalidrawEditor-4vFE--Uw.js +0 -2
- package/dist/client/assets/export-page-Cby8JzPO.js +0 -39
- package/dist/client/assets/exportDocument-C9v-bc7I.css +0 -1
- package/dist/client/assets/exportDocument-CRHCfsdo.js +0 -2
- package/dist/client/assets/file-history-view-controller-BDjEV9xJ.js +0 -112
- package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
- package/dist/client/assets/git-diff-view-controller-DgdM1aqb.js +0 -150
- package/dist/client/assets/git-panel-controller-BDTR2HVp.js +0 -207
- package/dist/client/assets/image-XGD7JQR6-XDUWHRpO.js +0 -1
- package/dist/client/assets/index-7xOyXDhP.css +0 -1
- package/dist/client/assets/index-Bz1KuQ6y.js +0 -2
- package/dist/client/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/dist/client/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/dist/client/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/dist/client/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/dist/client/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/client/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/client/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/client/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/client/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/client/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/client/assets/main-Ci07m9oP.js +0 -152
- package/dist/client/assets/preview-diagram-utils-n_bbJA9V.js +0 -1
- package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
- package/dist/client/assets/quick-switcher-controller-CoiYvllm.js +0 -12
- package/dist/client/assets/room-CDrmIdDt.js +0 -1
- package/dist/client/assets/runtime-config-CDgeuPWN.js +0 -1
- package/dist/client/assets/runtime-config-loader-BHGniHP5.js +0 -1
- package/dist/client/assets/runtime-paths-DvpihCEq.js +0 -1
- package/dist/client/assets/segmented-control-DJrHSz8M.js +0 -1
- package/dist/client/assets/vault-api-client-sLB2bo56.js +0 -1
- package/dist/client/assets/vault-paths-CVkuh0j-.js +0 -5
- package/src/client/bootstrap/lazy-controller-feature.js +0 -433
- package/src/client/infrastructure/backlinks-api-client.js +0 -16
- package/src/client/infrastructure/plantuml-api-client.js +0 -19
- package/src/client/infrastructure/runtime-config-loader.js +0 -56
- package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
- package/src/server/infrastructure/git/command-runner.js +0 -49
- package/src/server/infrastructure/git/errors.js +0 -8
- package/src/server/infrastructure/http/create-esm-proxy-handler.js +0 -130
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { exportToSvg as exportExcalidrawToSvg } from '@excalidraw/excalidraw';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
encodeSvgDataUrl,
|
|
5
|
+
loadImage,
|
|
6
|
+
resolveSvgDimensions,
|
|
7
|
+
sanitizeSvgMarkup,
|
|
8
|
+
} from '../application/preview-diagram-utils.js';
|
|
4
9
|
import { compilePreviewDocument } from '../application/preview-render-compiler.js';
|
|
5
10
|
import { stripVaultFileExtension } from '../../domain/file-kind.js';
|
|
6
11
|
import { parseSceneJson, sceneToInitialData } from '../domain/excalidraw-scene.js';
|
|
@@ -60,10 +65,6 @@ function createDocumentTitle(filePath, title = '') {
|
|
|
60
65
|
return stripVaultFileExtension(leaf) || 'document';
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
function encodeSvgDataUrl(svgMarkup) {
|
|
64
|
-
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgMarkup)}`;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
68
|
function encodeSvgBase64DataUrl(svgMarkup) {
|
|
68
69
|
const bytes = new TextEncoder().encode(String(svgMarkup ?? ''));
|
|
69
70
|
const chunkSize = 0x8000;
|
|
@@ -87,35 +88,6 @@ function blobToDataUrl(blob) {
|
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
function loadImage(src) {
|
|
91
|
-
return new Promise((resolve, reject) => {
|
|
92
|
-
const image = new Image();
|
|
93
|
-
image.decoding = 'async';
|
|
94
|
-
image.addEventListener('load', () => resolve(image), { once: true });
|
|
95
|
-
image.addEventListener('error', () => reject(new Error(`Failed to load image: ${src}`)), { once: true });
|
|
96
|
-
image.src = src;
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function resolveSvgDimensions(svgElement) {
|
|
101
|
-
const widthAttr = Number.parseFloat(svgElement.getAttribute('width') || '');
|
|
102
|
-
const heightAttr = Number.parseFloat(svgElement.getAttribute('height') || '');
|
|
103
|
-
const viewBox = svgElement.getAttribute('viewBox') || '';
|
|
104
|
-
const viewBoxParts = viewBox.split(/\s+/).map((value) => Number.parseFloat(value));
|
|
105
|
-
|
|
106
|
-
const width = Number.isFinite(widthAttr) && widthAttr > 0
|
|
107
|
-
? widthAttr
|
|
108
|
-
: (Number.isFinite(viewBoxParts[2]) && viewBoxParts[2] > 0 ? viewBoxParts[2] : 1200);
|
|
109
|
-
const height = Number.isFinite(heightAttr) && heightAttr > 0
|
|
110
|
-
? heightAttr
|
|
111
|
-
: (Number.isFinite(viewBoxParts[3]) && viewBoxParts[3] > 0 ? viewBoxParts[3] : 800);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
height,
|
|
115
|
-
width,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
91
|
function trimSvgCanvas(svgMarkup, { padding = 16 } = {}) {
|
|
120
92
|
const probe = document.createElement('div');
|
|
121
93
|
probe.style.position = 'fixed';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../styles/features/auth-gate.css';
|
|
2
2
|
|
|
3
|
+
import { getHashParamsFromRaw } from '../domain/hash-routes.js';
|
|
3
4
|
import { getRuntimeConfig } from './runtime-config.js';
|
|
4
5
|
|
|
5
6
|
const DEFAULT_AUTH_CONFIG = {
|
|
@@ -24,19 +25,12 @@ function getClientAuthConfig() {
|
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
function getHashParams() {
|
|
28
|
-
const rawHash = window.location.hash.startsWith('#')
|
|
29
|
-
? window.location.hash.slice(1)
|
|
30
|
-
: window.location.hash;
|
|
31
|
-
return new URLSearchParams(rawHash);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
28
|
function getPasswordFromHash() {
|
|
35
|
-
return
|
|
29
|
+
return getHashParamsFromRaw(window.location.hash).get('auth_password') || '';
|
|
36
30
|
}
|
|
37
31
|
|
|
38
32
|
function removePasswordFromHash() {
|
|
39
|
-
const params =
|
|
33
|
+
const params = getHashParamsFromRaw(window.location.hash);
|
|
40
34
|
if (!params.has('auth_password')) {
|
|
41
35
|
return;
|
|
42
36
|
}
|
|
@@ -48,7 +42,7 @@ function removePasswordFromHash() {
|
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
function consumeHashParam(name) {
|
|
51
|
-
const params =
|
|
45
|
+
const params = getHashParamsFromRaw(window.location.hash);
|
|
52
46
|
const value = params.get(name) || '';
|
|
53
47
|
if (!value) {
|
|
54
48
|
return '';
|
|
@@ -1,36 +1,49 @@
|
|
|
1
1
|
export class BrowserNotificationPort {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
this.NotificationImpl = NotificationImpl;
|
|
7
|
-
this.focusWindow = focusWindow;
|
|
2
|
+
getApi() {
|
|
3
|
+
return typeof globalThis.Notification === 'function'
|
|
4
|
+
? globalThis.Notification
|
|
5
|
+
: null;
|
|
8
6
|
}
|
|
9
7
|
|
|
10
8
|
getPermission() {
|
|
11
|
-
return
|
|
12
|
-
? this.NotificationImpl.permission
|
|
13
|
-
: 'unsupported';
|
|
9
|
+
return this.getApi()?.permission ?? 'unsupported';
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
async requestPermission() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
const api = this.getApi();
|
|
14
|
+
if (!api || typeof api.requestPermission !== 'function') {
|
|
15
|
+
return 'unsupported';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (api.permission !== 'default') {
|
|
19
|
+
return api.permission;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
return await api.requestPermission();
|
|
24
|
+
} catch {
|
|
25
|
+
return api.permission ?? 'default';
|
|
26
|
+
}
|
|
20
27
|
}
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
show({ body, onClick, tag, title } = {}) {
|
|
30
|
+
const api = this.getApi();
|
|
31
|
+
if (!api || api.permission !== 'granted' || !body) {
|
|
24
32
|
return null;
|
|
25
33
|
}
|
|
26
34
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
try {
|
|
36
|
+
const notification = new api(title, {
|
|
37
|
+
body,
|
|
38
|
+
renotify: true,
|
|
39
|
+
tag,
|
|
32
40
|
});
|
|
41
|
+
if (onClick) {
|
|
42
|
+
notification.onclick = onClick;
|
|
43
|
+
}
|
|
44
|
+
return notification;
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
33
47
|
}
|
|
34
|
-
return notification;
|
|
35
48
|
}
|
|
36
49
|
}
|
|
@@ -15,19 +15,25 @@ function writeStorage(storage, key, value) {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
const MAX_RECENT_FILES = 20;
|
|
19
|
+
|
|
18
20
|
export class BrowserPreferencesPort {
|
|
19
21
|
constructor({
|
|
20
|
-
|
|
22
|
+
fileTreeShowExtensionsKey,
|
|
21
23
|
lineWrappingKey,
|
|
24
|
+
recentFilesKey = 'collabmd-recent-files',
|
|
25
|
+
vimModeKey = 'collabmd-editor-vim-mode',
|
|
22
26
|
sidebarVisibleKey,
|
|
23
27
|
userNameKey,
|
|
24
28
|
storage = globalThis.localStorage,
|
|
25
29
|
}) {
|
|
26
|
-
this.
|
|
30
|
+
this.fileTreeShowExtensionsKey = fileTreeShowExtensionsKey;
|
|
27
31
|
this.lineWrappingKey = lineWrappingKey;
|
|
32
|
+
this.recentFilesKey = recentFilesKey;
|
|
28
33
|
this.sidebarVisibleKey = sidebarVisibleKey;
|
|
29
34
|
this.storage = storage;
|
|
30
35
|
this.userNameKey = userNameKey;
|
|
36
|
+
this.vimModeKey = vimModeKey;
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
getUserName() {
|
|
@@ -38,6 +44,14 @@ export class BrowserPreferencesPort {
|
|
|
38
44
|
writeStorage(this.storage, this.userNameKey, name);
|
|
39
45
|
}
|
|
40
46
|
|
|
47
|
+
getFileTreeShowExtensions() {
|
|
48
|
+
return readStorage(this.storage, this.fileTreeShowExtensionsKey, null) === 'true';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setFileTreeShowExtensions(showFileExtensions) {
|
|
52
|
+
writeStorage(this.storage, this.fileTreeShowExtensionsKey, showFileExtensions ? 'true' : 'false');
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
getLineWrappingEnabled() {
|
|
42
56
|
return readStorage(this.storage, this.lineWrappingKey, null) !== 'false';
|
|
43
57
|
}
|
|
@@ -46,6 +60,36 @@ export class BrowserPreferencesPort {
|
|
|
46
60
|
writeStorage(this.storage, this.lineWrappingKey, String(enabled));
|
|
47
61
|
}
|
|
48
62
|
|
|
63
|
+
getVimModeEnabled() {
|
|
64
|
+
return readStorage(this.storage, this.vimModeKey, null) === 'true';
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
setVimModeEnabled(enabled) {
|
|
68
|
+
writeStorage(this.storage, this.vimModeKey, String(enabled));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
getRecentFiles() {
|
|
72
|
+
const stored = readStorage(this.storage, this.recentFilesKey, '[]');
|
|
73
|
+
try {
|
|
74
|
+
const recentFiles = JSON.parse(stored);
|
|
75
|
+
return Array.isArray(recentFiles)
|
|
76
|
+
? [...new Set(recentFiles.filter((filePath) => typeof filePath === 'string' && filePath))]
|
|
77
|
+
: [];
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
recordRecentFile(filePath) {
|
|
84
|
+
if (!filePath) return;
|
|
85
|
+
|
|
86
|
+
const recentFiles = [
|
|
87
|
+
filePath,
|
|
88
|
+
...this.getRecentFiles().filter((recentFilePath) => recentFilePath !== filePath),
|
|
89
|
+
];
|
|
90
|
+
writeStorage(this.storage, this.recentFilesKey, JSON.stringify(recentFiles.slice(0, MAX_RECENT_FILES)));
|
|
91
|
+
}
|
|
92
|
+
|
|
49
93
|
getSidebarVisible() {
|
|
50
94
|
return readStorage(this.storage, this.sidebarVisibleKey, null);
|
|
51
95
|
}
|
|
@@ -54,11 +98,4 @@ export class BrowserPreferencesPort {
|
|
|
54
98
|
writeStorage(this.storage, this.sidebarVisibleKey, showSidebar ? 'true' : 'false');
|
|
55
99
|
}
|
|
56
100
|
|
|
57
|
-
getChatNotificationsEnabled() {
|
|
58
|
-
return readStorage(this.storage, this.chatNotificationsKey, null) === 'true';
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
setChatNotificationsEnabled(enabled) {
|
|
62
|
-
writeStorage(this.storage, this.chatNotificationsKey, String(enabled));
|
|
63
|
-
}
|
|
64
101
|
}
|
|
@@ -83,15 +83,21 @@ function normalizeSelectionAnchorPayload(payload, state) {
|
|
|
83
83
|
|
|
84
84
|
export class CommentThreadStore {
|
|
85
85
|
constructor({
|
|
86
|
+
canWrite = () => true,
|
|
87
|
+
createAnchor = null,
|
|
86
88
|
getDoc,
|
|
87
89
|
getEditorState,
|
|
88
90
|
getLocalUser,
|
|
89
91
|
onCommentsChange = null,
|
|
92
|
+
resolveThread = null,
|
|
90
93
|
}) {
|
|
94
|
+
this.canWrite = canWrite;
|
|
95
|
+
this.createAnchor = createAnchor;
|
|
91
96
|
this.getDoc = getDoc;
|
|
92
97
|
this.getEditorState = getEditorState;
|
|
93
98
|
this.getLocalUser = getLocalUser;
|
|
94
99
|
this.onCommentsChange = onCommentsChange;
|
|
100
|
+
this.resolveThread = resolveThread;
|
|
95
101
|
this.commentThreads = null;
|
|
96
102
|
this.ydoc = null;
|
|
97
103
|
this.ytext = null;
|
|
@@ -144,33 +150,44 @@ export class CommentThreadStore {
|
|
|
144
150
|
}
|
|
145
151
|
|
|
146
152
|
return serializeCommentThreads(this.commentThreads)
|
|
147
|
-
.map((thread) => this.
|
|
153
|
+
.map((thread) => this.resolveThread
|
|
154
|
+
? this.resolveThread(thread)
|
|
155
|
+
: this.resolveCommentThread(thread))
|
|
148
156
|
.filter(Boolean);
|
|
149
157
|
}
|
|
150
158
|
|
|
151
159
|
createCommentThread({ anchor, body }) {
|
|
152
|
-
|
|
153
|
-
if (!state || !this.commentThreads || !this.ytext || !this.ydoc) {
|
|
160
|
+
if (!this.canWrite() || !this.commentThreads || !this.ydoc) {
|
|
154
161
|
return null;
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
const state = this.getEditorState?.();
|
|
157
165
|
const normalizedBody = normalizeCommentBody(body);
|
|
158
|
-
|
|
166
|
+
if (!this.createAnchor && (!state || !this.ytext)) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const normalizedAnchor = this.createAnchor
|
|
171
|
+
? this.createAnchor(anchor)
|
|
172
|
+
: normalizeSelectionAnchorPayload(anchor, state);
|
|
159
173
|
if (!normalizedBody || !normalizedAnchor) {
|
|
160
174
|
return null;
|
|
161
175
|
}
|
|
162
176
|
|
|
163
177
|
const thread = createCommentThreadSharedType({
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
178
|
+
...normalizedAnchor,
|
|
179
|
+
...(this.createAnchor ? {} : {
|
|
180
|
+
anchorEnd: Y.relativePositionToJSON(
|
|
181
|
+
Y.createRelativePositionFromTypeIndex(this.ytext, normalizedAnchor.endIndex),
|
|
182
|
+
),
|
|
183
|
+
}),
|
|
168
184
|
anchorKind: normalizedAnchor.anchorKind,
|
|
169
185
|
anchorQuote: normalizedAnchor.anchorQuote,
|
|
170
|
-
|
|
171
|
-
Y.
|
|
172
|
-
|
|
173
|
-
|
|
186
|
+
...(this.createAnchor ? {} : {
|
|
187
|
+
anchorStart: Y.relativePositionToJSON(
|
|
188
|
+
Y.createRelativePositionFromTypeIndex(this.ytext, normalizedAnchor.startIndex),
|
|
189
|
+
),
|
|
190
|
+
}),
|
|
174
191
|
createdAt: Date.now(),
|
|
175
192
|
createdByColor: this.getLocalUser()?.color ?? '',
|
|
176
193
|
createdByName: this.getLocalUser()?.name ?? 'Anonymous',
|
|
@@ -194,6 +211,10 @@ export class CommentThreadStore {
|
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
replyToCommentThread(threadId, body) {
|
|
214
|
+
if (!this.canWrite()) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
|
|
197
218
|
const normalizedBody = normalizeCommentBody(body);
|
|
198
219
|
if (!normalizedBody || !this.ydoc) {
|
|
199
220
|
return null;
|
|
@@ -291,7 +312,7 @@ export class CommentThreadStore {
|
|
|
291
312
|
}
|
|
292
313
|
|
|
293
314
|
deleteCommentThread(threadId) {
|
|
294
|
-
if (!this.commentThreads || !this.ydoc) {
|
|
315
|
+
if (!this.canWrite() || !this.commentThreads || !this.ydoc) {
|
|
295
316
|
return false;
|
|
296
317
|
}
|
|
297
318
|
|
|
@@ -8,6 +8,7 @@ export class EditorSession {
|
|
|
8
8
|
constructor({
|
|
9
9
|
editorContainer,
|
|
10
10
|
lineWrappingEnabled = true,
|
|
11
|
+
vimModeEnabled = false,
|
|
11
12
|
initialTheme,
|
|
12
13
|
lineInfoElement,
|
|
13
14
|
onAwarenessChange,
|
|
@@ -44,6 +45,7 @@ export class EditorSession {
|
|
|
44
45
|
initialTheme,
|
|
45
46
|
lineInfoElement,
|
|
46
47
|
lineWrappingEnabled,
|
|
48
|
+
vimModeEnabled,
|
|
47
49
|
onDocChanged: () => {
|
|
48
50
|
this.emitContentChange();
|
|
49
51
|
},
|
|
@@ -210,6 +212,14 @@ export class EditorSession {
|
|
|
210
212
|
return this.viewAdapter.isLineWrappingEnabled();
|
|
211
213
|
}
|
|
212
214
|
|
|
215
|
+
isVimModeEnabled() {
|
|
216
|
+
return this.viewAdapter.isVimModeEnabled();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
setVimMode(enabled) {
|
|
220
|
+
return this.viewAdapter.setVimMode(enabled);
|
|
221
|
+
}
|
|
222
|
+
|
|
213
223
|
setLineWrapping(enabled) {
|
|
214
224
|
return this.viewAdapter.setLineWrapping(enabled);
|
|
215
225
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { vim } from '@replit/codemirror-vim';
|
|
1
2
|
import { autocompletion, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
|
2
3
|
import {
|
|
3
4
|
defaultKeymap,
|
|
@@ -20,7 +21,14 @@ import {
|
|
|
20
21
|
syntaxHighlighting,
|
|
21
22
|
} from '@codemirror/language';
|
|
22
23
|
import { languages } from '@codemirror/language-data';
|
|
23
|
-
import {
|
|
24
|
+
import {
|
|
25
|
+
findNext,
|
|
26
|
+
getSearchQuery,
|
|
27
|
+
highlightSelectionMatches,
|
|
28
|
+
openSearchPanel,
|
|
29
|
+
searchKeymap,
|
|
30
|
+
searchPanelOpen,
|
|
31
|
+
} from '@codemirror/search';
|
|
24
32
|
import { Compartment, EditorSelection, EditorState, Prec, StateEffect, StateField } from '@codemirror/state';
|
|
25
33
|
import { oneDark } from '@codemirror/theme-one-dark';
|
|
26
34
|
import {
|
|
@@ -38,15 +46,26 @@ import {
|
|
|
38
46
|
} from '@codemirror/view';
|
|
39
47
|
import { yCollab } from 'y-codemirror.next';
|
|
40
48
|
|
|
41
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
isBaseFilePath,
|
|
51
|
+
isMermaidFilePath,
|
|
52
|
+
isPlantUmlFilePath,
|
|
53
|
+
isStructurizrFilePath,
|
|
54
|
+
} from '../../domain/file-kind.js';
|
|
42
55
|
import { normalizeCommentQuote } from '../../domain/comment-threads.js';
|
|
43
56
|
import { createMarkdownToolbarEdit } from '../domain/markdown-formatting.js';
|
|
44
57
|
import { mermaidLanguage, mermaidLanguageDescription } from '../domain/mermaid-language.js';
|
|
45
58
|
import { wikiLinkCompletions } from '../domain/wiki-link-completions.js';
|
|
46
59
|
import { plantUmlLanguage, plantUmlLanguageDescription } from '../domain/plantuml-language.js';
|
|
60
|
+
import { structurizrLanguage, structurizrLanguageDescription } from '../domain/structurizr-language.js';
|
|
47
61
|
import { handleImagePasteEvent } from './editor-paste-utils.js';
|
|
48
62
|
|
|
49
|
-
const markdownCodeLanguages = [
|
|
63
|
+
const markdownCodeLanguages = [
|
|
64
|
+
...languages,
|
|
65
|
+
mermaidLanguageDescription,
|
|
66
|
+
plantUmlLanguageDescription,
|
|
67
|
+
structurizrLanguageDescription,
|
|
68
|
+
];
|
|
50
69
|
const pairedMatchingBracketMark = Decoration.mark({ class: 'cm-matchingBracket cm-matchingBracket-paired' });
|
|
51
70
|
const nonmatchingBracketMark = Decoration.mark({ class: 'cm-nonmatchingBracket' });
|
|
52
71
|
const remoteUpdateMark = Decoration.mark({ class: 'cm-remoteUpdateFlash' });
|
|
@@ -54,10 +73,82 @@ const REMOTE_UPDATE_FLASH_DURATION_MS = 1350;
|
|
|
54
73
|
const REMOTE_UPDATE_CARET_MAX_LENGTH = 160;
|
|
55
74
|
const RECENT_LOCAL_INPUT_WINDOW_MS = 900;
|
|
56
75
|
const TASK_LIST_MARKER_PATTERN = /^(\s*(?:>\s*)*(?:[-+*]|\d+[.)])\s+\[)( |x|X)(\])(\s.*)?$/;
|
|
76
|
+
|
|
77
|
+
function openSearchPanelPreservingViewport(view) {
|
|
78
|
+
const scrollTop = view.scrollDOM.scrollTop;
|
|
79
|
+
const selection = view.state.selection;
|
|
80
|
+
const applied = openSearchPanel(view);
|
|
81
|
+
|
|
82
|
+
if (applied) {
|
|
83
|
+
requestAnimationFrame(() => {
|
|
84
|
+
if (view.dom.isConnected && view.state.selection.eq(selection)) {
|
|
85
|
+
view.scrollDOM.scrollTop = scrollTop;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return applied;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function getSearchQueryKey(query) {
|
|
94
|
+
return JSON.stringify([query.search, query.caseSensitive, query.regexp, query.wholeWord]);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function createSearchNavigationListener() {
|
|
98
|
+
let lastQueryKey = '';
|
|
99
|
+
let panelWasOpen = false;
|
|
100
|
+
let pendingFrame = 0;
|
|
101
|
+
|
|
102
|
+
return EditorView.updateListener.of((update) => {
|
|
103
|
+
const panelOpen = searchPanelOpen(update.state);
|
|
104
|
+
const query = getSearchQuery(update.state);
|
|
105
|
+
const queryKey = getSearchQueryKey(query);
|
|
106
|
+
const shouldReveal = panelOpen
|
|
107
|
+
&& query.valid
|
|
108
|
+
&& (!panelWasOpen || queryKey !== lastQueryKey);
|
|
109
|
+
|
|
110
|
+
panelWasOpen = panelOpen;
|
|
111
|
+
lastQueryKey = queryKey;
|
|
112
|
+
|
|
113
|
+
if (!shouldReveal) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (pendingFrame) {
|
|
118
|
+
cancelAnimationFrame(pendingFrame);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
pendingFrame = requestAnimationFrame(() => {
|
|
122
|
+
pendingFrame = 0;
|
|
123
|
+
if (!update.view.dom.isConnected) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const currentQuery = getSearchQuery(update.view.state);
|
|
128
|
+
if (
|
|
129
|
+
!searchPanelOpen(update.view.state)
|
|
130
|
+
|| !currentQuery.valid
|
|
131
|
+
|| getSearchQueryKey(currentQuery) !== queryKey
|
|
132
|
+
) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const searchInput = update.view.dom.querySelector('.cm-search input[name="search"]');
|
|
137
|
+
const inputSelection = searchInput === update.view.root.activeElement && searchInput
|
|
138
|
+
? { end: searchInput.selectionEnd, start: searchInput.selectionStart }
|
|
139
|
+
: null;
|
|
140
|
+
findNext(update.view);
|
|
141
|
+
if (inputSelection && searchInput?.setSelectionRange) {
|
|
142
|
+
searchInput.setSelectionRange(inputSelection.start, inputSelection.end);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
57
148
|
const EDITOR_COMMANDS = Object.freeze({
|
|
58
149
|
indentLess,
|
|
59
150
|
indentMore,
|
|
60
|
-
openSearch:
|
|
151
|
+
openSearch: openSearchPanelPreservingViewport,
|
|
61
152
|
redo,
|
|
62
153
|
undo,
|
|
63
154
|
});
|
|
@@ -308,6 +399,10 @@ export function createLanguageExtension(filePath) {
|
|
|
308
399
|
return plantUmlLanguage;
|
|
309
400
|
}
|
|
310
401
|
|
|
402
|
+
if (isStructurizrFilePath(filePath)) {
|
|
403
|
+
return structurizrLanguage;
|
|
404
|
+
}
|
|
405
|
+
|
|
311
406
|
if (isBaseFilePath(filePath)) {
|
|
312
407
|
return yaml();
|
|
313
408
|
}
|
|
@@ -329,6 +424,7 @@ export class EditorViewAdapter {
|
|
|
329
424
|
initialTheme,
|
|
330
425
|
lineInfoElement,
|
|
331
426
|
lineWrappingEnabled = true,
|
|
427
|
+
vimModeEnabled = false,
|
|
332
428
|
onDocChanged = null,
|
|
333
429
|
onImagePaste = null,
|
|
334
430
|
onSelectionChanged = null,
|
|
@@ -339,6 +435,7 @@ export class EditorViewAdapter {
|
|
|
339
435
|
this.initialTheme = initialTheme;
|
|
340
436
|
this.lineInfoElement = lineInfoElement;
|
|
341
437
|
this.lineWrappingEnabled = lineWrappingEnabled;
|
|
438
|
+
this.vimModeEnabled = Boolean(vimModeEnabled);
|
|
342
439
|
this.onDocChanged = onDocChanged;
|
|
343
440
|
this.onImagePaste = onImagePaste;
|
|
344
441
|
this.onSelectionChanged = onSelectionChanged;
|
|
@@ -347,6 +444,7 @@ export class EditorViewAdapter {
|
|
|
347
444
|
this.themeCompartment = new Compartment();
|
|
348
445
|
this.syntaxThemeCompartment = new Compartment();
|
|
349
446
|
this.lineWrappingCompartment = new Compartment();
|
|
447
|
+
this.vimModeCompartment = new Compartment();
|
|
350
448
|
this.viewportFrame = 0;
|
|
351
449
|
this.remoteUpdateFlashTimer = 0;
|
|
352
450
|
this.lastLocalInputAt = 0;
|
|
@@ -398,11 +496,17 @@ export class EditorViewAdapter {
|
|
|
398
496
|
crosshairCursor(),
|
|
399
497
|
highlightActiveLine(),
|
|
400
498
|
highlightSelectionMatches(),
|
|
499
|
+
createSearchNavigationListener(),
|
|
500
|
+
this.vimModeCompartment.of(!readOnly && this.vimModeEnabled ? vim({ status: true }) : []),
|
|
401
501
|
keymap.of([
|
|
402
502
|
...closeBracketsKeymap,
|
|
403
503
|
...defaultKeymap,
|
|
404
504
|
...historyKeymap,
|
|
405
|
-
...searchKeymap
|
|
505
|
+
...searchKeymap.map((binding) => (
|
|
506
|
+
binding.run === openSearchPanel
|
|
507
|
+
? { ...binding, run: openSearchPanelPreservingViewport }
|
|
508
|
+
: binding
|
|
509
|
+
)),
|
|
406
510
|
...foldKeymap,
|
|
407
511
|
indentWithTab,
|
|
408
512
|
]),
|
|
@@ -561,6 +665,30 @@ export class EditorViewAdapter {
|
|
|
561
665
|
return this.lineWrappingEnabled;
|
|
562
666
|
}
|
|
563
667
|
|
|
668
|
+
isVimModeEnabled() {
|
|
669
|
+
return this.vimModeEnabled;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
setVimMode(enabled) {
|
|
673
|
+
const nextEnabled = Boolean(enabled);
|
|
674
|
+
if (nextEnabled === this.vimModeEnabled) {
|
|
675
|
+
return nextEnabled;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
this.vimModeEnabled = nextEnabled;
|
|
679
|
+
if (!this.editorView || this.editorView.state.readOnly) {
|
|
680
|
+
return nextEnabled;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
this.editorView.dispatch({
|
|
684
|
+
effects: this.vimModeCompartment.reconfigure(
|
|
685
|
+
nextEnabled ? vim({ status: true }) : [],
|
|
686
|
+
),
|
|
687
|
+
});
|
|
688
|
+
this.editorView.focus();
|
|
689
|
+
return nextEnabled;
|
|
690
|
+
}
|
|
691
|
+
|
|
564
692
|
setLineWrapping(enabled) {
|
|
565
693
|
this.lineWrappingEnabled = Boolean(enabled);
|
|
566
694
|
|