fix(xl-docx-exporter): clamp list nesting to the levels DOCX defines - #2969
Conversation
`numberedListItem` and `bulletListItem` passed the block's `nestingLevel` straight into docx's `numbering.level`, but the numbering configs built in `createDefaultDocumentOptions` only define 9 levels (`w:ilvl` 0-8). Lists nested deeper than that produced two distinct failures: - 11 levels or more made docx throw "Level cannot be greater than 9", which aborted the entire export with no feedback beyond a console error. - Exactly 10 levels did not throw, but emitted `<w:ilvl w:val="9"/>` while `numbering.xml` defines no level 9, so that item lost its bullet and indent. Clamp the level to the deepest one the numbering config defines, so deeper items render at that level instead - the same way Word collapses nesting past its own 9-level limit. The level count now comes from a single shared constant, so the config and the mappings cannot drift apart. Fixes TypeCellOS#2228
|
@adarshsm is attempting to deploy a commit to the TypeCell Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughDOCX export now defines the supported nine-level list range, clamps deeper numbered and bulleted list nesting to level 8, generates list configurations from the shared limit, and tests deep nested bullet-list export. ChangesDOCX list-level handling
Estimated code review effort: 2 (Simple) | ~10 minutes Mergeability Score: ⚪ Minimal · up to The change clamps deeply nested DOCX lists to supported numbering levels and adds regression coverage; no actionable merge-blocking risk remains beyond normal checks and review. Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
nperez0111
left a comment
There was a problem hiding this comment.
Thanks for this @adarshsm
@blocknote/ariakit
@blocknote/code-block
@blocknote/core
@blocknote/mantine
@blocknote/react
@blocknote/server-util
@blocknote/shadcn
@blocknote/xl-ai
@blocknote/xl-docx-exporter
@blocknote/xl-email-exporter
@blocknote/xl-multi-column
@blocknote/xl-odt-exporter
@blocknote/xl-pdf-exporter
commit: |
Fixes #2228.
The bug
numberedListItemandbulletListItempass the block'snestingLevelstraight into docx'snumbering.level:But the numbering configs built in
createDefaultDocumentOptionsdefine only 9 levels (w:ilvl0-8):Nothing reconciles the two, so a deeply nested list asks for a level that doesn't exist.
Two failures, not one
While writing the regression test I found the reported crash is the louder of two problems:
nestingLevelmainAt 11 levels or more,
docxthrowsLevel cannot be greater than 9and the entire export is lost — matching the report, where the only feedback is a console error.At exactly 10 levels it doesn't throw, which is why this half is easy to miss.
docxpermits level 9, so the export "succeeds" and writes<w:ilvl w:val="9"/>— butnumbering.xmldefines no level 9. I confirmed this onmainby exporting a 10-deep list and comparing the two files:So that last item references an undefined numbering level and loses its bullet and indent.
The fix
Clamp the level to the deepest one the numbering config actually defines. Deeper items render at that level rather than crashing or dangling — the same way Word collapses nesting past its own 9-level limit (the limit
docxpoints at in its error message).The level count now lives in one shared constant used by both the numbering config and the mappings, so they can't drift apart if the config ever gains levels.
An alternative would be synthesising extra indentation for levels past 8 to keep deep nesting visually distinct. I left that out deliberately: it would fight the indent defined on the numbering level itself, and Word doesn't do it either. Happy to add it if you'd prefer that behaviour.
Testing
Added
should clamp list nesting deeper than DOCX supportstodocxExporter.test.ts. It exports a 12-deep bullet list and asserts on the emittedw:ilvlsequence:Asserting the sequence rather than just "did not throw" covers both failures at once — the crash and the undefined-level case — and confirms all 12 items still make it into the document.
Verified in both directions: with only the two source files reverted (test kept), the new test fails with the upstream
Level cannot be greater than 9, while the other five tests still pass, so nothing is masking the result. With the fix, all 6 pass.No snapshots changed, which is the intended outcome — lists within 9 levels are byte-for-byte unaffected.
Summary by CodeRabbit
Bug Fixes
Tests