Repository navigation
bugfix: normalize ragged tables left by updates that skip transforms - #9459
Open
madsysharma wants to merge 1 commit into
Open
madsysharma wants to merge 1 commit into
madsysharma wants to merge 1 commit into
Conversation
madsysharma
requested review from
acywatson,
etrepum,
fantactuka,
ivailop7,
potatowagon and
zurfyx
as code owners
October 24, 2026 20:52
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Author
|
Hi @acywatson @etrepum @fantactuka @ivailop7 @potatowagon @zurfyx - please review this PR and let me know if everything is good to go. Thank you. |
lexical
@lexical/a11y
@lexical/clipboard
@lexical/code
@lexical/code-core
@lexical/code-prism
@lexical/code-shiki
@lexical/compiler
@lexical/devtools-core
@lexical/dragon
@lexical/eslint-plugin
@lexical/extension
@lexical/fast-check
@lexical/file
@lexical/hashtag
@lexical/headless
@lexical/history
@lexical/html
@lexical/internal
@lexical/link
@lexical/list
@lexical/mark
@lexical/markdown
@lexical/mdast
@lexical/offset
@lexical/overflow
@lexical/plain-text
@lexical/react
@lexical/rich-text
@lexical/selection
@lexical/table
@lexical/tailwind
@lexical/text
@lexical/utils
@lexical/yjs
commit: |
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 26, 2026 01:50
bc04043 to
9166502
Compare
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 26, 2026 14:24
9166502 to
97b27f5
Compare
Author
|
Hi @acywatson @etrepum @fantactuka @ivailop7 @potatowagon @zurfyx - please review this PR and let me know if everything is good to go. Thank you. |
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 27, 2026 20:20
97b27f5 to
d454af6
Compare
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 27, 2026 23:18
d454af6 to
0168105
Compare
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 28, 2026 21:48
0168105 to
db26ee8
Compare
madsysharma
force-pushed
the
bug/ragged-tables
branch
from
October 29, 2026 22:34
db26ee8 to
7a920d0
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[lexical-table] Bug Fix: Normalize ragged tables left by updates that skip transforms
Description
Current behavior
The
TableNodetransform pads ragged tables via$padTableRows, but only for tables that an update marks dirty. While checking #9453, I tested each load path the issue lists:setEditorState(parseEditorState(json))is already padded: a parsed editor state marks every node dirty, so the transform runs. Tables that exist when the plugin registers are also covered, becauseregisterNodeTransformmarks existing nodes dirty.skipTransformsstay ragged, even withTablePlugin/TableExtensionregistered: this is how collaboration updates arrive. The table then stays ragged indefinitely, because later updates don't mark it dirty again.Option 1 in the issue, padding in
importJSON/updateFromJSON, isn't feasible.$parseSerializedNodeImplcalls those methods before it appends the table's rows, so there's nothing to pad at that point.Changes
registerTablePluginnow registers an update listener: i.e.,registerRaggedTableNormalization. When a committed update leaves a dirtyTableNoderagged, the listener pads it with$padTableRowsin a follow-up update taggedHISTORY_MERGE_TAG, so the padding is never an undo step of its own. BecauseTableExtensioncallsregisterTablePlugin, both entry points get the listener.COLLABORATION_TAGupdates: each peer receives the same remote change. If each peer padded it, the CRDT would keep all of the appended cells, making the row wider than the others, and the next transform would then pad the remaining rows, so the table would keep growing. Remote ragged tables thus stay ragged in the model until a local table command pads them (the existing behavior from issue [lexical-table][lexical-website] Bug Fix: Table commands throw or misbehave on a ragged table #9375).HISTORIC_TAGupdates, so that padding never rewrites the state being restored by undo or redo.TableNode.exportDOMnow pads the exported HTML of a ragged table to a rectangle without touching editor state. This makes export correct in headless editors and during collaboration. Padding cells mirror$padTableRows: a cell becomes a<th>when the row's last cell has the row-header bit, and it uses the same inline stylesTableCellNode.exportDOMwrites for a default cell. Partial exports of a selection are left unpadded, because the exported rows no longer line up with the table map.colSpanorrowSpanis present. Typing inside an ordinary table therefore doesn't compute the table map on every update.No public API was added; both new functions are module-private.
Closes #9453
Test plan
Before
skipTransforms: truestayed ragged ([2, 1]cells per row) withTableExtensionregistered, and it stayed ragged after subsequent updates.$generateHtmlFromNodesproduced rows of different lengths (3, 1, 2cells).After
New file:
packages/lexical-table/src/__tests__/unit/RaggedTableNormalization.test.ts(11 tests).setEditorState(parseEditorState(...))is rectangular. This locks in the existing behavior.skipTransformsupdate is padded, including rows whose width comes from acolSpan.HistoryExtension, a single undo removes both the table and its padding. This test fails if the padding update is not taggedHISTORY_MERGE_TAG.COLLABORATION_TAGorHISTORIC_TAGare not padded in the model.<th>.The three model-padding tests fail with the listener disabled, and the undo test fails without
HISTORY_MERGE_TAG.Existing suites pass:
lexicalcore,lexical-react(including the collaboration tests),lexical-yjs,lexical-history,lexical-clipboard,lexical-markdown,lexical-table,lexical-html, the playground unit tests, and every other unit test file that uses tables.tsc --noEmitand ESLint are clean.