Skip to content

fix(mdx): collapse blank lines between JSX table elements on serialize#1444

Open
jesseyowell wants to merge 1 commit into
nextfrom
fix/mdx-table-whitespace
Open

fix(mdx): collapse blank lines between JSX table elements on serialize#1444
jesseyowell wants to merge 1 commit into
nextfrom
fix/mdx-table-whitespace

Conversation

@jesseyowell

Copy link
Copy Markdown

Problem

When the MDX serializer outputs a JSX table (i.e. a table with flow content like lists, code blocks, or paragraph breaks in cells), blank lines are introduced between every pair of sibling table elements:

    </th>
                        <!-- blank line inserted here -->
    <th style={{ textAlign: "center" }}>

This happens between </th><th>, </td><td>, </thead><tbody>, and </tr><tr>. The MDX renderer treats these blank lines as new AST nodes, which breaks table structure on re-parse.

Root cause

mdast-util-mdx-jsx's containerFlow function unconditionally inserts \n\n between all children of flow JSX elements. This is correct for most block elements, but for table sub-elements (<thead>, <tbody>, <tr>, <th>, <td>) it produces whitespace that breaks the table when the MDX is later parsed.

Fix

Post-process the serialized MDX string in lib/mdx.ts to collapse \n\n\n specifically between closing and opening table element tags:

return string.replace(
  /(<\/(?:th|td|tr|thead|tbody)>)\n\n(\s*<(?:th|td|tr|thead|tbody)[\s>])/g,
  '$1\n$2',
);

The regex only matches tag boundaries, so blank lines inside cell content (intentional paragraph breaks) are preserved.

Before

<Table align={["center","center"]}>
  <thead>
    <tr>
      <th style={{ textAlign: "center" }}>
        Header 1
      </th>

      <th style={{ textAlign: "center" }}>
        Header 2
      </th>
    </tr>
  </thead>

  <tbody>
    ...
  </tbody>
</Table>

After

<Table align={["center","center"]}>
  <thead>
    <tr>
      <th style={{ textAlign: "center" }}>
        Header 1
      </th>
      <th style={{ textAlign: "center" }}>
        Header 2
      </th>
    </tr>
  </thead>
  <tbody>
    ...
  </tbody>
</Table>

Tests

All 1993 tests pass. 11 inline snapshots updated across 4 test files to reflect the removed blank lines:

  • __tests__/compilers/tables.test.js — 6 snapshots (core table serialization)
  • __tests__/migration/tables.test.ts — 3 snapshots (RDMD → MDX migration)
  • __tests__/compilers/compatability.test.tsx — 1 snapshot
  • __tests__/migration/link-reference.test.ts — 1 snapshot

🤖 Generated with Claude Code

mdast-util-mdx-jsx's containerFlow function inserts \n\n between all
children of flow JSX elements. For tables converted to JSX (via
tables-to-jsx), this introduces blank lines between sibling elements
like </th> and <th>, </thead> and <tbody>, etc. The MDX renderer
treats these blank lines as new AST nodes, breaking table structure.

Post-process the serialized MDX string to collapse \n\n → \n
specifically between closing/opening table element tags. Blank lines
inside cell content (intentional paragraph breaks) are preserved.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant