All files / diff/src lines.ts

100% Statements 24/24
100% Branches 4/4
100% Functions 1/1
100% Lines 20/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48      20x                                     20x 9953x 9953x 9953x 9953x 9953x 74815x 32425x 129932x 129932x 129932x   42390x 20168x 135718x 135718x     22222x 135403x 135403x     9953x    
import {LINE_PATCH_OP_TYPE, type LinePatch} from './line';
import type {DiffLimits} from './limits';
import {PATCH_OP_TYPE} from './str';
import * as tok from './tok';
 
export type {DiffLimits} from './limits';
 
/**
 * Token-based line diff: hashes each line to a token and diffs the line
 * sequences with {@link tok.diff}, producing a {@link LinePatch} of whole-line
 * `DEL`/`EQL`/`INS` operations. Unlike `line.diff` it does not detect in-place
 * line modifications (a changed line is a delete plus an insert, never `MIX`),
 * which makes it much faster on large inputs since it never diffs characters.
 * The result is consumable by `line.apply`.
 *
 * @param src Source lines (newline-free is not required; lines are compared whole).
 * @param dst Destination lines.
 * @param limits Optional bounds; without them the patch is minimal. When a
 *     bound is hit the patch is near-minimal instead, and
 *     {@link DiffLimits.hitLimit} is set on the passed object.
 * @returns A line-level patch with no `MIX` operations.
 */
export const diff = (src: string[], dst: string[], limits?: DiffLimits): LinePatch => {
  const runs = tok.diff(src, dst, limits);
  const patch: LinePatch = [];
  let si = 0;
  let di = 0;
  for (const [type, count] of runs) {
    if (type === PATCH_OP_TYPE.EQL)
      for (let k = 0; k < count; k++) {
        patch.push([LINE_PATCH_OP_TYPE.EQL, si, di]);
        si++;
        di++;
      }
    else if (type === PATCH_OP_TYPE.DEL)
      for (let k = 0; k < count; k++) {
        patch.push([LINE_PATCH_OP_TYPE.DEL, si, di - 1]);
        si++;
      }
    else
      for (let k = 0; k < count; k++) {
        patch.push([LINE_PATCH_OP_TYPE.INS, si - 1, di]);
        di++;
      }
  }
  return patch;
};