diff --git a/.gitignore b/.gitignore index e64f658..c3aaf09 100644 --- a/.gitignore +++ b/.gitignore @@ -157,3 +157,7 @@ tmp test-results/ playwright-report/ playwright/.cache/ +.beads/ + +# WASM files copied from node_modules +site/public/ghostty-vt.wasm diff --git a/README.md b/README.md index 95f0410..380b3fd 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ pnpm add logsdx import { getLogsDX } from "logsdx"; // Initialize with a built-in theme -const logger = getLogsDX("dracula"); +const logger = await getLogsDX({ theme: "dracula" }); // Style a log line console.log( @@ -78,22 +78,28 @@ styledLogs.forEach((line) => console.log(line)); ### 3. Browser Integration (React Example) ```jsx -import { LogsDX } from "logsdx"; +import { useEffect, useState } from "react"; +import { getLogsDX } from "logsdx"; function LogViewer({ logs }) { - const logger = LogsDX.getInstance({ - theme: "dracula", - outputFormat: "html", - htmlStyleFormat: "css", - }); + const [styledLogs, setStyledLogs] = useState([]); + + useEffect(() => { + async function styleLogs() { + const logger = await getLogsDX({ + theme: "dracula", + outputFormat: "html", + htmlStyleFormat: "css", + }); + setStyledLogs(logs.map((log) => logger.processLine(log))); + } + styleLogs(); + }, [logs]); return (
- {logs.map((log, i) => ( -
+ {styledLogs.map((log, i) => ( +
))}
); @@ -104,18 +110,21 @@ function LogViewer({ logs }) { ```javascript // Terminal output with ANSI colors -const terminalLogger = getLogsDX("dracula", { +const terminalLogger = await getLogsDX({ + theme: "dracula", outputFormat: "ansi", }); // HTML with inline styles -const htmlLogger = getLogsDX("dracula", { +const htmlLogger = await getLogsDX({ + theme: "dracula", outputFormat: "html", htmlStyleFormat: "css", }); // HTML with CSS classes -const classLogger = getLogsDX("dracula", { +const classLogger = await getLogsDX({ + theme: "dracula", outputFormat: "html", htmlStyleFormat: "className", }); diff --git a/bun.lock b/bun.lock index c81936d..44d15ee 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": { @@ -31,12 +27,14 @@ "@radix-ui/react-tabs": "^1.1.13", "@shikijs/rehype": "^3.12.2", "@shikijs/transformers": "^3.12.2", + "@tailwindcss/typography": "^0.5.19", "@tanstack/react-query": "^5.90.9", "@tanstack/react-store": "^0.8.0", "@tanstack/store": "^0.8.0", "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", @@ -336,6 +334,8 @@ "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], + "@tailwindcss/typography": ["@tailwindcss/typography@0.5.19", "", { "dependencies": { "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg=="], + "@tanstack/query-core": ["@tanstack/query-core@5.90.9", "", {}, "sha512-UFOCQzi6pRGeVTVlPNwNdnAvT35zugcIydqjvFUzG62dvz2iVjElmNp/hJkUoM5eqbUPfSU/GJIr/wbvD8bTUw=="], "@tanstack/query-devtools": ["@tanstack/query-devtools@5.90.1", "", {}, "sha512-GtINOPjPUH0OegJExZ70UahT9ykmAhmtNVcmtdnOZbxLwT7R5OmRztR5Ahe3/Cu7LArEmR6/588tAycuaWb1xQ=="], @@ -508,6 +508,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 +946,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=="], @@ -956,6 +954,8 @@ "@radix-ui/react-primitive/@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=="], + "@tailwindcss/typography/postcss-selector-parser": ["postcss-selector-parser@6.0.10", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w=="], + "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], 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..a4db2e4 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,12 @@ "require": "./dist/index.cjs", "default": "./dist/index.mjs" }, + "./core": { + "types": "./dist/core.d.ts", + "import": "./dist/core.mjs", + "require": "./dist/core.cjs", + "default": "./dist/core.mjs" + }, "./themes": { "types": "./dist/themes/index.d.ts", "import": "./dist/themes/index.mjs", @@ -31,6 +37,12 @@ "require": "./dist/themes/presets/*.cjs", "default": "./dist/themes/presets/*.mjs" }, + "./tokenizer": { + "types": "./dist/tokenizer/index.d.ts", + "import": "./dist/tokenizer/index.mjs", + "require": "./dist/tokenizer/index.cjs", + "default": "./dist/tokenizer/index.mjs" + }, "./renderer": { "types": "./dist/renderer/index.d.ts", "import": "./dist/renderer/index.mjs", @@ -51,9 +63,10 @@ "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:core && 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:core": "bun build src/core.ts --outfile dist/core.mjs --format esm --minify && bun build src/core.ts --outfile dist/core.cjs --format cjs --minify", "build:cli": "bun build src/cli/bin.ts --outfile dist/cli.js --format cjs --minify --target node", "build:types": "tsc -p tsconfig.build.json", "test": "bun test tests/", @@ -66,7 +79,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 +103,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..850fac6 --- /dev/null +++ b/site/app/demos/page.tsx @@ -0,0 +1,83 @@ +"use client"; + +import { Navbar } from "@/components/navbar"; +import { OutputComparison } from "@/components/output-comparison"; +import { LogPlayground } from "@/components/log-playground"; +import { NavCard } from "@/components/nav-card"; +import { AnimatedSection } from "@/components/ui/animated-section"; +import { Card, CardContent } from "@/components/ui/card"; + +function Separator() { + return ( +
+
+
+ ); +} + +export default function DemosPage() { + return ( +
+ + +
+
+ +
+

+ + Live + {" "} + Demos +

+

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

+
+ + +
+
+
+
+
+ + +
+ +
+
+ + + + +
+
+ + + + + +
+
+
+
+ ); +} diff --git a/site/app/docs/[[...slug]]/page.tsx b/site/app/docs/[[...slug]]/page.tsx index a165906..3984328 100644 --- a/site/app/docs/[[...slug]]/page.tsx +++ b/site/app/docs/[[...slug]]/page.tsx @@ -7,9 +7,9 @@ import { extractHeadings } from "@/lib/toc"; import { TableOfContents } from "@/components/docs/TableOfContents"; interface DocPageProps { - params: { + params: Promise<{ slug?: string[]; - }; + }>; } export async function generateStaticParams() { @@ -24,7 +24,8 @@ export async function generateStaticParams() { } export async function generateMetadata({ params }: DocPageProps) { - const slug = params.slug?.length ? params.slug : ["index"]; + const { slug: slugParam } = await params; + const slug = slugParam?.length ? slugParam : ["index"]; const doc = getDocBySlug(slug); if (!doc) { @@ -62,7 +63,8 @@ async function getDocContent(slug: string[]) { } export default async function DocPage({ params }: DocPageProps) { - const slug = params.slug?.length ? params.slug : ["index"]; + const { slug: slugParam } = await params; + const slug = slugParam?.length ? slugParam : ["index"]; const meta = getDocBySlug(slug); if (!meta) { @@ -111,10 +113,7 @@ export default async function DocPage({ params }: DocPageProps) {
-
+
diff --git a/site/app/globals.css b/site/app/globals.css index 2be68ce..e8b251d 100644 --- a/site/app/globals.css +++ b/site/app/globals.css @@ -189,3 +189,40 @@ pre span[style] { font-weight: inherit; } + +/* Prose code blocks - Light mode */ +.prose pre { + background-color: #f8fafc !important; + border: 1px solid rgba(0, 0, 0, 0.1); + color: #1e293b; +} + +.prose code { + background-color: #f1f5f9; + color: #1e293b; + padding: 0.125rem 0.25rem; + border-radius: 0.25rem; + font-size: 0.875em; +} + +.prose pre code { + background-color: transparent; + padding: 0; + border-radius: 0; +} + +/* Prose code blocks - Dark mode */ +.dark .prose pre { + background-color: #1e293b !important; + border-color: rgba(255, 255, 255, 0.1); + color: #e2e8f0; +} + +.dark .prose code { + background-color: #334155; + color: #e2e8f0; +} + +.dark .prose pre code { + background-color: transparent; +} diff --git a/site/app/layout.tsx b/site/app/layout.tsx index 08bbeaa..3b3954e 100644 --- a/site/app/layout.tsx +++ b/site/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata } from "next"; import { Inter } from "next/font/google"; import "./globals.css"; import { Providers } from "@/components/providers"; +import { Footer } from "@/components/footer"; const inter = Inter({ subsets: ["latin"] }); @@ -18,8 +19,11 @@ export default function RootLayout({ }) { return ( - - {children} + + +
{children}
+