fix(super-editor): preserve generated line breaks in DOCX export#3630
Conversation
|
The Status: PASS Here's what I checked and why it holds:
One non-blocking note (not a spec violation): the split path replaces the original If you'd like the schema citations hardened, re-run with the |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
0a2be53 to
8a8d6f5
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8a8d6f5379
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
8a8d6f5 to
fa210d4
Compare
fa210d4 to
65bf8e3
Compare
65bf8e3 to
8f69e54
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65bf8e3f53
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
8f69e54 to
7f9c047
Compare
…3278)
Multi-line text in text-mode mutations stored newlines as a raw \n inside
one <w:t>, which Word collapses while SuperDoc renders a break. Convert
newlines to lineBreak nodes at creation, split any residual raw newline
into <w:t>/<w:br/> on export, and make the read model agree that a
lineBreak reads as \n so rewrite/search/query stay consistent. Serializes
as a Word-native <w:br/> (ECMA-376 17.3.3.1).
- buildTextWithTabs: normalize \n, \r\n, \r to lineBreak nodes, gated on
parent admission (probed per edit position) for text*-only parents
- materializeLineBreak: prefer lineBreak over hardBreak (soft, not page)
- getTextNodeForExport: split residual raw newline into <w:t>/<w:br/>
- del-translator: rename every <w:t> in a split run to <w:delText>
- lineBreak.leafText = '\n' so textBetweenWithTabs / charOffsetToDocPos /
text-offset-resolver read a break as \n; idempotent rewrite no longer
duplicates it, a rewrite to single-line text removes it
- SearchIndex honors leafText, and a single hit spanning text+lineBreak+
text coalesces to one contiguous range so query.match('Alpha\nBeta')
works (block separators still split; D5 guard intact)
- list paragraph beforeinput removes the placeholder break when text is
typed; visible text models skip tracked-deleted leaf nodes
7f9c047 to
a58352c
Compare
… (SD-3278)
Typing into a list item that holds only a placeholder break dropped the
caret before the first inserted character, so subsequent native
keystrokes prepended instead of appended ("abcdef" landed as "bcdefa").
Move the selection past the inserted text after the delete+insert.
…s (SD-3278) Coalesce adjacent search segments only when they are both offset-contiguous (same hit) and document-adjacent (segment.docFrom === current.to). This merges text + lineBreak + text within one run into a single range without bridging a skipped/tracked-deleted leaf or a run boundary, so the downstream D5 contiguity guard still rejects genuinely separate edits.
The span-rewrite path got the same parentAllowsLineBreak probe as the rewrite/insert paths but had no newline test, though its comment claimed coverage. Add two cases: a single '\n' in a normal parent mints one lineBreak (no hardBreak, no raw newline text node), and the same into a text*-only total-page-number falls back to literal text with no lineBreak.
Fixes SD-3278.
Generated multiline text could look correct in SuperDoc but export as raw newlines inside
<w:t>, which Word and LibreOffice do not treat as manual line breaks.This change:
\n/\r\n/\rtext into soft line break nodes<w:br/>lineBreakedits as soft breaks, not page breaks<w:delText>when runs are split around breaksThis also updates the read-side text model for
lineBreaknodes. The export fix now creates reallineBreaknodes instead of raw\ntext, so search/query/rewrite paths must read those nodes back as\n. Without that,query.match('Alpha\nBeta')and idempotent rewrites over generated multiline text would regress. That is why this PR also touches the search index, the doc-api text resolver, and the rewrite diff/offset accounting.Follow-ups are tracked separately for import-side normalization and tracked inserted breaks inside
<w:ins>.