Skip to content

Commit c80bbbe

Browse files
authored
fix: preserve source IDs when rewriting imported track-format changes (#2714)
1 parent 8407cda commit c80bbbe

17 files changed

Lines changed: 218 additions & 17 deletions

File tree

apps/docs/document-api/reference/_generated-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,5 +1016,5 @@
10161016
}
10171017
],
10181018
"marker": "{/* GENERATED FILE: DO NOT EDIT. Regenerate via `pnpm run docapi:sync`. */}",
1019-
"sourceHash": "4a3601ee0f28a73c712fbe06e8b4913a9ae882a71152f9f6e892ea51137fc5e8"
1019+
"sourceHash": "9f517507db3d5a45d0f2e6a22ec14f11de4b6d2f0a94c9b5ecef151ee64b795a"
10201020
}

apps/docs/document-api/reference/track-changes/get.mdx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Retrieve a single tracked change by ID.
2020

2121
## Expected result
2222

23-
Returns a TrackChangeInfo object with the change type, author, date, and affected content.
23+
Returns a TrackChangeInfo object with the change type, author, date, affected content, and source Word revision IDs when available.
2424

2525
## Input fields
2626

@@ -51,6 +51,10 @@ Returns a TrackChangeInfo object with the change type, author, date, and affecte
5151
| `excerpt` | string | no | |
5252
| `id` | string | yes | |
5353
| `type` | enum | yes | `"insert"`, `"delete"`, `"format"` |
54+
| `wordRevisionIds` | object | no | |
55+
| `wordRevisionIds.delete` | string | no | |
56+
| `wordRevisionIds.format` | string | no | |
57+
| `wordRevisionIds.insert` | string | no | |
5458

5559
### Example response
5660

@@ -62,9 +66,12 @@ Returns a TrackChangeInfo object with the change type, author, date, and affecte
6266
"kind": "entity"
6367
},
6468
"author": "Jane Doe",
65-
"authorEmail": "jane@example.com",
6669
"id": "id-001",
67-
"type": "insert"
70+
"type": "insert",
71+
"wordRevisionIds": {
72+
"delete": "example",
73+
"insert": "example"
74+
}
6875
}
6976
```
7077

@@ -127,6 +134,21 @@ Returns a TrackChangeInfo object with the change type, author, date, and affecte
127134
"delete",
128135
"format"
129136
]
137+
},
138+
"wordRevisionIds": {
139+
"additionalProperties": false,
140+
"properties": {
141+
"delete": {
142+
"type": "string"
143+
},
144+
"format": {
145+
"type": "string"
146+
},
147+
"insert": {
148+
"type": "string"
149+
}
150+
},
151+
"type": "object"
130152
}
131153
},
132154
"required": [

apps/docs/document-api/reference/track-changes/list.mdx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ List all tracked changes in the document.
2020

2121
## Expected result
2222

23-
Returns a TrackChangesListResult with an array of tracked change entries and total count.
23+
Returns a TrackChangesListResult with tracked change entries, total count, and source Word revision IDs when available.
2424

2525
## Input fields
2626

@@ -64,14 +64,17 @@ Returns a TrackChangesListResult with an array of tracked change entries and tot
6464
"kind": "entity"
6565
},
6666
"author": "Jane Doe",
67-
"authorEmail": "jane@example.com",
6867
"handle": {
6968
"ref": "handle:abc123",
7069
"refStability": "stable",
7170
"targetKind": "text"
7271
},
7372
"id": "id-001",
74-
"type": "insert"
73+
"type": "insert",
74+
"wordRevisionIds": {
75+
"delete": "example",
76+
"insert": "example"
77+
}
7578
}
7679
],
7780
"page": {
@@ -162,6 +165,21 @@ Returns a TrackChangesListResult with an array of tracked change entries and tot
162165
"delete",
163166
"format"
164167
]
168+
},
169+
"wordRevisionIds": {
170+
"additionalProperties": false,
171+
"properties": {
172+
"delete": {
173+
"type": "string"
174+
},
175+
"format": {
176+
"type": "string"
177+
},
178+
"insert": {
179+
"type": "string"
180+
}
181+
},
182+
"type": "object"
165183
}
166184
},
167185
"required": [

packages/document-api/src/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ List tracked changes in the document. Supports filtering by `type` and paginatio
711711
Retrieve full information for a single tracked change by its canonical ID. Throws `TARGET_NOT_FOUND` when the ID is invalid.
712712

713713
- **Input**: `TrackChangesGetInput` (`{ id }`)
714-
- **Output**: `TrackChangeInfo`
714+
- **Output**: `TrackChangeInfo` (includes `wordRevisionIds` when imported source OOXML revision IDs are available)
715715
- **Mutates**: No
716716
- **Idempotency**: idempotent
717717

packages/document-api/src/contract/operation-definitions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,7 +2214,8 @@ export const OPERATION_DEFINITIONS = {
22142214
'trackChanges.list': {
22152215
memberPath: 'trackChanges.list',
22162216
description: 'List all tracked changes in the document.',
2217-
expectedResult: 'Returns a TrackChangesListResult with an array of tracked change entries and total count.',
2217+
expectedResult:
2218+
'Returns a TrackChangesListResult with tracked change entries, total count, and source Word revision IDs when available.',
22182219
requiresDocumentContext: true,
22192220
metadata: readOperation({
22202221
idempotency: 'idempotent',
@@ -2228,7 +2229,8 @@ export const OPERATION_DEFINITIONS = {
22282229
'trackChanges.get': {
22292230
memberPath: 'trackChanges.get',
22302231
description: 'Retrieve a single tracked change by ID.',
2231-
expectedResult: 'Returns a TrackChangeInfo object with the change type, author, date, and affected content.',
2232+
expectedResult:
2233+
'Returns a TrackChangeInfo object with the change type, author, date, affected content, and source Word revision IDs when available.',
22322234
requiresDocumentContext: true,
22332235
metadata: readOperation({
22342236
idempotency: 'idempotent',

packages/document-api/src/contract/schemas.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,11 +1478,18 @@ const commentDomainItemSchema = discoveryItemSchema(
14781478

14791479
const commentsListResultSchema = discoveryResultSchema(commentDomainItemSchema);
14801480

1481+
const trackChangeWordRevisionIdsSchema = objectSchema({
1482+
insert: { type: 'string' },
1483+
delete: { type: 'string' },
1484+
format: { type: 'string' },
1485+
});
1486+
14811487
const trackChangeInfoSchema = objectSchema(
14821488
{
14831489
address: trackedChangeAddressSchema,
14841490
id: { type: 'string' },
14851491
type: { enum: ['insert', 'delete', 'format'] },
1492+
wordRevisionIds: trackChangeWordRevisionIdsSchema,
14861493
author: { type: 'string' },
14871494
authorEmail: { type: 'string' },
14881495
authorImage: { type: 'string' },
@@ -1496,6 +1503,7 @@ const trackChangeDomainItemSchema = discoveryItemSchema(
14961503
{
14971504
address: trackedChangeAddressSchema,
14981505
type: { enum: ['insert', 'delete', 'format'] },
1506+
wordRevisionIds: trackChangeWordRevisionIdsSchema,
14991507
author: { type: 'string' },
15001508
authorEmail: { type: 'string' },
15011509
authorImage: { type: 'string' },

packages/document-api/src/types/track-changes.types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@ import type { DiscoveryOutput } from './discovery.js';
33

44
export type TrackChangeType = 'insert' | 'delete' | 'format';
55

6+
export interface TrackChangeWordRevisionIds {
7+
insert?: string;
8+
delete?: string;
9+
format?: string;
10+
}
11+
612
export interface TrackChangeInfo {
713
address: TrackedChangeAddress;
814
/** Convenience alias for `address.entityId`. */
915
id: string;
1016
type: TrackChangeType;
17+
wordRevisionIds?: TrackChangeWordRevisionIds;
1118
author?: string;
1219
authorEmail?: string;
1320
authorImage?: string;
@@ -27,6 +34,7 @@ export interface TrackChangesListQuery {
2734
export interface TrackChangeDomain {
2835
address: TrackedChangeAddress;
2936
type: TrackChangeType;
37+
wordRevisionIds?: TrackChangeWordRevisionIds;
3038
author?: string;
3139
authorEmail?: string;
3240
authorImage?: string;

packages/super-editor/src/editors/v1/core/super-converter/v2/importer/markImporter.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export function handleStyleChangeMarksV2(rPrChange, currentMarks, params) {
114114
const attributes = rPrChange.attributes || {};
115115
const mappedAttributes = {
116116
id: attributes['w:id'],
117+
sourceId: attributes['w:id'],
117118
date: attributes['w:date'],
118119
author: attributes['w:author'],
119120
authorEmail: attributes['w:authorEmail'],
@@ -143,6 +144,7 @@ export function handleStyleChangeMarks(rPr, currentMarks) {
143144
const { attributes } = styleChangeMark;
144145
const mappedAttributes = {
145146
id: attributes['w:id'],
147+
sourceId: attributes['w:id'],
146148
date: attributes['w:date'],
147149
author: attributes['w:author'],
148150
authorEmail: attributes['w:authorEmail'],

packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/helpers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const createRunPropertiesChangeElement = (trackFormatMark) => {
3939
type: 'element',
4040
name: 'w:rPrChange',
4141
attributes: {
42-
'w:id': trackFormatMark.attrs?.id,
42+
'w:id': trackFormatMark.attrs?.sourceId || trackFormatMark.attrs?.id,
4343
'w:author': trackFormatMark.attrs?.author,
4444
'w:authorEmail': trackFormatMark.attrs?.authorEmail,
4545
'w:date': trackFormatMark.attrs?.date,

packages/super-editor/src/editors/v1/document-api-adapters/helpers/tracked-change-resolver.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ describe('groupTrackedChanges', () => {
6767

6868
it('groups marks by raw id', () => {
6969
vi.mocked(getTrackChanges).mockReturnValue([
70-
{ ...makeTrackMark(TrackInsertMarkName, 'tc-1'), from: 1, to: 5 },
71-
{ ...makeTrackMark(TrackDeleteMarkName, 'tc-1'), from: 5, to: 10 },
70+
{ ...makeTrackMark(TrackInsertMarkName, 'tc-1', { sourceId: '11' }), from: 1, to: 5 },
71+
{ ...makeTrackMark(TrackDeleteMarkName, 'tc-1', { sourceId: '10' }), from: 5, to: 10 },
7272
] as never);
7373

7474
const editor = makeEditor();
@@ -80,6 +80,7 @@ describe('groupTrackedChanges', () => {
8080
expect(grouped[0]?.to).toBe(10);
8181
expect(grouped[0]?.hasInsert).toBe(true);
8282
expect(grouped[0]?.hasDelete).toBe(true);
83+
expect(grouped[0]?.wordRevisionIds).toEqual({ insert: '11', delete: '10' });
8384
});
8485

8586
it('keeps separate entries for different raw ids', () => {
@@ -137,13 +138,14 @@ describe('groupTrackedChanges', () => {
137138

138139
it('detects format marks', () => {
139140
vi.mocked(getTrackChanges).mockReturnValue([
140-
{ ...makeTrackMark(TrackFormatMarkName, 'tc-1'), from: 1, to: 5 },
141+
{ ...makeTrackMark(TrackFormatMarkName, 'tc-1', { sourceId: '22' }), from: 1, to: 5 },
141142
] as never);
142143

143144
const grouped = groupTrackedChanges(makeEditor());
144145
expect(grouped[0]?.hasFormat).toBe(true);
145146
expect(grouped[0]?.hasInsert).toBe(false);
146147
expect(grouped[0]?.hasDelete).toBe(false);
148+
expect(grouped[0]?.wordRevisionIds).toEqual({ format: '22' });
147149
});
148150

149151
it('sorts results by from position', () => {

0 commit comments

Comments
 (0)