jsondiffpatch
Version:
Diff & Patch for Javascript objects
918 lines (799 loc) • 71.7 kB
JavaScript
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),(f.jsondiffpatch||(f.jsondiffpatch={})).formatters=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
module.exports = require('./formatters');
},{"./formatters":6}],2:[function(require,module,exports){
exports.isBrowser = typeof window !== 'undefined';
},{}],3:[function(require,module,exports){
var base = require('./base');
var BaseFormatter = base.BaseFormatter;
var AnnotatedFormatter = function AnnotatedFormatter() {
this.includeMoveDestinations = false;
};
AnnotatedFormatter.prototype = new BaseFormatter();
AnnotatedFormatter.prototype.prepareContext = function(context) {
BaseFormatter.prototype.prepareContext.call(this, context);
context.indent = function(levels) {
this.indentLevel = (this.indentLevel || 0) +
(typeof levels === 'undefined' ? 1 : levels);
this.indentPad = new Array(this.indentLevel + 1).join(' ');
};
context.row = function(json, htmlNote) {
context.out('<tr><td style="white-space: nowrap;">' +
'<pre class="jsondiffpatch-annotated-indent" style="display: inline-block">');
context.out(context.indentPad);
context.out('</pre><pre style="display: inline-block">');
context.out(json);
context.out('</pre></td><td class="jsondiffpatch-delta-note"><div>');
context.out(htmlNote);
context.out('</div></td></tr>');
};
};
AnnotatedFormatter.prototype.typeFormattterErrorFormatter = function(context, err) {
context.row('', '<pre class="jsondiffpatch-error">' + err + '</pre>');
};
AnnotatedFormatter.prototype.formatTextDiffString = function(context, value) {
var lines = this.parseTextDiff(value);
context.out('<ul class="jsondiffpatch-textdiff">');
for (var i = 0, l = lines.length; i < l; i++) {
var line = lines[i];
context.out('<li>' +
'<div class="jsondiffpatch-textdiff-location">' +
'<span class="jsondiffpatch-textdiff-line-number">' +
line.location.line +
'</span>' +
'<span class="jsondiffpatch-textdiff-char">' +
line.location.chr +
'</span>' +
'</div>' +
'<div class="jsondiffpatch-textdiff-line">');
var pieces = line.pieces;
for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
var piece = pieces[pieceIndex];
context.out('<span class="jsondiffpatch-textdiff-' + piece.type + '">' +
piece.text + '</span>');
}
context.out('</div></li>');
}
context.out('</ul>');
};
AnnotatedFormatter.prototype.rootBegin = function(context, type, nodeType) {
context.out('<table class="jsondiffpatch-annotated-delta">');
if (type === 'node') {
context.row('{');
context.indent();
}
if (nodeType === 'array') {
context.row('"_t": "a",', 'Array delta (member names indicate array indices)');
}
};
AnnotatedFormatter.prototype.rootEnd = function(context, type) {
if (type === 'node') {
context.indent(-1);
context.row('}');
}
context.out('</table>');
};
AnnotatedFormatter.prototype.nodeBegin = function(context, key, leftKey, type, nodeType) {
context.row('"' + key + '": {');
if (type === 'node') {
context.indent();
}
if (nodeType === 'array') {
context.row('"_t": "a",', 'Array delta (member names indicate array indices)');
}
};
AnnotatedFormatter.prototype.nodeEnd = function(context, key, leftKey, type, nodeType, isLast) {
if (type === 'node') {
context.indent(-1);
}
context.row('}' + (isLast ? '' : ','));
};
/* jshint camelcase: false */
AnnotatedFormatter.prototype.format_unchanged = function() {
return;
};
AnnotatedFormatter.prototype.format_movedestination = function() {
return;
};
AnnotatedFormatter.prototype.format_node = function(context, delta, left) {
// recurse
this.formatDeltaChildren(context, delta, left);
};
var wrapPropertyName = function(name) {
return '<pre style="display:inline-block">"' + name + '"</pre>';
};
var deltaAnnotations = {
added: function(delta, left, key, leftKey) {
var formatLegend = ' <pre>([newValue])</pre>';
if (typeof leftKey === 'undefined') {
return 'new value' + formatLegend;
}
if (typeof leftKey === 'number') {
return 'insert at index ' + leftKey + formatLegend;
}
return 'add property ' + wrapPropertyName(leftKey) + formatLegend;
},
modified: function(delta, left, key, leftKey) {
var formatLegend = ' <pre>([previousValue, newValue])</pre>';
if (typeof leftKey === 'undefined') {
return 'modify value' + formatLegend;
}
if (typeof leftKey === 'number') {
return 'modify at index ' + leftKey + formatLegend;
}
return 'modify property ' + wrapPropertyName(leftKey) + formatLegend;
},
deleted: function(delta, left, key, leftKey) {
var formatLegend = ' <pre>([previousValue, 0, 0])</pre>';
if (typeof leftKey === 'undefined') {
return 'delete value' + formatLegend;
}
if (typeof leftKey === 'number') {
return 'remove index ' + leftKey + formatLegend;
}
return 'delete property ' + wrapPropertyName(leftKey) + formatLegend;
},
moved: function(delta, left, key, leftKey) {
return 'move from <span title="(position to remove at original state)">index ' +
leftKey + '</span> to ' +
'<span title="(position to insert at final state)">index ' +
delta[1] + '</span>';
},
textdiff: function(delta, left, key, leftKey) {
var location = (typeof leftKey === 'undefined') ?
'' : (
(typeof leftKey === 'number') ?
' at index ' + leftKey :
' at property ' + wrapPropertyName(leftKey)
);
return 'text diff' + location + ', format is ' +
'<a href="https://code.google.com/p/google-diff-match-patch/wiki/Unidiff">' +
'a variation of Unidiff</a>';
}
};
var formatAnyChange = function(context, delta) {
var deltaType = this.getDeltaType(delta);
var annotator = deltaAnnotations[deltaType];
var htmlNote = annotator && annotator.apply(annotator,
Array.prototype.slice.call(arguments, 1));
var json = JSON.stringify(delta, null, 2);
if (deltaType === 'textdiff') {
// split text diffs lines
json = json.split('\\n').join('\\n"+\n "');
}
context.indent();
context.row(json, htmlNote);
context.indent(-1);
};
AnnotatedFormatter.prototype.format_added = formatAnyChange;
AnnotatedFormatter.prototype.format_modified = formatAnyChange;
AnnotatedFormatter.prototype.format_deleted = formatAnyChange;
AnnotatedFormatter.prototype.format_moved = formatAnyChange;
AnnotatedFormatter.prototype.format_textdiff = formatAnyChange;
/* jshint camelcase: true */
exports.AnnotatedFormatter = AnnotatedFormatter;
var defaultInstance;
exports.format = function(delta, left) {
if (!defaultInstance) {
defaultInstance = new AnnotatedFormatter();
}
return defaultInstance.format(delta, left);
};
},{"./base":4}],4:[function(require,module,exports){
var isArray = (typeof Array.isArray === 'function') ?
// use native function
Array.isArray :
// use instanceof operator
function(a) {
return a instanceof Array;
};
var getObjectKeys = typeof Object.keys === 'function' ?
function(obj) {
return Object.keys(obj);
} : function(obj) {
var names = [];
for (var property in obj) {
if (Object.prototype.hasOwnProperty.call(obj, property)) {
names.push(property);
}
}
return names;
};
var trimUnderscore = function(str) {
if (str.substr(0, 1) === '_') {
return str.slice(1);
}
return str;
};
var arrayKeyToSortNumber = function(key) {
if (key === '_t') {
return -1;
} else {
if (key.substr(0, 1) === '_') {
return parseInt(key.slice(1), 10);
} else {
return parseInt(key, 10) + 0.1;
}
}
};
var arrayKeyComparer = function(key1, key2) {
return arrayKeyToSortNumber(key1) - arrayKeyToSortNumber(key2);
};
var BaseFormatter = function BaseFormatter() {};
BaseFormatter.prototype.format = function(delta, left) {
var context = {};
this.prepareContext(context);
this.recurse(context, delta, left);
return this.finalize(context);
};
BaseFormatter.prototype.prepareContext = function(context) {
context.buffer = [];
context.out = function() {
this.buffer.push.apply(this.buffer, arguments);
};
};
BaseFormatter.prototype.typeFormattterNotFound = function(context, deltaType) {
throw new Error('cannot format delta type: ' + deltaType);
};
BaseFormatter.prototype.typeFormattterErrorFormatter = function(context, err) {
return err.toString();
};
BaseFormatter.prototype.finalize = function(context) {
if (isArray(context.buffer)) {
return context.buffer.join('');
}
};
BaseFormatter.prototype.recurse = function(context, delta, left, key, leftKey, movedFrom, isLast) {
var useMoveOriginHere = delta && movedFrom;
var leftValue = useMoveOriginHere ? movedFrom.value : left;
if (typeof delta === 'undefined' && typeof key === 'undefined') {
return undefined;
}
var type = this.getDeltaType(delta, movedFrom);
var nodeType = type === 'node' ? (delta._t === 'a' ? 'array' : 'object') : '';
if (typeof key !== 'undefined') {
this.nodeBegin(context, key, leftKey, type, nodeType, isLast);
} else {
this.rootBegin(context, type, nodeType);
}
var typeFormattter;
try {
typeFormattter = this['format_' + type] || this.typeFormattterNotFound(context, type);
typeFormattter.call(this, context, delta, leftValue, key, leftKey, movedFrom);
} catch (err) {
this.typeFormattterErrorFormatter(context, err, delta, leftValue, key, leftKey, movedFrom);
if (typeof console !== 'undefined' && console.error) {
console.error(err.stack);
}
}
if (typeof key !== 'undefined') {
this.nodeEnd(context, key, leftKey, type, nodeType, isLast);
} else {
this.rootEnd(context, type, nodeType);
}
};
BaseFormatter.prototype.formatDeltaChildren = function(context, delta, left) {
var self = this;
this.forEachDeltaKey(delta, left, function(key, leftKey, movedFrom, isLast) {
self.recurse(context, delta[key], left ? left[leftKey] : undefined,
key, leftKey, movedFrom, isLast);
});
};
BaseFormatter.prototype.forEachDeltaKey = function(delta, left, fn) {
var keys = getObjectKeys(delta);
var arrayKeys = delta._t === 'a';
var moveDestinations = {};
var name;
if (typeof left !== 'undefined') {
for (name in left) {
if (typeof delta[name] === 'undefined' &&
((!arrayKeys) || typeof delta['_' + name] === 'undefined')) {
keys.push(name);
}
}
}
// look for move destinations
for (name in delta) {
var value = delta[name];
if (isArray(value) && value[2] === 3) {
moveDestinations[value[1].toString()] = {
key: name,
value: left && left[parseInt(name.substr(1))]
};
if (this.includeMoveDestinations !== false) {
if ((typeof left === 'undefined') &&
(typeof delta[value[1]] === 'undefined')) {
keys.push(value[1].toString());
}
}
}
}
if (arrayKeys) {
keys.sort(arrayKeyComparer);
} else {
keys.sort();
}
for (var index = 0, length = keys.length; index < length; index++) {
var key = keys[index];
if (arrayKeys && key === '_t') {
continue;
}
var leftKey = arrayKeys ?
(typeof key === 'number' ? key : parseInt(trimUnderscore(key), 10)) :
key;
var isLast = (index === length - 1);
fn(key, leftKey, moveDestinations[leftKey], isLast);
}
};
BaseFormatter.prototype.getDeltaType = function(delta, movedFrom) {
if (typeof delta === 'undefined') {
if (typeof movedFrom !== 'undefined') {
return 'movedestination';
}
return 'unchanged';
}
if (isArray(delta)) {
if (delta.length === 1) {
return 'added';
}
if (delta.length === 2) {
return 'modified';
}
if (delta.length === 3 && delta[2] === 0) {
return 'deleted';
}
if (delta.length === 3 && delta[2] === 2) {
return 'textdiff';
}
if (delta.length === 3 && delta[2] === 3) {
return 'moved';
}
} else if (typeof delta === 'object') {
return 'node';
}
return 'unknown';
};
BaseFormatter.prototype.parseTextDiff = function(value) {
var output = [];
var lines = value.split('\n@@ ');
for (var i = 0, l = lines.length; i < l; i++) {
var line = lines[i];
var lineOutput = {
pieces: []
};
var location = /^(?:@@ )?[-+]?(\d+),(\d+)/.exec(line).slice(1);
lineOutput.location = {
line: location[0],
chr: location[1]
};
var pieces = line.split('\n').slice(1);
for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
var piece = pieces[pieceIndex];
if (!piece.length) {
continue;
}
var pieceOutput = {
type: 'context'
};
if (piece.substr(0, 1) === '+') {
pieceOutput.type = 'added';
} else if (piece.substr(0, 1) === '-') {
pieceOutput.type = 'deleted';
}
pieceOutput.text = piece.slice(1);
lineOutput.pieces.push(pieceOutput);
}
output.push(lineOutput);
}
return output;
};
exports.BaseFormatter = BaseFormatter;
},{}],5:[function(require,module,exports){
var base = require('./base');
var BaseFormatter = base.BaseFormatter;
var HtmlFormatter = function HtmlFormatter() {};
HtmlFormatter.prototype = new BaseFormatter();
function htmlEscape(text) {
var html = text;
var replacements = [
[/&/g, '&'],
[/</g, '<'],
[/>/g, '>'],
[/'/g, '''],
[/"/g, '"']
];
for (var i = 0; i < replacements.length; i++) {
html = html.replace(replacements[i][0], replacements[i][1]);
}
return html;
}
HtmlFormatter.prototype.typeFormattterErrorFormatter = function(context, err) {
context.out('<pre class="jsondiffpatch-error">' + err + '</pre>');
};
HtmlFormatter.prototype.formatValue = function(context, value) {
context.out('<pre>' + htmlEscape(JSON.stringify(value, null, 2)) + '</pre>');
};
HtmlFormatter.prototype.formatTextDiffString = function(context, value) {
var lines = this.parseTextDiff(value);
context.out('<ul class="jsondiffpatch-textdiff">');
for (var i = 0, l = lines.length; i < l; i++) {
var line = lines[i];
context.out('<li>' +
'<div class="jsondiffpatch-textdiff-location">' +
'<span class="jsondiffpatch-textdiff-line-number">' +
line.location.line +
'</span>' +
'<span class="jsondiffpatch-textdiff-char">' +
line.location.chr +
'</span>' +
'</div>' +
'<div class="jsondiffpatch-textdiff-line">');
var pieces = line.pieces;
for (var pieceIndex = 0, piecesLength = pieces.length; pieceIndex < piecesLength; pieceIndex++) {
/* global unescape */
var piece = pieces[pieceIndex];
context.out('<span class="jsondiffpatch-textdiff-' + piece.type + '">' +
htmlEscape(unescape(piece.text)) + '</span>');
}
context.out('</div></li>');
}
context.out('</ul>');
};
var adjustArrows = function jsondiffpatchHtmlFormatterAdjustArrows(node) {
node = node || document;
var getElementText = function(el) {
return el.textContent || el.innerText;
};
var eachByQuery = function(el, query, fn) {
var elems = el.querySelectorAll(query);
for (var i = 0, l = elems.length; i < l; i++) {
fn(elems[i]);
}
};
var eachChildren = function(el, fn) {
for (var i = 0, l = el.children.length; i < l; i++) {
fn(el.children[i], i);
}
};
eachByQuery(node, '.jsondiffpatch-arrow', function(arrow) {
var arrowParent = arrow.parentNode;
var svg = arrow.children[0],
path = svg.children[1];
svg.style.display = 'none';
var destination = getElementText(arrowParent.querySelector('.jsondiffpatch-moved-destination'));
var container = arrowParent.parentNode;
var destinationElem;
eachChildren(container, function(child) {
if (child.getAttribute('data-key') === destination) {
destinationElem = child;
}
});
if (!destinationElem) {
return;
}
try {
var distance = destinationElem.offsetTop - arrowParent.offsetTop;
svg.setAttribute('height', Math.abs(distance) + 6);
arrow.style.top = (-8 + (distance > 0 ? 0 : distance)) + 'px';
var curve = distance > 0 ?
'M30,0 Q-10,' + Math.round(distance / 2) + ' 26,' + (distance - 4) :
'M30,' + (-distance) + ' Q-10,' + Math.round(-distance / 2) + ' 26,4';
path.setAttribute('d', curve);
svg.style.display = '';
} catch (err) {
return;
}
});
};
HtmlFormatter.prototype.rootBegin = function(context, type, nodeType) {
var nodeClass = 'jsondiffpatch-' + type +
(nodeType ? ' jsondiffpatch-child-node-type-' + nodeType : '');
context.out('<div class="jsondiffpatch-delta ' + nodeClass + '">');
};
HtmlFormatter.prototype.rootEnd = function(context) {
context.out('</div>' + (context.hasArrows ?
('<script type="text/javascript">setTimeout(' +
adjustArrows.toString() +
',10);</script>') : ''));
};
HtmlFormatter.prototype.nodeBegin = function(context, key, leftKey, type, nodeType) {
var nodeClass = 'jsondiffpatch-' + type +
(nodeType ? ' jsondiffpatch-child-node-type-' + nodeType : '');
context.out('<li class="' + nodeClass + '" data-key="' + leftKey + '">' +
'<div class="jsondiffpatch-property-name">' + leftKey + '</div>');
};
HtmlFormatter.prototype.nodeEnd = function(context) {
context.out('</li>');
};
/* jshint camelcase: false */
HtmlFormatter.prototype.format_unchanged = function(context, delta, left) {
if (typeof left === 'undefined') {
return;
}
context.out('<div class="jsondiffpatch-value">');
this.formatValue(context, left);
context.out('</div>');
};
HtmlFormatter.prototype.format_movedestination = function(context, delta, left) {
if (typeof left === 'undefined') {
return;
}
context.out('<div class="jsondiffpatch-value">');
this.formatValue(context, left);
context.out('</div>');
};
HtmlFormatter.prototype.format_node = function(context, delta, left) {
// recurse
var nodeType = (delta._t === 'a') ? 'array' : 'object';
context.out('<ul class="jsondiffpatch-node jsondiffpatch-node-type-' + nodeType + '">');
this.formatDeltaChildren(context, delta, left);
context.out('</ul>');
};
HtmlFormatter.prototype.format_added = function(context, delta) {
context.out('<div class="jsondiffpatch-value">');
this.formatValue(context, delta[0]);
context.out('</div>');
};
HtmlFormatter.prototype.format_modified = function(context, delta) {
context.out('<div class="jsondiffpatch-value jsondiffpatch-left-value">');
this.formatValue(context, delta[0]);
context.out('</div>' +
'<div class="jsondiffpatch-value jsondiffpatch-right-value">');
this.formatValue(context, delta[1]);
context.out('</div>');
};
HtmlFormatter.prototype.format_deleted = function(context, delta) {
context.out('<div class="jsondiffpatch-value">');
this.formatValue(context, delta[0]);
context.out('</div>');
};
HtmlFormatter.prototype.format_moved = function(context, delta) {
context.out('<div class="jsondiffpatch-value">');
this.formatValue(context, delta[0]);
context.out('</div><div class="jsondiffpatch-moved-destination">' + delta[1] + '</div>');
// draw an SVG arrow from here to move destination
context.out(
/*jshint multistr: true */
'<div class="jsondiffpatch-arrow" style="position: relative; left: -34px;">\
<svg width="30" height="60" style="position: absolute; display: none;">\
<defs>\
<marker id="markerArrow" markerWidth="8" markerHeight="8" refx="2" refy="4"\
orient="auto" markerUnits="userSpaceOnUse">\
<path d="M1,1 L1,7 L7,4 L1,1" style="fill: #339;" />\
</marker>\
</defs>\
<path d="M30,0 Q-10,25 26,50" style="stroke: #88f; stroke-width: 2px; fill: none;\
stroke-opacity: 0.5; marker-end: url(#markerArrow);"></path>\
</svg>\
</div>');
context.hasArrows = true;
};
HtmlFormatter.prototype.format_textdiff = function(context, delta) {
context.out('<div class="jsondiffpatch-value">');
this.formatTextDiffString(context, delta[0]);
context.out('</div>');
};
/* jshint camelcase: true */
var showUnchanged = function(show, node, delay) {
var el = node || document.body;
var prefix = 'jsondiffpatch-unchanged-';
var classes = {
showing: prefix + 'showing',
hiding: prefix + 'hiding',
visible: prefix + 'visible',
hidden: prefix + 'hidden',
};
var list = el.classList;
if (!list) {
return;
}
if (!delay) {
list.remove(classes.showing);
list.remove(classes.hiding);
list.remove(classes.visible);
list.remove(classes.hidden);
if (show === false) {
list.add(classes.hidden);
}
return;
}
if (show === false) {
list.remove(classes.showing);
list.add(classes.visible);
setTimeout(function() {
list.add(classes.hiding);
}, 10);
} else {
list.remove(classes.hiding);
list.add(classes.showing);
list.remove(classes.hidden);
}
var intervalId = setInterval(function() {
adjustArrows(el);
}, 100);
setTimeout(function() {
list.remove(classes.showing);
list.remove(classes.hiding);
if (show === false) {
list.add(classes.hidden);
list.remove(classes.visible);
} else {
list.add(classes.visible);
list.remove(classes.hidden);
}
setTimeout(function() {
list.remove(classes.visible);
clearInterval(intervalId);
}, delay + 400);
}, delay);
};
var hideUnchanged = function(node, delay) {
return showUnchanged(false, node, delay);
};
exports.HtmlFormatter = HtmlFormatter;
exports.showUnchanged = showUnchanged;
exports.hideUnchanged = hideUnchanged;
var defaultInstance;
exports.format = function(delta, left) {
if (!defaultInstance) {
defaultInstance = new HtmlFormatter();
}
return defaultInstance.format(delta, left);
};
},{"./base":4}],6:[function(require,module,exports){
var environment = require('../environment');
exports.base = require('./base');
exports.html = require('./html');
exports.annotated = require('./annotated');
exports.jsonpatch = require('./jsonpatch');
if (!environment.isBrowser) {
var consoleModuleName = './console';
exports.console = require(consoleModuleName);
}
},{"../environment":2,"./annotated":3,"./base":4,"./html":5,"./jsonpatch":7}],7:[function(require,module,exports){
(function () {
var base = require('./base');
var BaseFormatter = base.BaseFormatter;
var named = {
added: 'add',
deleted: 'remove',
modified: 'replace',
moved: 'moved',
movedestination: 'movedestination',
unchanged: 'unchanged',
error: 'error',
textDiffLine: 'textDiffLine'
};
function JSONFormatter() {
this.includeMoveDestinations = false;
}
JSONFormatter.prototype = new BaseFormatter();
JSONFormatter.prototype.prepareContext = function (context) {
BaseFormatter.prototype.prepareContext.call(this, context);
context.result = [];
context.path = [];
context.pushCurrentOp = function (op, value) {
var val = {
op: op,
path: this.currentPath()
};
if (typeof value !== 'undefined') {
val.value = value;
}
this.result.push(val);
};
context.currentPath = function () {
return '/' + this.path.join('/');
};
};
JSONFormatter.prototype.typeFormattterErrorFormatter = function (context, err) {
context.out('[ERROR]' + err);
};
JSONFormatter.prototype.rootBegin = function () {
};
JSONFormatter.prototype.rootEnd = function () {
};
JSONFormatter.prototype.nodeBegin = function (context, key, leftKey) {
context.path.push(leftKey);
};
JSONFormatter.prototype.nodeEnd = function (context) {
context.path.pop();
};
/* jshint camelcase: false */
JSONFormatter.prototype.format_unchanged = function (context, delta, left) {
if (typeof left === 'undefined') {
return;
}
context.pushCurrentOp(named.unchanged, left);
};
JSONFormatter.prototype.format_movedestination = function (context, delta, left) {
if (typeof left === 'undefined') {
return;
}
context.pushCurrentOp(named.movedestination, left);
};
JSONFormatter.prototype.format_node = function (context, delta, left) {
this.formatDeltaChildren(context, delta, left);
};
JSONFormatter.prototype.format_added = function (context, delta) {
context.pushCurrentOp(named.added, delta[0]);
};
JSONFormatter.prototype.format_modified = function (context, delta) {
context.pushCurrentOp(named.modified, delta[1]);
};
JSONFormatter.prototype.format_deleted = function (context) {
context.pushCurrentOp(named.deleted);
};
JSONFormatter.prototype.format_moved = function (context, delta) {
context.pushCurrentOp(named.moved, delta[1]);
};
JSONFormatter.prototype.format_textdiff = function () {
throw 'not implimented';
};
JSONFormatter.prototype.format = function (delta, left) {
var context = {};
this.prepareContext(context);
this.recurse(context, delta, left);
return context.result;
};
/* jshint camelcase: true */
exports.JSONFormatter = JSONFormatter;
var defaultInstance;
function last(arr) {
return arr[arr.length - 1];
}
function sortBy(arr, pred) {
arr.sort(pred);
return arr;
}
var compareByIndexDesc = function (indexA, indexB) {
var lastA = parseInt(indexA, 10);
var lastB = parseInt(indexB, 10);
if (!(isNaN(lastA) || isNaN(lastB))) {
return lastB - lastA;
} else {
return 0;
}
};
function opsByDescendingOrder(removeOps) {
return sortBy(removeOps, function (a, b) {
var splitA = a.path.split('/');
var splitB = b.path.split('/');
if (splitA.length !== splitB.length) {
return splitA.length - splitB.length;
} else {
return compareByIndexDesc(last(splitA), last(splitB));
}
});
}
function partition(arr, pred) {
var left = [];
var right = [];
arr.forEach(function (el) {
var coll = pred(el) ? left : right;
coll.push(el);
});
return [left, right];
}
function reorderOps(jsonFormattedDiff) {
var removeOpsOtherOps = partition(jsonFormattedDiff, function (operation) {
return operation.op === 'remove';
});
var removeOps = removeOpsOtherOps[0];
var otherOps = removeOpsOtherOps[1];
var removeOpsReverse = opsByDescendingOrder(removeOps);
return removeOpsReverse.concat(otherOps);
}
var format = function (delta, left) {
if (!defaultInstance) {
defaultInstance = new JSONFormatter();
}
return reorderOps(defaultInstance.format(delta, left));
};
exports.log = function (delta, left) {
console.log(format(delta, left));
};
exports.format = format;
})();
},{"./base":4}]},{},[1])(1)
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9maWJlcmdsYXNzL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJzcmMvbWFpbi1mb3JtYXR0ZXJzLmpzIiwic3JjL2Vudmlyb25tZW50LmpzIiwic3JjL2Zvcm1hdHRlcnMvYW5ub3RhdGVkLmpzIiwic3JjL2Zvcm1hdHRlcnMvYmFzZS5qcyIsInNyYy9mb3JtYXR0ZXJzL2h0bWwuanMiLCJzcmMvZm9ybWF0dGVycy9pbmRleC5qcyIsInNyYy9mb3JtYXR0ZXJzL2pzb25wYXRjaC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTs7QUNGQTtBQUNBO0FBQ0E7O0FDRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdE9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6UkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vZm9ybWF0dGVycycpO1xuIiwiXG5leHBvcnRzLmlzQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnO1xuIiwidmFyIGJhc2UgPSByZXF1aXJlKCcuL2Jhc2UnKTtcbnZhciBCYXNlRm9ybWF0dGVyID0gYmFzZS5CYXNlRm9ybWF0dGVyO1xuXG52YXIgQW5ub3RhdGVkRm9ybWF0dGVyID0gZnVuY3Rpb24gQW5ub3RhdGVkRm9ybWF0dGVyKCkge1xuICB0aGlzLmluY2x1ZGVNb3ZlRGVzdGluYXRpb25zID0gZmFsc2U7XG59O1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlID0gbmV3IEJhc2VGb3JtYXR0ZXIoKTtcblxuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5wcmVwYXJlQ29udGV4dCA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgQmFzZUZvcm1hdHRlci5wcm90b3R5cGUucHJlcGFyZUNvbnRleHQuY2FsbCh0aGlzLCBjb250ZXh0KTtcbiAgY29udGV4dC5pbmRlbnQgPSBmdW5jdGlvbihsZXZlbHMpIHtcbiAgICB0aGlzLmluZGVudExldmVsID0gKHRoaXMuaW5kZW50TGV2ZWwgfHwgMCkgK1xuICAgICAgKHR5cGVvZiBsZXZlbHMgPT09ICd1bmRlZmluZWQnID8gMSA6IGxldmVscyk7XG4gICAgdGhpcy5pbmRlbnRQYWQgPSBuZXcgQXJyYXkodGhpcy5pbmRlbnRMZXZlbCArIDEpLmpvaW4oJyZuYnNwOyZuYnNwOycpO1xuICB9O1xuICBjb250ZXh0LnJvdyA9IGZ1bmN0aW9uKGpzb24sIGh0bWxOb3RlKSB7XG4gICAgY29udGV4dC5vdXQoJzx0cj48dGQgc3R5bGU9XCJ3aGl0ZS1zcGFjZTogbm93cmFwO1wiPicgK1xuICAgICAgJzxwcmUgY2xhc3M9XCJqc29uZGlmZnBhdGNoLWFubm90YXRlZC1pbmRlbnRcIiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9ja1wiPicpO1xuICAgIGNvbnRleHQub3V0KGNvbnRleHQuaW5kZW50UGFkKTtcbiAgICBjb250ZXh0Lm91dCgnPC9wcmU+PHByZSBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9ja1wiPicpO1xuICAgIGNvbnRleHQub3V0KGpzb24pO1xuICAgIGNvbnRleHQub3V0KCc8L3ByZT48L3RkPjx0ZCBjbGFzcz1cImpzb25kaWZmcGF0Y2gtZGVsdGEtbm90ZVwiPjxkaXY+Jyk7XG4gICAgY29udGV4dC5vdXQoaHRtbE5vdGUpO1xuICAgIGNvbnRleHQub3V0KCc8L2Rpdj48L3RkPjwvdHI+Jyk7XG4gIH07XG59O1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlLnR5cGVGb3JtYXR0dGVyRXJyb3JGb3JtYXR0ZXIgPSBmdW5jdGlvbihjb250ZXh0LCBlcnIpIHtcbiAgY29udGV4dC5yb3coJycsICc8cHJlIGNsYXNzPVwianNvbmRpZmZwYXRjaC1lcnJvclwiPicgKyBlcnIgKyAnPC9wcmU+Jyk7XG59O1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdFRleHREaWZmU3RyaW5nID0gZnVuY3Rpb24oY29udGV4dCwgdmFsdWUpIHtcbiAgdmFyIGxpbmVzID0gdGhpcy5wYXJzZVRleHREaWZmKHZhbHVlKTtcbiAgY29udGV4dC5vdXQoJzx1bCBjbGFzcz1cImpzb25kaWZmcGF0Y2gtdGV4dGRpZmZcIj4nKTtcbiAgZm9yICh2YXIgaSA9IDAsIGwgPSBsaW5lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuICAgIGNvbnRleHQub3V0KCc8bGk+JyArXG4gICAgICAnPGRpdiBjbGFzcz1cImpzb25kaWZmcGF0Y2gtdGV4dGRpZmYtbG9jYXRpb25cIj4nICtcbiAgICAgICc8c3BhbiBjbGFzcz1cImpzb25kaWZmcGF0Y2gtdGV4dGRpZmYtbGluZS1udW1iZXJcIj4nICtcbiAgICAgIGxpbmUubG9jYXRpb24ubGluZSArXG4gICAgICAnPC9zcGFuPicgK1xuICAgICAgJzxzcGFuIGNsYXNzPVwianNvbmRpZmZwYXRjaC10ZXh0ZGlmZi1jaGFyXCI+JyArXG4gICAgICBsaW5lLmxvY2F0aW9uLmNociArXG4gICAgICAnPC9zcGFuPicgK1xuICAgICAgJzwvZGl2PicgK1xuICAgICAgJzxkaXYgY2xhc3M9XCJqc29uZGlmZnBhdGNoLXRleHRkaWZmLWxpbmVcIj4nKTtcbiAgICB2YXIgcGllY2VzID0gbGluZS5waWVjZXM7XG4gICAgZm9yICh2YXIgcGllY2VJbmRleCA9IDAsIHBpZWNlc0xlbmd0aCA9IHBpZWNlcy5sZW5ndGg7IHBpZWNlSW5kZXggPCBwaWVjZXNMZW5ndGg7IHBpZWNlSW5kZXgrKykge1xuICAgICAgdmFyIHBpZWNlID0gcGllY2VzW3BpZWNlSW5kZXhdO1xuICAgICAgY29udGV4dC5vdXQoJzxzcGFuIGNsYXNzPVwianNvbmRpZmZwYXRjaC10ZXh0ZGlmZi0nICsgcGllY2UudHlwZSArICdcIj4nICtcbiAgICAgICAgcGllY2UudGV4dCArICc8L3NwYW4+Jyk7XG4gICAgfVxuICAgIGNvbnRleHQub3V0KCc8L2Rpdj48L2xpPicpO1xuICB9XG4gIGNvbnRleHQub3V0KCc8L3VsPicpO1xufTtcblxuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5yb290QmVnaW4gPSBmdW5jdGlvbihjb250ZXh0LCB0eXBlLCBub2RlVHlwZSkge1xuICBjb250ZXh0Lm91dCgnPHRhYmxlIGNsYXNzPVwianNvbmRpZmZwYXRjaC1hbm5vdGF0ZWQtZGVsdGFcIj4nKTtcbiAgaWYgKHR5cGUgPT09ICdub2RlJykge1xuICAgIGNvbnRleHQucm93KCd7Jyk7XG4gICAgY29udGV4dC5pbmRlbnQoKTtcbiAgfVxuICBpZiAobm9kZVR5cGUgPT09ICdhcnJheScpIHtcbiAgICBjb250ZXh0LnJvdygnXCJfdFwiOiBcImFcIiwnLCAnQXJyYXkgZGVsdGEgKG1lbWJlciBuYW1lcyBpbmRpY2F0ZSBhcnJheSBpbmRpY2VzKScpO1xuICB9XG59O1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlLnJvb3RFbmQgPSBmdW5jdGlvbihjb250ZXh0LCB0eXBlKSB7XG4gIGlmICh0eXBlID09PSAnbm9kZScpIHtcbiAgICBjb250ZXh0LmluZGVudCgtMSk7XG4gICAgY29udGV4dC5yb3coJ30nKTtcbiAgfVxuICBjb250ZXh0Lm91dCgnPC90YWJsZT4nKTtcbn07XG5cbkFubm90YXRlZEZvcm1hdHRlci5wcm90b3R5cGUubm9kZUJlZ2luID0gZnVuY3Rpb24oY29udGV4dCwga2V5LCBsZWZ0S2V5LCB0eXBlLCBub2RlVHlwZSkge1xuICBjb250ZXh0LnJvdygnJnF1b3Q7JyArIGtleSArICcmcXVvdDs6IHsnKTtcbiAgaWYgKHR5cGUgPT09ICdub2RlJykge1xuICAgIGNvbnRleHQuaW5kZW50KCk7XG4gIH1cbiAgaWYgKG5vZGVUeXBlID09PSAnYXJyYXknKSB7XG4gICAgY29udGV4dC5yb3coJ1wiX3RcIjogXCJhXCIsJywgJ0FycmF5IGRlbHRhIChtZW1iZXIgbmFtZXMgaW5kaWNhdGUgYXJyYXkgaW5kaWNlcyknKTtcbiAgfVxufTtcblxuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5ub2RlRW5kID0gZnVuY3Rpb24oY29udGV4dCwga2V5LCBsZWZ0S2V5LCB0eXBlLCBub2RlVHlwZSwgaXNMYXN0KSB7XG4gIGlmICh0eXBlID09PSAnbm9kZScpIHtcbiAgICBjb250ZXh0LmluZGVudCgtMSk7XG4gIH1cbiAgY29udGV4dC5yb3coJ30nICsgKGlzTGFzdCA/ICcnIDogJywnKSk7XG59O1xuXG4vKiBqc2hpbnQgY2FtZWxjYXNlOiBmYWxzZSAqL1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdF91bmNoYW5nZWQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuO1xufTtcblxuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRfbW92ZWRlc3RpbmF0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybjtcbn07XG5cblxuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRfbm9kZSA9IGZ1bmN0aW9uKGNvbnRleHQsIGRlbHRhLCBsZWZ0KSB7XG4gIC8vIHJlY3Vyc2VcbiAgdGhpcy5mb3JtYXREZWx0YUNoaWxkcmVuKGNvbnRleHQsIGRlbHRhLCBsZWZ0KTtcbn07XG5cbnZhciB3cmFwUHJvcGVydHlOYW1lID0gZnVuY3Rpb24obmFtZSkge1xuICByZXR1cm4gJzxwcmUgc3R5bGU9XCJkaXNwbGF5OmlubGluZS1ibG9ja1wiPiZxdW90OycgKyBuYW1lICsgJyZxdW90OzwvcHJlPic7XG59O1xuXG52YXIgZGVsdGFBbm5vdGF0aW9ucyA9IHtcbiAgYWRkZWQ6IGZ1bmN0aW9uKGRlbHRhLCBsZWZ0LCBrZXksIGxlZnRLZXkpIHtcbiAgICB2YXIgZm9ybWF0TGVnZW5kID0gJyA8cHJlPihbbmV3VmFsdWVdKTwvcHJlPic7XG4gICAgaWYgKHR5cGVvZiBsZWZ0S2V5ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuICduZXcgdmFsdWUnICsgZm9ybWF0TGVnZW5kO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGxlZnRLZXkgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gJ2luc2VydCBhdCBpbmRleCAnICsgbGVmdEtleSArIGZvcm1hdExlZ2VuZDtcbiAgICB9XG4gICAgcmV0dXJuICdhZGQgcHJvcGVydHkgJyArIHdyYXBQcm9wZXJ0eU5hbWUobGVmdEtleSkgKyBmb3JtYXRMZWdlbmQ7XG4gIH0sXG4gIG1vZGlmaWVkOiBmdW5jdGlvbihkZWx0YSwgbGVmdCwga2V5LCBsZWZ0S2V5KSB7XG4gICAgdmFyIGZvcm1hdExlZ2VuZCA9ICcgPHByZT4oW3ByZXZpb3VzVmFsdWUsIG5ld1ZhbHVlXSk8L3ByZT4nO1xuICAgIGlmICh0eXBlb2YgbGVmdEtleSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiAnbW9kaWZ5IHZhbHVlJyArIGZvcm1hdExlZ2VuZDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBsZWZ0S2V5ID09PSAnbnVtYmVyJykge1xuICAgICAgcmV0dXJuICdtb2RpZnkgYXQgaW5kZXggJyArIGxlZnRLZXkgKyBmb3JtYXRMZWdlbmQ7XG4gICAgfVxuICAgIHJldHVybiAnbW9kaWZ5IHByb3BlcnR5ICcgKyB3cmFwUHJvcGVydHlOYW1lKGxlZnRLZXkpICsgZm9ybWF0TGVnZW5kO1xuICB9LFxuICBkZWxldGVkOiBmdW5jdGlvbihkZWx0YSwgbGVmdCwga2V5LCBsZWZ0S2V5KSB7XG4gICAgdmFyIGZvcm1hdExlZ2VuZCA9ICcgPHByZT4oW3ByZXZpb3VzVmFsdWUsIDAsIDBdKTwvcHJlPic7XG4gICAgaWYgKHR5cGVvZiBsZWZ0S2V5ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuICdkZWxldGUgdmFsdWUnICsgZm9ybWF0TGVnZW5kO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGxlZnRLZXkgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gJ3JlbW92ZSBpbmRleCAnICsgbGVmdEtleSArIGZvcm1hdExlZ2VuZDtcbiAgICB9XG4gICAgcmV0dXJuICdkZWxldGUgcHJvcGVydHkgJyArIHdyYXBQcm9wZXJ0eU5hbWUobGVmdEtleSkgKyBmb3JtYXRMZWdlbmQ7XG4gIH0sXG4gIG1vdmVkOiBmdW5jdGlvbihkZWx0YSwgbGVmdCwga2V5LCBsZWZ0S2V5KSB7XG4gICAgcmV0dXJuICdtb3ZlIGZyb20gPHNwYW4gdGl0bGU9XCIocG9zaXRpb24gdG8gcmVtb3ZlIGF0IG9yaWdpbmFsIHN0YXRlKVwiPmluZGV4ICcgK1xuICAgICAgbGVmdEtleSArICc8L3NwYW4+IHRvICcgK1xuICAgICAgJzxzcGFuIHRpdGxlPVwiKHBvc2l0aW9uIHRvIGluc2VydCBhdCBmaW5hbCBzdGF0ZSlcIj5pbmRleCAnICtcbiAgICAgIGRlbHRhWzFdICsgJzwvc3Bhbj4nO1xuICB9LFxuICB0ZXh0ZGlmZjogZnVuY3Rpb24oZGVsdGEsIGxlZnQsIGtleSwgbGVmdEtleSkge1xuICAgIHZhciBsb2NhdGlvbiA9ICh0eXBlb2YgbGVmdEtleSA9PT0gJ3VuZGVmaW5lZCcpID9cbiAgICAgICcnIDogKFxuICAgICAgICAodHlwZW9mIGxlZnRLZXkgPT09ICdudW1iZXInKSA/XG4gICAgICAgICcgYXQgaW5kZXggJyArIGxlZnRLZXkgOlxuICAgICAgICAnIGF0IHByb3BlcnR5ICcgKyB3cmFwUHJvcGVydHlOYW1lKGxlZnRLZXkpXG4gICAgICApO1xuICAgIHJldHVybiAndGV4dCBkaWZmJyArIGxvY2F0aW9uICsgJywgZm9ybWF0IGlzICcgK1xuICAgICAgJzxhIGhyZWY9XCJodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2dvb2dsZS1kaWZmLW1hdGNoLXBhdGNoL3dpa2kvVW5pZGlmZlwiPicgK1xuICAgICAgJ2EgdmFyaWF0aW9uIG9mIFVuaWRpZmY8L2E+JztcbiAgfVxufTtcblxudmFyIGZvcm1hdEFueUNoYW5nZSA9IGZ1bmN0aW9uKGNvbnRleHQsIGRlbHRhKSB7XG4gIHZhciBkZWx0YVR5cGUgPSB0aGlzLmdldERlbHRhVHlwZShkZWx0YSk7XG4gIHZhciBhbm5vdGF0b3IgPSBkZWx0YUFubm90YXRpb25zW2RlbHRhVHlwZV07XG4gIHZhciBodG1sTm90ZSA9IGFubm90YXRvciAmJiBhbm5vdGF0b3IuYXBwbHkoYW5ub3RhdG9yLFxuICAgIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICB2YXIganNvbiA9IEpTT04uc3RyaW5naWZ5KGRlbHRhLCBudWxsLCAyKTtcbiAgaWYgKGRlbHRhVHlwZSA9PT0gJ3RleHRkaWZmJykge1xuICAgIC8vIHNwbGl0IHRleHQgZGlmZnMgbGluZXNcbiAgICBqc29uID0ganNvbi5zcGxpdCgnXFxcXG4nKS5qb2luKCdcXFxcblwiK1xcbiAgIFwiJyk7XG4gIH1cbiAgY29udGV4dC5pbmRlbnQoKTtcbiAgY29udGV4dC5yb3coanNvbiwgaHRtbE5vdGUpO1xuICBjb250ZXh0LmluZGVudCgtMSk7XG59O1xuXG5Bbm5vdGF0ZWRGb3JtYXR0ZXIucHJvdG90eXBlLmZvcm1hdF9hZGRlZCA9IGZvcm1hdEFueUNoYW5nZTtcbkFubm90YXRlZEZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0X21vZGlmaWVkID0gZm9ybWF0QW55Q2hhbmdlO1xuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRfZGVsZXRlZCA9IGZvcm1hdEFueUNoYW5nZTtcbkFubm90YXRlZEZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0X21vdmVkID0gZm9ybWF0QW55Q2hhbmdlO1xuQW5ub3RhdGVkRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JtYXRfdGV4dGRpZmYgPSBmb3JtYXRBbnlDaGFuZ2U7XG5cbi8qIGpzaGludCBjYW1lbGNhc2U6IHRydWUgKi9cblxuZXhwb3J0cy5Bbm5vdGF0ZWRGb3JtYXR0ZXIgPSBBbm5vdGF0ZWRGb3JtYXR0ZXI7XG5cbnZhciBkZWZhdWx0SW5zdGFuY2U7XG5cbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZGVsdGEsIGxlZnQpIHtcbiAgaWYgKCFkZWZhdWx0SW5zdGFuY2UpIHtcbiAgICBkZWZhdWx0SW5zdGFuY2UgPSBuZXcgQW5ub3RhdGVkRm9ybWF0dGVyKCk7XG4gIH1cbiAgcmV0dXJuIGRlZmF1bHRJbnN0YW5jZS5mb3JtYXQoZGVsdGEsIGxlZnQpO1xufTtcbiIsInZhciBpc0FycmF5ID0gKHR5cGVvZiBBcnJheS5pc0FycmF5ID09PSAnZnVuY3Rpb24nKSA/XG4gIC8vIHVzZSBuYXRpdmUgZnVuY3Rpb25cbiAgQXJyYXkuaXNBcnJheSA6XG4gIC8vIHVzZSBpbnN0YW5jZW9mIG9wZXJhdG9yXG4gIGZ1bmN0aW9uKGEpIHtcbiAgICByZXR1cm4gYSBpbnN0YW5jZW9mIEFycmF5O1xuICB9O1xuXG52YXIgZ2V0T2JqZWN0S2V5cyA9IHR5cGVvZiBPYmplY3Qua2V5cyA9PT0gJ2Z1bmN0aW9uJyA/XG4gIGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopO1xuICB9IDogZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIG5hbWVzID0gW107XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gb2JqKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcGVydHkpKSB7XG4gICAgICAgIG5hbWVzLnB1c2gocHJvcGVydHkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbmFtZXM7XG4gIH07XG5cbnZhciB0cmltVW5kZXJzY29yZSA9IGZ1bmN0aW9uKHN0cikge1xuICBpZiAoc3RyLnN1YnN0cigwLCAxKSA9PT0gJ18nKSB7XG4gICAgcmV0dXJuIHN0ci5zbGljZSgxKTtcbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxudmFyIGFycmF5S2V5VG9Tb3J0TnVtYmVyID0gZnVuY3Rpb24oa2V5KSB7XG4gIGlmIChrZXkgPT09ICdfdCcpIHtcbiAgICByZXR1cm4gLTE7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGtleS5zdWJzdHIoMCwgMSkgPT09ICdfJykge1xuICAgICAgcmV0dXJuIHBhcnNlSW50KGtleS5zbGljZSgxKSwgMTApO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcGFyc2VJbnQoa2V5LCAxMCkgKyAwLjE7XG4gICAgfVxuICB9XG59O1xuXG52YXIgYXJyYXlLZXlDb21wYXJlciA9IGZ1bmN0aW9uKGtleTEsIGtleTIpIHtcbiAgcmV0dXJuIGFycmF5S2V5VG9Tb3J0TnVtYmVyKGtleTEpIC0gYXJyYXlLZXlUb1NvcnROdW1iZXIoa2V5Mik7XG59O1xuXG52YXIgQmFzZUZvcm1hdHRlciA9IGZ1bmN0aW9uIEJhc2VGb3JtYXR0ZXIoKSB7fTtcblxuQmFzZUZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0ID0gZnVuY3Rpb24oZGVsdGEsIGxlZnQpIHtcbiAgdmFyIGNvbnRleHQgPSB7fTtcbiAgdGhpcy5wcmVwYXJlQ29udGV4dChjb250ZXh0KTtcbiAgdGhpcy5yZWN1cnNlKGNvbnRleHQsIGRlbHRhLCBsZWZ0KTtcbiAgcmV0dXJuIHRoaXMuZmluYWxpemUoY29udGV4dCk7XG59O1xuXG5CYXNlRm9ybWF0dGVyLnByb3RvdHlwZS5wcmVwYXJlQ29udGV4dCA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgY29udGV4dC5idWZmZXIgPSBbXTtcbiAgY29udGV4dC5vdXQgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLmJ1ZmZlci5wdXNoLmFwcGx5KHRoaXMuYnVmZmVyLCBhcmd1bWVudHMpO1xuICB9O1xufTtcblxuQmFzZUZvcm1hdHRlci5wcm90b3R5cGUudHlwZUZvcm1hdHR0ZXJOb3RGb3VuZCA9IGZ1bmN0aW9uKGNvbnRleHQsIGRlbHRhVHlwZSkge1xuICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBmb3JtYXQgZGVsdGEgdHlwZTogJyArIGRlbHRhVHlwZSk7XG59O1xuXG5CYXNlRm9ybWF0dGVyLnByb3RvdHlwZS50eXBlRm9ybWF0dHRlckVycm9yRm9ybWF0dGVyID0gZnVuY3Rpb24oY29udGV4dCwgZXJyKSB7XG4gIHJldHVybiBlcnIudG9TdHJpbmcoKTtcbn07XG5cbkJhc2VGb3JtYXR0ZXIucHJvdG90eXBlLmZpbmFsaXplID0gZnVuY3Rpb24oY29udGV4dCkge1xuICBpZiAoaXNBcnJheShjb250ZXh0LmJ1ZmZlcikpIHtcbiAgICByZXR1cm4gY29udGV4dC5idWZmZXIuam9pbignJyk7XG4gIH1cbn07XG5cbkJhc2VGb3JtYXR0ZXIucHJvdG90eXBlLnJlY3Vyc2UgPSBmdW5jdGlvbihjb250ZXh0LCBkZWx0YSwgbGVmdCwga2V5LCBsZWZ0S2V5LCBtb3ZlZEZyb20sIGlzTGFzdCkge1xuXG4gIHZhciB1c2VNb3ZlT3JpZ2luSGVyZSA9IGRlbHRhICYmIG1vdmVkRnJvbTtcbiAgdmFyIGxlZnRWYWx1ZSA9IHVzZU1vdmVPcmlnaW5IZXJlID8gbW92ZWRGcm9tLnZhbHVlIDogbGVmdDtcblxuICBpZiAodHlwZW9mIGRlbHRhID09PSAndW5kZWZpbmVkJyAmJiB0eXBlb2Yga2V5ID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICB2YXIgdHlwZSA9IHRoaXMuZ2V0RGVsdGFUeXBlKGRlbHRhLCBtb3ZlZEZyb20pO1xuICB2YXIgbm9kZVR5cGUgPSB0eXBlID09PSAnbm9kZScgPyAoZGVsdGEuX3QgPT09ICdhJyA/ICdhcnJheScgOiAnb2JqZWN0JykgOiAnJztcblxuICBpZiAodHlwZW9mIGtleSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB0aGlzLm5vZGVCZWdpbihjb250ZXh0LCBrZXksIGxlZnRLZXksIHR5cGUsIG5vZGVUeXBlLCBpc0xhc3QpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucm9vdEJlZ2luKGNvbnRleHQsIHR5cGUsIG5vZGVUeXBlKTtcbiAgfVxuXG4gIHZhciB0eXBlRm9ybWF0dHRlcjtcbiAgdHJ5IHtcbiAgICB0eXBlRm9ybWF0dHRlciA9IHRoaXNbJ2Zvcm1hdF8nICsgdHlwZV0gfHwgdGhpcy50eXBlRm9ybWF0dHRlck5vdEZvdW5kKGNvbnRleHQsIHR5cGUpO1xuICAgIHR5cGVGb3JtYXR0dGVyLmNhbGwodGhpcywgY29udGV4dCwgZGVsdGEsIGxlZnRWYWx1ZSwga2V5LCBsZWZ0S2V5LCBtb3ZlZEZyb20pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aGlzLnR5cGVGb3JtYXR0dGVyRXJyb3JGb3JtYXR0ZXIoY29udGV4dCwgZXJyLCBkZWx0YSwgbGVmdFZhbHVlLCBrZXksIGxlZnRLZXksIG1vdmVkRnJvbSk7XG4gICAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJiBjb25zb2xlLmVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGVyci5zdGFjayk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHR5cGVvZiBrZXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdGhpcy5ub2RlRW5kKGNvbnRleHQsIGtleSwgbGVmdEtleSwgdHlwZSwgbm9kZVR5cGUsIGlzTGFzdCk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5yb290RW5kKGNvbnRleHQsIHR5cGUsIG5vZGVUeXBlKTtcbiAgfVxufTtcblxuQmFzZUZvcm1hdHRlci5wcm90b3R5cGUuZm9ybWF0RGVsdGFDaGlsZHJlbiA9IGZ1bmN0aW9uKGNvbnRleHQsIGRlbHRhLCBsZWZ0KSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdGhpcy5mb3JFYWNoRGVsdGFLZXkoZGVsdGEsIGxlZnQsIGZ1bmN0aW9uKGtleSwgbGVmdEtleSwgbW92ZWRGcm9tLCBpc0xhc3QpIHtcbiAgICBzZWxmLnJlY3Vyc2UoY29udGV4dCwgZGVsdGFba2V5XSwgbGVmdCA/IGxlZnRbbGVmdEtleV0gOiB1bmRlZmluZWQsXG4gICAgICBrZXksIGxlZnRLZXksIG1vdmVkRnJvbSwgaXNMYXN0KTtcbiAgfSk7XG59O1xuXG5CYXNlRm9ybWF0dGVyLnByb3RvdHlwZS5mb3JFYWNoRGVsdGFLZXkgPSBmdW5jdGlvbihkZWx0YSwgbGVmdCwgZm4pIHtcbiAgdmFyIGtleXMgPSBnZXRPYmplY3RLZXlzKGRlbHRhKTtcbiAgdmFyIGFycmF5S2V5cyA9IGRlbHRhLl90ID09PSAnYSc7XG4gIHZhciBtb3ZlRGVzdGluYXRpb25zID0ge307XG4gIHZhciBuYW1lO1xuICBpZiAodHlwZW9mIGxlZnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgZm9yIChuYW1lIGluIGxlZnQpIHtcbiAgICAgIGlmICh0eXBlb2YgZGVsdGFbbmFtZV0gPT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICgoIWFycmF5S2V5cykgfHwgdHlwZW9mIGRlbHRhWydfJyArIG5hbWVdID09PSAndW5kZWZpbmVkJykpIHtcbiAgICAgICAga2V5cy5wdXNoKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICAvLyBsb29rIGZvciBtb3ZlIGRlc3RpbmF0aW9uc1xuICBmb3IgKG5hbWUgaW4gZGVsdGEpIHtcbiAgICB2YXIgdmFsdWUgPSBkZWx0YVtuYW1lXTtcbiAgICBpZiAoaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWVbMl0gPT09IDMpIHtcbiAgICAgIG1vdmVEZXN0aW5hdGlvbnNbdmFsdWVbMV0udG9TdHJpbmcoKV0gPSB7XG4gICAgICAgIGtleTogbmFtZSxcbiAgICAgICAgdmFsdWU6IGxlZnQgJiYgbGVmdFtwYXJzZUludChuYW1lLnN1YnN0cigxKSldXG4gICAgICB9O1xuICAgICAgaWYgKHRoaXMuaW5jbHVkZU1vdmVEZXN0aW5hdGlvbnMgIT09IGZhbHNlKSB7XG4gICAgICAgIGlmICgodHlwZW9mIGxlZnQgPT09ICd1bmRlZmluZWQnKSAmJlxuICAgICAgICAgICh0eXBlb2YgZGVsdGFbdmFsdWVbMV1dID09PSAndW5kZWZpbmVkJykpIHtcbiAgICAgICAgICBrZXlzLnB1c2godmFsdWVbMV0udG9TdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgaWYgKGFycmF5S2V5cykge1xuICAgIGtleXMuc29ydChhcnJheUtleUNvbXBhcmVyKTtcbiAgfSBlbHNlIHtcbiAgICBrZXlzLnNvcnQoKTtcbiAgfVxuICBmb3IgKHZhciBpbmRleCA9IDAsIGxlbmd0aCA9I