diff --git a/webclient/src/composables/useMarkdown.js b/webclient/src/composables/useMarkdown.js index dd2f15c..058b5b4 100644 --- a/webclient/src/composables/useMarkdown.js +++ b/webclient/src/composables/useMarkdown.js @@ -15,8 +15,11 @@ marked.use({ renderer }) -// Fix malformed GFM tables where the model merges the separator row with data. -// Pattern: line after a pipe-row whose cells aren't all valid separators (---/:---/---:). +// Fix malformed GFM tables: +// 1. Missing separator row — inject one between header and first data row. +// 2. Mixed separator/data row — inject proper separator before it. +// 3. Spurious all-separator rows inside the table body (model uses them as +// visual dividers) — strip them once the real header separator has been seen. function fixTables(text) { const lines = text.split('\n') const out = [] @@ -24,29 +27,47 @@ const isSepCell = c => /^:?-+:?$/.test(c.trim()) const colCount = l => l.split('|').slice(1, -1).length + let seenSep = false // have we emitted the header separator for the current table? + for (let i = 0; i < lines.length; i++) { const line = lines[i] const prev = out[out.length - 1] ?? '' - if (isPipeRow(line) && isPipeRow(prev)) { - const cells = line.split('|').slice(1, -1) - const allSep = cells.every(isSepCell) - const noneSep = cells.every(c => !isSepCell(c)) + if (!isPipeRow(line)) { + // Leaving table context + seenSep = false + out.push(line) + continue + } - if (!allSep && !noneSep) { - // Mixed: first cell looks like a mangled separator — inject a proper separator and re-emit line as data - const n = colCount(prev) - out.push('| ' + Array(n).fill('---').join(' | ') + ' |') + const cells = line.split('|').slice(1, -1) + const allSep = cells.every(isSepCell) + const noneSep = cells.every(c => !isSepCell(c)) + + if (allSep) { + if (!seenSep) { + // First separator row — keep it as the header separator + seenSep = true out.push(line) - continue } + // Subsequent all-separator rows are spurious visual dividers — drop them + continue + } - if (noneSep && i + 1 < lines.length && isPipeRow(lines[i + 1])) { - // Separator row is completely missing — inject it before this data row - const n = colCount(prev) - out.push('| ' + Array(n).fill('---').join(' | ') + ' |') + if (isPipeRow(prev)) { + if (!seenSep) { + if (!noneSep) { + // Mixed row: mangled separator — inject a clean one, treat this line as data + out.push('| ' + Array(colCount(prev)).fill('---').join(' | ') + ' |') + seenSep = true + } else if (i + 1 < lines.length && isPipeRow(lines[i + 1])) { + // Separator row is missing entirely — inject it + out.push('| ' + Array(colCount(prev)).fill('---').join(' | ') + ' |') + seenSep = true + } } } + out.push(line) } return out.join('\n')