joinAlignedDiffs.js
  1  'use strict';
  2  
  3  Object.defineProperty(exports, '__esModule', {
  4    value: true
  5  });
  6  exports.joinAlignedDiffsExpand = exports.joinAlignedDiffsNoExpand = void 0;
  7  
  8  var _cleanupSemantic = require('./cleanupSemantic');
  9  
 10  var _printDiffs = require('./printDiffs');
 11  
 12  /**
 13   * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
 14   *
 15   * This source code is licensed under the MIT license found in the
 16   * LICENSE file in the root directory of this source tree.
 17   */
 18  // jest --no-expand
 19  //
 20  // Given array of aligned strings with inverse highlight formatting,
 21  // return joined lines with diff formatting (and patch marks, if needed).
 22  const joinAlignedDiffsNoExpand = (diffs, options) => {
 23    const iLength = diffs.length;
 24    const nContextLines = options.contextLines;
 25    const nContextLines2 = nContextLines + nContextLines; // First pass: count output lines and see if it has patches.
 26  
 27    let jLength = iLength;
 28    let hasExcessAtStartOrEnd = false;
 29    let nExcessesBetweenChanges = 0;
 30    let i = 0;
 31  
 32    while (i !== iLength) {
 33      const iStart = i;
 34  
 35      while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
 36        i += 1;
 37      }
 38  
 39      if (iStart !== i) {
 40        if (iStart === 0) {
 41          // at start
 42          if (i > nContextLines) {
 43            jLength -= i - nContextLines; // subtract excess common lines
 44  
 45            hasExcessAtStartOrEnd = true;
 46          }
 47        } else if (i === iLength) {
 48          // at end
 49          const n = i - iStart;
 50  
 51          if (n > nContextLines) {
 52            jLength -= n - nContextLines; // subtract excess common lines
 53  
 54            hasExcessAtStartOrEnd = true;
 55          }
 56        } else {
 57          // between changes
 58          const n = i - iStart;
 59  
 60          if (n > nContextLines2) {
 61            jLength -= n - nContextLines2; // subtract excess common lines
 62  
 63            nExcessesBetweenChanges += 1;
 64          }
 65        }
 66      }
 67  
 68      while (i !== iLength && diffs[i][0] !== _cleanupSemantic.DIFF_EQUAL) {
 69        i += 1;
 70      }
 71    }
 72  
 73    const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd;
 74  
 75    if (nExcessesBetweenChanges !== 0) {
 76      jLength += nExcessesBetweenChanges + 1; // add patch lines
 77    } else if (hasExcessAtStartOrEnd) {
 78      jLength += 1; // add patch line
 79    }
 80  
 81    const jLast = jLength - 1;
 82    const lines = [];
 83    let jPatchMark = 0; // index of placeholder line for current patch mark
 84  
 85    if (hasPatch) {
 86      lines.push(''); // placeholder line for first patch mark
 87    } // Indexes of expected or received lines in current patch:
 88  
 89    let aStart = 0;
 90    let bStart = 0;
 91    let aEnd = 0;
 92    let bEnd = 0;
 93  
 94    const pushCommonLine = line => {
 95      const j = lines.length;
 96      lines.push(
 97        (0, _printDiffs.printCommonLine)(line, j === 0 || j === jLast, options)
 98      );
 99      aEnd += 1;
100      bEnd += 1;
101    };
102  
103    const pushDeleteLine = line => {
104      const j = lines.length;
105      lines.push(
106        (0, _printDiffs.printDeleteLine)(line, j === 0 || j === jLast, options)
107      );
108      aEnd += 1;
109    };
110  
111    const pushInsertLine = line => {
112      const j = lines.length;
113      lines.push(
114        (0, _printDiffs.printInsertLine)(line, j === 0 || j === jLast, options)
115      );
116      bEnd += 1;
117    }; // Second pass: push lines with diff formatting (and patch marks, if needed).
118  
119    i = 0;
120  
121    while (i !== iLength) {
122      let iStart = i;
123  
124      while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_EQUAL) {
125        i += 1;
126      }
127  
128      if (iStart !== i) {
129        if (iStart === 0) {
130          // at beginning
131          if (i > nContextLines) {
132            iStart = i - nContextLines;
133            aStart = iStart;
134            bStart = iStart;
135            aEnd = aStart;
136            bEnd = bStart;
137          }
138  
139          for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
140            pushCommonLine(diffs[iCommon][1]);
141          }
142        } else if (i === iLength) {
143          // at end
144          const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i;
145  
146          for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
147            pushCommonLine(diffs[iCommon][1]);
148          }
149        } else {
150          // between changes
151          const nCommon = i - iStart;
152  
153          if (nCommon > nContextLines2) {
154            const iEnd = iStart + nContextLines;
155  
156            for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) {
157              pushCommonLine(diffs[iCommon][1]);
158            }
159  
160            lines[jPatchMark] = (0, _printDiffs.createPatchMark)(
161              aStart,
162              aEnd,
163              bStart,
164              bEnd,
165              options
166            );
167            jPatchMark = lines.length;
168            lines.push(''); // placeholder line for next patch mark
169  
170            const nOmit = nCommon - nContextLines2;
171            aStart = aEnd + nOmit;
172            bStart = bEnd + nOmit;
173            aEnd = aStart;
174            bEnd = bStart;
175  
176            for (let iCommon = i - nContextLines; iCommon !== i; iCommon += 1) {
177              pushCommonLine(diffs[iCommon][1]);
178            }
179          } else {
180            for (let iCommon = iStart; iCommon !== i; iCommon += 1) {
181              pushCommonLine(diffs[iCommon][1]);
182            }
183          }
184        }
185      }
186  
187      while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_DELETE) {
188        pushDeleteLine(diffs[i][1]);
189        i += 1;
190      }
191  
192      while (i !== iLength && diffs[i][0] === _cleanupSemantic.DIFF_INSERT) {
193        pushInsertLine(diffs[i][1]);
194        i += 1;
195      }
196    }
197  
198    if (hasPatch) {
199      lines[jPatchMark] = (0, _printDiffs.createPatchMark)(
200        aStart,
201        aEnd,
202        bStart,
203        bEnd,
204        options
205      );
206    }
207  
208    return lines.join('\n');
209  }; // jest --expand
210  //
211  // Given array of aligned strings with inverse highlight formatting,
212  // return joined lines with diff formatting.
213  
214  exports.joinAlignedDiffsNoExpand = joinAlignedDiffsNoExpand;
215  
216  const joinAlignedDiffsExpand = (diffs, options) =>
217    diffs
218      .map((diff, i, diffs) => {
219        const line = diff[1];
220        const isFirstOrLast = i === 0 || i === diffs.length - 1;
221  
222        switch (diff[0]) {
223          case _cleanupSemantic.DIFF_DELETE:
224            return (0, _printDiffs.printDeleteLine)(line, isFirstOrLast, options);
225  
226          case _cleanupSemantic.DIFF_INSERT:
227            return (0, _printDiffs.printInsertLine)(line, isFirstOrLast, options);
228  
229          default:
230            return (0, _printDiffs.printCommonLine)(line, isFirstOrLast, options);
231        }
232      })
233      .join('\n');
234  
235  exports.joinAlignedDiffsExpand = joinAlignedDiffsExpand;