export interface MarkdownNormalization { markdown: string; convertedTables: number; } function splitTableRow(line: string): string[] { const trimmed = line.trim().replace(/^\|/, "").replace(/\|$/, ""); return trimmed.split(/(? cell.trim().replace(/\\\|/g, "|")); } function isTableSeparator(line: string): boolean { const cells = splitTableRow(line); return cells.length > 0 && cells.every((cell) => /^:?-{3,}:?$/.test(cell)); } function formatTableRow(headers: string[], cells: string[]): string { const values = headers.map((header, index) => { const value = cells[index] ?? ""; return header ? `**${header}**:${value || "–"}` : value; }).filter(Boolean); return `- ${values.join(";")}`; } /** Convert GFM tables to readable paragraphs so word_create never creates a table by default. */ export function normalizeMarkdownWithoutTables(markdown: string): MarkdownNormalization { const lines = markdown.replace(/\r\n?/g, "\n").split("\n"); const output: string[] = []; let convertedTables = 0; for (let index = 0; index < lines.length; index += 1) { const headerLine = lines[index] ?? ""; const separatorLine = lines[index + 1] ?? ""; if (!headerLine.includes("|") || !separatorLine.includes("|") || !isTableSeparator(separatorLine)) { output.push(headerLine); continue; } const headers = splitTableRow(headerLine); const rows: string[][] = []; index += 2; while (index < lines.length && (lines[index] ?? "").includes("|") && (lines[index] ?? "").trim() !== "") { rows.push(splitTableRow(lines[index] ?? "")); index += 1; } index -= 1; convertedTables += 1; if (rows.length === 0) output.push(`- ${headers.join(";")}`); else output.push(...rows.map((row) => formatTableRow(headers, row))); } return { markdown: output.join("\n"), convertedTables }; }