Skip to content

Commit 24c8473

Browse files
fix(converter): avoid raw field ends in non-tracked wrappers
1 parent 4e9c9ca commit 24c8473

2 files changed

Lines changed: 58 additions & 2 deletions

File tree

packages/super-editor/src/editors/v1/core/super-converter/field-references/preProcessNodesForFldChar.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ export const preProcessNodesForFldChar = (nodes = [], docx) => {
228228
// A field from this level or higher ended in the children.
229229
const shouldPreserveRaw = childResult.unpairedEndPreserveRaw || isTrackChangeElement(node);
230230
if (collectedNodesStack.length === 0) {
231-
// Preserve the original subtree; child processing may have stripped the fldChar end marker.
232-
processedNodes.push(rawNode);
231+
// Track-change wrappers need the original field boundary; ordinary wrappers can keep processed children.
232+
processedNodes.push(shouldPreserveRaw ? rawNode : node);
233233
unpairedEnd = true;
234234
if (shouldPreserveRaw) unpairedEndPreserveRaw = true;
235235
return;

packages/super-editor/src/editors/v1/core/super-converter/field-references/preProcessNodesForFldChar.test.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,62 @@ describe('preProcessNodesForFldChar', () => {
303303
]);
304304
});
305305

306+
it('processes known fields that end inside nested non-tracked wrappers', () => {
307+
const nodes = [
308+
{ name: 'w:r', elements: [{ name: 'w:fldChar', attributes: { 'w:fldCharType': 'begin' } }] },
309+
{
310+
name: 'w:r',
311+
elements: [{ name: 'w:instrText', elements: [{ type: 'text', text: 'HYPERLINK "http://example.com"' }] }],
312+
},
313+
{ name: 'w:r', elements: [{ name: 'w:fldChar', attributes: { 'w:fldCharType': 'separate' } }] },
314+
{
315+
name: 'w:p',
316+
elements: [
317+
{
318+
name: 'w:sdt',
319+
elements: [
320+
{
321+
name: 'w:sdtContent',
322+
elements: [
323+
{ name: 'w:r', elements: [{ name: 'w:t', elements: [{ type: 'text', text: 'link text' }] }] },
324+
{ name: 'w:r', elements: [{ name: 'w:fldChar', attributes: { 'w:fldCharType': 'end' } }] },
325+
],
326+
},
327+
],
328+
},
329+
],
330+
},
331+
];
332+
333+
const { processedNodes } = preProcessNodesForFldChar(nodes, mockDocx);
334+
335+
expect(processedNodes).toEqual([
336+
{
337+
name: 'w:hyperlink',
338+
type: 'element',
339+
attributes: { 'r:id': 'rIdabc12345' },
340+
elements: [
341+
{
342+
name: 'w:p',
343+
elements: [
344+
{
345+
name: 'w:sdt',
346+
elements: [
347+
{
348+
name: 'w:sdtContent',
349+
elements: [
350+
{ name: 'w:r', elements: [{ name: 'w:t', elements: [{ type: 'text', text: 'link text' }] }] },
351+
],
352+
},
353+
],
354+
},
355+
],
356+
},
357+
],
358+
},
359+
]);
360+
});
361+
306362
it('preserves a tracked-deletion-wrapped field split across paragraphs without throwing', () => {
307363
const expectedNodes = [
308364
{

0 commit comments

Comments
 (0)