@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,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WYSIWYG markdown editor for the file preview. Makes rendered markdown
|
|
3
|
+
* blocks contentEditable and translates user changes back to markdown
|
|
4
|
+
* source, calling edit_block for surgical file updates.
|
|
5
|
+
*/
|
|
6
|
+
import { renderMarkdown } from './markdown-renderer.js';
|
|
7
|
+
import { createEditorToolbar, handleFormatKeydown } from './editor-toolbar.js';
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Markdown source → blocks parser
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
export function parseMarkdownBlocks(source) {
|
|
12
|
+
const lines = source.split('\n');
|
|
13
|
+
const blocks = [];
|
|
14
|
+
let i = 0;
|
|
15
|
+
while (i < lines.length) {
|
|
16
|
+
const line = lines[i];
|
|
17
|
+
// Blank line — skip
|
|
18
|
+
if (line.trim() === '') {
|
|
19
|
+
i++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
// Fenced code block (``` or ~~~)
|
|
23
|
+
const fenceMatch = line.match(/^(`{3,}|~{3,})/);
|
|
24
|
+
if (fenceMatch) {
|
|
25
|
+
const fence = fenceMatch[1];
|
|
26
|
+
const start = i;
|
|
27
|
+
i++;
|
|
28
|
+
while (i < lines.length && !lines[i].startsWith(fence))
|
|
29
|
+
i++;
|
|
30
|
+
if (i < lines.length)
|
|
31
|
+
i++; // closing fence
|
|
32
|
+
blocks.push({
|
|
33
|
+
type: 'code',
|
|
34
|
+
source: lines.slice(start, i).join('\n'),
|
|
35
|
+
startLine: start + 1,
|
|
36
|
+
endLine: i,
|
|
37
|
+
editable: false,
|
|
38
|
+
});
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Setext heading (underline with = or -)
|
|
42
|
+
if (i + 1 < lines.length &&
|
|
43
|
+
/^[=-]+\s*$/.test(lines[i + 1]) &&
|
|
44
|
+
line.trim() !== '') {
|
|
45
|
+
const level = lines[i + 1].startsWith('=') ? 1 : 2;
|
|
46
|
+
blocks.push({
|
|
47
|
+
type: 'heading',
|
|
48
|
+
source: lines.slice(i, i + 2).join('\n'),
|
|
49
|
+
startLine: i + 1,
|
|
50
|
+
endLine: i + 2,
|
|
51
|
+
level,
|
|
52
|
+
editable: true,
|
|
53
|
+
});
|
|
54
|
+
i += 2;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
// ATX heading
|
|
58
|
+
const headingMatch = line.match(/^(#{1,6})\s+(.*)/);
|
|
59
|
+
if (headingMatch) {
|
|
60
|
+
blocks.push({
|
|
61
|
+
type: 'heading',
|
|
62
|
+
source: line,
|
|
63
|
+
startLine: i + 1,
|
|
64
|
+
endLine: i + 1,
|
|
65
|
+
level: headingMatch[1].length,
|
|
66
|
+
editable: true,
|
|
67
|
+
});
|
|
68
|
+
i++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// Horizontal rule
|
|
72
|
+
if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line)) {
|
|
73
|
+
blocks.push({
|
|
74
|
+
type: 'hr',
|
|
75
|
+
source: line,
|
|
76
|
+
startLine: i + 1,
|
|
77
|
+
endLine: i + 1,
|
|
78
|
+
editable: false,
|
|
79
|
+
});
|
|
80
|
+
i++;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Blockquote
|
|
84
|
+
if (line.startsWith('>')) {
|
|
85
|
+
const start = i;
|
|
86
|
+
while (i < lines.length &&
|
|
87
|
+
(lines[i].startsWith('>') ||
|
|
88
|
+
(lines[i].trim() !== '' && !isBlockStart(lines[i]) && i > start))) {
|
|
89
|
+
i++;
|
|
90
|
+
if (i < lines.length && lines[i].trim() === '')
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
blocks.push({
|
|
94
|
+
type: 'blockquote',
|
|
95
|
+
source: lines.slice(start, i).join('\n'),
|
|
96
|
+
startLine: start + 1,
|
|
97
|
+
endLine: i,
|
|
98
|
+
editable: true,
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// List (unordered or ordered)
|
|
103
|
+
const listMatch = line.match(/^(\s*)([-*+]|\d+\.)\s/);
|
|
104
|
+
if (listMatch) {
|
|
105
|
+
const start = i;
|
|
106
|
+
const isOrdered = /\d+\./.test(listMatch[2]);
|
|
107
|
+
i++;
|
|
108
|
+
while (i < lines.length) {
|
|
109
|
+
const l = lines[i];
|
|
110
|
+
if (l.trim() === '') {
|
|
111
|
+
// Blank inside list — check if next line continues the list
|
|
112
|
+
if (i + 1 < lines.length && /^(\s*)([-*+]|\d+\.)\s/.test(lines[i + 1])) {
|
|
113
|
+
i++;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
if (/^(\s*)([-*+]|\d+\.)\s/.test(l) || /^\s+\S/.test(l)) {
|
|
119
|
+
i++;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
blocks.push({
|
|
126
|
+
type: 'list',
|
|
127
|
+
source: lines.slice(start, i).join('\n'),
|
|
128
|
+
startLine: start + 1,
|
|
129
|
+
endLine: i,
|
|
130
|
+
listType: isOrdered ? 'ol' : 'ul',
|
|
131
|
+
editable: true,
|
|
132
|
+
});
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
// Table (pipe-delimited with separator row)
|
|
136
|
+
if (line.includes('|') &&
|
|
137
|
+
i + 1 < lines.length &&
|
|
138
|
+
/^\|?\s*[-:]+[-| :]*$/.test(lines[i + 1])) {
|
|
139
|
+
const start = i;
|
|
140
|
+
while (i < lines.length && lines[i].includes('|') && lines[i].trim() !== '')
|
|
141
|
+
i++;
|
|
142
|
+
blocks.push({
|
|
143
|
+
type: 'table',
|
|
144
|
+
source: lines.slice(start, i).join('\n'),
|
|
145
|
+
startLine: start + 1,
|
|
146
|
+
endLine: i,
|
|
147
|
+
editable: false,
|
|
148
|
+
});
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// Paragraph (default — consecutive non-blank non-block-start lines)
|
|
152
|
+
{
|
|
153
|
+
const start = i;
|
|
154
|
+
i++;
|
|
155
|
+
while (i < lines.length && lines[i].trim() !== '' && !isBlockStart(lines[i])) {
|
|
156
|
+
i++;
|
|
157
|
+
}
|
|
158
|
+
blocks.push({
|
|
159
|
+
type: 'paragraph',
|
|
160
|
+
source: lines.slice(start, i).join('\n'),
|
|
161
|
+
startLine: start + 1,
|
|
162
|
+
endLine: i,
|
|
163
|
+
editable: true,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return blocks;
|
|
168
|
+
}
|
|
169
|
+
/** Returns true if a line starts a new block (heading, fence, hr, list, quote, table). */
|
|
170
|
+
function isBlockStart(line) {
|
|
171
|
+
if (/^(#{1,6})\s/.test(line))
|
|
172
|
+
return true;
|
|
173
|
+
if (/^(`{3,}|~{3,})/.test(line))
|
|
174
|
+
return true;
|
|
175
|
+
if (/^(-{3,}|\*{3,}|_{3,})\s*$/.test(line))
|
|
176
|
+
return true;
|
|
177
|
+
if (line.startsWith('>'))
|
|
178
|
+
return true;
|
|
179
|
+
if (/^(\s*)([-*+]|\d+\.)\s/.test(line))
|
|
180
|
+
return true;
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
// HTML → inline markdown conversion (for contentEditable round-tripping)
|
|
185
|
+
// ---------------------------------------------------------------------------
|
|
186
|
+
function nodeToMarkdown(node) {
|
|
187
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
188
|
+
return node.textContent ?? '';
|
|
189
|
+
}
|
|
190
|
+
if (node.nodeType !== Node.ELEMENT_NODE)
|
|
191
|
+
return '';
|
|
192
|
+
const el = node;
|
|
193
|
+
const tag = el.tagName.toLowerCase();
|
|
194
|
+
const children = Array.from(el.childNodes).map(nodeToMarkdown).join('');
|
|
195
|
+
switch (tag) {
|
|
196
|
+
case 'strong':
|
|
197
|
+
case 'b':
|
|
198
|
+
return `**${children}**`;
|
|
199
|
+
case 'em':
|
|
200
|
+
case 'i':
|
|
201
|
+
return `*${children}*`;
|
|
202
|
+
case 'code':
|
|
203
|
+
// Inline code only (not inside <pre>)
|
|
204
|
+
if (!el.closest('pre'))
|
|
205
|
+
return `\`${el.textContent ?? ''}\``;
|
|
206
|
+
return children;
|
|
207
|
+
case 'a': {
|
|
208
|
+
const href = el.getAttribute('href') ?? '';
|
|
209
|
+
return `[${children}](${href})`;
|
|
210
|
+
}
|
|
211
|
+
case 'img': {
|
|
212
|
+
const alt = el.getAttribute('alt') ?? '';
|
|
213
|
+
const src = el.getAttribute('src') ?? '';
|
|
214
|
+
return ``;
|
|
215
|
+
}
|
|
216
|
+
case 'br':
|
|
217
|
+
return '\n';
|
|
218
|
+
case 'del':
|
|
219
|
+
case 's':
|
|
220
|
+
case 'strike':
|
|
221
|
+
return `~~${children}~~`;
|
|
222
|
+
case 'span': {
|
|
223
|
+
// Preserve styled spans as inline HTML (color, font-size)
|
|
224
|
+
const style = el.getAttribute('style') ?? '';
|
|
225
|
+
if (style) {
|
|
226
|
+
return `<span style="${style}">${children}</span>`;
|
|
227
|
+
}
|
|
228
|
+
return children;
|
|
229
|
+
}
|
|
230
|
+
case 'font': {
|
|
231
|
+
// execCommand('foreColor') produces <font color="...">
|
|
232
|
+
// execCommand('fontSize') produces <font size="...">
|
|
233
|
+
const color = el.getAttribute('color');
|
|
234
|
+
const size = el.getAttribute('size');
|
|
235
|
+
if (color) {
|
|
236
|
+
return `<span style="color: ${color}">${children}</span>`;
|
|
237
|
+
}
|
|
238
|
+
if (size) {
|
|
239
|
+
return `<span style="font-size: ${size}">${children}</span>`;
|
|
240
|
+
}
|
|
241
|
+
return children;
|
|
242
|
+
}
|
|
243
|
+
default:
|
|
244
|
+
return children;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function extractInlineMarkdown(element) {
|
|
248
|
+
return Array.from(element.childNodes).map(nodeToMarkdown).join('').trim();
|
|
249
|
+
}
|
|
250
|
+
// ---------------------------------------------------------------------------
|
|
251
|
+
// Block → markdown reconstruction from edited DOM
|
|
252
|
+
// ---------------------------------------------------------------------------
|
|
253
|
+
function blockToMarkdown(block, editedEl) {
|
|
254
|
+
switch (block.type) {
|
|
255
|
+
case 'heading': {
|
|
256
|
+
const prefix = '#'.repeat(block.level ?? 1);
|
|
257
|
+
const text = extractInlineMarkdown(editedEl);
|
|
258
|
+
return `${prefix} ${text}`;
|
|
259
|
+
}
|
|
260
|
+
case 'paragraph': {
|
|
261
|
+
const pTags = editedEl.querySelectorAll('p');
|
|
262
|
+
if (pTags.length > 0) {
|
|
263
|
+
return Array.from(pTags)
|
|
264
|
+
.map(p => extractInlineMarkdown(p))
|
|
265
|
+
.join('\n\n');
|
|
266
|
+
}
|
|
267
|
+
return extractInlineMarkdown(editedEl);
|
|
268
|
+
}
|
|
269
|
+
case 'list': {
|
|
270
|
+
const listItems = editedEl.querySelectorAll(':scope > li');
|
|
271
|
+
const isOrdered = block.listType === 'ol';
|
|
272
|
+
return Array.from(listItems)
|
|
273
|
+
.map((li, idx) => {
|
|
274
|
+
const liEl = li;
|
|
275
|
+
// markdown-it wraps loose list content in <p>
|
|
276
|
+
const pEl = liEl.querySelector(':scope > p');
|
|
277
|
+
const text = extractInlineMarkdown(pEl ?? liEl);
|
|
278
|
+
const prefix = isOrdered ? `${idx + 1}. ` : '- ';
|
|
279
|
+
return `${prefix}${text}`;
|
|
280
|
+
})
|
|
281
|
+
.join('\n');
|
|
282
|
+
}
|
|
283
|
+
case 'blockquote': {
|
|
284
|
+
const paragraphs = editedEl.querySelectorAll('p');
|
|
285
|
+
let text;
|
|
286
|
+
if (paragraphs.length > 0) {
|
|
287
|
+
text = Array.from(paragraphs)
|
|
288
|
+
.map(p => extractInlineMarkdown(p))
|
|
289
|
+
.join('\n\n');
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
text = extractInlineMarkdown(editedEl);
|
|
293
|
+
}
|
|
294
|
+
return text
|
|
295
|
+
.split('\n')
|
|
296
|
+
.map(line => `> ${line}`)
|
|
297
|
+
.join('\n');
|
|
298
|
+
}
|
|
299
|
+
default:
|
|
300
|
+
return block.source;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
// Editable rendering — wraps each block in a container with data attributes
|
|
305
|
+
// ---------------------------------------------------------------------------
|
|
306
|
+
export function renderEditableMarkdown(source) {
|
|
307
|
+
const blocks = parseMarkdownBlocks(source);
|
|
308
|
+
let html = '';
|
|
309
|
+
for (const block of blocks) {
|
|
310
|
+
const rendered = renderMarkdown(block.source);
|
|
311
|
+
const editableClass = block.editable ? ' md-block--editable' : '';
|
|
312
|
+
const attrs = [
|
|
313
|
+
`data-md-start="${block.startLine}"`,
|
|
314
|
+
`data-md-end="${block.endLine}"`,
|
|
315
|
+
`data-md-type="${block.type}"`,
|
|
316
|
+
block.level !== undefined ? `data-md-level="${block.level}"` : '',
|
|
317
|
+
block.listType ? `data-md-list="${block.listType}"` : '',
|
|
318
|
+
]
|
|
319
|
+
.filter(Boolean)
|
|
320
|
+
.join(' ');
|
|
321
|
+
html += `<div class="md-block${editableClass}" ${attrs}>${rendered}</div>`;
|
|
322
|
+
}
|
|
323
|
+
return html;
|
|
324
|
+
}
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
// Editor handlers — attaches click/blur/keyboard editing to the DOM
|
|
327
|
+
// ---------------------------------------------------------------------------
|
|
328
|
+
/**
|
|
329
|
+
* Find the inner content element that should become contentEditable.
|
|
330
|
+
* Returns null for non-editable block types.
|
|
331
|
+
*/
|
|
332
|
+
function getEditableChild(blockEl) {
|
|
333
|
+
const type = blockEl.dataset.mdType;
|
|
334
|
+
switch (type) {
|
|
335
|
+
case 'heading':
|
|
336
|
+
return blockEl.querySelector('h1, h2, h3, h4, h5, h6');
|
|
337
|
+
case 'paragraph':
|
|
338
|
+
return blockEl.querySelector('p') ?? blockEl;
|
|
339
|
+
case 'list':
|
|
340
|
+
return blockEl.querySelector('ul, ol');
|
|
341
|
+
case 'blockquote':
|
|
342
|
+
return blockEl.querySelector('blockquote');
|
|
343
|
+
default:
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
function truncate(text, maxLen) {
|
|
348
|
+
const singleLine = text.replace(/\n/g, ' ').trim();
|
|
349
|
+
return singleLine.length > maxLen ? singleLine.slice(0, maxLen) + '...' : singleLine;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Attach WYSIWYG editing handlers to editable markdown blocks inside
|
|
353
|
+
* the given container. All editable blocks are contentEditable from the
|
|
354
|
+
* start — users can select and type immediately without an activation
|
|
355
|
+
* click. Changes are committed when focus leaves the editor.
|
|
356
|
+
*/
|
|
357
|
+
export function attachEditorHandlers(container, source, filePath, callbacks) {
|
|
358
|
+
const blocks = parseMarkdownBlocks(source);
|
|
359
|
+
const blockMap = new Map();
|
|
360
|
+
for (const block of blocks) {
|
|
361
|
+
blockMap.set(`${block.startLine}-${block.endLine}`, block);
|
|
362
|
+
}
|
|
363
|
+
// Snapshot each block's original innerHTML so we can detect changes
|
|
364
|
+
const originalHTML = new Map();
|
|
365
|
+
let activeBlockEl = null;
|
|
366
|
+
let activeEditEl = null;
|
|
367
|
+
const editHistory = [];
|
|
368
|
+
// Floating formatting toolbar
|
|
369
|
+
const toolbar = createEditorToolbar();
|
|
370
|
+
container.style.position = 'relative';
|
|
371
|
+
container.appendChild(toolbar.element);
|
|
372
|
+
// --- Make all editable blocks live from the start ---
|
|
373
|
+
const editableBlocks = container.querySelectorAll('.md-block--editable');
|
|
374
|
+
editableBlocks.forEach(blockEl => {
|
|
375
|
+
const editEl = getEditableChild(blockEl);
|
|
376
|
+
if (editEl) {
|
|
377
|
+
editEl.contentEditable = 'true';
|
|
378
|
+
const key = blockKey(blockEl);
|
|
379
|
+
originalHTML.set(key, editEl.innerHTML);
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
function blockKey(el) {
|
|
383
|
+
return `${el.dataset.mdStart}-${el.dataset.mdEnd}`;
|
|
384
|
+
}
|
|
385
|
+
async function commitBlock(blockEl, editEl) {
|
|
386
|
+
const key = blockKey(blockEl);
|
|
387
|
+
const block = blockMap.get(key);
|
|
388
|
+
if (!block)
|
|
389
|
+
return;
|
|
390
|
+
const origHTML = originalHTML.get(key);
|
|
391
|
+
if (editEl.innerHTML === origHTML)
|
|
392
|
+
return; // No change
|
|
393
|
+
const newMarkdown = blockToMarkdown(block, editEl);
|
|
394
|
+
if (newMarkdown === block.source)
|
|
395
|
+
return;
|
|
396
|
+
callbacks.trackEvent?.('md_block_edited', {
|
|
397
|
+
block_type: block.type,
|
|
398
|
+
line: block.startLine,
|
|
399
|
+
});
|
|
400
|
+
const prevSource = block.source;
|
|
401
|
+
try {
|
|
402
|
+
await callbacks.callTool('edit_block', {
|
|
403
|
+
file_path: filePath,
|
|
404
|
+
old_string: block.source,
|
|
405
|
+
new_string: newMarkdown,
|
|
406
|
+
});
|
|
407
|
+
block.source = newMarkdown;
|
|
408
|
+
editHistory.push({
|
|
409
|
+
oldText: prevSource,
|
|
410
|
+
newText: newMarkdown,
|
|
411
|
+
line: block.startLine,
|
|
412
|
+
});
|
|
413
|
+
// Re-render the block and make it editable again
|
|
414
|
+
const freshHtml = renderMarkdown(newMarkdown);
|
|
415
|
+
blockEl.innerHTML = freshHtml;
|
|
416
|
+
const newEditEl = getEditableChild(blockEl);
|
|
417
|
+
if (newEditEl) {
|
|
418
|
+
newEditEl.contentEditable = 'true';
|
|
419
|
+
originalHTML.set(key, newEditEl.innerHTML);
|
|
420
|
+
}
|
|
421
|
+
const recent = editHistory.slice(-5).map(e => ` - Line ${e.line}: "${truncate(e.oldText, 50)}" -> "${truncate(e.newText, 50)}"`);
|
|
422
|
+
callbacks.updateContext(`User edited ${filePath} via preview editor (${editHistory.length} edit${editHistory.length !== 1 ? 's' : ''}):\n${recent.join('\n')}`);
|
|
423
|
+
}
|
|
424
|
+
catch (err) {
|
|
425
|
+
// Revert on failure
|
|
426
|
+
if (origHTML !== undefined)
|
|
427
|
+
editEl.innerHTML = origHTML;
|
|
428
|
+
callbacks.trackEvent?.('md_edit_failed', {
|
|
429
|
+
block_type: block.type,
|
|
430
|
+
error: String(err),
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
// --- Track which block the user is in via focusin ---
|
|
435
|
+
function handleFocusIn(e) {
|
|
436
|
+
const target = e.target;
|
|
437
|
+
const blockEl = target.closest('.md-block--editable');
|
|
438
|
+
if (!blockEl)
|
|
439
|
+
return;
|
|
440
|
+
if (blockEl !== activeBlockEl) {
|
|
441
|
+
// Switching blocks — commit the previous one
|
|
442
|
+
if (activeBlockEl && activeEditEl) {
|
|
443
|
+
void commitBlock(activeBlockEl, activeEditEl);
|
|
444
|
+
}
|
|
445
|
+
activeBlockEl = blockEl;
|
|
446
|
+
activeEditEl = getEditableChild(blockEl);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// --- Commit when focus leaves the editor entirely ---
|
|
450
|
+
function handleFocusOut(e) {
|
|
451
|
+
const related = e.relatedTarget;
|
|
452
|
+
// Focus stayed inside the editor or toolbar — don't commit
|
|
453
|
+
if (related && (container.contains(related) || toolbar.element.contains(related)))
|
|
454
|
+
return;
|
|
455
|
+
toolbar.hide();
|
|
456
|
+
if (activeBlockEl && activeEditEl) {
|
|
457
|
+
void commitBlock(activeBlockEl, activeEditEl);
|
|
458
|
+
}
|
|
459
|
+
activeBlockEl = null;
|
|
460
|
+
activeEditEl = null;
|
|
461
|
+
}
|
|
462
|
+
// --- Keyboard shortcuts ---
|
|
463
|
+
function handleKeydown(e) {
|
|
464
|
+
if (!activeBlockEl || !activeEditEl)
|
|
465
|
+
return;
|
|
466
|
+
if (handleFormatKeydown(e))
|
|
467
|
+
return;
|
|
468
|
+
// Enter in headings → commit
|
|
469
|
+
if (e.key === 'Enter' && activeBlockEl.dataset.mdType === 'heading') {
|
|
470
|
+
e.preventDefault();
|
|
471
|
+
toolbar.hide();
|
|
472
|
+
void commitBlock(activeBlockEl, activeEditEl);
|
|
473
|
+
activeBlockEl = null;
|
|
474
|
+
activeEditEl = null;
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
// Escape → revert this block
|
|
478
|
+
if (e.key === 'Escape') {
|
|
479
|
+
e.preventDefault();
|
|
480
|
+
toolbar.hide();
|
|
481
|
+
const key = blockKey(activeBlockEl);
|
|
482
|
+
const origHTML = originalHTML.get(key);
|
|
483
|
+
if (origHTML !== undefined && activeEditEl) {
|
|
484
|
+
activeEditEl.innerHTML = origHTML;
|
|
485
|
+
}
|
|
486
|
+
activeEditEl?.blur();
|
|
487
|
+
activeBlockEl = null;
|
|
488
|
+
activeEditEl = null;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
// --- Toolbar: show on any text selection in any editable block ---
|
|
492
|
+
function handleSelectionChange() {
|
|
493
|
+
const sel = document.getSelection();
|
|
494
|
+
if (!sel || !sel.rangeCount)
|
|
495
|
+
return;
|
|
496
|
+
if (sel.isCollapsed) {
|
|
497
|
+
// Keep toolbar visible if a dropdown is open (user is picking
|
|
498
|
+
// a color/size), otherwise hide it.
|
|
499
|
+
if (toolbar.isVisible && !toolbar.hasOpenDropdown) {
|
|
500
|
+
toolbar.hide();
|
|
501
|
+
}
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
// Check if the selection is within any editable block in this editor
|
|
505
|
+
const anchor = sel.anchorNode;
|
|
506
|
+
const focus = sel.focusNode;
|
|
507
|
+
if (!anchor || !focus)
|
|
508
|
+
return;
|
|
509
|
+
if (!container.contains(anchor) || !container.contains(focus))
|
|
510
|
+
return;
|
|
511
|
+
const editEl = anchor.parentElement?.closest('[contenteditable="true"]');
|
|
512
|
+
if (!editEl || !container.contains(editEl))
|
|
513
|
+
return;
|
|
514
|
+
const range = sel.getRangeAt(0);
|
|
515
|
+
const selRect = range.getBoundingClientRect();
|
|
516
|
+
const containerRect = container.getBoundingClientRect();
|
|
517
|
+
toolbar.show(selRect, containerRect);
|
|
518
|
+
}
|
|
519
|
+
container.addEventListener('focusin', handleFocusIn);
|
|
520
|
+
container.addEventListener('focusout', handleFocusOut);
|
|
521
|
+
container.addEventListener('keydown', handleKeydown);
|
|
522
|
+
document.addEventListener('selectionchange', handleSelectionChange);
|
|
523
|
+
return {
|
|
524
|
+
cleanup() {
|
|
525
|
+
container.removeEventListener('focusin', handleFocusIn);
|
|
526
|
+
container.removeEventListener('focusout', handleFocusOut);
|
|
527
|
+
container.removeEventListener('keydown', handleKeydown);
|
|
528
|
+
document.removeEventListener('selectionchange', handleSelectionChange);
|
|
529
|
+
toolbar.destroy();
|
|
530
|
+
},
|
|
531
|
+
isEditing() {
|
|
532
|
+
return activeEditEl !== null;
|
|
533
|
+
},
|
|
534
|
+
};
|
|
535
|
+
}
|
|
@@ -1,21 +1,59 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markdown rendering pipeline for preview mode. It configures markdown-it and highlighting so markdown content is rendered consistently with code block support.
|
|
3
3
|
*/
|
|
4
|
-
// markdown-it is intentionally typed locally here to avoid maintaining global ambient module declarations.
|
|
5
|
-
// @ts-expect-error markdown-it does not provide local TypeScript typings in this setup.
|
|
6
|
-
import MarkdownIt from 'markdown-it';
|
|
7
4
|
import { highlightSource } from './highlighting.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
linkify: true,
|
|
12
|
-
typographer: false,
|
|
5
|
+
import { createMarkdownIt, prepareMarkdownSource, readHeadingProjection } from '../markdown/parser.js';
|
|
6
|
+
import { createSlugTracker } from '../markdown/slugify.js';
|
|
7
|
+
const markdown = createMarkdownIt({
|
|
13
8
|
highlight(code, language) {
|
|
14
9
|
const normalizedLanguage = (language || 'text').toLowerCase();
|
|
15
10
|
const highlighted = highlightSource(code, normalizedLanguage);
|
|
16
11
|
return `<pre class="code-viewer"><code class="hljs language-${normalizedLanguage}">${highlighted}</code></pre>`;
|
|
17
12
|
}
|
|
18
13
|
});
|
|
14
|
+
const renderHeadingOpen = markdown.renderer.rules.heading_open;
|
|
15
|
+
markdown.renderer.rules.heading_open = (...args) => {
|
|
16
|
+
const tokens = args[0];
|
|
17
|
+
const index = args[1];
|
|
18
|
+
const options = args[2];
|
|
19
|
+
const environment = args[3] ?? {};
|
|
20
|
+
const self = args[4];
|
|
21
|
+
const nextSlug = typeof environment.nextSlug === 'function'
|
|
22
|
+
? environment.nextSlug
|
|
23
|
+
: createSlugTracker();
|
|
24
|
+
environment.nextSlug = nextSlug;
|
|
25
|
+
const heading = readHeadingProjection(tokens, index, nextSlug);
|
|
26
|
+
const token = tokens[index];
|
|
27
|
+
if (heading) {
|
|
28
|
+
token.attrSet?.('id', heading.id);
|
|
29
|
+
token.attrSet?.('data-heading-id', heading.id);
|
|
30
|
+
}
|
|
31
|
+
if (typeof renderHeadingOpen === 'function') {
|
|
32
|
+
return renderHeadingOpen(...args);
|
|
33
|
+
}
|
|
34
|
+
return self.renderToken(tokens, index, options);
|
|
35
|
+
};
|
|
36
|
+
const renderLinkOpen = markdown.renderer.rules.link_open;
|
|
37
|
+
markdown.renderer.rules.link_open = (...args) => {
|
|
38
|
+
const tokens = args[0];
|
|
39
|
+
const index = args[1];
|
|
40
|
+
const options = args[2];
|
|
41
|
+
const self = args[4];
|
|
42
|
+
const token = tokens[index];
|
|
43
|
+
token.attrSet?.('data-markdown-link', 'true');
|
|
44
|
+
const title = token.attrGet?.('title');
|
|
45
|
+
if (title?.startsWith('mcp-wiki:')) {
|
|
46
|
+
const rawWikiLink = decodeURIComponent(title.slice('mcp-wiki:'.length));
|
|
47
|
+
token.attrSet?.('data-wiki-link', rawWikiLink);
|
|
48
|
+
if (Array.isArray(token.attrs)) {
|
|
49
|
+
token.attrs = token.attrs.filter(([name]) => name !== 'title');
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (typeof renderLinkOpen === 'function') {
|
|
53
|
+
return renderLinkOpen(...args);
|
|
54
|
+
}
|
|
55
|
+
return self.renderToken(tokens, index, options);
|
|
56
|
+
};
|
|
19
57
|
export function renderMarkdown(content) {
|
|
20
|
-
return markdown.render(content);
|
|
58
|
+
return markdown.render(prepareMarkdownSource(content), { nextSlug: createSlugTracker() });
|
|
21
59
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RenderBodyResult, RenderPayload } from './model.js';
|
|
2
|
+
export declare function renderDirectoryBody(content: string, rootPath: string): RenderBodyResult;
|
|
3
|
+
export declare function attachDirectoryHandlers(options: {
|
|
4
|
+
container: HTMLElement;
|
|
5
|
+
callTool?: (name: string, args: Record<string, unknown>) => Promise<unknown | undefined>;
|
|
6
|
+
buildOpenInFolderCommand: (filePath: string) => string | undefined;
|
|
7
|
+
onOpenPayload: (payload: RenderPayload) => void;
|
|
8
|
+
}): void;
|