From 2807e34ce6ceb22b3a3675dc81344be839d88351 Mon Sep 17 00:00:00 2001 From: Jeff Wainwright <1074042+yowainwright@users.noreply.github.com> Date: Thu, 1 Jan 2026 02:30:47 -0800 Subject: [PATCH 1/4] fix(app): fixes the app --- bun.lock | 3 + site/app/demos/page.tsx | 36 + site/components/cli-demo/constants.ts | 50 ++ site/components/cli-demo/index.tsx | 216 ++++++ site/components/cli-demo/types.ts | 10 + .../interactive/CodeExample/constants.ts | 18 + .../interactive/CodeExample/index.tsx | 39 + .../interactive/CodeExample/types.ts | 11 + .../interactive/PreviewPane/constants.ts | 7 + .../interactive/PreviewPane/index.tsx | 59 ++ .../interactive/PreviewPane/types.ts | 10 + .../interactive/ThemeControls/constants.ts | 8 + .../interactive/ThemeControls/index.tsx | 67 ++ .../interactive/ThemeControls/types.ts | 9 + site/components/interactive/constants.ts | 34 + site/components/interactive/index.tsx | 733 +++--------------- site/components/log-playground/OutputPane.tsx | 65 ++ .../log-playground/ThemeSelector.tsx | 31 + site/components/log-playground/constants.ts | 32 + site/components/log-playground/index.tsx | 143 ++++ site/components/log-playground/types.ts | 9 + .../output-comparison/GhosttyTerminal.tsx | 114 +++ .../components/output-comparison/constants.ts | 43 + site/components/output-comparison/index.tsx | 291 +++++++ site/components/output-comparison/types.ts | 16 + site/components/schema-viz/constants.ts | 136 ++++ site/components/schema-viz/index.tsx | 159 ++++ site/components/schema-viz/types.ts | 13 + site/components/theme-card.tsx | 296 ------- .../theme-card/LogPane/constants.ts | 9 + site/components/theme-card/LogPane/index.tsx | 53 ++ site/components/theme-card/LogPane/types.ts | 7 + site/components/theme-card/constants.ts | 26 + site/components/theme-card/index.tsx | 58 ++ site/components/theme-card/types.ts | 9 + site/components/theme-card/utils.ts | 6 + site/hooks/useThemeProcessor.ts | 138 ++++ site/next-env.d.ts | 2 +- site/package.json | 1 + .../components/cli-demo/CliDemo.test.tsx | 54 ++ .../interactive/CodeExample.test.tsx | 46 ++ .../interactive/PreviewPane.test.tsx | 64 ++ .../interactive/ThemeControls.test.tsx | 57 ++ .../log-playground/LogPlayground.test.tsx | 61 ++ .../OutputComparison.test.tsx | 51 ++ .../schema-viz/SchemaVisualization.test.tsx | 61 ++ .../components/theme-card/LogPane.test.tsx | 62 ++ .../components/theme-card/ThemeCard.test.tsx | 51 ++ src/cli/index.ts | 5 +- src/index.ts | 11 +- src/themes/index.ts | 1 - src/themes/registry.ts | 5 +- src/tokenizer/index.ts | 13 +- src/utils/index.ts | 3 +- src/utils/logger.ts | 89 ++- tests/unit/utils/logger.test.ts | 87 ++- 56 files changed, 2709 insertions(+), 979 deletions(-) create mode 100644 site/app/demos/page.tsx create mode 100644 site/components/cli-demo/constants.ts create mode 100644 site/components/cli-demo/index.tsx create mode 100644 site/components/cli-demo/types.ts create mode 100644 site/components/interactive/CodeExample/constants.ts create mode 100644 site/components/interactive/CodeExample/index.tsx create mode 100644 site/components/interactive/CodeExample/types.ts create mode 100644 site/components/interactive/PreviewPane/constants.ts create mode 100644 site/components/interactive/PreviewPane/index.tsx create mode 100644 site/components/interactive/PreviewPane/types.ts create mode 100644 site/components/interactive/ThemeControls/constants.ts create mode 100644 site/components/interactive/ThemeControls/index.tsx create mode 100644 site/components/interactive/ThemeControls/types.ts create mode 100644 site/components/interactive/constants.ts create mode 100644 site/components/log-playground/OutputPane.tsx create mode 100644 site/components/log-playground/ThemeSelector.tsx create mode 100644 site/components/log-playground/constants.ts create mode 100644 site/components/log-playground/index.tsx create mode 100644 site/components/log-playground/types.ts create mode 100644 site/components/output-comparison/GhosttyTerminal.tsx create mode 100644 site/components/output-comparison/constants.ts create mode 100644 site/components/output-comparison/index.tsx create mode 100644 site/components/output-comparison/types.ts create mode 100644 site/components/schema-viz/constants.ts create mode 100644 site/components/schema-viz/index.tsx create mode 100644 site/components/schema-viz/types.ts delete mode 100644 site/components/theme-card.tsx create mode 100644 site/components/theme-card/LogPane/constants.ts create mode 100644 site/components/theme-card/LogPane/index.tsx create mode 100644 site/components/theme-card/LogPane/types.ts create mode 100644 site/components/theme-card/constants.ts create mode 100644 site/components/theme-card/index.tsx create mode 100644 site/components/theme-card/types.ts create mode 100644 site/components/theme-card/utils.ts create mode 100644 site/hooks/useThemeProcessor.ts create mode 100644 site/tests/components/cli-demo/CliDemo.test.tsx create mode 100644 site/tests/components/interactive/CodeExample.test.tsx create mode 100644 site/tests/components/interactive/PreviewPane.test.tsx create mode 100644 site/tests/components/interactive/ThemeControls.test.tsx create mode 100644 site/tests/components/log-playground/LogPlayground.test.tsx create mode 100644 site/tests/components/output-comparison/OutputComparison.test.tsx create mode 100644 site/tests/components/schema-viz/SchemaVisualization.test.tsx create mode 100644 site/tests/components/theme-card/LogPane.test.tsx create mode 100644 site/tests/components/theme-card/ThemeCard.test.tsx diff --git a/bun.lock b/bun.lock index c81936d..27f576d 100644 --- a/bun.lock +++ b/bun.lock @@ -37,6 +37,7 @@ "ansi-to-html": "^0.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "ghostty-web": "^0.4.0", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "idb": "^8.0.3", @@ -508,6 +509,8 @@ "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + "ghostty-web": ["ghostty-web@0.4.0", "", {}, "sha512-0puDBik2qapbD/QQBW9o5ZHfXnZBqZWx/ctBiVtKZ6ZLds4NYb+wZuw1cRLXZk9zYovIQ908z3rvFhexAvc5Hg=="], + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], diff --git a/site/app/demos/page.tsx b/site/app/demos/page.tsx new file mode 100644 index 0000000..604e81f --- /dev/null +++ b/site/app/demos/page.tsx @@ -0,0 +1,36 @@ +"use client"; + +import { Navbar } from "@/components/navbar"; +import { OutputComparison } from "@/components/output-comparison"; +import { LogPlayground } from "@/components/log-playground"; +import { CliDemo } from "@/components/cli-demo"; +import { SchemaVisualization } from "@/components/schema-viz"; + +export default function DemosPage() { + return ( +
+ + +
+
+
+

+ + Live + {" "} + Demos +

+

+ See logsDX in action with real terminal and browser output comparisons +

+
+
+
+ + + + + +
+ ); +} diff --git a/site/components/cli-demo/constants.ts b/site/components/cli-demo/constants.ts new file mode 100644 index 0000000..7060470 --- /dev/null +++ b/site/components/cli-demo/constants.ts @@ -0,0 +1,50 @@ +import type { CliFeature } from "./types"; + +export const CLI_FEATURES: CliFeature[] = [ + { + title: "Pipe Logs", + description: "Pipe any log output through logsdx for instant styling", + command: "cat server.log | logsdx --theme dracula", + }, + { + title: "Process Files", + description: "Process log files directly with your chosen theme", + command: "logsdx process app.log --theme github-dark", + }, + { + title: "Interactive Theme Creator", + description: "Create custom themes with an interactive wizard", + command: "logsdx create-theme", + }, + { + title: "Preview Themes", + description: "Preview any theme with sample logs before using", + command: "logsdx preview --theme nord", + }, + { + title: "Tail with Style", + description: "Follow logs in real-time with beautiful styling", + command: "tail -f /var/log/app.log | logsdx --theme monokai", + }, + { + title: "List Themes", + description: "View all available built-in themes", + command: "logsdx themes", + }, +]; + +export const INSTALL_COMMANDS = { + npm: "npm install -g logsdx", + pnpm: "pnpm add -g logsdx", + bun: "bun add -g logsdx", +} as const; + +export const TERMINAL_COLORS = { + bg: "#1a1b26", + headerBg: "#24283b", + border: "#414868", + text: "#a9b1d6", + prompt: "#7aa2f7", + command: "#9ece6a", + output: "#787c99", +} as const; diff --git a/site/components/cli-demo/index.tsx b/site/components/cli-demo/index.tsx new file mode 100644 index 0000000..0c39bfc --- /dev/null +++ b/site/components/cli-demo/index.tsx @@ -0,0 +1,216 @@ +"use client"; + +import React, { useState } from "react"; +import { CLI_FEATURES, INSTALL_COMMANDS, TERMINAL_COLORS } from "./constants"; + +type PackageManager = keyof typeof INSTALL_COMMANDS; + +export function CliDemo() { + const [activeFeature, setActiveFeature] = useState(0); + const [packageManager, setPackageManager] = useState("npm"); + + const feature = CLI_FEATURES[activeFeature]; + + return ( +
+
+
+

+ + Powerful + {" "} + CLI +

+

+ Style your logs from anywhere with a single command +

+ +
+
+ {(Object.keys(INSTALL_COMMANDS) as PackageManager[]).map((pm) => ( + + ))} +
+
+ $ + + {INSTALL_COMMANDS[packageManager]} + +
+
+ +
+
+ {CLI_FEATURES.map((f, i) => ( + + ))} +
+ +
+
+
+
+
+
+
+ Terminal +
+
+
+ ~ $ + + {feature.command} + +
+
+ {activeFeature === 0 && ( + + )} + {activeFeature === 1 && ( + + )} + {activeFeature === 2 && ( + + )} + {activeFeature === 3 && ( + + )} + {activeFeature === 4 && ( + + )} + {activeFeature === 5 && ( + + )} +
+
+
+
+
+
+
+ ); +} + +interface TerminalLine { + text: string; + color: string; + blink?: boolean; +} + +function TerminalOutput({ lines }: { lines: TerminalLine[] }) { + return ( + <> + {lines.map((line, i) => ( +
+ {line.text} +
+ ))} + + ); +} + +export type { CliFeature } from "./types"; diff --git a/site/components/cli-demo/types.ts b/site/components/cli-demo/types.ts new file mode 100644 index 0000000..1889381 --- /dev/null +++ b/site/components/cli-demo/types.ts @@ -0,0 +1,10 @@ +export interface CliCommand { + command: string; + description: string; +} + +export interface CliFeature { + title: string; + description: string; + command: string; +} diff --git a/site/components/interactive/CodeExample/constants.ts b/site/components/interactive/CodeExample/constants.ts new file mode 100644 index 0000000..12b6b0c --- /dev/null +++ b/site/components/interactive/CodeExample/constants.ts @@ -0,0 +1,18 @@ +import type { ThemeBackground } from "./types"; + +export const THEME_BACKGROUNDS: Record = { + "github-light": { bg: "#ffffff", headerBg: "#f6f8fa", border: "#d1d9e0" }, + "github-dark": { bg: "#0d1117", headerBg: "#161b22", border: "#30363d" }, + "solarized-light": { bg: "#fdf6e3", headerBg: "#eee8d5", border: "#eee8d5" }, + "solarized-dark": { bg: "#002b36", headerBg: "#073642", border: "#073642" }, + dracula: { bg: "#282a36", headerBg: "#1e1f29", border: "#44475a" }, + nord: { bg: "#2e3440", headerBg: "#3b4252", border: "#4c566a" }, + monokai: { bg: "#272822", headerBg: "#3e3d32", border: "#75715e" }, + "oh-my-zsh": { bg: "#2c3e50", headerBg: "#34495e", border: "#34495e" }, +}; + +export const DEFAULT_BACKGROUND: ThemeBackground = { + bg: "#0d1117", + headerBg: "#161b22", + border: "#30363d", +}; diff --git a/site/components/interactive/CodeExample/index.tsx b/site/components/interactive/CodeExample/index.tsx new file mode 100644 index 0000000..98594da --- /dev/null +++ b/site/components/interactive/CodeExample/index.tsx @@ -0,0 +1,39 @@ +"use client"; + +import React from "react"; +import { THEME_BACKGROUNDS, DEFAULT_BACKGROUND } from "./constants"; +import type { CodeExampleProps } from "./types"; + +export function CodeExample({ title, code, themeName }: CodeExampleProps) { + const bg = THEME_BACKGROUNDS[themeName] || DEFAULT_BACKGROUND; + + return ( +
+
+
+
+
+
+
+ {title} +
+
+
{code}
+
+
+ Theme: {themeName} +
+
+ ); +} + +export type { CodeExampleProps } from "./types"; diff --git a/site/components/interactive/CodeExample/types.ts b/site/components/interactive/CodeExample/types.ts new file mode 100644 index 0000000..2312cc0 --- /dev/null +++ b/site/components/interactive/CodeExample/types.ts @@ -0,0 +1,11 @@ +export interface CodeExampleProps { + title: string; + code: string; + themeName: string; +} + +export interface ThemeBackground { + bg: string; + headerBg: string; + border: string; +} diff --git a/site/components/interactive/PreviewPane/constants.ts b/site/components/interactive/PreviewPane/constants.ts new file mode 100644 index 0000000..d978bdc --- /dev/null +++ b/site/components/interactive/PreviewPane/constants.ts @@ -0,0 +1,7 @@ +export const WINDOW_BUTTON_COLORS = { + close: "bg-red-500", + minimize: "bg-yellow-500", + maximize: "bg-green-500", +} as const; + +export const DEFAULT_HEIGHT = "h-96"; diff --git a/site/components/interactive/PreviewPane/index.tsx b/site/components/interactive/PreviewPane/index.tsx new file mode 100644 index 0000000..25f78e9 --- /dev/null +++ b/site/components/interactive/PreviewPane/index.tsx @@ -0,0 +1,59 @@ +"use client"; + +import React from "react"; +import type { PreviewPaneProps } from "./types"; +import { WINDOW_BUTTON_COLORS, DEFAULT_HEIGHT } from "./constants"; + +export function PreviewPane({ + title, + themeName, + logs, + backgroundColor, + headerBg, + borderColor, + isLoading = false, + showBorder = false, +}: PreviewPaneProps) { + return ( +
+
+
+
+
+
+
+ {title} +
+
+ {isLoading ? ( +
+
Loading...
+
+ ) : ( + logs.map((log, i) => ( +
+ )) + )} +
+
+ Theme: {themeName} +
+
+ ); +} + +export type { PreviewPaneProps } from "./types"; diff --git a/site/components/interactive/PreviewPane/types.ts b/site/components/interactive/PreviewPane/types.ts new file mode 100644 index 0000000..a52acdf --- /dev/null +++ b/site/components/interactive/PreviewPane/types.ts @@ -0,0 +1,10 @@ +export interface PreviewPaneProps { + title: string; + themeName: string; + logs: string[]; + backgroundColor: string; + headerBg: string; + borderColor: string; + isLoading?: boolean; + showBorder?: boolean; +} diff --git a/site/components/interactive/ThemeControls/constants.ts b/site/components/interactive/ThemeControls/constants.ts new file mode 100644 index 0000000..228e4dc --- /dev/null +++ b/site/components/interactive/ThemeControls/constants.ts @@ -0,0 +1,8 @@ +export const THEME_NAMES = [ + "GitHub", + "Solarized", + "Dracula", + "Nord", + "Monokai", + "Oh My Zsh", +] as const; diff --git a/site/components/interactive/ThemeControls/index.tsx b/site/components/interactive/ThemeControls/index.tsx new file mode 100644 index 0000000..bba6953 --- /dev/null +++ b/site/components/interactive/ThemeControls/index.tsx @@ -0,0 +1,67 @@ +"use client"; + +import React from "react"; +import { Button } from "@/components/ui/button"; +import { Moon, Sun, Monitor } from "lucide-react"; +import { THEME_NAMES } from "./constants"; +import type { ThemeControlsProps } from "./types"; + +export function ThemeControls({ + selectedTheme, + colorMode, + isDarkOnly, + onThemeChange, + onColorModeChange, +}: ThemeControlsProps) { + return ( +
+
+
+
+ {THEME_NAMES.map((theme) => ( + + ))} +
+ + {!isDarkOnly && ( +
+ + + +
+ )} +
+
+
+ ); +} + +export type { ThemeControlsProps, ColorMode } from "./types"; diff --git a/site/components/interactive/ThemeControls/types.ts b/site/components/interactive/ThemeControls/types.ts new file mode 100644 index 0000000..5eab84f --- /dev/null +++ b/site/components/interactive/ThemeControls/types.ts @@ -0,0 +1,9 @@ +export type ColorMode = "light" | "dark" | "system"; + +export interface ThemeControlsProps { + selectedTheme: string; + colorMode: ColorMode; + isDarkOnly: boolean; + onThemeChange: (theme: string) => void; + onColorModeChange: (mode: ColorMode) => void; +} diff --git a/site/components/interactive/constants.ts b/site/components/interactive/constants.ts new file mode 100644 index 0000000..d7194ee --- /dev/null +++ b/site/components/interactive/constants.ts @@ -0,0 +1,34 @@ +import type { ThemePair } from "./types"; + +export const SAMPLE_LOGS = [ + "[2024-01-15 10:23:45] INFO: Server started on port 3000", + "GET /api/users 200 OK (123ms)", + "POST /api/auth/login 401 Unauthorized", + "WARN: Memory usage high: 85% (1.7GB/2GB)", + "[ERROR] Database connection failed: ECONNREFUSED 127.0.0.1:5432", + "DEBUG: SQL Query executed in 45ms", + "SUCCESS: All tests passed (42 tests, 0 failures)", + "CRITICAL: System shutdown initiated", + "Processing batch job... [████████████████████] 100%", + "Application ready at http://localhost:3000", +]; + +export const THEME_PAIRS: Record = { + GitHub: { light: "github-light", dark: "github-dark" }, + Solarized: { light: "solarized-light", dark: "solarized-dark" }, + Dracula: { light: "dracula", dark: "dracula" }, + Nord: { light: "nord", dark: "nord" }, + Monokai: { light: "monokai", dark: "monokai" }, + "Oh My Zsh": { light: "oh-my-zsh", dark: "oh-my-zsh" }, +}; + +export const THEME_BACKGROUNDS: Record = { + "github-light": { bg: "#ffffff", headerBg: "#f6f8fa", border: "#d1d9e0" }, + "github-dark": { bg: "#0d1117", headerBg: "#161b22", border: "#30363d" }, + "solarized-light": { bg: "#fdf6e3", headerBg: "#eee8d5", border: "#eee8d5" }, + "solarized-dark": { bg: "#002b36", headerBg: "#073642", border: "#073642" }, + dracula: { bg: "#282a36", headerBg: "#1e1f29", border: "#44475a" }, + nord: { bg: "#2e3440", headerBg: "#3b4252", border: "#4c566a" }, + monokai: { bg: "#272822", headerBg: "#3e3d32", border: "#75715e" }, + "oh-my-zsh": { bg: "#2c3e50", headerBg: "#34495e", border: "#34495e" }, +}; diff --git a/site/components/interactive/index.tsx b/site/components/interactive/index.tsx index ac2f0fb..b5064d7 100644 --- a/site/components/interactive/index.tsx +++ b/site/components/interactive/index.tsx @@ -1,295 +1,13 @@ "use client"; -import React, { useState, useEffect, useRef } from "react"; -import { Button } from "@/components/ui/button"; -import { Moon, Sun, Monitor } from "lucide-react"; -import type { ThemeConfig, ThemePair, ColorMode } from "./types"; - -// Sample log messages to demonstrate styling -const SAMPLE_LOGS = [ - "[2024-01-15 10:23:45] INFO: Server started on port 3000", - "GET /api/users 200 OK (123ms)", - "POST /api/auth/login 401 Unauthorized", - "WARN: Memory usage high: 85% (1.7GB/2GB)", - "[ERROR] Database connection failed: ECONNREFUSED 127.0.0.1:5432", - "DEBUG: SQL Query executed in 45ms", - "✓ All tests passed (42 tests, 0 failures)", - "CRITICAL: System shutdown initiated", - "SUCCESS: Deployment completed to production", - "TODO: Refactor authentication module", - "Processing batch job... [████████████████████] 100%", - "🚀 Application ready at http://localhost:3000", -]; - -// Theme configurations with light/dark pairs -const THEME_PAIRS: Record = { - GitHub: { light: "github-light", dark: "github-dark" }, - Solarized: { light: "solarized-light", dark: "solarized-dark" }, - Dracula: { light: "dracula", dark: "dracula" }, // Dracula is dark-only - Nord: { light: "nord", dark: "nord" }, // Nord is dark-only - Monokai: { light: "monokai", dark: "monokai" }, // Monokai is dark-only - "Oh My Zsh": { light: "oh-my-zsh", dark: "oh-my-zsh" }, // OMZ is dark-only -}; - -// Get theme colors and styling -const getThemeStyles = (themeName: string): ThemeConfig => { - const themes: Record = { - "github-light": { - bg: "#ffffff", - headerBg: "#f6f8fa", - text: "#1f2328", - border: "#d1d9e0", - colors: { - info: "#0969da", - warn: "#fb8500", - error: "#cf222e", - success: "#1f883d", - debug: "#8250df", - critical: "#a40e26", - }, - }, - "github-dark": { - bg: "#0d1117", - headerBg: "#161b22", - text: "#e6edf3", - border: "#30363d", - colors: { - info: "#58a6ff", - warn: "#f0883e", - error: "#f85149", - success: "#3fb950", - debug: "#a5a5ff", - critical: "#ff6b6b", - }, - }, - "solarized-light": { - bg: "#fdf6e3", - headerBg: "#eee8d5", - text: "#657b83", - border: "#eee8d5", - colors: { - info: "#268bd2", - warn: "#cb4b16", - error: "#dc322f", - success: "#859900", - debug: "#6c71c4", - critical: "#d33682", - }, - }, - "solarized-dark": { - bg: "#002b36", - headerBg: "#073642", - text: "#839496", - border: "#073642", - colors: { - info: "#268bd2", - warn: "#cb4b16", - error: "#dc322f", - success: "#859900", - debug: "#6c71c4", - critical: "#d33682", - }, - }, - dracula: { - bg: "#282a36", - headerBg: "#1e1f29", - text: "#f8f8f2", - border: "#44475a", - colors: { - info: "#8be9fd", - warn: "#ffb86c", - error: "#ff5555", - success: "#50fa7b", - debug: "#bd93f9", - critical: "#ff79c6", - }, - }, - nord: { - bg: "#2e3440", - headerBg: "#3b4252", - text: "#eceff4", - border: "#4c566a", - colors: { - info: "#5e81ac", - warn: "#d08770", - error: "#bf616a", - success: "#a3be8c", - debug: "#b48ead", - critical: "#d8dee9", - }, - }, - monokai: { - bg: "#272822", - headerBg: "#3e3d32", - text: "#f8f8f2", - border: "#75715e", - colors: { - info: "#66d9ef", - warn: "#fd971f", - error: "#f92672", - success: "#a6e22e", - debug: "#ae81ff", - critical: "#e6db74", - }, - }, - "oh-my-zsh": { - bg: "#2c3e50", - headerBg: "#34495e", - text: "#ecf0f1", - border: "#34495e", - colors: { - info: "#3498db", - warn: "#f39c12", - error: "#e74c3c", - success: "#27ae60", - debug: "#2ecc71", - critical: "#c0392b", - }, - }, - }; - - return themes[themeName] || themes["github-dark"]; -}; - -// Style individual log lines based on content -const styleLogLine = (log: string, theme: ThemeConfig) => { - const { colors } = theme; - - // Determine log type and apply color - if (log.includes("CRITICAL")) { - return `${log}`; - } else if ( - log.includes("ERROR") || - log.includes("failed") || - log.includes("401") || - log.includes("Unauthorized") - ) { - return `${log}`; - } else if (log.includes("WARN") || log.includes("Memory usage")) { - return `${log}`; - } else if ( - log.includes("SUCCESS") || - log.includes("✓") || - log.includes("🚀") || - log.includes("200 OK") - ) { - return `${log}`; - } else if (log.includes("DEBUG")) { - return `${log}`; - } else if (log.includes("INFO")) { - return `${log}`; - } else if (log.includes("TODO")) { - return `${log}`; - } else { - return `${log}`; - } -}; - -// Code block component with syntax highlighting -function CodeBlock({ - children, - theme, - className = "", -}: { - children: string; - theme: string; - className?: string; -}) { - const themeStyle = getThemeStyles(theme); - - // Simple syntax highlighting for JavaScript - const highlightCode = (code: string) => { - const keywords = [ - "import", - "from", - "const", - "let", - "var", - "function", - "return", - "export", - "default", - "true", - "false", - "new", - ]; - const strings = /(["'`])(?:(?=(\\?))\2.)*?\1/g; - const comments = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)/gm; - - let highlighted = code - // Escape HTML - .replace(/&/g, "&") - .replace(//g, ">") - // Highlight strings - .replace( - strings, - `$&`, - ) - // Highlight comments - .replace( - comments, - `$&`, - ); - - // Highlight keywords - keywords.forEach((keyword) => { - const regex = new RegExp(`\\b${keyword}\\b`, "g"); - highlighted = highlighted.replace( - regex, - `${keyword}`, - ); - }); - - // Highlight function names and properties - highlighted = highlighted - .replace( - /(\w+)(?=\()/g, - `$1`, - ) - .replace( - /\.(\w+)/g, - `.$1`, - ); - - return highlighted; - }; - - return ( - <> -