feat(opencode): enhanced markdown renderer with tables, themes, and syntax highlighting
Related Issues
Tables & Formatting:
- Closes #3845 - Markdown tables display as plain text instead of formatted tables
- Closes #7671 - Markdown table formatting
- Closes #4988 - [FEATURE]: Support Table Rendering in Markdown Format
- Closes #5675 - markdown user messages aren't formatted
Summary
Comprehensive markdown rendering overhaul for both CLI and TUI with proper table support, theme integration, syntax highlighting, and unified rendering architecture.
Key Features
📊 Table Rendering
- ✅ Box-drawing borders - Unicode characters (┌─┬─┐) instead of ASCII pipes
- ✅ Automatic column sizing - Proportional width distribution based on content
- ✅ Word wrapping - Long content wraps within cells without breaking inline code
- ✅ Backtick preservation - Never breaks `code` across lines
- ✅ Inline markdown in cells - Bold, italic, code, links all work in table cells
- ✅ Escaped pipes - Support for \| to show literal pipes (TypeScript union types: `number | undefined`)
- ✅ Double-width character support - Proper alignment with Unicode/emoji
🎨 Theme Support
- ✅ Unified theme system - CLI and TUI use identical colors from user's theme
- ✅ 12+ built-in themes - opencode, dracula, nord, catppuccin, tokyo-night, etc.
- ✅ Theme loader - Loads theme JSON files and converts to rendering format
- ✅ Automatic detection - Reads from user config, no manual setup needed
💻 Syntax Highlighting
- ✅ Tree-sitter integration - Uses OpenTUI's tree-sitter for code blocks
- ✅ 10+ languages - JavaScript, TypeScript, Python, Go, Rust, Shell, etc.
- ✅ Diff highlighting - Red/green colors for added/removed lines
- ✅ Stable rendering - No flashing during streaming
🎯 Advanced Formatting
- ✅ Inline markdown - **bold**, *italic*, `code`, links, ~~strikethrough~~
- ✅ Lists - Numbered and bulleted with colored markers
- ✅ Blockquotes - Bar with proper formatting
- ✅ Headers - Background color for h1/h2, bold for h3+
- ✅ Horizontal rules - Clean separator lines
🏗️ Architecture
- ✅ Unified rendering - Single source of truth (`renderMarkdownThemedStyled()`)
- ✅ Code deduplication - CLI and TUI share rendering logic
- ✅ TextChunk system - Universal format converted to ANSI (CLI) or StyledText (TUI)
- ✅ Clean codebase - Removed 283 lines of dead legacy code (-18%)
🔧 Smart Behavior
- ✅ TTY detection - Raw text when piped, formatted when interactive
- ✅ Context-aware - GitHub bot doesn't load themes (no overhead for automation)
- ✅ Streaming-friendly - No re-renders or flashing during message streaming
Technical Details
Files Changed
- `markdown-renderer.ts` (new, 1297 lines) - Core rendering engine
- `theme-loader.ts` (new, 98 lines) - Theme loading and conversion
- `session/index.tsx` (+117 lines) - TUI integration with hybrid rendering
- `run.ts` (+8 lines) - CLI theme integration
- `ui.ts` (+5 lines) - Theme parameter support
Key Functions
- `renderMarkdownThemedStyled()` - Main renderer, outputs TextChunks
- `renderTableThemed()` - Table rendering with word wrap and inline markdown
- `renderInlineThemed()` - Inline formatting (bold, italic, code, links)
- `textChunksToAnsi()` - Converts TextChunks to ANSI for CLI
- `loadTheme()` - Loads and converts theme JSON to rendering format
Rendering Flow
CLI: ``` User config → loadTheme() → MarkdownTheme Markdown → renderMarkdownThemedStyled() → TextChunks TextChunks → textChunksToAnsi() → ANSI string → stdout ```
TUI:
```
User config → Theme context → MarkdownTheme
Markdown → parseMarkdownSegments() → [text, code, text, code]
Text segments → renderMarkdownThemedStyled() → StyledText →
```
Examples
Before/After: Tables
Before: ``` | Header | Value | | A | B | ```
After: ``` ┌────────┬───────┐ │ Header │ Value │ ├────────┼───────┤ │ A │ B │ └────────┴───────┘ ```
Theme Colors
All colors match user's selected theme:
- Headers - Accent color with background
- Code - Monospace with code color
- Links - Link color + underline
- Bold/Italic - Distinct from regular text
- Borders - Border color from theme
Testing
✅ CLI output verified with multiple themes
✅ TUI rendering stable during streaming
✅ Tables with complex content (inline code, word wrap, unicode)
✅ Escaped pipes (\|) for union types
✅ Double-width characters (emoji, CJK)
✅ TTY detection (piped vs interactive)
✅ All 12+ built-in themes load correctly
Breaking Changes
None - backward compatible. Existing markdown rendering continues to work.
Performance
- Minimal overhead - Only loads theme once per session
- No flashing - Stable rendering during streaming
- Smart caching - Theme colors resolved once
- Efficient word wrap - Token-based wrapping preserves inline code
Migration Notes
No migration needed. The feature is automatically available in both CLI and TUI.
Commits
22 commits with iterative improvements:
- Initial implementation
- Stability fixes (flashing, streaming)
- Feature additions (tables, themes, inline markdown)
- Code cleanup (removed 283 lines of dead code)
- Bug fixes (escaped pipes, unicode width)
- Refactoring (unified architecture)