@travisennis/acai 0.0.5 → 0.0.7
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 +190 -19
- package/bin/acai-wrapper.js +26 -0
- package/dist/agent/index.d.ts +132 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +434 -0
- package/dist/api/exa/index.js +1 -1
- package/dist/cli.d.ts +4 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +67 -40
- package/dist/commands/add-directory-command.d.ts +3 -0
- package/dist/commands/add-directory-command.d.ts.map +1 -0
- package/dist/commands/add-directory-command.js +54 -0
- package/dist/commands/application-log-command.d.ts +1 -1
- package/dist/commands/application-log-command.d.ts.map +1 -1
- package/dist/commands/application-log-command.js +18 -20
- package/dist/commands/clear-command.d.ts +1 -1
- package/dist/commands/clear-command.d.ts.map +1 -1
- package/dist/commands/clear-command.js +7 -3
- package/dist/commands/compact-command.d.ts.map +1 -1
- package/dist/commands/compact-command.js +9 -5
- package/dist/commands/context-command.d.ts +3 -0
- package/dist/commands/context-command.d.ts.map +1 -0
- package/dist/commands/context-command.js +124 -0
- package/dist/commands/copy-command.d.ts.map +1 -1
- package/dist/commands/copy-command.js +14 -5
- package/dist/commands/edit-command.d.ts +1 -1
- package/dist/commands/edit-command.d.ts.map +1 -1
- package/dist/commands/edit-command.js +21 -34
- package/dist/commands/edit-prompt-command.d.ts +1 -1
- package/dist/commands/edit-prompt-command.d.ts.map +1 -1
- package/dist/commands/edit-prompt-command.js +18 -15
- package/dist/commands/exit-command.d.ts +1 -4
- package/dist/commands/exit-command.d.ts.map +1 -1
- package/dist/commands/exit-command.js +9 -5
- package/dist/commands/files-command.d.ts +1 -1
- package/dist/commands/files-command.d.ts.map +1 -1
- package/dist/commands/files-command.js +20 -16
- package/dist/commands/generate-rules-command.d.ts +1 -1
- package/dist/commands/generate-rules-command.d.ts.map +1 -1
- package/dist/commands/generate-rules-command.js +307 -39
- package/dist/commands/handoff-command.d.ts +3 -0
- package/dist/commands/handoff-command.d.ts.map +1 -0
- package/dist/commands/handoff-command.js +191 -0
- package/dist/commands/health-command.d.ts +1 -1
- package/dist/commands/health-command.d.ts.map +1 -1
- package/dist/commands/health-command.js +49 -27
- package/dist/commands/help-command.d.ts +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +25 -5
- package/dist/commands/history-command.d.ts +3 -0
- package/dist/commands/history-command.d.ts.map +1 -0
- package/dist/commands/history-command.js +458 -0
- package/dist/commands/init-command.d.ts +1 -1
- package/dist/commands/init-command.d.ts.map +1 -1
- package/dist/commands/init-command.js +40 -22
- package/dist/commands/last-log-command.d.ts +1 -1
- package/dist/commands/last-log-command.d.ts.map +1 -1
- package/dist/commands/last-log-command.js +15 -15
- package/dist/commands/list-directories-command.d.ts +3 -0
- package/dist/commands/list-directories-command.d.ts.map +1 -0
- package/dist/commands/list-directories-command.js +35 -0
- package/dist/commands/list-tools-command.d.ts.map +1 -1
- package/dist/commands/list-tools-command.js +61 -21
- package/dist/commands/manager.d.ts +9 -4
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +64 -39
- package/dist/commands/model-command.d.ts.map +1 -1
- package/dist/commands/model-command.js +201 -66
- package/dist/commands/paste-command.d.ts +1 -1
- package/dist/commands/paste-command.d.ts.map +1 -1
- package/dist/commands/paste-command.js +23 -9
- package/dist/commands/pickup-command.d.ts +3 -0
- package/dist/commands/pickup-command.d.ts.map +1 -0
- package/dist/commands/pickup-command.js +109 -0
- package/dist/commands/prompt-command.d.ts +19 -1
- package/dist/commands/prompt-command.d.ts.map +1 -1
- package/dist/commands/prompt-command.js +191 -98
- package/dist/commands/remove-directory-command.d.ts +3 -0
- package/dist/commands/remove-directory-command.d.ts.map +1 -0
- package/dist/commands/remove-directory-command.js +55 -0
- package/dist/commands/reset-command.d.ts +1 -1
- package/dist/commands/reset-command.d.ts.map +1 -1
- package/dist/commands/reset-command.js +8 -5
- package/dist/commands/rules-command.d.ts +1 -1
- package/dist/commands/rules-command.d.ts.map +1 -1
- package/dist/commands/rules-command.js +25 -22
- package/dist/commands/save-command.d.ts +1 -1
- package/dist/commands/save-command.d.ts.map +1 -1
- package/dist/commands/save-command.js +8 -3
- package/dist/commands/shell-command.d.ts.map +1 -1
- package/dist/commands/shell-command.js +45 -24
- package/dist/commands/types.d.ts +9 -7
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/commands/usage-command.d.ts +1 -1
- package/dist/commands/usage-command.d.ts.map +1 -1
- package/dist/commands/usage-command.js +18 -7
- package/dist/config.d.ts +21 -11
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -63
- package/dist/execution/index.d.ts +17 -2
- package/dist/execution/index.d.ts.map +1 -1
- package/dist/execution/index.js +62 -20
- package/dist/formatting.d.ts +127 -0
- package/dist/formatting.d.ts.map +1 -1
- package/dist/formatting.js +201 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +263 -102
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +47 -18
- package/dist/mentions.d.ts +2 -1
- package/dist/mentions.d.ts.map +1 -1
- package/dist/mentions.js +16 -1
- package/dist/messages.d.ts +11 -0
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +122 -21
- package/dist/middleware/cache.d.ts +3 -0
- package/dist/middleware/cache.d.ts.map +1 -0
- package/dist/middleware/cache.js +53 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -0
- package/dist/models/ai-config.d.ts +4 -2
- package/dist/models/ai-config.d.ts.map +1 -1
- package/dist/models/ai-config.js +12 -2
- package/dist/models/anthropic-provider.d.ts.map +1 -1
- package/dist/models/anthropic-provider.js +3 -67
- package/dist/models/deepseek-provider.d.ts.map +1 -1
- package/dist/models/deepseek-provider.js +0 -2
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +0 -3
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +0 -1
- package/dist/models/manager.d.ts +2 -1
- package/dist/models/manager.d.ts.map +1 -1
- package/dist/models/manager.js +26 -2
- package/dist/models/openai-provider.d.ts.map +1 -1
- package/dist/models/openai-provider.js +0 -4
- package/dist/models/openrouter-provider.d.ts +16 -22
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +175 -236
- package/dist/models/providers.d.ts +4 -14
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +1 -57
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -2
- package/dist/prompts.d.ts +10 -4
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +447 -70
- package/dist/repl/project-status-line.d.ts +3 -0
- package/dist/repl/project-status-line.d.ts.map +1 -0
- package/dist/repl/project-status-line.js +61 -0
- package/dist/repl/tool-call-repair.d.ts.map +1 -1
- package/dist/repl/tool-call-repair.js +8 -4
- package/dist/repl-new.d.ts +51 -0
- package/dist/repl-new.d.ts.map +1 -0
- package/dist/repl-new.js +354 -0
- package/dist/skills.d.ts +20 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +192 -0
- package/dist/terminal/control.d.ts +55 -0
- package/dist/terminal/control.d.ts.map +1 -0
- package/dist/terminal/control.js +109 -0
- package/dist/terminal/default-theme.d.ts +1 -1
- package/dist/terminal/default-theme.d.ts.map +1 -1
- package/dist/terminal/default-theme.js +24 -28
- package/dist/terminal/formatting.d.ts +23 -25
- package/dist/terminal/formatting.d.ts.map +1 -1
- package/dist/terminal/formatting.js +35 -52
- package/dist/terminal/highlight/index.d.ts.map +1 -1
- package/dist/terminal/highlight/index.js +3 -6
- package/dist/terminal/highlight/theme.d.ts.map +1 -1
- package/dist/terminal/highlight/theme.js +2 -6
- package/dist/terminal/index.d.ts +2 -94
- package/dist/terminal/index.d.ts.map +1 -1
- package/dist/terminal/index.js +2 -370
- package/dist/terminal/markdown.js +10 -5
- package/dist/terminal/select-prompt.d.ts +2 -2
- package/dist/terminal/select-prompt.d.ts.map +1 -1
- package/dist/terminal/select-prompt.js +47 -39
- package/dist/terminal/strip-ansi.js +4 -4
- package/dist/terminal/table/cell.d.ts +114 -0
- package/dist/terminal/table/cell.d.ts.map +1 -0
- package/dist/terminal/table/cell.js +407 -0
- package/dist/terminal/table/debug.d.ts +15 -0
- package/dist/terminal/table/debug.d.ts.map +1 -0
- package/dist/terminal/table/debug.js +32 -0
- package/dist/terminal/table/index.d.ts +3 -0
- package/dist/terminal/table/index.d.ts.map +1 -0
- package/dist/terminal/table/index.js +2 -0
- package/dist/terminal/table/layout-manager.d.ts +27 -0
- package/dist/terminal/table/layout-manager.d.ts.map +1 -0
- package/dist/terminal/table/layout-manager.js +257 -0
- package/dist/terminal/table/table.d.ts +9 -0
- package/dist/terminal/table/table.d.ts.map +1 -0
- package/dist/terminal/table/table.js +97 -0
- package/dist/terminal/table/utils.d.ts +63 -0
- package/dist/terminal/table/utils.d.ts.map +1 -0
- package/dist/terminal/table/utils.js +326 -0
- package/dist/tokens/threshold.d.ts +20 -0
- package/dist/tokens/threshold.d.ts.map +1 -0
- package/dist/tokens/threshold.js +67 -0
- package/dist/tools/advanced-edit-file.d.ts +69 -0
- package/dist/tools/advanced-edit-file.d.ts.map +1 -0
- package/dist/tools/advanced-edit-file.js +285 -0
- package/dist/tools/agent.d.ts +16 -5
- package/dist/tools/agent.d.ts.map +1 -1
- package/dist/tools/agent.js +86 -59
- package/dist/tools/bash.d.ts +23 -12
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +243 -128
- package/dist/tools/batch.d.ts +34 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +174 -0
- package/dist/tools/code-interpreter.d.ts +21 -9
- package/dist/tools/code-interpreter.d.ts.map +1 -1
- package/dist/tools/code-interpreter.js +151 -134
- package/dist/tools/delete-file.d.ts +17 -10
- package/dist/tools/delete-file.d.ts.map +1 -1
- package/dist/tools/delete-file.js +60 -97
- package/dist/tools/directory-tree.d.ts +17 -12
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +57 -48
- package/dist/tools/dynamic-tool-loader.d.ts +16 -10
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +122 -130
- package/dist/tools/dynamic-tool-parser.d.ts +1 -0
- package/dist/tools/dynamic-tool-parser.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-parser.js +1 -0
- package/dist/tools/edit-file.d.ts +35 -15
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +127 -114
- package/dist/tools/glob.d.ts +36 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +154 -0
- package/dist/tools/grep.d.ts +73 -12
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +425 -165
- package/dist/tools/index.d.ts +220 -126
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +284 -135
- package/dist/tools/llm-edit-fixer.d.ts +24 -0
- package/dist/tools/llm-edit-fixer.d.ts.map +1 -0
- package/dist/tools/llm-edit-fixer.js +136 -0
- package/dist/tools/move-file.d.ts +19 -7
- package/dist/tools/move-file.d.ts.map +1 -1
- package/dist/tools/move-file.js +48 -34
- package/dist/tools/read-file.d.ts +47 -9
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +84 -70
- package/dist/tools/read-multiple-files.d.ts +17 -6
- package/dist/tools/read-multiple-files.d.ts.map +1 -1
- package/dist/tools/read-multiple-files.js +132 -72
- package/dist/tools/save-file.d.ts +45 -12
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +76 -101
- package/dist/tools/think.d.ts +15 -7
- package/dist/tools/think.d.ts.map +1 -1
- package/dist/tools/think.js +34 -20
- package/dist/tools/types.d.ts +8 -10
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +9 -0
- package/dist/tools/utils.d.ts +14 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +16 -0
- package/dist/tools/web-fetch.d.ts +11 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +39 -38
- package/dist/tools/web-search.d.ts +15 -6
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +64 -31
- package/dist/tui/autocomplete.d.ts +44 -0
- package/dist/tui/autocomplete.d.ts.map +1 -0
- package/dist/tui/autocomplete.js +466 -0
- package/dist/tui/components/assistant-message.d.ts +18 -0
- package/dist/tui/components/assistant-message.d.ts.map +1 -0
- package/dist/tui/components/assistant-message.js +29 -0
- package/dist/tui/components/box.d.ts +20 -0
- package/dist/tui/components/box.d.ts.map +1 -0
- package/dist/tui/components/box.js +81 -0
- package/dist/tui/components/editor.d.ts +106 -0
- package/dist/tui/components/editor.d.ts.map +1 -0
- package/dist/tui/components/editor.js +1220 -0
- package/dist/tui/components/footer.d.ts +12 -0
- package/dist/tui/components/footer.d.ts.map +1 -0
- package/dist/tui/components/footer.js +209 -0
- package/dist/tui/components/header.d.ts +21 -0
- package/dist/tui/components/header.d.ts.map +1 -0
- package/dist/tui/components/header.js +63 -0
- package/dist/tui/components/input.d.ts +14 -0
- package/dist/tui/components/input.d.ts.map +1 -0
- package/dist/tui/components/input.js +122 -0
- package/dist/tui/components/loader.d.ts +23 -0
- package/dist/tui/components/loader.d.ts.map +1 -0
- package/dist/tui/components/loader.js +45 -0
- package/dist/tui/components/markdown.d.ts +106 -0
- package/dist/tui/components/markdown.d.ts.map +1 -0
- package/dist/tui/components/markdown.js +586 -0
- package/dist/tui/components/modal.d.ts +29 -0
- package/dist/tui/components/modal.d.ts.map +1 -0
- package/dist/tui/components/modal.js +263 -0
- package/dist/tui/components/progress-bar.d.ts +19 -0
- package/dist/tui/components/progress-bar.d.ts.map +1 -0
- package/dist/tui/components/progress-bar.js +78 -0
- package/dist/tui/components/prompt-status.d.ts +17 -0
- package/dist/tui/components/prompt-status.d.ts.map +1 -0
- package/dist/tui/components/prompt-status.js +26 -0
- package/dist/tui/components/select-list.d.ts +48 -0
- package/dist/tui/components/select-list.d.ts.map +1 -0
- package/dist/tui/components/select-list.js +207 -0
- package/dist/tui/components/spacer.d.ts +16 -0
- package/dist/tui/components/spacer.d.ts.map +1 -0
- package/dist/tui/components/spacer.js +27 -0
- package/dist/tui/components/table.d.ts +27 -0
- package/dist/tui/components/table.d.ts.map +1 -0
- package/dist/tui/components/table.js +125 -0
- package/dist/tui/components/text.d.ts +26 -0
- package/dist/tui/components/text.d.ts.map +1 -0
- package/dist/tui/components/text.js +143 -0
- package/dist/tui/components/thinking-block.d.ts +14 -0
- package/dist/tui/components/thinking-block.d.ts.map +1 -0
- package/dist/tui/components/thinking-block.js +33 -0
- package/dist/tui/components/tool-execution.d.ts +21 -0
- package/dist/tui/components/tool-execution.d.ts.map +1 -0
- package/dist/tui/components/tool-execution.js +161 -0
- package/dist/tui/components/user-message.d.ts +9 -0
- package/dist/tui/components/user-message.d.ts.map +1 -0
- package/dist/tui/components/user-message.js +23 -0
- package/dist/tui/components/welcome.d.ts +6 -0
- package/dist/tui/components/welcome.d.ts.map +1 -0
- package/dist/tui/components/welcome.js +30 -0
- package/dist/tui/index.d.ts +18 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +22 -0
- package/dist/tui/terminal.d.ts +38 -0
- package/dist/tui/terminal.d.ts.map +1 -0
- package/dist/tui/terminal.js +94 -0
- package/dist/tui/tui.d.ts +69 -0
- package/dist/tui/tui.d.ts.map +1 -0
- package/dist/tui/tui.js +204 -0
- package/dist/tui/utils.d.ts +24 -0
- package/dist/tui/utils.d.ts.map +1 -0
- package/dist/tui/utils.js +111 -0
- package/dist/utils/bash.d.ts +7 -0
- package/dist/utils/bash.d.ts.map +1 -0
- package/dist/{tools/bash-utils.js → utils/bash.js} +31 -12
- package/dist/utils/{filesystem.d.ts → filesystem/operations.d.ts} +1 -1
- package/dist/utils/filesystem/operations.d.ts.map +1 -0
- package/dist/utils/filesystem/security.d.ts +9 -0
- package/dist/utils/filesystem/security.d.ts.map +1 -0
- package/dist/{tools/filesystem-utils.js → utils/filesystem/security.js} +93 -21
- package/dist/utils/funcs.d.ts +6 -0
- package/dist/utils/funcs.d.ts.map +1 -0
- package/dist/utils/funcs.js +6 -0
- package/dist/utils/generators.d.ts +3 -0
- package/dist/utils/generators.d.ts.map +1 -0
- package/dist/utils/generators.js +25 -0
- package/dist/{tools/git-utils.d.ts → utils/git.d.ts} +1 -1
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/{tools/git-utils.js → utils/git.js} +0 -6
- package/dist/utils/glob.js +1 -1
- package/dist/utils/iterables.d.ts +2 -0
- package/dist/utils/iterables.d.ts.map +1 -0
- package/dist/utils/iterables.js +6 -0
- package/dist/utils/{zod-utils.d.ts → zod.d.ts} +1 -1
- package/dist/utils/zod.d.ts.map +1 -0
- package/package.json +21 -21
- package/dist/conversation-analyzer.d.ts +0 -11
- package/dist/conversation-analyzer.d.ts.map +0 -1
- package/dist/conversation-analyzer.js +0 -88
- package/dist/repl/display-tool-messages.d.ts +0 -4
- package/dist/repl/display-tool-messages.d.ts.map +0 -1
- package/dist/repl/display-tool-messages.js +0 -55
- package/dist/repl/display-tool-use.d.ts +0 -14
- package/dist/repl/display-tool-use.d.ts.map +0 -1
- package/dist/repl/display-tool-use.js +0 -63
- package/dist/repl/get-prompt-header.d.ts +0 -8
- package/dist/repl/get-prompt-header.d.ts.map +0 -1
- package/dist/repl/get-prompt-header.js +0 -38
- package/dist/repl-prompt.d.ts +0 -15
- package/dist/repl-prompt.d.ts.map +0 -1
- package/dist/repl-prompt.js +0 -147
- package/dist/repl.d.ts +0 -31
- package/dist/repl.d.ts.map +0 -1
- package/dist/repl.js +0 -310
- package/dist/terminal/checkbox-prompt.d.ts +0 -36
- package/dist/terminal/checkbox-prompt.d.ts.map +0 -1
- package/dist/terminal/checkbox-prompt.js +0 -362
- package/dist/terminal/editor-prompt.d.ts +0 -10
- package/dist/terminal/editor-prompt.d.ts.map +0 -1
- package/dist/terminal/editor-prompt.js +0 -61
- package/dist/terminal/errors.d.ts +0 -19
- package/dist/terminal/errors.d.ts.map +0 -1
- package/dist/terminal/errors.js +0 -37
- package/dist/terminal/input-prompt.d.ts +0 -16
- package/dist/terminal/input-prompt.d.ts.map +0 -1
- package/dist/terminal/input-prompt.js +0 -181
- package/dist/terminal/search-prompt.d.ts +0 -20
- package/dist/terminal/search-prompt.d.ts.map +0 -1
- package/dist/terminal/search-prompt.js +0 -279
- package/dist/terminal/types.d.ts +0 -35
- package/dist/terminal/types.d.ts.map +0 -1
- package/dist/terminal/types.js +0 -1
- package/dist/tokens/manage-output.d.ts +0 -34
- package/dist/tokens/manage-output.d.ts.map +0 -1
- package/dist/tokens/manage-output.js +0 -44
- package/dist/tool-executor.d.ts +0 -28
- package/dist/tool-executor.d.ts.map +0 -1
- package/dist/tool-executor.js +0 -74
- package/dist/tools/bash-utils.d.ts +0 -7
- package/dist/tools/bash-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.d.ts +0 -2
- package/dist/tools/file-editing-utils.d.ts.map +0 -1
- package/dist/tools/file-editing-utils.js +0 -135
- package/dist/tools/filesystem-utils.d.ts +0 -7
- package/dist/tools/filesystem-utils.d.ts.map +0 -1
- package/dist/tools/git-utils.d.ts.map +0 -1
- package/dist/utils/filesystem.d.ts.map +0 -1
- package/dist/utils/zod-utils.d.ts.map +0 -1
- /package/dist/utils/{filesystem.js → filesystem/operations.js} +0 -0
- /package/dist/utils/{zod-utils.js → zod.js} +0 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
import { marked } from "marked";
|
|
2
|
+
import { DEFAULT_HIGHLIGHT_THEME } from "../../terminal/default-theme.js";
|
|
3
|
+
import { highlight, supportsLanguage } from "../../terminal/highlight/index.js";
|
|
4
|
+
import { getListNumber } from "../../terminal/markdown-utils.js";
|
|
5
|
+
import stripAnsi from "../../terminal/strip-ansi.js";
|
|
6
|
+
import style from "../../terminal/style.js";
|
|
7
|
+
import { Table } from "../../terminal/table/index.js";
|
|
8
|
+
import wrapAnsi from "../../terminal/wrap-ansi.js";
|
|
9
|
+
import { applyBackgroundToLine, visibleWidth } from "../utils.js";
|
|
10
|
+
const DEFAULT_THEME = {
|
|
11
|
+
heading: (text) => style.bold.yellow(text),
|
|
12
|
+
paragraph: (text) => text,
|
|
13
|
+
link: (text) => style.underline.blue(text),
|
|
14
|
+
linkUrl: (text) => style.gray(text),
|
|
15
|
+
code: (text) => style.cyan(text),
|
|
16
|
+
codeBlock: (text) => style.green(text),
|
|
17
|
+
codeBlockBorder: (text) => style.gray(text),
|
|
18
|
+
quote: (text) => style.italic(text),
|
|
19
|
+
quoteBorder: (text) => style.gray(text),
|
|
20
|
+
hr: (text) => style.gray(text),
|
|
21
|
+
listBullet: (text) => style.cyan(text),
|
|
22
|
+
bold: (text) => style.bold(text),
|
|
23
|
+
italic: (text) => style.italic(text),
|
|
24
|
+
strikethrough: (text) => style.strikethrough(text),
|
|
25
|
+
underline: (text) => style.underline(text),
|
|
26
|
+
};
|
|
27
|
+
export class Markdown {
|
|
28
|
+
text;
|
|
29
|
+
bgColor;
|
|
30
|
+
customBgRgb;
|
|
31
|
+
paddingX; // Left/right padding
|
|
32
|
+
paddingY; // Top/bottom padding
|
|
33
|
+
theme;
|
|
34
|
+
highlightTheme;
|
|
35
|
+
// Cache for rendered output
|
|
36
|
+
cachedText;
|
|
37
|
+
cachedWidth;
|
|
38
|
+
cachedLines;
|
|
39
|
+
constructor(text, options = {}) {
|
|
40
|
+
this.text = text;
|
|
41
|
+
this.bgColor = options.bgColor;
|
|
42
|
+
this.customBgRgb = options.customBgRgb;
|
|
43
|
+
this.paddingX = options.paddingX ?? 1;
|
|
44
|
+
this.paddingY = options.paddingY ?? 1;
|
|
45
|
+
this.theme = options.theme ?? DEFAULT_THEME;
|
|
46
|
+
this.highlightTheme = options.highlightTheme ?? DEFAULT_HIGHLIGHT_THEME;
|
|
47
|
+
}
|
|
48
|
+
setText(text) {
|
|
49
|
+
this.text = text;
|
|
50
|
+
// Invalidate cache when text changes
|
|
51
|
+
this.cachedText = undefined;
|
|
52
|
+
this.cachedWidth = undefined;
|
|
53
|
+
this.cachedLines = undefined;
|
|
54
|
+
}
|
|
55
|
+
setBgColor(bgColor) {
|
|
56
|
+
this.bgColor = bgColor;
|
|
57
|
+
// Invalidate cache when color changes
|
|
58
|
+
this.cachedText = undefined;
|
|
59
|
+
this.cachedWidth = undefined;
|
|
60
|
+
this.cachedLines = undefined;
|
|
61
|
+
}
|
|
62
|
+
setCustomBgRgb(customBgRgb) {
|
|
63
|
+
this.customBgRgb = customBgRgb;
|
|
64
|
+
// Invalidate cache when color changes
|
|
65
|
+
this.cachedText = undefined;
|
|
66
|
+
this.cachedWidth = undefined;
|
|
67
|
+
this.cachedLines = undefined;
|
|
68
|
+
}
|
|
69
|
+
invalidate() {
|
|
70
|
+
this.cachedText = undefined;
|
|
71
|
+
this.cachedWidth = undefined;
|
|
72
|
+
this.cachedLines = undefined;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the background color function based on current configuration
|
|
76
|
+
*/
|
|
77
|
+
getBackgroundFunction() {
|
|
78
|
+
if (this.customBgRgb) {
|
|
79
|
+
const { r, g, b } = this.customBgRgb;
|
|
80
|
+
return (text) => style.bgRgb(r, g, b)(text);
|
|
81
|
+
}
|
|
82
|
+
if (this.bgColor) {
|
|
83
|
+
const bgColor = this.bgColor;
|
|
84
|
+
return (text) => style[bgColor](text);
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
render(width) {
|
|
89
|
+
// Check cache
|
|
90
|
+
if (this.cachedLines &&
|
|
91
|
+
this.cachedText === this.text &&
|
|
92
|
+
this.cachedWidth === width) {
|
|
93
|
+
return this.cachedLines;
|
|
94
|
+
}
|
|
95
|
+
// Calculate available width for content (subtract horizontal padding)
|
|
96
|
+
const contentWidth = Math.max(1, width - this.paddingX * 2);
|
|
97
|
+
// Don't render anything if there's no actual text
|
|
98
|
+
if (!this.text || this.text.trim() === "") {
|
|
99
|
+
const result = [];
|
|
100
|
+
// Update cache
|
|
101
|
+
this.cachedText = this.text;
|
|
102
|
+
this.cachedWidth = width;
|
|
103
|
+
this.cachedLines = result;
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
// Replace tabs with 3 spaces for consistent rendering
|
|
107
|
+
const normalizedText = this.text.replace(/\t/g, " ");
|
|
108
|
+
// Parse markdown to HTML-like tokens
|
|
109
|
+
const tokens = marked.lexer(normalizedText);
|
|
110
|
+
// Convert tokens to styled terminal output
|
|
111
|
+
const renderedLines = [];
|
|
112
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
113
|
+
const token = tokens[i];
|
|
114
|
+
const nextToken = tokens[i + 1];
|
|
115
|
+
const tokenLines = this.renderToken(token, contentWidth, nextToken?.type);
|
|
116
|
+
renderedLines.push(...tokenLines);
|
|
117
|
+
}
|
|
118
|
+
// Wrap lines (NO padding, NO background yet)
|
|
119
|
+
const wrappedLines = [];
|
|
120
|
+
for (const line of renderedLines) {
|
|
121
|
+
wrappedLines.push(...this.wrapLine(line, contentWidth));
|
|
122
|
+
}
|
|
123
|
+
// Add margins and background to each wrapped line
|
|
124
|
+
const leftMargin = " ".repeat(this.paddingX);
|
|
125
|
+
const rightMargin = " ".repeat(this.paddingX);
|
|
126
|
+
const bgFn = this.getBackgroundFunction();
|
|
127
|
+
const contentLines = [];
|
|
128
|
+
for (const line of wrappedLines) {
|
|
129
|
+
const lineWithMargins = leftMargin + line + rightMargin;
|
|
130
|
+
if (bgFn) {
|
|
131
|
+
contentLines.push(applyBackgroundToLine(lineWithMargins, width, bgFn));
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// No background - just pad to width
|
|
135
|
+
const visibleLen = visibleWidth(lineWithMargins);
|
|
136
|
+
const paddingNeeded = Math.max(0, width - visibleLen);
|
|
137
|
+
contentLines.push(lineWithMargins + " ".repeat(paddingNeeded));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Add top/bottom padding (empty lines)
|
|
141
|
+
const emptyLine = " ".repeat(width);
|
|
142
|
+
const emptyLines = [];
|
|
143
|
+
for (let i = 0; i < this.paddingY; i++) {
|
|
144
|
+
const line = bgFn
|
|
145
|
+
? applyBackgroundToLine(emptyLine, width, bgFn)
|
|
146
|
+
: emptyLine;
|
|
147
|
+
emptyLines.push(line);
|
|
148
|
+
}
|
|
149
|
+
const result = [...emptyLines, ...contentLines, ...emptyLines];
|
|
150
|
+
// Update cache
|
|
151
|
+
this.cachedText = this.text;
|
|
152
|
+
this.cachedWidth = width;
|
|
153
|
+
this.cachedLines = result;
|
|
154
|
+
return result.length > 0 ? result : [""];
|
|
155
|
+
}
|
|
156
|
+
renderToken(token, width, nextTokenType) {
|
|
157
|
+
const lines = [];
|
|
158
|
+
switch (token.type) {
|
|
159
|
+
case "heading": {
|
|
160
|
+
const headingLevel = token.depth;
|
|
161
|
+
const headingPrefix = `${"#".repeat(headingLevel)} `;
|
|
162
|
+
const headingText = this.renderInlineTokens(token.tokens || []);
|
|
163
|
+
if (headingLevel === 1) {
|
|
164
|
+
lines.push(style.underline(this.theme.heading(headingText)));
|
|
165
|
+
}
|
|
166
|
+
else if (headingLevel === 2) {
|
|
167
|
+
lines.push(this.theme.heading(headingText));
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
lines.push(this.theme.heading(headingPrefix + headingText));
|
|
171
|
+
}
|
|
172
|
+
lines.push(""); // Add spacing after headings
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
case "paragraph": {
|
|
176
|
+
const paragraphText = this.renderInlineTokens(token.tokens || []);
|
|
177
|
+
lines.push(this.theme.paragraph(paragraphText));
|
|
178
|
+
// Don't add spacing if next token is space or list
|
|
179
|
+
if (nextTokenType &&
|
|
180
|
+
nextTokenType !== "list" &&
|
|
181
|
+
nextTokenType !== "space") {
|
|
182
|
+
lines.push("");
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
case "code": {
|
|
187
|
+
if (token.lang && supportsLanguage(token.lang)) {
|
|
188
|
+
// Use syntax highlighting for supported languages
|
|
189
|
+
const highlightedCode = highlight(token.text, {
|
|
190
|
+
language: token.lang,
|
|
191
|
+
theme: this.highlightTheme,
|
|
192
|
+
});
|
|
193
|
+
const codeLines = highlightedCode.split("\n");
|
|
194
|
+
lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang}`));
|
|
195
|
+
for (const codeLine of codeLines) {
|
|
196
|
+
lines.push(style.dim(" ") + codeLine);
|
|
197
|
+
}
|
|
198
|
+
lines.push(this.theme.codeBlockBorder("```"));
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
// Fallback to basic styling for unsupported languages
|
|
202
|
+
lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
|
|
203
|
+
const codeLines = token.text.split("\n");
|
|
204
|
+
for (const codeLine of codeLines) {
|
|
205
|
+
lines.push(style.dim(" ") + this.theme.codeBlock(codeLine));
|
|
206
|
+
}
|
|
207
|
+
lines.push(this.theme.codeBlockBorder("```"));
|
|
208
|
+
}
|
|
209
|
+
lines.push(""); // Add spacing after code blocks
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "list": {
|
|
213
|
+
const listLines = this.renderList(token, 0);
|
|
214
|
+
lines.push(...listLines);
|
|
215
|
+
// Don't add spacing after lists if a space token follows
|
|
216
|
+
// (the space token will handle it)
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case "table": {
|
|
220
|
+
const tableLines = this.renderTable(token);
|
|
221
|
+
lines.push(...tableLines);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case "blockquote": {
|
|
225
|
+
const quoteText = this.renderInlineTokens(token.tokens || []);
|
|
226
|
+
const quoteLines = quoteText.split("\n");
|
|
227
|
+
for (const quoteLine of quoteLines) {
|
|
228
|
+
lines.push(this.theme.quoteBorder("│ ") + this.theme.quote(quoteLine));
|
|
229
|
+
}
|
|
230
|
+
lines.push(""); // Add spacing after blockquotes
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case "hr":
|
|
234
|
+
lines.push(this.theme.hr("─".repeat(Math.min(width, 80))));
|
|
235
|
+
lines.push(""); // Add spacing after horizontal rules
|
|
236
|
+
break;
|
|
237
|
+
case "image": {
|
|
238
|
+
const alt = (token.title ?? token.text ?? "").toString().trim();
|
|
239
|
+
if (alt.length > 0) {
|
|
240
|
+
lines.push(`[Image: ${alt} (${token.href})]`);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
lines.push(`[Image: ${token.href}]`);
|
|
244
|
+
}
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
case "html":
|
|
248
|
+
// Render HTML tags with dim styling and content as normal text
|
|
249
|
+
lines.push(style.dim(token.text));
|
|
250
|
+
break;
|
|
251
|
+
case "space":
|
|
252
|
+
// Space tokens represent blank lines in markdown
|
|
253
|
+
lines.push("");
|
|
254
|
+
break;
|
|
255
|
+
default:
|
|
256
|
+
// Handle any other token types as plain text
|
|
257
|
+
if ("text" in token && typeof token.text === "string") {
|
|
258
|
+
lines.push(token.text);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return lines;
|
|
262
|
+
}
|
|
263
|
+
renderInlineTokens(tokens) {
|
|
264
|
+
let result = "";
|
|
265
|
+
for (const token of tokens) {
|
|
266
|
+
switch (token.type) {
|
|
267
|
+
case "text":
|
|
268
|
+
// Text tokens in list items can have nested tokens for inline formatting
|
|
269
|
+
if (token.tokens && token.tokens.length > 0) {
|
|
270
|
+
result += this.renderInlineTokens(token.tokens);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
result += token.text;
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
case "strong":
|
|
277
|
+
result += this.theme.bold(this.renderInlineTokens(token.tokens || []));
|
|
278
|
+
break;
|
|
279
|
+
case "em":
|
|
280
|
+
result += this.theme.italic(this.renderInlineTokens(token.tokens || []));
|
|
281
|
+
break;
|
|
282
|
+
case "codespan":
|
|
283
|
+
result +=
|
|
284
|
+
this.theme.codeBlockBorder("`") +
|
|
285
|
+
this.theme.code(token.text) +
|
|
286
|
+
this.theme.codeBlockBorder("`");
|
|
287
|
+
break;
|
|
288
|
+
case "link": {
|
|
289
|
+
const linkText = this.renderInlineTokens(token.tokens || []);
|
|
290
|
+
// If link text matches href, only show the link once
|
|
291
|
+
if (linkText === token.href) {
|
|
292
|
+
result += this.theme.link(linkText);
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
result +=
|
|
296
|
+
this.theme.link(linkText) +
|
|
297
|
+
this.theme.linkUrl(` (${token.href})`);
|
|
298
|
+
}
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
case "br":
|
|
302
|
+
result += "\n";
|
|
303
|
+
break;
|
|
304
|
+
case "del":
|
|
305
|
+
result += this.theme.strikethrough(this.renderInlineTokens(token.tokens || []));
|
|
306
|
+
break;
|
|
307
|
+
case "image": {
|
|
308
|
+
const alt = (token.title ?? token.text ?? "").toString().trim();
|
|
309
|
+
if (alt.length > 0) {
|
|
310
|
+
result += `[Image: ${alt} (${token.href})]`;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
result += `[Image: ${token.href}]`;
|
|
314
|
+
}
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
default:
|
|
318
|
+
// Handle any other inline token types as plain text
|
|
319
|
+
if ("text" in token && typeof token.text === "string") {
|
|
320
|
+
result += token.text;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
wrapLine(line, contentWidth) {
|
|
327
|
+
// Handle undefined or null lines
|
|
328
|
+
if (!line) {
|
|
329
|
+
return [""];
|
|
330
|
+
}
|
|
331
|
+
// Protect inline code spans from being split across lines
|
|
332
|
+
// by temporarily replacing them with placeholders
|
|
333
|
+
const { protectedText, codeSpans } = this.protectCodeSpans(line);
|
|
334
|
+
// Use the existing wrapAnsi function for robust ANSI-aware wrapping
|
|
335
|
+
// Use contentWidth (available width after padding) for wrapping
|
|
336
|
+
const wrappedText = wrapAnsi(protectedText, contentWidth, { trim: false });
|
|
337
|
+
const lines = wrappedText.split("\n");
|
|
338
|
+
// Restore the code spans
|
|
339
|
+
const restoredLines = this.restoreCodeSpans(lines, codeSpans);
|
|
340
|
+
return restoredLines;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Protect inline code spans by replacing them with placeholders
|
|
344
|
+
* This prevents wrapAnsi from breaking code spans across lines
|
|
345
|
+
*/
|
|
346
|
+
protectCodeSpans(text) {
|
|
347
|
+
const codeSpans = [];
|
|
348
|
+
let protectedText = text;
|
|
349
|
+
let placeholderIndex = 0;
|
|
350
|
+
// Create a version of the text without ANSI codes for code span detection
|
|
351
|
+
// This allows us to reliably find code spans regardless of styling
|
|
352
|
+
const cleanText = stripAnsi(text);
|
|
353
|
+
// Use the clean text to find code spans
|
|
354
|
+
let i = 0;
|
|
355
|
+
while (i < cleanText.length) {
|
|
356
|
+
// Find the next backtick in clean text
|
|
357
|
+
const backtickIndex = cleanText.indexOf("`", i);
|
|
358
|
+
if (backtickIndex === -1)
|
|
359
|
+
break;
|
|
360
|
+
// Look for the closing backtick in clean text
|
|
361
|
+
let closingIndex = -1;
|
|
362
|
+
let depth = 1;
|
|
363
|
+
for (let j = backtickIndex + 1; j < cleanText.length; j++) {
|
|
364
|
+
if (cleanText[j] === "`") {
|
|
365
|
+
depth--;
|
|
366
|
+
if (depth === 0) {
|
|
367
|
+
closingIndex = j;
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (closingIndex !== -1) {
|
|
373
|
+
// Extract the actual code span from the original styled text
|
|
374
|
+
// We need to map the positions from clean text to styled text
|
|
375
|
+
const cleanCodeSpan = cleanText.slice(backtickIndex, closingIndex + 1);
|
|
376
|
+
// Find the corresponding span in the styled text
|
|
377
|
+
// This is complex due to ANSI codes, so we use a simpler approach:
|
|
378
|
+
// Just use the regex on the original text and validate with clean text
|
|
379
|
+
const regex = new RegExp(cleanCodeSpan.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g");
|
|
380
|
+
const match = regex.exec(text);
|
|
381
|
+
if (match) {
|
|
382
|
+
const styledCodeSpan = match[0];
|
|
383
|
+
// Check if this is an actual code span
|
|
384
|
+
if (this.isActualCodeSpan(text, match.index, match.index + styledCodeSpan.length)) {
|
|
385
|
+
const placeholder = `__CODE_SPAN_${placeholderIndex}__`;
|
|
386
|
+
// Store the full styled code span for restoration
|
|
387
|
+
codeSpans.push(styledCodeSpan);
|
|
388
|
+
// Replace with placeholder
|
|
389
|
+
protectedText = protectedText.replace(styledCodeSpan, placeholder);
|
|
390
|
+
placeholderIndex++;
|
|
391
|
+
// Move past this code span
|
|
392
|
+
i = closingIndex + 1;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
// Move to next character
|
|
398
|
+
i = backtickIndex + 1;
|
|
399
|
+
}
|
|
400
|
+
return { protectedText, codeSpans };
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Check if a potential code span is an actual code span (not escaped backticks)
|
|
404
|
+
*/
|
|
405
|
+
isActualCodeSpan(text, startIndex, endIndex) {
|
|
406
|
+
// If the text around the code span contains ANSI escape sequences,
|
|
407
|
+
// it's likely an actual code span that was processed by renderInlineTokens
|
|
408
|
+
// Look for ANSI escape sequences in the surrounding context
|
|
409
|
+
const contextStart = Math.max(0, startIndex - 10);
|
|
410
|
+
const contextEnd = Math.min(text.length, endIndex + 10);
|
|
411
|
+
const context = text.slice(contextStart, contextEnd);
|
|
412
|
+
// Check for ANSI escape sequences that would indicate styled code
|
|
413
|
+
// Use String.fromCharCode(27) to avoid control characters in regex
|
|
414
|
+
const escapeChar = String.fromCharCode(27);
|
|
415
|
+
return context.includes(`${escapeChar}[`);
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Check if a line represents a nested list item
|
|
419
|
+
*/
|
|
420
|
+
isNestedListLine(line, currentDepth) {
|
|
421
|
+
// A nested list line should have proper indentation for its depth
|
|
422
|
+
// and typically starts with a bullet (cyan colored number or dash)
|
|
423
|
+
const expectedIndent = " ".repeat(currentDepth + 1);
|
|
424
|
+
const escapeChar = String.fromCharCode(27);
|
|
425
|
+
// Check if the line starts with the expected indent for a nested list
|
|
426
|
+
// and contains a cyan bullet (either number or dash) after the indent
|
|
427
|
+
if (line.startsWith(expectedIndent)) {
|
|
428
|
+
const afterIndent = line.slice(expectedIndent.length);
|
|
429
|
+
// Look for cyan-colored content at the start (bullet)
|
|
430
|
+
// Pattern: cyan escape sequence followed by content, then reset
|
|
431
|
+
const cyanPattern = `${escapeChar}[36m`;
|
|
432
|
+
const resetPattern = `${escapeChar}[39m`;
|
|
433
|
+
if (afterIndent.startsWith(cyanPattern)) {
|
|
434
|
+
const afterCyan = afterIndent.slice(cyanPattern.length);
|
|
435
|
+
const resetIndex = afterCyan.indexOf(resetPattern);
|
|
436
|
+
if (resetIndex > 0) {
|
|
437
|
+
const bulletContent = afterCyan.slice(0, resetIndex);
|
|
438
|
+
// Check if this looks like a list bullet (number with dot or dash)
|
|
439
|
+
return /^(\d+\.|-)/.test(bulletContent);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Restore code spans from placeholders after wrapping
|
|
447
|
+
*/
|
|
448
|
+
restoreCodeSpans(lines, codeSpans) {
|
|
449
|
+
return lines.map((line) => {
|
|
450
|
+
let restoredLine = line;
|
|
451
|
+
// Restore each code span placeholder
|
|
452
|
+
for (let i = 0; i < codeSpans.length; i++) {
|
|
453
|
+
const placeholder = `__CODE_SPAN_${i}__`;
|
|
454
|
+
const codeSpan = codeSpans[i];
|
|
455
|
+
restoredLine = restoredLine.replace(placeholder, codeSpan);
|
|
456
|
+
}
|
|
457
|
+
return restoredLine;
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Render a list with proper nesting support
|
|
462
|
+
*/
|
|
463
|
+
renderList(token, depth) {
|
|
464
|
+
const lines = [];
|
|
465
|
+
const indent = " ".repeat(depth);
|
|
466
|
+
for (let i = 0; i < token.items.length; i++) {
|
|
467
|
+
const item = token.items[i];
|
|
468
|
+
const startNumber = typeof token.start === "string"
|
|
469
|
+
? Number.parseInt(token.start, 10)
|
|
470
|
+
: token.start;
|
|
471
|
+
const bullet = token.ordered
|
|
472
|
+
? `${getListNumber(depth, (startNumber ?? 1) + i)}. `
|
|
473
|
+
: "- ";
|
|
474
|
+
// Process item tokens to handle nested lists
|
|
475
|
+
const itemLines = this.renderListItem(item.tokens || [], depth);
|
|
476
|
+
if (itemLines.length > 0) {
|
|
477
|
+
// First line - check if it's a nested list
|
|
478
|
+
const firstLine = itemLines[0];
|
|
479
|
+
const isNestedList = this.isNestedListLine(firstLine, depth);
|
|
480
|
+
if (isNestedList) {
|
|
481
|
+
// This is a nested list, just add it as-is (already has full indent)
|
|
482
|
+
lines.push(firstLine);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
// Regular text content - add indent and bullet
|
|
486
|
+
lines.push(indent + this.theme.listBullet(bullet) + firstLine);
|
|
487
|
+
}
|
|
488
|
+
// Rest of the lines
|
|
489
|
+
for (let j = 1; j < itemLines.length; j++) {
|
|
490
|
+
const line = itemLines[j];
|
|
491
|
+
const isNestedListLine = line.includes("\x1b[36m"); // cyan bullet color
|
|
492
|
+
if (isNestedListLine) {
|
|
493
|
+
// Nested list line - already has full indent
|
|
494
|
+
lines.push(line);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
// Regular content - add parent indent + 2 spaces for continuation
|
|
498
|
+
lines.push(`${indent} ${line}`);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
else {
|
|
503
|
+
lines.push(indent + this.theme.listBullet(bullet));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
return lines;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Render list item tokens, handling nested lists
|
|
510
|
+
* Returns lines WITHOUT the parent indent (renderList will add it)
|
|
511
|
+
*/
|
|
512
|
+
renderListItem(tokens, parentDepth) {
|
|
513
|
+
const lines = [];
|
|
514
|
+
for (const token of tokens) {
|
|
515
|
+
if (token.type === "list") {
|
|
516
|
+
// Nested list - render with one additional indent level
|
|
517
|
+
// These lines will have their own indent, so we just add them as-is
|
|
518
|
+
const nestedLines = this.renderList(token, parentDepth + 1);
|
|
519
|
+
lines.push(...nestedLines);
|
|
520
|
+
}
|
|
521
|
+
else if (token.type === "text") {
|
|
522
|
+
// Text content (may have inline tokens)
|
|
523
|
+
const text = token.tokens && token.tokens.length > 0
|
|
524
|
+
? this.renderInlineTokens(token.tokens)
|
|
525
|
+
: token.text || "";
|
|
526
|
+
lines.push(text);
|
|
527
|
+
}
|
|
528
|
+
else if (token.type === "paragraph") {
|
|
529
|
+
// Paragraph in list item
|
|
530
|
+
const text = this.renderInlineTokens(token.tokens || []);
|
|
531
|
+
lines.push(text);
|
|
532
|
+
}
|
|
533
|
+
else if (token.type === "code") {
|
|
534
|
+
// Code block in list item
|
|
535
|
+
lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
|
|
536
|
+
const codeLines = token.text.split("\n");
|
|
537
|
+
for (const codeLine of codeLines) {
|
|
538
|
+
lines.push(style.dim(" ") + this.theme.codeBlock(codeLine));
|
|
539
|
+
}
|
|
540
|
+
lines.push(this.theme.codeBlockBorder("```"));
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
// Other token types - try to render as inline
|
|
544
|
+
const text = this.renderInlineTokens([token]);
|
|
545
|
+
if (text) {
|
|
546
|
+
lines.push(text);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return lines;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Render a table
|
|
554
|
+
*/
|
|
555
|
+
renderTable(token) {
|
|
556
|
+
const lines = [];
|
|
557
|
+
// Extract header and row texts
|
|
558
|
+
const header = token.header.map((cell) => {
|
|
559
|
+
const headerCell = cell;
|
|
560
|
+
return this.renderInlineTokens(headerCell.tokens || []);
|
|
561
|
+
});
|
|
562
|
+
const rows = token.rows.map((row) => row.map((cell) => {
|
|
563
|
+
const rowCell = cell;
|
|
564
|
+
return this.renderInlineTokens(rowCell.tokens || []);
|
|
565
|
+
}));
|
|
566
|
+
// Calculate column widths based on available width
|
|
567
|
+
const padding = 5; // Account for table borders and padding
|
|
568
|
+
const availableWidth = Math.max(10, 80 - padding); // Use reasonable default width for TUI
|
|
569
|
+
const colCount = header?.length ?? 1;
|
|
570
|
+
const width = Math.max(10, Math.floor(availableWidth / Math.max(1, colCount)));
|
|
571
|
+
const computedColWidths = new Array(colCount).fill(width);
|
|
572
|
+
// Create table using cli-table3
|
|
573
|
+
const table = new Table({
|
|
574
|
+
head: header,
|
|
575
|
+
colWidths: computedColWidths,
|
|
576
|
+
wordWrap: true, // Enable word wrapping for the description column
|
|
577
|
+
});
|
|
578
|
+
table.push(...rows);
|
|
579
|
+
// Split table output into lines
|
|
580
|
+
const tableOutput = table.toString();
|
|
581
|
+
const tableLines = tableOutput.split("\n");
|
|
582
|
+
lines.push(...tableLines);
|
|
583
|
+
lines.push(""); // Add spacing after table
|
|
584
|
+
return lines;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Component } from "../tui.ts";
|
|
2
|
+
import { Container } from "../tui.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Modal component - displays content in an overlay on top of the main UI
|
|
5
|
+
*/
|
|
6
|
+
export declare class Modal extends Container implements Component {
|
|
7
|
+
private title;
|
|
8
|
+
backdrop: boolean;
|
|
9
|
+
private onClose?;
|
|
10
|
+
private maxWidth;
|
|
11
|
+
private maxHeight;
|
|
12
|
+
private scrollPosition;
|
|
13
|
+
constructor(title: string, content: Component, backdrop?: boolean, onClose?: () => void, maxWidth?: number, maxHeight?: number);
|
|
14
|
+
handleInput(data: string): void;
|
|
15
|
+
close(): void;
|
|
16
|
+
render(width: number): string[];
|
|
17
|
+
getCursorPosition(): [number, number] | null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* ModalText component - displays text content in a modal with word wrapping
|
|
21
|
+
*/
|
|
22
|
+
export declare class ModalText extends Container {
|
|
23
|
+
private text;
|
|
24
|
+
private paddingX;
|
|
25
|
+
private paddingY;
|
|
26
|
+
constructor(text: string, paddingX?: number, paddingY?: number);
|
|
27
|
+
render(width: number): string[];
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../source/tui/components/modal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC;;GAEG;AACH,qBAAa,KAAM,SAAQ,SAAU,YAAW,SAAS;IACvD,OAAO,CAAC,KAAK,CAAS;IACf,QAAQ,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,OAAO,CAAC,CAAa;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAK;gBAGzB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,SAAS,EAClB,QAAQ,UAAO,EACf,OAAO,CAAC,EAAE,MAAM,IAAI,EACpB,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM;IAYpB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgD/B,KAAK,IAAI,IAAI;IAMJ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAqHxC,iBAAiB,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;CA2B7C;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,SAAS;IACtC,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,IAAI,EAAE,MAAM,EAAE,QAAQ,SAAI,EAAE,QAAQ,SAAI;IAO3C,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAkFzC"}
|