Replace as a tracked change
Record a tracked replacement with findMatches and replaceMatch in the editor, or with insertText and TrackMineOnly in the editing API.
In a browser host, find the text with editor.findMatches and replace one match with the replaceMatch command. In suggesting mode, the replacement is a tracked change as the editor's author. The selection and the scroll position do not move.
findMatches also returns matches in headers, footers, notes, and text boxes. Those matches have a scope. replaceMatch replaces text only in the story that the reader has open, and refuses the others, so the example keeps body matches: the ones without a scope.
import { useDocxEditor } from '@docx-editor.dev/react';
export function ProposeTerm({ from, to }: { from: string; to: string }) {
const editor = useDocxEditor();
const run = () => {
if (!editor || !editor.setEditingMode('suggesting').ok) return;
const match = editor.findMatches(from, { matchCase: true }).find((found) => !found.scope);
if (match) editor.exec({ type: 'replaceMatch', match, text: to });
};
return <button onClick={run}>Propose {to}</button>;
}<script setup lang="ts">
import { useDocxEditor } from '@docx-editor.dev/vue';
const props = defineProps<{ from: string; to: string }>();
const editor = useDocxEditor();
function run() {
const current = editor.value;
if (!current || !current.setEditingMode('suggesting').ok) return;
const match = current.findMatches(props.from, { matchCase: true }).find((found) => !found.scope);
if (match) current.exec({ type: 'replaceMatch', match, text: props.to });
}
</script>
<template>
<button @click="run">Propose {{ to }}</button>
</template>Suggesting mode needs an editor author. Without one, setEditingMode('suggesting') refuses. To replace every match in one undo step, run the replaceAllMatches command, { type: 'replaceAllMatches', query, text }, through the editor's exec.
Replace in a headless pipeline
In the editing API, set document.changeTrackingMode to 'TrackMineOnly', and then replace the found range with insertText(text, 'Replace').
import { DocxEditor } from '@docx-editor.dev/editor-api';
const runtime = await DocxEditor.createServer(bytes, { author: 'Review bot' });
await runtime.run(async (context) => {
context.document.changeTrackingMode = 'TrackMineOnly';
const found = context.document.body.search(from, { matchCase: true });
found.load('items');
await context.sync();
found.items[0]?.insertText(to, 'Replace');
await context.sync();
});
const saved = await runtime.save();
runtime.dispose();Both paths save the same w:del and w:ins structure, with the same author and date format. Never turn tracking off to make a refused tracked edit succeed.
Comment on found text
Find text in the open document and comment on it with useReview, or with Range.insertComment in a headless pipeline.
Propose an AI rewrite as tracked changes
Read a paragraph for your model, and propose the model text as the fewest tracked changes, with fields, equations, and locked controls kept whole.