fix(tracked-changes): preserve format on export and import#2362
fix(tracked-changes): preserve format on export and import#2362
Conversation
palmer-cl
commented
Mar 11, 2026
- Preserve formatting changes on export
- Add tests for multiple types of format preservation
|
Status: FAIL The core structural changes look correct — wrapping 1.
// helpers.js
'w:authorEmail': trackStyleMark.attrs.authorEmail,
// r-translator.test.js
expect(runPropertyChange?.attributes).toMatchObject({
'w:authorEmail': 'reviewer@example.com',
...
});Per §17.13.5.31, 2.
expect(sizeNode?.attributes?.['w:val']).toBe(24); // numberBut the input fixture in { name: 'w:sz', attributes: { 'w:val': '24' } }
|
caio-pizzol
left a comment
There was a problem hiding this comment.
@colep approach is clean, no major issues.
two small DX suggestions inline — nothing blocking.
on tests: would be good to add coverage for (1) a text node with only a trackFormat mark and no other formatting, and (2) a run that already has a w:rPrChange surviving through replaceRunProps. both cover branches that would silently break without a test catching it. left inline comments.
packages/super-editor/src/core/super-converter/v3/handlers/helpers.js
Outdated
Show resolved
Hide resolved
| if (runPropertiesNode) { | ||
| if (!Array.isArray(runPropertiesNode.elements)) runPropertiesNode.elements = []; | ||
|
|
||
| const existingChangeKeys = new Set( |
There was a problem hiding this comment.
the dedup logic here can't actually trigger — the template never contains w:rPrChange nodes, so the Set is always empty. could just append directly without the key check.
There was a problem hiding this comment.
Would the preserved changes ever have duplicates we need to account for? or safe to just put them all in?
caio-pizzol
left a comment
There was a problem hiding this comment.
@palmer-cl pipeline switch and expanded comment look good.
two small things still open — left inline comments. no correctness issues, good to go once those are sorted.
| if (runPropertiesNode) { | ||
| if (!Array.isArray(runPropertiesNode.elements)) runPropertiesNode.elements = []; | ||
|
|
||
| const existingChangeKeys = new Set( |
There was a problem hiding this comment.
to answer your question: no, duplicates can't happen. the template never contains w:rPrChange nodes, and the spec only allows one per w:rPr. safe to just push directly without the Set.
| return { type, attrs: mark?.attrs || {} }; | ||
| }; | ||
|
|
||
| const toRunPropertyElements = (marks = []) => |
There was a problem hiding this comment.
the IIFE wrapper doesn't do anything here — a regular block body works the same.
| const toRunPropertyElements = (marks = []) => | |
| const toRunPropertyElements = (marks = []) => { | |
| const normalizedMarks = marks.map((mark) => normalizeMark(mark)).filter(Boolean); | |
| const runProperties = decodeRPrFromMarks(normalizedMarks); | |
| const rPrNode = wRPrNodeTranslator.decode({ node: { attrs: { runProperties } } }); | |
| return Array.isArray(rPrNode?.elements) ? rPrNode.elements : []; | |
| }; |
| const rPrNode = wRPrNodeTranslator.decode({ node: { attrs: { runProperties: combinedRunProperties } } }); | ||
| const hasRunProperties = Array.isArray(rPrNode?.elements) && rPrNode.elements.length > 0; | ||
| const hasStyleChange = Boolean(trackedStyleChange); | ||
| const resolvedRunProperties = |
There was a problem hiding this comment.
the editor side of tracked formatting has good test coverage (display, reject, revert), but the export/import side — which is what this PR fixes — is thin. the r-translator test always pairs trackFormat with bold, so the branch where tracked formatting is the only thing on the run never runs. also createTrackStyleMark has no direct tests (both paths: passthrough of existing XML nodes and building from marks). worth adding at least the standalone trackFormat case and a direct test for createTrackStyleMark?