Compare and apply tracked changes
Compare two documents, apply the result as a reviewable tracked change, and check what document shapes are supported before you rely on it.
Document comparison turns two versions of a document into a reviewable tracked change, instead of asking a person to spot the difference by eye. The workflow is diff.capture on the target, diff.compare against the base, then diff.apply with changeMode: 'tracked'. The resulting change goes through the same review API as an authored tracked change.
Not every document shape is eligible for a tracked apply today. Read applyEligibility before apply and the supported-case matrix before relying on this workflow for a document you have not already checked.
Compare two documents
Capture the target document's snapshot, then compare it against the currently open base document:
const targetSnapshot = await targetDoc.diff.capture();
const diff = await baseDoc.diff.compare({ targetSnapshot });
console.log(diff.summary.changedComponents);
// e.g. ['body']diff.summary reports which components changed (body, comments, styles, numbering, headerFooters, parts) without exposing the underlying comparison mechanics. diff.payload is opaque and engine-owned; do not inspect or persist it directly. See the diff.compare reference for the full result shape.
Read applyEligibility before apply
diff.applyEligibility reports, per change mode, whether the diff is a candidate for apply or already known to be blocked, before you call apply at all:
const trackedEligibility = diff.applyEligibility?.tracked;
if (trackedEligibility?.status !== 'candidate') {
throw new Error(`Tracked apply is blocked: ${JSON.stringify(trackedEligibility?.blockers ?? [])}`);
}
const result = await baseDoc.diff.apply({ diff, changeMode: 'tracked' });A blocker names the affected families and a stable code (for example structural-paragraph-unsupported or header-footer-tracked-lifecycle-unsupported). diff.apply enforces the same boundary at apply time: an unsupported family fails the whole call closed, with no partial output and no mutation, rather than silently applying a broader replacement than requested. See the diff.apply reference for every documented family and blocker code.
Review and decide
A comparison-generated change is reviewed and decided exactly like an authored one. Follow List and inspect changes and Accept or reject one change — the same trackChanges.list(), trackChanges.get(), and trackChanges.decide() operations apply regardless of whether the change came from a rewrite or a comparison.
Supported-case matrix
This matrix states current, version-qualified support; each row is checked against this version's actual behavior, not a completed feature's original intent.
| Shape | Current behavior | Owning issue |
|---|---|---|
| Localized, repeated, or separated body-text changes | Supported in direct and tracked modes. Tracked replacements retain independent comparison-hunk review groups. | SD-4953, SD-5189 |
| Body run-formatting changes | Supported in direct and tracked modes for verified run-formatting cases; unsupported surrounding structures still fail closed. | SD-5130 |
| Tables | Supported in verified direct and tracked cases; eligibility remains authoritative for the exact table shape. | SD-5130 |
| Header/footer in-place content edits | Supported in direct and tracked modes. | SD-3647 |
| Header/footer slot repointing or topology changes | Supported in direct mode. Tracked mode remains unsupported and fails closed. | SD-3647 |
| Existing footnote/endnote content | Supported in direct and tracked modes. | SD-5227 |
| New or removed footnote/endnote parts and references | Supported in verified exact-lifecycle cases in both modes. Ambiguous or mixed reference ownership fails closed. | SD-5227 |
| Pre-existing pending revisions in the base or target | Supported in both modes when the target revision set can be reconciled exactly; ambiguous replay fails closed. | SD-5130 |
| Inline images and drawings | Text beside a retained drawing and verified exact image replay are supported. Changed carriers, relationships, media, or opaque sidecars remain eligibility-gated and can fail closed. | SD-5130, SD-5271 |
| Fields and cross-references | Verified simple- and complex-field insertion/removal cases are supported. Incomplete, mixed, or changed retained carriers fail closed. | SD-5130, SD-5216 |
| First comment on a document | Lossless plain-text creation is supported in both modes, including initials. Rich or otherwise lossy first-comment creation fails closed. | SD-5130 |
| Content controls (SDT) | Unsupported: an SDT in the body currently fails the body family closed, including edits elsewhere in that body. | SD-5219 |
This snapshot was verified against @superdoc/sdk 2.16.0-next.8 and @superdoc/docx-engine
0.18.0-next.7. Its source work is tracked by SD-4953 (localized tracked comparison), SD-5130 (reporter
pair eligibility), and SD-3647 (header/footer coverage), with the narrower follow-ups named in the table. Re-run the
Document API comparison suites and update this matrix whenever diff eligibility, replay behavior, or review-group
contracts change. For a runnable version of the workflow above, see the document comparison
example.