@createiq/htmldiff 1.1.0 → 1.2.0-beta.0

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.
@@ -1,4 +1,68 @@
1
+ //#region src/Action.d.ts
2
+ declare enum Action {
3
+ Equal = 0,
4
+ Delete = 1,
5
+ Insert = 2,
6
+ None = 3,
7
+ Replace = 4
8
+ }
9
+ //#endregion
10
+ //#region src/Operation.d.ts
11
+ declare class Operation {
12
+ action: Action;
13
+ startInOld: number;
14
+ endInOld: number;
15
+ startInNew: number;
16
+ endInNew: number;
17
+ constructor(action: Action, startInOld: number, endInOld: number, startInNew: number, endInNew: number);
18
+ }
19
+ //#endregion
1
20
  //#region src/HtmlDiff.d.ts
21
+ /**
22
+ * Options for the `HtmlDiff.analyze` static helper.
23
+ *
24
+ * `useProjections` controls structural-tag normalisation:
25
+ * - `undefined` → use the same heuristic as `build()` (per-call decision)
26
+ * - `true` → force projection on (skipped if either side has no content)
27
+ * - `false` → force projection off (diff runs on raw word arrays)
28
+ * Composers of multiple analyses (e.g. three-way diff) MUST pass the
29
+ * same explicit boolean to all calls so shared inputs tokenise
30
+ * identically across analyses.
31
+ *
32
+ * The remaining options mirror the per-instance fields on `HtmlDiff`
33
+ * itself — they exist on the options bag because `analyze` constructs
34
+ * the inner instance internally.
35
+ */
36
+ interface AnalyzeOptions {
37
+ useProjections?: boolean;
38
+ blockExpressions?: readonly RegExp[];
39
+ repeatingWordsAccuracy?: number;
40
+ orphanMatchThreshold?: number;
41
+ ignoreWhitespaceDifferences?: boolean;
42
+ }
43
+ interface AnalyzeResult {
44
+ /** Word array the `operations` index into (projected or raw). */
45
+ readonly oldDiffWords: readonly string[];
46
+ readonly newDiffWords: readonly string[];
47
+ readonly operations: readonly Operation[];
48
+ /** Original WordSplitter output, before any projection. */
49
+ readonly oldOriginalWords: readonly string[];
50
+ readonly newOriginalWords: readonly string[];
51
+ /** Diff-index → original-word-index map; null when projections inactive. */
52
+ readonly oldContentToOriginal: readonly number[] | null;
53
+ readonly newContentToOriginal: readonly number[] | null;
54
+ }
55
+ /**
56
+ * Options for `HtmlDiff.executeThreeWay`. Same shape as `AnalyzeOptions`
57
+ * — the values flow unchanged into both internal `analyze` calls so V2's
58
+ * tokenisation stays symmetric. Aliased so future divergence in either
59
+ * direction lives in one place.
60
+ *
61
+ * `useProjections`: when undefined, `executeThreeWay` computes the
62
+ * decision as the conjunction of both pair-wise
63
+ * `evaluateProjectionApplicability` results.
64
+ */
65
+ type ThreeWayOptions = AnalyzeOptions;
2
66
  declare class HtmlDiff {
3
67
  /**
4
68
  * This value defines balance between speed and memory utilization. The higher it is the faster it works and more memory consumes.
@@ -21,10 +85,20 @@ declare class HtmlDiff {
21
85
  * pathological input.
22
86
  */
23
87
  private static MaxTablePreprocessDepth;
88
+ /**
89
+ * Mirror cap for the three-way path. The 2-way `MaxTablePreprocessDepth`
90
+ * guards the recursion inside `executeWithContext`; the 3-way path has
91
+ * its own recursion (`executeThreeWay` → `preprocessTablesThreeWay` →
92
+ * `cellDiff` → `executeThreeWay`) which needs its own guard. Once the
93
+ * cap is reached, `executeThreeWay` skips table preprocessing and
94
+ * falls back to the word-level merge — same bail-out semantics as the
95
+ * 2-way path.
96
+ */
97
+ private static MaxThreeWayDepth;
24
98
  private content;
25
99
  private newText;
26
100
  private oldText;
27
- private readonly tablePreprocessDepth;
101
+ private tablePreprocessDepth;
28
102
  private specialTagDiffStack;
29
103
  private newWords;
30
104
  private oldWords;
@@ -87,12 +161,71 @@ declare class HtmlDiff {
87
161
  * Initializes a new instance of the class.
88
162
  * @param oldText The old text.
89
163
  * @param newText The new text.
90
- * @param tablePreprocessDepth Internal: nested-call depth for table
91
- * preprocessing. Callers should leave at default (0); the recursive
92
- * `diffCell` callback in TableDiff bumps it.
93
164
  */
94
- constructor(oldText: string, newText: string, tablePreprocessDepth?: number);
95
- static execute(oldText: string, newText: string, tablePreprocessDepth?: number): string;
165
+ constructor(oldText: string, newText: string);
166
+ static execute(oldText: string, newText: string): string;
167
+ /**
168
+ * Analyse a two-way diff and return its raw building blocks: the word
169
+ * arrays the diff ran against, the operations produced, the original
170
+ * (pre-projection) word arrays, and the mappings from diff-index back
171
+ * to original-word index when structural projection is active.
172
+ * Consumed by `executeThreeWay` so it can compose two diffs by walking
173
+ * their Operation streams.
174
+ *
175
+ * The caller is expected to coordinate `useProjections` symmetrically
176
+ * across composed analyses — if V1↔V2 projects but V2↔V3 doesn't,
177
+ * V2's "new" array in the first analysis won't equal V2's "old" array
178
+ * in the second. `evaluateProjectionApplicability` exposes the same
179
+ * heuristic `build()` uses internally, so the orchestrator can compute
180
+ * a single decision and pass it into every `analyze` call.
181
+ *
182
+ * Table preprocessing is skipped here. Placeholders mutate the input
183
+ * in ways that don't compose across two independent analyses; the
184
+ * 3-way orchestrator handles tables explicitly before calling analyze.
185
+ */
186
+ static analyze(oldText: string, newText: string, options?: AnalyzeOptions): AnalyzeResult;
187
+ /**
188
+ * Whether content-projection (structural-tag normalisation) would
189
+ * apply to this pair of inputs under `build()`'s default heuristic.
190
+ * Exposed so composers of multiple analyses can compute a symmetric
191
+ * decision before calling `analyze` — see `analyze`'s docstring for
192
+ * why symmetry matters.
193
+ */
194
+ static evaluateProjectionApplicability(oldText: string, newText: string): boolean;
195
+ /**
196
+ * Three-way HTML diff. Given V1 (the version Me last sent), V2 (the
197
+ * version CP sent back), and V3 (Me's current draft), produces a
198
+ * single attributed HTML output where CP's and Me's changes are
199
+ * distinguished by `data-author` ('cp' or 'me') and matching
200
+ * `class='diffins cp'` / `class='diffdel me'` etc. The "Me rejected
201
+ * CP's proposal" case (Me deleted text CP had inserted) gets a
202
+ * dedicated marker: `data-rejects='cp'` plus `class='... rejects-cp'`.
203
+ *
204
+ * Coordinates the symmetric-projection decision (D1) across both
205
+ * internal `analyze` calls so V2 tokenises identically on each side
206
+ * of the spine. When `useProjections` is left undefined, the decision
207
+ * is the conjunction of both pair-wise heuristics — project iff both
208
+ * pairs would project on their own. Pass an explicit boolean to
209
+ * override.
210
+ */
211
+ static executeThreeWay(v1: string, v2: string, v3: string, options?: ThreeWayOptions): string;
212
+ private static executeThreeWayWithDepth;
213
+ /**
214
+ * Drives a fresh `HtmlDiff` instance through `insertTag` for ins/del
215
+ * segments and pushes equal segments straight to its `content`
216
+ * buffer. Reusing the instance keeps the formatting-tag stack
217
+ * (`specialTagDiffStack`) coherent across segments — a `<strong>`
218
+ * opened in one segment and closed in another stays balanced.
219
+ */
220
+ private static emitSegments;
221
+ /**
222
+ * Internal entry point used by the table-cell recursion. Constructs an
223
+ * inner `HtmlDiff`, applies the caller's settings, and bumps the
224
+ * recursion depth — keeping the public constructor signature clean
225
+ * while still threading the configuration that's required for cell-
226
+ * level output to match the top-level call's behaviour.
227
+ */
228
+ private static executeWithContext;
96
229
  /**
97
230
  * Builds the HTML diff output
98
231
  * @return HTML diff markup
@@ -185,5 +318,6 @@ declare class HtmlDiff {
185
318
  private findMatchingBlocks;
186
319
  private findMatch;
187
320
  }
188
- export = HtmlDiff;
321
+ //#endregion
322
+ export { AnalyzeOptions, AnalyzeResult, ThreeWayOptions, HtmlDiff as default };
189
323
  //# sourceMappingURL=HtmlDiff.d.cts.map
@@ -1,4 +1,68 @@
1
+ //#region src/Action.d.ts
2
+ declare enum Action {
3
+ Equal = 0,
4
+ Delete = 1,
5
+ Insert = 2,
6
+ None = 3,
7
+ Replace = 4
8
+ }
9
+ //#endregion
10
+ //#region src/Operation.d.ts
11
+ declare class Operation {
12
+ action: Action;
13
+ startInOld: number;
14
+ endInOld: number;
15
+ startInNew: number;
16
+ endInNew: number;
17
+ constructor(action: Action, startInOld: number, endInOld: number, startInNew: number, endInNew: number);
18
+ }
19
+ //#endregion
1
20
  //#region src/HtmlDiff.d.ts
21
+ /**
22
+ * Options for the `HtmlDiff.analyze` static helper.
23
+ *
24
+ * `useProjections` controls structural-tag normalisation:
25
+ * - `undefined` → use the same heuristic as `build()` (per-call decision)
26
+ * - `true` → force projection on (skipped if either side has no content)
27
+ * - `false` → force projection off (diff runs on raw word arrays)
28
+ * Composers of multiple analyses (e.g. three-way diff) MUST pass the
29
+ * same explicit boolean to all calls so shared inputs tokenise
30
+ * identically across analyses.
31
+ *
32
+ * The remaining options mirror the per-instance fields on `HtmlDiff`
33
+ * itself — they exist on the options bag because `analyze` constructs
34
+ * the inner instance internally.
35
+ */
36
+ interface AnalyzeOptions {
37
+ useProjections?: boolean;
38
+ blockExpressions?: readonly RegExp[];
39
+ repeatingWordsAccuracy?: number;
40
+ orphanMatchThreshold?: number;
41
+ ignoreWhitespaceDifferences?: boolean;
42
+ }
43
+ interface AnalyzeResult {
44
+ /** Word array the `operations` index into (projected or raw). */
45
+ readonly oldDiffWords: readonly string[];
46
+ readonly newDiffWords: readonly string[];
47
+ readonly operations: readonly Operation[];
48
+ /** Original WordSplitter output, before any projection. */
49
+ readonly oldOriginalWords: readonly string[];
50
+ readonly newOriginalWords: readonly string[];
51
+ /** Diff-index → original-word-index map; null when projections inactive. */
52
+ readonly oldContentToOriginal: readonly number[] | null;
53
+ readonly newContentToOriginal: readonly number[] | null;
54
+ }
55
+ /**
56
+ * Options for `HtmlDiff.executeThreeWay`. Same shape as `AnalyzeOptions`
57
+ * — the values flow unchanged into both internal `analyze` calls so V2's
58
+ * tokenisation stays symmetric. Aliased so future divergence in either
59
+ * direction lives in one place.
60
+ *
61
+ * `useProjections`: when undefined, `executeThreeWay` computes the
62
+ * decision as the conjunction of both pair-wise
63
+ * `evaluateProjectionApplicability` results.
64
+ */
65
+ type ThreeWayOptions = AnalyzeOptions;
2
66
  declare class HtmlDiff {
3
67
  /**
4
68
  * This value defines balance between speed and memory utilization. The higher it is the faster it works and more memory consumes.
@@ -21,10 +85,20 @@ declare class HtmlDiff {
21
85
  * pathological input.
22
86
  */
23
87
  private static MaxTablePreprocessDepth;
88
+ /**
89
+ * Mirror cap for the three-way path. The 2-way `MaxTablePreprocessDepth`
90
+ * guards the recursion inside `executeWithContext`; the 3-way path has
91
+ * its own recursion (`executeThreeWay` → `preprocessTablesThreeWay` →
92
+ * `cellDiff` → `executeThreeWay`) which needs its own guard. Once the
93
+ * cap is reached, `executeThreeWay` skips table preprocessing and
94
+ * falls back to the word-level merge — same bail-out semantics as the
95
+ * 2-way path.
96
+ */
97
+ private static MaxThreeWayDepth;
24
98
  private content;
25
99
  private newText;
26
100
  private oldText;
27
- private readonly tablePreprocessDepth;
101
+ private tablePreprocessDepth;
28
102
  private specialTagDiffStack;
29
103
  private newWords;
30
104
  private oldWords;
@@ -87,12 +161,71 @@ declare class HtmlDiff {
87
161
  * Initializes a new instance of the class.
88
162
  * @param oldText The old text.
89
163
  * @param newText The new text.
90
- * @param tablePreprocessDepth Internal: nested-call depth for table
91
- * preprocessing. Callers should leave at default (0); the recursive
92
- * `diffCell` callback in TableDiff bumps it.
93
164
  */
94
- constructor(oldText: string, newText: string, tablePreprocessDepth?: number);
95
- static execute(oldText: string, newText: string, tablePreprocessDepth?: number): string;
165
+ constructor(oldText: string, newText: string);
166
+ static execute(oldText: string, newText: string): string;
167
+ /**
168
+ * Analyse a two-way diff and return its raw building blocks: the word
169
+ * arrays the diff ran against, the operations produced, the original
170
+ * (pre-projection) word arrays, and the mappings from diff-index back
171
+ * to original-word index when structural projection is active.
172
+ * Consumed by `executeThreeWay` so it can compose two diffs by walking
173
+ * their Operation streams.
174
+ *
175
+ * The caller is expected to coordinate `useProjections` symmetrically
176
+ * across composed analyses — if V1↔V2 projects but V2↔V3 doesn't,
177
+ * V2's "new" array in the first analysis won't equal V2's "old" array
178
+ * in the second. `evaluateProjectionApplicability` exposes the same
179
+ * heuristic `build()` uses internally, so the orchestrator can compute
180
+ * a single decision and pass it into every `analyze` call.
181
+ *
182
+ * Table preprocessing is skipped here. Placeholders mutate the input
183
+ * in ways that don't compose across two independent analyses; the
184
+ * 3-way orchestrator handles tables explicitly before calling analyze.
185
+ */
186
+ static analyze(oldText: string, newText: string, options?: AnalyzeOptions): AnalyzeResult;
187
+ /**
188
+ * Whether content-projection (structural-tag normalisation) would
189
+ * apply to this pair of inputs under `build()`'s default heuristic.
190
+ * Exposed so composers of multiple analyses can compute a symmetric
191
+ * decision before calling `analyze` — see `analyze`'s docstring for
192
+ * why symmetry matters.
193
+ */
194
+ static evaluateProjectionApplicability(oldText: string, newText: string): boolean;
195
+ /**
196
+ * Three-way HTML diff. Given V1 (the version Me last sent), V2 (the
197
+ * version CP sent back), and V3 (Me's current draft), produces a
198
+ * single attributed HTML output where CP's and Me's changes are
199
+ * distinguished by `data-author` ('cp' or 'me') and matching
200
+ * `class='diffins cp'` / `class='diffdel me'` etc. The "Me rejected
201
+ * CP's proposal" case (Me deleted text CP had inserted) gets a
202
+ * dedicated marker: `data-rejects='cp'` plus `class='... rejects-cp'`.
203
+ *
204
+ * Coordinates the symmetric-projection decision (D1) across both
205
+ * internal `analyze` calls so V2 tokenises identically on each side
206
+ * of the spine. When `useProjections` is left undefined, the decision
207
+ * is the conjunction of both pair-wise heuristics — project iff both
208
+ * pairs would project on their own. Pass an explicit boolean to
209
+ * override.
210
+ */
211
+ static executeThreeWay(v1: string, v2: string, v3: string, options?: ThreeWayOptions): string;
212
+ private static executeThreeWayWithDepth;
213
+ /**
214
+ * Drives a fresh `HtmlDiff` instance through `insertTag` for ins/del
215
+ * segments and pushes equal segments straight to its `content`
216
+ * buffer. Reusing the instance keeps the formatting-tag stack
217
+ * (`specialTagDiffStack`) coherent across segments — a `<strong>`
218
+ * opened in one segment and closed in another stays balanced.
219
+ */
220
+ private static emitSegments;
221
+ /**
222
+ * Internal entry point used by the table-cell recursion. Constructs an
223
+ * inner `HtmlDiff`, applies the caller's settings, and bumps the
224
+ * recursion depth — keeping the public constructor signature clean
225
+ * while still threading the configuration that's required for cell-
226
+ * level output to match the top-level call's behaviour.
227
+ */
228
+ private static executeWithContext;
96
229
  /**
97
230
  * Builds the HTML diff output
98
231
  * @return HTML diff markup
@@ -186,5 +319,5 @@ declare class HtmlDiff {
186
319
  private findMatch;
187
320
  }
188
321
  //#endregion
189
- export { HtmlDiff as default };
322
+ export { AnalyzeOptions, AnalyzeResult, ThreeWayOptions, HtmlDiff as default };
190
323
  //# sourceMappingURL=HtmlDiff.d.mts.map