@createiq/htmldiff 1.2.0-beta.0 → 1.2.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -127,45 +127,72 @@ This property defines relative size of the match to be considered as orphan, fro
127
127
 
128
128
  Returns the diff from an HtmlDiff instance.
129
129
 
130
- ### HtmlDiff.executeThreeWay(v1, v2, v3, options?)
130
+ ### HtmlDiff.executeThreeWay(genesis, cpLatest, meCurrent, options?)
131
131
 
132
132
  Three-way HTML diff for back-and-forth negotiation scenarios. Given:
133
133
 
134
- - `v1` — the version you last sent
135
- - `v2` — the version the counterparty sent back
136
- - `v3` — your current draft
134
+ - `genesis` — the shared common ancestor (the version both parties started from)
135
+ - `cpLatest` — the counterparty's current published position
136
+ - `meCurrent` — your current draft
137
137
 
138
- `executeThreeWay` produces a single attributed HTML output where the counterparty's changes (V1→V2) and your changes
139
- (V2→V3) are distinguished by `data-author` and class:
138
+ `executeThreeWay` compares both `cpLatest` and `meCurrent` against `genesis` and attributes each side's accumulated
139
+ changes independently:
140
140
 
141
141
  - Counterparty insertions / deletions: `<ins class='diffins cp' data-author='cp'>` / `<del class='diffdel cp' ...>`
142
142
  - Your insertions / deletions: `<ins class='diffins me' data-author='me'>` / `<del class='diffdel me' ...>`
143
- - Your rejections of counterparty insertions (you deleted text they added): `<del class='diffdel me rejects-cp' data-author='me' data-rejects='cp'>`
143
+ - When both authors made the same change, the result is treated as **settled** and emitted plain (no markup).
144
+ - When both authors deleted the same content, the deletion is settled and silenced.
144
145
 
145
146
  ```ts
146
147
  import HtmlDiff from '@createiq/htmldiff'
147
148
 
148
- const v1 = '<p>The fee is five percent.</p>'
149
- const v2 = '<p>The interest fee is five and a half percent.</p>'
150
- const v3 = '<p>The interest fee is five percent.</p>'
149
+ const genesis = '<p>The quick brown fox jumps over the lazy dog</p>'
150
+ const cpLatest = '<p>The fast brown fox leaps</p>'
151
+ const meCurrent = '<p>The quick brown antelope leaps over the lazy pig</p>'
151
152
 
152
- const merged = HtmlDiff.executeThreeWay(v1, v2, v3)
153
- // Counterparty added "interest" — kept by you.
154
- // Counterparty changed "five" "five and a half" — you rejected.
153
+ const merged = HtmlDiff.executeThreeWay(genesis, cpLatest, meCurrent)
154
+ // CP changed quick→fast and removed "over the lazy dog" — attributed to cp.
155
+ // You changed foxantelope and added "pig"attributed to me.
156
+ // "jumps→leaps" was made by CP and kept by you — settled, emitted plain.
155
157
  ```
156
158
 
157
159
  Tables (including multi-table documents) and row/column structural changes are supported with the same author
158
- attribution at row, cell, and content granularity.
160
+ attribution at row, cell, and content granularity. Settled changes (both sides agree) propagate through every
161
+ granularity — a table both sides added unchanged emits plain; a row only one side added carries that author's
162
+ attribution.
163
+
164
+ #### Picking a genesis
165
+
166
+ The right `genesis` depends on the negotiation:
167
+
168
+ - **Single shared starting point** (e.g. `prefillReceiverAnswers=true`): use the V1.0 version that both parties
169
+ started from.
170
+ - **Per-user starting points** (e.g. `prefillReceiverAnswers=false`): each party has their own genesis (their
171
+ `initialAnswers` — preset state or schema defaults). The diff from each user's perspective uses their own genesis,
172
+ and the two views may differ.
173
+
174
+ The library doesn't pick the genesis itself — it consumes whatever the caller supplies. CreateiQ's frontend does the
175
+ per-user selection.
159
176
 
160
177
  #### Options
161
178
 
162
- `executeThreeWay` accepts the same per-instance options as `HtmlDiff` (`repeatingWordsAccuracy`,
163
- `ignoreWhitespaceDifferences`, `orphanMatchThreshold`, `blockExpressions`). They flow into both internal pair-wise
164
- analyses identically.
179
+ `executeThreeWay` accepts the same options as `HtmlDiff` (`repeatingWordsAccuracy`, `ignoreWhitespaceDifferences`,
180
+ `orphanMatchThreshold`, `blockExpressions`). They flow into both internal pair-wise analyses identically.
165
181
 
166
182
  `useProjections` controls structural-tag normalisation. When undefined (default), the decision is the conjunction of
167
- both pair-wise heuristics — projection only activates when both V1V2 and V2V3 would benefit from it. Pass an
168
- explicit boolean to override.
183
+ both pair-wise heuristics — projection only activates when both `genesiscpLatest` and `genesismeCurrent` would
184
+ benefit from it. Pass an explicit boolean to override.
185
+
186
+ #### Known limitations
187
+
188
+ - **Partial-adoption visibility.** When one author deletes a phrase but the other keeps part of it (e.g. CP deletes
189
+ "over the lazy dog" but Me keeps "over the lazy" and only changes "dog"→"pig"), the algorithm reports the deletion
190
+ at the token level — each kept token appears as a pending `<del cp>` while the one changed token appears separately.
191
+ The reader sees an honest token-level picture rather than a misleading phrase-level summary.
192
+ - **Boundary-based settled-insertion detection.** Two authors inserting the same content but at slightly different
193
+ boundaries (because their respective diffs decomposed the surrounding change differently) may be reported as two
194
+ separate one-sided insertions rather than one settled insertion. Identical content at identical boundaries does
195
+ detect as settled.
169
196
 
170
197
  ## Contributing
171
198