@wonderwhy-er/desktop-commander 0.2.37 → 0.2.39
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 +290 -100
- package/dist/command-manager.js +6 -3
- package/dist/config-field-definitions.d.ts +41 -0
- package/dist/config-field-definitions.js +37 -0
- package/dist/config-manager.d.ts +2 -0
- package/dist/config-manager.js +22 -2
- package/dist/handlers/filesystem-handlers.d.ts +5 -0
- package/dist/handlers/filesystem-handlers.js +19 -12
- package/dist/remote-device/desktop-commander-integration.js +1 -1
- package/dist/remote-device/remote-channel.js +1 -1
- package/dist/search-manager.js +31 -38
- package/dist/server.js +11 -4
- package/dist/terminal-manager.js +4 -2
- package/dist/tools/config.d.ts +71 -0
- package/dist/tools/config.js +117 -2
- package/dist/tools/edit.js +34 -1
- package/dist/tools/filesystem.js +91 -3
- package/dist/tools/improved-process-tools.js +2 -1
- package/dist/tools/schemas.d.ts +3 -0
- package/dist/tools/schemas.js +1 -0
- package/dist/types.d.ts +0 -1
- package/dist/ui/config-editor/app.d.ts +43 -0
- package/dist/ui/config-editor/app.js +840 -0
- package/dist/ui/config-editor/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/array-modal.js +185 -0
- package/dist/ui/config-editor/config-editor-runtime.js +150 -0
- package/dist/ui/config-editor/index.html +13 -0
- package/dist/ui/config-editor/main.js +2 -0
- package/dist/ui/config-editor/src/App.d.ts +43 -0
- package/dist/ui/config-editor/src/App.js +840 -0
- package/dist/ui/config-editor/src/array-modal.d.ts +19 -0
- package/dist/ui/config-editor/src/array-modal.js +185 -0
- package/dist/ui/config-editor/src/components/layout.d.ts +4 -0
- package/dist/ui/config-editor/src/components/layout.js +83 -0
- package/dist/ui/config-editor/src/components/toolbar.d.ts +1 -0
- package/dist/ui/config-editor/src/components/toolbar.js +21 -0
- package/dist/ui/config-editor/src/config-values.d.ts +6 -0
- package/dist/ui/config-editor/src/config-values.js +61 -0
- package/dist/ui/config-editor/src/contracts.d.ts +14 -0
- package/dist/ui/config-editor/src/contracts.js +3 -0
- package/dist/ui/config-editor/src/directory-browser.d.ts +6 -0
- package/dist/ui/config-editor/src/directory-browser.js +71 -0
- package/dist/ui/config-editor/src/layout.d.ts +5 -0
- package/dist/ui/config-editor/src/layout.js +90 -0
- package/dist/ui/config-editor/src/main.js +2 -0
- package/dist/ui/config-editor/src/parsing.d.ts +5 -0
- package/dist/ui/config-editor/src/parsing.js +50 -0
- package/dist/ui/config-editor/src/toolbar.d.ts +1 -0
- package/dist/ui/config-editor/src/toolbar.js +18 -0
- package/dist/ui/config-editor/src/types.d.ts +17 -0
- package/dist/ui/config-editor/src/types.js +3 -0
- package/dist/ui/config-editor/src/utils/config-values.d.ts +9 -0
- package/dist/ui/config-editor/src/utils/config-values.js +61 -0
- package/dist/ui/config-editor/src/utils/directory-browser.d.ts +31 -0
- package/dist/ui/config-editor/src/utils/directory-browser.js +201 -0
- package/dist/ui/config-editor/src/utils/parsing.d.ts +8 -0
- package/dist/ui/config-editor/src/utils/parsing.js +50 -0
- package/dist/ui/config-editor/styles.css +587 -0
- package/dist/ui/file-preview/app.d.ts +8 -0
- package/dist/ui/file-preview/app.js +2020 -0
- package/dist/ui/file-preview/components/code-viewer.d.ts +6 -0
- package/dist/ui/file-preview/components/code-viewer.js +73 -0
- package/dist/ui/file-preview/components/highlighting.d.ts +2 -0
- package/dist/ui/file-preview/components/highlighting.js +54 -0
- package/dist/ui/file-preview/components/html-renderer.d.ts +5 -0
- package/dist/ui/file-preview/components/html-renderer.js +47 -0
- package/dist/ui/file-preview/components/markdown-renderer.d.ts +1 -0
- package/dist/ui/file-preview/components/markdown-renderer.js +67 -0
- package/dist/ui/file-preview/components/toolbar.d.ts +6 -0
- package/dist/ui/file-preview/components/toolbar.js +75 -0
- package/dist/ui/file-preview/image-preview.d.ts +3 -0
- package/dist/ui/file-preview/image-preview.js +21 -0
- package/dist/ui/file-preview/main.js +5 -0
- package/dist/ui/file-preview/markdown/editor.d.ts +36 -0
- package/dist/ui/file-preview/markdown/editor.js +643 -0
- package/dist/ui/file-preview/markdown/linking.d.ts +9 -0
- package/dist/ui/file-preview/markdown/linking.js +210 -0
- package/dist/ui/file-preview/markdown/outline.d.ts +7 -0
- package/dist/ui/file-preview/markdown/outline.js +40 -0
- package/dist/ui/file-preview/markdown/preview.d.ts +8 -0
- package/dist/ui/file-preview/markdown/preview.js +33 -0
- package/dist/ui/file-preview/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/markdown/toc.d.ts +11 -0
- package/dist/ui/file-preview/markdown/toc.js +75 -0
- package/dist/ui/file-preview/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/markdown/utils.js +15 -0
- package/dist/ui/file-preview/markdown/workspace-controller.d.ts +25 -0
- package/dist/ui/file-preview/markdown/workspace-controller.js +40 -0
- package/dist/ui/file-preview/preview-runtime.js +399 -13969
- package/dist/ui/file-preview/shared/preview-file-types.d.ts +1 -1
- package/dist/ui/file-preview/shared/preview-file-types.js +3 -1
- package/dist/ui/file-preview/src/App.d.ts +4 -0
- package/dist/ui/file-preview/src/App.js +564 -0
- package/dist/ui/file-preview/src/components/CodeViewer.d.ts +6 -0
- package/dist/ui/file-preview/src/components/CodeViewer.js +60 -0
- package/dist/ui/file-preview/src/components/HtmlRenderer.d.ts +8 -0
- package/dist/ui/file-preview/src/components/HtmlRenderer.js +45 -0
- package/dist/ui/file-preview/src/components/MarkdownRenderer.d.ts +1 -0
- package/dist/ui/file-preview/src/components/MarkdownRenderer.js +15 -0
- package/dist/ui/file-preview/src/components/editor-toolbar.d.ts +15 -0
- package/dist/ui/file-preview/src/components/editor-toolbar.js +384 -0
- package/dist/ui/file-preview/src/components/html-renderer.d.ts +1 -5
- package/dist/ui/file-preview/src/components/html-renderer.js +11 -27
- package/dist/ui/file-preview/src/components/markdown-editor.d.ts +29 -0
- package/dist/ui/file-preview/src/components/markdown-editor.js +535 -0
- package/dist/ui/file-preview/src/components/markdown-renderer.js +47 -9
- package/dist/ui/file-preview/src/directory-controller.d.ts +8 -0
- package/dist/ui/file-preview/src/directory-controller.js +233 -0
- package/dist/ui/file-preview/src/document-layout.d.ts +20 -0
- package/dist/ui/file-preview/src/document-layout.js +109 -0
- package/dist/ui/file-preview/src/document-outline.d.ts +17 -0
- package/dist/ui/file-preview/src/document-outline.js +97 -0
- package/dist/ui/file-preview/src/document-workspace.d.ts +19 -0
- package/dist/ui/file-preview/src/document-workspace.js +33 -0
- package/dist/ui/file-preview/src/file-type-handlers.d.ts +10 -0
- package/dist/ui/file-preview/src/file-type-handlers.js +98 -0
- package/dist/ui/file-preview/src/host/external-actions.d.ts +19 -0
- package/dist/ui/file-preview/src/host/external-actions.js +94 -0
- package/dist/ui/file-preview/src/host/selection-context.d.ts +9 -0
- package/dist/ui/file-preview/src/host/selection-context.js +106 -0
- package/dist/ui/file-preview/src/markdown/block-merge.d.ts +25 -0
- package/dist/ui/file-preview/src/markdown/block-merge.js +86 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.d.ts +40 -0
- package/dist/ui/file-preview/src/markdown/conflict-dialog.js +163 -0
- package/dist/ui/file-preview/src/markdown/controller.d.ts +38 -0
- package/dist/ui/file-preview/src/markdown/controller.js +921 -0
- package/dist/ui/file-preview/src/markdown/editor.d.ts +35 -0
- package/dist/ui/file-preview/src/markdown/editor.js +691 -0
- package/dist/ui/file-preview/src/markdown/link-modal.d.ts +13 -0
- package/dist/ui/file-preview/src/markdown/link-modal.js +213 -0
- package/dist/ui/file-preview/src/markdown/linking.d.ts +16 -0
- package/dist/ui/file-preview/src/markdown/linking.js +228 -0
- package/dist/ui/file-preview/src/markdown/outline.d.ts +2 -0
- package/dist/ui/file-preview/src/markdown/outline.js +16 -0
- package/dist/ui/file-preview/src/markdown/parser.d.ts +30 -0
- package/dist/ui/file-preview/src/markdown/parser.js +38 -0
- package/dist/ui/file-preview/src/markdown/preview.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/preview.js +20 -0
- package/dist/ui/file-preview/src/markdown/raw-editor.d.ts +8 -0
- package/dist/ui/file-preview/src/markdown/raw-editor.js +61 -0
- package/dist/ui/file-preview/src/markdown/selection-toolbar.d.ts +14 -0
- package/dist/ui/file-preview/src/markdown/selection-toolbar.js +128 -0
- package/dist/ui/file-preview/src/markdown/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown/toc.d.ts +11 -0
- package/dist/ui/file-preview/src/markdown/toc.js +75 -0
- package/dist/ui/file-preview/src/markdown/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown/utils.js +15 -0
- package/dist/ui/file-preview/src/markdown-workspace/editor.d.ts +36 -0
- package/dist/ui/file-preview/src/markdown-workspace/editor.js +643 -0
- package/dist/ui/file-preview/src/markdown-workspace/linking.d.ts +9 -0
- package/dist/ui/file-preview/src/markdown-workspace/linking.js +210 -0
- package/dist/ui/file-preview/src/markdown-workspace/outline.d.ts +7 -0
- package/dist/ui/file-preview/src/markdown-workspace/outline.js +40 -0
- package/dist/ui/file-preview/src/markdown-workspace/preview.d.ts +8 -0
- package/dist/ui/file-preview/src/markdown-workspace/preview.js +33 -0
- package/dist/ui/file-preview/src/markdown-workspace/slugify.d.ts +3 -0
- package/dist/ui/file-preview/src/markdown-workspace/slugify.js +31 -0
- package/dist/ui/file-preview/src/markdown-workspace/toc.d.ts +11 -0
- package/dist/ui/file-preview/src/markdown-workspace/toc.js +75 -0
- package/dist/ui/file-preview/src/markdown-workspace/utils.d.ts +1 -0
- package/dist/ui/file-preview/src/markdown-workspace/utils.js +15 -0
- package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.d.ts +25 -0
- package/dist/ui/file-preview/src/markdown-workspace/workspace-controller.js +40 -0
- package/dist/ui/file-preview/src/model.d.ts +34 -0
- package/dist/ui/file-preview/src/panel-actions.d.ts +17 -0
- package/dist/ui/file-preview/src/panel-actions.js +182 -0
- package/dist/ui/file-preview/src/path-utils.d.ts +6 -0
- package/dist/ui/file-preview/src/path-utils.js +64 -0
- package/dist/ui/file-preview/src/payload-utils.d.ts +11 -0
- package/dist/ui/file-preview/src/payload-utils.js +94 -0
- package/dist/ui/file-preview/styles.css +1144 -277
- package/dist/ui/file-preview/types.d.ts +1 -0
- package/dist/ui/file-preview/types.js +1 -0
- package/dist/ui/resources.d.ts +7 -0
- package/dist/ui/resources.js +16 -2
- package/dist/ui/server-integration.d.ts +13 -0
- package/dist/ui/server-integration.js +31 -0
- package/dist/ui/shared/ToolHeader.d.ts +9 -0
- package/dist/ui/shared/ToolHeader.js +29 -0
- package/dist/ui/shared/app-bootstrap.d.ts +9 -0
- package/dist/ui/shared/app-bootstrap.js +15 -0
- package/dist/ui/shared/compact-row.d.ts +11 -0
- package/dist/ui/shared/compact-row.js +18 -0
- package/dist/ui/shared/guards.d.ts +1 -0
- package/dist/ui/shared/guards.js +3 -0
- package/dist/ui/shared/host-context.d.ts +15 -0
- package/dist/ui/shared/host-context.js +51 -0
- package/dist/ui/shared/host-lifecycle.d.ts +1 -0
- package/dist/ui/shared/host-lifecycle.js +8 -2
- package/dist/ui/shared/tool-bridge.d.ts +30 -0
- package/dist/ui/shared/tool-bridge.js +137 -0
- package/dist/ui/shared/tool-shell.d.ts +9 -0
- package/dist/ui/shared/tool-shell.js +46 -4
- package/dist/ui/shared/ui-event-tracker.d.ts +9 -0
- package/dist/ui/shared/ui-event-tracker.js +27 -0
- package/dist/ui/shared/widget-state.d.ts +6 -1
- package/dist/ui/shared/widget-state.js +102 -4
- package/dist/utils/capture.js +3 -3
- package/dist/utils/files/base.d.ts +2 -0
- package/dist/utils/open-browser.js +1 -1
- package/dist/utils/ui-call-context.d.ts +8 -0
- package/dist/utils/ui-call-context.js +72 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +13 -4
- package/dist/data/spec-kit-prompts.json +0 -123
- package/dist/handlers/node-handlers.d.ts +0 -6
- package/dist/handlers/node-handlers.js +0 -73
- package/dist/handlers/test-crash-handler.d.ts +0 -11
- package/dist/handlers/test-crash-handler.js +0 -26
- package/dist/http-index.d.ts +0 -45
- package/dist/http-index.js +0 -51
- package/dist/http-server-auto-tunnel.js +0 -667
- package/dist/http-server-named-tunnel.d.ts +0 -2
- package/dist/http-server-named-tunnel.js +0 -167
- package/dist/http-server-tunnel.d.ts +0 -2
- package/dist/http-server-tunnel.js +0 -111
- package/dist/http-server.d.ts +0 -2
- package/dist/http-server.js +0 -270
- package/dist/index-oauth.d.ts +0 -2
- package/dist/index-oauth.js +0 -201
- package/dist/oauth/auth-middleware.d.ts +0 -20
- package/dist/oauth/auth-middleware.js +0 -62
- package/dist/oauth/index.d.ts +0 -3
- package/dist/oauth/index.js +0 -3
- package/dist/oauth/oauth-manager.d.ts +0 -80
- package/dist/oauth/oauth-manager.js +0 -179
- package/dist/oauth/oauth-routes.d.ts +0 -3
- package/dist/oauth/oauth-routes.js +0 -377
- package/dist/oauth/provider.d.ts +0 -22
- package/dist/oauth/provider.js +0 -124
- package/dist/oauth/server.d.ts +0 -18
- package/dist/oauth/server.js +0 -160
- package/dist/oauth/types.d.ts +0 -54
- package/dist/oauth/types.js +0 -2
- package/dist/remote-device/templates/auth-success.d.ts +0 -1
- package/dist/remote-device/templates/auth-success.js +0 -30
- package/dist/setup.log +0 -275
- package/dist/test-setup.js +0 -14
- package/dist/tools/docx/builders/html-builder.d.ts +0 -17
- package/dist/tools/docx/builders/html-builder.js +0 -92
- package/dist/tools/docx/builders/image.d.ts +0 -14
- package/dist/tools/docx/builders/image.js +0 -84
- package/dist/tools/docx/builders/index.d.ts +0 -11
- package/dist/tools/docx/builders/index.js +0 -11
- package/dist/tools/docx/builders/markdown-builder.d.ts +0 -2
- package/dist/tools/docx/builders/markdown-builder.js +0 -260
- package/dist/tools/docx/builders/paragraph.d.ts +0 -12
- package/dist/tools/docx/builders/paragraph.js +0 -29
- package/dist/tools/docx/builders/table.d.ts +0 -10
- package/dist/tools/docx/builders/table.js +0 -138
- package/dist/tools/docx/builders/utils.d.ts +0 -5
- package/dist/tools/docx/builders/utils.js +0 -18
- package/dist/tools/docx/constants.d.ts +0 -32
- package/dist/tools/docx/constants.js +0 -61
- package/dist/tools/docx/converters/markdown-to-html.d.ts +0 -17
- package/dist/tools/docx/converters/markdown-to-html.js +0 -111
- package/dist/tools/docx/create.d.ts +0 -21
- package/dist/tools/docx/create.js +0 -386
- package/dist/tools/docx/dom.d.ts +0 -139
- package/dist/tools/docx/dom.js +0 -448
- package/dist/tools/docx/errors.d.ts +0 -28
- package/dist/tools/docx/errors.js +0 -48
- package/dist/tools/docx/extractors/images.d.ts +0 -14
- package/dist/tools/docx/extractors/images.js +0 -40
- package/dist/tools/docx/extractors/metadata.d.ts +0 -14
- package/dist/tools/docx/extractors/metadata.js +0 -64
- package/dist/tools/docx/extractors/sections.d.ts +0 -14
- package/dist/tools/docx/extractors/sections.js +0 -61
- package/dist/tools/docx/html.d.ts +0 -17
- package/dist/tools/docx/html.js +0 -111
- package/dist/tools/docx/index.d.ts +0 -10
- package/dist/tools/docx/index.js +0 -10
- package/dist/tools/docx/markdown.d.ts +0 -84
- package/dist/tools/docx/markdown.js +0 -507
- package/dist/tools/docx/modify.d.ts +0 -28
- package/dist/tools/docx/modify.js +0 -271
- package/dist/tools/docx/operations/handlers/index.d.ts +0 -39
- package/dist/tools/docx/operations/handlers/index.js +0 -152
- package/dist/tools/docx/operations/html-manipulator.d.ts +0 -24
- package/dist/tools/docx/operations/html-manipulator.js +0 -352
- package/dist/tools/docx/operations/index.d.ts +0 -14
- package/dist/tools/docx/operations/index.js +0 -61
- package/dist/tools/docx/operations/operation-handlers.d.ts +0 -3
- package/dist/tools/docx/operations/operation-handlers.js +0 -67
- package/dist/tools/docx/operations/preprocessor.d.ts +0 -14
- package/dist/tools/docx/operations/preprocessor.js +0 -44
- package/dist/tools/docx/operations/xml-replacer.d.ts +0 -9
- package/dist/tools/docx/operations/xml-replacer.js +0 -35
- package/dist/tools/docx/operations.d.ts +0 -13
- package/dist/tools/docx/operations.js +0 -13
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.d.ts +0 -11
- package/dist/tools/docx/ops/delete-paragraph-at-body-index.js +0 -23
- package/dist/tools/docx/ops/header-replace-text-exact.d.ts +0 -13
- package/dist/tools/docx/ops/header-replace-text-exact.js +0 -55
- package/dist/tools/docx/ops/index.d.ts +0 -17
- package/dist/tools/docx/ops/index.js +0 -70
- package/dist/tools/docx/ops/insert-image-after-text.d.ts +0 -24
- package/dist/tools/docx/ops/insert-image-after-text.js +0 -128
- package/dist/tools/docx/ops/insert-paragraph-after-text.d.ts +0 -12
- package/dist/tools/docx/ops/insert-paragraph-after-text.js +0 -74
- package/dist/tools/docx/ops/insert-table-after-text.d.ts +0 -19
- package/dist/tools/docx/ops/insert-table-after-text.js +0 -57
- package/dist/tools/docx/ops/replace-hyperlink-url.d.ts +0 -12
- package/dist/tools/docx/ops/replace-hyperlink-url.js +0 -37
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.d.ts +0 -9
- package/dist/tools/docx/ops/replace-paragraph-at-body-index.js +0 -25
- package/dist/tools/docx/ops/replace-paragraph-text-exact.d.ts +0 -21
- package/dist/tools/docx/ops/replace-paragraph-text-exact.js +0 -36
- package/dist/tools/docx/ops/replace-table-cell-text.d.ts +0 -25
- package/dist/tools/docx/ops/replace-table-cell-text.js +0 -85
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.d.ts +0 -9
- package/dist/tools/docx/ops/set-color-for-paragraph-exact.js +0 -24
- package/dist/tools/docx/ops/set-color-for-style.d.ts +0 -13
- package/dist/tools/docx/ops/set-color-for-style.js +0 -31
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.d.ts +0 -8
- package/dist/tools/docx/ops/set-paragraph-style-at-body-index.js +0 -57
- package/dist/tools/docx/ops/table-set-cell-text.d.ts +0 -9
- package/dist/tools/docx/ops/table-set-cell-text.js +0 -40
- package/dist/tools/docx/parsers/image-extractor.d.ts +0 -18
- package/dist/tools/docx/parsers/image-extractor.js +0 -61
- package/dist/tools/docx/parsers/index.d.ts +0 -9
- package/dist/tools/docx/parsers/index.js +0 -9
- package/dist/tools/docx/parsers/paragraph-parser.d.ts +0 -2
- package/dist/tools/docx/parsers/paragraph-parser.js +0 -88
- package/dist/tools/docx/parsers/table-parser.d.ts +0 -9
- package/dist/tools/docx/parsers/table-parser.js +0 -72
- package/dist/tools/docx/parsers/xml-parser.d.ts +0 -25
- package/dist/tools/docx/parsers/xml-parser.js +0 -71
- package/dist/tools/docx/parsers/zip-reader.d.ts +0 -23
- package/dist/tools/docx/parsers/zip-reader.js +0 -52
- package/dist/tools/docx/read.d.ts +0 -27
- package/dist/tools/docx/read.js +0 -308
- package/dist/tools/docx/relationships.d.ts +0 -22
- package/dist/tools/docx/relationships.js +0 -76
- package/dist/tools/docx/structure.d.ts +0 -25
- package/dist/tools/docx/structure.js +0 -102
- package/dist/tools/docx/styled-html-parser.d.ts +0 -23
- package/dist/tools/docx/styled-html-parser.js +0 -1262
- package/dist/tools/docx/types.d.ts +0 -213
- package/dist/tools/docx/types.js +0 -5
- package/dist/tools/docx/utils/escaping.d.ts +0 -13
- package/dist/tools/docx/utils/escaping.js +0 -26
- package/dist/tools/docx/utils/images.d.ts +0 -9
- package/dist/tools/docx/utils/images.js +0 -26
- package/dist/tools/docx/utils/index.d.ts +0 -12
- package/dist/tools/docx/utils/index.js +0 -17
- package/dist/tools/docx/utils/markdown.d.ts +0 -13
- package/dist/tools/docx/utils/markdown.js +0 -32
- package/dist/tools/docx/utils/paths.d.ts +0 -15
- package/dist/tools/docx/utils/paths.js +0 -27
- package/dist/tools/docx/utils/versioning.d.ts +0 -25
- package/dist/tools/docx/utils/versioning.js +0 -55
- package/dist/tools/docx/utils.d.ts +0 -101
- package/dist/tools/docx/utils.js +0 -299
- package/dist/tools/docx/validate.d.ts +0 -33
- package/dist/tools/docx/validate.js +0 -49
- package/dist/tools/docx/validators.d.ts +0 -13
- package/dist/tools/docx/validators.js +0 -40
- package/dist/tools/docx/write.d.ts +0 -17
- package/dist/tools/docx/write.js +0 -88
- package/dist/tools/docx/xml-view-test.js +0 -63
- package/dist/tools/docx/xml-view.d.ts +0 -56
- package/dist/tools/docx/xml-view.js +0 -169
- package/dist/tools/docx/zip.d.ts +0 -21
- package/dist/tools/docx/zip.js +0 -35
- package/dist/tools/pdf-processor.js +0 -3
- package/dist/tools/search.d.ts +0 -32
- package/dist/tools/search.js +0 -202
- package/dist/ui/file-preview/src/app.d.ts +0 -4
- package/dist/ui/file-preview/src/app.js +0 -800
- package/dist/utils/crash-logger.d.ts +0 -18
- package/dist/utils/crash-logger.js +0 -44
- package/dist/utils/dedent.d.ts +0 -8
- package/dist/utils/dedent.js +0 -38
- /package/dist/{http-server-auto-tunnel.d.ts → ui/config-editor/main.d.ts} +0 -0
- /package/dist/{test-docx.d.ts → ui/config-editor/src/main.d.ts} +0 -0
- /package/dist/{tools/docx/xml-view-test.d.ts → ui/file-preview/main.d.ts} +0 -0
- /package/dist/ui/file-preview/src/components/{toolbar.d.ts → Toolbar.d.ts} +0 -0
- /package/dist/ui/file-preview/src/components/{toolbar.js → Toolbar.js} +0 -0
- /package/dist/{tools/pdf-processor.d.ts → ui/file-preview/src/model.js} +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { MarkdownLinkHeading, MarkdownLinkSearchItem } from './editor.js';
|
|
2
|
+
export declare function renderLinkModalHtml(): string;
|
|
3
|
+
export interface LinkModalHandle {
|
|
4
|
+
open(selectedText?: string): void;
|
|
5
|
+
close(): void;
|
|
6
|
+
destroy(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function attachLinkModal(options: {
|
|
9
|
+
root: HTMLElement;
|
|
10
|
+
searchLinks?: (query: string) => Promise<MarkdownLinkSearchItem[]>;
|
|
11
|
+
loadHeadings?: (filePath: string) => Promise<MarkdownLinkHeading[]>;
|
|
12
|
+
onInsert: (text: string) => void;
|
|
13
|
+
}): LinkModalHandle;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const SEARCH_DEBOUNCE_MS = 150;
|
|
2
|
+
export function renderLinkModalHtml() {
|
|
3
|
+
return `
|
|
4
|
+
<div id="markdown-link-modal" class="markdown-link-modal" hidden>
|
|
5
|
+
<div class="markdown-link-modal-card">
|
|
6
|
+
<div class="markdown-link-mode-tabs">
|
|
7
|
+
<button type="button" id="markdown-link-mode-file" class="markdown-link-mode-tab is-active">File</button>
|
|
8
|
+
<button type="button" id="markdown-link-mode-url" class="markdown-link-mode-tab">URL</button>
|
|
9
|
+
</div>
|
|
10
|
+
<div id="markdown-link-file-fields">
|
|
11
|
+
<label class="markdown-link-modal-label" for="markdown-link-search">Find note</label>
|
|
12
|
+
<input id="markdown-link-search" class="markdown-link-modal-input" type="text" placeholder="Search files..." />
|
|
13
|
+
<div id="markdown-link-results" class="markdown-link-results"></div>
|
|
14
|
+
<label class="markdown-link-modal-label" for="markdown-link-heading">Heading</label>
|
|
15
|
+
<select id="markdown-link-heading" class="markdown-link-modal-input markdown-link-modal-select">
|
|
16
|
+
<option value="">None</option>
|
|
17
|
+
</select>
|
|
18
|
+
<label class="markdown-link-modal-label" for="markdown-link-alias">Alias</label>
|
|
19
|
+
<input id="markdown-link-alias" class="markdown-link-modal-input" type="text" placeholder="Optional label" />
|
|
20
|
+
</div>
|
|
21
|
+
<div id="markdown-link-url-fields" hidden>
|
|
22
|
+
<label class="markdown-link-modal-label" for="markdown-link-input">URL</label>
|
|
23
|
+
<input id="markdown-link-input" class="markdown-link-modal-input" type="url" placeholder="https://example.com" />
|
|
24
|
+
<label class="markdown-link-modal-label" for="markdown-link-label">Label</label>
|
|
25
|
+
<input id="markdown-link-label" class="markdown-link-modal-input" type="text" placeholder="Optional label" />
|
|
26
|
+
</div>
|
|
27
|
+
<div class="markdown-link-modal-actions">
|
|
28
|
+
<button type="button" id="markdown-link-cancel" class="markdown-link-modal-button">Cancel</button>
|
|
29
|
+
<button type="button" id="markdown-link-apply" class="markdown-link-modal-button markdown-link-modal-button--primary">Insert</button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
export function attachLinkModal(options) {
|
|
36
|
+
const modalEl = options.root.querySelector('#markdown-link-modal');
|
|
37
|
+
if (!modalEl) {
|
|
38
|
+
return { open: () => undefined, close: () => undefined, destroy: () => undefined };
|
|
39
|
+
}
|
|
40
|
+
const modal = modalEl;
|
|
41
|
+
const tabFile = modal.querySelector('#markdown-link-mode-file');
|
|
42
|
+
const tabUrl = modal.querySelector('#markdown-link-mode-url');
|
|
43
|
+
const fileFields = modal.querySelector('#markdown-link-file-fields');
|
|
44
|
+
const urlFields = modal.querySelector('#markdown-link-url-fields');
|
|
45
|
+
const searchInput = modal.querySelector('#markdown-link-search');
|
|
46
|
+
const resultsEl = modal.querySelector('#markdown-link-results');
|
|
47
|
+
const headingSelect = modal.querySelector('#markdown-link-heading');
|
|
48
|
+
const aliasInput = modal.querySelector('#markdown-link-alias');
|
|
49
|
+
const urlInput = modal.querySelector('#markdown-link-input');
|
|
50
|
+
const labelInput = modal.querySelector('#markdown-link-label');
|
|
51
|
+
const applyBtn = modal.querySelector('#markdown-link-apply');
|
|
52
|
+
const cancelBtn = modal.querySelector('#markdown-link-cancel');
|
|
53
|
+
let mode = 'file';
|
|
54
|
+
let selectedItem = null;
|
|
55
|
+
let searchRequestId = 0;
|
|
56
|
+
let headingRequestId = 0;
|
|
57
|
+
let searchDebounce = null;
|
|
58
|
+
function setMode(next) {
|
|
59
|
+
mode = next;
|
|
60
|
+
tabFile.classList.toggle('is-active', mode === 'file');
|
|
61
|
+
tabUrl.classList.toggle('is-active', mode === 'url');
|
|
62
|
+
fileFields.hidden = mode !== 'file';
|
|
63
|
+
urlFields.hidden = mode !== 'url';
|
|
64
|
+
}
|
|
65
|
+
function renderResults(items, message) {
|
|
66
|
+
if (items.length === 0) {
|
|
67
|
+
resultsEl.innerHTML = `<div class="markdown-link-result markdown-link-result--empty">${message ?? 'No results'}</div>`;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
resultsEl.innerHTML = items.map((item, idx) => `
|
|
71
|
+
<button type="button" class="markdown-link-result${selectedItem?.path === item.path ? ' is-selected' : ''}" data-idx="${idx}">
|
|
72
|
+
<span class="markdown-link-result-title">${escapeHtml(item.title)}</span>
|
|
73
|
+
<span class="markdown-link-result-path">${escapeHtml(item.relativePath)}</span>
|
|
74
|
+
</button>
|
|
75
|
+
`).join('');
|
|
76
|
+
Array.from(resultsEl.querySelectorAll('[data-idx]')).forEach((btn) => {
|
|
77
|
+
btn.addEventListener('click', async () => {
|
|
78
|
+
const idx = Number(btn.dataset.idx);
|
|
79
|
+
selectedItem = items[idx] ?? null;
|
|
80
|
+
Array.from(resultsEl.querySelectorAll('.markdown-link-result')).forEach((el) => {
|
|
81
|
+
el.classList.toggle('is-selected', el === btn);
|
|
82
|
+
});
|
|
83
|
+
await loadHeadingsFor(selectedItem);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async function loadHeadingsFor(item) {
|
|
88
|
+
headingSelect.innerHTML = '<option value="">None</option>';
|
|
89
|
+
if (!item || !options.loadHeadings)
|
|
90
|
+
return;
|
|
91
|
+
const myRequest = ++headingRequestId;
|
|
92
|
+
try {
|
|
93
|
+
const headings = await options.loadHeadings(item.path);
|
|
94
|
+
if (myRequest !== headingRequestId)
|
|
95
|
+
return;
|
|
96
|
+
for (const heading of headings) {
|
|
97
|
+
const option = document.createElement('option');
|
|
98
|
+
option.value = heading.id;
|
|
99
|
+
option.textContent = heading.text;
|
|
100
|
+
headingSelect.appendChild(option);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// ignore — heading load failures shouldn't block insertion
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function runSearch(query) {
|
|
108
|
+
if (!options.searchLinks) {
|
|
109
|
+
renderResults([], 'Search unavailable');
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const myRequest = ++searchRequestId;
|
|
113
|
+
try {
|
|
114
|
+
const items = await options.searchLinks(query);
|
|
115
|
+
if (myRequest !== searchRequestId)
|
|
116
|
+
return;
|
|
117
|
+
renderResults(items, query ? 'No files match' : 'Start typing to search');
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
if (myRequest !== searchRequestId)
|
|
121
|
+
return;
|
|
122
|
+
renderResults([], `Search failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function apply() {
|
|
126
|
+
if (mode === 'url') {
|
|
127
|
+
const url = urlInput.value.trim();
|
|
128
|
+
if (!url)
|
|
129
|
+
return;
|
|
130
|
+
const label = labelInput.value.trim();
|
|
131
|
+
options.onInsert(label ? `[${label}](${url})` : `<${url}>`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
if (!selectedItem)
|
|
135
|
+
return;
|
|
136
|
+
const heading = headingSelect.value.trim();
|
|
137
|
+
const alias = aliasInput.value.trim();
|
|
138
|
+
let text = `[[${selectedItem.wikiPath}`;
|
|
139
|
+
if (heading)
|
|
140
|
+
text += `#${heading}`;
|
|
141
|
+
if (alias)
|
|
142
|
+
text += `|${alias}`;
|
|
143
|
+
text += ']]';
|
|
144
|
+
options.onInsert(text);
|
|
145
|
+
}
|
|
146
|
+
close();
|
|
147
|
+
}
|
|
148
|
+
function reset() {
|
|
149
|
+
setMode('file');
|
|
150
|
+
selectedItem = null;
|
|
151
|
+
searchInput.value = '';
|
|
152
|
+
aliasInput.value = '';
|
|
153
|
+
urlInput.value = '';
|
|
154
|
+
labelInput.value = '';
|
|
155
|
+
headingSelect.innerHTML = '<option value="">None</option>';
|
|
156
|
+
renderResults([], 'Start typing to search');
|
|
157
|
+
}
|
|
158
|
+
function open(selectedText) {
|
|
159
|
+
reset();
|
|
160
|
+
if (selectedText && /^https?:\/\//i.test(selectedText)) {
|
|
161
|
+
setMode('url');
|
|
162
|
+
urlInput.value = selectedText;
|
|
163
|
+
}
|
|
164
|
+
else if (selectedText) {
|
|
165
|
+
aliasInput.value = selectedText;
|
|
166
|
+
labelInput.value = selectedText;
|
|
167
|
+
}
|
|
168
|
+
modal.hidden = false;
|
|
169
|
+
(mode === 'file' ? searchInput : urlInput).focus();
|
|
170
|
+
}
|
|
171
|
+
function close() {
|
|
172
|
+
modal.hidden = true;
|
|
173
|
+
}
|
|
174
|
+
const onSearchInput = () => {
|
|
175
|
+
if (searchDebounce)
|
|
176
|
+
clearTimeout(searchDebounce);
|
|
177
|
+
searchDebounce = setTimeout(() => {
|
|
178
|
+
void runSearch(searchInput.value);
|
|
179
|
+
}, SEARCH_DEBOUNCE_MS);
|
|
180
|
+
};
|
|
181
|
+
const onKeyDown = (event) => {
|
|
182
|
+
if (event.key === 'Escape') {
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
close();
|
|
185
|
+
}
|
|
186
|
+
else if (event.key === 'Enter' && !event.shiftKey) {
|
|
187
|
+
event.preventDefault();
|
|
188
|
+
apply();
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
tabFile.addEventListener('click', () => setMode('file'));
|
|
192
|
+
tabUrl.addEventListener('click', () => setMode('url'));
|
|
193
|
+
searchInput.addEventListener('input', onSearchInput);
|
|
194
|
+
applyBtn.addEventListener('click', apply);
|
|
195
|
+
cancelBtn.addEventListener('click', close);
|
|
196
|
+
modal.addEventListener('keydown', onKeyDown);
|
|
197
|
+
return {
|
|
198
|
+
open,
|
|
199
|
+
close,
|
|
200
|
+
destroy: () => {
|
|
201
|
+
if (searchDebounce)
|
|
202
|
+
clearTimeout(searchDebounce);
|
|
203
|
+
close();
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
function escapeHtml(value) {
|
|
208
|
+
return value
|
|
209
|
+
.replace(/&/g, '&')
|
|
210
|
+
.replace(/</g, '<')
|
|
211
|
+
.replace(/>/g, '>')
|
|
212
|
+
.replace(/"/g, '"');
|
|
213
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface ResolvedMarkdownLink {
|
|
2
|
+
kind: 'external' | 'anchor' | 'file';
|
|
3
|
+
href: string;
|
|
4
|
+
url?: string;
|
|
5
|
+
targetPath?: string;
|
|
6
|
+
anchor?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Invert `rewriteWikiLinks`: convert `[alias](href "mcp-wiki:ENCODED")` links
|
|
10
|
+
* back to their original `[[...]]` form. Used when serializing a WYSIWYG
|
|
11
|
+
* edit session back to markdown — the `mcp-wiki:` title prefix is the
|
|
12
|
+
* round-trip marker written by `rewriteWikiLinks`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function restoreWikiLinks(markdown: string): string;
|
|
15
|
+
export declare function rewriteWikiLinks(source: string): string;
|
|
16
|
+
export declare function resolveMarkdownLink(currentPath: string, rawHref: string): ResolvedMarkdownLink;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { slugifyMarkdownHeading } from './slugify.js';
|
|
2
|
+
import { getParentDirectory, isWindowsAbsolutePath, normalizeFilePath, normalizePathSeparators } from '../path-utils.js';
|
|
3
|
+
const WIKI_LINK_PATTERN = /\[\[([^\]|#]*)(?:#([^\]|]+))?(?:\|([^\]]+))?\]\]/g;
|
|
4
|
+
const FENCE_PATTERN = /^(`{3,}|~{3,})/;
|
|
5
|
+
function encodeLinkPath(pathValue) {
|
|
6
|
+
return encodeURI(normalizePathSeparators(pathValue));
|
|
7
|
+
}
|
|
8
|
+
function safeDecodeURIComponent(value) {
|
|
9
|
+
try {
|
|
10
|
+
return decodeURIComponent(value);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function parseWikiLink(rawHref) {
|
|
17
|
+
const match = rawHref.match(/^\[\[([^\]|#]*)(?:#([^\]|]+))?(?:\|([^\]]+))?\]\]$/);
|
|
18
|
+
if (!match) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
path: (match[1] ?? '').trim(),
|
|
23
|
+
anchor: match[2]?.trim(),
|
|
24
|
+
alias: match[3]?.trim(),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function buildWikiDisplayText(link) {
|
|
28
|
+
if (link.alias && link.alias.length > 0) {
|
|
29
|
+
return link.alias;
|
|
30
|
+
}
|
|
31
|
+
if (link.path && link.anchor) {
|
|
32
|
+
return `${link.path}#${link.anchor}`;
|
|
33
|
+
}
|
|
34
|
+
if (link.path) {
|
|
35
|
+
return link.path;
|
|
36
|
+
}
|
|
37
|
+
return link.anchor ?? '';
|
|
38
|
+
}
|
|
39
|
+
function appendMarkdownExtension(pathValue) {
|
|
40
|
+
if (/\.[A-Za-z0-9_-]+$/.test(pathValue)) {
|
|
41
|
+
return pathValue;
|
|
42
|
+
}
|
|
43
|
+
return `${pathValue}.md`;
|
|
44
|
+
}
|
|
45
|
+
function buildWikiHref(link) {
|
|
46
|
+
if (!link.path) {
|
|
47
|
+
if (!link.anchor) {
|
|
48
|
+
return '#';
|
|
49
|
+
}
|
|
50
|
+
return `#${slugifyMarkdownHeading(link.anchor)}`;
|
|
51
|
+
}
|
|
52
|
+
const normalizedPath = appendMarkdownExtension(normalizePathSeparators(link.path));
|
|
53
|
+
const prefixedPath = normalizedPath.startsWith('./')
|
|
54
|
+
|| normalizedPath.startsWith('../')
|
|
55
|
+
|| normalizedPath.startsWith('/')
|
|
56
|
+
|| isWindowsAbsolutePath(normalizedPath)
|
|
57
|
+
? normalizedPath
|
|
58
|
+
: `./${normalizedPath}`;
|
|
59
|
+
const encodedPath = encodeLinkPath(prefixedPath);
|
|
60
|
+
if (!link.anchor) {
|
|
61
|
+
return encodedPath;
|
|
62
|
+
}
|
|
63
|
+
return `${encodedPath}#${slugifyMarkdownHeading(link.anchor)}`;
|
|
64
|
+
}
|
|
65
|
+
function rewriteWikiLinksInPlainText(segment) {
|
|
66
|
+
return segment.replace(WIKI_LINK_PATTERN, (match) => {
|
|
67
|
+
const parsed = parseWikiLink(match);
|
|
68
|
+
if (!parsed) {
|
|
69
|
+
return match;
|
|
70
|
+
}
|
|
71
|
+
const displayText = buildWikiDisplayText(parsed);
|
|
72
|
+
const href = buildWikiHref(parsed);
|
|
73
|
+
return `[${displayText}](${href} "mcp-wiki:${encodeURIComponent(match)}")`;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function replaceWikiLinksOutsideInlineCode(line) {
|
|
77
|
+
let result = '';
|
|
78
|
+
let cursor = 0;
|
|
79
|
+
while (cursor < line.length) {
|
|
80
|
+
const codeStart = line.indexOf('`', cursor);
|
|
81
|
+
if (codeStart === -1) {
|
|
82
|
+
result += rewriteWikiLinksInPlainText(line.slice(cursor));
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
result += rewriteWikiLinksInPlainText(line.slice(cursor, codeStart));
|
|
86
|
+
let delimiterEnd = codeStart;
|
|
87
|
+
while (delimiterEnd < line.length && line[delimiterEnd] === '`') {
|
|
88
|
+
delimiterEnd += 1;
|
|
89
|
+
}
|
|
90
|
+
const delimiter = line.slice(codeStart, delimiterEnd);
|
|
91
|
+
const codeEnd = line.indexOf(delimiter, delimiterEnd);
|
|
92
|
+
if (codeEnd === -1) {
|
|
93
|
+
result += line.slice(codeStart);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
result += line.slice(codeStart, codeEnd + delimiter.length);
|
|
97
|
+
cursor = codeEnd + delimiter.length;
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function decodeAnchorFragment(fragment) {
|
|
102
|
+
if (!fragment || fragment.length === 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return safeDecodeURIComponent(fragment);
|
|
106
|
+
}
|
|
107
|
+
function splitHref(rawHref) {
|
|
108
|
+
const hashIndex = rawHref.indexOf('#');
|
|
109
|
+
if (hashIndex === -1) {
|
|
110
|
+
return { pathPart: rawHref };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
pathPart: rawHref.slice(0, hashIndex),
|
|
114
|
+
anchorPart: rawHref.slice(hashIndex + 1),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function toDirectoryFileUrl(directoryPath) {
|
|
118
|
+
const normalized = normalizeFilePath(directoryPath);
|
|
119
|
+
const withTrailingSlash = normalized.endsWith('/') ? normalized : `${normalized}/`;
|
|
120
|
+
if (isWindowsAbsolutePath(withTrailingSlash)) {
|
|
121
|
+
return new URL(`file:///${encodeLinkPath(withTrailingSlash)}`);
|
|
122
|
+
}
|
|
123
|
+
if (withTrailingSlash.startsWith('/')) {
|
|
124
|
+
return new URL(`file://${encodeLinkPath(withTrailingSlash)}`);
|
|
125
|
+
}
|
|
126
|
+
return new URL(`file:///${encodeLinkPath(withTrailingSlash)}`);
|
|
127
|
+
}
|
|
128
|
+
function fromFileUrl(url) {
|
|
129
|
+
const decodedPath = safeDecodeURIComponent(url.pathname);
|
|
130
|
+
if (/^\/[A-Za-z]:\//.test(decodedPath)) {
|
|
131
|
+
return decodedPath.slice(1);
|
|
132
|
+
}
|
|
133
|
+
return decodedPath;
|
|
134
|
+
}
|
|
135
|
+
function isExternalHref(rawHref) {
|
|
136
|
+
return /^[A-Za-z][A-Za-z0-9+.-]*:/.test(rawHref) && !isWindowsAbsolutePath(rawHref);
|
|
137
|
+
}
|
|
138
|
+
function resolveFileTargetPath(currentPath, rawPath) {
|
|
139
|
+
const normalizedRawPath = normalizePathSeparators(safeDecodeURIComponent(rawPath));
|
|
140
|
+
if (normalizedRawPath.startsWith('/') || isWindowsAbsolutePath(normalizedRawPath)) {
|
|
141
|
+
return normalizeFilePath(normalizedRawPath);
|
|
142
|
+
}
|
|
143
|
+
const baseDirectory = getParentDirectory(currentPath);
|
|
144
|
+
if (baseDirectory === '.' && !normalizeFilePath(currentPath).includes('/')) {
|
|
145
|
+
return normalizeFilePath(normalizedRawPath);
|
|
146
|
+
}
|
|
147
|
+
const resolvedUrl = new URL(encodeURI(normalizedRawPath), toDirectoryFileUrl(baseDirectory));
|
|
148
|
+
return normalizeFilePath(fromFileUrl(resolvedUrl));
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Invert `rewriteWikiLinks`: convert `[alias](href "mcp-wiki:ENCODED")` links
|
|
152
|
+
* back to their original `[[...]]` form. Used when serializing a WYSIWYG
|
|
153
|
+
* edit session back to markdown — the `mcp-wiki:` title prefix is the
|
|
154
|
+
* round-trip marker written by `rewriteWikiLinks`.
|
|
155
|
+
*/
|
|
156
|
+
export function restoreWikiLinks(markdown) {
|
|
157
|
+
return markdown.replace(/\[([^\]]*)\]\(([^)\s]*)(?:\s+"mcp-wiki:([^"]+)")\)/g, (_, _alias, _href, encoded) => {
|
|
158
|
+
try {
|
|
159
|
+
return decodeURIComponent(encoded);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return `[[${encoded}]]`;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
export function rewriteWikiLinks(source) {
|
|
167
|
+
const lines = source.split('\n');
|
|
168
|
+
let activeFence = null;
|
|
169
|
+
return lines.map((line) => {
|
|
170
|
+
const trimmedStart = line.trimStart();
|
|
171
|
+
const fenceMatch = trimmedStart.match(FENCE_PATTERN);
|
|
172
|
+
if (fenceMatch) {
|
|
173
|
+
const marker = fenceMatch[1];
|
|
174
|
+
if (!activeFence) {
|
|
175
|
+
activeFence = marker;
|
|
176
|
+
}
|
|
177
|
+
else if (marker[0] === activeFence[0] && marker.length >= activeFence.length) {
|
|
178
|
+
activeFence = null;
|
|
179
|
+
}
|
|
180
|
+
return line;
|
|
181
|
+
}
|
|
182
|
+
if (activeFence) {
|
|
183
|
+
return line;
|
|
184
|
+
}
|
|
185
|
+
return replaceWikiLinksOutsideInlineCode(line);
|
|
186
|
+
}).join('\n');
|
|
187
|
+
}
|
|
188
|
+
export function resolveMarkdownLink(currentPath, rawHref) {
|
|
189
|
+
const wikiLink = parseWikiLink(rawHref);
|
|
190
|
+
if (wikiLink) {
|
|
191
|
+
const href = buildWikiHref(wikiLink);
|
|
192
|
+
if (href.startsWith('#')) {
|
|
193
|
+
return {
|
|
194
|
+
kind: 'anchor',
|
|
195
|
+
href: rawHref,
|
|
196
|
+
anchor: decodeAnchorFragment(href.slice(1)),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
const [pathPart, anchorPart] = href.split('#');
|
|
200
|
+
return {
|
|
201
|
+
kind: 'file',
|
|
202
|
+
href: rawHref,
|
|
203
|
+
targetPath: resolveFileTargetPath(currentPath, pathPart),
|
|
204
|
+
...(anchorPart ? { anchor: decodeAnchorFragment(anchorPart) } : {}),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (isExternalHref(rawHref)) {
|
|
208
|
+
return {
|
|
209
|
+
kind: 'external',
|
|
210
|
+
href: rawHref,
|
|
211
|
+
url: rawHref,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
if (rawHref.startsWith('#')) {
|
|
215
|
+
return {
|
|
216
|
+
kind: 'anchor',
|
|
217
|
+
href: rawHref,
|
|
218
|
+
anchor: decodeAnchorFragment(rawHref.slice(1)),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const { pathPart, anchorPart } = splitHref(rawHref);
|
|
222
|
+
return {
|
|
223
|
+
kind: 'file',
|
|
224
|
+
href: rawHref,
|
|
225
|
+
targetPath: resolveFileTargetPath(currentPath, pathPart),
|
|
226
|
+
...(anchorPart ? { anchor: decodeAnchorFragment(anchorPart) } : {}),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createMarkdownIt, prepareMarkdownSource, readHeadingProjection } from './parser.js';
|
|
2
|
+
import { createSlugTracker } from './slugify.js';
|
|
3
|
+
const outlineParser = createMarkdownIt();
|
|
4
|
+
export function extractMarkdownOutline(source) {
|
|
5
|
+
const tokens = outlineParser.parse(prepareMarkdownSource(source), {});
|
|
6
|
+
const nextSlug = createSlugTracker();
|
|
7
|
+
const outline = [];
|
|
8
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
9
|
+
const heading = readHeadingProjection(tokens, index, nextSlug);
|
|
10
|
+
if (!heading) {
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
outline.push(heading);
|
|
14
|
+
}
|
|
15
|
+
return outline;
|
|
16
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MarkdownSlugTracker } from './slugify.js';
|
|
2
|
+
export interface MarkdownToken {
|
|
3
|
+
type?: string;
|
|
4
|
+
tag?: string;
|
|
5
|
+
map?: number[];
|
|
6
|
+
children?: unknown;
|
|
7
|
+
content?: unknown;
|
|
8
|
+
attrSet?: (name: string, value: string) => void;
|
|
9
|
+
attrGet?: (name: string) => string | null;
|
|
10
|
+
attrs?: Array<[string, string]>;
|
|
11
|
+
}
|
|
12
|
+
interface MarkdownItInstance {
|
|
13
|
+
render: (source: string, env?: Record<string, unknown>) => string;
|
|
14
|
+
parse: (source: string, env?: Record<string, unknown>) => MarkdownToken[];
|
|
15
|
+
renderer: {
|
|
16
|
+
rules: Record<string, (...args: unknown[]) => string>;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface MarkdownHeadingProjection {
|
|
20
|
+
id: string;
|
|
21
|
+
text: string;
|
|
22
|
+
level: number;
|
|
23
|
+
line: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function createMarkdownIt(options?: {
|
|
26
|
+
highlight?: (code: string, language: string) => string;
|
|
27
|
+
}): MarkdownItInstance;
|
|
28
|
+
export declare function prepareMarkdownSource(source: string): string;
|
|
29
|
+
export declare function readHeadingProjection(tokens: MarkdownToken[], index: number, nextSlug: MarkdownSlugTracker): MarkdownHeadingProjection | null;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// markdown-it is intentionally typed locally here to avoid maintaining ambient module declarations.
|
|
2
|
+
import MarkdownIt from 'markdown-it';
|
|
3
|
+
import { rewriteWikiLinks } from './linking.js';
|
|
4
|
+
import { extractInlineText } from './utils.js';
|
|
5
|
+
const MarkdownItCtor = MarkdownIt;
|
|
6
|
+
export function createMarkdownIt(options = {}) {
|
|
7
|
+
return new MarkdownItCtor({
|
|
8
|
+
html: false,
|
|
9
|
+
linkify: true,
|
|
10
|
+
typographer: false,
|
|
11
|
+
...(options.highlight ? { highlight: options.highlight } : {}),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export function prepareMarkdownSource(source) {
|
|
15
|
+
return rewriteWikiLinks(source);
|
|
16
|
+
}
|
|
17
|
+
export function readHeadingProjection(tokens, index, nextSlug) {
|
|
18
|
+
const token = tokens[index];
|
|
19
|
+
if (token?.type !== 'heading_open' || typeof token.tag !== 'string') {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const level = Number.parseInt(token.tag.replace(/^h/i, ''), 10);
|
|
23
|
+
if (!Number.isFinite(level)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const inlineToken = tokens[index + 1];
|
|
27
|
+
const text = extractInlineText(inlineToken).trim();
|
|
28
|
+
if (!text) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const lineMap = Array.isArray(token.map) ? token.map : undefined;
|
|
32
|
+
return {
|
|
33
|
+
id: nextSlug(text),
|
|
34
|
+
text,
|
|
35
|
+
level,
|
|
36
|
+
line: typeof lineMap?.[0] === 'number' ? lineMap[0] + 1 : index + 1,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getRenderedMarkdownCopyText(content: string): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { renderMarkdown } from '../components/markdown-renderer.js';
|
|
2
|
+
export function getRenderedMarkdownCopyText(content) {
|
|
3
|
+
const html = renderMarkdown(content);
|
|
4
|
+
const normalizedHtml = html
|
|
5
|
+
.replace(/<\s*br\s*\/?>/gi, '\n')
|
|
6
|
+
.replace(/<\/p>/gi, '\n\n')
|
|
7
|
+
.replace(/<\/h[1-6]>/gi, '\n\n')
|
|
8
|
+
.replace(/<\/li>/gi, '\n')
|
|
9
|
+
.replace(/<li>/gi, '- ')
|
|
10
|
+
.replace(/<[^>]+>/g, '');
|
|
11
|
+
return normalizedHtml
|
|
12
|
+
.replace(/ /g, ' ')
|
|
13
|
+
.replace(/&/g, '&')
|
|
14
|
+
.replace(/</g, '<')
|
|
15
|
+
.replace(/>/g, '>')
|
|
16
|
+
.replace(/'/g, "'")
|
|
17
|
+
.replace(/"/g, '"')
|
|
18
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
19
|
+
.trim();
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MarkdownEditorHandle } from './editor.js';
|
|
2
|
+
export declare function mountCodeMirrorRaw(options: {
|
|
3
|
+
target: HTMLElement;
|
|
4
|
+
value: string;
|
|
5
|
+
initialScrollTop?: number;
|
|
6
|
+
onChange: (value: string) => void;
|
|
7
|
+
onBlur?: () => void;
|
|
8
|
+
}): MarkdownEditorHandle;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
|
2
|
+
import { markdown } from '@codemirror/lang-markdown';
|
|
3
|
+
import { defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
|
4
|
+
import { EditorState } from '@codemirror/state';
|
|
5
|
+
import { oneDark } from '@codemirror/theme-one-dark';
|
|
6
|
+
import { EditorView, keymap, lineNumbers } from '@codemirror/view';
|
|
7
|
+
export function mountCodeMirrorRaw(options) {
|
|
8
|
+
const state = EditorState.create({
|
|
9
|
+
doc: options.value,
|
|
10
|
+
extensions: [
|
|
11
|
+
lineNumbers(),
|
|
12
|
+
history(),
|
|
13
|
+
markdown(),
|
|
14
|
+
oneDark,
|
|
15
|
+
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
|
16
|
+
keymap.of([...defaultKeymap, ...historyKeymap]),
|
|
17
|
+
EditorView.lineWrapping,
|
|
18
|
+
EditorView.updateListener.of((update) => {
|
|
19
|
+
if (update.docChanged) {
|
|
20
|
+
options.onChange(update.state.doc.toString());
|
|
21
|
+
}
|
|
22
|
+
}),
|
|
23
|
+
EditorView.domEventHandlers({
|
|
24
|
+
blur: () => {
|
|
25
|
+
options.onBlur?.();
|
|
26
|
+
return false;
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
const view = new EditorView({ state, parent: options.target });
|
|
32
|
+
if (typeof options.initialScrollTop === 'number') {
|
|
33
|
+
view.scrollDOM.scrollTop = options.initialScrollTop;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
destroy: () => view.destroy(),
|
|
37
|
+
focus: () => view.focus(),
|
|
38
|
+
getValue: () => view.state.doc.toString(),
|
|
39
|
+
setValue: (value) => {
|
|
40
|
+
const current = view.state.doc.toString();
|
|
41
|
+
if (current === value)
|
|
42
|
+
return;
|
|
43
|
+
view.dispatch({
|
|
44
|
+
changes: { from: 0, to: view.state.doc.length, insert: value },
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
revealLine: (lineNumber) => {
|
|
48
|
+
const total = view.state.doc.lines;
|
|
49
|
+
const clamped = Math.max(1, Math.min(lineNumber, total));
|
|
50
|
+
const line = view.state.doc.line(clamped);
|
|
51
|
+
view.dispatch({
|
|
52
|
+
selection: { anchor: line.from },
|
|
53
|
+
scrollIntoView: true,
|
|
54
|
+
});
|
|
55
|
+
view.focus();
|
|
56
|
+
},
|
|
57
|
+
setScrollTop: (scrollTop) => {
|
|
58
|
+
view.scrollDOM.scrollTop = scrollTop;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface SelectionToolbarHandle {
|
|
2
|
+
destroy(): void;
|
|
3
|
+
}
|
|
4
|
+
export interface SelectionToolbarOptions {
|
|
5
|
+
editorRoot: HTMLElement;
|
|
6
|
+
onLinkRequest?: (selectedText: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Floating selection toolbar that appears above non-empty text selections
|
|
10
|
+
* inside the editor root. Uses `document.execCommand` for formatting so it
|
|
11
|
+
* works uniformly with ProseMirror (which intercepts beforeinput) and plain
|
|
12
|
+
* contenteditable.
|
|
13
|
+
*/
|
|
14
|
+
export declare function attachSelectionToolbar(options: SelectionToolbarOptions): SelectionToolbarHandle;
|