diff --git a/bun.lock b/bun.lock index c81936d..7f33149 100644 --- a/bun.lock +++ b/bun.lock @@ -4,9 +4,6 @@ "workspaces": { "": { "name": "logsdx", - "dependencies": { - "zod": "^3.25.74", - }, "devDependencies": { "@types/bun": "^1.2.11", "mprocs": "^0.7.3", @@ -14,7 +11,6 @@ "prettier": "^3.5.3", "turbo": "^2.5.6", "typescript": "^5.0.0", - "zod-to-json-schema": "^3.24.6", }, }, "site": { @@ -37,6 +33,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 +505,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=="], @@ -944,10 +943,6 @@ "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - - "zod-to-json-schema": ["zod-to-json-schema@3.24.6", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg=="], - "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], diff --git a/docs/CREATE_THEME.md b/docs/CREATE_THEME.md deleted file mode 100644 index 1ff8c0b..0000000 --- a/docs/CREATE_THEME.md +++ /dev/null @@ -1,171 +0,0 @@ -# LogsDX Interactive Theme Creator - -The LogsDX theme creator is an interactive CLI tool that guides you through creating custom themes for your log styling needs. - -## Getting Started - -Run the theme creator with: - -```bash -bun run create-theme -``` - -> **Note:** The theme creator uses `@inquirer/prompts` for an enhanced interactive experience. This dependency is automatically installed with LogsDX. - -## Features - -### šŸŽØ Interactive Color Selection - -- Choose from predefined color presets (Vibrant, Pastel, Neon, Earth, Ocean) -- Customize each color individually with live preview -- Supports hex color codes - -### šŸ“‹ Feature Presets - -Select which log features to highlight: - -- Log levels (ERROR, WARN, INFO, DEBUG) -- Numbers and numeric values -- Dates and timestamps -- Boolean values (true, false, null) -- Brackets and punctuation -- Quoted strings - -### šŸ” Custom Patterns - -Add custom regex patterns to highlight specific text: - -- IP addresses -- UUIDs -- Email addresses -- Custom identifiers - -### ✨ Custom Word Highlighting - -Highlight specific words with custom colors and styles: - -- Choose color from theme palette -- Add styles: bold, italic, underline, blink - -### ♿ Accessibility Features - -- Automatic WCAG compliance checking -- Shows accessibility score and level (A, AA, AAA) -- Auto-fix option for contrast issues -- Validates theme colors for readability - -### šŸ’¾ Export Options - -Save your theme in multiple formats: - -- **JSON file**: For direct use with `--config` -- **TypeScript file**: For importing in code -- **Clipboard**: Quick copy for sharing -- **Register**: Use immediately in current session - -## Example Workflow - -1. **Theme Information** - - ``` - Theme name: my-awesome-theme - Description: A vibrant theme for production logs - Mode: Dark - ``` - -2. **Color Configuration** - - Select a preset or start from scratch - - Customize each color with live preview - - See sample logs rendered with your colors - -3. **Feature Selection** - - Choose which log features to highlight - - Add custom regex patterns for your use case - - Define custom words with special styling - -4. **Accessibility Check** - - Review WCAG compliance score - - Auto-fix contrast issues if needed - - Ensure readability across different displays - -5. **Save & Use** - - ```bash - # Save as JSON - logsdx --config ./themes/my-awesome-theme.json input.log - - # Or register for immediate use - logsdx --theme my-awesome-theme input.log - ``` - -## Color Presets - -### Vibrant - -Bright, high-contrast colors perfect for dark terminals - -### Pastel - -Soft, muted colors that are easy on the eyes - -### Neon - -Bold, fluorescent colors for maximum visibility - -### Earth - -Natural, warm tones inspired by nature - -### Ocean - -Cool blues and teals with calming effect - -## Tips - -- Use the live preview to see how your theme looks with real log data -- Test your theme with both light and dark terminal backgrounds -- Consider accessibility - aim for at least AA compliance -- Export to TypeScript for version control and sharing -- Use custom patterns to highlight domain-specific content - -## Advanced Usage - -### Extending Existing Themes - -After creating a theme, you can extend it programmatically: - -```typescript -import { extendTheme } from "logsdx"; -import { myAwesomeTheme } from "./themes/my-awesome-theme"; - -const extendedTheme = extendTheme(myAwesomeTheme, { - customWords: { - CRITICAL: { color: "error", styleCodes: ["bold", "blink"] }, - }, -}); -``` - -### Batch Theme Creation - -Create multiple theme variants: - -```typescript -import { generateThemeVariants } from "logsdx"; - -const { light, dark } = generateThemeVariants({ - name: "my-theme", - colors: { - /* ... */ - }, -}); -``` - -## Integration - -Themes created with the interactive tool are fully compatible with: - -- LogsDX CLI (`--theme` flag) -- Configuration files (`.logsdxrc`) -- Programmatic API -- Web browser rendering -- CI/CD pipelines diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md deleted file mode 100644 index 79aee3c..0000000 --- a/docs/GETTING_STARTED.md +++ /dev/null @@ -1,476 +0,0 @@ -# Getting Started with LogsDX - -This guide will walk you through setting up and using LogsDX in your project step by step. - -## Table of Contents - -- [Prerequisites](#prerequisites) -- [Installation](#installation) -- [Quick Verification](#quick-verification) -- [Step-by-Step Tutorial](#step-by-step-tutorial) - - [Step 1: Basic Log Styling](#step-1-basic-log-styling) - - [Step 2: Processing Log Files](#step-2-processing-log-files) - - [Step 3: Real-time Log Streaming](#step-3-real-time-log-streaming) - - [Step 4: Browser Integration](#step-4-browser-integration) - - [Step 5: Custom Theme Creation](#step-5-custom-theme-creation) - - [Step 6: Integration with Winston Logger](#step-6-integration-with-winston-logger) - - [Step 7: Using the CLI Tool](#step-7-using-the-cli-tool) -- [Common Patterns](#common-patterns) - - [Pattern 1: Environment-based Themes](#pattern-1-environment-based-themes) - - [Pattern 2: Multiple Output Formats](#pattern-2-multiple-output-formats) - - [Pattern 3: Conditional Styling](#pattern-3-conditional-styling) - - [Pattern 4: Log Level Filtering](#pattern-4-log-level-filtering) -- [Testing Your Setup](#testing-your-setup) -- [Troubleshooting](#troubleshooting) -- [Next Steps](#next-steps) -- [Resources](#resources) -- [Quick Reference](#quick-reference) - -## Prerequisites - -- **Node.js 18+** or **Bun 1.0+** -- Basic knowledge of JavaScript/TypeScript -- A project with logs to style - -## Installation - -Choose your package manager: - -```bash -# Using npm -npm install logsdx - -# Using bun (recommended for faster installation) -bun add logsdx - -# Using yarn -yarn add logsdx - -# Using pnpm -pnpm add logsdx -``` - -## Quick Verification - -After installation, verify LogsDX is working: - -```javascript -// test-logsdx.js -import { getLogsDX } from "logsdx"; - -const logger = getLogsDX("dracula"); -console.log(logger.processLine("ERROR: Test message")); -``` - -Run it: - -```bash -node test-logsdx.js -# You should see "ERROR" in red and "Test message" in styled text -``` - -## Step-by-Step Tutorial - -### Step 1: Basic Log Styling - -Let's start with the simplest use case - styling console output: - -```javascript -// 1-basic.js -import { getLogsDX } from "logsdx"; - -// Create a logger with the 'nord' theme -const logger = getLogsDX("nord"); - -// Style different log levels -console.log(logger.processLine("INFO: Application starting...")); -console.log(logger.processLine("WARN: Config file not found, using defaults")); -console.log(logger.processLine("ERROR: Database connection failed")); -console.log(logger.processLine("SUCCESS: Server started on port 3000")); -``` - -### Step 2: Processing Log Files - -Read and style existing log files: - -```javascript -// 2-files.js -import { getLogsDX } from "logsdx"; -import fs from "fs"; - -const logger = getLogsDX("dracula"); - -// Read a log file -const logContent = fs.readFileSync("app.log", "utf-8"); -const lines = logContent.split("\n"); - -// Process and display styled logs -const styledLines = logger.processLines(lines); -styledLines.forEach((line) => console.log(line)); - -// Or save to a new file (ANSI codes included) -fs.writeFileSync("styled-app.log", styledLines.join("\n")); -``` - -### Step 3: Real-time Log Streaming - -Style logs as they're generated: - -```javascript -// 3-streaming.js -import { getLogsDX } from "logsdx"; -import { createReadStream } from "fs"; -import { createInterface } from "readline"; - -const logger = getLogsDX("monokai"); - -// Stream and style logs line by line -const rl = createInterface({ - input: createReadStream("server.log"), - crlfDelay: Infinity, -}); - -rl.on("line", (line) => { - console.log(logger.processLine(line)); -}); -``` - -### Step 4: Browser Integration - -For web applications, use HTML output: - -```javascript -// 4-browser.js -import { LogsDX } from "logsdx"; - -// Configure for HTML output -const logger = LogsDX.getInstance({ - theme: "github-dark", - outputFormat: "html", - htmlStyleFormat: "css", -}); - -// Generate HTML with inline styles -const htmlLog = logger.processLine("ERROR: User authentication failed"); -// Returns: ERROR: User authentication failed - -// For React/Vue/Angular -document.getElementById("log-container").innerHTML = htmlLog; -``` - -### Step 5: Custom Theme Creation - -Create a theme tailored to your needs: - -```javascript -// 5-custom-theme.js -import { getLogsDX } from "logsdx"; - -const customTheme = { - name: "my-app-theme", - mode: "dark", - schema: { - defaultStyle: { - color: "#ffffff", - }, - matchWords: { - // Log levels - FATAL: { color: "#ff0000", styleCodes: ["bold", "underline"] }, - ERROR: { color: "#ff5555", styleCodes: ["bold"] }, - WARN: { color: "#ffaa00" }, - INFO: { color: "#00aaff" }, - DEBUG: { color: "#888888", styleCodes: ["dim"] }, - - // Custom keywords - DATABASE: { color: "#00ff00", styleCodes: ["italic"] }, - API: { color: "#ff00ff", styleCodes: ["italic"] }, - CACHE: { color: "#ffff00" }, - }, - matchPatterns: [ - // Highlight timestamps - { - name: "timestamp", - pattern: "\\d{4}-\\d{2}-\\d{2}[T ]\\d{2}:\\d{2}:\\d{2}", - options: { color: "#666666", styleCodes: ["dim"] }, - }, - // Highlight IPs - { - name: "ip", - pattern: "\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b", - options: { color: "#cyan" }, - }, - // Highlight UUIDs - { - name: "uuid", - pattern: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", - options: { color: "#magenta", styleCodes: ["italic"] }, - }, - ], - }, -}; - -const logger = getLogsDX(customTheme); -console.log( - logger.processLine( - "2024-01-15T10:30:00 ERROR: DATABASE connection to 192.168.1.100 failed", - ), -); -``` - -### Step 6: Integration with Winston Logger - -```javascript -// 6-winston.js -import winston from "winston"; -import { getLogsDX } from "logsdx"; - -const logsDX = getLogsDX("dracula"); - -// Create a custom Winston format -const logsDXFormat = winston.format.printf(({ level, message, timestamp }) => { - const logLine = `[${timestamp}] ${level.toUpperCase()}: ${message}`; - return logsDX.processLine(logLine); -}); - -// Configure Winston with LogsDX -const logger = winston.createLogger({ - format: winston.format.combine(winston.format.timestamp(), logsDXFormat), - transports: [new winston.transports.Console()], -}); - -// Use Winston as normal - output will be styled -logger.info("Application started"); -logger.error("Connection failed"); -logger.warn("Low memory"); -``` - -### Step 7: Using the CLI Tool - -After installing LogsDX globally, use the CLI: - -```bash -# Install globally for CLI access -npm install -g logsdx - -# Basic usage -logsdx server.log - -# With specific theme -logsdx server.log --theme dracula - -# Process from stdin -tail -f /var/log/app.log | logsdx - -# Save styled output -logsdx input.log --output styled.log --theme nord - -# List all themes -logsdx --list-themes -``` - -## Common Patterns - -### Pattern 1: Environment-based Themes - -```javascript -import { getLogsDX } from "logsdx"; - -const theme = process.env.NODE_ENV === "production" ? "github-dark" : "dracula"; -const logger = getLogsDX(theme); -``` - -### Pattern 2: Multiple Output Formats - -```javascript -import { getLogsDX } from "logsdx"; - -const terminalLogger = getLogsDX("nord", { outputFormat: "ansi" }); -const htmlLogger = getLogsDX("nord", { outputFormat: "html" }); - -const line = "ERROR: Critical failure"; - -// For terminal -console.log(terminalLogger.processLine(line)); - -// For web dashboard -const htmlOutput = htmlLogger.processLine(line); -``` - -### Pattern 3: Conditional Styling - -```javascript -import { getLogsDX } from "logsdx"; -import chalk from "chalk"; - -const logger = getLogsDX("dracula"); - -function log(message, level = "INFO") { - const styledMessage = logger.processLine(`${level}: ${message}`); - - if (level === "ERROR") { - console.error(styledMessage); - } else { - console.log(styledMessage); - } -} - -log("Server started", "INFO"); -log("Database error", "ERROR"); -``` - -### Pattern 4: Log Level Filtering - -```javascript -import { getLogsDX } from "logsdx"; - -const logger = getLogsDX("nord"); -const MIN_LEVEL = process.env.LOG_LEVEL || "INFO"; - -const levels = { - ERROR: 0, - WARN: 1, - INFO: 2, - DEBUG: 3, -}; - -function shouldLog(line) { - const match = line.match(/^(ERROR|WARN|INFO|DEBUG):/); - if (!match) return true; - - const lineLevel = match[1]; - return levels[lineLevel] <= levels[MIN_LEVEL]; -} - -function processLog(line) { - if (shouldLog(line)) { - console.log(logger.processLine(line)); - } -} -``` - -## Testing Your Setup - -Create a test file to verify everything works: - -```javascript -// test-setup.js -import { getLogsDX, getThemeNames, validateTheme } from "logsdx"; - -// Test 1: List available themes -console.log("Available themes:", getThemeNames()); - -// Test 2: Process different log types -const logger = getLogsDX("dracula"); -const testLines = [ - "INFO: Server starting on port 3000", - "WARN: Deprecated API used", - "ERROR: Connection timeout at 192.168.1.1", - "DEBUG: Cache miss for key abc-123-def", - "2024-01-15T10:30:00Z ERROR: Database connection failed", -]; - -console.log("\nStyled output:"); -testLines.forEach((line) => { - console.log(logger.processLine(line)); -}); - -// Test 3: Validate custom theme -const customTheme = { - name: "test", - mode: "dark", - schema: { - defaultStyle: { color: "#fff" }, - matchWords: { - ERROR: { color: "#f00" }, - }, - }, -}; - -const validation = validateTheme(customTheme); -console.log("\nTheme valid:", validation.success); -``` - -## Troubleshooting - -### Issue: Colors not showing in terminal - -**Solution:** Ensure your terminal supports ANSI colors. Set `FORCE_COLOR=1` environment variable: - -```bash -FORCE_COLOR=1 node your-script.js -``` - -### Issue: CLI command not found - -**Solution:** Install globally or use npx: - -```bash -# Global install -npm install -g logsdx - -# Or use npx -npx logsdx your-log-file.log -``` - -### Issue: Custom theme not working - -**Solution:** Validate your theme: - -```javascript -import { validateTheme } from "logsdx"; - -const result = validateTheme(yourTheme); -if (!result.success) { - console.error("Theme validation errors:", result.error); -} -``` - -### Issue: HTML output shows raw tags - -**Solution:** Use proper HTML rendering: - -```javascript -// React -
; - -// Vanilla JS -element.innerHTML = logger.processLine(log); -``` - -## Next Steps - -1. **Explore Themes**: Try different built-in themes to find your favorite -2. **Create Custom Themes**: Build themes that match your brand -3. **Integrate with Loggers**: Add LogsDX to your existing logging setup -4. **Share Themes**: Contribute your themes to the community - -## Resources - -- [API Documentation](../README.md#api-reference) -- [Theme Creation Guide](../README.md#creating-custom-themes) -- [GitHub Repository](https://github.com/yowainwright/logsdx) -- [Report Issues](https://github.com/yowainwright/logsdx/issues) - -## Quick Reference - -```javascript -import { - getLogsDX, // Get logger instance - LogsDX, // Class for singleton pattern - getThemeNames, // List available themes - getTheme, // Get theme by name - getAllThemes, // Get all theme objects - registerTheme, // Register custom theme - validateTheme, // Validate theme structure - createTheme, // Create theme helper - renderLightBox, // Light theme rendering - checkWCAGCompliance, // Accessibility check -} from "logsdx"; - -// Configuration options -const options = { - outputFormat: "ansi", // "ansi" | "html" - htmlStyleFormat: "css", // "css" | "className" - debug: false, // Enable debug output -}; -``` diff --git a/docs/TERMINAL_ADAPTATION.md b/docs/TERMINAL_ADAPTATION.md deleted file mode 100644 index 92646fc..0000000 --- a/docs/TERMINAL_ADAPTATION.md +++ /dev/null @@ -1,111 +0,0 @@ -# Terminal Background Adaptation - -LogsDX automatically detects your terminal's background color and adjusts themes for optimal visibility. This prevents issues like dark text on dark backgrounds. - -## The Problem - -Light themes (like `github-light` or `solarized-light`) use dark text colors designed for light backgrounds. When used in dark terminals, the text becomes nearly invisible. - -## The Solution - -LogsDX includes automatic terminal background detection that: - -1. **Detects Terminal Background** - Checks environment variables and terminal programs -2. **Adjusts Theme Selection** - Automatically uses dark variants in dark terminals -3. **Modifies Text Colors** - Ensures text remains visible regardless of theme - -## How It Works - -```typescript -// Automatic adjustment (default behavior) -const logger = getLogsDX({ theme: "github-light" }); -// In dark terminal: automatically uses github-dark - -// Disable auto-adjustment if needed -const logger = getLogsDX({ - theme: "github-light", - autoAdjustTerminal: false, -}); -``` - -## Terminal Detection - -LogsDX detects dark terminals by checking: - -- `COLORFGBG` environment variable -- `TERM_PROGRAM` (iTerm, Hyper, VSCode, etc.) -- `TERMINAL_EMULATOR` settings -- Common terminal indicators - -## Theme Mappings - -| Requested Theme | Dark Terminal | Light Terminal | -| --------------- | -------------- | --------------- | -| github-light | github-dark | github-light | -| solarized-light | solarized-dark | solarized-light | -| github-dark | github-dark | github-dark | -| solarized-dark | solarized-dark | solarized-dark | -| dracula | dracula | dracula | -| oh-my-zsh | oh-my-zsh | oh-my-zsh | - -## Examples - -### Before (No Adaptation) - -``` -# github-light in dark terminal -[Nearly invisible dark text on dark background] -``` - -### After (With Adaptation) - -``` -# github-light → github-dark (auto-adjusted) -[Clearly visible light text on dark background] -``` - -## Configuration Options - -```typescript -interface LogsDXOptions { - // Enable/disable automatic terminal adaptation - autoAdjustTerminal?: boolean; // default: true -} -``` - -## Testing Your Terminal - -Run this command to see what LogsDX detects: - -```bash -bun run scripts/test-terminal-adaptation.ts -``` - -This will show: - -- Your terminal environment variables -- The original vs adjusted theme -- Side-by-side comparison of outputs - -## Best Practices - -1. **Use Theme Pairs** - Always provide both light and dark variants -2. **Test Both Modes** - Check your logs in both light and dark terminals -3. **Document Behavior** - Let users know about automatic adjustments -4. **Provide Override** - Allow users to disable auto-adjustment if needed - -## Manual Theme Selection - -If you prefer manual control: - -```typescript -// Detect terminal yourself -const isDarkTerminal = process.env.COLORFGBG?.includes("0;"); - -// Choose theme accordingly -const themeName = isDarkTerminal ? "github-dark" : "github-light"; -const logger = getLogsDX({ - theme: themeName, - autoAdjustTerminal: false, -}); -``` diff --git a/package.json b/package.json index a01a10e..2f05889 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "scripts": { "setup": "bash scripts/setup.sh", "clean": "rm -rf dist node_modules/.bun site/node_modules", - "build": "bun run build:cjs && bun run build:esm && bun run build:cli && bun run build:types && bun run generate-schema", + "build": "bun run build:cjs && bun run build:esm && bun run build:cli && bun run build:types", "build:cjs": "bun build src/index.ts --outfile dist/index.cjs --format cjs --minify", "build:esm": "bun build src/index.ts --outfile dist/index.mjs --format esm --minify", "build:cli": "bun build src/cli/bin.ts --outfile dist/cli.js --format cjs --minify --target node", @@ -66,7 +66,6 @@ "format:check": "bun run prettier --check .", "check": "bun run lint && bun run format:check && bun run test", "generate-css": "bun run scripts/generate-css.ts", - "generate-schema": "bun run scripts/generate-schema.ts", "demo": "bun run demo-dracula-consistency.js", "turbo:build": "turbo run build", "turbo:dev": "turbo run dev", @@ -91,10 +90,7 @@ "oxlint": "^0.15.0", "prettier": "^3.5.3", "turbo": "^2.5.6", - "typescript": "^5.0.0", - "zod-to-json-schema": "^3.24.6" + "typescript": "^5.0.0" }, - "dependencies": { - "zod": "^3.25.74" - } + "dependencies": {} } diff --git a/scripts/build-themes.ts b/scripts/build-themes.ts deleted file mode 100644 index c61a5c4..0000000 --- a/scripts/build-themes.ts +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env bun -import { build } from "bun"; -import { readdirSync } from "fs"; -import { join } from "path"; - -const themesDir = join(import.meta.dir, "../src/themes/presets"); -const outputDir = join(import.meta.dir, "../dist/themes/presets"); - -const themeFiles = readdirSync(themesDir).filter((file) => - file.endsWith(".ts"), -); - -console.log(`Building ${themeFiles.length} theme presets...`); - -const buildPromises = themeFiles.map(async (file) => { - const themeName = file.replace(".ts", ""); - const inputPath = join(themesDir, file); - - await Promise.all([ - build({ - entrypoints: [inputPath], - outdir: outputDir, - format: "esm", - minify: true, - naming: `${themeName}.mjs`, - target: "browser", - }), - - build({ - entrypoints: [inputPath], - outdir: outputDir, - format: "cjs", - minify: true, - naming: `${themeName}.cjs`, - target: "node", - }), - ]); - - console.log(`āœ“ Built theme: ${themeName}`); -}); - -await Promise.all(buildPromises); - -console.log("āœ“ All themes built successfully!"); diff --git a/scripts/generate-schema.ts b/scripts/generate-schema.ts deleted file mode 100644 index c2bc28c..0000000 --- a/scripts/generate-schema.ts +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env bun - -import fs from "node:fs/promises"; -import path from "node:path"; -import { zodToJsonSchema } from "zod-to-json-schema"; -import { - tokenSchema, - tokenListSchema, - themePresetSchema, - styleOptionsSchema, - schemaConfigSchema, -} from "../src/schema/index"; -import { JsonSchemaOptions } from "../src/schema/types"; - -async function main() { - const args = process.argv.slice(2); - const outputDir = args[0] || "dist/schemas"; - - const packageJson = JSON.parse( - await fs.readFile(path.join(process.cwd(), "package.json"), "utf-8"), - ); - const version = packageJson.version; - - try { - await fs.mkdir(outputDir, { recursive: true }); - console.log(`Creating schemas in ${outputDir}`); - - const schemas = [ - { - name: "token", - schema: tokenSchema, - filename: "token.schema.json", - }, - { - name: "token-list", - schema: tokenListSchema, - filename: "token-list.schema.json", - }, - { - name: "theme", - schema: themePresetSchema, - filename: "theme.schema.json", - }, - { - name: "style-options", - schema: styleOptionsSchema, - filename: "style-options.schema.json", - }, - { - name: "schema-config", - schema: schemaConfigSchema, - filename: "schema-config.schema.json", - }, - ]; - - for (const { name, schema, filename } of schemas) { - console.log(`Generating ${name} schema...`); - - const jsonSchema = zodToJsonSchema(schema, { - name, - $refStrategy: "relative", - definitionPath: "$defs", - definitions: {}, - } as JsonSchemaOptions); - - // Add version to the schema - jsonSchema.version = version; - - const outputPath = path.join(outputDir, filename); - await fs.writeFile(outputPath, JSON.stringify(jsonSchema, null, 2)); - console.log(`āœ“ ${filename}`); - } - - console.log(`\nāœ… Successfully generated ${schemas.length} schema files`); - } catch (error) { - console.error("Error generating schemas:", error); - process.exit(1); - } -} - -if (import.meta.main) { - main(); -} diff --git a/scripts/remove-comments.ts b/scripts/remove-comments.ts deleted file mode 100644 index 157b26e..0000000 --- a/scripts/remove-comments.ts +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env bun - -import { readdir, readFile, writeFile } from "fs/promises"; -import { join } from "path"; - -async function getAllTsFiles(dir: string): Promise { - const files: string[] = []; - const entries = await readdir(dir, { withFileTypes: true }); - - for (const entry of entries) { - const fullPath = join(dir, entry.name); - if (entry.isDirectory()) { - files.push(...(await getAllTsFiles(fullPath))); - } else if (entry.name.endsWith(".ts")) { - files.push(fullPath); - } - } - - return files; -} - -function removeComments(code: string): string { - let result = ""; - let i = 0; - let inString = false; - let stringChar = ""; - let inTemplate = false; - - while (i < code.length) { - const char = code[i]; - const nextChar = code[i + 1]; - - if (!inString && !inTemplate && char === "/" && nextChar === "/") { - const lineEnd = code.indexOf("\n", i); - if (lineEnd === -1) { - break; - } - result += "\n"; - i = lineEnd + 1; - continue; - } - - if (!inString && !inTemplate && char === "/" && nextChar === "*") { - const commentEnd = code.indexOf("*/", i + 2); - if (commentEnd === -1) { - break; - } - const commentContent = code.substring(i, commentEnd + 2); - const newlines = (commentContent.match(/\n/g) || []).length; - result += "\n".repeat(newlines); - i = commentEnd + 2; - continue; - } - - if (!inTemplate && (char === '"' || char === "'")) { - if (!inString) { - inString = true; - stringChar = char; - } else if (char === stringChar && code[i - 1] !== "\\") { - inString = false; - stringChar = ""; - } - } - - if (!inString && char === "`") { - inTemplate = !inTemplate; - } - - result += char; - i++; - } - - return result; -} - -async function processFile(filePath: string) { - console.log(`Processing: ${filePath}`); - const content = await readFile(filePath, "utf-8"); - const cleaned = removeComments(content); - await writeFile(filePath, cleaned, "utf-8"); -} - -async function main() { - const srcFiles = await getAllTsFiles("src"); - const testFiles = await getAllTsFiles("tests"); - const allFiles = [...srcFiles, ...testFiles]; - - console.log(`Found ${allFiles.length} TypeScript files`); - - for (const file of allFiles) { - await processFile(file); - } - - console.log("Done!"); -} - -main().catch(console.error); diff --git a/site/app/demos/page.tsx b/site/app/demos/page.tsx new file mode 100644 index 0000000..1877a77 --- /dev/null +++ b/site/app/demos/page.tsx @@ -0,0 +1,37 @@ +"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/bunfig.toml b/site/bunfig.toml index d5e19ca..2c651e1 100644 --- a/site/bunfig.toml +++ b/site/bunfig.toml @@ -1,4 +1,4 @@ [test] preload = ["./test-setup.ts"] root = "./tests" -isolate = true +isolate = false 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..7110845 --- /dev/null +++ b/site/components/cli-demo/index.tsx @@ -0,0 +1,283 @@ +"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..5567602 --- /dev/null +++ b/site/components/interactive/PreviewPane/index.tsx @@ -0,0 +1,69 @@ +"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..3b3011b --- /dev/null +++ b/site/components/interactive/constants.ts @@ -0,0 +1,37 @@ +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< + string, + { bg: string; headerBg: string; border: string } +> = { + "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..fbdb449 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 ( - <> -