From c277418349c286b09e2f487c16da60e8add65b4b Mon Sep 17 00:00:00 2001 From: mitchell Date: Tue, 26 May 2026 03:43:23 -0400 Subject: [PATCH] fix: list/blockquote newlines and table width --- src/render/markdown.ts | 51 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/render/markdown.ts b/src/render/markdown.ts index 9ccb4b0..64276c1 100644 --- a/src/render/markdown.ts +++ b/src/render/markdown.ts @@ -17,7 +17,7 @@ let highligherLangs = ""; class SWCell extends Cell { public override get length() { - return stringWidth(this.toString(), { ambiguousIsNarrow: true }); + return stringWidth(this.toString()); } } @@ -25,7 +25,7 @@ class LmcRenderer extends Renderer { private columns: number; constructor(columns: number) { - super({ gfm: true }); + super(); this.columns = columns; } @@ -49,14 +49,13 @@ class LmcRenderer extends Renderer { override paragraph({ tokens }: Tokens.Paragraph) { const text = this.parser.parseInline(tokens); - return wrapAnsi(`\n${text}\n`, this.columns, { trim: false }); + return wrapAnsi(`\n${text}\n`, this.columns - 2, { trim: false }); } override blockquote({ tokens }: Tokens.Blockquote) { - const text = this.parser.parse(tokens).trim(); - const lines = wrapAnsi(`\n${text}\n`, this.columns - 2, { - trim: false, - }).split("\n"); + let text = this.parser.parse(tokens).trim(); + if (!text.includes("\n")) text = wrapAnsi(text, this.columns - 2); + const lines = `\n${text}\n`.split("\n"); const toRender = lines.map((line) => `> ${line}`).join("\n"); return `${toRender.replaceAll(">", chalk.dim(">"))}\n`; } @@ -85,33 +84,36 @@ class LmcRenderer extends Renderer { this.listitem(item, ordered ? num + index : undefined), ) .join("\n"); - return `\n${renderedItems}\n`.replaceAll("\n\n", "\n"); + return `\n${renderedItems}\n`; } - override listitem({ task, checked, tokens }: Tokens.ListItem, num?: number) { - const text = this.parser.parse(tokens); + override listitem({ tokens }: Tokens.ListItem, num?: number) { + const text = this.parser.parse(tokens).trim(); let marker = ""; - if (task) { - marker = checked ? "• [✓]" : "• [ ]"; - } else if (num !== undefined) { + if (num !== undefined) { marker = `${num}.`; } else { marker = "•"; } - const cols = this.columns - 2; - return wrapAnsi(`${marker} ${text}`, cols, { trim: false }) + let item = `${marker} ${text}`; + if (!item.includes("\n")) item = wrapAnsi(item, this.columns - 2); + return item .split("\n") .map((line) => (line.length > 0 ? ` ${line}` : "")) .join("\n"); } + override checkbox({ checked }: Tokens.Checkbox): string { + return checked ? "[✓] " : "[ ] "; + } + override hr() { return `\n${chalk.dim("─".repeat(this.columns))}\n`; } override table({ header, rows }: Tokens.Table) { - const headerCells = header.map((col) => { + const headers = header.map((col) => { const text = this.parser.parseInline(col.tokens); return new SWCell(chalk.red.bold(text)); }); @@ -123,11 +125,13 @@ class LmcRenderer extends Renderer { }), ); + const cols = this.columns - (headers.length * 3 + 1); + const maxWidth = Math.floor(cols / headers.length); const table = new Table() - .header(headerCells) + .header(headers) .body(body) .border() - .maxColWidth(Math.floor((this.columns - 4) / headerCells.length)) + .maxColWidth(maxWidth) .toString(); return `\n${table}\n`; @@ -161,8 +165,8 @@ class LmcRenderer extends Renderer { return chalk.red("\nImages are unsupported (for now)\n"); } - override text(token: Tokens.Text) { - if (token.tokens) { + override text(token: Tokens.Text | Tokens.Escape) { + if (token.type === "text" && token.tokens) { return this.parser.parseInline(token.tokens); } return token.text @@ -205,12 +209,7 @@ export async function renderMarkdown( } const renderer = new LmcRenderer(columns); - marked.setOptions({ - renderer, - gfm: true, - }); - - const rendered = await marked.parse(md); + const rendered = await marked.parse(md, { renderer }); return rendered.trimStart(); }