'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports.diffStringsRaw = exports.diffStringsUnified = exports.createPatchMark = exports.printDiffLines = exports.printAnnotation = exports.countChanges = exports.hasCommonDiff = exports.printCommonLine = exports.printInsertLine = exports.printDeleteLine = void 0; var _cleanupSemantic = require('./cleanupSemantic'); var _diffLines = require('./diffLines'); var _diffStrings = _interopRequireDefault(require('./diffStrings')); var _getAlignedDiffs = _interopRequireDefault(require('./getAlignedDiffs')); var _joinAlignedDiffs = require('./joinAlignedDiffs'); var _normalizeDiffOptions = require('./normalizeDiffOptions'); 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 formatTrailingSpaces = (line, trailingSpaceFormatter) => line.replace(/\s+$/, match => trailingSpaceFormatter(match)); const printDiffLine = ( line, isFirstOrLast, color, indicator, trailingSpaceFormatter, emptyFirstOrLastLinePlaceholder ) => line.length !== 0 ? color( indicator + ' ' + formatTrailingSpaces(line, trailingSpaceFormatter) ) : indicator !== ' ' ? color(indicator) : isFirstOrLast && emptyFirstOrLastLinePlaceholder.length !== 0 ? color(indicator + ' ' + emptyFirstOrLastLinePlaceholder) : ''; const printDeleteLine = ( line, isFirstOrLast, { aColor, aIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder } ) => printDiffLine( line, isFirstOrLast, aColor, aIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder ); exports.printDeleteLine = printDeleteLine; const printInsertLine = ( line, isFirstOrLast, { bColor, bIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder } ) => printDiffLine( line, isFirstOrLast, bColor, bIndicator, changeLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder ); exports.printInsertLine = printInsertLine; const printCommonLine = ( line, isFirstOrLast, { commonColor, commonIndicator, commonLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder } ) => printDiffLine( line, isFirstOrLast, commonColor, commonIndicator, commonLineTrailingSpaceColor, emptyFirstOrLastLinePlaceholder ); exports.printCommonLine = printCommonLine; const hasCommonDiff = (diffs, isMultiline) => { if (isMultiline) { // Important: Ignore common newline that was appended to multiline strings! const iLast = diffs.length - 1; return diffs.some( (diff, i) => diff[0] === _cleanupSemantic.DIFF_EQUAL && (i !== iLast || diff[1] !== '\n') ); } return diffs.some(diff => diff[0] === _cleanupSemantic.DIFF_EQUAL); }; exports.hasCommonDiff = hasCommonDiff; const countChanges = diffs => { let a = 0; let b = 0; diffs.forEach(diff => { switch (diff[0]) { case _cleanupSemantic.DIFF_DELETE: a += 1; break; case _cleanupSemantic.DIFF_INSERT: b += 1; break; } }); return { a, b }; }; exports.countChanges = countChanges; const printAnnotation = ( { aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator, includeChangeCounts, omitAnnotationLines }, changeCounts ) => { if (omitAnnotationLines) { return ''; } let aRest = ''; let bRest = ''; if (includeChangeCounts) { const aCount = String(changeCounts.a); const bCount = String(changeCounts.b); // Padding right aligns the ends of the annotations. const baAnnotationLengthDiff = bAnnotation.length - aAnnotation.length; const aAnnotationPadding = ' '.repeat(Math.max(0, baAnnotationLengthDiff)); const bAnnotationPadding = ' '.repeat(Math.max(0, -baAnnotationLengthDiff)); // Padding left aligns the ends of the counts. const baCountLengthDiff = bCount.length - aCount.length; const aCountPadding = ' '.repeat(Math.max(0, baCountLengthDiff)); const bCountPadding = ' '.repeat(Math.max(0, -baCountLengthDiff)); aRest = aAnnotationPadding + ' ' + aIndicator + ' ' + aCountPadding + aCount; bRest = bAnnotationPadding + ' ' + bIndicator + ' ' + bCountPadding + bCount; } return ( aColor(aIndicator + ' ' + aAnnotation + aRest) + '\n' + bColor(bIndicator + ' ' + bAnnotation + bRest) + '\n\n' ); }; exports.printAnnotation = printAnnotation; const printDiffLines = (diffs, options) => printAnnotation(options, countChanges(diffs)) + (options.expand ? (0, _joinAlignedDiffs.joinAlignedDiffsExpand)(diffs, options) : (0, _joinAlignedDiffs.joinAlignedDiffsNoExpand)(diffs, options)); // In GNU diff format, indexes are one-based instead of zero-based. exports.printDiffLines = printDiffLines; const createPatchMark = (aStart, aEnd, bStart, bEnd, {patchColor}) => patchColor( `@@ -${aStart + 1},${aEnd - aStart} +${bStart + 1},${bEnd - bStart} @@` ); // Compare two strings character-by-character. // Format as comparison lines in which changed substrings have inverse colors. exports.createPatchMark = createPatchMark; const diffStringsUnified = (a, b, options) => { if (a !== b && a.length !== 0 && b.length !== 0) { const isMultiline = a.includes('\n') || b.includes('\n'); // getAlignedDiffs assumes that a newline was appended to the strings. const diffs = diffStringsRaw( isMultiline ? a + '\n' : a, isMultiline ? b + '\n' : b, true // cleanupSemantic ); if (hasCommonDiff(diffs, isMultiline)) { const optionsNormalized = (0, _normalizeDiffOptions.normalizeDiffOptions)( options ); const lines = (0, _getAlignedDiffs.default)( diffs, optionsNormalized.changeColor ); return printDiffLines(lines, optionsNormalized); } } // Fall back to line-by-line diff. return (0, _diffLines.diffLinesUnified)( a.split('\n'), b.split('\n'), options ); }; // Compare two strings character-by-character. // Optionally clean up small common substrings, also known as chaff. exports.diffStringsUnified = diffStringsUnified; const diffStringsRaw = (a, b, cleanup) => { const diffs = (0, _diffStrings.default)(a, b); if (cleanup) { (0, _cleanupSemantic.cleanupSemantic)(diffs); // impure function } return diffs; }; exports.diffStringsRaw = diffStringsRaw;