Skip to content

fix: prevent crash in normalizeTable when body row has more cells than header - #4222

Merged
Jocs merged 1 commit into
developfrom
worktree-swirling-forging-sun
May 16, 2026
Merged

Jocs merged 1 commit into
developfrom
worktree-swirling-forging-sun

Conversation

@Jocs

@Jocs Jocs commented May 16, 2026 •

Copy link
Copy Markdown
Member

Closes #4190

Summary

  • Root cause: when a table body row contains more cells than the header row, columnWidth[j] is undefined for the extra columns, causing TypeError: Cannot read properties of undefined (reading 'width') in normalizeTable
  • Guard the width-calculation loop with Math.min(tableData[i].length, columnWidth.length) and .slice(0, columnWidth.length) before the row-rendering map, silently dropping extra cells (matches GFM spec behaviour)
  • Adds test/unit/specs/export-markdown.spec.js with 3 regression tests (well-formed table, body row with extra cells, body row with fewer cells)

Reproduction

Create a markdown file where a body row has more columns than the header and open it in MarkText — any save/export triggers the crash:

| col1 | col2 |
|------|------|
| a    | b    | extra |

Test plan

  • New unit test does not throw when a body row has more cells than the header (issue #4190) directly reproduces and verifies the fix
  • All 548 existing unit tests pass
  • Manual: open a table with mismatched column counts and verify no crash on save

🤖 Generated with Claude Code

…n header

Fixes TypeError: Cannot read properties of undefined (reading 'width')
(issue #4190). When a table body row contains more cells than the header,
columnWidth[j] is undefined for extra columns. Guard the width-calculation
loop with Math.min and slice body rows to header column count before
rendering, matching standard GFM behaviour of silently ignoring extra cells.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Copilot AI review requested due to automatic review settings May 16, 2026 06:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a normalizeTable crash when table body rows contain more cells than the header, aligning export behavior with GFM-style column limits and adding regression coverage.

Changes:

  • Caps table width calculation to the number of header-defined columns.
  • Drops extra body cells during Markdown rendering.
  • Adds unit tests for well-formed and mismatched table row lengths.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/muya/lib/utils/exportMarkdown.js Guards table normalization against body rows with extra cells and truncates rendered rows to header column count.
test/unit/specs/export-markdown.spec.js Adds regression tests for table export behavior with matching, extra, and fewer body cells.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions

Copy link
Copy Markdown

Build artifacts for PR #4222:

Run: https://github.com/marktext/marktext/actions/runs/25954684198

Artifact Size Link
marktext-macos-x64 564.8 MB Download
marktext-windows 284.9 MB Download
marktext-linux 628.5 MB Download
marktext-macos-arm64 567.3 MB Download

@Jocs
Jocs merged commit 9884342 into develop May 16, 2026
12 checks passed
@Jocs
Jocs deleted the worktree-swirling-forging-sun branch May 18, 2026 09:32
Jocs added a commit that referenced this pull request Jun 8, 2026
The serializeTable ragged-row coverage in tableNormalization.spec.ts
duplicated the existing serializeTable — row width mismatch suite in
stateToMarkdown.spec.ts (both #4222/#4190): same well-formed,
extra-cell-dropped, and short-row scenarios. Keeping two suites for one
behavior risks them drifting apart, so remove the redundant file and
keep the single existing suite as the source of truth.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Jocs added a commit that referenced this pull request Jun 8, 2026
* test(muya): port MarkText regression cases (#4341/#4307/#4190)

Port three MarkText-specific regression cases from the legacy
`packages/muyajs` desktop specs into `@muyajs/core`'s own suite to lock
in behavioral fidelity for the migration off legacy muyajs. Tests only —
no engine changes.

- #4341 nested mixed lists (ul-in-ol / ol-in-ul): PASS. The state tree
  from MarkdownToState nests the differing-type list under the correct
  list-item (no paragraph collapse), and md -> state -> md round-trips
  identically. Ported as structural + round-trip assertions.
- #4190 table normalization (body row with more/fewer cells than the
  header): PASS. StateToMarkdown.serializeTable clamps each row to the
  header column count (extra cell dropped) and never throws. The legacy
  spec hand-built a malformed block tree for ExportMarkdown.normalizeTable;
  the muya equivalent hand-builds a malformed ITableState because a GFM
  round trip can never produce a ragged table.
- #4307 CJK strong flanking (`**"加粗"**` against a CJK boundary):
  documented engine GAP. marked@16 implements the CommonMark flanking
  rule literally and classifies CJK ideographs / Hangul as "other"
  (neither whitespace nor punctuation), so `**` adjacent to a CJK char
  with punctuation-bounded inner content does not open/close emphasis.
  Legacy muyajs shipped a custom tokenizer that treats CJK as punctuation
  for flanking; marked does not. The four CJK cases assert the CORRECT
  (legacy) behavior under `it.fails`, so the suite stays green while the
  gap exists and flips red the moment the gap closes. Sanity cases that
  already work are plain `it` so a future fix can't regress them.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* test(muya): drop duplicate tableNormalization spec

The serializeTable ragged-row coverage in tableNormalization.spec.ts
duplicated the existing serializeTable — row width mismatch suite in
stateToMarkdown.spec.ts (both #4222/#4190): same well-formed,
extra-cell-dropped, and short-row scenarios. Keeping two suites for one
behavior risks them drifting apart, so remove the redundant file and
keep the single existing suite as the source of truth.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
thimbleberrysystems pushed a commit to thimbleberrysystems/WordBird that referenced this pull request Jun 21, 2026
…n header (marktext#4222)

Fixes TypeError: Cannot read properties of undefined (reading 'width')
(issue marktext#4190). When a table body row contains more cells than the header,
columnWidth[j] is undefined for extra columns. Guard the width-calculation
loop with Math.min and slice body rows to header column count before
rendering, matching standard GFM behaviour of silently ignoring extra cells.

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
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.

Unexpected error: Cannot read properties of undefined (reading 'width')

2 participants