123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', {
- value: true
- });
- exports.default = void 0;
- var _chalk = _interopRequireDefault(require('chalk'));
- var _diffSequences = _interopRequireDefault(require('diff-sequences'));
- var _constants = require('./constants');
- var _printDiffs = require('./printDiffs');
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {default: obj};
- }
- /**
- * 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.
- */
- const DIFF_CONTEXT_DEFAULT = 5;
- const fgDelete = _chalk.default.green;
- const fgInsert = _chalk.default.red;
- const fgCommon = _chalk.default.dim; // common lines (even indentation same)
- const fgIndent = _chalk.default.cyan; // common lines (only indentation different)
- const bgCommon = _chalk.default.bgYellow; // edge spaces in common line (even indentation same)
- const bgInverse = _chalk.default.inverse; // edge spaces in any other lines
- // ONLY trailing if expected value is snapshot or multiline string.
- const highlightTrailingSpaces = (line, bgColor) =>
- line.replace(/\s+$/, bgColor('$&')); // BOTH leading AND trailing if expected value is data structure.
- const highlightLeadingTrailingSpaces = (
- line,
- bgColor // If line consists of ALL spaces: highlight all of them.
- ) =>
- highlightTrailingSpaces(line, bgColor).replace(
- // If line has an ODD length of leading spaces: highlight only the LAST.
- /^(\s\s)*(\s)(?=[^\s])/,
- '$1' + bgColor('$2')
- );
- const getHighlightSpaces = bothEdges =>
- bothEdges ? highlightLeadingTrailingSpaces : highlightTrailingSpaces;
- // Given index interval in expected lines, put formatted delete lines.
- const formatDelete = (aStart, aEnd, aLinesUn, aLinesIn, put) => {
- const highlightSpaces = getHighlightSpaces(aLinesUn !== aLinesIn);
- for (let aIndex = aStart; aIndex !== aEnd; aIndex += 1) {
- const aLineUn = aLinesUn[aIndex];
- const aLineIn = aLinesIn[aIndex];
- const indentation = aLineIn.slice(0, aLineIn.length - aLineUn.length);
- put(fgDelete('- ' + indentation + highlightSpaces(aLineUn, bgInverse)));
- }
- }; // Given index interval in received lines, put formatted insert lines.
- const formatInsert = (bStart, bEnd, bLinesUn, bLinesIn, put) => {
- const highlightSpaces = getHighlightSpaces(bLinesUn !== bLinesIn);
- for (let bIndex = bStart; bIndex !== bEnd; bIndex += 1) {
- const bLineUn = bLinesUn[bIndex];
- const bLineIn = bLinesIn[bIndex];
- const indentation = bLineIn.slice(0, bLineIn.length - bLineUn.length);
- put(fgInsert('+ ' + indentation + highlightSpaces(bLineUn, bgInverse)));
- }
- }; // Given the number of items and starting indexes of a common subsequence,
- // put formatted common lines.
- const formatCommon = (
- nCommon,
- aCommon,
- bCommon,
- aLinesIn,
- bLinesUn,
- bLinesIn,
- put
- ) => {
- const highlightSpaces = getHighlightSpaces(bLinesUn !== bLinesIn);
- for (; nCommon !== 0; nCommon -= 1, aCommon += 1, bCommon += 1) {
- const bLineUn = bLinesUn[bCommon];
- const bLineIn = bLinesIn[bCommon];
- const bLineInLength = bLineIn.length; // For common lines, received indentation seems more intuitive.
- const indentation = bLineIn.slice(0, bLineInLength - bLineUn.length); // Color shows whether expected and received line has same indentation.
- const hasSameIndentation = aLinesIn[aCommon].length === bLineInLength;
- const fg = hasSameIndentation ? fgCommon : fgIndent;
- const bg = hasSameIndentation ? bgCommon : bgInverse;
- put(fg(' ' + indentation + highlightSpaces(bLineUn, bg)));
- }
- }; // jest --expand
- // Return formatted diff as joined string of all lines.
- const diffExpand = (aLinesUn, bLinesUn, aLinesIn, bLinesIn) => {
- const isCommon = (aIndex, bIndex) => aLinesUn[aIndex] === bLinesUn[bIndex];
- const array = [];
- const put = line => {
- array.push(line);
- };
- let aStart = 0;
- let bStart = 0;
- const foundSubsequence = (nCommon, aCommon, bCommon) => {
- formatDelete(aStart, aCommon, aLinesUn, aLinesIn, put);
- formatInsert(bStart, bCommon, bLinesUn, bLinesIn, put);
- formatCommon(nCommon, aCommon, bCommon, aLinesIn, bLinesUn, bLinesIn, put);
- aStart = aCommon + nCommon;
- bStart = bCommon + nCommon;
- };
- const aLength = aLinesUn.length;
- const bLength = bLinesUn.length;
- (0, _diffSequences.default)(aLength, bLength, isCommon, foundSubsequence); // After the last common subsequence, format remaining change lines.
- formatDelete(aStart, aLength, aLinesUn, aLinesIn, put);
- formatInsert(bStart, bLength, bLinesUn, bLinesIn, put);
- return array.join('\n');
- };
- const getContextLines = options =>
- options &&
- typeof options.contextLines === 'number' &&
- options.contextLines >= 0
- ? options.contextLines
- : DIFF_CONTEXT_DEFAULT; // jest --no-expand
- // Return joined string of formatted diff for all change lines,
- // but if some common lines are omitted because there are more than the context,
- // then a “patch mark” precedes each set of adjacent changed and common lines.
- const diffNoExpand = (
- aLinesUn,
- bLinesUn,
- aLinesIn,
- bLinesIn,
- nContextLines
- ) => {
- const isCommon = (aIndex, bIndex) => aLinesUn[aIndex] === bLinesUn[bIndex];
- let iPatchMark = 0; // index of placeholder line for patch mark
- const array = [''];
- const put = line => {
- array.push(line);
- };
- let isAtEnd = false;
- const aLength = aLinesUn.length;
- const bLength = bLinesUn.length;
- const nContextLines2 = nContextLines + nContextLines; // Initialize the first patch for changes at the start,
- // especially for edge case in which there is no common subsequence.
- let aStart = 0;
- let aEnd = 0;
- let bStart = 0;
- let bEnd = 0; // Given the number of items and starting indexes of each common subsequence,
- // format any preceding change lines, and then common context lines.
- const foundSubsequence = (nCommon, aStartCommon, bStartCommon) => {
- const aEndCommon = aStartCommon + nCommon;
- const bEndCommon = bStartCommon + nCommon;
- isAtEnd = aEndCommon === aLength && bEndCommon === bLength; // If common subsequence is at start, re-initialize the first patch.
- if (aStartCommon === 0 && bStartCommon === 0) {
- const nLines = nContextLines < nCommon ? nContextLines : nCommon;
- aStart = aEndCommon - nLines;
- bStart = bEndCommon - nLines;
- formatCommon(nLines, aStart, bStart, aLinesIn, bLinesUn, bLinesIn, put);
- aEnd = aEndCommon;
- bEnd = bEndCommon;
- return;
- } // Format preceding change lines.
- formatDelete(aEnd, aStartCommon, aLinesUn, aLinesIn, put);
- formatInsert(bEnd, bStartCommon, bLinesUn, bLinesIn, put);
- aEnd = aStartCommon;
- bEnd = bStartCommon; // If common subsequence is at end, then context follows preceding changes;
- // else context follows preceding changes AND precedes following changes.
- const maxContextLines = isAtEnd ? nContextLines : nContextLines2;
- if (nCommon <= maxContextLines) {
- // The patch includes all lines in the common subsequence.
- formatCommon(nCommon, aEnd, bEnd, aLinesIn, bLinesUn, bLinesIn, put);
- aEnd += nCommon;
- bEnd += nCommon;
- return;
- } // The patch ends because context is less than number of common lines.
- formatCommon(nContextLines, aEnd, bEnd, aLinesIn, bLinesUn, bLinesIn, put);
- aEnd += nContextLines;
- bEnd += nContextLines;
- array[iPatchMark] = (0, _printDiffs.createPatchMark)(
- aStart,
- aEnd,
- bStart,
- bEnd
- ); // If common subsequence is not at end, another patch follows it.
- if (!isAtEnd) {
- iPatchMark = array.length; // index of placeholder line
- array[iPatchMark] = '';
- const nLines = nContextLines < nCommon ? nContextLines : nCommon;
- aStart = aEndCommon - nLines;
- bStart = bEndCommon - nLines;
- formatCommon(nLines, aStart, bStart, aLinesIn, bLinesUn, bLinesIn, put);
- aEnd = aEndCommon;
- bEnd = bEndCommon;
- }
- };
- (0, _diffSequences.default)(aLength, bLength, isCommon, foundSubsequence); // If no common subsequence or last was not at end, format remaining change lines.
- if (!isAtEnd) {
- formatDelete(aEnd, aLength, aLinesUn, aLinesIn, put);
- formatInsert(bEnd, bLength, bLinesUn, bLinesIn, put);
- aEnd = aLength;
- bEnd = bLength;
- }
- if (aStart === 0 && aEnd === aLength && bStart === 0 && bEnd === bLength) {
- array.splice(0, 1); // delete placeholder line for patch mark
- } else {
- array[iPatchMark] = (0, _printDiffs.createPatchMark)(
- aStart,
- aEnd,
- bStart,
- bEnd
- );
- }
- return array.join('\n');
- };
- var _default = (a, b, options, original) => {
- if (a === b) {
- return _constants.NO_DIFF_MESSAGE;
- }
- let aLinesUn = a.split('\n');
- let bLinesUn = b.split('\n'); // Indentation is unknown if expected value is snapshot or multiline string.
- let aLinesIn = aLinesUn;
- let bLinesIn = bLinesUn;
- if (original) {
- // Indentation is known if expected value is data structure:
- // Compare lines without indentation and format lines with indentation.
- aLinesIn = original.a.split('\n');
- bLinesIn = original.b.split('\n');
- if (
- aLinesUn.length !== aLinesIn.length ||
- bLinesUn.length !== bLinesIn.length
- ) {
- // Fall back if unindented and indented lines are inconsistent.
- aLinesUn = aLinesIn;
- bLinesUn = bLinesIn;
- }
- }
- return (
- (0, _printDiffs.printAnnotation)(options) +
- (options && options.expand === false
- ? diffNoExpand(
- aLinesUn,
- bLinesUn,
- aLinesIn,
- bLinesIn,
- getContextLines(options)
- )
- : diffExpand(aLinesUn, bLinesUn, aLinesIn, bLinesIn))
- );
- };
- exports.default = _default;
|