@createiq/htmldiff 1.1.0 → 1.2.0-beta.1
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/.claude/settings.local.json +15 -0
- package/README.md +67 -0
- package/dist/HtmlDiff.cjs +1192 -456
- package/dist/HtmlDiff.cjs.map +1 -1
- package/dist/HtmlDiff.d.cts +160 -7
- package/dist/HtmlDiff.d.mts +159 -7
- package/dist/HtmlDiff.mjs +1192 -456
- package/dist/HtmlDiff.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Alignment.ts +349 -0
- package/src/HtmlDiff.ts +343 -33
- package/src/HtmlScanner.ts +200 -0
- package/src/TableDiff.ts +67 -522
- package/src/ThreeWayDiff.ts +269 -0
- package/src/ThreeWayTable.ts +625 -0
- package/src/Utils.ts +34 -2
- package/test/HtmlDiff.analyze.spec.ts +152 -0
- package/test/HtmlDiff.tables.spec.ts +43 -19
- package/test/HtmlDiff.threeWay.spec.ts +173 -0
- package/test/HtmlDiff.threeWay.tables.spec.ts +301 -0
- package/test/TableDiff.bench.ts +39 -0
- package/test/Utils.spec.ts +48 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(diff -u test/input1.html test/input2.html)",
|
|
5
|
+
"Bash(npm test -- test/Bug.spec.tsx)",
|
|
6
|
+
"Bash(timeout 30s npm run test:ci -- test/Bug.spec.tsx)",
|
|
7
|
+
"Bash(npm run build)",
|
|
8
|
+
"Bash(timeout 10s npm run test:ci -- test/Bug.spec.tsx)",
|
|
9
|
+
"Bash(npm run lint)",
|
|
10
|
+
"Bash(npm run test:ci)",
|
|
11
|
+
"Bash(npm run bench:ci)"
|
|
12
|
+
],
|
|
13
|
+
"deny": []
|
|
14
|
+
}
|
|
15
|
+
}
|
package/README.md
CHANGED
|
@@ -127,6 +127,73 @@ 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(genesis, cpLatest, meCurrent, options?)
|
|
131
|
+
|
|
132
|
+
Three-way HTML diff for back-and-forth negotiation scenarios. Given:
|
|
133
|
+
|
|
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
|
+
|
|
138
|
+
`executeThreeWay` compares both `cpLatest` and `meCurrent` against `genesis` and attributes each side's accumulated
|
|
139
|
+
changes independently:
|
|
140
|
+
|
|
141
|
+
- Counterparty insertions / deletions: `<ins class='diffins cp' data-author='cp'>` / `<del class='diffdel cp' ...>`
|
|
142
|
+
- Your insertions / deletions: `<ins class='diffins me' data-author='me'>` / `<del class='diffdel me' ...>`
|
|
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.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
import HtmlDiff from '@createiq/htmldiff'
|
|
148
|
+
|
|
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>'
|
|
152
|
+
|
|
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 fox→antelope and added "pig" — attributed to me.
|
|
156
|
+
// "jumps→leaps" was made by CP and kept by you — settled, emitted plain.
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Tables (including multi-table documents) and row/column structural changes are supported with the same author
|
|
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.
|
|
176
|
+
|
|
177
|
+
#### Options
|
|
178
|
+
|
|
179
|
+
`executeThreeWay` accepts the same options as `HtmlDiff` (`repeatingWordsAccuracy`, `ignoreWhitespaceDifferences`,
|
|
180
|
+
`orphanMatchThreshold`, `blockExpressions`). They flow into both internal pair-wise analyses identically.
|
|
181
|
+
|
|
182
|
+
`useProjections` controls structural-tag normalisation. When undefined (default), the decision is the conjunction of
|
|
183
|
+
both pair-wise heuristics — projection only activates when both `genesis↔cpLatest` and `genesis↔meCurrent` 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.
|
|
196
|
+
|
|
130
197
|
## Contributing
|
|
131
198
|
|
|
132
199
|
The library uses [Biome](https://biomejs.dev/) for linting and formatting, and [Vitest](https://vitest.dev/) for unit
|