fix(tui): render inline markdown formatting with ANSI codes

Block-level renderer methods (paragraph, heading, blockquote, list) were
using raw token.text instead of this.parser.parseInline(tokens), causing
bold, italic, and inline code to never render. Add table renderer with
aligned columns and box-drawing separators. Remove unused marked-terminal
dependency (incompatible with marked v17).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
William Valentin
2026-02-10 11:29:57 -08:00
parent ff03f74404
commit 4cc29f534a
4 changed files with 150 additions and 131 deletions
+86 -5
View File
@@ -7,8 +7,37 @@ describe('renderMarkdown', () => {
expect(result).toContain('Hello world');
});
it('renders bold text', () => {
it('renders bold text with ANSI bold code', () => {
const result = renderMarkdown('This is **bold** text');
expect(result).toContain('\x1b[1m');
expect(result).toContain('bold');
expect(result).toContain('\x1b[0m');
});
it('renders italic text with ANSI italic code', () => {
const result = renderMarkdown('This is *italic* text');
expect(result).toContain('\x1b[3m');
expect(result).toContain('italic');
expect(result).toContain('\x1b[0m');
});
it('renders inline code with ANSI cyan code', () => {
const result = renderMarkdown('Use `console.log()` for debugging');
expect(result).toContain('\x1b[36m');
expect(result).toContain('console.log()');
expect(result).toContain('\x1b[0m');
});
it('renders headings with bold + underline', () => {
const result = renderMarkdown('# My Heading');
expect(result).toContain('\x1b[1m\x1b[4m');
expect(result).toContain('My Heading');
expect(result).toContain('\x1b[0m');
});
it('renders heading with inline formatting', () => {
const result = renderMarkdown('## A **bold** heading');
expect(result).toContain('\x1b[1m');
expect(result).toContain('bold');
});
@@ -18,14 +47,66 @@ describe('renderMarkdown', () => {
expect(result).toContain('x');
});
it('renders inline code', () => {
const result = renderMarkdown('Use `console.log()` for debugging');
expect(result).toContain('console.log()');
it('renders code blocks with unknown language without crashing', () => {
const result = renderMarkdown('```madeuplang\nsome code\n```');
expect(result).toContain('some code');
});
it('renders lists', () => {
it('renders unordered lists', () => {
const result = renderMarkdown('- Item 1\n- Item 2');
expect(result).toContain('•');
expect(result).toContain('Item 1');
expect(result).toContain('Item 2');
});
it('renders inline formatting inside list items', () => {
const result = renderMarkdown('- **bold** item\n- `code` item');
expect(result).toContain('\x1b[1m');
expect(result).toContain('bold');
expect(result).toContain('\x1b[36m');
expect(result).toContain('code');
});
it('renders blockquotes with │ prefix', () => {
const result = renderMarkdown('> This is a quote');
expect(result).toContain('│');
expect(result).toContain('This is a quote');
});
it('renders inline formatting inside blockquotes', () => {
const result = renderMarkdown('> A **bold** quote');
expect(result).toContain('│');
expect(result).toContain('\x1b[1m');
expect(result).toContain('bold');
});
it('renders tables with │ separator', () => {
const result = renderMarkdown('| Col A | Col B |\n|-------|-------|\n| 1 | 2 |\n| 3 | 4 |');
expect(result).toContain('│');
expect(result).toContain('Col A');
expect(result).toContain('Col B');
expect(result).toContain('1');
expect(result).toContain('4');
});
it('renders table headers in bold', () => {
const result = renderMarkdown('| Name | Value |\n|------|-------|\n| a | b |');
// Header cells should have bold ANSI
const lines = result.split('\n');
const headerLine = lines[0];
expect(headerLine).toContain('\x1b[1m');
});
it('renders horizontal rules', () => {
const result = renderMarkdown('---');
expect(result).toContain('─');
});
it('renders links with underline and blue URL', () => {
const result = renderMarkdown('[click here](https://example.com)');
expect(result).toContain('\x1b[4m');
expect(result).toContain('click here');
expect(result).toContain('\x1b[34m');
expect(result).toContain('https://example.com');
});
});