@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,233 @@
|
|
|
1
|
+
import { escapeHtml } from './components/highlighting.js';
|
|
2
|
+
import { buildRenderPayload, extractToolText } from './payload-utils.js';
|
|
3
|
+
function parseDirectoryEntries(content) {
|
|
4
|
+
const lines = content.split('\n');
|
|
5
|
+
const hintLines = [];
|
|
6
|
+
const entryLines = [];
|
|
7
|
+
for (const line of lines) {
|
|
8
|
+
if (/^\[(DIR|FILE|DENIED|WARNING)\]/.test(line.trim())) {
|
|
9
|
+
entryLines.push(line.trim());
|
|
10
|
+
}
|
|
11
|
+
else if (entryLines.length === 0) {
|
|
12
|
+
hintLines.push(line);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const flat = [];
|
|
16
|
+
for (const line of entryLines) {
|
|
17
|
+
if (line.startsWith('[WARNING]')) {
|
|
18
|
+
const warnBody = line.replace(/^\[WARNING\]\s*/, '');
|
|
19
|
+
const colonIdx = warnBody.indexOf(':');
|
|
20
|
+
const dirName = colonIdx >= 0 ? warnBody.slice(0, colonIdx).trim() : '';
|
|
21
|
+
const msg = colonIdx >= 0 ? warnBody.slice(colonIdx + 1).trim() : warnBody;
|
|
22
|
+
const parts = dirName.replace(/\\/g, '/').split('/').filter(Boolean);
|
|
23
|
+
flat.push({
|
|
24
|
+
name: dirName,
|
|
25
|
+
fullPath: dirName,
|
|
26
|
+
isDir: false,
|
|
27
|
+
isDenied: false,
|
|
28
|
+
isWarning: true,
|
|
29
|
+
warningText: msg,
|
|
30
|
+
depth: parts.length,
|
|
31
|
+
});
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const isDir = line.startsWith('[DIR]');
|
|
35
|
+
const isDenied = line.startsWith('[DENIED]');
|
|
36
|
+
const name = line.replace(/^\[(DIR|FILE|DENIED)\]\s*/, '');
|
|
37
|
+
const parts = name.replace(/\\/g, '/').split('/');
|
|
38
|
+
flat.push({
|
|
39
|
+
name,
|
|
40
|
+
fullPath: name,
|
|
41
|
+
isDir,
|
|
42
|
+
isDenied,
|
|
43
|
+
isWarning: false,
|
|
44
|
+
warningText: '',
|
|
45
|
+
depth: parts.length - 1,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const root = [];
|
|
49
|
+
const stack = [root];
|
|
50
|
+
for (const item of flat) {
|
|
51
|
+
const baseName = item.fullPath.replace(/\\/g, '/').split('/').pop() ?? item.fullPath;
|
|
52
|
+
const entry = {
|
|
53
|
+
name: baseName,
|
|
54
|
+
isDir: item.isDir,
|
|
55
|
+
isDenied: item.isDenied,
|
|
56
|
+
isWarning: item.isWarning,
|
|
57
|
+
warningText: item.warningText,
|
|
58
|
+
children: [],
|
|
59
|
+
relativePath: item.fullPath,
|
|
60
|
+
};
|
|
61
|
+
while (stack.length > item.depth + 1) {
|
|
62
|
+
stack.pop();
|
|
63
|
+
}
|
|
64
|
+
const parent = stack[stack.length - 1];
|
|
65
|
+
parent.push(entry);
|
|
66
|
+
if (item.isDir) {
|
|
67
|
+
stack.push(entry.children);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return { hint: hintLines.join('\n').trim(), entries: root };
|
|
71
|
+
}
|
|
72
|
+
let dirEntryIdCounter = 0;
|
|
73
|
+
function renderDirTree(entries, rootPath) {
|
|
74
|
+
if (entries.length === 0) {
|
|
75
|
+
return '<div class="dir-tree"><span class="dir-empty">Empty directory</span></div>';
|
|
76
|
+
}
|
|
77
|
+
function renderEntries(items) {
|
|
78
|
+
return items.map((item) => {
|
|
79
|
+
const id = `de-${dirEntryIdCounter++}`;
|
|
80
|
+
const fullPath = `${rootPath}/${item.relativePath.replace(/\\/g, '/')}`;
|
|
81
|
+
const escapedPath = escapeHtml(fullPath);
|
|
82
|
+
if (item.isWarning) {
|
|
83
|
+
return `<div class="dir-entry"><button class="dir-row dir-row-warning dir-load-more" data-loadpath="${escapedPath}"><span class="dir-warning-icon">⚠️</span> <span class="dir-warning-text">${escapeHtml(item.warningText)} — click to load all</span></button></div>`;
|
|
84
|
+
}
|
|
85
|
+
if (item.isDenied) {
|
|
86
|
+
return `<div class="dir-entry"><span class="dir-icon">🚫</span> <span class="dir-name-denied">${escapeHtml(item.name)}</span></div>`;
|
|
87
|
+
}
|
|
88
|
+
if (item.isDir) {
|
|
89
|
+
const hasChildren = item.children.length > 0;
|
|
90
|
+
const chevron = `<span class="dir-chevron${hasChildren ? ' expanded' : ''}">${hasChildren ? '▼' : '▶'}</span>`;
|
|
91
|
+
const openButton = `<button class="dir-open-btn" data-openpath="${escapedPath}" title="Open in Finder">📂</button>`;
|
|
92
|
+
const childrenHtml = hasChildren ? `<div class="dir-children" id="${id}-ch">${renderEntries(item.children)}</div>` : '';
|
|
93
|
+
return `<div class="dir-entry-group" id="${id}"><div class="dir-row dir-row-folder" data-path="${escapedPath}" data-eid="${id}" data-loaded="${hasChildren}">${chevron} <span class="dir-icon">📁</span> <span class="dir-name">${escapeHtml(item.name)}</span>${openButton}</div>${childrenHtml}</div>`;
|
|
94
|
+
}
|
|
95
|
+
return `<div class="dir-entry"><div class="dir-row dir-row-file" data-path="${escapedPath}"><span class="file-icon">📄</span> <span class="file-name">${escapeHtml(item.name)}</span></div></div>`;
|
|
96
|
+
}).join('');
|
|
97
|
+
}
|
|
98
|
+
return `<div class="dir-tree">${renderEntries(entries)}</div>`;
|
|
99
|
+
}
|
|
100
|
+
export function renderDirectoryBody(content, rootPath) {
|
|
101
|
+
dirEntryIdCounter = 0;
|
|
102
|
+
const { hint, entries } = parseDirectoryEntries(content);
|
|
103
|
+
return {
|
|
104
|
+
notice: hint || undefined,
|
|
105
|
+
html: `<div class="panel-content directory-content">${renderDirTree(entries, rootPath)}</div>`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
export function attachDirectoryHandlers(options) {
|
|
109
|
+
const tree = options.container.querySelector('.dir-tree');
|
|
110
|
+
if (!tree) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
tree.addEventListener('click', async (event) => {
|
|
114
|
+
const openBtn = event.target.closest('.dir-open-btn');
|
|
115
|
+
if (openBtn) {
|
|
116
|
+
event.stopPropagation();
|
|
117
|
+
const openPath = openBtn.dataset.openpath;
|
|
118
|
+
if (!openPath) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const command = options.buildOpenInFolderCommand(openPath);
|
|
122
|
+
if (command) {
|
|
123
|
+
try {
|
|
124
|
+
await options.callTool?.('start_process', { command, timeout_ms: 12000 });
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Keep UI stable if opening folder fails.
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const loadMoreBtn = event.target.closest('.dir-load-more');
|
|
133
|
+
if (loadMoreBtn) {
|
|
134
|
+
event.stopPropagation();
|
|
135
|
+
const loadPath = loadMoreBtn.dataset.loadpath;
|
|
136
|
+
if (!loadPath) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Loading…';
|
|
140
|
+
loadMoreBtn.disabled = true;
|
|
141
|
+
try {
|
|
142
|
+
const result = await options.callTool?.('list_directory', { path: loadPath, depth: 1 });
|
|
143
|
+
const text = extractToolText(result) ?? '';
|
|
144
|
+
if (text) {
|
|
145
|
+
const parsed = parseDirectoryEntries(text);
|
|
146
|
+
const html = renderDirTree(parsed.entries, loadPath);
|
|
147
|
+
const parentChildren = loadMoreBtn.closest('.dir-children');
|
|
148
|
+
if (parentChildren) {
|
|
149
|
+
const temp = document.createElement('div');
|
|
150
|
+
temp.innerHTML = html;
|
|
151
|
+
const inner = temp.querySelector('.dir-tree');
|
|
152
|
+
parentChildren.innerHTML = inner ? inner.innerHTML : '';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
loadMoreBtn.querySelector('.dir-warning-text').textContent = 'Failed to load';
|
|
158
|
+
loadMoreBtn.disabled = false;
|
|
159
|
+
}
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const target = event.target.closest('.dir-row');
|
|
163
|
+
if (!target) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
const fullPath = target.dataset.path;
|
|
167
|
+
if (!fullPath) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (target.classList.contains('dir-row-folder')) {
|
|
171
|
+
const entryId = target.dataset.eid;
|
|
172
|
+
if (!entryId) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const childrenEl = document.getElementById(`${entryId}-ch`);
|
|
176
|
+
const chevron = target.querySelector('.dir-chevron');
|
|
177
|
+
if (childrenEl) {
|
|
178
|
+
const hidden = childrenEl.classList.toggle('dir-collapsed');
|
|
179
|
+
chevron?.classList.toggle('expanded', !hidden);
|
|
180
|
+
if (chevron)
|
|
181
|
+
chevron.textContent = hidden ? '▶' : '▼';
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (target.dataset.loaded === 'true') {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
if (chevron)
|
|
188
|
+
chevron.textContent = '⏳';
|
|
189
|
+
try {
|
|
190
|
+
const result = await options.callTool?.('list_directory', { path: fullPath, depth: 2 });
|
|
191
|
+
const text = extractToolText(result) ?? '';
|
|
192
|
+
if (text) {
|
|
193
|
+
target.dataset.loaded = 'true';
|
|
194
|
+
const parsed = parseDirectoryEntries(text);
|
|
195
|
+
const html = renderDirTree(parsed.entries, fullPath);
|
|
196
|
+
const wrapper = document.createElement('div');
|
|
197
|
+
wrapper.className = 'dir-children';
|
|
198
|
+
wrapper.id = `${entryId}-ch`;
|
|
199
|
+
const temp = document.createElement('div');
|
|
200
|
+
temp.innerHTML = html;
|
|
201
|
+
const inner = temp.querySelector('.dir-tree');
|
|
202
|
+
wrapper.innerHTML = inner ? inner.innerHTML : '<span class="dir-empty">Empty</span>';
|
|
203
|
+
target.parentElement?.appendChild(wrapper);
|
|
204
|
+
chevron?.classList.add('expanded');
|
|
205
|
+
if (chevron)
|
|
206
|
+
chevron.textContent = '▼';
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
if (chevron)
|
|
211
|
+
chevron.textContent = '⚠';
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (target.classList.contains('dir-row-file')) {
|
|
216
|
+
target.classList.add('dir-loading');
|
|
217
|
+
try {
|
|
218
|
+
const result = await options.callTool?.('read_file', { path: fullPath });
|
|
219
|
+
if (!result || typeof result !== 'object' || result === null) {
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
const structuredContent = result.structuredContent;
|
|
223
|
+
if (structuredContent && typeof structuredContent === 'object') {
|
|
224
|
+
const text = extractToolText(result) ?? '';
|
|
225
|
+
options.onOpenPayload(buildRenderPayload(structuredContent, text));
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
target.classList.remove('dir-loading');
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FileTypeCapabilities, MarkdownWorkspaceState, RenderBodyResult, RenderPayload } from './model.js';
|
|
2
|
+
export declare function buildDocumentLayout(options: {
|
|
3
|
+
payload: RenderPayload;
|
|
4
|
+
body: RenderBodyResult;
|
|
5
|
+
capabilities: FileTypeCapabilities;
|
|
6
|
+
fileExtension: string;
|
|
7
|
+
htmlMode: 'rendered' | 'source';
|
|
8
|
+
currentDisplayMode: string | null;
|
|
9
|
+
isExpanded: boolean;
|
|
10
|
+
hideSummaryRow: boolean;
|
|
11
|
+
markdownWorkspace?: MarkdownWorkspaceState;
|
|
12
|
+
canGoFullscreen: boolean;
|
|
13
|
+
isMarkdownUndoAvailable: boolean;
|
|
14
|
+
defaultMarkdownEditorName?: string;
|
|
15
|
+
markdownEditorAppIcon: string;
|
|
16
|
+
hasDirectoryBackButton: boolean;
|
|
17
|
+
}): {
|
|
18
|
+
html: string;
|
|
19
|
+
effectiveExpanded: boolean;
|
|
20
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { renderCompactRow } from '../../shared/compact-row.js';
|
|
2
|
+
import { escapeHtml } from '../../shared/escape-html.js';
|
|
3
|
+
import { parseReadRange, stripReadStatusLine } from './document-workspace.js';
|
|
4
|
+
import { renderMarkdownCopyButton, renderMarkdownModeToggle } from './markdown/editor.js';
|
|
5
|
+
import { buildBreadcrumb, countContentLines } from './payload-utils.js';
|
|
6
|
+
function renderCopyIcon() {
|
|
7
|
+
return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
|
|
8
|
+
}
|
|
9
|
+
function renderFolderIcon() {
|
|
10
|
+
return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
|
|
11
|
+
}
|
|
12
|
+
function renderUndoIcon() {
|
|
13
|
+
return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14 4 9l5-5"/><path d="M4 9h11a5 5 0 1 1 0 10h-1"/></svg>';
|
|
14
|
+
}
|
|
15
|
+
function renderExpandIcon() {
|
|
16
|
+
return '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>';
|
|
17
|
+
}
|
|
18
|
+
function renderMarkdownSaveStatus(workspace) {
|
|
19
|
+
if (workspace.fileDeleted) {
|
|
20
|
+
return '<span class="panel-save-status panel-save-status--saved">File deleted</span>';
|
|
21
|
+
}
|
|
22
|
+
if (workspace.saveIndicator !== 'saved') {
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
const variant = workspace.saving ? 'saving' : 'saved';
|
|
26
|
+
return `<span class="panel-save-status panel-save-status--${variant}">Saved</span>`;
|
|
27
|
+
}
|
|
28
|
+
export function buildDocumentLayout(options) {
|
|
29
|
+
const range = parseReadRange(options.payload.content);
|
|
30
|
+
const notice = options.body.notice ? `<div class="notice">${options.body.notice}</div>` : '';
|
|
31
|
+
const breadcrumb = buildBreadcrumb(options.payload.filePath);
|
|
32
|
+
const lineCount = range ? range.toLine - range.fromLine + 1 : countContentLines(options.payload.content);
|
|
33
|
+
const fileTypeLabel = options.payload.fileType === 'markdown' ? 'MARKDOWN'
|
|
34
|
+
: options.payload.fileType === 'html' ? 'HTML'
|
|
35
|
+
: options.payload.fileType === 'image' ? 'IMAGE'
|
|
36
|
+
: options.payload.fileType === 'directory' ? 'DIRECTORY'
|
|
37
|
+
: options.fileExtension !== 'none' ? options.fileExtension.toUpperCase()
|
|
38
|
+
: 'TEXT';
|
|
39
|
+
const compactLabel = range?.isPartial
|
|
40
|
+
? `View lines ${range.fromLine}–${range.toLine}`
|
|
41
|
+
: options.payload.fileType === 'directory' ? 'View directory'
|
|
42
|
+
: 'View file';
|
|
43
|
+
let footerLabel = range?.isPartial
|
|
44
|
+
? `${fileTypeLabel} • LINES ${range.fromLine}–${range.toLine} OF ${range.totalLines}`
|
|
45
|
+
: `${fileTypeLabel} • ${lineCount} LINE${lineCount !== 1 ? 'S' : ''}`;
|
|
46
|
+
if (options.markdownWorkspace) {
|
|
47
|
+
const source = stripReadStatusLine(options.markdownWorkspace.draftContent);
|
|
48
|
+
const markdownWordCount = source.trim().split(/\s+/).filter(Boolean).length;
|
|
49
|
+
const markdownLineCount = countContentLines(source);
|
|
50
|
+
footerLabel = `${fileTypeLabel} • EDIT MODE • ${markdownLineCount} LINES • ${markdownWordCount} WORDS`;
|
|
51
|
+
}
|
|
52
|
+
const isFullscreen = options.currentDisplayMode === 'fullscreen';
|
|
53
|
+
const htmlToggle = options.payload.fileType === 'html'
|
|
54
|
+
? `<button class="panel-action" id="toggle-html-mode">${options.htmlMode === 'rendered' ? 'Source' : 'Rendered'}</button>`
|
|
55
|
+
: '';
|
|
56
|
+
const backButton = options.hasDirectoryBackButton && options.payload.fileType !== 'directory'
|
|
57
|
+
? '<button class="panel-action dir-back-btn" id="dir-back" title="Back to directory">← Back</button>'
|
|
58
|
+
: '';
|
|
59
|
+
const isMarkdown = options.payload.fileType === 'markdown';
|
|
60
|
+
const isMarkdownEdit = isMarkdown && !!options.markdownWorkspace;
|
|
61
|
+
const revertDisabled = isMarkdownEdit && (options.markdownWorkspace.fileDeleted || options.markdownWorkspace.loadingDocument || !options.isMarkdownUndoAvailable);
|
|
62
|
+
const fileDeleted = isMarkdownEdit && options.markdownWorkspace.fileDeleted;
|
|
63
|
+
const hasMissingBefore = range?.isPartial && range.fromLine > 1;
|
|
64
|
+
const hasMissingAfter = range?.isPartial && range.toLine < range.totalLines && (range.totalLines - range.toLine) > 1;
|
|
65
|
+
const loadBeforeBanner = hasMissingBefore
|
|
66
|
+
? `<button class="load-lines-banner" id="load-before">↑ Load lines 1–${range.fromLine - 1}</button>`
|
|
67
|
+
: '';
|
|
68
|
+
const loadAfterBanner = hasMissingAfter
|
|
69
|
+
? `<button class="load-lines-banner" id="load-after">↓ Load lines ${range.toLine + 1}–${range.totalLines}</button>`
|
|
70
|
+
: '';
|
|
71
|
+
const effectiveExpanded = options.isExpanded || isFullscreen;
|
|
72
|
+
const canOpenInFolder = options.capabilities.canOpenInFolder;
|
|
73
|
+
const canCopy = options.capabilities.canCopy;
|
|
74
|
+
return {
|
|
75
|
+
effectiveExpanded,
|
|
76
|
+
html: `
|
|
77
|
+
<main id="tool-shell" class="shell tool-shell ${effectiveExpanded ? 'expanded' : 'collapsed'}${options.hideSummaryRow ? ' host-framed' : ''}${isFullscreen ? ' fullscreen' : ''}">
|
|
78
|
+
${isFullscreen ? '' : renderCompactRow({ id: 'compact-toggle', label: compactLabel, filename: options.payload.fileName, variant: 'ready', expandable: true, expanded: options.isExpanded, interactive: true })}
|
|
79
|
+
<section class="panel">
|
|
80
|
+
<div class="panel-topbar">
|
|
81
|
+
${backButton}
|
|
82
|
+
${options.hideSummaryRow ? '' : `<span class="panel-breadcrumb" title="${escapeHtml(options.payload.filePath)}">${breadcrumb}</span>`}
|
|
83
|
+
<span class="panel-topbar-actions">
|
|
84
|
+
${isMarkdownEdit ? renderMarkdownSaveStatus(options.markdownWorkspace) : ''}
|
|
85
|
+
${htmlToggle}
|
|
86
|
+
${isMarkdownEdit && isFullscreen ? renderMarkdownModeToggle(options.markdownWorkspace.editorView) : ''}
|
|
87
|
+
${isMarkdown && !isFullscreen && options.canGoFullscreen ? `<button class="panel-action" id="expand-fullscreen" title="Expand" aria-label="Expand">${renderExpandIcon()}</button>` : ''}
|
|
88
|
+
${isMarkdownEdit ? `<button class="panel-action" id="revert-markdown" ${isFullscreen ? '' : 'title="Undo" aria-label="Undo" '}${revertDisabled ? 'disabled' : ''}>${renderUndoIcon()}${isFullscreen ? ' Undo' : ''}</button>` : ''}
|
|
89
|
+
${isMarkdownEdit && isFullscreen ? renderMarkdownCopyButton() : ''}
|
|
90
|
+
${isMarkdown && !isFullscreen ? `<button class="panel-action" id="copy-active-markdown" title="Copy" aria-label="Copy">${renderCopyIcon()}</button>` : ''}
|
|
91
|
+
${canCopy && options.capabilities.supportsPreview && !isMarkdown ? `<button class="panel-action" id="copy-source" title="Copy source" aria-label="Copy source">${renderCopyIcon()}</button>` : ''}
|
|
92
|
+
${canOpenInFolder && isMarkdownEdit && isFullscreen ? `<button class="panel-action" id="open-in-editor" ${fileDeleted ? 'disabled' : ''}>${options.markdownEditorAppIcon} Open in ${escapeHtml(options.defaultMarkdownEditorName ?? 'editor')}</button>` : ''}
|
|
93
|
+
${canOpenInFolder && !(isMarkdownEdit && isFullscreen) ? `<button class="panel-action" id="open-in-folder" title="Open in folder" aria-label="Open in folder" ${isMarkdownEdit && fileDeleted ? 'disabled' : ''}>${renderFolderIcon()}</button>` : ''}
|
|
94
|
+
</span>
|
|
95
|
+
</div>
|
|
96
|
+
${notice}
|
|
97
|
+
<div class="panel-content-wrapper">
|
|
98
|
+
${loadBeforeBanner}
|
|
99
|
+
${options.body.html}
|
|
100
|
+
${loadAfterBanner}
|
|
101
|
+
</div>
|
|
102
|
+
<div class="panel-footer">
|
|
103
|
+
<span>${footerLabel}</span>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
</main>
|
|
107
|
+
`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface DocumentOutlineItem {
|
|
2
|
+
id: string;
|
|
3
|
+
text: string;
|
|
4
|
+
level: number;
|
|
5
|
+
line?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface DocumentOutlineHandle {
|
|
8
|
+
dispose: () => void;
|
|
9
|
+
refresh: (outline: DocumentOutlineItem[], activeHeadingId?: string | null) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare function renderDocumentOutline(outline: DocumentOutlineItem[], activeHeadingId?: string | null): string;
|
|
12
|
+
export declare function attachDocumentOutline(options: {
|
|
13
|
+
shell: HTMLElement;
|
|
14
|
+
outline: DocumentOutlineItem[];
|
|
15
|
+
scrollContainer: HTMLElement;
|
|
16
|
+
onSelect: (headingId: string) => void;
|
|
17
|
+
}): DocumentOutlineHandle | null;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { escapeHtml } from '../../shared/escape-html.js';
|
|
2
|
+
function setActiveItem(nav, activeId) {
|
|
3
|
+
const buttons = Array.from(nav.querySelectorAll('[data-toc-id]'));
|
|
4
|
+
buttons.forEach((button) => {
|
|
5
|
+
const isActive = button.dataset.tocId === activeId;
|
|
6
|
+
button.classList.toggle('is-active', isActive);
|
|
7
|
+
button.setAttribute('aria-current', isActive ? 'location' : 'false');
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
function renderDocumentOutlineItems(outline, activeHeadingId) {
|
|
11
|
+
return outline.map((item) => {
|
|
12
|
+
const activeClass = item.id === activeHeadingId ? ' is-active' : '';
|
|
13
|
+
return `<button class="document-outline-link markdown-toc-link${activeClass}" type="button" data-toc-id="${escapeHtml(item.id)}" data-level="${item.level}" aria-current="${item.id === activeHeadingId ? 'location' : 'false'}">${escapeHtml(item.text)}</button>`;
|
|
14
|
+
}).join('');
|
|
15
|
+
}
|
|
16
|
+
function renderCollapseIcon() {
|
|
17
|
+
return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>';
|
|
18
|
+
}
|
|
19
|
+
function renderExpandIcon() {
|
|
20
|
+
return '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg>';
|
|
21
|
+
}
|
|
22
|
+
export function renderDocumentOutline(outline, activeHeadingId) {
|
|
23
|
+
if (outline.length === 0) {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
return `
|
|
27
|
+
<aside class="document-outline-shell markdown-toc-shell" aria-label="Table of contents">
|
|
28
|
+
<div class="document-outline-header markdown-toc-header">
|
|
29
|
+
<span class="document-outline-title markdown-toc-title">Contents</span>
|
|
30
|
+
<button class="document-outline-toggle" id="toc-toggle" type="button" title="Collapse sidebar" aria-label="Collapse sidebar">${renderCollapseIcon()}</button>
|
|
31
|
+
</div>
|
|
32
|
+
<nav class="document-outline-nav markdown-toc-nav">${renderDocumentOutlineItems(outline, activeHeadingId)}</nav>
|
|
33
|
+
</aside>
|
|
34
|
+
`;
|
|
35
|
+
}
|
|
36
|
+
export function attachDocumentOutline(options) {
|
|
37
|
+
const nav = options.shell.querySelector('.document-outline-nav');
|
|
38
|
+
if (!nav) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
let currentOutline = options.outline;
|
|
42
|
+
const handleClick = (event) => {
|
|
43
|
+
const target = event.target;
|
|
44
|
+
const button = target?.closest('[data-toc-id]');
|
|
45
|
+
const headingId = button?.dataset.tocId;
|
|
46
|
+
if (!headingId) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
options.onSelect(headingId);
|
|
50
|
+
setActiveItem(nav, headingId);
|
|
51
|
+
};
|
|
52
|
+
const updateActiveHeading = () => {
|
|
53
|
+
const headings = currentOutline
|
|
54
|
+
.map((item) => {
|
|
55
|
+
const element = document.getElementById(item.id);
|
|
56
|
+
return element ? { item, element } : null;
|
|
57
|
+
})
|
|
58
|
+
.filter((entry) => entry !== null);
|
|
59
|
+
if (headings.length === 0) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const scrollTop = options.scrollContainer.scrollTop;
|
|
63
|
+
const nextActive = headings.reduce((activeId, current) => {
|
|
64
|
+
if (current.element.offsetTop - scrollTop <= 96) {
|
|
65
|
+
return current.item.id;
|
|
66
|
+
}
|
|
67
|
+
return activeId;
|
|
68
|
+
}, headings[0].item.id);
|
|
69
|
+
setActiveItem(nav, nextActive);
|
|
70
|
+
};
|
|
71
|
+
const toggleButton = options.shell.querySelector('#toc-toggle');
|
|
72
|
+
const handleToggle = () => {
|
|
73
|
+
const isCollapsed = options.shell.classList.toggle('markdown-toc-collapsed');
|
|
74
|
+
if (toggleButton) {
|
|
75
|
+
toggleButton.innerHTML = isCollapsed ? renderExpandIcon() : renderCollapseIcon();
|
|
76
|
+
toggleButton.title = isCollapsed ? 'Expand sidebar' : 'Collapse sidebar';
|
|
77
|
+
toggleButton.setAttribute('aria-label', isCollapsed ? 'Expand sidebar' : 'Collapse sidebar');
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
toggleButton?.addEventListener('click', handleToggle);
|
|
81
|
+
nav.addEventListener('click', handleClick);
|
|
82
|
+
options.scrollContainer.addEventListener('scroll', updateActiveHeading, { passive: true });
|
|
83
|
+
updateActiveHeading();
|
|
84
|
+
return {
|
|
85
|
+
dispose: () => {
|
|
86
|
+
nav.removeEventListener('click', handleClick);
|
|
87
|
+
options.scrollContainer.removeEventListener('scroll', updateActiveHeading);
|
|
88
|
+
toggleButton?.removeEventListener('click', handleToggle);
|
|
89
|
+
},
|
|
90
|
+
refresh: (outline, activeHeadingId) => {
|
|
91
|
+
currentOutline = outline;
|
|
92
|
+
nav.innerHTML = renderDocumentOutlineItems(currentOutline, activeHeadingId);
|
|
93
|
+
setActiveItem(nav, activeHeadingId ?? null);
|
|
94
|
+
updateActiveHeading();
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ReadRange {
|
|
2
|
+
fromLine: number;
|
|
3
|
+
toLine: number;
|
|
4
|
+
totalLines: number;
|
|
5
|
+
isPartial: boolean;
|
|
6
|
+
/** 0-based offset for read_file calls. "from start" → 0, "from line N" → N. */
|
|
7
|
+
readOffset: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function stripReadStatusLine(content: string): string;
|
|
10
|
+
export declare function parseReadRange(content: string): ReadRange | undefined;
|
|
11
|
+
export declare function getDocumentFullscreenAvailability(options: {
|
|
12
|
+
availableDisplayModes?: string[];
|
|
13
|
+
}): {
|
|
14
|
+
canFullscreen: true;
|
|
15
|
+
} | {
|
|
16
|
+
canFullscreen: false;
|
|
17
|
+
reason: string;
|
|
18
|
+
};
|
|
19
|
+
export declare function shouldAutoLoadDocumentOnEnterFullscreen(content: string): boolean;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function stripReadStatusLine(content) {
|
|
2
|
+
return content.replace(/^\[Reading [^\]]+\]\r?\n(?:\r?\n)?/, '');
|
|
3
|
+
}
|
|
4
|
+
export function parseReadRange(content) {
|
|
5
|
+
const match = content.match(/^\[Reading (\d+) lines from (?:line )?(\d+|start) \(total: (\d+) lines/);
|
|
6
|
+
if (!match) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const count = Number.parseInt(match[1], 10);
|
|
10
|
+
const isFromStart = match[2] === 'start';
|
|
11
|
+
const readOffset = isFromStart ? 0 : Number.parseInt(match[2], 10);
|
|
12
|
+
const fromLine = isFromStart ? 1 : readOffset;
|
|
13
|
+
const totalLines = Number.parseInt(match[3], 10);
|
|
14
|
+
return {
|
|
15
|
+
fromLine,
|
|
16
|
+
toLine: fromLine + count - 1,
|
|
17
|
+
totalLines,
|
|
18
|
+
isPartial: count < totalLines,
|
|
19
|
+
readOffset,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function getDocumentFullscreenAvailability(options) {
|
|
23
|
+
if (!options.availableDisplayModes?.includes('fullscreen')) {
|
|
24
|
+
return {
|
|
25
|
+
canFullscreen: false,
|
|
26
|
+
reason: 'Fullscreen editing is unavailable in this host.',
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { canFullscreen: true };
|
|
30
|
+
}
|
|
31
|
+
export function shouldAutoLoadDocumentOnEnterFullscreen(content) {
|
|
32
|
+
return parseReadRange(content)?.isPartial === true;
|
|
33
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FileTypeCapabilities, RenderBodyResult, RenderPayload } from './model.js';
|
|
2
|
+
import type { MarkdownController } from './markdown/controller.js';
|
|
3
|
+
import type { HtmlPreviewMode } from './types.js';
|
|
4
|
+
export declare function getFileTypeCapabilities(payload: RenderPayload): FileTypeCapabilities;
|
|
5
|
+
export declare function renderPayloadBody(options: {
|
|
6
|
+
payload: RenderPayload;
|
|
7
|
+
htmlMode: HtmlPreviewMode;
|
|
8
|
+
startLine: number;
|
|
9
|
+
markdownController: MarkdownController;
|
|
10
|
+
}): RenderBodyResult;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { formatJsonIfPossible, inferLanguageFromPath, renderCodeViewer } from './components/code-viewer.js';
|
|
2
|
+
import { escapeHtml } from './components/highlighting.js';
|
|
3
|
+
import { renderHtmlPreview } from './components/html-renderer.js';
|
|
4
|
+
import { renderDirectoryBody } from './directory-controller.js';
|
|
5
|
+
import { stripReadStatusLine } from './document-workspace.js';
|
|
6
|
+
import { isAllowedImageMimeType, normalizeImageMimeType } from './image-preview.js';
|
|
7
|
+
import { isLikelyUrl } from './payload-utils.js';
|
|
8
|
+
function renderRawFallback(source) {
|
|
9
|
+
return `<pre class="code-viewer"><code class="hljs language-text">${escapeHtml(source)}</code></pre>`;
|
|
10
|
+
}
|
|
11
|
+
function renderImageBody(payload) {
|
|
12
|
+
const mimeType = normalizeImageMimeType(payload.mimeType);
|
|
13
|
+
if (!isAllowedImageMimeType(mimeType)) {
|
|
14
|
+
return {
|
|
15
|
+
notice: 'Preview is unavailable for this image format.',
|
|
16
|
+
html: '<div class="panel-content source-content"></div>',
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (!payload.imageData || payload.imageData.trim().length === 0) {
|
|
20
|
+
return {
|
|
21
|
+
notice: 'Preview is unavailable because image data is missing.',
|
|
22
|
+
html: '<div class="panel-content source-content"></div>',
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const src = `data:${mimeType};base64,${payload.imageData}`;
|
|
26
|
+
return {
|
|
27
|
+
html: `<div class="panel-content image-content"><div class="image-preview"><img src="${escapeHtml(src)}" alt="${escapeHtml(payload.fileName)}" loading="eager" decoding="async"></div></div>`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function buildPreviewCapabilities(payload, canCopy) {
|
|
31
|
+
return {
|
|
32
|
+
supportsPreview: true,
|
|
33
|
+
canCopy,
|
|
34
|
+
canOpenInFolder: !isLikelyUrl(payload.filePath),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const handlerRegistry = {
|
|
38
|
+
directory: {
|
|
39
|
+
getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
|
|
40
|
+
renderBody: ({ payload }) => renderDirectoryBody(stripReadStatusLine(payload.content), payload.filePath),
|
|
41
|
+
},
|
|
42
|
+
html: {
|
|
43
|
+
getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
|
|
44
|
+
renderBody: ({ payload, htmlMode }) => renderHtmlPreview(stripReadStatusLine(payload.content), htmlMode),
|
|
45
|
+
},
|
|
46
|
+
image: {
|
|
47
|
+
getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
|
|
48
|
+
renderBody: ({ payload }) => renderImageBody(payload),
|
|
49
|
+
},
|
|
50
|
+
markdown: {
|
|
51
|
+
getCapabilities: (payload) => buildPreviewCapabilities(payload, false),
|
|
52
|
+
renderBody: ({ payload, markdownController }) => {
|
|
53
|
+
try {
|
|
54
|
+
return markdownController.buildBody(payload);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return {
|
|
58
|
+
notice: 'Markdown renderer failed. Showing raw source instead.',
|
|
59
|
+
html: `<div class="panel-content source-content">${renderRawFallback(stripReadStatusLine(payload.content))}</div>`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
text: {
|
|
65
|
+
getCapabilities: (payload) => buildPreviewCapabilities(payload, true),
|
|
66
|
+
renderBody: ({ payload, startLine }) => {
|
|
67
|
+
const cleanedContent = stripReadStatusLine(payload.content);
|
|
68
|
+
const detectedLanguage = inferLanguageFromPath(payload.filePath);
|
|
69
|
+
const formatted = formatJsonIfPossible(cleanedContent, payload.filePath);
|
|
70
|
+
return {
|
|
71
|
+
notice: formatted.notice,
|
|
72
|
+
html: `<div class="panel-content source-content">${renderCodeViewer(formatted.content, detectedLanguage, startLine)}</div>`,
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
unsupported: {
|
|
77
|
+
getCapabilities: () => ({
|
|
78
|
+
supportsPreview: false,
|
|
79
|
+
canCopy: false,
|
|
80
|
+
canOpenInFolder: true,
|
|
81
|
+
}),
|
|
82
|
+
renderBody: () => ({
|
|
83
|
+
notice: 'Preview is not available for this file type.',
|
|
84
|
+
html: '<div class="panel-content source-content"></div>',
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
export function getFileTypeCapabilities(payload) {
|
|
89
|
+
return handlerRegistry[payload.fileType]?.getCapabilities(payload) ?? {
|
|
90
|
+
supportsPreview: false,
|
|
91
|
+
canCopy: false,
|
|
92
|
+
canOpenInFolder: !isLikelyUrl(payload.filePath),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
export function renderPayloadBody(options) {
|
|
96
|
+
const handler = handlerRegistry[options.payload.fileType] ?? handlerRegistry.text;
|
|
97
|
+
return handler.renderBody(options);
|
|
98
|
+
}
|