From 5452bc96b16b4e16d61b5256b6c615dc8902ab70 Mon Sep 17 00:00:00 2001 From: Paulo Victor Cordeiro <146781332+pvcordeiro@users.noreply.github.com> Date: Tue, 2 Jun 2026 17:59:05 +0100 Subject: [PATCH] fix: markdown table renders separator row as visible data (#1252) * fix: markdown table renders separator row as visible data The alignment separator (|---|---|) at row index 1 was rendered as a row with dashes as cell content. Skip it and only open at that point, so tables render as header + data without the garbage separator row in between. * test: add regression test for table separator row rendering Verifies that the markdown table renderer skips the separator row (|---|---|) instead of rendering it as a visible data row. Also updates the test harness to handle the splitTableRow import. --- static/js/markdown.js | 8 +++++--- tests/test_markdown_rendering_js.py | 23 +++++++++++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/static/js/markdown.js b/static/js/markdown.js index efd2d02..7895a13 100644 --- a/static/js/markdown.js +++ b/static/js/markdown.js @@ -536,16 +536,18 @@ export function mdToHtml(src) { let html = ''; rows.forEach((row, idx) => { + if (idx === 1 && /^[\s|:\-]+$/.test(row)) { + html += ''; + return; + } const cells = splitTableRow(row); if (cells.length === 0) return; - html += idx === 1 ? '' : ''; html += ''; cells.forEach(cell => { const tag = idx === 0 ? 'th' : 'td'; - const style = idx === 1 ? 'style="border-top: 2px solid var(--red);"' : ''; - html += `<${tag} ${style} style="padding: 8px; text-align: left; border-bottom: 1px solid var(--border);">${cell.trim()}`; + html += `<${tag} style="padding: 8px; text-align: left; border-bottom: 1px solid var(--border);">${cell.trim()}`; }); html += ''; diff --git a/tests/test_markdown_rendering_js.py b/tests/test_markdown_rendering_js.py index f606fdd..75af810 100644 --- a/tests/test_markdown_rendering_js.py +++ b/tests/test_markdown_rendering_js.py @@ -20,7 +20,7 @@ def node_available(): def _run_markdown_case(markdown: str) -> str: script = textwrap.dedent( - """ + r""" import fs from 'node:fs'; globalThis.window = { location: { origin: 'http://localhost' }, katex: null }; @@ -32,7 +32,17 @@ def _run_markdown_case(markdown: str) -> str: let source = fs.readFileSync('./static/js/markdown.js', 'utf8'); source = source.replace( - "import uiModule from './ui.js';\\n\\nvar escapeHtml = uiModule.esc;", + /import uiModule from ['"]\.\/ui\.js['"];/, + '' + ); + source = source.replace( + /import \{ splitTableRow \} from ['"]\.\/markdown\/tableRow\.js['"];/, + `function splitTableRow(row) { + return (row || '').replace(/^\\s*\\|/, '').replace(/\\|\\s*$/, '').split('|').map(c => c.trim()); + }` + ); + source = source.replace( + /var escapeHtml = uiModule\.esc;/, `var escapeHtml = (value) => String(value ?? '') .replace(/&/g, '&') .replace(/
  • " not in html assert "

    Before

    " in html assert "

    After

    " in html + + +def test_table_separator_row_not_rendered_as_data(node_available): + html = _run_markdown_case("| A | B |\n|---|---|\n| 1 | 2 |") + + assert html.count("
  • ") == 2 + assert "