projen
Version:
CDK for software projects
170 lines • 23.5 kB
JavaScript
;
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