<bmx-document-compare>
A redline of two versions of a document - Word (.docx), PDF, HTML, Markdown or plain text, in any mix - side by side or inline, with every change listed and decided.
18 properties · 3 events · 14 methods · 6 parts
Example
Open your own .docx, PDF, HTML, Markdown or text files to compare them instead. Alt+Down and Alt+Up move between changes.
Show markup
<bmx-document-compare id="ex-dc" allow-open original-label="Our NDA (v3, sent 2 Oct)" revised-label="Counterparty mark-up (9 Oct)"></bmx-document-compare>
<p class="note" id="ex-dc-out" role="status" style="margin: 12px 0 0">Open your own .docx, PDF, HTML, Markdown or text files to compare them instead. Alt+Down and Alt+Up move between changes.</p>
<script type="module">
await customElements.whenDefined('bmx-document-compare');
const cmp = document.getElementById('ex-dc');
const out = document.getElementById('ex-dc-out');
const ours = `
<h1>Mutual Non-Disclosure Agreement</h1>
<p>This Agreement is made on <b>2 October 2026</b> between Binarymission Technologies Limited (the "Company") and the Recipient.</p>
<h2>1. Confidential Information</h2>
<p>"Confidential Information" means any information disclosed by either party, in any form, that is marked as confidential or that a reasonable person would understand to be confidential.</p>
<h2>2. Obligations</h2>
<p>The Recipient shall keep the Confidential Information secret and shall not disclose it to any third party without the prior written consent of the Company.</p>
<p>The Recipient shall use the Confidential Information solely for the purpose of evaluating a possible business relationship between the parties.</p>
<h2>3. Exceptions</h2>
<ul>
<li>information that is or becomes public other than through a breach of this Agreement;</li>
<li>information already known to the Recipient before disclosure;</li>
<li>information required to be disclosed by law or by a court.</li>
</ul>
<h2>4. Term</h2>
<p>The obligations in this Agreement continue for <b>five (5) years</b> from the date of disclosure.</p>
<h2>5. Return of Information</h2>
<p>On request, the Recipient shall promptly return or destroy all Confidential Information and confirm this in writing.</p>
<h2>6. Governing Law</h2>
<p>This Agreement is governed by the laws of England and Wales, and the courts of England have exclusive jurisdiction.</p>`;
const theirs = `
<h1>Mutual Non-Disclosure Agreement</h1>
<p>This Agreement is made on <b>9 October 2026</b> between Binarymission Technologies Limited (the "Company") and the Recipient.</p>
<h2>1. Confidential Information</h2>
<p>"Confidential Information" means any information disclosed by either party, in any form, that is marked as confidential.</p>
<h2>2. Obligations</h2>
<p>The Recipient shall keep the Confidential Information secret and shall not disclose it to any third party without the prior written consent of the Company, which shall not be unreasonably withheld.</p>
<p>The Recipient shall use the Confidential Information <i>solely</i> for the purpose of evaluating a possible business relationship between the parties.</p>
<h2>3. Exceptions</h2>
<ul>
<li>information that is or becomes public other than through a breach of this Agreement;</li>
<li>information already known to the Recipient before disclosure;</li>
<li>information independently developed by the Recipient;</li>
<li>information required to be disclosed by law or by a court.</li>
</ul>
<h2>4. Term</h2>
<p>The obligations in this Agreement continue for <b>two (2) years</b> from the date of disclosure.</p>
<h2>5. Governing Law</h2>
<p>This Agreement is governed by the laws of England and Wales, and the courts of England have exclusive jurisdiction.</p>
<h2>6. Return of Information</h2>
<p>On request, the Recipient shall promptly return or destroy all Confidential Information and confirm this in writing.</p>
<h3>Notices</h3>
<p>Notices under this Agreement must be in writing and sent by email to the addresses each party gives.</p>`;
cmp.original = ours;
cmp.revised = theirs;
cmp.addEventListener('bmxCompare', e => (out.textContent = `${e.detail.changes} changes found. Accept or reject them in the list, then export the redline or the clean copy.`));
cmp.addEventListener('bmxDecision', e => {
const decided = Object.keys(e.detail.decisions).length;
out.textContent = `${decided} change${decided === 1 ? '' : 's'} decided. The page would save event.detail.decisions.`;
});
</script>
<bmx-document-compare id="cmp" allow-open original-label="Our draft" revised-label="Their mark-up"></bmx-document-compare>
<script>
await cmp.load('original', ourDocxFile); // a File, Blob, bytes, text or HTML
await cmp.load('revised', theirPdfBytes, { format: 'pdf' });
cmp.addEventListener('bmxDecision', e => save(e.detail.decisions));
const redline = await cmp.getRedlineHtml(); // to send or file
</script>
Paragraphs are lined up first (unchanged ones anchoring the match, so a long agreement lines up even when clauses have moved), then compared word by word: insertions, deletions and replacements, paragraphs that moved, and formatting that changed (bold, italic, a paragraph that became a heading). Case, spacing and typographic quotes can be ignored. Unchanged stretches fold away. Each change can be accepted or rejected; the clean copy follows the decisions. Exports: the redline as HTML, the clean copy as HTML or text, and a change report as CSV. Files are read in the page - nothing is uploaded anywhere.
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
allowOpen |
allow-open |
boolean |
false |
Shows Open buttons and drop areas for the two files. |
context |
context |
number |
2 |
Unchanged paragraphs shown around each change; the rest fold away. -1 shows everything. |
decisions |
property only | Record<string, BmxCompareDecision> |
{} |
The decisions by change id. Two-way. |
detectMoves |
detect-moves |
boolean |
true |
Find paragraphs that moved. |
format |
format |
'auto' | 'text' | 'markdown' | 'html' |
'auto' |
How original and revised text is read. auto: HTML when it starts with a tag, otherwise text. |
ignoreCase |
ignore-case |
boolean |
false |
Treat upper and lower case as the same. |
ignoreFormatting |
ignore-formatting |
boolean |
false |
Do not report formatting changes. |
ignoreWhitespace |
ignore-whitespace |
boolean |
true |
Treat runs of spaces as one. |
label |
label |
string |
— | The comparison's accessible name. |
original |
original |
string | BmxCompareDocument |
— | The original document: text, HTML or Markdown (see format), or a document object (or JSON). Files and bytes go through load(). |
originalLabel |
original-label |
string |
— | The original's name. Default: its file name, or "Original". |
panel |
panel |
'changes' | 'none' |
'changes' |
The list of changes beside the comparison. |
pending |
pending |
BmxComparePending |
'accept' |
In the clean copy, what happens to changes nobody has decided: kept (accept) or left out (reject). |
review |
review |
boolean |
true |
Lets the reader accept and reject changes. |
revised |
revised |
string | BmxCompareDocument |
— | The revised document, as original. |
revisedLabel |
revised-label |
string |
— | The revised document's name. Default: its file name, or "Revised". |
strings |
strings |
Partial<BmxDocumentCompareStrings> | string |
— | Words to show instead of the English ones, as an object or JSON. |
view |
view |
BmxCompareView |
'side-by-side' |
Side by side or inline. Narrow screens show inline. Two-way. |
Events
| Event | Detail | Description |
|---|---|---|
bmxCompare |
BmxCompareDoneDetail |
Fired after each comparison, with the counts. |
bmxDecision |
BmxCompareDecisionDetail |
Fired when changes are accepted or rejected (or a decision is cleared). |
bmxError |
BmxCompareErrorDetail |
Fired when a file cannot be read. |
Methods
| Method | Signature | Description |
|---|---|---|
accept |
accept(id: string | "all") => Promise<void> |
Accepts a change, or every change with all. |
expandAll |
expandAll() => Promise<void> |
Shows every unchanged paragraph. |
getChanges |
getChanges() => Promise<BmxCompareChange[]> |
The changes, with their ids, kinds, places and text. |
getChangesCsv |
getChangesCsv() => Promise<string> |
The change report as CSV. |
getMergedHtml |
getMergedHtml() => Promise<string> |
The clean copy, as the decisions leave it, as a standalone HTML page. |
getMergedText |
getMergedText() => Promise<string> |
The clean copy, as the decisions leave it, as text. |
getRedlineHtml |
getRedlineHtml(options?: BmxCompareRedlineOptions) => Promise<string> |
The redline as a standalone HTML page: insertions, deletions, moves and formatting marked; decided changes shown as decided. |
getResult |
getResult() => Promise<BmxCompareResult | null> |
The comparison, or null until both documents are loaded. |
goTo |
goTo(id: string) => Promise<boolean> |
Moves to a change, showing and scrolling to it. |
load |
load(side: BmxCompareSide, input: BmxCompareInput, options?: { format?: BmxCompareFormat; name?: string; password?: string; }) => Promise<BmxCompareDocument> |
Reads a file or text into one side: Word (.docx), PDF, HTML, Markdown or text, by format or the file's name and contents. |
next |
next() => Promise<void> |
Moves to the next change. |
previous |
previous() => Promise<void> |
Moves to the previous change. |
reject |
reject(id: string | "all") => Promise<void> |
Rejects a change, or every change with all. |
undecide |
undecide(id: string | "all") => Promise<void> |
Clears a decision, or every decision with all. |
CSS shadow parts
| Part | Description |
|---|---|
changes |
The list of changes. |
delete |
Deleted text. |
document |
The comparison. |
insert |
Inserted text. |
row |
A paragraph of the comparison; also row-changed. |
toolbar |
The row of documents, view, options, navigation and export. |
CSS custom properties
| Property | Description |
|---|---|
--bmx-document-compare-delete |
The colour of deleted text. |
--bmx-document-compare-delete-background |
The background of deleted text. |
--bmx-document-compare-font |
The font of the documents' text. |
--bmx-document-compare-insert |
The colour of inserted text. |
--bmx-document-compare-insert-background |
The background of inserted text. |
--bmx-document-compare-max-height |
The tallest the comparison grows before it scrolls. |
--bmx-document-compare-move |
The colour that marks moved paragraphs and formatting changes. |
--bmx-document-compare-panel-width |
The width of the list of changes. |