Spaces:
Paused
Paused
| import { format, plugins } from 'pretty-format'; | |
| import * as diff$1 from 'diff-sequences'; | |
| import { g as getColors } from './chunk-colors.js'; | |
| function getType(value) { | |
| if (value === void 0) { | |
| return "undefined"; | |
| } else if (value === null) { | |
| return "null"; | |
| } else if (Array.isArray(value)) { | |
| return "array"; | |
| } else if (typeof value === "boolean") { | |
| return "boolean"; | |
| } else if (typeof value === "function") { | |
| return "function"; | |
| } else if (typeof value === "number") { | |
| return "number"; | |
| } else if (typeof value === "string") { | |
| return "string"; | |
| } else if (typeof value === "bigint") { | |
| return "bigint"; | |
| } else if (typeof value === "object") { | |
| if (value != null) { | |
| if (value.constructor === RegExp) | |
| return "regexp"; | |
| else if (value.constructor === Map) | |
| return "map"; | |
| else if (value.constructor === Set) | |
| return "set"; | |
| else if (value.constructor === Date) | |
| return "date"; | |
| } | |
| return "object"; | |
| } else if (typeof value === "symbol") { | |
| return "symbol"; | |
| } | |
| throw new Error(`value of unknown type: ${value}`); | |
| } | |
| const DIFF_DELETE = -1; | |
| const DIFF_INSERT = 1; | |
| const DIFF_EQUAL = 0; | |
| class Diff { | |
| 0; | |
| 1; | |
| constructor(op, text) { | |
| this[0] = op; | |
| this[1] = text; | |
| } | |
| } | |
| const diff_commonPrefix = function(text1, text2) { | |
| if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) | |
| return 0; | |
| let pointermin = 0; | |
| let pointermax = Math.min(text1.length, text2.length); | |
| let pointermid = pointermax; | |
| let pointerstart = 0; | |
| while (pointermin < pointermid) { | |
| if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) { | |
| pointermin = pointermid; | |
| pointerstart = pointermin; | |
| } else { | |
| pointermax = pointermid; | |
| } | |
| pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); | |
| } | |
| return pointermid; | |
| }; | |
| const diff_commonSuffix = function(text1, text2) { | |
| if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) | |
| return 0; | |
| let pointermin = 0; | |
| let pointermax = Math.min(text1.length, text2.length); | |
| let pointermid = pointermax; | |
| let pointerend = 0; | |
| while (pointermin < pointermid) { | |
| if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) { | |
| pointermin = pointermid; | |
| pointerend = pointermin; | |
| } else { | |
| pointermax = pointermid; | |
| } | |
| pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin); | |
| } | |
| return pointermid; | |
| }; | |
| const diff_commonOverlap_ = function(text1, text2) { | |
| const text1_length = text1.length; | |
| const text2_length = text2.length; | |
| if (text1_length === 0 || text2_length === 0) | |
| return 0; | |
| if (text1_length > text2_length) | |
| text1 = text1.substring(text1_length - text2_length); | |
| else if (text1_length < text2_length) | |
| text2 = text2.substring(0, text1_length); | |
| const text_length = Math.min(text1_length, text2_length); | |
| if (text1 === text2) | |
| return text_length; | |
| let best = 0; | |
| let length = 1; | |
| while (true) { | |
| const pattern = text1.substring(text_length - length); | |
| const found = text2.indexOf(pattern); | |
| if (found === -1) | |
| return best; | |
| length += found; | |
| if (found === 0 || text1.substring(text_length - length) === text2.substring(0, length)) { | |
| best = length; | |
| length++; | |
| } | |
| } | |
| }; | |
| const diff_cleanupSemantic = function(diffs) { | |
| let changes = false; | |
| const equalities = []; | |
| let equalitiesLength = 0; | |
| let lastEquality = null; | |
| let pointer = 0; | |
| let length_insertions1 = 0; | |
| let length_deletions1 = 0; | |
| let length_insertions2 = 0; | |
| let length_deletions2 = 0; | |
| while (pointer < diffs.length) { | |
| if (diffs[pointer][0] === DIFF_EQUAL) { | |
| equalities[equalitiesLength++] = pointer; | |
| length_insertions1 = length_insertions2; | |
| length_deletions1 = length_deletions2; | |
| length_insertions2 = 0; | |
| length_deletions2 = 0; | |
| lastEquality = diffs[pointer][1]; | |
| } else { | |
| if (diffs[pointer][0] === DIFF_INSERT) | |
| length_insertions2 += diffs[pointer][1].length; | |
| else | |
| length_deletions2 += diffs[pointer][1].length; | |
| if (lastEquality && lastEquality.length <= Math.max(length_insertions1, length_deletions1) && lastEquality.length <= Math.max(length_insertions2, length_deletions2)) { | |
| diffs.splice(equalities[equalitiesLength - 1], 0, new Diff(DIFF_DELETE, lastEquality)); | |
| diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT; | |
| equalitiesLength--; | |
| equalitiesLength--; | |
| pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1; | |
| length_insertions1 = 0; | |
| length_deletions1 = 0; | |
| length_insertions2 = 0; | |
| length_deletions2 = 0; | |
| lastEquality = null; | |
| changes = true; | |
| } | |
| } | |
| pointer++; | |
| } | |
| if (changes) | |
| diff_cleanupMerge(diffs); | |
| diff_cleanupSemanticLossless(diffs); | |
| pointer = 1; | |
| while (pointer < diffs.length) { | |
| if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) { | |
| const deletion = diffs[pointer - 1][1]; | |
| const insertion = diffs[pointer][1]; | |
| const overlap_length1 = diff_commonOverlap_(deletion, insertion); | |
| const overlap_length2 = diff_commonOverlap_(insertion, deletion); | |
| if (overlap_length1 >= overlap_length2) { | |
| if (overlap_length1 >= deletion.length / 2 || overlap_length1 >= insertion.length / 2) { | |
| diffs.splice(pointer, 0, new Diff(DIFF_EQUAL, insertion.substring(0, overlap_length1))); | |
| diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlap_length1); | |
| diffs[pointer + 1][1] = insertion.substring(overlap_length1); | |
| pointer++; | |
| } | |
| } else { | |
| if (overlap_length2 >= deletion.length / 2 || overlap_length2 >= insertion.length / 2) { | |
| diffs.splice(pointer, 0, new Diff(DIFF_EQUAL, deletion.substring(0, overlap_length2))); | |
| diffs[pointer - 1][0] = DIFF_INSERT; | |
| diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlap_length2); | |
| diffs[pointer + 1][0] = DIFF_DELETE; | |
| diffs[pointer + 1][1] = deletion.substring(overlap_length2); | |
| pointer++; | |
| } | |
| } | |
| pointer++; | |
| } | |
| pointer++; | |
| } | |
| }; | |
| const nonAlphaNumericRegex_ = /[^a-zA-Z0-9]/; | |
| const whitespaceRegex_ = /\s/; | |
| const linebreakRegex_ = /[\r\n]/; | |
| const blanklineEndRegex_ = /\n\r?\n$/; | |
| const blanklineStartRegex_ = /^\r?\n\r?\n/; | |
| function diff_cleanupSemanticLossless(diffs) { | |
| function diff_cleanupSemanticScore_(one, two) { | |
| if (!one || !two) { | |
| return 6; | |
| } | |
| const char1 = one.charAt(one.length - 1); | |
| const char2 = two.charAt(0); | |
| const nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_); | |
| const nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_); | |
| const whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_); | |
| const whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_); | |
| const lineBreak1 = whitespace1 && char1.match(linebreakRegex_); | |
| const lineBreak2 = whitespace2 && char2.match(linebreakRegex_); | |
| const blankLine1 = lineBreak1 && one.match(blanklineEndRegex_); | |
| const blankLine2 = lineBreak2 && two.match(blanklineStartRegex_); | |
| if (blankLine1 || blankLine2) { | |
| return 5; | |
| } else if (lineBreak1 || lineBreak2) { | |
| return 4; | |
| } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) { | |
| return 3; | |
| } else if (whitespace1 || whitespace2) { | |
| return 2; | |
| } else if (nonAlphaNumeric1 || nonAlphaNumeric2) { | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| let pointer = 1; | |
| while (pointer < diffs.length - 1) { | |
| if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) { | |
| let equality1 = diffs[pointer - 1][1]; | |
| let edit = diffs[pointer][1]; | |
| let equality2 = diffs[pointer + 1][1]; | |
| const commonOffset = diff_commonSuffix(equality1, edit); | |
| if (commonOffset) { | |
| const commonString = edit.substring(edit.length - commonOffset); | |
| equality1 = equality1.substring(0, equality1.length - commonOffset); | |
| edit = commonString + edit.substring(0, edit.length - commonOffset); | |
| equality2 = commonString + equality2; | |
| } | |
| let bestEquality1 = equality1; | |
| let bestEdit = edit; | |
| let bestEquality2 = equality2; | |
| let bestScore = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2); | |
| while (edit.charAt(0) === equality2.charAt(0)) { | |
| equality1 += edit.charAt(0); | |
| edit = edit.substring(1) + equality2.charAt(0); | |
| equality2 = equality2.substring(1); | |
| const score = diff_cleanupSemanticScore_(equality1, edit) + diff_cleanupSemanticScore_(edit, equality2); | |
| if (score >= bestScore) { | |
| bestScore = score; | |
| bestEquality1 = equality1; | |
| bestEdit = edit; | |
| bestEquality2 = equality2; | |
| } | |
| } | |
| if (diffs[pointer - 1][1] !== bestEquality1) { | |
| if (bestEquality1) { | |
| diffs[pointer - 1][1] = bestEquality1; | |
| } else { | |
| diffs.splice(pointer - 1, 1); | |
| pointer--; | |
| } | |
| diffs[pointer][1] = bestEdit; | |
| if (bestEquality2) { | |
| diffs[pointer + 1][1] = bestEquality2; | |
| } else { | |
| diffs.splice(pointer + 1, 1); | |
| pointer--; | |
| } | |
| } | |
| } | |
| pointer++; | |
| } | |
| } | |
| function diff_cleanupMerge(diffs) { | |
| diffs.push(new Diff(DIFF_EQUAL, "")); | |
| let pointer = 0; | |
| let count_delete = 0; | |
| let count_insert = 0; | |
| let text_delete = ""; | |
| let text_insert = ""; | |
| let commonlength; | |
| while (pointer < diffs.length) { | |
| switch (diffs[pointer][0]) { | |
| case DIFF_INSERT: | |
| count_insert++; | |
| text_insert += diffs[pointer][1]; | |
| pointer++; | |
| break; | |
| case DIFF_DELETE: | |
| count_delete++; | |
| text_delete += diffs[pointer][1]; | |
| pointer++; | |
| break; | |
| case DIFF_EQUAL: | |
| if (count_delete + count_insert > 1) { | |
| if (count_delete !== 0 && count_insert !== 0) { | |
| commonlength = diff_commonPrefix(text_insert, text_delete); | |
| if (commonlength !== 0) { | |
| if (pointer - count_delete - count_insert > 0 && diffs[pointer - count_delete - count_insert - 1][0] === DIFF_EQUAL) { | |
| diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength); | |
| } else { | |
| diffs.splice(0, 0, new Diff(DIFF_EQUAL, text_insert.substring(0, commonlength))); | |
| pointer++; | |
| } | |
| text_insert = text_insert.substring(commonlength); | |
| text_delete = text_delete.substring(commonlength); | |
| } | |
| commonlength = diff_commonSuffix(text_insert, text_delete); | |
| if (commonlength !== 0) { | |
| diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1]; | |
| text_insert = text_insert.substring(0, text_insert.length - commonlength); | |
| text_delete = text_delete.substring(0, text_delete.length - commonlength); | |
| } | |
| } | |
| pointer -= count_delete + count_insert; | |
| diffs.splice(pointer, count_delete + count_insert); | |
| if (text_delete.length) { | |
| diffs.splice(pointer, 0, new Diff(DIFF_DELETE, text_delete)); | |
| pointer++; | |
| } | |
| if (text_insert.length) { | |
| diffs.splice(pointer, 0, new Diff(DIFF_INSERT, text_insert)); | |
| pointer++; | |
| } | |
| pointer++; | |
| } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) { | |
| diffs[pointer - 1][1] += diffs[pointer][1]; | |
| diffs.splice(pointer, 1); | |
| } else { | |
| pointer++; | |
| } | |
| count_insert = 0; | |
| count_delete = 0; | |
| text_delete = ""; | |
| text_insert = ""; | |
| break; | |
| } | |
| } | |
| if (diffs[diffs.length - 1][1] === "") | |
| diffs.pop(); | |
| let changes = false; | |
| pointer = 1; | |
| while (pointer < diffs.length - 1) { | |
| if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) { | |
| if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) { | |
| diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length); | |
| diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1]; | |
| diffs.splice(pointer - 1, 1); | |
| changes = true; | |
| } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) { | |
| diffs[pointer - 1][1] += diffs[pointer + 1][1]; | |
| diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1]; | |
| diffs.splice(pointer + 1, 1); | |
| changes = true; | |
| } | |
| } | |
| pointer++; | |
| } | |
| if (changes) | |
| diff_cleanupMerge(diffs); | |
| } | |
| const NO_DIFF_MESSAGE = "Compared values have no visual difference."; | |
| const SIMILAR_MESSAGE = "Compared values serialize to the same structure.\nPrinting internal object structure without calling `toJSON` instead."; | |
| function formatTrailingSpaces(line, trailingSpaceFormatter) { | |
| return line.replace(/\s+$/, (match) => trailingSpaceFormatter(match)); | |
| } | |
| function printDiffLine(line, isFirstOrLast, color, indicator, trailingSpaceFormatter, emptyFirstOrLastLinePlaceholder) { | |
| return line.length !== 0 ? color( | |
| `${indicator} ${formatTrailingSpaces(line, trailingSpaceFormatter)}` | |
| ) : indicator !== " " ? color(indicator) : isFirstOrLast && emptyFirstOrLastLinePlaceholder.length !== 0 ? color(`${indicator} ${emptyFirstOrLastLinePlaceholder}`) : ""; | |
| } | |
| function printDeleteLine(line, isFirstOrLast, { | |
| aColor, | |
| aIndicator, | |
| changeLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| }) { | |
| return printDiffLine( | |
| line, | |
| isFirstOrLast, | |
| aColor, | |
| aIndicator, | |
| changeLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| ); | |
| } | |
| function printInsertLine(line, isFirstOrLast, { | |
| bColor, | |
| bIndicator, | |
| changeLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| }) { | |
| return printDiffLine( | |
| line, | |
| isFirstOrLast, | |
| bColor, | |
| bIndicator, | |
| changeLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| ); | |
| } | |
| function printCommonLine(line, isFirstOrLast, { | |
| commonColor, | |
| commonIndicator, | |
| commonLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| }) { | |
| return printDiffLine( | |
| line, | |
| isFirstOrLast, | |
| commonColor, | |
| commonIndicator, | |
| commonLineTrailingSpaceColor, | |
| emptyFirstOrLastLinePlaceholder | |
| ); | |
| } | |
| function createPatchMark(aStart, aEnd, bStart, bEnd, { patchColor }) { | |
| return patchColor( | |
| `@@ -${aStart + 1},${aEnd - aStart} +${bStart + 1},${bEnd - bStart} @@` | |
| ); | |
| } | |
| function joinAlignedDiffsNoExpand(diffs, options) { | |
| const iLength = diffs.length; | |
| const nContextLines = options.contextLines; | |
| const nContextLines2 = nContextLines + nContextLines; | |
| let jLength = iLength; | |
| let hasExcessAtStartOrEnd = false; | |
| let nExcessesBetweenChanges = 0; | |
| let i = 0; | |
| while (i !== iLength) { | |
| const iStart = i; | |
| while (i !== iLength && diffs[i][0] === DIFF_EQUAL) | |
| i += 1; | |
| if (iStart !== i) { | |
| if (iStart === 0) { | |
| if (i > nContextLines) { | |
| jLength -= i - nContextLines; | |
| hasExcessAtStartOrEnd = true; | |
| } | |
| } else if (i === iLength) { | |
| const n = i - iStart; | |
| if (n > nContextLines) { | |
| jLength -= n - nContextLines; | |
| hasExcessAtStartOrEnd = true; | |
| } | |
| } else { | |
| const n = i - iStart; | |
| if (n > nContextLines2) { | |
| jLength -= n - nContextLines2; | |
| nExcessesBetweenChanges += 1; | |
| } | |
| } | |
| } | |
| while (i !== iLength && diffs[i][0] !== DIFF_EQUAL) | |
| i += 1; | |
| } | |
| const hasPatch = nExcessesBetweenChanges !== 0 || hasExcessAtStartOrEnd; | |
| if (nExcessesBetweenChanges !== 0) | |
| jLength += nExcessesBetweenChanges + 1; | |
| else if (hasExcessAtStartOrEnd) | |
| jLength += 1; | |
| const jLast = jLength - 1; | |
| const lines = []; | |
| let jPatchMark = 0; | |
| if (hasPatch) | |
| lines.push(""); | |
| let aStart = 0; | |
| let bStart = 0; | |
| let aEnd = 0; | |
| let bEnd = 0; | |
| const pushCommonLine = (line) => { | |
| const j = lines.length; | |
| lines.push(printCommonLine(line, j === 0 || j === jLast, options)); | |
| aEnd += 1; | |
| bEnd += 1; | |
| }; | |
| const pushDeleteLine = (line) => { | |
| const j = lines.length; | |
| lines.push(printDeleteLine(line, j === 0 || j === jLast, options)); | |
| aEnd += 1; | |
| }; | |
| const pushInsertLine = (line) => { | |
| const j = lines.length; | |
| lines.push(printInsertLine(line, j === 0 || j === jLast, options)); | |
| bEnd += 1; | |
| }; | |
| i = 0; | |
| while (i !== iLength) { | |
| let iStart = i; | |
| while (i !== iLength && diffs[i][0] === DIFF_EQUAL) | |
| i += 1; | |
| if (iStart !== i) { | |
| if (iStart === 0) { | |
| 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) { | |
| const iEnd = i - iStart > nContextLines ? iStart + nContextLines : i; | |
| for (let iCommon = iStart; iCommon !== iEnd; iCommon += 1) | |
| pushCommonLine(diffs[iCommon][1]); | |
| } else { | |
| 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] = createPatchMark( | |
| aStart, | |
| aEnd, | |
| bStart, | |
| bEnd, | |
| options | |
| ); | |
| jPatchMark = lines.length; | |
| lines.push(""); | |
| 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] === DIFF_DELETE) { | |
| pushDeleteLine(diffs[i][1]); | |
| i += 1; | |
| } | |
| while (i !== iLength && diffs[i][0] === DIFF_INSERT) { | |
| pushInsertLine(diffs[i][1]); | |
| i += 1; | |
| } | |
| } | |
| if (hasPatch) | |
| lines[jPatchMark] = createPatchMark(aStart, aEnd, bStart, bEnd, options); | |
| return lines.join("\n"); | |
| } | |
| function joinAlignedDiffsExpand(diffs, options) { | |
| return diffs.map((diff, i, diffs2) => { | |
| const line = diff[1]; | |
| const isFirstOrLast = i === 0 || i === diffs2.length - 1; | |
| switch (diff[0]) { | |
| case DIFF_DELETE: | |
| return printDeleteLine(line, isFirstOrLast, options); | |
| case DIFF_INSERT: | |
| return printInsertLine(line, isFirstOrLast, options); | |
| default: | |
| return printCommonLine(line, isFirstOrLast, options); | |
| } | |
| }).join("\n"); | |
| } | |
| const noColor = (string) => string; | |
| const DIFF_CONTEXT_DEFAULT = 5; | |
| const DIFF_TRUNCATE_THRESHOLD_DEFAULT = 0; | |
| function getDefaultOptions() { | |
| const c = getColors(); | |
| return { | |
| aAnnotation: "Expected", | |
| aColor: c.green, | |
| aIndicator: "-", | |
| bAnnotation: "Received", | |
| bColor: c.red, | |
| bIndicator: "+", | |
| changeColor: c.inverse, | |
| changeLineTrailingSpaceColor: noColor, | |
| commonColor: c.dim, | |
| commonIndicator: " ", | |
| commonLineTrailingSpaceColor: noColor, | |
| compareKeys: void 0, | |
| contextLines: DIFF_CONTEXT_DEFAULT, | |
| emptyFirstOrLastLinePlaceholder: "", | |
| expand: true, | |
| includeChangeCounts: false, | |
| omitAnnotationLines: false, | |
| patchColor: c.yellow, | |
| truncateThreshold: DIFF_TRUNCATE_THRESHOLD_DEFAULT, | |
| truncateAnnotation: "... Diff result is truncated", | |
| truncateAnnotationColor: noColor | |
| }; | |
| } | |
| function getCompareKeys(compareKeys) { | |
| return compareKeys && typeof compareKeys === "function" ? compareKeys : void 0; | |
| } | |
| function getContextLines(contextLines) { | |
| return typeof contextLines === "number" && Number.isSafeInteger(contextLines) && contextLines >= 0 ? contextLines : DIFF_CONTEXT_DEFAULT; | |
| } | |
| function normalizeDiffOptions(options = {}) { | |
| return { | |
| ...getDefaultOptions(), | |
| ...options, | |
| compareKeys: getCompareKeys(options.compareKeys), | |
| contextLines: getContextLines(options.contextLines) | |
| }; | |
| } | |
| function isEmptyString(lines) { | |
| return lines.length === 1 && lines[0].length === 0; | |
| } | |
| function countChanges(diffs) { | |
| let a = 0; | |
| let b = 0; | |
| diffs.forEach((diff2) => { | |
| switch (diff2[0]) { | |
| case DIFF_DELETE: | |
| a += 1; | |
| break; | |
| case DIFF_INSERT: | |
| b += 1; | |
| break; | |
| } | |
| }); | |
| return { a, b }; | |
| } | |
| function 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); | |
| const baAnnotationLengthDiff = bAnnotation.length - aAnnotation.length; | |
| const aAnnotationPadding = " ".repeat(Math.max(0, baAnnotationLengthDiff)); | |
| const bAnnotationPadding = " ".repeat(Math.max(0, -baAnnotationLengthDiff)); | |
| 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}`; | |
| } | |
| const a = `${aIndicator} ${aAnnotation}${aRest}`; | |
| const b = `${bIndicator} ${bAnnotation}${bRest}`; | |
| return `${aColor(a)} | |
| ${bColor(b)} | |
| `; | |
| } | |
| function printDiffLines(diffs, truncated, options) { | |
| return printAnnotation(options, countChanges(diffs)) + (options.expand ? joinAlignedDiffsExpand(diffs, options) : joinAlignedDiffsNoExpand(diffs, options)) + (truncated ? options.truncateAnnotationColor(` | |
| ${options.truncateAnnotation}`) : ""); | |
| } | |
| function diffLinesUnified(aLines, bLines, options) { | |
| const normalizedOptions = normalizeDiffOptions(options); | |
| const [diffs, truncated] = diffLinesRaw( | |
| isEmptyString(aLines) ? [] : aLines, | |
| isEmptyString(bLines) ? [] : bLines, | |
| normalizedOptions | |
| ); | |
| return printDiffLines( | |
| diffs, | |
| truncated, | |
| normalizedOptions | |
| ); | |
| } | |
| function diffLinesUnified2(aLinesDisplay, bLinesDisplay, aLinesCompare, bLinesCompare, options) { | |
| if (isEmptyString(aLinesDisplay) && isEmptyString(aLinesCompare)) { | |
| aLinesDisplay = []; | |
| aLinesCompare = []; | |
| } | |
| if (isEmptyString(bLinesDisplay) && isEmptyString(bLinesCompare)) { | |
| bLinesDisplay = []; | |
| bLinesCompare = []; | |
| } | |
| if (aLinesDisplay.length !== aLinesCompare.length || bLinesDisplay.length !== bLinesCompare.length) { | |
| return diffLinesUnified(aLinesDisplay, bLinesDisplay, options); | |
| } | |
| const [diffs, truncated] = diffLinesRaw(aLinesCompare, bLinesCompare, options); | |
| let aIndex = 0; | |
| let bIndex = 0; | |
| diffs.forEach((diff2) => { | |
| switch (diff2[0]) { | |
| case DIFF_DELETE: | |
| diff2[1] = aLinesDisplay[aIndex]; | |
| aIndex += 1; | |
| break; | |
| case DIFF_INSERT: | |
| diff2[1] = bLinesDisplay[bIndex]; | |
| bIndex += 1; | |
| break; | |
| default: | |
| diff2[1] = bLinesDisplay[bIndex]; | |
| aIndex += 1; | |
| bIndex += 1; | |
| } | |
| }); | |
| return printDiffLines(diffs, truncated, normalizeDiffOptions(options)); | |
| } | |
| function diffLinesRaw(aLines, bLines, options) { | |
| const truncate = (options == null ? void 0 : options.truncateThreshold) ?? false; | |
| const truncateThreshold = Math.max(Math.floor((options == null ? void 0 : options.truncateThreshold) ?? 0), 0); | |
| const aLength = truncate ? Math.min(aLines.length, truncateThreshold) : aLines.length; | |
| const bLength = truncate ? Math.min(bLines.length, truncateThreshold) : bLines.length; | |
| const truncated = aLength !== aLines.length || bLength !== bLines.length; | |
| const isCommon = (aIndex2, bIndex2) => aLines[aIndex2] === bLines[bIndex2]; | |
| const diffs = []; | |
| let aIndex = 0; | |
| let bIndex = 0; | |
| const foundSubsequence = (nCommon, aCommon, bCommon) => { | |
| for (; aIndex !== aCommon; aIndex += 1) | |
| diffs.push(new Diff(DIFF_DELETE, aLines[aIndex])); | |
| for (; bIndex !== bCommon; bIndex += 1) | |
| diffs.push(new Diff(DIFF_INSERT, bLines[bIndex])); | |
| for (; nCommon !== 0; nCommon -= 1, aIndex += 1, bIndex += 1) | |
| diffs.push(new Diff(DIFF_EQUAL, bLines[bIndex])); | |
| }; | |
| const diffSequences = diff$1.default.default || diff$1.default; | |
| diffSequences(aLength, bLength, isCommon, foundSubsequence); | |
| for (; aIndex !== aLength; aIndex += 1) | |
| diffs.push(new Diff(DIFF_DELETE, aLines[aIndex])); | |
| for (; bIndex !== bLength; bIndex += 1) | |
| diffs.push(new Diff(DIFF_INSERT, bLines[bIndex])); | |
| return [diffs, truncated]; | |
| } | |
| function getNewLineSymbol(string) { | |
| return string.includes("\r\n") ? "\r\n" : "\n"; | |
| } | |
| function diffStrings(a, b, options) { | |
| const truncate = (options == null ? void 0 : options.truncateThreshold) ?? false; | |
| const truncateThreshold = Math.max(Math.floor((options == null ? void 0 : options.truncateThreshold) ?? 0), 0); | |
| let aLength = a.length; | |
| let bLength = b.length; | |
| if (truncate) { | |
| const aMultipleLines = a.includes("\n"); | |
| const bMultipleLines = b.includes("\n"); | |
| const aNewLineSymbol = getNewLineSymbol(a); | |
| const bNewLineSymbol = getNewLineSymbol(b); | |
| const _a = aMultipleLines ? `${a.split(aNewLineSymbol, truncateThreshold).join(aNewLineSymbol)} | |
| ` : a; | |
| const _b = bMultipleLines ? `${b.split(bNewLineSymbol, truncateThreshold).join(bNewLineSymbol)} | |
| ` : b; | |
| aLength = _a.length; | |
| bLength = _b.length; | |
| } | |
| const truncated = aLength !== a.length || bLength !== b.length; | |
| const isCommon = (aIndex2, bIndex2) => a[aIndex2] === b[bIndex2]; | |
| let aIndex = 0; | |
| let bIndex = 0; | |
| const diffs = []; | |
| const foundSubsequence = (nCommon, aCommon, bCommon) => { | |
| if (aIndex !== aCommon) | |
| diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex, aCommon))); | |
| if (bIndex !== bCommon) | |
| diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex, bCommon))); | |
| aIndex = aCommon + nCommon; | |
| bIndex = bCommon + nCommon; | |
| diffs.push(new Diff(DIFF_EQUAL, b.slice(bCommon, bIndex))); | |
| }; | |
| const diffSequences = diff$1.default.default || diff$1.default; | |
| diffSequences(aLength, bLength, isCommon, foundSubsequence); | |
| if (aIndex !== aLength) | |
| diffs.push(new Diff(DIFF_DELETE, a.slice(aIndex))); | |
| if (bIndex !== bLength) | |
| diffs.push(new Diff(DIFF_INSERT, b.slice(bIndex))); | |
| return [diffs, truncated]; | |
| } | |
| function concatenateRelevantDiffs(op, diffs, changeColor) { | |
| return diffs.reduce( | |
| (reduced, diff) => reduced + (diff[0] === DIFF_EQUAL ? diff[1] : diff[0] === op && diff[1].length !== 0 ? changeColor(diff[1]) : ""), | |
| "" | |
| ); | |
| } | |
| class ChangeBuffer { | |
| op; | |
| line; | |
| // incomplete line | |
| lines; | |
| // complete lines | |
| changeColor; | |
| constructor(op, changeColor) { | |
| this.op = op; | |
| this.line = []; | |
| this.lines = []; | |
| this.changeColor = changeColor; | |
| } | |
| pushSubstring(substring) { | |
| this.pushDiff(new Diff(this.op, substring)); | |
| } | |
| pushLine() { | |
| this.lines.push( | |
| this.line.length !== 1 ? new Diff( | |
| this.op, | |
| concatenateRelevantDiffs(this.op, this.line, this.changeColor) | |
| ) : this.line[0][0] === this.op ? this.line[0] : new Diff(this.op, this.line[0][1]) | |
| // was common diff | |
| ); | |
| this.line.length = 0; | |
| } | |
| isLineEmpty() { | |
| return this.line.length === 0; | |
| } | |
| // Minor input to buffer. | |
| pushDiff(diff) { | |
| this.line.push(diff); | |
| } | |
| // Main input to buffer. | |
| align(diff) { | |
| const string = diff[1]; | |
| if (string.includes("\n")) { | |
| const substrings = string.split("\n"); | |
| const iLast = substrings.length - 1; | |
| substrings.forEach((substring, i) => { | |
| if (i < iLast) { | |
| this.pushSubstring(substring); | |
| this.pushLine(); | |
| } else if (substring.length !== 0) { | |
| this.pushSubstring(substring); | |
| } | |
| }); | |
| } else { | |
| this.pushDiff(diff); | |
| } | |
| } | |
| // Output from buffer. | |
| moveLinesTo(lines) { | |
| if (!this.isLineEmpty()) | |
| this.pushLine(); | |
| lines.push(...this.lines); | |
| this.lines.length = 0; | |
| } | |
| } | |
| class CommonBuffer { | |
| deleteBuffer; | |
| insertBuffer; | |
| lines; | |
| constructor(deleteBuffer, insertBuffer) { | |
| this.deleteBuffer = deleteBuffer; | |
| this.insertBuffer = insertBuffer; | |
| this.lines = []; | |
| } | |
| pushDiffCommonLine(diff) { | |
| this.lines.push(diff); | |
| } | |
| pushDiffChangeLines(diff) { | |
| const isDiffEmpty = diff[1].length === 0; | |
| if (!isDiffEmpty || this.deleteBuffer.isLineEmpty()) | |
| this.deleteBuffer.pushDiff(diff); | |
| if (!isDiffEmpty || this.insertBuffer.isLineEmpty()) | |
| this.insertBuffer.pushDiff(diff); | |
| } | |
| flushChangeLines() { | |
| this.deleteBuffer.moveLinesTo(this.lines); | |
| this.insertBuffer.moveLinesTo(this.lines); | |
| } | |
| // Input to buffer. | |
| align(diff) { | |
| const op = diff[0]; | |
| const string = diff[1]; | |
| if (string.includes("\n")) { | |
| const substrings = string.split("\n"); | |
| const iLast = substrings.length - 1; | |
| substrings.forEach((substring, i) => { | |
| if (i === 0) { | |
| const subdiff = new Diff(op, substring); | |
| if (this.deleteBuffer.isLineEmpty() && this.insertBuffer.isLineEmpty()) { | |
| this.flushChangeLines(); | |
| this.pushDiffCommonLine(subdiff); | |
| } else { | |
| this.pushDiffChangeLines(subdiff); | |
| this.flushChangeLines(); | |
| } | |
| } else if (i < iLast) { | |
| this.pushDiffCommonLine(new Diff(op, substring)); | |
| } else if (substring.length !== 0) { | |
| this.pushDiffChangeLines(new Diff(op, substring)); | |
| } | |
| }); | |
| } else { | |
| this.pushDiffChangeLines(diff); | |
| } | |
| } | |
| // Output from buffer. | |
| getLines() { | |
| this.flushChangeLines(); | |
| return this.lines; | |
| } | |
| } | |
| function getAlignedDiffs(diffs, changeColor) { | |
| const deleteBuffer = new ChangeBuffer(DIFF_DELETE, changeColor); | |
| const insertBuffer = new ChangeBuffer(DIFF_INSERT, changeColor); | |
| const commonBuffer = new CommonBuffer(deleteBuffer, insertBuffer); | |
| diffs.forEach((diff) => { | |
| switch (diff[0]) { | |
| case DIFF_DELETE: | |
| deleteBuffer.align(diff); | |
| break; | |
| case DIFF_INSERT: | |
| insertBuffer.align(diff); | |
| break; | |
| default: | |
| commonBuffer.align(diff); | |
| } | |
| }); | |
| return commonBuffer.getLines(); | |
| } | |
| function hasCommonDiff(diffs, isMultiline) { | |
| if (isMultiline) { | |
| const iLast = diffs.length - 1; | |
| return diffs.some( | |
| (diff, i) => diff[0] === DIFF_EQUAL && (i !== iLast || diff[1] !== "\n") | |
| ); | |
| } | |
| return diffs.some((diff) => diff[0] === DIFF_EQUAL); | |
| } | |
| function diffStringsUnified(a, b, options) { | |
| if (a !== b && a.length !== 0 && b.length !== 0) { | |
| const isMultiline = a.includes("\n") || b.includes("\n"); | |
| const [diffs, truncated] = diffStringsRaw( | |
| isMultiline ? `${a} | |
| ` : a, | |
| isMultiline ? `${b} | |
| ` : b, | |
| true, | |
| // cleanupSemantic | |
| options | |
| ); | |
| if (hasCommonDiff(diffs, isMultiline)) { | |
| const optionsNormalized = normalizeDiffOptions(options); | |
| const lines = getAlignedDiffs(diffs, optionsNormalized.changeColor); | |
| return printDiffLines(lines, truncated, optionsNormalized); | |
| } | |
| } | |
| return diffLinesUnified(a.split("\n"), b.split("\n"), options); | |
| } | |
| function diffStringsRaw(a, b, cleanup, options) { | |
| const [diffs, truncated] = diffStrings(a, b, options); | |
| if (cleanup) | |
| diff_cleanupSemantic(diffs); | |
| return [diffs, truncated]; | |
| } | |
| function getCommonMessage(message, options) { | |
| const { commonColor } = normalizeDiffOptions(options); | |
| return commonColor(message); | |
| } | |
| const { | |
| AsymmetricMatcher, | |
| DOMCollection, | |
| DOMElement, | |
| Immutable, | |
| ReactElement, | |
| ReactTestComponent | |
| } = plugins; | |
| const PLUGINS = [ | |
| ReactTestComponent, | |
| ReactElement, | |
| DOMElement, | |
| DOMCollection, | |
| Immutable, | |
| AsymmetricMatcher | |
| ]; | |
| const FORMAT_OPTIONS = { | |
| plugins: PLUGINS | |
| }; | |
| const FALLBACK_FORMAT_OPTIONS = { | |
| callToJSON: false, | |
| maxDepth: 10, | |
| plugins: PLUGINS | |
| }; | |
| function diff(a, b, options) { | |
| if (Object.is(a, b)) | |
| return ""; | |
| const aType = getType(a); | |
| let expectedType = aType; | |
| let omitDifference = false; | |
| if (aType === "object" && typeof a.asymmetricMatch === "function") { | |
| if (a.$$typeof !== Symbol.for("jest.asymmetricMatcher")) { | |
| return null; | |
| } | |
| if (typeof a.getExpectedType !== "function") { | |
| return null; | |
| } | |
| expectedType = a.getExpectedType(); | |
| omitDifference = expectedType === "string"; | |
| } | |
| if (expectedType !== getType(b)) { | |
| const { aAnnotation, aColor, aIndicator, bAnnotation, bColor, bIndicator } = normalizeDiffOptions(options); | |
| const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options); | |
| const aDisplay = format(a, formatOptions); | |
| const bDisplay = format(b, formatOptions); | |
| const aDiff = `${aColor(`${aIndicator} ${aAnnotation}:`)} | |
| ${aDisplay}`; | |
| const bDiff = `${bColor(`${bIndicator} ${bAnnotation}:`)} | |
| ${bDisplay}`; | |
| return `${aDiff} | |
| ${bDiff}`; | |
| } | |
| if (omitDifference) | |
| return null; | |
| switch (aType) { | |
| case "string": | |
| return diffLinesUnified(a.split("\n"), b.split("\n"), options); | |
| case "boolean": | |
| case "number": | |
| return comparePrimitive(a, b, options); | |
| case "map": | |
| return compareObjects(sortMap(a), sortMap(b), options); | |
| case "set": | |
| return compareObjects(sortSet(a), sortSet(b), options); | |
| default: | |
| return compareObjects(a, b, options); | |
| } | |
| } | |
| function comparePrimitive(a, b, options) { | |
| const aFormat = format(a, FORMAT_OPTIONS); | |
| const bFormat = format(b, FORMAT_OPTIONS); | |
| return aFormat === bFormat ? "" : diffLinesUnified(aFormat.split("\n"), bFormat.split("\n"), options); | |
| } | |
| function sortMap(map) { | |
| return new Map(Array.from(map.entries()).sort()); | |
| } | |
| function sortSet(set) { | |
| return new Set(Array.from(set.values()).sort()); | |
| } | |
| function compareObjects(a, b, options) { | |
| let difference; | |
| let hasThrown = false; | |
| try { | |
| const formatOptions = getFormatOptions(FORMAT_OPTIONS, options); | |
| difference = getObjectsDifference(a, b, formatOptions, options); | |
| } catch { | |
| hasThrown = true; | |
| } | |
| const noDiffMessage = getCommonMessage(NO_DIFF_MESSAGE, options); | |
| if (difference === void 0 || difference === noDiffMessage) { | |
| const formatOptions = getFormatOptions(FALLBACK_FORMAT_OPTIONS, options); | |
| difference = getObjectsDifference(a, b, formatOptions, options); | |
| if (difference !== noDiffMessage && !hasThrown) { | |
| difference = `${getCommonMessage( | |
| SIMILAR_MESSAGE, | |
| options | |
| )} | |
| ${difference}`; | |
| } | |
| } | |
| return difference; | |
| } | |
| function getFormatOptions(formatOptions, options) { | |
| const { compareKeys } = normalizeDiffOptions(options); | |
| return { | |
| ...formatOptions, | |
| compareKeys | |
| }; | |
| } | |
| function getObjectsDifference(a, b, formatOptions, options) { | |
| const formatOptionsZeroIndent = { ...formatOptions, indent: 0 }; | |
| const aCompare = format(a, formatOptionsZeroIndent); | |
| const bCompare = format(b, formatOptionsZeroIndent); | |
| if (aCompare === bCompare) { | |
| return getCommonMessage(NO_DIFF_MESSAGE, options); | |
| } else { | |
| const aDisplay = format(a, formatOptions); | |
| const bDisplay = format(b, formatOptions); | |
| return diffLinesUnified2( | |
| aDisplay.split("\n"), | |
| bDisplay.split("\n"), | |
| aCompare.split("\n"), | |
| bCompare.split("\n"), | |
| options | |
| ); | |
| } | |
| } | |
| export { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, Diff, diff, diffLinesRaw, diffLinesUnified, diffLinesUnified2, diffStringsRaw, diffStringsUnified }; | |