UNPKG

projen

Version:

CDK for software projects

170 lines 23.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unifiedDiff = unifiedDiff; const chalk_1 = require("chalk"); /** * Compute a unified diff between two strings with context lines, hunk headers, * and optional colorized output with character-level inline highlighting. * * @param oldContent the previous content. * @param newContent the new content. * @param colorize whether to colorize the output. * @param contextSize number of unchanged context lines around each change. * @returns the diff as an array of lines, or `undefined` if there are no changes. */ function unifiedDiff(oldContent, newContent, colorize, contextSize) { const oldLines = oldContent.split("\n"); const newLines = newContent.split("\n"); const edits = computeEdits(oldLines, newLines); // Find indices of changed edits const changeIndices = []; for (let i = 0; i < edits.length; i++) { if (edits[i].type !== "equal") { changeIndices.push(i); } } if (changeIndices.length === 0) { return undefined; } // Group changes into hunks with context, merging overlapping ones const hunks = []; for (const ci of changeIndices) { const start = Math.max(0, ci - contextSize); const end = Math.min(edits.length - 1, ci + contextSize); if (hunks.length > 0 && start <= hunks[hunks.length - 1].end + 1) { hunks[hunks.length - 1].end = end; } else { hunks.push({ start, end }); } } // Format hunks const output = []; for (const hunk of hunks) { // Compute line numbers for the header let oldStart = 1; let newStart = 1; for (let i = 0; i < hunk.start; i++) { const e = edits[i]; if (e.type === "equal" || e.type === "delete" || e.type === "replace") { oldStart++; } if (e.type === "equal" || e.type === "insert" || e.type === "replace") { newStart++; } } let oldCount = 0; let newCount = 0; for (let i = hunk.start; i <= hunk.end; i++) { const e = edits[i]; if (e.type === "equal" || e.type === "delete" || e.type === "replace") { oldCount++; } if (e.type === "equal" || e.type === "insert" || e.type === "replace") { newCount++; } } const header = `@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`; output.push(colorize ? (0, chalk_1.cyan)(header) : header); for (let i = hunk.start; i <= hunk.end; i++) { const e = edits[i]; switch (e.type) { case "equal": output.push(` ${oldLines[e.oldIdx]}`); break; case "delete": output.push(colorize ? `${chalk_1.bold.red("-")} ${(0, chalk_1.red)(oldLines[e.oldIdx])}` : `- ${oldLines[e.oldIdx]}`); break; case "insert": output.push(colorize ? `${chalk_1.bold.green("+")} ${(0, chalk_1.green)(newLines[e.newIdx])}` : `+ ${newLines[e.newIdx]}`); break; case "replace": output.push(...inlineDiff(oldLines[e.oldIdx], newLines[e.newIdx], colorize)); break; } } } return output; } /** * Compute edit operations between two arrays of lines using LCS. */ function computeEdits(oldLines, newLines) { const oldLen = oldLines.length; const newLen = newLines.length; // Build LCS table const lcs = Array.from({ length: oldLen + 1 }, () => new Array(newLen + 1).fill(0)); for (let i = oldLen - 1; i >= 0; i--) { for (let j = newLen - 1; j >= 0; j--) { if (oldLines[i] === newLines[j]) { lcs[i][j] = lcs[i + 1][j + 1] + 1; } else { lcs[i][j] = Math.max(lcs[i + 1][j], lcs[i][j + 1]); } } } // Walk the LCS table to produce edit operations const edits = []; let i = 0; let j = 0; while (i < oldLen || j < newLen) { if (i < oldLen && j < newLen && oldLines[i] === newLines[j]) { edits.push({ type: "equal", oldIdx: i, newIdx: j }); i++; j++; } else if (i < oldLen && j < newLen && lcs[i + 1][j] === lcs[i][j + 1]) { // Both sides advance equally — treat as a replacement edits.push({ type: "replace", oldIdx: i, newIdx: j }); i++; j++; } else if (j < newLen && (i >= oldLen || lcs[i][j + 1] >= lcs[i + 1][j])) { edits.push({ type: "insert", newIdx: j }); j++; } else { edits.push({ type: "delete", oldIdx: i }); i++; } } return edits; } /** * Produces a remove/add line pair with character-level highlighting * of the parts that changed. */ function inlineDiff(oldLine, newLine, colorize) { // Find common prefix and suffix let prefix = 0; while (prefix < oldLine.length && prefix < newLine.length && oldLine[prefix] === newLine[prefix]) { prefix++; } let oldSuffix = oldLine.length; let newSuffix = newLine.length; while (oldSuffix > prefix && newSuffix > prefix && oldLine[oldSuffix - 1] === newLine[newSuffix - 1]) { oldSuffix--; newSuffix--; } if (colorize) { const before = oldLine.substring(0, prefix); const after = oldLine.substring(oldSuffix); const oldChanged = oldLine.substring(prefix, oldSuffix); const newChanged = newLine.substring(prefix, newSuffix); return [ `${chalk_1.bold.red("-")} ${(0, chalk_1.red)(before)}${chalk_1.red.bold.underline(oldChanged)}${(0, chalk_1.red)(after)}`, `${chalk_1.bold.green("+")} ${(0, chalk_1.green)(before)}${chalk_1.green.bold.underline(newChanged)}${(0, chalk_1.green)(after)}`, ]; } return [`- ${oldLine}`, `+ ${newLine}`]; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlmZi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlsL2RpZmYudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFZQSxrQ0E4RkM7QUExR0QsaUNBQStDO0FBRS9DOzs7Ozs7Ozs7R0FTRztBQUNILFNBQWdCLFdBQVcsQ0FDekIsVUFBa0IsRUFDbEIsVUFBa0IsRUFDbEIsUUFBaUIsRUFDakIsV0FBbUI7SUFFbkIsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QyxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sS0FBSyxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFFL0MsZ0NBQWdDO0lBQ2hDLE1BQU0sYUFBYSxHQUFhLEVBQUUsQ0FBQztJQUNuQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3RDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUM5QixhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDSCxDQUFDO0lBQ0QsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQy9CLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxrRUFBa0U7SUFDbEUsTUFBTSxLQUFLLEdBQTBDLEVBQUUsQ0FBQztJQUN4RCxLQUFLLE1BQU0sRUFBRSxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQy9CLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxXQUFXLENBQUMsQ0FBQztRQUM1QyxNQUFNLEdBQUcsR0FBRyxJQUFJ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LEdBQUcsTUFBTSxFQUFFLENBQUM7UUFDaEMsSUFBSSxDQUFDLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxNQUFNLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzVELEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDcEQsQ0FBQyxFQUFFLENBQUM7WUFDSixDQUFDLEVBQUUsQ0FBQztRQUNOLENBQUM7YUFBTSxJQUFJLENBQUMsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN2RSxzREFBc0Q7WUFDdEQsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN0RCxDQUFDLEVBQUUsQ0FBQztZQUNKLENBQUMsRUFBRSxDQUFDO1FBQ04sQ0FBQzthQUFNLElBQUksQ0FBQyxHQUFHLE1BQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN6RSxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUMxQyxDQUFDLEVBQUUsQ0FBQztRQUNOLENBQUM7YUFBTSxDQUFDO1lBQ04sS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDMUMsQ0FBQyxFQUFFLENBQUM7UUFDTixDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsVUFBVSxDQUNqQixPQUFlLEVBQ2YsT0FBZSxFQUNmLFFBQWlCO0lBRWpCLGdDQUFnQztJQUNoQyxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDZixPQUNFLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTTtRQUN2QixNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU07UUFDdkIsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFDbkMsQ0FBQztRQUNELE1BQU0sRUFBRSxDQUFDO0lBQ1gsQ0FBQztJQUNELElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7SUFDL0IsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUMvQixPQUNFLFNBQVMsR0FBRyxNQUFNO1FBQ2xCLFNBQVMsR0FBRyxNQUFNO1FBQ2xCLE9BQU8sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLEtBQUssT0FBTyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsRUFDakQsQ0FBQztRQUNELFNBQVMsRUFBRSxDQUFDO1FBQ1osU0FBUyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUNiLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzVDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDM0MsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDeEQsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDeEQsT0FBTztZQUNMLEdBQUcsWUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFBLFdBQUcsRUFBQyxNQUFNLENBQUMsR0FBRyxXQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUFBLFdBQUcsRUFBQyxLQUFLLENBQUMsRUFBRTtZQUMvRSxHQUFHLFlBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksSUFBQSxhQUFLLEVBQUMsTUFBTSxDQUFDLEdBQUcsYUFBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsSUFBQSxhQUFLLEVBQUMsS0FBSyxDQUFDLEVBQUU7U0FDeEYsQ0FBQztJQUNKLENBQUM7SUFFRCxPQUFPLENBQUMsS0FBSyxPQUFPLEVBQUUsRUFBRSxLQUFLLE9BQU8sRUFBRSxDQUFDLENBQUM7QUFDMUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGJvbGQsIGN5YW4sIGdyZWVuLCByZWQgfSBmcm9tIFwiY2hhbGtcIjtcblxuLyoqXG4gKiBDb21wdXRlIGEgdW5pZmllZCBkaWZmIGJldHdlZW4gdHdvIHN0cmluZ3Mgd2l0aCBjb250ZXh0IGxpbmVzLCBodW5rIGhlYWRlcnMsXG4gKiBhbmQgb3B0aW9uYWwgY29sb3JpemVkIG91dHB1dCB3aXRoIGNoYXJhY3Rlci1sZXZlbCBpbmxpbmUgaGlnaGxpZ2h0aW5nLlxuICpcbiAqIEBwYXJhbSBvbGRDb250ZW50IHRoZSBwcmV2aW91cyBjb250ZW50LlxuICogQHBhcmFtIG5ld0NvbnRlbnQgdGhlIG5ldyBjb250ZW50LlxuICogQHBhcmFtIGNvbG9yaXplIHdoZXRoZXIgdG8gY29sb3JpemUgdGhlIG91dHB1dC5cbiAqIEBwYXJhbSBjb250ZXh0U2l6ZSBudW1iZXIgb2YgdW5jaGFuZ2VkIGNvbnRleHQgbGluZXMgYXJvdW5kIGVhY2ggY2hhbmdlLlxuICogQHJldHVybnMgdGhlIGRpZmYgYXMgYW4gYXJyYXkgb2YgbGluZXMsIG9yIGB1bmRlZmluZWRgIGlmIHRoZXJlIGFyZSBubyBjaGFuZ2VzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdW5pZmllZERpZmYoXG4gIG9sZENvbnRlbnQ6IHN0cmluZyxcbiAgbmV3Q29udGVudDogc3RyaW5nLFxuICBjb2xvcml6ZTogYm9vbGVhbixcbiAgY29udGV4dFNpemU6IG51bWJlcixcbik6IHN0cmluZ1tdIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qgb2xkTGluZXMgPSBvbGRDb250ZW50LnNwbGl0KFwiXFxuXCIpO1xuICBjb25zdCBuZXdMaW5lcyA9IG5ld0NvbnRlbnQuc3BsaXQoXCJcXG5cIik7XG4gIGNvbnN0IGVkaXRzID0gY29tcHV0ZUVkaXRzKG9sZExpbmVzLCBuZXdMaW5lcyk7XG5cbiAgLy8gRmluZCBpbmRpY2VzIG9mIGNoYW5nZWQgZWRpdHNcbiAgY29uc3QgY2hhbmdlSW5kaWNlczogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBlZGl0cy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChlZGl0c1tpXS50eXBlICE9PSBcImVxdWFsXCIpIHtcbiAgICAgIGNoYW5nZUluZGljZXMucHVzaChpKTtcbiAgICB9XG4gIH1cbiAgaWYgKGNoYW5nZUluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIEdyb3VwIGNoYW5nZXMgaW50byBodW5rcyB3aXRoIGNvbnRleHQsIG1lcmdpbmcgb3ZlcmxhcHBpbmcgb25lc1xuICBjb25zdCBodW5rczogQXJyYXk8eyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlciB9PiA9IFtdO1xuICBmb3IgKGNvbnN0IGNpIG9mIGNoYW5nZUluZGljZXMpIHtcbiAgICBjb25zdCBzdGFydCA9IE1hdGgubWF4KDAsIGNpIC0gY29udGV4dFNpemUpO1xuICAgIGNvbnN0IGVuZCA9IE1hdGgubWluKGVkaXRzLmxlbmd0aCAtIDEsIGNpICsgY29udGV4dFNpemUpO1xuICAgIGlmIChodW5rcy5sZW5ndGggPiAwICYmIHN0YXJ0IDw9IGh1bmtzW2h1bmtzLmxlbmd0aCAtIDFdLmVuZCArIDEpIHtcbiAgICAgIGh1bmtzW2h1bmtzLmxlbmd0aCAtIDFdLmVuZCA9IGVuZDtcbiAgICB9IGVsc2Uge1xuICAgICAgaHVua3MucHVzaCh7IHN0YXJ0LCBlbmQgfSk7XG4gICAgfVxuICB9XG5cbiAgLy8gRm9ybWF0IGh1bmtzXG4gIGNvbnN0IG91dHB1dDogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBodW5rIG9mIGh1bmtzKSB7XG4gICAgLy8gQ29tcHV0ZSBsaW5lIG51bWJlcnMgZm9yIHRoZSBoZWFkZXJcbiAgICBsZXQgb2xkU3RhcnQgPSAxO1xuICAgIGxldCBuZXdTdGFydCA9IDE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBodW5rLnN0YXJ0OyBpKyspIHtcbiAgICAgIGNvbnN0IGUgPSBlZGl0c1tpXTtcbiAgICAgIGlmIChlLnR5cGUgPT09IFwiZXF1YWxcIiB8fCBlLnR5cGUgPT09IFwiZGVsZXRlXCIgfHwgZS50eXBlID09PSBcInJlcGxhY2VcIikge1xuICAgICAgICBvbGRTdGFydCsrO1xuICAgICAgfVxuICAgICAgaWYgKGUudHlwZSA9PT0gXCJlcXVhbFwiIHx8IGUudHlwZSA9PT0gXCJpbnNlcnRcIiB8fCBlLnR5cGUgPT09IFwicmVwbGFjZVwiKSB7XG4gICAgICAgIG5ld1N0YXJ0Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IG9sZENvdW50ID0gMDtcbiAgICBsZXQgbmV3Q291bnQgPSAwO1xuICAgIGZvciAobGV0IGkgPSBodW5rLnN0YXJ0OyBpIDw9IGh1bmsuZW5kOyBpKyspIHtcbiAgICAgIGNvbnN0IGUgPSBlZGl0c1tpXTtcbiAgICAgIGlmIChlLnR5cGUgPT09IFwiZXF1YWxcIiB8fCBlLnR5cGUgPT09IFwiZGVsZXRlXCIgfHwgZS50eXBlID09PSBcInJlcGxhY2VcIikge1xuICAgICAgICBvbGRDb3VudCsrO1xuICAgICAgfVxuICAgICAgaWYgKGUudHlwZSA9PT0gXCJlcXVhbFwiIHx8IGUudHlwZSA9PT0gXCJpbnNlcnRcIiB8fCBlLnR5cGUgPT09IFwicmVwbGFjZVwiKSB7XG4gICAgICAgIG5ld0NvdW50Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZGVyID0gYEBAIC0ke29sZFN0YXJ0fSwke29sZENvdW50fSArJHtuZXdTdGFydH0sJHtuZXdDb3VudH0gQEBgO1xuICAgIG91dHB1dC5wdXNoKGNvbG9yaXplID8gY3lhbihoZWFkZXIpIDogaGVhZGVyKTtcblxuICAgIGZvciAobGV0IGkgPSBodW5rLnN0YXJ0OyBpIDw9IGh1bmsuZW5kOyBpKyspIHtcbiAgICAgIGNvbnN0IGUgPSBlZGl0c1tpXTtcbiAgICAgIHN3aXRjaCAoZS50eXBlKSB7XG4gICAgICAgIGNhc2UgXCJlcXVhbFwiOlxuICAgICAgICAgIG91dHB1dC5wdXNoKGAgICR7b2xkTGluZXNbZS5vbGRJZHhdfWApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiZGVsZXRlXCI6XG4gICAgICAgICAgb3V0cHV0LnB1c2goXG4gICAgICAgICAgICBjb2xvcml6ZVxuICAgICAgICAgICAgICA/IGAke2JvbGQucmVkKFwiLVwiKX0gJHtyZWQob2xkTGluZXNbZS5vbGRJZHhdKX1gXG4gICAgICAgICAgICAgIDogYC0gJHtvbGRMaW5lc1tlLm9sZElkeF19YCxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiaW5zZXJ0XCI6XG4gICAgICAgICAgb3V0cHV0LnB1c2goXG4gICAgICAgICAgICBjb2xvcml6ZVxuICAgICAgICAgICAgICA/IGAke2JvbGQuZ3JlZW4oXCIrXCIpfSAke2dyZWVuKG5ld0xpbmVzW2UubmV3SWR4XSl9YFxuICAgICAgICAgICAgICA6IGArICR7bmV3TGluZXNbZS5uZXdJZHhdfWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcInJlcGxhY2VcIjpcbiAgICAgICAgICBvdXRwdXQucHVzaChcbiAgICAgICAgICAgIC4uLmlubGluZURpZmYob2xkTGluZXNbZS5vbGRJZHhdLCBuZXdMaW5lc1tlLm5ld0lkeF0sIGNvbG9yaXplKSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59XG5cbnR5cGUgRWRpdE9wID1cbiAgfCB7IHR5cGU6IFwiZXF1YWxcIjsgb2xkSWR4OiBudW1iZXI7IG5ld0lkeDogbnVtYmVyIH1cbiAgfCB7IHR5cGU6IFwiZGVsZXRlXCI7IG9sZElkeDogbnVtYmVyIH1cbiAgfCB7IHR5cGU6IFwiaW5zZXJ0XCI7IG5ld0lkeDogbnVtYmVyIH1cbiAgfCB7IHR5cGU6IFwicmVwbGFjZVwiOyBvbGRJZHg6IG51bWJlcjsgbmV3SWR4OiBudW1iZXIgfTtcblxuLyoqXG4gKiBDb21wdXRlIGVkaXQgb3BlcmF0aW9ucyBiZXR3ZWVuIHR3byBhcnJheXMgb2YgbGluZXMgdXNpbmcgTENTLlxuICovXG5mdW5jdGlvbiBjb21wdXRlRWRpdHMob2xkTGluZXM6IHN0cmluZ1tdLCBuZXdMaW5lczogc3RyaW5nW10pOiBFZGl0T3BbXSB7XG4gIGNvbnN0IG9sZExlbiA9IG9sZExpbmVzLmxlbmd0aDtcbiAgY29uc3QgbmV3TGVuID0gbmV3TGluZXMubGVuZ3RoO1xuXG4gIC8vIEJ1aWxkIExDUyB0YWJsZVxuICBjb25zdCBsY3M6IG51bWJlcltdW10gPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBvbGRMZW4gKyAxIH0sICgpID0+XG4gICAgbmV3IEFycmF5KG5ld0xlbiArIDEpLmZpbGwoMCksXG4gICk7XG4gIGZvciAobGV0IGkgPSBvbGRMZW4gLSAxOyBpID49IDA7IGktLSkge1xuICAgIGZvciAobGV0IGogPSBuZXdMZW4gLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgaWYgKG9sZExpbmVzW2ldID09PSBuZXdMaW5lc1tqXSkge1xuICAgICAgICBsY3NbaV1bal0gPSBsY3NbaSArIDFdW2ogKyAxXSArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsY3NbaV1bal0gPSBNYXRoLm1heChsY3NbaSArIDFdW2pdLCBsY3NbaV1baiArIDFdKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBXYWxrIHRoZSBMQ1MgdGFibGUgdG8gcHJvZHVjZSBlZGl0IG9wZXJhdGlvbnNcbiAgY29uc3QgZWRpdHM6IEVkaXRPcFtdID0gW107XG4gIGxldCBpID0gMDtcbiAgbGV0IGogPSAwO1xuICB3aGlsZSAoaSA8IG9sZExlbiB8fCBqIDwgbmV3TGVuKSB7XG4gICAgaWYgKGkgPCBvbGRMZW4gJiYgaiA8IG5ld0xlbiAmJiBvbGRMaW5lc1tpXSA9PT0gbmV3TGluZXNbal0pIHtcbiAgICAgIGVkaXRzLnB1c2goeyB0eXBlOiBcImVxdWFsXCIsIG9sZElkeDogaSwgbmV3SWR4OiBqIH0pO1xuICAgICAgaSsrO1xuICAgICAgaisrO1xuICAgIH0gZWxzZSBpZiAoaSA8IG9sZExlbiAmJiBqIDwgbmV3TGVuICYmIGxjc1tpICsgMV1bal0gPT09IGxjc1tpXVtqICsgMV0pIHtcbiAgICAgIC8vIEJvdGggc2lkZXMgYWR2YW5jZSBlcXVhbGx5IOKAlCB0cmVhdCBhcyBhIHJlcGxhY2VtZW50XG4gICAgICBlZGl0cy5wdXNoKHsgdHlwZTogXCJyZXBsYWNlXCIsIG9sZElkeDogaSwgbmV3SWR4OiBqIH0pO1xuICAgICAgaSsrO1xuICAgICAgaisrO1xuICAgIH0gZWxzZSBpZiAoaiA8IG5ld0xlbiAmJiAoaSA+PSBvbGRMZW4gfHwgbGNzW2ldW2ogKyAxXSA+PSBsY3NbaSArIDFdW2pdKSkge1xuICAgICAgZWRpdHMucHVzaCh7IHR5cGU6IFwiaW5zZXJ0XCIsIG5ld0lkeDogaiB9KTtcbiAgICAgIGorKztcbiAgICB9IGVsc2Uge1xuICAgICAgZWRpdHMucHVzaCh7IHR5cGU6IFwiZGVsZXRlXCIsIG9sZElkeDogaSB9KTtcbiAgICAgIGkrKztcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZWRpdHM7XG59XG5cbi8qKlxuICogUHJvZHVjZXMgYSByZW1vdmUvYWRkIGxpbmUgcGFpciB3aXRoIGNoYXJhY3Rlci1sZXZlbCBoaWdobGlnaHRpbmdcbiAqIG9mIHRoZSBwYXJ0cyB0aGF0IGNoYW5nZWQuXG4gKi9cbmZ1bmN0aW9uIGlubGluZURpZmYoXG4gIG9sZExpbmU6IHN0cmluZyxcbiAgbmV3TGluZTogc3RyaW5nLFxuICBjb2xvcml6ZTogYm9vbGVhbixcbik6IHN0cmluZ1tdIHtcbiAgLy8gRmluZCBjb21tb24gcHJlZml4IGFuZCBzdWZmaXhcbiAgbGV0IHByZWZpeCA9IDA7XG4gIHdoaWxlIChcbiAgICBwcmVmaXggPCBvbGRMaW5lLmxlbmd0aCAmJlxuICAgIHByZWZpeCA8IG5ld0xpbmUubGVuZ3RoICYmXG4gICAgb2xkTGluZVtwcmVmaXhdID09PSBuZXdMaW5lW3ByZWZpeF1cbiAgKSB7XG4gICAgcHJlZml4Kys7XG4gIH1cbiAgbGV0IG9sZFN1ZmZpeCA9IG9sZExpbmUubGVuZ3RoO1xuICBsZXQgbmV3U3VmZml4ID0gbmV3TGluZS5sZW5ndGg7XG4gIHdoaWxlIChcbiAgICBvbGRTdWZmaXggPiBwcmVmaXggJiZcbiAgICBuZXdTdWZmaXggPiBwcmVmaXggJiZcbiAgICBvbGRMaW5lW29sZFN1ZmZpeCAtIDFdID09PSBuZXdMaW5lW25ld1N1ZmZpeCAtIDFdXG4gICkge1xuICAgIG9sZFN1ZmZpeC0tO1xuICAgIG5ld1N1ZmZpeC0tO1xuICB9XG5cbiAgaWYgKGNvbG9yaXplKSB7XG4gICAgY29uc3QgYmVmb3JlID0gb2xkTGluZS5zdWJzdHJpbmcoMCwgcHJlZml4KTtcbiAgICBjb25zdCBhZnRlciA9IG9sZExpbmUuc3Vic3RyaW5nKG9sZFN1ZmZpeCk7XG4gICAgY29uc3Qgb2xkQ2hhbmdlZCA9IG9sZExpbmUuc3Vic3RyaW5nKHByZWZpeCwgb2xkU3VmZml4KTtcbiAgICBjb25zdCBuZXdDaGFuZ2VkID0gbmV3TGluZS5zdWJzdHJpbmcocHJlZml4LCBuZXdTdWZmaXgpO1xuICAgIHJldHVybiBbXG4gICAgICBgJHtib2xkLnJlZChcIi1cIil9ICR7cmVkKGJlZm9yZSl9JHtyZWQuYm9sZC51bmRlcmxpbmUob2xkQ2hhbmdlZCl9JHtyZWQoYWZ0ZXIpfWAsXG4gICAgICBgJHtib2xkLmdyZWVuKFwiK1wiKX0gJHtncmVlbihiZWZvcmUpfSR7Z3JlZW4uYm9sZC51bmRlcmxpbmUobmV3Q2hhbmdlZCl9JHtncmVlbihhZnRlcil9YCxcbiAgICBdO1xuICB9XG5cbiAgcmV0dXJuIFtgLSAke29sZExpbmV9YCwgYCsgJHtuZXdMaW5lfWBdO1xufVxuIl19