Skip to content

fix(preset-gfm): incorrect table parsing when pasting from Google Docs - #2283

Merged
Saul-Mirone merged 2 commits into
mainfrom
fix/table-paste-google-docs
Mar 22, 2026
Merged

Saul-Mirone merged 2 commits into
mainfrom
fix/table-paste-google-docs

Conversation

@Saul-Mirone

@Saul-Mirone Saul-Mirone commented Mar 22, 2026

Copy link
Copy Markdown
Member
  • I read the contributing guide
  • I agree to follow the code of conduct

Summary

Fixes #2259

Google Docs tables only use <td>, never <th>. When pasting such a table, ProseMirror's schema (content: 'table_header_row table_row+') auto-inserts an empty table_header_row, and the paste rule fills it with empty <br> cells — producing N+1 rows instead of N.

The fix promotes the first data row to become the header row (converting table_celltable_header) when there are 2+ data rows. For single-row tables, the existing fallback (empty header cells) is kept to satisfy the table_row+ constraint.

Also switched from flat slice.content.forEach to a recursive traversal so tables nested inside wrapper nodes (e.g. Google Docs' <b><div>…</div></b> structure) are found and fixed.

How did you test this change?

E2E tests.

Google Docs tables use only <td>, never <th>. ProseMirror auto-inserts
an empty table_header_row, resulting in an extra row with empty cells.

Promote the first data row to header when there are 2+ data rows.
For single-row tables, keep existing fallback (empty header cells).

Also add recursive traversal in the paste rule so tables nested inside
wrapper nodes are found and fixed.

Closes #2259
@vercel

vercel Bot commented Mar 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
milkdown-storybook Ready Ready Preview, Comment Mar 22, 2026 1:01pm

Request Review

@changeset-bot

changeset-bot Bot commented Mar 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6d43627

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Mar 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@milkdown/components

npm i https://pkg.pr.new/@milkdown/components@2283

@milkdown/core

npm i https://pkg.pr.new/@milkdown/core@2283

@milkdown/crepe

npm i https://pkg.pr.new/@milkdown/crepe@2283

@milkdown/ctx

npm i https://pkg.pr.new/@milkdown/ctx@2283

@milkdown/exception

npm i https://pkg.pr.new/@milkdown/exception@2283

@milkdown/kit

npm i https://pkg.pr.new/@milkdown/kit@2283

@milkdown/prose

npm i https://pkg.pr.new/@milkdown/prose@2283

@milkdown/transformer

npm i https://pkg.pr.new/@milkdown/transformer@2283

@milkdown/utils

npm i https://pkg.pr.new/@milkdown/utils@2283

@milkdown/react

npm i https://pkg.pr.new/@milkdown/react@2283

@milkdown/vue

npm i https://pkg.pr.new/@milkdown/vue@2283

@milkdown/plugin-automd

npm i https://pkg.pr.new/@milkdown/plugin-automd@2283

@milkdown/plugin-block

npm i https://pkg.pr.new/@milkdown/plugin-block@2283

@milkdown/plugin-clipboard

npm i https://pkg.pr.new/@milkdown/plugin-clipboard@2283

@milkdown/plugin-collab

npm i https://pkg.pr.new/@milkdown/plugin-collab@2283

@milkdown/plugin-cursor

npm i https://pkg.pr.new/@milkdown/plugin-cursor@2283

@milkdown/plugin-emoji

npm i https://pkg.pr.new/@milkdown/plugin-emoji@2283

@milkdown/plugin-highlight

npm i https://pkg.pr.new/@milkdown/plugin-highlight@2283

@milkdown/plugin-history

npm i https://pkg.pr.new/@milkdown/plugin-history@2283

@milkdown/plugin-indent

npm i https://pkg.pr.new/@milkdown/plugin-indent@2283

@milkdown/plugin-listener

npm i https://pkg.pr.new/@milkdown/plugin-listener@2283

@milkdown/plugin-prism

npm i https://pkg.pr.new/@milkdown/plugin-prism@2283

@milkdown/plugin-slash

npm i https://pkg.pr.new/@milkdown/plugin-slash@2283

@milkdown/plugin-tooltip

npm i https://pkg.pr.new/@milkdown/plugin-tooltip@2283

@milkdown/plugin-trailing

npm i https://pkg.pr.new/@milkdown/plugin-trailing@2283

@milkdown/plugin-upload

npm i https://pkg.pr.new/@milkdown/plugin-upload@2283

@milkdown/preset-commonmark

npm i https://pkg.pr.new/@milkdown/preset-commonmark@2283

@milkdown/preset-gfm

npm i https://pkg.pr.new/@milkdown/preset-gfm@2283

@milkdown/theme-nord

npm i https://pkg.pr.new/@milkdown/theme-nord@2283

commit: 6d43627

@Saul-Mirone
Saul-Mirone enabled auto-merge March 22, 2026 13:03
@Saul-Mirone
Saul-Mirone added this pull request to the merge queue Mar 22, 2026
Merged via the queue into main with commit 7ca55f5 Mar 22, 2026
14 checks passed
@Saul-Mirone
Saul-Mirone deleted the fix/table-paste-google-docs branch March 22, 2026 13:08

This branch was successfully deployed

1 active deployment
Preview 6d436270 Deployed Mar 22, 2026 by vercel[bot]
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.

[Bug] Incorrect table parsing when pasting content from Google Docs in Milkdown

1 participant