joinAlignedDiffs.js 6.17 KB
'use strict';

Object.defineProperty(exports, '__esModule', {
  value: true
});
exports.joinAlignedDiffsExpand = exports.joinAlignedDiffsNoExpand = void 0;

var _cleanupSemantic = require('./cleanupSemantic');

var _printDiffs = require('./printDiffs');

/**
 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
// jest --no-expand
//
// Given array of aligned strings with inverse highlight formatting,
// return joined lines with diff formatting (and patch marks, if needed).
const joinAlignedDiffsNoExpand = (diffs, options) => {
  const iLength = diffs.length;
  const nContextLines = options.contextLines;
  const nContextLines2 = nContextLines + nContextLines; // First pass: count output lines and see if it has patches.

  let jLength = iLength;
  let hasExcessAtStartOrEnd = false;
  let nExcessesBetweenChanges = 0;
  let i = 0;

  while (i !== iLength) {
    const iStart = i;

    while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
      i += 1;
    }

    if (iStart !== i) {
      if (iStart === 0) {
        // at start
        if (i > nContextLines) {
          jLength -= i - nContextLines; // subtract excess common lines

          hasExcessAtStartOrEnd = true;
        }
      } else if (i === iLength) {
        // at end
        const n = i - iStart;

        if (n > nContextLines) {
          jLength -= n - nContextLines; // subtract excess common lines

          hasExcessAtStartOrEnd = true;
        }
      } else {
        // between changes
        const n = i - iStart;

        if (n > nContextLines2) {
          jLength -= n - nContextLines2; // subtract excess common lines

          nExcessesBetweenChanges += 1;
        }
      }
    }

    while (i !== iLength && diffs[i][0] !== _cleanupSemantic.DIFF_EQUAL) {
      i += 1;
    }
  }

  const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd;

  if (nExcessesBetweenChanges !== 0) {
    jLength += nExcessesBetweenChanges + 1; // add patch lines
  } else if (hasExcessAtStartOrEnd) {
    jLength += 1; // add patch line
  }

  const jLast = jLength - 1;
  const lines = [];
  let jPatchMark = 0; // index of placeholder line for current patch mark

  if (hasPatch) {
    lines.push(''); // placeholder line for first patch mark
  } // Indexes of expected or received lines in current patch:

  let aStart = 0;
  let bStart = 0;
  let aEnd = 0;
  let bEnd = 0;

  const pushCommonLine = line => {
    const j = lines.length;
    lines.push(
      (0, _printDiffs.printCommonLine)(line, j === 0 || j === jLast, options)
    );
    aEnd += 1;
    bEnd += 1;
  };

  const pushDeleteLine = line => {
    const j = lines.length;
    lines.push(
      (0, _printDiffs.printDeleteLine)(line, j === 0 || j === jLast, options)
    );
    aEnd += 1;
  };

  const pushInsertLine = line => {
    const j = lines.length;
    lines.push(
      (0, _printDiffs.printInsertLine)(line, j === 0 || j === jLast, options)
    );
    bEnd += 1;
  }; // Second pass: push lines with diff formatting (and patch marks, if needed).

  i = 0;

  while (i !== iLength) {
    let iStart = i;

    while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
      i += 1;
    }

    if (iStart !== i) {
      if (iStart === 0) {
        // at beginning
        if (i > nContextLines) {
          iStart = i - nContextLines;
          aStart = iStart;
          bStart = iStart;
          aEnd = aStart;
          bEnd = bStart;
        }

        for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
          pushCommonLine(diffs[iCommon][1]);
        }
      } else if (i === iLength) {
        // at end
        const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i;

        for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
          pushCommonLine(diffs[iCommon][1]);
        }
      } else {
        // between changes
        const nCommon = i - iStart;

        if (nCommon > nContextLines2) {
          const iEnd = iStart + nContextLines;

          for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
            pushCommonLine(diffs[iCommon][1]);
          }

          lines[jPatchMark] = (0, _printDiffs.createPatchMark)(
            aStart,
            aEnd,
            bStart,
            bEnd,
            options
          );
          jPatchMark = lines.length;
          lines.push(''); // placeholder line for next patch mark

          const nOmit = nCommon - nContextLines2;
          aStart = aEnd + nOmit;
          bStart = bEnd + nOmit;
          aEnd = aStart;
          bEnd = bStart;

          for (let iCommon = i - nContextLines; iCommon !== i; iCommon += 1) {
            pushCommonLine(diffs[iCommon][1]);
          }
        } else {
          for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
            pushCommonLine(diffs[iCommon][1]);
          }
        }
      }
    }

    while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_DELETE) {
      pushDeleteLine(diffs[i][1]);
      i += 1;
    }

    while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_INSERT) {
      pushInsertLine(diffs[i][1]);
      i += 1;
    }
  }

  if (hasPatch) {
    lines[jPatchMark] = (0, _printDiffs.createPatchMark)(
      aStart,
      aEnd,
      bStart,
      bEnd,
      options
    );
  }

  return lines.join('\n');
}; // jest --expand
//
// Given array of aligned strings with inverse highlight formatting,
// return joined lines with diff formatting.

exports.joinAlignedDiffsNoExpand = joinAlignedDiffsNoExpand;

const joinAlignedDiffsExpand = (diffs, options) =>
  diffs
    .map((diff, i, diffs) => {
      const line = diff[1];
      const isFirstOrLast = i === 0 || i === diffs.length - 1;

      switch (diff[0]) {
        case _cleanupSemantic.DIFF_DELETE:
          return (0, _printDiffs.printDeleteLine)(line, isFirstOrLast, options);

        case _cleanupSemantic.DIFF_INSERT:
          return (0, _printDiffs.printInsertLine)(line, isFirstOrLast, options);

        default:
          return (0, _printDiffs.printCommonLine)(line, isFirstOrLast, options);
      }
    })
    .join('\n');

exports.joinAlignedDiffsExpand = joinAlignedDiffsExpand;