@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,45 @@
|
|
|
1
|
+
import { renderCodeViewer } from './CodeViewer.js';
|
|
2
|
+
import { escapeHtml } from './highlighting.js';
|
|
3
|
+
function sanitizeHtml(rawHtml) {
|
|
4
|
+
const blockedTagPattern = /<\/?(script|iframe|object|embed|link|meta|base|form)[^>]*>/gi;
|
|
5
|
+
let safe = rawHtml.replace(blockedTagPattern, '');
|
|
6
|
+
safe = safe.replace(/\son[a-z]+\s*=\s*(".*?"|'.*?'|[^\s>]+)/gi, '');
|
|
7
|
+
safe = safe.replace(/\s(href|src)\s*=\s*(".*?"|'.*?'|[^\s>]+)/gi, (match, attr, value) => {
|
|
8
|
+
const strippedValue = String(value).replace(/^['"]|['"]$/g, '').trim().toLowerCase();
|
|
9
|
+
if (strippedValue.startsWith('javascript:')) {
|
|
10
|
+
return ` ${attr}="#"`;
|
|
11
|
+
}
|
|
12
|
+
if (strippedValue.startsWith('data:text/html')) {
|
|
13
|
+
return ` ${attr}="#"`;
|
|
14
|
+
}
|
|
15
|
+
return match;
|
|
16
|
+
});
|
|
17
|
+
return safe;
|
|
18
|
+
}
|
|
19
|
+
function renderSandboxedHtmlFrame(content, allowUnsafeScripts) {
|
|
20
|
+
const htmlContent = allowUnsafeScripts ? content : sanitizeHtml(content);
|
|
21
|
+
const csp = allowUnsafeScripts
|
|
22
|
+
? ''
|
|
23
|
+
: `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: http: data:; style-src 'unsafe-inline';">`;
|
|
24
|
+
const sandbox = allowUnsafeScripts ? 'allow-scripts allow-forms allow-popups' : '';
|
|
25
|
+
const frameDocument = `<!doctype html><html><head><meta charset="utf-8" />${csp}<style>body{font-family:"IBM Plex Sans","Segoe UI",sans-serif;color:#0f172a;padding:16px;margin:0;line-height:1.5;}img{max-width:100%;height:auto;}</style></head><body>${htmlContent}</body></html>`;
|
|
26
|
+
return `<iframe class="html-rendered-frame" title="Rendered HTML preview" sandbox="${sandbox}" referrerpolicy="no-referrer" srcdoc="${escapeHtml(frameDocument)}"></iframe>`;
|
|
27
|
+
}
|
|
28
|
+
export function renderHtmlPreview(content, mode, options = {}) {
|
|
29
|
+
if (mode === 'source') {
|
|
30
|
+
return {
|
|
31
|
+
html: `<div class="panel-content source-content">${renderCodeViewer(content, 'html')}</div>`
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return {
|
|
36
|
+
html: `<div class="panel-content html-content">${renderSandboxedHtmlFrame(content, options.allowUnsafeScripts === true)}</div>`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return {
|
|
41
|
+
html: `<div class="panel-content source-content">${renderCodeViewer(content, 'html')}</div>`,
|
|
42
|
+
notice: 'HTML renderer failed. Showing source instead.'
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function renderMarkdown(content: string): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import MarkdownIt from 'markdown-it';
|
|
2
|
+
import { highlightSource } from './highlighting.js';
|
|
3
|
+
const markdown = new MarkdownIt({
|
|
4
|
+
html: false,
|
|
5
|
+
linkify: true,
|
|
6
|
+
typographer: false,
|
|
7
|
+
highlight(code, language) {
|
|
8
|
+
const normalizedLanguage = (language || 'text').toLowerCase();
|
|
9
|
+
const highlighted = highlightSource(code, normalizedLanguage);
|
|
10
|
+
return `<pre class="code-viewer"><code class="hljs language-${normalizedLanguage}">${highlighted}</code></pre>`;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export function renderMarkdown(content) {
|
|
14
|
+
return markdown.render(content);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating formatting toolbar for the WYSIWYG markdown editor. Appears above
|
|
3
|
+
* selected text and provides inline formatting: bold, italic, strikethrough,
|
|
4
|
+
* code, link, text color, and font size.
|
|
5
|
+
*/
|
|
6
|
+
export interface EditorToolbar {
|
|
7
|
+
element: HTMLElement;
|
|
8
|
+
show: (anchorRect: DOMRect, containerRect: DOMRect) => void;
|
|
9
|
+
hide: () => void;
|
|
10
|
+
destroy: () => void;
|
|
11
|
+
readonly isVisible: boolean;
|
|
12
|
+
readonly hasOpenDropdown: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function createEditorToolbar(onFormatApplied?: () => void): EditorToolbar;
|
|
15
|
+
export declare function handleFormatKeydown(e: KeyboardEvent): boolean;
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating formatting toolbar for the WYSIWYG markdown editor. Appears above
|
|
3
|
+
* selected text and provides inline formatting: bold, italic, strikethrough,
|
|
4
|
+
* code, link, text color, and font size.
|
|
5
|
+
*/
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
// Preset palettes
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
const COLORS = [
|
|
10
|
+
{ label: 'Default', value: '' },
|
|
11
|
+
{ label: 'Red', value: '#ef4444' },
|
|
12
|
+
{ label: 'Orange', value: '#f97316' },
|
|
13
|
+
{ label: 'Amber', value: '#f59e0b' },
|
|
14
|
+
{ label: 'Green', value: '#22c55e' },
|
|
15
|
+
{ label: 'Blue', value: '#3b82f6' },
|
|
16
|
+
{ label: 'Purple', value: '#a855f7' },
|
|
17
|
+
{ label: 'Pink', value: '#ec4899' },
|
|
18
|
+
{ label: 'Gray', value: '#6b7280' },
|
|
19
|
+
];
|
|
20
|
+
const FONT_SIZES = [
|
|
21
|
+
{ label: 'Small', value: '0.85em' },
|
|
22
|
+
{ label: 'Normal', value: '' },
|
|
23
|
+
{ label: 'Large', value: '1.25em' },
|
|
24
|
+
{ label: 'X-Large', value: '1.5em' },
|
|
25
|
+
];
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// SVG icons (inline, 16×16, matching project style)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
const ICONS = {
|
|
30
|
+
bold: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/></svg>`,
|
|
31
|
+
italic: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="4" x2="10" y2="4"/><line x1="14" y1="20" x2="5" y2="20"/><line x1="15" y1="4" x2="9" y2="20"/></svg>`,
|
|
32
|
+
strike: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M17.3 4.9c-1.2-.9-2.7-1.4-4.3-1.4-3.3 0-5 2-5 4 0 .8.2 1.5.5 2"/><path d="M5 12h14"/><path d="M6.7 19.1c1.2.9 2.7 1.4 4.3 1.4 3.3 0 5-2 5-4 0-.8-.2-1.5-.5-2"/></svg>`,
|
|
33
|
+
code: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>`,
|
|
34
|
+
link: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>`,
|
|
35
|
+
color: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2l5.5 14H6.5z"/><line x1="4" y1="22" x2="20" y2="22" stroke-width="3"/></svg>`,
|
|
36
|
+
fontSize: `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7V4h16v3"/><path d="M12 4v16"/><path d="M8 20h8"/></svg>`,
|
|
37
|
+
chevron: `<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>`,
|
|
38
|
+
};
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Selection save/restore (needed before opening dropdowns)
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
let savedRange = null;
|
|
43
|
+
function saveSelection() {
|
|
44
|
+
const sel = document.getSelection();
|
|
45
|
+
if (sel && sel.rangeCount > 0 && !sel.isCollapsed) {
|
|
46
|
+
savedRange = sel.getRangeAt(0).cloneRange();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function restoreSelection() {
|
|
50
|
+
if (!savedRange)
|
|
51
|
+
return false;
|
|
52
|
+
const sel = document.getSelection();
|
|
53
|
+
if (!sel)
|
|
54
|
+
return false;
|
|
55
|
+
sel.removeAllRanges();
|
|
56
|
+
sel.addRange(savedRange);
|
|
57
|
+
return !sel.isCollapsed;
|
|
58
|
+
}
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Format helpers
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/**
|
|
63
|
+
* After a format command the browser typically collapses the selection.
|
|
64
|
+
* Force-restore the pre-command range so the user can chain operations.
|
|
65
|
+
*/
|
|
66
|
+
function forceReselect() {
|
|
67
|
+
// The original savedRange still points at the right text — the browser
|
|
68
|
+
// mutated the DOM in-place (bold wraps in <b>, etc.) but the range
|
|
69
|
+
// endpoints stay valid. Re-add it.
|
|
70
|
+
restoreSelection();
|
|
71
|
+
}
|
|
72
|
+
function execFormat(command, value) {
|
|
73
|
+
if (!restoreSelection())
|
|
74
|
+
return;
|
|
75
|
+
document.execCommand(command, false, value);
|
|
76
|
+
forceReselect();
|
|
77
|
+
}
|
|
78
|
+
function wrapSelectionHtml(tag, attrs = '') {
|
|
79
|
+
if (!restoreSelection())
|
|
80
|
+
return;
|
|
81
|
+
const sel = document.getSelection();
|
|
82
|
+
if (!sel || sel.isCollapsed)
|
|
83
|
+
return;
|
|
84
|
+
const selectedText = sel.toString();
|
|
85
|
+
const html = `<${tag}${attrs ? ' ' + attrs : ''}>${escapeForInsert(selectedText)}</${tag}>`;
|
|
86
|
+
document.execCommand('insertHTML', false, html);
|
|
87
|
+
forceReselect();
|
|
88
|
+
}
|
|
89
|
+
function escapeForInsert(text) {
|
|
90
|
+
return text
|
|
91
|
+
.replace(/&/g, '&')
|
|
92
|
+
.replace(/</g, '<')
|
|
93
|
+
.replace(/>/g, '>');
|
|
94
|
+
}
|
|
95
|
+
function applyColor(color) {
|
|
96
|
+
if (!color) {
|
|
97
|
+
execFormat('removeFormat');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!restoreSelection())
|
|
101
|
+
return;
|
|
102
|
+
document.execCommand('foreColor', false, color);
|
|
103
|
+
forceReselect();
|
|
104
|
+
}
|
|
105
|
+
function applyFontSize(size) {
|
|
106
|
+
if (!size) {
|
|
107
|
+
execFormat('removeFormat');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (!restoreSelection())
|
|
111
|
+
return;
|
|
112
|
+
document.execCommand('fontSize', false, '7');
|
|
113
|
+
// Find the <font size="7"> the browser just created and swap it for a span
|
|
114
|
+
const editableRoot = document.getSelection()?.anchorNode?.parentElement?.closest('[contenteditable="true"]');
|
|
115
|
+
if (editableRoot) {
|
|
116
|
+
const fonts = editableRoot.querySelectorAll('font[size="7"]');
|
|
117
|
+
fonts.forEach(font => {
|
|
118
|
+
const span = document.createElement('span');
|
|
119
|
+
span.style.fontSize = size;
|
|
120
|
+
span.innerHTML = font.innerHTML;
|
|
121
|
+
font.replaceWith(span);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
forceReselect();
|
|
125
|
+
}
|
|
126
|
+
function applyCode() {
|
|
127
|
+
wrapSelectionHtml('code');
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Link insertion via inline input (prompt() is blocked in sandboxed iframes).
|
|
131
|
+
* The `linkInputContainer` ref is set by the factory below after the toolbar
|
|
132
|
+
* DOM is built.
|
|
133
|
+
*/
|
|
134
|
+
let linkInputContainer = null;
|
|
135
|
+
let linkApplyCallback = null;
|
|
136
|
+
function applyLink() {
|
|
137
|
+
if (!linkInputContainer)
|
|
138
|
+
return;
|
|
139
|
+
saveSelection();
|
|
140
|
+
linkInputContainer.classList.add('md-tb-link-input--visible');
|
|
141
|
+
const input = linkInputContainer.querySelector('input');
|
|
142
|
+
if (input) {
|
|
143
|
+
input.value = 'https://';
|
|
144
|
+
input.focus();
|
|
145
|
+
input.select();
|
|
146
|
+
}
|
|
147
|
+
linkApplyCallback = (url) => {
|
|
148
|
+
if (!url)
|
|
149
|
+
return;
|
|
150
|
+
restoreSelection();
|
|
151
|
+
document.execCommand('createLink', false, url);
|
|
152
|
+
forceReselect();
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
// Toolbar DOM construction
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
function btn(icon, title, className = '') {
|
|
159
|
+
return `<button class="md-tb-btn ${className}" title="${title}" aria-label="${title}" type="button" tabindex="-1">${icon}</button>`;
|
|
160
|
+
}
|
|
161
|
+
function buildToolbarHTML() {
|
|
162
|
+
// Color swatches
|
|
163
|
+
const colorSwatches = COLORS.map(c => `<button class="md-tb-swatch${c.value === '' ? ' md-tb-swatch--default' : ''}" data-color="${c.value}" title="${c.label}" style="${c.value ? `background:${c.value}` : ''}" type="button" tabindex="-1">${c.value === '' ? '×' : ''}</button>`).join('');
|
|
164
|
+
// Font size options
|
|
165
|
+
const sizeOptions = FONT_SIZES.map(s => `<button class="md-tb-size-opt${s.value === '' ? ' md-tb-size-opt--active' : ''}" data-size="${s.value}" type="button" tabindex="-1">${s.label}</button>`).join('');
|
|
166
|
+
return `
|
|
167
|
+
<div class="md-tb-group">
|
|
168
|
+
${btn(ICONS.bold, 'Bold (Ctrl+B)', 'md-tb-bold')}
|
|
169
|
+
${btn(ICONS.italic, 'Italic (Ctrl+I)', 'md-tb-italic')}
|
|
170
|
+
${btn(ICONS.strike, 'Strikethrough', 'md-tb-strike')}
|
|
171
|
+
${btn(ICONS.code, 'Inline code', 'md-tb-code')}
|
|
172
|
+
${btn(ICONS.link, 'Insert link (Ctrl+K)', 'md-tb-link')}
|
|
173
|
+
</div>
|
|
174
|
+
<div class="md-tb-sep"></div>
|
|
175
|
+
<div class="md-tb-group">
|
|
176
|
+
<div class="md-tb-dropdown">
|
|
177
|
+
<button class="md-tb-btn md-tb-color-trigger" title="Text color" aria-label="Text color" type="button" tabindex="-1">
|
|
178
|
+
${ICONS.color}${ICONS.chevron}
|
|
179
|
+
</button>
|
|
180
|
+
<div class="md-tb-dropdown-panel md-tb-color-panel">${colorSwatches}</div>
|
|
181
|
+
</div>
|
|
182
|
+
<div class="md-tb-dropdown">
|
|
183
|
+
<button class="md-tb-btn md-tb-size-trigger" title="Font size" aria-label="Font size" type="button" tabindex="-1">
|
|
184
|
+
${ICONS.fontSize}${ICONS.chevron}
|
|
185
|
+
</button>
|
|
186
|
+
<div class="md-tb-dropdown-panel md-tb-size-panel">${sizeOptions}</div>
|
|
187
|
+
</div>
|
|
188
|
+
</div>
|
|
189
|
+
<div class="md-tb-link-input">
|
|
190
|
+
<input type="text" class="md-tb-link-url" placeholder="https://" spellcheck="false" />
|
|
191
|
+
<button class="md-tb-link-apply" type="button" tabindex="-1">Go</button>
|
|
192
|
+
</div>
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
export function createEditorToolbar(onFormatApplied) {
|
|
196
|
+
const el = document.createElement('div');
|
|
197
|
+
el.className = 'md-toolbar';
|
|
198
|
+
el.setAttribute('role', 'toolbar');
|
|
199
|
+
el.innerHTML = buildToolbarHTML();
|
|
200
|
+
// Wire up inline link input
|
|
201
|
+
linkInputContainer = el.querySelector('.md-tb-link-input');
|
|
202
|
+
const linkInput = el.querySelector('.md-tb-link-url');
|
|
203
|
+
const linkApplyBtn = el.querySelector('.md-tb-link-apply');
|
|
204
|
+
function commitLink() {
|
|
205
|
+
const url = linkInput?.value.trim();
|
|
206
|
+
linkInputContainer?.classList.remove('md-tb-link-input--visible');
|
|
207
|
+
if (url && linkApplyCallback) {
|
|
208
|
+
linkApplyCallback(url);
|
|
209
|
+
linkApplyCallback = null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function cancelLink() {
|
|
213
|
+
linkInputContainer?.classList.remove('md-tb-link-input--visible');
|
|
214
|
+
linkApplyCallback = null;
|
|
215
|
+
restoreSelection();
|
|
216
|
+
}
|
|
217
|
+
linkApplyBtn?.addEventListener('click', commitLink);
|
|
218
|
+
linkInput?.addEventListener('keydown', (e) => {
|
|
219
|
+
if (e.key === 'Enter') {
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
commitLink();
|
|
222
|
+
}
|
|
223
|
+
if (e.key === 'Escape') {
|
|
224
|
+
e.preventDefault();
|
|
225
|
+
cancelLink();
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
let visible = false;
|
|
229
|
+
let openDropdown = null;
|
|
230
|
+
// --- Positioning ---
|
|
231
|
+
function show(anchorRect, containerRect) {
|
|
232
|
+
if (!el.parentElement)
|
|
233
|
+
return;
|
|
234
|
+
visible = true;
|
|
235
|
+
el.classList.add('md-toolbar--visible');
|
|
236
|
+
// Measure toolbar
|
|
237
|
+
const tbWidth = el.offsetWidth || 320;
|
|
238
|
+
const tbHeight = el.offsetHeight || 40;
|
|
239
|
+
// Center above selection
|
|
240
|
+
let left = anchorRect.left + anchorRect.width / 2 - tbWidth / 2 - containerRect.left;
|
|
241
|
+
let top = anchorRect.top - tbHeight - 8 - containerRect.top + (el.parentElement?.scrollTop ?? 0);
|
|
242
|
+
// Clamp horizontal
|
|
243
|
+
left = Math.max(4, Math.min(left, containerRect.width - tbWidth - 4));
|
|
244
|
+
// If not enough space above, show below
|
|
245
|
+
if (anchorRect.top - containerRect.top < tbHeight + 12) {
|
|
246
|
+
top = anchorRect.bottom + 8 - containerRect.top + (el.parentElement?.scrollTop ?? 0);
|
|
247
|
+
}
|
|
248
|
+
el.style.left = `${left}px`;
|
|
249
|
+
el.style.top = `${top}px`;
|
|
250
|
+
}
|
|
251
|
+
function hide() {
|
|
252
|
+
visible = false;
|
|
253
|
+
el.classList.remove('md-toolbar--visible');
|
|
254
|
+
closeDropdown();
|
|
255
|
+
linkInputContainer?.classList.remove('md-tb-link-input--visible');
|
|
256
|
+
linkApplyCallback = null;
|
|
257
|
+
}
|
|
258
|
+
function closeDropdown() {
|
|
259
|
+
if (openDropdown) {
|
|
260
|
+
openDropdown.classList.remove('md-tb-dropdown--open');
|
|
261
|
+
openDropdown = null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function toggleDropdown(dropdown) {
|
|
265
|
+
if (openDropdown === dropdown) {
|
|
266
|
+
closeDropdown();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
closeDropdown();
|
|
270
|
+
saveSelection();
|
|
271
|
+
openDropdown = dropdown;
|
|
272
|
+
dropdown.classList.add('md-tb-dropdown--open');
|
|
273
|
+
}
|
|
274
|
+
// --- Event handling ---
|
|
275
|
+
el.addEventListener('mousedown', (e) => {
|
|
276
|
+
const target = e.target;
|
|
277
|
+
// Let the link URL input receive focus normally
|
|
278
|
+
if (target.closest('.md-tb-link-input'))
|
|
279
|
+
return;
|
|
280
|
+
// Save the selection NOW — at mousedown time the browser hasn't
|
|
281
|
+
// cleared it yet. Every subsequent format operation will restore
|
|
282
|
+
// from this snapshot.
|
|
283
|
+
saveSelection();
|
|
284
|
+
// Prevent toolbar clicks from blurring the editable element
|
|
285
|
+
e.preventDefault();
|
|
286
|
+
});
|
|
287
|
+
el.addEventListener('click', (e) => {
|
|
288
|
+
const target = e.target;
|
|
289
|
+
const button = target.closest('button');
|
|
290
|
+
if (!button)
|
|
291
|
+
return;
|
|
292
|
+
// Dropdown triggers
|
|
293
|
+
const dropdown = button.closest('.md-tb-dropdown');
|
|
294
|
+
if (button.classList.contains('md-tb-color-trigger') || button.classList.contains('md-tb-size-trigger')) {
|
|
295
|
+
if (dropdown)
|
|
296
|
+
toggleDropdown(dropdown);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// Color swatch
|
|
300
|
+
if (button.classList.contains('md-tb-swatch')) {
|
|
301
|
+
const color = button.dataset.color ?? '';
|
|
302
|
+
applyColor(color);
|
|
303
|
+
closeDropdown();
|
|
304
|
+
onFormatApplied?.();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
// Font size option
|
|
308
|
+
if (button.classList.contains('md-tb-size-opt')) {
|
|
309
|
+
const size = button.dataset.size ?? '';
|
|
310
|
+
applyFontSize(size);
|
|
311
|
+
closeDropdown();
|
|
312
|
+
onFormatApplied?.();
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
// Inline format buttons
|
|
316
|
+
closeDropdown();
|
|
317
|
+
if (button.classList.contains('md-tb-bold')) {
|
|
318
|
+
execFormat('bold');
|
|
319
|
+
}
|
|
320
|
+
else if (button.classList.contains('md-tb-italic')) {
|
|
321
|
+
execFormat('italic');
|
|
322
|
+
}
|
|
323
|
+
else if (button.classList.contains('md-tb-strike')) {
|
|
324
|
+
execFormat('strikeThrough');
|
|
325
|
+
}
|
|
326
|
+
else if (button.classList.contains('md-tb-code')) {
|
|
327
|
+
applyCode();
|
|
328
|
+
}
|
|
329
|
+
else if (button.classList.contains('md-tb-link')) {
|
|
330
|
+
applyLink();
|
|
331
|
+
}
|
|
332
|
+
onFormatApplied?.();
|
|
333
|
+
});
|
|
334
|
+
// Close dropdown on outside click
|
|
335
|
+
function handleDocClick(e) {
|
|
336
|
+
if (openDropdown && !el.contains(e.target)) {
|
|
337
|
+
closeDropdown();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
document.addEventListener('click', handleDocClick);
|
|
341
|
+
function destroy() {
|
|
342
|
+
document.removeEventListener('click', handleDocClick);
|
|
343
|
+
el.remove();
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
element: el,
|
|
347
|
+
show,
|
|
348
|
+
hide,
|
|
349
|
+
destroy,
|
|
350
|
+
get isVisible() { return visible; },
|
|
351
|
+
get hasOpenDropdown() { return openDropdown !== null; },
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
// ---------------------------------------------------------------------------
|
|
355
|
+
// Keyboard shortcut handler (call from within contentEditable keydown)
|
|
356
|
+
// ---------------------------------------------------------------------------
|
|
357
|
+
export function handleFormatKeydown(e) {
|
|
358
|
+
const mod = e.metaKey || e.ctrlKey;
|
|
359
|
+
if (!mod)
|
|
360
|
+
return false;
|
|
361
|
+
switch (e.key.toLowerCase()) {
|
|
362
|
+
case 'b':
|
|
363
|
+
e.preventDefault();
|
|
364
|
+
saveSelection();
|
|
365
|
+
execFormat('bold');
|
|
366
|
+
return true;
|
|
367
|
+
case 'i':
|
|
368
|
+
e.preventDefault();
|
|
369
|
+
saveSelection();
|
|
370
|
+
execFormat('italic');
|
|
371
|
+
return true;
|
|
372
|
+
case 'k':
|
|
373
|
+
e.preventDefault();
|
|
374
|
+
applyLink();
|
|
375
|
+
return true;
|
|
376
|
+
case 'e':
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
saveSelection();
|
|
379
|
+
applyCode();
|
|
380
|
+
return true;
|
|
381
|
+
default:
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import type { HtmlPreviewMode } from '../types.js';
|
|
2
|
-
|
|
3
|
-
allowUnsafeScripts?: boolean;
|
|
4
|
-
}
|
|
5
|
-
export declare function renderHtmlPreview(content: string, mode: HtmlPreviewMode, options?: HtmlRenderOptions): {
|
|
2
|
+
export declare function renderHtmlPreview(content: string, mode: HtmlPreviewMode): {
|
|
6
3
|
html: string;
|
|
7
4
|
notice?: string;
|
|
8
5
|
};
|
|
9
|
-
export {};
|
|
@@ -1,24 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* HTML preview renderer with
|
|
2
|
+
* HTML preview renderer with display mode control. It handles rendered HTML versus
|
|
3
|
+
* source text display and ensures fallback behavior is predictable.
|
|
4
|
+
*
|
|
5
|
+
* The rendered preview runs inside a nested sandboxed iframe, which is itself inside
|
|
6
|
+
* the MCP app's sandboxed iframe chain. Scripts and external resources (CDNs) are
|
|
7
|
+
* allowed since the sandbox isolation prevents any escape.
|
|
3
8
|
*/
|
|
4
9
|
import { renderCodeViewer } from './code-viewer.js';
|
|
5
10
|
import { escapeHtml } from './highlighting.js';
|
|
6
|
-
function sanitizeHtml(rawHtml) {
|
|
7
|
-
const blockedTagPattern = /<\/?(script|iframe|object|embed|link|meta|base|form)[^>]*>/gi;
|
|
8
|
-
let safe = rawHtml.replace(blockedTagPattern, '');
|
|
9
|
-
safe = safe.replace(/\son[a-z]+\s*=\s*(".*?"|'.*?'|[^\s>]+)/gi, '');
|
|
10
|
-
safe = safe.replace(/\s(href|src)\s*=\s*(".*?"|'.*?'|[^\s>]+)/gi, (match, attr, value) => {
|
|
11
|
-
const strippedValue = String(value).replace(/^['"]|['"]$/g, '').trim().toLowerCase();
|
|
12
|
-
if (strippedValue.startsWith('javascript:')) {
|
|
13
|
-
return ` ${attr}="#"`;
|
|
14
|
-
}
|
|
15
|
-
if (strippedValue.startsWith('data:text/html')) {
|
|
16
|
-
return ` ${attr}="#"`;
|
|
17
|
-
}
|
|
18
|
-
return match;
|
|
19
|
-
});
|
|
20
|
-
return safe;
|
|
21
|
-
}
|
|
22
11
|
function resolveThemeFrameStyles() {
|
|
23
12
|
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
24
13
|
return {
|
|
@@ -33,17 +22,12 @@ function resolveThemeFrameStyles() {
|
|
|
33
22
|
const fontFamily = rootStyles.getPropertyValue('--font-sans').trim() || 'system-ui, sans-serif';
|
|
34
23
|
return { background, text, fontFamily };
|
|
35
24
|
}
|
|
36
|
-
function renderSandboxedHtmlFrame(content
|
|
37
|
-
const htmlContent = allowUnsafeScripts ? content : sanitizeHtml(content);
|
|
38
|
-
const csp = allowUnsafeScripts
|
|
39
|
-
? ''
|
|
40
|
-
: `<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: http: data:; style-src 'unsafe-inline';">`;
|
|
41
|
-
const sandbox = allowUnsafeScripts ? 'allow-scripts allow-forms allow-popups' : '';
|
|
25
|
+
function renderSandboxedHtmlFrame(content) {
|
|
42
26
|
const palette = resolveThemeFrameStyles();
|
|
43
|
-
const frameDocument = `<!doctype html><html><head><meta charset="utf-8"
|
|
44
|
-
return `<iframe class="html-rendered-frame" title="Rendered HTML preview" sandbox="
|
|
27
|
+
const frameDocument = `<!doctype html><html><head><meta charset="utf-8" /><style>html,body{margin:0;padding:0;background:${palette.background};color:${palette.text};}body{font-family:${palette.fontFamily};padding:16px;line-height:1.5;}img{max-width:100%;height:auto;}</style></head><body>${content}</body></html>`;
|
|
28
|
+
return `<iframe class="html-rendered-frame" title="Rendered HTML preview" sandbox="allow-scripts allow-forms allow-popups" referrerpolicy="no-referrer" srcdoc="${escapeHtml(frameDocument)}"></iframe>`;
|
|
45
29
|
}
|
|
46
|
-
export function renderHtmlPreview(content, mode
|
|
30
|
+
export function renderHtmlPreview(content, mode) {
|
|
47
31
|
if (mode === 'source') {
|
|
48
32
|
return {
|
|
49
33
|
html: `<div class="panel-content source-content">${renderCodeViewer(content, 'html')}</div>`
|
|
@@ -51,7 +35,7 @@ export function renderHtmlPreview(content, mode, options = {}) {
|
|
|
51
35
|
}
|
|
52
36
|
try {
|
|
53
37
|
return {
|
|
54
|
-
html: `<div class="panel-content html-content">${renderSandboxedHtmlFrame(content
|
|
38
|
+
html: `<div class="panel-content html-content">${renderSandboxedHtmlFrame(content)}</div>`
|
|
55
39
|
};
|
|
56
40
|
}
|
|
57
41
|
catch {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface MarkdownBlock {
|
|
2
|
+
type: 'heading' | 'paragraph' | 'list' | 'code' | 'blockquote' | 'hr' | 'table';
|
|
3
|
+
source: string;
|
|
4
|
+
startLine: number;
|
|
5
|
+
endLine: number;
|
|
6
|
+
level?: number;
|
|
7
|
+
listType?: 'ul' | 'ol';
|
|
8
|
+
editable: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface EditorCallbacks {
|
|
11
|
+
callTool: (name: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
12
|
+
updateContext: (text: string) => void;
|
|
13
|
+
trackEvent?: (event: string, params?: Record<string, unknown>) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface EditorHandle {
|
|
16
|
+
/** Remove all event listeners and toolbar DOM. */
|
|
17
|
+
cleanup: () => void;
|
|
18
|
+
/** True when a block is actively being edited (contentEditable is on). */
|
|
19
|
+
isEditing: () => boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function parseMarkdownBlocks(source: string): MarkdownBlock[];
|
|
22
|
+
export declare function renderEditableMarkdown(source: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Attach WYSIWYG editing handlers to editable markdown blocks inside
|
|
25
|
+
* the given container. All editable blocks are contentEditable from the
|
|
26
|
+
* start — users can select and type immediately without an activation
|
|
27
|
+
* click. Changes are committed when focus leaves the editor.
|
|
28
|
+
*/
|
|
29
|
+
export declare function attachEditorHandlers(container: HTMLElement, source: string, filePath: string, callbacks: EditorCallbacks): EditorHandle;
|