|
| 1 | +# @interweb/visual-diff |
| 2 | + |
| 3 | +Beautiful visual diff with syntax highlighting for terminal and HTML output. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- Line-by-line diff computation with LCS algorithm |
| 8 | +- Syntax highlighting for 15+ languages (JavaScript, TypeScript, Python, SQL, Go, Rust, and more) |
| 9 | +- Beautiful terminal output with ANSI colors |
| 10 | +- HTML output with dark/light mode support |
| 11 | +- 6 built-in themes (default, github, monokai, dracula, nord, minimal) |
| 12 | +- Customizable themes and styling |
| 13 | +- Side-by-side and unified diff views |
| 14 | +- Parse and create unified diff format |
| 15 | + |
| 16 | +## Installation |
| 17 | + |
| 18 | +```bash |
| 19 | +npm install @interweb/visual-diff |
| 20 | +# or |
| 21 | +pnpm add @interweb/visual-diff |
| 22 | +# or |
| 23 | +yarn add @interweb/visual-diff |
| 24 | +``` |
| 25 | + |
| 26 | +## Quick Start |
| 27 | + |
| 28 | +```typescript |
| 29 | +import { diff, renderTerminal, renderHtml } from '@interweb/visual-diff'; |
| 30 | + |
| 31 | +const oldCode = `function hello() { |
| 32 | + console.log("Hello"); |
| 33 | +}`; |
| 34 | + |
| 35 | +const newCode = `function hello() { |
| 36 | + console.log("Hello, World!"); |
| 37 | +}`; |
| 38 | + |
| 39 | +// Compute the diff |
| 40 | +const result = diff(oldCode, newCode); |
| 41 | + |
| 42 | +// Render to terminal with syntax highlighting |
| 43 | +console.log(renderTerminal(result, { |
| 44 | + language: 'javascript', |
| 45 | + theme: 'dracula' |
| 46 | +})); |
| 47 | + |
| 48 | +// Render to HTML |
| 49 | +const html = renderHtml(result, { |
| 50 | + language: 'javascript', |
| 51 | + darkMode: true |
| 52 | +}); |
| 53 | +``` |
| 54 | + |
| 55 | +## API |
| 56 | + |
| 57 | +### Diff Functions |
| 58 | + |
| 59 | +#### `diff(oldContent, newContent, options?)` |
| 60 | + |
| 61 | +Computes the diff between two strings. |
| 62 | + |
| 63 | +```typescript |
| 64 | +const result = diff(oldContent, newContent, { |
| 65 | + context: 3, // Number of context lines (default: 3) |
| 66 | + ignoreWhitespace: false, // Ignore whitespace differences |
| 67 | + ignoreCase: false // Ignore case differences |
| 68 | +}); |
| 69 | +``` |
| 70 | + |
| 71 | +#### `diffFiles(oldContent, newContent, oldFile, newFile, options?)` |
| 72 | + |
| 73 | +Computes diff with file metadata and auto-detected language. |
| 74 | + |
| 75 | +```typescript |
| 76 | +const result = diffFiles( |
| 77 | + oldContent, |
| 78 | + newContent, |
| 79 | + 'src/old.ts', |
| 80 | + 'src/new.ts' |
| 81 | +); |
| 82 | +// result.language will be 'typescript' |
| 83 | +``` |
| 84 | + |
| 85 | +### Render Functions |
| 86 | + |
| 87 | +#### `renderTerminal(result, options?)` |
| 88 | + |
| 89 | +Renders diff to terminal with ANSI colors. |
| 90 | + |
| 91 | +```typescript |
| 92 | +const output = renderTerminal(result, { |
| 93 | + theme: 'github', // Theme name or custom theme |
| 94 | + showLineNumbers: true, // Show line numbers |
| 95 | + syntaxHighlight: true, // Enable syntax highlighting |
| 96 | + language: 'typescript', // Override language detection |
| 97 | + colorize: true // Enable ANSI colors |
| 98 | +}); |
| 99 | +``` |
| 100 | + |
| 101 | +#### `renderHtml(result, options?)` |
| 102 | + |
| 103 | +Renders diff to HTML. |
| 104 | + |
| 105 | +```typescript |
| 106 | +const html = renderHtml(result, { |
| 107 | + theme: 'monokai', |
| 108 | + darkMode: true, |
| 109 | + className: 'my-diff', |
| 110 | + inlineStyles: true, |
| 111 | + syntaxHighlight: true |
| 112 | +}); |
| 113 | +``` |
| 114 | + |
| 115 | +#### `renderHtmlDocument(result, options?)` |
| 116 | + |
| 117 | +Renders a complete HTML document with the diff. |
| 118 | + |
| 119 | +#### `renderHtmlSideBySide(result, options?)` |
| 120 | + |
| 121 | +Renders diff in side-by-side layout. |
| 122 | + |
| 123 | +### Themes |
| 124 | + |
| 125 | +Built-in themes: |
| 126 | +- `default` - Clean default theme |
| 127 | +- `github` - GitHub-style colors |
| 128 | +- `monokai` - Monokai editor theme |
| 129 | +- `dracula` - Dracula theme |
| 130 | +- `nord` - Nord color palette |
| 131 | +- `minimal` - Minimal styling |
| 132 | + |
| 133 | +#### Custom Themes |
| 134 | + |
| 135 | +```typescript |
| 136 | +import { createTheme } from '@interweb/visual-diff'; |
| 137 | + |
| 138 | +const myTheme = createTheme('custom', { |
| 139 | + added: { fg: 'cyan', bold: true }, |
| 140 | + removed: { fg: 'yellow' }, |
| 141 | + syntax: { |
| 142 | + keyword: { fg: 'magenta', bold: true }, |
| 143 | + string: { fg: 'green' } |
| 144 | + } |
| 145 | +}); |
| 146 | + |
| 147 | +renderTerminal(result, { theme: myTheme }); |
| 148 | +``` |
| 149 | + |
| 150 | +### Syntax Highlighting |
| 151 | + |
| 152 | +Supported languages: |
| 153 | +- JavaScript / TypeScript |
| 154 | +- Python |
| 155 | +- JSON |
| 156 | +- HTML / XML |
| 157 | +- CSS / SCSS |
| 158 | +- SQL |
| 159 | +- YAML |
| 160 | +- Markdown |
| 161 | +- Go |
| 162 | +- Rust |
| 163 | +- Java |
| 164 | +- C / C++ |
| 165 | +- Shell / Bash |
| 166 | + |
| 167 | +#### Language Detection |
| 168 | + |
| 169 | +```typescript |
| 170 | +import { detectLanguage } from '@interweb/visual-diff'; |
| 171 | + |
| 172 | +detectLanguage('file.ts'); // 'typescript' |
| 173 | +detectLanguage('file.py'); // 'python' |
| 174 | +detectLanguage('file.sql'); // 'sql' |
| 175 | +``` |
| 176 | + |
| 177 | +### Unified Diff Format |
| 178 | + |
| 179 | +```typescript |
| 180 | +import { createUnifiedDiff, parseUnifiedDiff } from '@interweb/visual-diff'; |
| 181 | + |
| 182 | +// Create unified diff string |
| 183 | +const unified = createUnifiedDiff(result); |
| 184 | + |
| 185 | +// Parse unified diff string |
| 186 | +const parsed = parseUnifiedDiff(unifiedDiffString); |
| 187 | +``` |
| 188 | + |
| 189 | +### Utilities |
| 190 | + |
| 191 | +```typescript |
| 192 | +import { hasDifferences, countChanges } from '@interweb/visual-diff'; |
| 193 | + |
| 194 | +// Check if there are any differences |
| 195 | +if (hasDifferences(result)) { |
| 196 | + // Get counts |
| 197 | + const { additions, deletions } = countChanges(result); |
| 198 | + console.log(`+${additions} -${deletions}`); |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +## License |
| 203 | + |
| 204 | +MIT |
0 commit comments