Why track changes matters
Track changes records every insertion, deletion, and formatting change in a document, attributing each to an author with a timestamp. Legal teams use it to redline contracts. Compliance teams use it for audit trails. Editorial teams use it for manuscript review.
Any DOCX editor that handles professional workflows needs to parse, render, and serialize OOXML revision marks. This post explains how that works under the hood in docx-js-editor.
How OOXML stores revisions
In the OOXML spec, tracked changes are stored as markup within the document XML. When a user inserts text with tracking enabled, Word wraps the new content in a <w:ins> element:
<w:p>
<w:r>
<w:t>The contract value is </w:t>
</w:r>
<w:ins w:id="1" w:author="Jane" w:date="2026-03-10T14:30:00Z">
<w:r>
<w:rPr>
<w:color w:val="FF0000"/>
</w:rPr>
<w:t>$50,000</w:t>
</w:r>
</w:ins>
</w:p>Deletions use <w:del>:
<w:del w:id="2" w:author="Jane" w:date="2026-03-10T14:32:00Z">
<w:r>
<w:delText>$40,000</w:delText>
</w:r>
</w:del>Each revision carries metadata: a unique ID, the author's name, and a timestamp.
How docx-js-editor implements it
docx-js-editor parses w:ins and w:del elements from the document XML and maps them to ProseMirror marks via TrackedChangeExtensions:
- Insertions —
TrackedInsertionMarkrenders with a green underline, carriesrevisionId,author,date - Deletions —
TrackedDeletionMarkrenders with red strikethrough, same metadata
Suggesting mode
When mode="suggesting" is set, the editor intercepts edits at the DOM beforeinput level:
- Text insertions are wrapped with insertion marks automatically
- Text deletions don't remove content — they mark it with deletion marks instead
- Consecutive edits by the same author are grouped into a single revision
This is the same behavior as Word's "Track Changes" toggle.
Accepting and rejecting changes
The editor exposes acceptChange(from, to) and rejectChange(from, to) commands:
- Accept — insertion text stays (mark removed), deletion text is deleted
- Reject — insertion text is deleted, deletion text stays (mark removed)
The comments sidebar shows accept/reject buttons when a tracked change card is expanded.
Enabling track changes in your React app
import { DocxEditor } from "@eigenpal/docx-js-editor";
function ContractEditor({ buffer }: { buffer: ArrayBuffer }) {
return (
<DocxEditor
documentBuffer={buffer}
mode="suggesting"
author="Current User"
onSave={(blob) => {
// Save the document with revision marks intact
downloadBlob(blob, "contract-redlined.docx");
}}
/>
);
}Setting mode="suggesting" enables track changes — every edit the user makes is wrapped in revision markup. The author prop determines whose name appears on each revision. You can switch between "editing" (direct edits), "suggesting" (tracked changes), and "viewing" (read-only) modes.
Rendering revision marks
The visual rendering of tracked changes:
| Change type | Visual indicator | Color |
|---|---|---|
| Insertion | Underline | Green |
| Deletion | Strikethrough | Red |
Preserving revisions on export
When the user saves the document, the revision markup is serialized back to OOXML:
<w:ins>elements for insertions<w:del>elements with<w:delText>for deletions<w:rPrChange>for formatting changes- Author, date, and revision ID metadata
A document redlined in Word can be loaded into the editor with all revisions intact, and vice versa.
Use cases
Legal contract review
Law firms use track changes to negotiate contract terms. Both parties can see exactly what was added, removed, or modified. The redlined document serves as a record of the negotiation.
Regulatory compliance
Financial documents go through multiple review stages. Track changes provides an audit trail showing who changed what and when.
Editorial workflows
Publishing teams use track changes for manuscript editing. Authors can see every suggestion from their editor and choose to accept or reject each one.
Next steps
- Learn about document comments for threaded discussions
- Follow the React integration tutorial
- Try the live demo