From 551e08290ad1f2308d3be2445fdaf2b27140d155 Mon Sep 17 00:00:00 2001 From: fantomc0der Date: Mon, 27 Apr 2026 18:44:02 -0400 Subject: [PATCH] Fix colspan cells producing misaligned markdown table columns When a table cell has colspan>1, the table-cell Turndown rule now emits extra empty pipe-delimited columns (colspan-1 of them) so the rendered row always has the same column count as the separator and data rows. Previously a colspan="2" header like "mikethecoder" produced "| mikethecoder |" (1 column) while the separator and data rows had 2 columns, causing most markdown renderers to reject the table entirely. Co-Authored-By: Claude Opus 4.7 --- src/converters/html-to-markdown.ts | 5 ++++- tests/converters/html-to-markdown.test.ts | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/converters/html-to-markdown.ts b/src/converters/html-to-markdown.ts index 61e1d9a..7d919b5 100644 --- a/src/converters/html-to-markdown.ts +++ b/src/converters/html-to-markdown.ts @@ -194,7 +194,10 @@ function createTurndownService(): TurndownService { const text = content.replace(/[\r\n]+/g, " ").replace(/\|/g, "\\|").trim(); const index = directCellIndex(node); const prefix = index === 0 ? "| " : " "; - return prefix + text + " |"; + const rawSpan = parseInt((node as HTMLElement).getAttribute?.("colspan") ?? "1", 10); + const span = Number.isFinite(rawSpan) && rawSpan > 1 ? rawSpan : 1; + const extra = span > 1 ? " |".repeat(span - 1) : ""; + return prefix + text + " |" + extra; }, }); diff --git a/tests/converters/html-to-markdown.test.ts b/tests/converters/html-to-markdown.test.ts index e4865f4..48f57ab 100644 --- a/tests/converters/html-to-markdown.test.ts +++ b/tests/converters/html-to-markdown.test.ts @@ -288,7 +288,7 @@ describe("htmlToMarkdown", () => { expect(result).toContain("| Magic Number | 17 |"); }); - it("separator column count respects colspan on first-row cells", () => { + it("colspan cells emit extra empty columns to keep table width consistent", () => { const html = ` @@ -296,7 +296,7 @@ describe("htmlToMarkdown", () => {
Header
`; const result = htmlToMarkdown(html); - expect(result).toContain("| Header |"); + expect(result).toContain("| Header | |"); expect(result).toContain("| --- | --- |"); expect(result).toContain("| Left | Right |"); }); @@ -351,7 +351,7 @@ describe("htmlToMarkdown", () => { `; const result = htmlToMarkdown(html); - expect(result).toContain("| someuser |"); + expect(result).toContain("| someuser | |"); expect(result).toContain("| --- | --- |"); expect(result).toContain("| Magic Number | 17 |"); expect(result).toContain("| Job | Celebrity Nobody |");