@soederpop/luca 0.0.2
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/CLAUDE.md +71 -0
- package/README.md +78 -0
- package/bun.lock +2928 -0
- package/bunfig.toml +3 -0
- package/commands/audit-docs.ts +740 -0
- package/commands/build-scaffolds.ts +154 -0
- package/commands/generate-api-docs.ts +114 -0
- package/commands/update-introspection.ts +67 -0
- package/docs/CLI.md +335 -0
- package/docs/README.md +88 -0
- package/docs/TABLE-OF-CONTENTS.md +157 -0
- package/docs/apis/clients/elevenlabs.md +84 -0
- package/docs/apis/clients/graph.md +56 -0
- package/docs/apis/clients/openai.md +69 -0
- package/docs/apis/clients/rest.md +41 -0
- package/docs/apis/clients/websocket.md +107 -0
- package/docs/apis/features/agi/assistant.md +471 -0
- package/docs/apis/features/agi/assistants-manager.md +154 -0
- package/docs/apis/features/agi/claude-code.md +602 -0
- package/docs/apis/features/agi/conversation-history.md +352 -0
- package/docs/apis/features/agi/conversation.md +333 -0
- package/docs/apis/features/agi/docs-reader.md +121 -0
- package/docs/apis/features/agi/openai-codex.md +318 -0
- package/docs/apis/features/agi/openapi.md +138 -0
- package/docs/apis/features/agi/semantic-search.md +387 -0
- package/docs/apis/features/agi/skills-library.md +216 -0
- package/docs/apis/features/node/container-link.md +133 -0
- package/docs/apis/features/node/content-db.md +313 -0
- package/docs/apis/features/node/disk-cache.md +379 -0
- package/docs/apis/features/node/dns.md +651 -0
- package/docs/apis/features/node/docker.md +705 -0
- package/docs/apis/features/node/downloader.md +81 -0
- package/docs/apis/features/node/esbuild.md +59 -0
- package/docs/apis/features/node/file-manager.md +182 -0
- package/docs/apis/features/node/fs.md +581 -0
- package/docs/apis/features/node/git.md +330 -0
- package/docs/apis/features/node/google-auth.md +174 -0
- package/docs/apis/features/node/google-calendar.md +187 -0
- package/docs/apis/features/node/google-docs.md +151 -0
- package/docs/apis/features/node/google-drive.md +225 -0
- package/docs/apis/features/node/google-sheets.md +179 -0
- package/docs/apis/features/node/grep.md +290 -0
- package/docs/apis/features/node/helpers.md +135 -0
- package/docs/apis/features/node/ink.md +334 -0
- package/docs/apis/features/node/ipc-socket.md +260 -0
- package/docs/apis/features/node/json-tree.md +86 -0
- package/docs/apis/features/node/launcher-app-command-listener.md +145 -0
- package/docs/apis/features/node/networking.md +281 -0
- package/docs/apis/features/node/nlp.md +133 -0
- package/docs/apis/features/node/opener.md +97 -0
- package/docs/apis/features/node/os.md +118 -0
- package/docs/apis/features/node/package-finder.md +402 -0
- package/docs/apis/features/node/postgres.md +212 -0
- package/docs/apis/features/node/proc.md +430 -0
- package/docs/apis/features/node/process-manager.md +210 -0
- package/docs/apis/features/node/python.md +278 -0
- package/docs/apis/features/node/repl.md +88 -0
- package/docs/apis/features/node/runpod.md +673 -0
- package/docs/apis/features/node/secure-shell.md +169 -0
- package/docs/apis/features/node/semantic-search.md +401 -0
- package/docs/apis/features/node/sqlite.md +211 -0
- package/docs/apis/features/node/telegram.md +254 -0
- package/docs/apis/features/node/tts.md +118 -0
- package/docs/apis/features/node/ui.md +703 -0
- package/docs/apis/features/node/vault.md +64 -0
- package/docs/apis/features/node/vm.md +84 -0
- package/docs/apis/features/node/window-manager.md +337 -0
- package/docs/apis/features/node/yaml-tree.md +85 -0
- package/docs/apis/features/node/yaml.md +176 -0
- package/docs/apis/features/web/asset-loader.md +47 -0
- package/docs/apis/features/web/container-link.md +133 -0
- package/docs/apis/features/web/esbuild.md +59 -0
- package/docs/apis/features/web/helpers.md +135 -0
- package/docs/apis/features/web/network.md +30 -0
- package/docs/apis/features/web/speech.md +55 -0
- package/docs/apis/features/web/vault.md +64 -0
- package/docs/apis/features/web/vm.md +84 -0
- package/docs/apis/features/web/voice.md +67 -0
- package/docs/apis/servers/express.md +127 -0
- package/docs/apis/servers/mcp.md +213 -0
- package/docs/apis/servers/websocket.md +99 -0
- package/docs/documentation-audit.md +134 -0
- package/docs/examples/content-db.md +77 -0
- package/docs/examples/disk-cache.md +83 -0
- package/docs/examples/docker.md +101 -0
- package/docs/examples/downloader.md +70 -0
- package/docs/examples/esbuild.md +80 -0
- package/docs/examples/file-manager.md +82 -0
- package/docs/examples/fs.md +83 -0
- package/docs/examples/git.md +85 -0
- package/docs/examples/google-auth.md +88 -0
- package/docs/examples/google-calendar.md +94 -0
- package/docs/examples/google-docs.md +82 -0
- package/docs/examples/google-drive.md +96 -0
- package/docs/examples/google-sheets.md +95 -0
- package/docs/examples/grep.md +85 -0
- package/docs/examples/ink-blocks.md +75 -0
- package/docs/examples/ink-renderer.md +41 -0
- package/docs/examples/ink.md +103 -0
- package/docs/examples/ipc-socket.md +103 -0
- package/docs/examples/json-tree.md +91 -0
- package/docs/examples/launcher-app-command-listener.md +120 -0
- package/docs/examples/networking.md +58 -0
- package/docs/examples/nlp.md +91 -0
- package/docs/examples/opener.md +78 -0
- package/docs/examples/os.md +72 -0
- package/docs/examples/package-finder.md +89 -0
- package/docs/examples/port-exposer.md +89 -0
- package/docs/examples/postgres.md +91 -0
- package/docs/examples/proc.md +81 -0
- package/docs/examples/process-manager.md +79 -0
- package/docs/examples/python.md +91 -0
- package/docs/examples/repl.md +93 -0
- package/docs/examples/runpod.md +119 -0
- package/docs/examples/secure-shell.md +92 -0
- package/docs/examples/sqlite.md +86 -0
- package/docs/examples/telegram.md +77 -0
- package/docs/examples/tts.md +86 -0
- package/docs/examples/ui.md +80 -0
- package/docs/examples/vault.md +70 -0
- package/docs/examples/vm.md +86 -0
- package/docs/examples/window-manager.md +125 -0
- package/docs/examples/yaml-tree.md +93 -0
- package/docs/examples/yaml.md +104 -0
- package/docs/ideas/class-registration-refactor-possibilities.md +197 -0
- package/docs/ideas/container-use-api.md +9 -0
- package/docs/ideas/easy-auth-for-express-servers-and-luca-serve.md +0 -0
- package/docs/ideas/feature-stacks.md +22 -0
- package/docs/ideas/luca-cli-self-sufficiency-demo.md +23 -0
- package/docs/ideas/mcp-design.md +9 -0
- package/docs/ideas/web-container-debugging-feature.md +13 -0
- package/docs/introspection-audit.md +49 -0
- package/docs/introspection.md +154 -0
- package/docs/mcp/readme.md +162 -0
- package/docs/models.ts +38 -0
- package/docs/philosophy.md +85 -0
- package/docs/principles.md +7 -0
- package/docs/prompts/audit-codebase-for-failures-to-use-the-container.md +34 -0
- package/docs/prompts/mcp-test-easy-command.md +27 -0
- package/docs/reports/assistant-bugs.md +38 -0
- package/docs/reports/attach-pattern-usage.md +18 -0
- package/docs/reports/code-audit-results.md +391 -0
- package/docs/reports/introspection-audit-tasks.md +378 -0
- package/docs/reports/luca-mcp-improvements.md +128 -0
- package/docs/scaffolds/client.md +140 -0
- package/docs/scaffolds/command.md +106 -0
- package/docs/scaffolds/endpoint.md +176 -0
- package/docs/scaffolds/feature.md +148 -0
- package/docs/scaffolds/server.md +187 -0
- package/docs/tasks/web-container-helper-discovery.md +71 -0
- package/docs/todos.md +1 -0
- package/docs/tutorials/01-getting-started.md +106 -0
- package/docs/tutorials/02-container.md +210 -0
- package/docs/tutorials/03-scripts.md +194 -0
- package/docs/tutorials/04-features-overview.md +196 -0
- package/docs/tutorials/05-state-and-events.md +171 -0
- package/docs/tutorials/06-servers.md +157 -0
- package/docs/tutorials/07-endpoints.md +198 -0
- package/docs/tutorials/08-commands.md +171 -0
- package/docs/tutorials/09-clients.md +162 -0
- package/docs/tutorials/10-creating-features.md +198 -0
- package/docs/tutorials/11-contentbase.md +191 -0
- package/docs/tutorials/12-assistants.md +215 -0
- package/docs/tutorials/13-introspection.md +147 -0
- package/docs/tutorials/14-type-system.md +174 -0
- package/docs/tutorials/15-project-patterns.md +222 -0
- package/docs/tutorials/16-google-features.md +534 -0
- package/docs/tutorials/17-tui-blocks.md +530 -0
- package/docs/tutorials/18-semantic-search.md +334 -0
- package/index.ts +1 -0
- package/luca.console.ts +9 -0
- package/main.py +6 -0
- package/package.json +154 -0
- package/pyproject.toml +7 -0
- package/scripts/animations/chrome-glitch.ts +55 -0
- package/scripts/animations/index.ts +16 -0
- package/scripts/animations/neon-pulse.ts +64 -0
- package/scripts/animations/types.ts +6 -0
- package/scripts/build-web.ts +28 -0
- package/scripts/examples/ask-luca-expert.ts +42 -0
- package/scripts/examples/assistant-questions.ts +12 -0
- package/scripts/examples/excalidraw-expert.ts +75 -0
- package/scripts/examples/expert-chat.ts +0 -0
- package/scripts/examples/file-manager.ts +14 -0
- package/scripts/examples/ideas.ts +12 -0
- package/scripts/examples/interactive-chat.ts +20 -0
- package/scripts/examples/openai-tool-calls.ts +113 -0
- package/scripts/examples/opening-a-web-browser.ts +5 -0
- package/scripts/examples/telegram-bot.ts +79 -0
- package/scripts/examples/telegram-ink-ui.ts +302 -0
- package/scripts/examples/using-assistant-with-mcp.ts +560 -0
- package/scripts/examples/using-claude-code.ts +10 -0
- package/scripts/examples/using-contentdb.ts +35 -0
- package/scripts/examples/using-conversations.ts +35 -0
- package/scripts/examples/using-disk-cache.ts +10 -0
- package/scripts/examples/using-docker-shell.ts +75 -0
- package/scripts/examples/using-elevenlabs.ts +25 -0
- package/scripts/examples/using-google-calendar.ts +57 -0
- package/scripts/examples/using-google-docs.ts +74 -0
- package/scripts/examples/using-google-drive.ts +74 -0
- package/scripts/examples/using-google-sheets.ts +89 -0
- package/scripts/examples/using-nlp.ts +55 -0
- package/scripts/examples/using-ollama.ts +10 -0
- package/scripts/examples/using-openai-codex.ts +23 -0
- package/scripts/examples/using-postgres.ts +55 -0
- package/scripts/examples/using-runpod.ts +32 -0
- package/scripts/examples/using-tts.ts +40 -0
- package/scripts/examples/vm-loading-esm-modules.ts +16 -0
- package/scripts/scaffold.ts +391 -0
- package/scripts/scratch.ts +15 -0
- package/scripts/test-command-listener.ts +123 -0
- package/scripts/test-window-manager-lifecycle.ts +86 -0
- package/scripts/test-window-manager.ts +43 -0
- package/scripts/update-introspection-data.ts +58 -0
- package/src/agi/README.md +14 -0
- package/src/agi/container.server.ts +114 -0
- package/src/agi/endpoints/ask.ts +60 -0
- package/src/agi/endpoints/conversations/[id].ts +45 -0
- package/src/agi/endpoints/conversations.ts +31 -0
- package/src/agi/endpoints/experts.ts +37 -0
- package/src/agi/features/assistant.ts +767 -0
- package/src/agi/features/assistants-manager.ts +260 -0
- package/src/agi/features/claude-code.ts +1111 -0
- package/src/agi/features/conversation-history.ts +497 -0
- package/src/agi/features/conversation.ts +799 -0
- package/src/agi/features/openai-codex.ts +631 -0
- package/src/agi/features/openapi.ts +438 -0
- package/src/agi/features/skills-library.ts +425 -0
- package/src/agi/index.ts +6 -0
- package/src/agi/lib/token-counter.ts +122 -0
- package/src/browser.ts +25 -0
- package/src/bus.ts +100 -0
- package/src/cli/cli.ts +70 -0
- package/src/client.ts +461 -0
- package/src/clients/civitai/index.ts +541 -0
- package/src/clients/client-template.ts +41 -0
- package/src/clients/comfyui/index.ts +597 -0
- package/src/clients/elevenlabs/index.ts +291 -0
- package/src/clients/openai/index.ts +451 -0
- package/src/clients/supabase/index.ts +366 -0
- package/src/command.ts +164 -0
- package/src/commands/chat.ts +182 -0
- package/src/commands/console.ts +192 -0
- package/src/commands/describe.ts +433 -0
- package/src/commands/eval.ts +116 -0
- package/src/commands/help.ts +214 -0
- package/src/commands/index.ts +14 -0
- package/src/commands/mcp.ts +64 -0
- package/src/commands/prompt.ts +807 -0
- package/src/commands/run.ts +257 -0
- package/src/commands/sandbox-mcp.ts +439 -0
- package/src/commands/scaffold.ts +79 -0
- package/src/commands/serve.ts +172 -0
- package/src/container.ts +781 -0
- package/src/endpoint.ts +340 -0
- package/src/feature.ts +75 -0
- package/src/hash-object.ts +97 -0
- package/src/helper.ts +543 -0
- package/src/introspection/generated.agi.ts +23388 -0
- package/src/introspection/generated.node.ts +18899 -0
- package/src/introspection/generated.web.ts +2021 -0
- package/src/introspection/index.ts +256 -0
- package/src/introspection/scan.ts +912 -0
- package/src/node/container.ts +354 -0
- package/src/node/feature.ts +13 -0
- package/src/node/features/container-link.ts +558 -0
- package/src/node/features/content-db.ts +475 -0
- package/src/node/features/disk-cache.ts +382 -0
- package/src/node/features/dns.ts +655 -0
- package/src/node/features/docker.ts +912 -0
- package/src/node/features/downloader.ts +92 -0
- package/src/node/features/esbuild.ts +68 -0
- package/src/node/features/file-manager.ts +357 -0
- package/src/node/features/fs.ts +534 -0
- package/src/node/features/git.ts +492 -0
- package/src/node/features/google-auth.ts +502 -0
- package/src/node/features/google-calendar.ts +300 -0
- package/src/node/features/google-docs.ts +404 -0
- package/src/node/features/google-drive.ts +339 -0
- package/src/node/features/google-sheets.ts +279 -0
- package/src/node/features/grep.ts +406 -0
- package/src/node/features/helpers.ts +374 -0
- package/src/node/features/ink.ts +490 -0
- package/src/node/features/ipc-socket.ts +459 -0
- package/src/node/features/json-tree.ts +188 -0
- package/src/node/features/launcher-app-command-listener.ts +388 -0
- package/src/node/features/networking.ts +925 -0
- package/src/node/features/nlp.ts +211 -0
- package/src/node/features/opener.ts +166 -0
- package/src/node/features/os.ts +157 -0
- package/src/node/features/package-finder.ts +539 -0
- package/src/node/features/port-exposer.ts +342 -0
- package/src/node/features/postgres.ts +273 -0
- package/src/node/features/proc.ts +502 -0
- package/src/node/features/process-manager.ts +542 -0
- package/src/node/features/python.ts +444 -0
- package/src/node/features/repl.ts +194 -0
- package/src/node/features/runpod.ts +802 -0
- package/src/node/features/secure-shell.ts +248 -0
- package/src/node/features/semantic-search.ts +924 -0
- package/src/node/features/sqlite.ts +289 -0
- package/src/node/features/telegram.ts +342 -0
- package/src/node/features/tts.ts +184 -0
- package/src/node/features/ui.ts +857 -0
- package/src/node/features/vault.ts +164 -0
- package/src/node/features/vm.ts +312 -0
- package/src/node/features/window-manager.ts +804 -0
- package/src/node/features/yaml-tree.ts +149 -0
- package/src/node/features/yaml.ts +132 -0
- package/src/node.ts +70 -0
- package/src/react/index.ts +175 -0
- package/src/registry.ts +199 -0
- package/src/scaffolds/generated.ts +1613 -0
- package/src/scaffolds/template.ts +37 -0
- package/src/schemas/base.ts +255 -0
- package/src/server.ts +135 -0
- package/src/servers/express.ts +209 -0
- package/src/servers/mcp.ts +805 -0
- package/src/servers/socket.ts +120 -0
- package/src/state.ts +101 -0
- package/src/web/clients/socket.ts +82 -0
- package/src/web/container.ts +74 -0
- package/src/web/extension.ts +30 -0
- package/src/web/feature.ts +12 -0
- package/src/web/features/asset-loader.ts +64 -0
- package/src/web/features/container-link.ts +385 -0
- package/src/web/features/esbuild.ts +79 -0
- package/src/web/features/helpers.ts +267 -0
- package/src/web/features/network.ts +61 -0
- package/src/web/features/speech.ts +87 -0
- package/src/web/features/vault.ts +189 -0
- package/src/web/features/vm.ts +78 -0
- package/src/web/features/voice-recognition.ts +129 -0
- package/src/web/shims/isomorphic-vm.ts +149 -0
- package/test/bus.test.ts +134 -0
- package/test/clients-servers.test.ts +216 -0
- package/test/container-link.test.ts +274 -0
- package/test/features.test.ts +160 -0
- package/test/integration.test.ts +787 -0
- package/test/node-container.test.ts +121 -0
- package/test/rate-limit.test.ts +272 -0
- package/test/semantic-search.test.ts +550 -0
- package/test/state.test.ts +121 -0
- package/test-integration/assistant.test.ts +138 -0
- package/test-integration/assistants-manager.test.ts +123 -0
- package/test-integration/claude-code.test.ts +98 -0
- package/test-integration/conversation-history.test.ts +205 -0
- package/test-integration/conversation.test.ts +137 -0
- package/test-integration/elevenlabs.test.ts +55 -0
- package/test-integration/google-services.test.ts +80 -0
- package/test-integration/helpers.ts +89 -0
- package/test-integration/openai-codex.test.ts +93 -0
- package/test-integration/runpod.test.ts +58 -0
- package/test-integration/server-endpoints.test.ts +97 -0
- package/test-integration/skills-library.test.ts +157 -0
- package/test-integration/telegram.test.ts +46 -0
- package/tsconfig.json +58 -0
- package/uv.lock +8 -0
|
@@ -0,0 +1,857 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { FeatureStateSchema } from '../../schemas/base.js'
|
|
3
|
+
import { features, Feature } from "../feature.js";
|
|
4
|
+
import colors from "chalk";
|
|
5
|
+
import type { Fonts } from "figlet";
|
|
6
|
+
|
|
7
|
+
let figlet: typeof import("figlet").default | null = null;
|
|
8
|
+
try {
|
|
9
|
+
figlet = require("figlet");
|
|
10
|
+
} catch {
|
|
11
|
+
// figlet not installed — asciiArt/banner will fall back to plain text
|
|
12
|
+
}
|
|
13
|
+
import inquirer from "inquirer";
|
|
14
|
+
import { marked } from 'marked';
|
|
15
|
+
import { markedTerminal } from 'marked-terminal';
|
|
16
|
+
import _endent from 'endent';
|
|
17
|
+
// Handle CJS/ESM interop for bun --compile
|
|
18
|
+
const endent = typeof _endent === 'function' ? _endent : (_endent as any).default;
|
|
19
|
+
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
marked.use(markedTerminal({ }));
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Zod schema for the UI feature state.
|
|
25
|
+
* Manages terminal UI configuration and cached data.
|
|
26
|
+
*/
|
|
27
|
+
export const UIStateSchema = FeatureStateSchema.extend({
|
|
28
|
+
/** Array of available fonts for ASCII art generation */
|
|
29
|
+
fonts: z.array(z.string()).optional().describe('Array of available fonts for ASCII art generation'),
|
|
30
|
+
/** Color palette for automatic color assignment */
|
|
31
|
+
colorPalette: z.array(z.string()).optional().describe('Color palette of hex colors for automatic color assignment'),
|
|
32
|
+
})
|
|
33
|
+
type UIState = z.infer<typeof UIStateSchema>
|
|
34
|
+
|
|
35
|
+
/** Global registry tracking assigned colors to prevent duplicates */
|
|
36
|
+
const _assignedColors: Record<string, string> = {};
|
|
37
|
+
|
|
38
|
+
/** Type representing available chalk color functions */
|
|
39
|
+
type Color = keyof typeof colors;
|
|
40
|
+
|
|
41
|
+
/** Basic print function signature */
|
|
42
|
+
type PrintFunction = (...args: any[]) => void;
|
|
43
|
+
|
|
44
|
+
/** Enhanced print function with color methods attached */
|
|
45
|
+
type ColoredPrintFunction = PrintFunction & {
|
|
46
|
+
[color in Color]: (...args: any[]) => void;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* UI Feature - Interactive Terminal User Interface Builder
|
|
51
|
+
*
|
|
52
|
+
* This feature provides comprehensive tools for creating beautiful, interactive terminal experiences.
|
|
53
|
+
* It combines several popular libraries (chalk, figlet, inquirer) into a unified interface for
|
|
54
|
+
* building professional CLI applications with colors, ASCII art, and interactive prompts.
|
|
55
|
+
*
|
|
56
|
+
* **Core Capabilities:**
|
|
57
|
+
* - Rich color management using chalk library
|
|
58
|
+
* - ASCII art generation with multiple fonts
|
|
59
|
+
* - Interactive prompts and wizards
|
|
60
|
+
* - Automatic color assignment for consistent theming
|
|
61
|
+
* - Text padding and formatting utilities
|
|
62
|
+
* - Gradient text effects (horizontal and vertical)
|
|
63
|
+
* - Banner creation with styled ASCII art
|
|
64
|
+
*
|
|
65
|
+
* **Color System:**
|
|
66
|
+
* - Full chalk API access for complex styling
|
|
67
|
+
* - Automatic color assignment with palette cycling
|
|
68
|
+
* - Consistent color mapping for named entities
|
|
69
|
+
* - Support for hex colors and gradients
|
|
70
|
+
*
|
|
71
|
+
* **ASCII Art Features:**
|
|
72
|
+
* - Multiple font options via figlet
|
|
73
|
+
* - Automatic font discovery and caching
|
|
74
|
+
* - Banner creation with color gradients
|
|
75
|
+
* - Text styling and effects
|
|
76
|
+
*
|
|
77
|
+
* **Interactive Elements:**
|
|
78
|
+
* - Wizard creation with inquirer integration
|
|
79
|
+
* - External editor integration
|
|
80
|
+
* - User input validation and processing
|
|
81
|
+
*
|
|
82
|
+
* **Usage Examples:**
|
|
83
|
+
*
|
|
84
|
+
* **Basic Colors:**
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const ui = container.feature('ui');
|
|
87
|
+
*
|
|
88
|
+
* // Direct color usage
|
|
89
|
+
* ui.print.red('Error message');
|
|
90
|
+
* ui.print.green('Success!');
|
|
91
|
+
*
|
|
92
|
+
* // Complex styling
|
|
93
|
+
* console.log(ui.colors.blue.bold.underline('Important text'));
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* **ASCII Art Banners:**
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const banner = ui.banner('MyApp', {
|
|
99
|
+
* font: 'Big',
|
|
100
|
+
* colors: ['red', 'white', 'blue']
|
|
101
|
+
* });
|
|
102
|
+
* console.log(banner);
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* **Interactive Wizards:**
|
|
106
|
+
* ```typescript
|
|
107
|
+
* const answers = await ui.wizard([
|
|
108
|
+
* { type: 'input', name: 'name', message: 'Your name?' },
|
|
109
|
+
* { type: 'confirm', name: 'continue', message: 'Continue?' }
|
|
110
|
+
* ]);
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* **Automatic Color Assignment:**
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const userColor = ui.assignColor('john');
|
|
116
|
+
* const adminColor = ui.assignColor('admin');
|
|
117
|
+
* console.log(userColor('John\'s message'));
|
|
118
|
+
* console.log(adminColor('Admin notice'));
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export class UI<T extends UIState = UIState> extends Feature<T> {
|
|
122
|
+
/** The shortcut path for accessing this feature */
|
|
123
|
+
static override shortcut = "features.ui" as const
|
|
124
|
+
static override stateSchema = UIStateSchema
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Gets the initial state configuration for the UI feature.
|
|
128
|
+
* Sets up default color palette and initializes empty fonts array.
|
|
129
|
+
*
|
|
130
|
+
* @returns The initial state with enabled flag, color palette, and fonts array
|
|
131
|
+
*/
|
|
132
|
+
override get initialState() : T {
|
|
133
|
+
return ({
|
|
134
|
+
enabled: true,
|
|
135
|
+
colorPalette: ASSIGNABLE_COLORS,
|
|
136
|
+
fonts: []
|
|
137
|
+
} as unknown) as T
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Enhanced print function with color methods for convenient terminal output */
|
|
141
|
+
print: ColoredPrintFunction = Object.assign((...args: any[]) => {
|
|
142
|
+
return console.log(...args)
|
|
143
|
+
}, {
|
|
144
|
+
red: (text: string) => console.log(colors.red(text)),
|
|
145
|
+
green: (text: string) => console.log(colors.green(text)),
|
|
146
|
+
blue: (text: string) => console.log(colors.blue(text)),
|
|
147
|
+
yellow: (text: string) => console.log(colors.yellow(text)),
|
|
148
|
+
cyan: (text: string) => console.log(colors.cyan(text)),
|
|
149
|
+
dim: (text: string) => console.log(colors.dim(text)),
|
|
150
|
+
bold: (text: string) => console.log(colors.bold(text)),
|
|
151
|
+
italic: (text: string) => console.log(colors.italic(text)),
|
|
152
|
+
underline: (text: string) => console.log(colors.underline(text)),
|
|
153
|
+
strikethrough: (text: string) => console.log(colors.strikethrough(text)),
|
|
154
|
+
inverse: (text: string) => console.log(colors.inverse(text)),
|
|
155
|
+
bgRed: (text: string) => console.log(colors.bgRed(text)),
|
|
156
|
+
bgGreen: (text: string) => console.log(colors.bgGreen(text)),
|
|
157
|
+
bgBlue: (text: string) => console.log(colors.bgBlue(text)),
|
|
158
|
+
bgYellow: (text: string) => console.log(colors.bgYellow(text)),
|
|
159
|
+
bgCyan: (text: string) => console.log(colors.bgCyan(text)),
|
|
160
|
+
bgMagenta: (text: string) => console.log(colors.bgMagenta(text)),
|
|
161
|
+
bgWhite: (text: string) => console.log(colors.bgWhite(text)),
|
|
162
|
+
}) as ColoredPrintFunction
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Parse markdown text and render it for terminal display using marked-terminal.
|
|
166
|
+
*
|
|
167
|
+
* @param text - The markdown string to parse and render
|
|
168
|
+
* @returns The rendered terminal-formatted string
|
|
169
|
+
*/
|
|
170
|
+
markdown(text: string) {
|
|
171
|
+
return marked.parse(text)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Provides access to the full chalk colors API.
|
|
177
|
+
*
|
|
178
|
+
* Chalk provides extensive color and styling capabilities including:
|
|
179
|
+
* - Basic colors: red, green, blue, yellow, etc.
|
|
180
|
+
* - Background colors: bgRed, bgGreen, etc.
|
|
181
|
+
* - Styles: bold, italic, underline, strikethrough
|
|
182
|
+
* - Advanced: rgb, hex, hsl color support
|
|
183
|
+
*
|
|
184
|
+
* Colors and styles can be chained for complex formatting.
|
|
185
|
+
*
|
|
186
|
+
* @returns The chalk colors object with all styling methods
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* // Basic colors
|
|
191
|
+
* ui.colors.red('Error message')
|
|
192
|
+
* ui.colors.green('Success!')
|
|
193
|
+
*
|
|
194
|
+
* // Chained styling
|
|
195
|
+
* ui.colors.blue.bold.underline('Important link')
|
|
196
|
+
* ui.colors.white.bgRed.bold(' ALERT ')
|
|
197
|
+
*
|
|
198
|
+
* // Hex and RGB colors
|
|
199
|
+
* ui.colors.hex('#FF5733')('Custom color')
|
|
200
|
+
* ui.colors.rgb(255, 87, 51)('RGB color')
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
get colors(): typeof colors {
|
|
204
|
+
return colors;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Gets the current color palette used for automatic color assignment.
|
|
209
|
+
*
|
|
210
|
+
* The color palette is a predefined set of hex colors that are automatically
|
|
211
|
+
* assigned to named entities in a cycling fashion. This ensures consistent
|
|
212
|
+
* color assignment across the application.
|
|
213
|
+
*
|
|
214
|
+
* @returns Array of hex color strings for automatic assignment
|
|
215
|
+
*/
|
|
216
|
+
get colorPalette(): string[] {
|
|
217
|
+
return this.state.get("colorPalette")!;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Assigns a consistent color to a named entity.
|
|
222
|
+
*
|
|
223
|
+
* This method provides automatic color assignment that remains consistent across
|
|
224
|
+
* the application session. Each unique name gets assigned a color from the palette,
|
|
225
|
+
* and subsequent calls with the same name return the same color function.
|
|
226
|
+
*
|
|
227
|
+
* **Assignment Strategy:**
|
|
228
|
+
* - First call with a name assigns the next available palette color
|
|
229
|
+
* - Subsequent calls return the previously assigned color
|
|
230
|
+
* - Colors cycle through the palette when all colors are used
|
|
231
|
+
* - Returns a chalk hex color function for styling text
|
|
232
|
+
*
|
|
233
|
+
* @param name - The unique identifier to assign a color to
|
|
234
|
+
* @returns A chalk color function for styling text with the assigned color
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* // Assign colors to users
|
|
239
|
+
* const johnColor = ui.assignColor('john');
|
|
240
|
+
* const janeColor = ui.assignColor('jane');
|
|
241
|
+
*
|
|
242
|
+
* // Use consistently throughout the app
|
|
243
|
+
* console.log(johnColor('John: Hello there!'));
|
|
244
|
+
* console.log(janeColor('Jane: Hi John!'));
|
|
245
|
+
* console.log(johnColor('John: How are you?')); // Same color as before
|
|
246
|
+
*
|
|
247
|
+
* // Different entities get different colors
|
|
248
|
+
* const errorColor = ui.assignColor('error');
|
|
249
|
+
* const successColor = ui.assignColor('success');
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
assignColor(name: string): (str: string) => string {
|
|
253
|
+
const assignedCount = Object.keys(_assignedColors).length;
|
|
254
|
+
|
|
255
|
+
if (_assignedColors[name]) {
|
|
256
|
+
const assigned = _assignedColors[name];
|
|
257
|
+
return this.colors.hex(assigned);
|
|
258
|
+
} else {
|
|
259
|
+
const pickedColor =
|
|
260
|
+
this.colorPalette[assignedCount % this.colorPalette.length];
|
|
261
|
+
_assignedColors[name] = pickedColor!;
|
|
262
|
+
return this.colors.hex(pickedColor!);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Gets a random color name from the available chalk colors.
|
|
268
|
+
*
|
|
269
|
+
* This provides access to a randomly selected color from chalk's built-in
|
|
270
|
+
* color set. Useful for adding variety to terminal output or testing.
|
|
271
|
+
*
|
|
272
|
+
* @returns A random color name that can be used with chalk
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* const randomColor = ui.randomColor;
|
|
277
|
+
* console.log(ui.colors[randomColor]('This text is a random color!'));
|
|
278
|
+
*
|
|
279
|
+
* // Use in loops for varied output
|
|
280
|
+
* items.forEach(item => {
|
|
281
|
+
* const color = ui.randomColor;
|
|
282
|
+
* console.log(ui.colors[color](`- ${item}`));
|
|
283
|
+
* });
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
get randomColor() {
|
|
287
|
+
const colors = Object.keys(this.colors);
|
|
288
|
+
const index = Math.floor(Math.random() * colors.length);
|
|
289
|
+
|
|
290
|
+
return colors[index];
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Gets an array of available fonts for ASCII art generation.
|
|
295
|
+
*
|
|
296
|
+
* This method provides access to all fonts available through figlet for
|
|
297
|
+
* creating ASCII art. The fonts are automatically discovered and cached
|
|
298
|
+
* on first access for performance.
|
|
299
|
+
*
|
|
300
|
+
* **Font Discovery:**
|
|
301
|
+
* - Fonts are loaded from figlet's built-in font collection
|
|
302
|
+
* - Results are cached in state to avoid repeated file system access
|
|
303
|
+
* - Returns comprehensive list of available font names
|
|
304
|
+
*
|
|
305
|
+
* @returns Array of font names that can be used with asciiArt() and banner()
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* // List all available fonts
|
|
310
|
+
* const fonts = ui.fonts;
|
|
311
|
+
* console.log(`Available fonts: ${fonts.join(', ')}`);
|
|
312
|
+
*
|
|
313
|
+
* // Use random font for variety
|
|
314
|
+
* const randomFont = fonts[Math.floor(Math.random() * fonts.length)];
|
|
315
|
+
* const art = ui.asciiArt('Hello', randomFont);
|
|
316
|
+
*
|
|
317
|
+
* // Common fonts: 'Big', 'Standard', 'Small', 'Slant', '3D-ASCII'
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
get fonts(): string[] {
|
|
321
|
+
const fonts = this.state.get("fonts")! || [];
|
|
322
|
+
|
|
323
|
+
if (!fonts.length && figlet) {
|
|
324
|
+
this.state.set("fonts", figlet.fontsSync());
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return this.state.get("fonts")!;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Creates an interactive wizard using inquirer prompts.
|
|
332
|
+
*
|
|
333
|
+
* This method provides a convenient wrapper around inquirer for creating
|
|
334
|
+
* interactive command-line wizards. It supports all inquirer question types
|
|
335
|
+
* and can handle complex validation and conditional logic.
|
|
336
|
+
*
|
|
337
|
+
* **Supported Question Types:**
|
|
338
|
+
* - input: Text input fields
|
|
339
|
+
* - confirm: Yes/no confirmations
|
|
340
|
+
* - list: Single selection from options
|
|
341
|
+
* - checkbox: Multiple selections
|
|
342
|
+
* - password: Hidden text input
|
|
343
|
+
* - editor: External editor integration
|
|
344
|
+
*
|
|
345
|
+
* **Advanced Features:**
|
|
346
|
+
* - Conditional questions based on previous answers
|
|
347
|
+
* - Input validation and transformation
|
|
348
|
+
* - Custom prompts and styling
|
|
349
|
+
* - Initial answer pre-population
|
|
350
|
+
*
|
|
351
|
+
* @param questions - Array of inquirer question objects
|
|
352
|
+
* @param initialAnswers - Pre-populated answers to skip questions or provide defaults
|
|
353
|
+
* @returns Promise resolving to the user's answers object
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```typescript
|
|
357
|
+
* // Basic wizard
|
|
358
|
+
* const answers = await ui.wizard([
|
|
359
|
+
* {
|
|
360
|
+
* type: 'input',
|
|
361
|
+
* name: 'projectName',
|
|
362
|
+
* message: 'What is your project name?',
|
|
363
|
+
* validate: (input) => input.length > 0 || 'Name is required'
|
|
364
|
+
* },
|
|
365
|
+
* {
|
|
366
|
+
* type: 'list',
|
|
367
|
+
* name: 'framework',
|
|
368
|
+
* message: 'Choose a framework:',
|
|
369
|
+
* choices: ['React', 'Vue', 'Angular', 'Svelte']
|
|
370
|
+
* },
|
|
371
|
+
* {
|
|
372
|
+
* type: 'confirm',
|
|
373
|
+
* name: 'typescript',
|
|
374
|
+
* message: 'Use TypeScript?',
|
|
375
|
+
* default: true
|
|
376
|
+
* }
|
|
377
|
+
* ]);
|
|
378
|
+
*
|
|
379
|
+
* console.log(`Creating ${answers.projectName} with ${answers.framework}`);
|
|
380
|
+
*
|
|
381
|
+
* // With initial answers
|
|
382
|
+
* const moreAnswers = await ui.wizard([
|
|
383
|
+
* { type: 'input', name: 'version', message: 'Version?' }
|
|
384
|
+
* ], { version: '1.0.0' });
|
|
385
|
+
* ```
|
|
386
|
+
*/
|
|
387
|
+
wizard(questions: any[], initialAnswers: any = {}) {
|
|
388
|
+
return inquirer.createPromptModule()(questions, initialAnswers);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Prompt the user with a single text input question.
|
|
393
|
+
*
|
|
394
|
+
* @param question - The question message to display
|
|
395
|
+
* @returns Promise resolving to the answers object with a `question` key
|
|
396
|
+
*/
|
|
397
|
+
askQuestion(question: string) {
|
|
398
|
+
return inquirer.createPromptModule()([{
|
|
399
|
+
type: 'input',
|
|
400
|
+
name: 'question',
|
|
401
|
+
message: question
|
|
402
|
+
}])
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Opens text in the user's external editor for editing.
|
|
407
|
+
*
|
|
408
|
+
* This method integrates with the user's configured editor (via $EDITOR or $VISUAL
|
|
409
|
+
* environment variables) to allow editing of text content. The edited content is
|
|
410
|
+
* returned when the user saves and closes the editor.
|
|
411
|
+
*
|
|
412
|
+
* **Editor Integration:**
|
|
413
|
+
* - Respects $EDITOR and $VISUAL environment variables
|
|
414
|
+
* - Creates temporary file with specified extension
|
|
415
|
+
* - Returns modified content after editor closes
|
|
416
|
+
* - Handles editor cancellation gracefully
|
|
417
|
+
*
|
|
418
|
+
* @param text - The initial text content to edit
|
|
419
|
+
* @param extension - File extension for syntax highlighting (default: ".ts")
|
|
420
|
+
* @returns Promise resolving to the edited text content
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```typescript
|
|
424
|
+
* // Edit code snippet
|
|
425
|
+
* const code = `function hello() {\n console.log('Hello');\n}`;
|
|
426
|
+
* const editedCode = await ui.openInEditor(code, '.js');
|
|
427
|
+
*
|
|
428
|
+
* // Edit configuration
|
|
429
|
+
* const config = JSON.stringify({ port: 3000 }, null, 2);
|
|
430
|
+
* const newConfig = await ui.openInEditor(config, '.json');
|
|
431
|
+
*
|
|
432
|
+
* // Edit markdown content
|
|
433
|
+
* const markdown = '# Title\n\nContent here...';
|
|
434
|
+
* const editedMarkdown = await ui.openInEditor(markdown, '.md');
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
async openInEditor(text: string, extension = ".ts") {
|
|
438
|
+
const results = await new Promise((resolve, reject) => {
|
|
439
|
+
/*
|
|
440
|
+
editAsync(
|
|
441
|
+
text,
|
|
442
|
+
(err, result) => {
|
|
443
|
+
if (err) {
|
|
444
|
+
return reject(err);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
return resolve(result);
|
|
448
|
+
},
|
|
449
|
+
{
|
|
450
|
+
postfix: extension,
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
*/
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
return results;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Generates ASCII art from text using the specified font.
|
|
461
|
+
*
|
|
462
|
+
* This method converts regular text into stylized ASCII art using figlet's
|
|
463
|
+
* extensive font collection. Perfect for creating eye-catching headers,
|
|
464
|
+
* logos, and decorative text in terminal applications.
|
|
465
|
+
*
|
|
466
|
+
* **Font Capabilities:**
|
|
467
|
+
* - Large collection of artistic fonts
|
|
468
|
+
* - Various styles: block, script, decorative, technical
|
|
469
|
+
* - Different sizes and character sets
|
|
470
|
+
* - Consistent spacing and alignment
|
|
471
|
+
*
|
|
472
|
+
* @param text - The text to convert to ASCII art
|
|
473
|
+
* @param font - The figlet font to use (see fonts property for available options)
|
|
474
|
+
* @returns The ASCII art representation of the text
|
|
475
|
+
*
|
|
476
|
+
* @throws {Error} When the specified font is not available
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```typescript
|
|
480
|
+
* // Create a banner
|
|
481
|
+
* const banner = ui.asciiArt('WELCOME', 'Big');
|
|
482
|
+
* console.log(banner);
|
|
483
|
+
*
|
|
484
|
+
* // Different fonts for different purposes
|
|
485
|
+
* const title = ui.asciiArt('MyApp', 'Standard');
|
|
486
|
+
* const subtitle = ui.asciiArt('v2.0', 'Small');
|
|
487
|
+
*
|
|
488
|
+
* // Technical/coding themes
|
|
489
|
+
* const code = ui.asciiArt('CODE', '3D-ASCII');
|
|
490
|
+
*
|
|
491
|
+
* // List available fonts first
|
|
492
|
+
* console.log('Available fonts:', ui.fonts.slice(0, 10).join(', '));
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
asciiArt(text: string, font: Fonts) {
|
|
496
|
+
if (!figlet) return text;
|
|
497
|
+
return figlet.textSync(text, font);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Creates a styled banner with ASCII art and color gradients.
|
|
502
|
+
*
|
|
503
|
+
* This method combines ASCII art generation with color gradient effects to create
|
|
504
|
+
* visually striking banners for terminal applications. It automatically applies
|
|
505
|
+
* color gradients to the generated ASCII art based on the specified options.
|
|
506
|
+
*
|
|
507
|
+
* **Banner Features:**
|
|
508
|
+
* - ASCII art text generation
|
|
509
|
+
* - Automatic color gradient application
|
|
510
|
+
* - Customizable gradient directions
|
|
511
|
+
* - Multiple color combinations
|
|
512
|
+
* - Professional terminal presentation
|
|
513
|
+
*
|
|
514
|
+
* @param text - The text to convert to a styled banner
|
|
515
|
+
* @param options - Banner styling options
|
|
516
|
+
* @param options.font - The figlet font to use for ASCII art generation
|
|
517
|
+
* @param options.colors - Array of colors for the gradient effect
|
|
518
|
+
* @returns The styled banner with ASCII art and color gradients
|
|
519
|
+
*
|
|
520
|
+
* @throws {Error} When required options are missing or invalid
|
|
521
|
+
*
|
|
522
|
+
* @example
|
|
523
|
+
* ```typescript
|
|
524
|
+
* // Classic patriotic banner
|
|
525
|
+
* const banner = ui.banner('AMERICA', {
|
|
526
|
+
* font: 'Big',
|
|
527
|
+
* colors: ['red', 'white', 'blue']
|
|
528
|
+
* });
|
|
529
|
+
* console.log(banner);
|
|
530
|
+
*
|
|
531
|
+
* // Tech company banner
|
|
532
|
+
* const techBanner = ui.banner('TechCorp', {
|
|
533
|
+
* font: 'Slant',
|
|
534
|
+
* colors: ['cyan', 'blue', 'magenta']
|
|
535
|
+
* });
|
|
536
|
+
*
|
|
537
|
+
* // Warning banner
|
|
538
|
+
* const warningBanner = ui.banner('WARNING', {
|
|
539
|
+
* font: 'Standard',
|
|
540
|
+
* colors: ['yellow', 'red']
|
|
541
|
+
* });
|
|
542
|
+
*
|
|
543
|
+
* // Available fonts: see ui.fonts property
|
|
544
|
+
* // Available colors: any chalk color names
|
|
545
|
+
* ```
|
|
546
|
+
*/
|
|
547
|
+
banner(text: string, options: { font: Fonts; colors: Color[] } = { font: 'Star Wars', colors: ['red', 'white', 'blue'] }) {
|
|
548
|
+
const art = this.asciiArt(text, options.font || 'Star Wars');
|
|
549
|
+
const colored = this.applyGradient(art, options.colors || ['red', 'white', 'blue']);
|
|
550
|
+
|
|
551
|
+
return colored;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Dedent and format a tagged template literal using endent.
|
|
556
|
+
* Strips leading indentation while preserving relative indentation.
|
|
557
|
+
*
|
|
558
|
+
* @param args - Tagged template literal arguments
|
|
559
|
+
* @returns The dedented string
|
|
560
|
+
*/
|
|
561
|
+
endent(...args: any[]) {
|
|
562
|
+
// @ts-ignore
|
|
563
|
+
return endent(...args)
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Applies color gradients to text with configurable direction.
|
|
568
|
+
*
|
|
569
|
+
* This method creates smooth color transitions across text content, supporting
|
|
570
|
+
* both horizontal (character-by-character) and vertical (line-by-line) gradients.
|
|
571
|
+
* Perfect for creating visually appealing terminal output and ASCII art effects.
|
|
572
|
+
*
|
|
573
|
+
* **Gradient Types:**
|
|
574
|
+
* - Horizontal: Colors transition across characters in each line
|
|
575
|
+
* - Vertical: Colors transition across lines of text
|
|
576
|
+
* - Customizable color sequences and transitions
|
|
577
|
+
* - Automatic color cycling for long content
|
|
578
|
+
*
|
|
579
|
+
* @param text - The text content to apply gradients to
|
|
580
|
+
* @param lineColors - Array of colors to cycle through in the gradient
|
|
581
|
+
* @param direction - Gradient direction: 'horizontal' or 'vertical'
|
|
582
|
+
* @returns The text with applied color gradients
|
|
583
|
+
*
|
|
584
|
+
* @example
|
|
585
|
+
* ```typescript
|
|
586
|
+
* // Horizontal rainbow effect
|
|
587
|
+
* const rainbow = ui.applyGradient('Hello World!',
|
|
588
|
+
* ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta'],
|
|
589
|
+
* 'horizontal'
|
|
590
|
+
* );
|
|
591
|
+
*
|
|
592
|
+
* // Vertical gradient for multi-line text
|
|
593
|
+
* const multiline = 'Line 1\nLine 2\nLine 3\nLine 4';
|
|
594
|
+
* const vertical = ui.applyGradient(multiline,
|
|
595
|
+
* ['red', 'white', 'blue'],
|
|
596
|
+
* 'vertical'
|
|
597
|
+
* );
|
|
598
|
+
*
|
|
599
|
+
* // Fire effect
|
|
600
|
+
* const fire = ui.applyGradient('FIRE', ['red', 'yellow'], 'horizontal');
|
|
601
|
+
*
|
|
602
|
+
* // Ocean effect
|
|
603
|
+
* const ocean = ui.applyGradient('OCEAN', ['blue', 'cyan', 'white'], 'vertical');
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
606
|
+
applyGradient(
|
|
607
|
+
text: string,
|
|
608
|
+
lineColors: Color[] = ["red", "white", "blue"],
|
|
609
|
+
direction: "horizontal" | "vertical" = "horizontal"
|
|
610
|
+
) {
|
|
611
|
+
if (direction === "horizontal") {
|
|
612
|
+
return this.applyHorizontalGradient(text, lineColors);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
return this.applyVerticalGradient(text, lineColors);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Applies horizontal color gradients character by character.
|
|
620
|
+
*
|
|
621
|
+
* This method creates color transitions across characters within the text,
|
|
622
|
+
* cycling through the provided colors to create smooth horizontal gradients.
|
|
623
|
+
* Each character gets assigned a color based on its position in the sequence.
|
|
624
|
+
*
|
|
625
|
+
* **Horizontal Gradient Behavior:**
|
|
626
|
+
* - Each character is individually colored
|
|
627
|
+
* - Colors cycle through the provided array
|
|
628
|
+
* - Creates smooth transitions across text width
|
|
629
|
+
* - Works well with ASCII art and single lines
|
|
630
|
+
*
|
|
631
|
+
* @param text - The text to apply horizontal gradients to
|
|
632
|
+
* @param lineColors - Array of colors to cycle through
|
|
633
|
+
* @returns Text with horizontal color gradients applied
|
|
634
|
+
*
|
|
635
|
+
* @example
|
|
636
|
+
* ```typescript
|
|
637
|
+
* // Rainbow effect across characters
|
|
638
|
+
* const rainbow = ui.applyHorizontalGradient('RAINBOW',
|
|
639
|
+
* ['red', 'yellow', 'green', 'cyan', 'blue', 'magenta']
|
|
640
|
+
* );
|
|
641
|
+
*
|
|
642
|
+
* // Simple two-color transition
|
|
643
|
+
* const sunset = ui.applyHorizontalGradient('SUNSET', ['red', 'orange']);
|
|
644
|
+
*
|
|
645
|
+
* // Great for short text and ASCII art
|
|
646
|
+
* const art = ui.asciiArt('COOL', 'Big');
|
|
647
|
+
* const coloredArt = ui.applyHorizontalGradient(art, ['cyan', 'blue']);
|
|
648
|
+
* ```
|
|
649
|
+
*/
|
|
650
|
+
applyHorizontalGradient(
|
|
651
|
+
text: string,
|
|
652
|
+
lineColors: Color[] = ["red", "white", "blue"]
|
|
653
|
+
) {
|
|
654
|
+
const gColors = Object.fromEntries(
|
|
655
|
+
lineColors.map((color) => [color, this.colors[color]])
|
|
656
|
+
);
|
|
657
|
+
const lines = text.split("");
|
|
658
|
+
|
|
659
|
+
const colored = lines.map((line, index) => {
|
|
660
|
+
const colorFn = gColors[lineColors[index % lineColors.length]!]!;
|
|
661
|
+
// @ts-ignore-next-line
|
|
662
|
+
return colorFn(line);
|
|
663
|
+
});
|
|
664
|
+
|
|
665
|
+
return colored.join("");
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Applies vertical color gradients line by line.
|
|
670
|
+
*
|
|
671
|
+
* This method creates color transitions across lines of text, with each line
|
|
672
|
+
* getting a different color from the sequence. Perfect for multi-line content
|
|
673
|
+
* like ASCII art, banners, and structured output.
|
|
674
|
+
*
|
|
675
|
+
* **Vertical Gradient Behavior:**
|
|
676
|
+
* - Each line is colored uniformly
|
|
677
|
+
* - Colors cycle through the provided array
|
|
678
|
+
* - Creates smooth transitions across text height
|
|
679
|
+
* - Ideal for multi-line ASCII art and structured content
|
|
680
|
+
*
|
|
681
|
+
* @param text - The text to apply vertical gradients to (supports newlines)
|
|
682
|
+
* @param lineColors - Array of colors to cycle through for each line
|
|
683
|
+
* @returns Text with vertical color gradients applied
|
|
684
|
+
*
|
|
685
|
+
* @example
|
|
686
|
+
* ```typescript
|
|
687
|
+
* // Patriotic vertical gradient
|
|
688
|
+
* const flag = 'USA\nUSA\nUSA\nUSA';
|
|
689
|
+
* const patriotic = ui.applyVerticalGradient(flag, ['red', 'white', 'blue']);
|
|
690
|
+
*
|
|
691
|
+
* // Sunset effect on ASCII art
|
|
692
|
+
* const banner = ui.asciiArt('SUNSET', 'Big');
|
|
693
|
+
* const sunset = ui.applyVerticalGradient(banner,
|
|
694
|
+
* ['yellow', 'orange', 'red', 'purple']
|
|
695
|
+
* );
|
|
696
|
+
*
|
|
697
|
+
* // Ocean waves effect
|
|
698
|
+
* const waves = 'Wave 1\nWave 2\nWave 3\nWave 4\nWave 5';
|
|
699
|
+
* const ocean = ui.applyVerticalGradient(waves, ['cyan', 'blue']);
|
|
700
|
+
* ```
|
|
701
|
+
*/
|
|
702
|
+
applyVerticalGradient(
|
|
703
|
+
text: string,
|
|
704
|
+
lineColors: Color[] = ["red", "white", "blue"]
|
|
705
|
+
) {
|
|
706
|
+
const gColors = Object.fromEntries(
|
|
707
|
+
lineColors.map((color) => [color, this.colors[color]])
|
|
708
|
+
);
|
|
709
|
+
const lines = text.split("\n");
|
|
710
|
+
const colored = lines.map((line, index) => {
|
|
711
|
+
const colorFn = gColors[lineColors[index % lineColors.length]!]!;
|
|
712
|
+
// @ts-ignore-next-line
|
|
713
|
+
return colorFn(line);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
return colored.join("\n");
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/**
|
|
720
|
+
* Pads text on the left to reach the specified length.
|
|
721
|
+
*
|
|
722
|
+
* This utility method adds padding characters to the left side of text to achieve
|
|
723
|
+
* a desired total length. Useful for creating aligned columns, formatted tables,
|
|
724
|
+
* and consistent text layout in terminal applications.
|
|
725
|
+
*
|
|
726
|
+
* **Padding Behavior:**
|
|
727
|
+
* - Adds padding to the left (start) of the string
|
|
728
|
+
* - Uses specified padding character (default: space)
|
|
729
|
+
* - Returns original string if already at or beyond target length
|
|
730
|
+
* - Handles multi-character padding by repeating the character
|
|
731
|
+
*
|
|
732
|
+
* @param str - The string to pad
|
|
733
|
+
* @param length - The desired total length after padding
|
|
734
|
+
* @param padChar - The character to use for padding (default: " ")
|
|
735
|
+
* @returns The left-padded string
|
|
736
|
+
*
|
|
737
|
+
* @example
|
|
738
|
+
* ```typescript
|
|
739
|
+
* // Number alignment
|
|
740
|
+
* const numbers = ['1', '23', '456'];
|
|
741
|
+
* numbers.forEach(num => {
|
|
742
|
+
* console.log(ui.padLeft(num, 5, '0')); // '00001', '00023', '00456'
|
|
743
|
+
* });
|
|
744
|
+
*
|
|
745
|
+
* // Text alignment in columns
|
|
746
|
+
* const items = ['apple', 'banana', 'cherry'];
|
|
747
|
+
* items.forEach(item => {
|
|
748
|
+
* console.log(ui.padLeft(item, 10) + ' | Price: $1.00');
|
|
749
|
+
* });
|
|
750
|
+
*
|
|
751
|
+
* // Custom padding character
|
|
752
|
+
* const title = ui.padLeft('TITLE', 20, '-'); // '---------------TITLE'
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
padLeft(str: string, length: number, padChar = " ") {
|
|
756
|
+
if (str.length >= length) {
|
|
757
|
+
return str;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
const padding = Array(length - str.length)
|
|
761
|
+
.fill(padChar)
|
|
762
|
+
.join("");
|
|
763
|
+
|
|
764
|
+
return padding + str;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Pads text on the right to reach the specified length.
|
|
769
|
+
*
|
|
770
|
+
* This utility method adds padding characters to the right side of text to achieve
|
|
771
|
+
* a desired total length. Essential for creating properly aligned columns, tables,
|
|
772
|
+
* and formatted output in terminal applications.
|
|
773
|
+
*
|
|
774
|
+
* **Padding Behavior:**
|
|
775
|
+
* - Adds padding to the right (end) of the string
|
|
776
|
+
* - Uses specified padding character (default: space)
|
|
777
|
+
* - Returns original string if already at or beyond target length
|
|
778
|
+
* - Handles multi-character padding by repeating the character
|
|
779
|
+
*
|
|
780
|
+
* @param str - The string to pad
|
|
781
|
+
* @param length - The desired total length after padding
|
|
782
|
+
* @param padChar - The character to use for padding (default: " ")
|
|
783
|
+
* @returns The right-padded string
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```typescript
|
|
787
|
+
* // Create aligned table columns
|
|
788
|
+
* const data = [
|
|
789
|
+
* ['Name', 'Age', 'City'],
|
|
790
|
+
* ['John', '25', 'NYC'],
|
|
791
|
+
* ['Jane', '30', 'LA'],
|
|
792
|
+
* ['Bob', '35', 'Chicago']
|
|
793
|
+
* ];
|
|
794
|
+
*
|
|
795
|
+
* data.forEach(row => {
|
|
796
|
+
* const formatted = row.map((cell, i) => {
|
|
797
|
+
* const widths = [15, 5, 10];
|
|
798
|
+
* return ui.padRight(cell, widths[i]);
|
|
799
|
+
* }).join(' | ');
|
|
800
|
+
* console.log(formatted);
|
|
801
|
+
* });
|
|
802
|
+
*
|
|
803
|
+
* // Progress bars
|
|
804
|
+
* const progress = ui.padRight('████', 20, '░'); // '████░░░░░░░░░░░░░░░░'
|
|
805
|
+
*
|
|
806
|
+
* // Menu items with dots
|
|
807
|
+
* const menuItem = ui.padRight('Coffee', 20, '.') + '$3.50';
|
|
808
|
+
* ```
|
|
809
|
+
*/
|
|
810
|
+
padRight(str: string, length: number, padChar = " ") {
|
|
811
|
+
if (str.length >= length) {
|
|
812
|
+
return str;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const padding = Array(length - str.length)
|
|
816
|
+
.fill(padChar)
|
|
817
|
+
.join("");
|
|
818
|
+
return str + padding;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
export default features.register("ui", UI);
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* Predefined color palette for automatic color assignment.
|
|
826
|
+
*
|
|
827
|
+
* This carefully curated palette provides visually distinct colors that work well
|
|
828
|
+
* in terminal environments. Colors are chosen for readability, contrast, and
|
|
829
|
+
* aesthetic appeal across different terminal themes.
|
|
830
|
+
*
|
|
831
|
+
* **Palette Characteristics:**
|
|
832
|
+
* - 16 distinct hex colors
|
|
833
|
+
* - Good contrast on both light and dark backgrounds
|
|
834
|
+
* - Balanced saturation and brightness
|
|
835
|
+
* - Accessible color combinations
|
|
836
|
+
* - Professional appearance
|
|
837
|
+
*
|
|
838
|
+
* @constant
|
|
839
|
+
*/
|
|
840
|
+
const ASSIGNABLE_COLORS = [
|
|
841
|
+
"#FF6B6B",
|
|
842
|
+
"#FFD166",
|
|
843
|
+
"#4ECDC4",
|
|
844
|
+
"#54C6EB",
|
|
845
|
+
"#A3D9FF",
|
|
846
|
+
"#88D498",
|
|
847
|
+
"#9C89B8",
|
|
848
|
+
"#F08A5D",
|
|
849
|
+
"#B83B5E",
|
|
850
|
+
"#6A2C70",
|
|
851
|
+
"#F38181",
|
|
852
|
+
"#95E1D3",
|
|
853
|
+
"#EAFDE6",
|
|
854
|
+
"#FCE38A",
|
|
855
|
+
"#EAFFD0",
|
|
856
|
+
"#BDE4F4",
|
|
857
|
+
];
|