Skip to content

Instantly share code, notes, and snippets.

@joshski
Created October 22, 2017 10:36
Show Gist options
  • Save joshski/b6fdb8131c9c8d451863b41a6558d727 to your computer and use it in GitHub Desktop.
Save joshski/b6fdb8131c9c8d451863b41a6558d727 to your computer and use it in GitHub Desktop.
requirebin sketch
var hyperdom = require('hyperdom')
var h = hyperdom.html
class App {
render() {
return h('.container',
h('#example',
h('div.foo div', h('input[type=submit]'))
),
h.component({
onadd: function(pre) {
pre.innerText = document.querySelector('#example').innerHTML
}
}, h('pre'))
)
}
}
hyperdom.append(document.body, new App())
setTimeout(function(){
;require=(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){
},{}],2:[function(require,module,exports){
var VText = require("virtual-dom/vnode/vtext.js")
var domComponent = require('./domComponent');
var hyperdom = require('.');
var deprecations = require('./deprecations');
function ComponentWidget(state, vdom) {
if (!vdom) {
throw new Error('hyperdom.html.component([options], vdom) expects a vdom argument');
}
this.state = state;
this.key = state.key;
var currentRender = hyperdom.currentRender();
if (typeof vdom === 'function') {
this.render = function () {
if (currentRender) {
currentRender.eventHandlerWrapper = state.on;
}
return vdom.apply(this.state, arguments);
};
this.canRefresh = true;
} else {
vdom = vdom || new VText('');
this.render = function () {
return vdom;
}
}
this.cacheKey = state.cacheKey;
this.component = domComponent();
var renderFinished = currentRender && currentRender.finished;
if (renderFinished) {
this.afterRender = function (fn) {
renderFinished.then(fn);
};
} else {
this.afterRender = function () {};
}
}
ComponentWidget.prototype.type = 'Widget';
ComponentWidget.prototype.init = function () {
var self = this;
if (self.state.onbeforeadd) {
self.state.onbeforeadd();
}
var vdom = this.render(this);
if (vdom instanceof Array) {
throw new Error('vdom returned from component cannot be an array');
}
var element = this.component.create(vdom);
if (self.state.onadd) {
this.afterRender(function () {
self.state.onadd(element);
});
}
if (self.state.detached) {
return document.createTextNode('');
} else {
return element;
}
};
ComponentWidget.prototype.update = function (previous) {
var self = this;
var refresh = !this.cacheKey || this.cacheKey !== previous.cacheKey;
if (refresh) {
if (self.state.onupdate) {
this.afterRender(function () {
self.state.onupdate(self.component.element);
});
}
}
this.component = previous.component;
if (previous.state && this.state) {
var keys = Object.keys(this.state);
for(var n = 0; n < keys.length; n++) {
var key = keys[n];
previous.state[key] = self.state[key];
}
this.state = previous.state;
}
if (refresh) {
var element = this.component.update(this.render(this));
if (self.state.detached) {
return document.createTextNode('');
} else {
return element;
}
}
};
ComponentWidget.prototype.refresh = function () {
this.component.update(this.render(this));
if (this.state.onupdate) {
this.state.onupdate(this.component.element);
}
};
ComponentWidget.prototype.rerender = ComponentWidget.prototype.refresh;
ComponentWidget.prototype.destroy = function (element) {
var self = this;
if (self.state.onremove) {
this.afterRender(function () {
self.state.onremove(element);
});
}
this.component.destroy();
};
module.exports = function (state, vdom) {
deprecations.component('hyperdom.html.component is deprecated, please use ViewModels');
if (typeof state === 'function') {
return new ComponentWidget({}, state);
} else if (state.constructor === Object) {
return new ComponentWidget(state, vdom);
} else {
return new ComponentWidget({}, state);
}
};
module.exports.ComponentWidget = ComponentWidget;
},{".":"hyperdom","./deprecations":3,"./domComponent":4,"virtual-dom/vnode/vtext.js":32}],3:[function(require,module,exports){
function deprecationWarning() {
var warningIssued = false;
return function (arg) {
if (!warningIssued) {
console.warn(arg);
warningIssued = true;
}
};
}
module.exports = {
refresh: deprecationWarning(),
currentRender: deprecationWarning(),
window: deprecationWarning(),
component: deprecationWarning(),
renderFunction: deprecationWarning(),
refreshAfter: deprecationWarning(),
norefresh: deprecationWarning()
};
},{}],4:[function(require,module,exports){
var createElement = require('virtual-dom/create-element');
var diff = require('virtual-dom/diff');
var patch = require('virtual-dom/patch');
var toVdom = require('./toVdom');
var isVdom = require('./isVdom');
function DomComponent(options) {
this.document = options && options.document;
}
function prepareVdom(object) {
var vdom = toVdom(object);
if (!isVdom(vdom)) {
throw new Error('expected render to return vdom');
} else {
return vdom;
}
}
DomComponent.prototype.create = function (vdom) {
this.vdom = prepareVdom(vdom);
return this.element = createElement(this.vdom, {document: this.document});
};
DomComponent.prototype.merge = function (vdom, element) {
this.vdom = prepareVdom(vdom);
return this.element = element;
};
DomComponent.prototype.update = function (vdom) {
var oldVdom = this.vdom;
this.vdom = prepareVdom(vdom);
var patches = diff(oldVdom, this.vdom);
return this.element = patch(this.element, patches);
};
DomComponent.prototype.destroy = function (options) {
function destroyWidgets(vdom) {
if (vdom.type === 'Widget') {
vdom.destroy();
} else if (vdom.children) {
vdom.children.forEach(destroyWidgets);
}
}
destroyWidgets(this.vdom);
if (options && options.removeElement && this.element.parentNode) {
this.element.parentNode.removeChild(this.element);
}
};
function domComponent(options) {
return new DomComponent(options);
}
module.exports = domComponent;
},{"./isVdom":5,"./toVdom":40,"virtual-dom/create-element":8,"virtual-dom/diff":9,"virtual-dom/patch":14}],5:[function(require,module,exports){
var virtualDomVersion = require("virtual-dom/vnode/version")
module.exports = function(x) {
var type = x.type;
if (type == 'VirtualNode' || type == 'VirtualText') {
return x.version == virtualDomVersion;
} else {
return type == 'Widget' || type == 'Thunk';
}
};
},{"virtual-dom/vnode/version":29}],6:[function(require,module,exports){
module.exports = function (model, property) {
var hyperdomMeta = model._hyperdomMeta;
if (!hyperdomMeta) {
hyperdomMeta = {};
Object.defineProperty(model, '_hyperdomMeta', {value: hyperdomMeta});
}
if (property) {
var meta = hyperdomMeta[property];
if (!meta) {
meta = hyperdomMeta[property] = {};
}
return meta;
} else {
return hyperdomMeta;
}
};
},{}],7:[function(require,module,exports){
var hyperdomMeta = require('./meta');
var runRender = require('./runRender');
var hyperdom = require('.');
var Set = require('./set');
var lastId = 0;
function Mount(model, options) {
var win = (options && options.window) || window;
this.requestRender = (options && options.requestRender) || win.requestAnimationFrame || win.setTimeout;
this.model = model;
this.renderQueued = false;
this.mountRenderRequested = false;
this.widgetRendersRequested = undefined;
this.id = ++lastId;
this.mounted = true;
}
Mount.prototype.queueRender = function () {
if (!this.renderQueued) {
var requestRender = this.requestRender;
var self = this;
requestRender(function () {
self.renderQueued = false;
if (self.mounted) {
runRender(self, function () {
if (self.mountRenderRequested) {
var vdom = self.render();
self.component.update(vdom);
self.mountRenderRequested = false;
} else if (self.widgetRendersRequested && self.widgetRendersRequested.length) {
for (var i = 0, l = self.widgetRendersRequested.length; i < l; i++) {
var w = self.widgetRendersRequested[i];
w.rerender();
}
self.widgetRendersRequested = undefined;
}
});
}
});
this.renderQueued = true;
}
};
Mount.prototype.render = function() {
return this.renderViewModel(this.model);
};
Mount.prototype.rerender = function () {
this.mountRenderRequested = true;
this.queueRender();
};
Mount.prototype.rerenderWidget = function (widget) {
if (!this.widgetRendersRequested) {
this.widgetRendersRequested = [];
}
this.widgetRendersRequested.push(widget);
this.queueRender();
};
Mount.prototype._renderViewModel = function(model) {
var self = this;
model.rerender = function () {
self.rerender();
};
model.rerenderViewModel = function() {
var meta = hyperdomMeta(this);
meta.widgets.forEach(function (w) {
self.rerenderWidget(w);
});
};
var meta = hyperdomMeta(model);
if (!meta.mount) {
meta.mount = this;
}
if (!meta.widgets) {
meta.widgets = new Set();
}
if (typeof model.onload == 'function') {
if (!meta.loaded) {
meta.loaded = true;
hyperdom.refreshify(function () { return model.onload(); }, {refresh: 'promise'})();
}
}
var vdom = model.render();
if (vdom instanceof Array) {
throw new Error('vdom returned from component cannot be an array');
}
if (vdom && vdom.properties) {
vdom.properties._hyperdomViewModel = model;
}
return vdom;
}
Mount.prototype.renderViewModel = function(model) {
if (typeof model.renderCacheKey === 'function') {
var meta = hyperdomMeta(model);
var key = model.renderCacheKey();
if (key !== undefined && meta.cacheKey === key && meta.cachedVdom) {
return meta.cachedVdom;
} else {
meta.cacheKey = key;
return meta.cachedVdom = this._renderViewModel(model);
}
} else {
return this._renderViewModel(model);
}
};
Mount.prototype.detach = function () {
this.mounted = false;
};
Mount.prototype.remove = function () {
this.component.destroy({removeElement: true});
this.mounted = false;
};
module.exports = Mount;
},{".":"hyperdom","./meta":6,"./runRender":37,"./set":38}],8:[function(require,module,exports){
var createElement = require("./vdom/create-element.js")
module.exports = createElement
},{"./vdom/create-element.js":16}],9:[function(require,module,exports){
var diff = require("./vtree/diff.js")
module.exports = diff
},{"./vtree/diff.js":34}],10:[function(require,module,exports){
/*!
* Cross-Browser Split 1.1.1
* Copyright 2007-2012 Steven Levithan <stevenlevithan.com>
* Available under the MIT License
* ECMAScript compliant, uniform cross-browser split method
*/
/**
* Splits a string into an array of strings using a regex or string separator. Matches of the
* separator are not included in the result array. However, if `separator` is a regex that contains
* capturing groups, backreferences are spliced into the result each time `separator` is matched.
* Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
* cross-browser.
* @param {String} str String to split.
* @param {RegExp|String} separator Regex or string to use for separating the string.
* @param {Number} [limit] Maximum number of items to include in the result array.
* @returns {Array} Array of substrings.
* @example
*
* // Basic use
* split('a b c d', ' ');
* // -> ['a', 'b', 'c', 'd']
*
* // With limit
* split('a b c d', ' ', 2);
* // -> ['a', 'b']
*
* // Backreferences in result array
* split('..word1 word2..', /([a-z]+)(\d+)/i);
* // -> ['..', 'word', '1', ' ', 'word', '2', '..']
*/
module.exports = (function split(undef) {
var nativeSplit = String.prototype.split,
compliantExecNpcg = /()??/.exec("")[1] === undef,
// NPCG: nonparticipating capturing group
self;
self = function(str, separator, limit) {
// If `separator` is not a regex, use `nativeSplit`
if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
return nativeSplit.call(str, separator, limit);
}
var output = [],
flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
(separator.sticky ? "y" : ""),
// Firefox 3+
lastLastIndex = 0,
// Make `global` and avoid `lastIndex` issues by working with a copy
separator = new RegExp(separator.source, flags + "g"),
separator2, match, lastIndex, lastLength;
str += ""; // Type-convert
if (!compliantExecNpcg) {
// Doesn't need flags gy, but they don't hurt
separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
}
/* Values for `limit`, per the spec:
* If undefined: 4294967295 // Math.pow(2, 32) - 1
* If 0, Infinity, or NaN: 0
* If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
* If negative number: 4294967296 - Math.floor(Math.abs(limit))
* If other: Type-convert, then use the above rules
*/
limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
limit >>> 0; // ToUint32(limit)
while (match = separator.exec(str)) {
// `separator.lastIndex` is not reliable cross-browser
lastIndex = match.index + match[0].length;
if (lastIndex > lastLastIndex) {
output.push(str.slice(lastLastIndex, match.index));
// Fix browsers whose `exec` methods don't consistently return `undefined` for
// nonparticipating capturing groups
if (!compliantExecNpcg && match.length > 1) {
match[0].replace(separator2, function() {
for (var i = 1; i < arguments.length - 2; i++) {
if (arguments[i] === undef) {
match[i] = undef;
}
}
});
}
if (match.length > 1 && match.index < str.length) {
Array.prototype.push.apply(output, match.slice(1));
}
lastLength = match[0].length;
lastLastIndex = lastIndex;
if (output.length >= limit) {
break;
}
}
if (separator.lastIndex === match.index) {
separator.lastIndex++; // Avoid an infinite loop
}
}
if (lastLastIndex === str.length) {
if (lastLength || !separator.test("")) {
output.push("");
}
} else {
output.push(str.slice(lastLastIndex));
}
return output.length > limit ? output.slice(0, limit) : output;
};
return self;
})();
},{}],11:[function(require,module,exports){
(function (global){
var topLevel = typeof global !== 'undefined' ? global :
typeof window !== 'undefined' ? window : {}
var minDoc = require('min-document');
if (typeof document !== 'undefined') {
module.exports = document;
} else {
var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
if (!doccy) {
doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
}
module.exports = doccy;
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"min-document":1}],12:[function(require,module,exports){
"use strict";
module.exports = function isObject(x) {
return typeof x === "object" && x !== null;
};
},{}],13:[function(require,module,exports){
var nativeIsArray = Array.isArray
var toString = Object.prototype.toString
module.exports = nativeIsArray || isArray
function isArray(obj) {
return toString.call(obj) === "[object Array]"
}
},{}],14:[function(require,module,exports){
var patch = require("./vdom/patch.js")
module.exports = patch
},{"./vdom/patch.js":19}],15:[function(require,module,exports){
var isObject = require("is-object")
var isHook = require("../vnode/is-vhook.js")
module.exports = applyProperties
function applyProperties(node, props, previous) {
for (var propName in props) {
var propValue = props[propName]
if (propValue === undefined) {
removeProperty(node, propName, propValue, previous);
} else if (isHook(propValue)) {
removeProperty(node, propName, propValue, previous)
if (propValue.hook) {
propValue.hook(node,
propName,
previous ? previous[propName] : undefined)
}
} else {
if (isObject(propValue)) {
patchObject(node, props, previous, propName, propValue);
} else {
node[propName] = propValue
}
}
}
}
function removeProperty(node, propName, propValue, previous) {
if (previous) {
var previousValue = previous[propName]
if (!isHook(previousValue)) {
if (propName === "attributes") {
for (var attrName in previousValue) {
node.removeAttribute(attrName)
}
} else if (propName === "style") {
for (var i in previousValue) {
node.style[i] = ""
}
} else if (typeof previousValue === "string") {
node[propName] = ""
} else {
node[propName] = null
}
} else if (previousValue.unhook) {
previousValue.unhook(node, propName, propValue)
}
}
}
function patchObject(node, props, previous, propName, propValue) {
var previousValue = previous ? previous[propName] : undefined
// Set attributes
if (propName === "attributes") {
for (var attrName in propValue) {
var attrValue = propValue[attrName]
if (attrValue === undefined) {
node.removeAttribute(attrName)
} else {
node.setAttribute(attrName, attrValue)
}
}
return
}
if(previousValue && isObject(previousValue) &&
getPrototype(previousValue) !== getPrototype(propValue)) {
node[propName] = propValue
return
}
if (!isObject(node[propName])) {
node[propName] = {}
}
var replacer = propName === "style" ? "" : undefined
for (var k in propValue) {
var value = propValue[k]
node[propName][k] = (value === undefined) ? replacer : value
}
}
function getPrototype(value) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(value)
} else if (value.__proto__) {
return value.__proto__
} else if (value.constructor) {
return value.constructor.prototype
}
}
},{"../vnode/is-vhook.js":25,"is-object":12}],16:[function(require,module,exports){
var document = require("global/document")
var applyProperties = require("./apply-properties")
var isVNode = require("../vnode/is-vnode.js")
var isVText = require("../vnode/is-vtext.js")
var isWidget = require("../vnode/is-widget.js")
var handleThunk = require("../vnode/handle-thunk.js")
module.exports = createElement
function createElement(vnode, opts) {
var doc = opts ? opts.document || document : document
var warn = opts ? opts.warn : null
vnode = handleThunk(vnode).a
if (isWidget(vnode)) {
return vnode.init()
} else if (isVText(vnode)) {
return doc.createTextNode(vnode.text)
} else if (!isVNode(vnode)) {
if (warn) {
warn("Item is not a valid virtual dom node", vnode)
}
return null
}
var node = (vnode.namespace === null) ?
doc.createElement(vnode.tagName) :
doc.createElementNS(vnode.namespace, vnode.tagName)
var props = vnode.properties
applyProperties(node, props)
var children = vnode.children
for (var i = 0; i < children.length; i++) {
var childNode = createElement(children[i], opts)
if (childNode) {
node.appendChild(childNode)
}
}
return node
}
},{"../vnode/handle-thunk.js":23,"../vnode/is-vnode.js":26,"../vnode/is-vtext.js":27,"../vnode/is-widget.js":28,"./apply-properties":15,"global/document":11}],17:[function(require,module,exports){
// Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
// We don't want to read all of the DOM nodes in the tree so we use
// the in-order tree indexing to eliminate recursion down certain branches.
// We only recurse into a DOM node if we know that it contains a child of
// interest.
var noChild = {}
module.exports = domIndex
function domIndex(rootNode, tree, indices, nodes) {
if (!indices || indices.length === 0) {
return {}
} else {
indices.sort(ascending)
return recurse(rootNode, tree, indices, nodes, 0)
}
}
function recurse(rootNode, tree, indices, nodes, rootIndex) {
nodes = nodes || {}
if (rootNode) {
if (indexInRange(indices, rootIndex, rootIndex)) {
nodes[rootIndex] = rootNode
}
var vChildren = tree.children
if (vChildren) {
var childNodes = rootNode.childNodes
for (var i = 0; i < tree.children.length; i++) {
rootIndex += 1
var vChild = vChildren[i] || noChild
var nextIndex = rootIndex + (vChild.count || 0)
// skip recursion down the tree if there are no nodes down here
if (indexInRange(indices, rootIndex, nextIndex)) {
recurse(childNodes[i], vChild, indices, nodes, rootIndex)
}
rootIndex = nextIndex
}
}
}
return nodes
}
// Binary search for an index in the interval [left, right]
function indexInRange(indices, left, right) {
if (indices.length === 0) {
return false
}
var minIndex = 0
var maxIndex = indices.length - 1
var currentIndex
var currentItem
while (minIndex <= maxIndex) {
currentIndex = ((maxIndex + minIndex) / 2) >> 0
currentItem = indices[currentIndex]
if (minIndex === maxIndex) {
return currentItem >= left && currentItem <= right
} else if (currentItem < left) {
minIndex = currentIndex + 1
} else if (currentItem > right) {
maxIndex = currentIndex - 1
} else {
return true
}
}
return false;
}
function ascending(a, b) {
return a > b ? 1 : -1
}
},{}],18:[function(require,module,exports){
var applyProperties = require("./apply-properties")
var isWidget = require("../vnode/is-widget.js")
var VPatch = require("../vnode/vpatch.js")
var updateWidget = require("./update-widget")
module.exports = applyPatch
function applyPatch(vpatch, domNode, renderOptions) {
var type = vpatch.type
var vNode = vpatch.vNode
var patch = vpatch.patch
switch (type) {
case VPatch.REMOVE:
return removeNode(domNode, vNode)
case VPatch.INSERT:
return insertNode(domNode, patch, renderOptions)
case VPatch.VTEXT:
return stringPatch(domNode, vNode, patch, renderOptions)
case VPatch.WIDGET:
return widgetPatch(domNode, vNode, patch, renderOptions)
case VPatch.VNODE:
return vNodePatch(domNode, vNode, patch, renderOptions)
case VPatch.ORDER:
reorderChildren(domNode, patch)
return domNode
case VPatch.PROPS:
applyProperties(domNode, patch, vNode.properties)
return domNode
case VPatch.THUNK:
return replaceRoot(domNode,
renderOptions.patch(domNode, patch, renderOptions))
default:
return domNode
}
}
function removeNode(domNode, vNode) {
var parentNode = domNode.parentNode
if (parentNode) {
parentNode.removeChild(domNode)
}
destroyWidget(domNode, vNode);
return null
}
function insertNode(parentNode, vNode, renderOptions) {
var newNode = renderOptions.render(vNode, renderOptions)
if (parentNode) {
parentNode.appendChild(newNode)
}
return parentNode
}
function stringPatch(domNode, leftVNode, vText, renderOptions) {
var newNode
if (domNode.nodeType === 3) {
domNode.replaceData(0, domNode.length, vText.text)
newNode = domNode
} else {
var parentNode = domNode.parentNode
newNode = renderOptions.render(vText, renderOptions)
if (parentNode && newNode !== domNode) {
parentNode.replaceChild(newNode, domNode)
}
}
return newNode
}
function widgetPatch(domNode, leftVNode, widget, renderOptions) {
var updating = updateWidget(leftVNode, widget)
var newNode
if (updating) {
newNode = widget.update(leftVNode, domNode) || domNode
} else {
newNode = renderOptions.render(widget, renderOptions)
}
var parentNode = domNode.parentNode
if (parentNode && newNode !== domNode) {
parentNode.replaceChild(newNode, domNode)
}
if (!updating) {
destroyWidget(domNode, leftVNode)
}
return newNode
}
function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
var parentNode = domNode.parentNode
var newNode = renderOptions.render(vNode, renderOptions)
if (parentNode && newNode !== domNode) {
parentNode.replaceChild(newNode, domNode)
}
return newNode
}
function destroyWidget(domNode, w) {
if (typeof w.destroy === "function" && isWidget(w)) {
w.destroy(domNode)
}
}
function reorderChildren(domNode, moves) {
var childNodes = domNode.childNodes
var keyMap = {}
var node
var remove
var insert
for (var i = 0; i < moves.removes.length; i++) {
remove = moves.removes[i]
node = childNodes[remove.from]
if (remove.key) {
keyMap[remove.key] = node
}
domNode.removeChild(node)
}
var length = childNodes.length
for (var j = 0; j < moves.inserts.length; j++) {
insert = moves.inserts[j]
node = keyMap[insert.key]
// this is the weirdest bug i've ever seen in webkit
domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to])
}
}
function replaceRoot(oldRoot, newRoot) {
if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
oldRoot.parentNode.replaceChild(newRoot, oldRoot)
}
return newRoot;
}
},{"../vnode/is-widget.js":28,"../vnode/vpatch.js":31,"./apply-properties":15,"./update-widget":20}],19:[function(require,module,exports){
var document = require("global/document")
var isArray = require("x-is-array")
var render = require("./create-element")
var domIndex = require("./dom-index")
var patchOp = require("./patch-op")
module.exports = patch
function patch(rootNode, patches, renderOptions) {
renderOptions = renderOptions || {}
renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch
? renderOptions.patch
: patchRecursive
renderOptions.render = renderOptions.render || render
return renderOptions.patch(rootNode, patches, renderOptions)
}
function patchRecursive(rootNode, patches, renderOptions) {
var indices = patchIndices(patches)
if (indices.length === 0) {
return rootNode
}
var index = domIndex(rootNode, patches.a, indices)
var ownerDocument = rootNode.ownerDocument
if (!renderOptions.document && ownerDocument !== document) {
renderOptions.document = ownerDocument
}
for (var i = 0; i < indices.length; i++) {
var nodeIndex = indices[i]
rootNode = applyPatch(rootNode,
index[nodeIndex],
patches[nodeIndex],
renderOptions)
}
return rootNode
}
function applyPatch(rootNode, domNode, patchList, renderOptions) {
if (!domNode) {
return rootNode
}
var newNode
if (isArray(patchList)) {
for (var i = 0; i < patchList.length; i++) {
newNode = patchOp(patchList[i], domNode, renderOptions)
if (domNode === rootNode) {
rootNode = newNode
}
}
} else {
newNode = patchOp(patchList, domNode, renderOptions)
if (domNode === rootNode) {
rootNode = newNode
}
}
return rootNode
}
function patchIndices(patches) {
var indices = []
for (var key in patches) {
if (key !== "a") {
indices.push(Number(key))
}
}
return indices
}
},{"./create-element":16,"./dom-index":17,"./patch-op":18,"global/document":11,"x-is-array":13}],20:[function(require,module,exports){
var isWidget = require("../vnode/is-widget.js")
module.exports = updateWidget
function updateWidget(a, b) {
if (isWidget(a) && isWidget(b)) {
if ("name" in a && "name" in b) {
return a.id === b.id
} else {
return a.init === b.init
}
}
return false
}
},{"../vnode/is-widget.js":28}],21:[function(require,module,exports){
'use strict';
module.exports = SoftSetHook;
function SoftSetHook(value) {
if (!(this instanceof SoftSetHook)) {
return new SoftSetHook(value);
}
this.value = value;
}
SoftSetHook.prototype.hook = function (node, propertyName) {
if (node[propertyName] !== this.value) {
node[propertyName] = this.value;
}
};
},{}],22:[function(require,module,exports){
'use strict';
var split = require('browser-split');
var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/;
var notClassId = /^\.|#/;
module.exports = parseTag;
function parseTag(tag, props) {
if (!tag) {
return 'DIV';
}
var noId = !(props.hasOwnProperty('id'));
var tagParts = split(tag, classIdSplit);
var tagName = null;
if (notClassId.test(tagParts[1])) {
tagName = 'DIV';
}
var classes, part, type, i;
for (i = 0; i < tagParts.length; i++) {
part = tagParts[i];
if (!part) {
continue;
}
type = part.charAt(0);
if (!tagName) {
tagName = part;
} else if (type === '.') {
classes = classes || [];
classes.push(part.substring(1, part.length));
} else if (type === '#' && noId) {
props.id = part.substring(1, part.length);
}
}
if (classes) {
if (props.className) {
classes.push(props.className);
}
props.className = classes.join(' ');
}
return props.namespace ? tagName : tagName.toUpperCase();
}
},{"browser-split":10}],23:[function(require,module,exports){
var isVNode = require("./is-vnode")
var isVText = require("./is-vtext")
var isWidget = require("./is-widget")
var isThunk = require("./is-thunk")
module.exports = handleThunk
function handleThunk(a, b) {
var renderedA = a
var renderedB = b
if (isThunk(b)) {
renderedB = renderThunk(b, a)
}
if (isThunk(a)) {
renderedA = renderThunk(a, null)
}
return {
a: renderedA,
b: renderedB
}
}
function renderThunk(thunk, previous) {
var renderedThunk = thunk.vnode
if (!renderedThunk) {
renderedThunk = thunk.vnode = thunk.render(previous)
}
if (!(isVNode(renderedThunk) ||
isVText(renderedThunk) ||
isWidget(renderedThunk))) {
throw new Error("thunk did not return a valid node");
}
return renderedThunk
}
},{"./is-thunk":24,"./is-vnode":26,"./is-vtext":27,"./is-widget":28}],24:[function(require,module,exports){
module.exports = isThunk
function isThunk(t) {
return t && t.type === "Thunk"
}
},{}],25:[function(require,module,exports){
module.exports = isHook
function isHook(hook) {
return hook &&
(typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
}
},{}],26:[function(require,module,exports){
var version = require("./version")
module.exports = isVirtualNode
function isVirtualNode(x) {
return x && x.type === "VirtualNode" && x.version === version
}
},{"./version":29}],27:[function(require,module,exports){
var version = require("./version")
module.exports = isVirtualText
function isVirtualText(x) {
return x && x.type === "VirtualText" && x.version === version
}
},{"./version":29}],28:[function(require,module,exports){
module.exports = isWidget
function isWidget(w) {
return w && w.type === "Widget"
}
},{}],29:[function(require,module,exports){
module.exports = "2"
},{}],30:[function(require,module,exports){
var version = require("./version")
var isVNode = require("./is-vnode")
var isWidget = require("./is-widget")
var isThunk = require("./is-thunk")
var isVHook = require("./is-vhook")
module.exports = VirtualNode
var noProperties = {}
var noChildren = []
function VirtualNode(tagName, properties, children, key, namespace) {
this.tagName = tagName
this.properties = properties || noProperties
this.children = children || noChildren
this.key = key != null ? String(key) : undefined
this.namespace = (typeof namespace === "string") ? namespace : null
var count = (children && children.length) || 0
var descendants = 0
var hasWidgets = false
var hasThunks = false
var descendantHooks = false
var hooks
for (var propName in properties) {
if (properties.hasOwnProperty(propName)) {
var property = properties[propName]
if (isVHook(property) && property.unhook) {
if (!hooks) {
hooks = {}
}
hooks[propName] = property
}
}
}
for (var i = 0; i < count; i++) {
var child = children[i]
if (isVNode(child)) {
descendants += child.count || 0
if (!hasWidgets && child.hasWidgets) {
hasWidgets = true
}
if (!hasThunks && child.hasThunks) {
hasThunks = true
}
if (!descendantHooks && (child.hooks || child.descendantHooks)) {
descendantHooks = true
}
} else if (!hasWidgets && isWidget(child)) {
if (typeof child.destroy === "function") {
hasWidgets = true
}
} else if (!hasThunks && isThunk(child)) {
hasThunks = true;
}
}
this.count = count + descendants
this.hasWidgets = hasWidgets
this.hasThunks = hasThunks
this.hooks = hooks
this.descendantHooks = descendantHooks
}
VirtualNode.prototype.version = version
VirtualNode.prototype.type = "VirtualNode"
},{"./is-thunk":24,"./is-vhook":25,"./is-vnode":26,"./is-widget":28,"./version":29}],31:[function(require,module,exports){
var version = require("./version")
VirtualPatch.NONE = 0
VirtualPatch.VTEXT = 1
VirtualPatch.VNODE = 2
VirtualPatch.WIDGET = 3
VirtualPatch.PROPS = 4
VirtualPatch.ORDER = 5
VirtualPatch.INSERT = 6
VirtualPatch.REMOVE = 7
VirtualPatch.THUNK = 8
module.exports = VirtualPatch
function VirtualPatch(type, vNode, patch) {
this.type = Number(type)
this.vNode = vNode
this.patch = patch
}
VirtualPatch.prototype.version = version
VirtualPatch.prototype.type = "VirtualPatch"
},{"./version":29}],32:[function(require,module,exports){
var version = require("./version")
module.exports = VirtualText
function VirtualText(text) {
this.text = String(text)
}
VirtualText.prototype.version = version
VirtualText.prototype.type = "VirtualText"
},{"./version":29}],33:[function(require,module,exports){
var isObject = require("is-object")
var isHook = require("../vnode/is-vhook")
module.exports = diffProps
function diffProps(a, b) {
var diff
for (var aKey in a) {
if (!(aKey in b)) {
diff = diff || {}
diff[aKey] = undefined
}
var aValue = a[aKey]
var bValue = b[aKey]
if (aValue === bValue) {
continue
} else if (isObject(aValue) && isObject(bValue)) {
if (getPrototype(bValue) !== getPrototype(aValue)) {
diff = diff || {}
diff[aKey] = bValue
} else if (isHook(bValue)) {
diff = diff || {}
diff[aKey] = bValue
} else {
var objectDiff = diffProps(aValue, bValue)
if (objectDiff) {
diff = diff || {}
diff[aKey] = objectDiff
}
}
} else {
diff = diff || {}
diff[aKey] = bValue
}
}
for (var bKey in b) {
if (!(bKey in a)) {
diff = diff || {}
diff[bKey] = b[bKey]
}
}
return diff
}
function getPrototype(value) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(value)
} else if (value.__proto__) {
return value.__proto__
} else if (value.constructor) {
return value.constructor.prototype
}
}
},{"../vnode/is-vhook":25,"is-object":12}],34:[function(require,module,exports){
var isArray = require("x-is-array")
var VPatch = require("../vnode/vpatch")
var isVNode = require("../vnode/is-vnode")
var isVText = require("../vnode/is-vtext")
var isWidget = require("../vnode/is-widget")
var isThunk = require("../vnode/is-thunk")
var handleThunk = require("../vnode/handle-thunk")
var diffProps = require("./diff-props")
module.exports = diff
function diff(a, b) {
var patch = { a: a }
walk(a, b, patch, 0)
return patch
}
function walk(a, b, patch, index) {
if (a === b) {
return
}
var apply = patch[index]
var applyClear = false
if (isThunk(a) || isThunk(b)) {
thunks(a, b, patch, index)
} else if (b == null) {
// If a is a widget we will add a remove patch for it
// Otherwise any child widgets/hooks must be destroyed.
// This prevents adding two remove patches for a widget.
if (!isWidget(a)) {
clearState(a, patch, index)
apply = patch[index]
}
apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
} else if (isVNode(b)) {
if (isVNode(a)) {
if (a.tagName === b.tagName &&
a.namespace === b.namespace &&
a.key === b.key) {
var propsPatch = diffProps(a.properties, b.properties)
if (propsPatch) {
apply = appendPatch(apply,
new VPatch(VPatch.PROPS, a, propsPatch))
}
apply = diffChildren(a, b, patch, apply, index)
} else {
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
applyClear = true
}
} else {
apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
applyClear = true
}
} else if (isVText(b)) {
if (!isVText(a)) {
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
applyClear = true
} else if (a.text !== b.text) {
apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
}
} else if (isWidget(b)) {
if (!isWidget(a)) {
applyClear = true
}
apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
}
if (apply) {
patch[index] = apply
}
if (applyClear) {
clearState(a, patch, index)
}
}
function diffChildren(a, b, patch, apply, index) {
var aChildren = a.children
var orderedSet = reorder(aChildren, b.children)
var bChildren = orderedSet.children
var aLen = aChildren.length
var bLen = bChildren.length
var len = aLen > bLen ? aLen : bLen
for (var i = 0; i < len; i++) {
var leftNode = aChildren[i]
var rightNode = bChildren[i]
index += 1
if (!leftNode) {
if (rightNode) {
// Excess nodes in b need to be added
apply = appendPatch(apply,
new VPatch(VPatch.INSERT, null, rightNode))
}
} else {
walk(leftNode, rightNode, patch, index)
}
if (isVNode(leftNode) && leftNode.count) {
index += leftNode.count
}
}
if (orderedSet.moves) {
// Reorder nodes last
apply = appendPatch(apply, new VPatch(
VPatch.ORDER,
a,
orderedSet.moves
))
}
return apply
}
function clearState(vNode, patch, index) {
// TODO: Make this a single walk, not two
unhook(vNode, patch, index)
destroyWidgets(vNode, patch, index)
}
// Patch records for all destroyed widgets must be added because we need
// a DOM node reference for the destroy function
function destroyWidgets(vNode, patch, index) {
if (isWidget(vNode)) {
if (typeof vNode.destroy === "function") {
patch[index] = appendPatch(
patch[index],
new VPatch(VPatch.REMOVE, vNode, null)
)
}
} else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
var children = vNode.children
var len = children.length
for (var i = 0; i < len; i++) {
var child = children[i]
index += 1
destroyWidgets(child, patch, index)
if (isVNode(child) && child.count) {
index += child.count
}
}
} else if (isThunk(vNode)) {
thunks(vNode, null, patch, index)
}
}
// Create a sub-patch for thunks
function thunks(a, b, patch, index) {
var nodes = handleThunk(a, b)
var thunkPatch = diff(nodes.a, nodes.b)
if (hasPatches(thunkPatch)) {
patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
}
}
function hasPatches(patch) {
for (var index in patch) {
if (index !== "a") {
return true
}
}
return false
}
// Execute hooks when two nodes are identical
function unhook(vNode, patch, index) {
if (isVNode(vNode)) {
if (vNode.hooks) {
patch[index] = appendPatch(
patch[index],
new VPatch(
VPatch.PROPS,
vNode,
undefinedKeys(vNode.hooks)
)
)
}
if (vNode.descendantHooks || vNode.hasThunks) {
var children = vNode.children
var len = children.length
for (var i = 0; i < len; i++) {
var child = children[i]
index += 1
unhook(child, patch, index)
if (isVNode(child) && child.count) {
index += child.count
}
}
}
} else if (isThunk(vNode)) {
thunks(vNode, null, patch, index)
}
}
function undefinedKeys(obj) {
var result = {}
for (var key in obj) {
result[key] = undefined
}
return result
}
// List diff, naive left to right reordering
function reorder(aChildren, bChildren) {
// O(M) time, O(M) memory
var bChildIndex = keyIndex(bChildren)
var bKeys = bChildIndex.keys
var bFree = bChildIndex.free
if (bFree.length === bChildren.length) {
return {
children: bChildren,
moves: null
}
}
// O(N) time, O(N) memory
var aChildIndex = keyIndex(aChildren)
var aKeys = aChildIndex.keys
var aFree = aChildIndex.free
if (aFree.length === aChildren.length) {
return {
children: bChildren,
moves: null
}
}
// O(MAX(N, M)) memory
var newChildren = []
var freeIndex = 0
var freeCount = bFree.length
var deletedItems = 0
// Iterate through a and match a node in b
// O(N) time,
for (var i = 0 ; i < aChildren.length; i++) {
var aItem = aChildren[i]
var itemIndex
if (aItem.key) {
if (bKeys.hasOwnProperty(aItem.key)) {
// Match up the old keys
itemIndex = bKeys[aItem.key]
newChildren.push(bChildren[itemIndex])
} else {
// Remove old keyed items
itemIndex = i - deletedItems++
newChildren.push(null)
}
} else {
// Match the item in a with the next free item in b
if (freeIndex < freeCount) {
itemIndex = bFree[freeIndex++]
newChildren.push(bChildren[itemIndex])
} else {
// There are no free items in b to match with
// the free items in a, so the extra free nodes
// are deleted.
itemIndex = i - deletedItems++
newChildren.push(null)
}
}
}
var lastFreeIndex = freeIndex >= bFree.length ?
bChildren.length :
bFree[freeIndex]
// Iterate through b and append any new keys
// O(M) time
for (var j = 0; j < bChildren.length; j++) {
var newItem = bChildren[j]
if (newItem.key) {
if (!aKeys.hasOwnProperty(newItem.key)) {
// Add any new keyed items
// We are adding new items to the end and then sorting them
// in place. In future we should insert new items in place.
newChildren.push(newItem)
}
} else if (j >= lastFreeIndex) {
// Add any leftover non-keyed items
newChildren.push(newItem)
}
}
var simulate = newChildren.slice()
var simulateIndex = 0
var removes = []
var inserts = []
var simulateItem
for (var k = 0; k < bChildren.length;) {
var wantedItem = bChildren[k]
simulateItem = simulate[simulateIndex]
// remove items
while (simulateItem === null && simulate.length) {
removes.push(remove(simulate, simulateIndex, null))
simulateItem = simulate[simulateIndex]
}
if (!simulateItem || simulateItem.key !== wantedItem.key) {
// if we need a key in this position...
if (wantedItem.key) {
if (simulateItem && simulateItem.key) {
// if an insert doesn't put this key in place, it needs to move
if (bKeys[simulateItem.key] !== k + 1) {
removes.push(remove(simulate, simulateIndex, simulateItem.key))
simulateItem = simulate[simulateIndex]
// if the remove didn't put the wanted item in place, we need to insert it
if (!simulateItem || simulateItem.key !== wantedItem.key) {
inserts.push({key: wantedItem.key, to: k})
}
// items are matching, so skip ahead
else {
simulateIndex++
}
}
else {
inserts.push({key: wantedItem.key, to: k})
}
}
else {
inserts.push({key: wantedItem.key, to: k})
}
k++
}
// a key in simulate has no matching wanted key, remove it
else if (simulateItem && simulateItem.key) {
removes.push(remove(simulate, simulateIndex, simulateItem.key))
}
}
else {
simulateIndex++
k++
}
}
// remove all the remaining nodes from simulate
while(simulateIndex < simulate.length) {
simulateItem = simulate[simulateIndex]
removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key))
}
// If the only moves we have are deletes then we can just
// let the delete patch remove these items.
if (removes.length === deletedItems && !inserts.length) {
return {
children: newChildren,
moves: null
}
}
return {
children: newChildren,
moves: {
removes: removes,
inserts: inserts
}
}
}
function remove(arr, index, key) {
arr.splice(index, 1)
return {
from: index,
key: key
}
}
function keyIndex(children) {
var keys = {}
var free = []
var length = children.length
for (var i = 0; i < length; i++) {
var child = children[i]
if (child.key) {
keys[child.key] = i
} else {
free.push(i)
}
}
return {
keys: keys, // A hash of key name to index
free: free // An array of unkeyed item indices
}
}
function appendPatch(apply, patch) {
if (apply) {
if (isArray(apply)) {
apply.push(patch)
} else {
apply = [apply, patch]
}
return apply
} else {
return patch
}
}
},{"../vnode/handle-thunk":23,"../vnode/is-thunk":24,"../vnode/is-vnode":26,"../vnode/is-vtext":27,"../vnode/is-widget":28,"../vnode/vpatch":31,"./diff-props":33,"x-is-array":13}],35:[function(require,module,exports){
var simplePromise = require('./simplePromise');
function Render(mount) {
this.finished = simplePromise();
this.mount = mount;
this.attachment = mount;
}
module.exports = Render;
},{"./simplePromise":39}],36:[function(require,module,exports){
(function (global){
var h = require('./vhtml');
var domComponent = require('./domComponent');
var bindingMeta = require('./meta');
var toVdom = require('./toVdom');
var parseTag = require('virtual-dom/virtual-hyperscript/parse-tag');
var ViewModel = require('./viewModel');
var Mount = require('./mount');
var runRender = require('./runRender');
var deprecations = require('./deprecations');
var hyperdom = require('.');
function isViewModelOrComponent(component) {
return component
&& ((typeof component.init === 'function'
&& typeof component.update === 'function'
&& typeof component.destroy === 'function') || (typeof component.renderViewModel === 'function'));
}
exports.merge = function (element, render, model, options) {
var mount = startAttachment(render, model, options, function(mount, domComponentOptions) {
var component = domComponent(domComponentOptions);
var currentRender = hyperdom.currentRender;
currentRender.eventHandlerWrapper = function() {
return null;
};
var vdom = mount.render();
component.merge(vdom, element);
return component;
});
mount.rerender();
return mount;
};
exports.append = function (element, render, model, options) {
return startAttachment(render, model, options, function(mount, domComponentOptions) {
var component = domComponent(domComponentOptions);
var vdom = mount.render();
element.appendChild(component.create(vdom));
return component;
});
};
exports.replace = function (element, render, model, options) {
return startAttachment(render, model, options, function(mount, domComponentOptions) {
var component = domComponent(domComponentOptions);
var vdom = mount.render();
element.parentNode.replaceChild(component.create(vdom), element);
return component;
});
};
exports.appendVDom = function (vdom, render, model, options) {
return startAttachment(render, model, options, function(mount) {
var component = {
create: function(newVDom) {
vdom.children = [];
if (newVDom) {
vdom.children.push(newVDom);
}
},
update: function(newVDom) {
vdom.children = [];
if (newVDom) {
vdom.children.push(newVDom);
}
}
};
component.create(mount.render());
return component;
});
};
exports.ViewModel = ViewModel;
function startAttachment(render, model, options, attachToDom) {
if (typeof render == 'object' && typeof render.render == 'function') {
return start(render, attachToDom, model);
} else {
deprecations.renderFunction('hyperdom.append and hyperdom.replace with render functions are deprecated, please pass a ViewModel');
return start({render: function () { return render(model); }}, attachToDom, options);
}
}
function start(model, attachToDom, options) {
var mount = new Mount(model, options);
runRender(mount, function () {
if (options) {
var domComponentOptions = {document: options.document};
}
mount.component = attachToDom(mount, domComponentOptions);
});
return mount;
}
var norefresh = {};
function norefreshFunction() {
return norefresh;
}
function refreshify(fn, options) {
if (!fn) {
return fn;
}
var currentRender = hyperdom.currentRender();
if (!currentRender) {
if (typeof global === 'object') {
return fn;
} else {
throw new Error('You cannot create virtual-dom event handlers outside a render function. See https://github.com/featurist/hyperdom#outside-render-cycle');
}
}
var mount = currentRender.mount;
var handleEventResult = exports.createEventResultHandler(mount, options);
if (options && (options.norefresh == true || options.refresh == false)) {
return fn;
}
return function () {
var result = fn.apply(this, arguments);
return handleEventResult(result);
};
}
exports.createEventResultHandler = function(mount, options) {
var onlyRefreshAfterPromise = options && options.refresh == 'promise';
var viewModelToRefresh = options && options.viewModel;
var componentToRefresh = options && options.component;
function handleEventResult(result, promiseResult) {
if (result && typeof(result.then) == 'function') {
result.then(function (result) { handleEventResult(result, true); });
}
if (onlyRefreshAfterPromise && !promiseResult) {
return;
}
if (isViewModelOrComponent(result)) {
mount.rerenderWidget(result);
} else if (result instanceof Array) {
for (var i = 0; i < result.length; i++) {
handleEventResult(result[i]);
}
} else if (viewModelToRefresh) {
viewModelToRefresh.rerenderViewModel();
} else if (componentToRefresh) {
componentToRefresh.refresh();
} else if (result === norefresh) {
// don't refresh;
} else if (result === norefreshFunction) {
deprecations.norefresh('hyperdom.html.norefresh is deprecated, please use hyperdom.norefresh()');
// don't refresh;
} else {
mount.rerender();
return result;
}
}
return handleEventResult;
};
function bindTextInput(attributes, children, get, set) {
var textEventNames = ['onkeyup', 'oninput', 'onpaste', 'textInput'];
var bindingValue = get();
if (!(bindingValue instanceof Error)) {
attributes.value = bindingValue != undefined? bindingValue: '';
}
attachEventHandler(attributes, textEventNames, function (ev) {
if (bindingValue != ev.target.value) {
set(ev.target.value);
}
});
}
function sequenceFunctions(handler1, handler2) {
return function (ev) {
handler1(ev);
return handler2(ev);
};
}
function insertEventHandler(attributes, eventName, handler) {
var previousHandler = attributes[eventName];
if (previousHandler) {
attributes[eventName] = sequenceFunctions(handler, previousHandler);
} else {
attributes[eventName] = handler;
}
}
function attachEventHandler(attributes, eventNames, handler) {
if (eventNames instanceof Array) {
for (var n = 0; n < eventNames.length; n++) {
insertEventHandler(attributes, eventNames[n], handler);
}
} else {
insertEventHandler(attributes, eventNames, handler);
}
}
function ListenerHook(listener) {
this.listener = exports.html.refreshify(listener);
}
ListenerHook.prototype.hook = function (element, propertyName) {
element.addEventListener(propertyName.substring(2), this.listener, false);
};
ListenerHook.prototype.unhook = function (element, propertyName) {
element.removeEventListener(propertyName.substring(2), this.listener);
};
function customEvent(name) {
if (typeof Event == 'function') {
return new Event(name);
} else {
var event = document.createEvent('Event');
event.initEvent(name, false, false);
return event;
}
}
var inputTypeBindings = {
text: bindTextInput,
textarea: bindTextInput,
checkbox: function (attributes, children, get, set) {
attributes.checked = get();
attachEventHandler(attributes, 'onclick', function (ev) {
attributes.checked = ev.target.checked;
set(ev.target.checked);
});
},
radio: function (attributes, children, get, set) {
var value = attributes.value;
attributes.checked = get() == attributes.value;
attributes.on_hyperdomsyncchecked = new ListenerHook(function (event) {
attributes.checked = event.target.checked;
});
attachEventHandler(attributes, 'onclick', function (event) {
var name = event.target.name;
if (name) {
var inputs = document.getElementsByName(name);
for (var i = 0, l = inputs.length; i < l; i++) {
inputs[i].dispatchEvent(customEvent('_hyperdomsyncchecked'));
}
}
set(value);
});
},
select: function (attributes, children, get, set) {
var currentValue = get();
var options = children.filter(function (child) {
return child.tagName.toLowerCase() == 'option';
});
var values = [];
var selectedIndex;
for(var n = 0; n < options.length; n++) {
var option = options[n];
var hasValue = option.properties.hasOwnProperty('value');
var value = option.properties.value;
var text = option.children.map(function (x) { return x.text; }).join('');
values.push(hasValue? value: text);
var selected = value == currentValue || text == currentValue;
if (selected) {
selectedIndex = n;
}
option.properties.selected = selected;
option.properties.value = n;
}
if (selectedIndex !== undefined) {
attributes.selectedIndex = selectedIndex;
}
attachEventHandler(attributes, 'onchange', function (ev) {
attributes.selectedIndex = ev.target.selectedIndex;
set(values[ev.target.value]);
});
},
file: function (attributes, children, get, set) {
var multiple = attributes.multiple;
attachEventHandler(attributes, 'onchange', function (ev) {
if (multiple) {
set(ev.target.files);
} else {
set(ev.target.files[0]);
}
});
}
};
function bindModel(attributes, children, type) {
var bind = inputTypeBindings[type] || bindTextInput;
var bindingAttr = makeBinding(attributes.binding);
bind(attributes, children, bindingAttr.get, bindingAttr.set);
}
function inputType(selector, attributes) {
if (/^textarea\b/i.test(selector)) {
return 'textarea';
} else if (/^select\b/i.test(selector)) {
return 'select';
} else {
return attributes.type || 'text';
}
}
var renames = {
for: 'htmlFor',
class: 'className',
contenteditable: 'contentEditable',
tabindex: 'tabIndex',
colspan: 'colSpan'
};
var dataAttributeRegex = /^data-/;
function prepareAttributes(tag, attributes, childElements) {
var keys = Object.keys(attributes);
var dataset;
var currentRender = hyperdom.currentRender();
var eventHandlerWrapper = currentRender && currentRender.eventHandlerWrapper;
for (var k = 0; k < keys.length; k++) {
var key = keys[k];
var attribute = attributes[key];
if (typeof(attribute) == 'function') {
if (eventHandlerWrapper) {
var fn = eventHandlerWrapper.call(undefined, key.replace(/^on/, ''), attribute);
attributes[key] = typeof fn === 'function'? refreshify(fn): fn;
} else {
attributes[key] = refreshify(attribute);
}
}
var rename = renames[key];
if (rename) {
attributes[rename] = attribute;
delete attributes[key];
continue;
}
if (dataAttributeRegex.test(key)) {
if (!dataset) {
dataset = attributes.dataset;
if (!dataset) {
dataset = attributes.dataset = {};
}
}
var datakey = key
.replace(dataAttributeRegex, '')
.replace(/-([a-z])/ig, function(_, x) { return x.toUpperCase(); });
dataset[datakey] = attribute;
delete attributes[key];
continue;
}
}
if (attributes.className) {
attributes.className = generateClassName(attributes.className);
}
if (attributes.binding) {
bindModel(attributes, childElements, inputType(tag, attributes));
delete attributes.binding;
}
}
/**
* this function is quite ugly and you may be very tempted
* to refactor it into smaller functions, I certainly am.
* however, it was written like this for performance
* so think of that before refactoring! :)
*/
exports.html = function (hierarchySelector) {
var hasHierarchy = hierarchySelector.indexOf(' ') >= 0;
var selector, selectorElements;
if (hasHierarchy) {
selectorElements = hierarchySelector.match(/\S+/g);
selector = selectorElements[selectorElements.length - 1];
} else {
selector = hierarchySelector;
}
var childElements;
var vdom;
var tag;
var attributes = arguments[1];
if (attributes && attributes.constructor == Object && typeof attributes.render !== 'function') {
childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 2));
prepareAttributes(selector, attributes, childElements);
tag = parseTag(selector, attributes);
vdom = h(tag, attributes, childElements);
} else {
attributes = {};
childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 1));
tag = parseTag(selector, attributes);
vdom = h(tag, attributes, childElements);
}
if (hasHierarchy) {
for(var n = selectorElements.length - 2; n >= 0; n--) {
vdom = h(selectorElements[n], {}, [vdom]);
}
}
return vdom;
};
exports.jsx = function (tag, attributes) {
var childElements = toVdom.recursive(Array.prototype.slice.call(arguments, 2));
if (attributes) {
prepareAttributes(tag, attributes, childElements);
}
return h(tag, attributes || {}, childElements);
};
Object.defineProperty(exports.html, 'currentRender', {get: function () {
deprecations.currentRender('hyperdom.html.currentRender is deprecated, please use hyperdom.currentRender() instead');
return exports.html._currentRender;
}});
Object.defineProperty(exports.html, 'refresh', {get: function () {
deprecations.refresh('hyperdom.html.refresh is deprecated, please use viewModel.rerender() instead');
return exports.html._refresh;
}});
function refreshAfter(promise) {
deprecations.refreshAfter('hyperdom.html.refreshAfter is deprecated');
var refresh = exports.html.refresh;
promise.then(refresh);
}
exports.html.refreshify = refreshify;
exports.html.refreshAfter = refreshAfter;
exports.html.norefresh = norefresh;
function makeBinding(b, options) {
var binding = b instanceof Array
? bindingObject.apply(undefined, b)
: b;
binding.set = refreshify(binding.set, options);
return binding;
}
function makeConverter(converter) {
if (typeof converter == 'function') {
return {
view: function (model) {
return model;
},
model: function (view) {
return converter(view);
}
};
} else {
return converter;
}
}
function chainConverters(startIndex, converters) {
function makeConverters() {
if (!_converters) {
_converters = new Array(converters.length - startIndex);
for(var n = startIndex; n < converters.length; n++) {
_converters[n - startIndex] = makeConverter(converters[n]);
}
}
}
if ((converters.length - startIndex) == 1) {
return makeConverter(converters[startIndex]);
} else {
var _converters;
return {
view: function (model) {
makeConverters();
var intermediateValue = model;
for(var n = 0; n < _converters.length; n++) {
intermediateValue = _converters[n].view(intermediateValue);
}
return intermediateValue;
},
model: function (view) {
makeConverters();
var intermediateValue = view;
for(var n = _converters.length - 1; n >= 0; n--) {
intermediateValue = _converters[n].model(intermediateValue);
}
return intermediateValue;
}
};
}
}
function bindingObject(model, property) {
var _meta;
function hyperdomMeta() {
return _meta || (_meta = bindingMeta(model, property));
}
if (arguments.length > 2) {
var converter = chainConverters(2, arguments);
return {
get: function() {
var meta = hyperdomMeta();
var modelValue = model[property];
var modelText;
if (meta.error) {
return meta.view;
} else if (meta.view === undefined) {
modelText = converter.view(modelValue);
meta.view = modelText;
return modelText;
} else {
var previousValue = converter.model(meta.view);
modelText = converter.view(modelValue);
var normalisedPreviousText = converter.view(previousValue);
if (modelText === normalisedPreviousText) {
return meta.view;
} else {
meta.view = modelText;
return modelText;
}
}
},
set: function(view) {
var meta = hyperdomMeta();
meta.view = view;
try {
model[property] = converter.model(view, model[property]);
delete meta.error;
} catch (e) {
meta.error = e;
}
},
meta: function() {
return hyperdomMeta();
}
};
} else {
return {
get: function () {
return model[property];
},
set: function (value) {
model[property] = value;
},
meta: function() {
return hyperdomMeta();
}
};
}
}
exports.binding = makeBinding;
exports.html.binding = makeBinding;
exports.html.meta = bindingMeta;
function rawHtml() {
var selector;
var html;
var options;
if (arguments.length == 2) {
selector = arguments[0];
html = arguments[1];
options = {innerHTML: html};
return exports.html(selector, options);
} else {
selector = arguments[0];
options = arguments[1];
html = arguments[2];
options.innerHTML = html;
return exports.html(selector, options);
}
}
exports.html.rawHtml = rawHtml;
function generateConditionalClassNames(obj) {
return Object.keys(obj).filter(function (key) {
return obj[key];
}).join(' ') || undefined;
}
function generateClassName(obj) {
if (typeof(obj) == 'object') {
if (obj instanceof Array) {
var names = obj.map(function(item) {
return generateClassName(item);
});
return names.join(' ') || undefined;
} else {
return generateConditionalClassNames(obj);
}
} else {
return obj;
}
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{".":"hyperdom","./deprecations":3,"./domComponent":4,"./meta":6,"./mount":7,"./runRender":37,"./toVdom":40,"./vhtml":41,"./viewModel":42,"virtual-dom/virtual-hyperscript/parse-tag":22}],37:[function(require,module,exports){
var hyperdom = require('.');
var Render = require('./render');
var rendering = require('./rendering');
function refreshOutOfRender() {
throw new Error('Please assign hyperdom.html.refresh during a render cycle if you want to use it in event handlers. See https://github.com/featurist/hyperdom#refresh-outside-render-cycle');
}
module.exports = function(mount, fn) {
var render = new Render(mount);
try {
hyperdom._currentRender = render;
rendering.html._currentRender = render;
rendering.html._refresh = rendering.createEventResultHandler(mount);
fn();
} finally {
render.finished.fulfill();
hyperdom._currentRender = undefined;
rendering.html._refresh = refreshOutOfRender;
rendering.html._currentRender = undefined;
}
};
},{".":"hyperdom","./render":35,"./rendering":36}],38:[function(require,module,exports){
if (typeof Set === 'function') {
module.exports = Set;
} else {
module.exports = function() {
this.items = [];
};
module.exports.prototype.add = function(widget) {
if (this.items.indexOf(widget) == -1) {
this.items.push(widget);
}
};
module.exports.prototype.delete = function(widget) {
var i = this.items.indexOf(widget);
if (i !== -1) {
this.items.splice(i, 1);
}
};
module.exports.prototype.forEach = function(fn) {
for(var n = 0; n < this.items.length; n++) {
fn(this.items[n]);
}
};
}
},{}],39:[function(require,module,exports){
function SimplePromise () {
this.listeners = [];
}
SimplePromise.prototype.fulfill = function (value) {
if (!this.isFulfilled) {
this.isFulfilled = true;
this.value = value;
this.listeners.forEach(function (listener) {
listener();
});
}
};
SimplePromise.prototype.then = function (success) {
if (this.isFulfilled) {
var self = this;
setTimeout(function () {
success(self.value);
});
} else {
this.listeners.push(success);
}
};
module.exports = function () {
return new SimplePromise();
};
},{}],40:[function(require,module,exports){
var vtext = require("virtual-dom/vnode/vtext.js")
var rendering = require('./rendering');
var isVdom = require('./isVdom');
function toVdom(object) {
if (object === undefined || object === null) {
return new vtext('');
} else if (typeof(object) != 'object') {
return new vtext(String(object));
} else if (object instanceof Date) {
return new vtext(String(object));
} else if (object instanceof Error) {
return new vtext(object.toString());
} else if (isVdom(object)) {
return object;
} else if (typeof object.render === 'function') {
return new rendering.ViewModel(object);
} else {
return new vtext(JSON.stringify(object));
}
}
module.exports = toVdom;
function addChild(children, child) {
if (child instanceof Array) {
for (var n = 0; n < child.length; n++) {
addChild(children, child[n]);
}
} else {
children.push(toVdom(child));
}
}
module.exports.recursive = function (child) {
var children = [];
addChild(children, child);
return children;
};
},{"./isVdom":5,"./rendering":36,"virtual-dom/vnode/vtext.js":32}],41:[function(require,module,exports){
'use strict';
var VNode = require('virtual-dom/vnode/vnode.js');
var isHook = require('virtual-dom/vnode/is-vhook');
var softSetHook = require('virtual-dom/virtual-hyperscript/hooks/soft-set-hook.js');
module.exports = h;
function h(tagName, props, children) {
var tag = tagName;
// support keys
if (props.hasOwnProperty('key')) {
var key = props.key;
props.key = undefined;
}
// support namespace
if (props.hasOwnProperty('namespace')) {
var namespace = props.namespace;
props.namespace = undefined;
}
// fix cursor bug
if (tag.toLowerCase() === 'input' &&
!namespace &&
props.hasOwnProperty('value') &&
props.value !== undefined &&
!isHook(props.value)
) {
props.value = softSetHook(props.value);
}
return new VNode(tag, props, children, key, namespace);
}
},{"virtual-dom/virtual-hyperscript/hooks/soft-set-hook.js":21,"virtual-dom/vnode/is-vhook":25,"virtual-dom/vnode/vnode.js":30}],42:[function(require,module,exports){
var domComponent = require('./domComponent');
var hyperdomMeta = require('./meta');
var hyperdom = require('.');
function ViewModel(model) {
var currentRender = hyperdom.currentRender();
this.currentRender = currentRender;
this.model = model;
this.key = model.renderKey;
this.component = undefined;
this.mount = currentRender.mount;
}
ViewModel.prototype.type = 'Widget';
ViewModel.prototype.init = function () {
var self = this;
var vdom = this.render();
var meta = hyperdomMeta(this.model);
meta.widgets.add(this);
this.component = domComponent();
var element = this.component.create(vdom);
if (self.model.onadd) {
this.currentRender.finished.then(function () {
self.model.onadd(element);
});
}
if (self.model.detached) {
return document.createTextNode('');
} else {
return element;
}
};
ViewModel.prototype.update = function (previous) {
var self = this;
if (self.model.onupdate) {
this.currentRender.finished.then(function () {
self.model.onupdate(self.component.element);
});
}
this.component = previous.component;
var element = this.component.update(this.render());
if (self.model.detached) {
return document.createTextNode('');
} else {
return element;
}
};
ViewModel.prototype.render = function () {
return this.mount.renderViewModel(this.model);
};
ViewModel.prototype.rerender = function () {
this.component.update(this.render());
if (this.model.onupdate) {
this.model.onupdate(this.component.element);
}
};
ViewModel.prototype.destroy = function (element) {
var self = this;
var meta = hyperdomMeta(this.model);
meta.widgets.delete(this);
if (self.model.onremove) {
this.currentRender.finished.then(function () {
self.model.onremove(element);
});
}
this.component.destroy();
};
module.exports = ViewModel;
},{".":"hyperdom","./domComponent":4,"./meta":6}],43:[function(require,module,exports){
var domComponent = require('./domComponent');
var rendering = require('./rendering');
var VText = require("virtual-dom/vnode/vtext.js")
function WindowWidget(attributes) {
this.attributes = attributes;
this.vdom = new VText('');
this.component = domComponent();
var self = this;
this.cache = {};
Object.keys(this.attributes).forEach(function (key) {
self.cache[key] = rendering.html.refreshify(self.attributes[key]);
});
}
WindowWidget.prototype.type = 'Widget';
WindowWidget.prototype.init = function () {
applyPropertyDiffs(window, {}, this.attributes, {}, this.cache);
return this.element = document.createTextNode('');
};
function uniq(array) {
var sortedArray = array.slice();
sortedArray.sort();
var last;
for(var n = 0; n < sortedArray.length;) {
var current = sortedArray[n];
if (last === current) {
sortedArray.splice(n, 1);
} else {
n++;
}
last = current;
}
return sortedArray;
}
function applyPropertyDiffs(element, previous, current, previousCache, currentCache) {
uniq(Object.keys(previous).concat(Object.keys(current))).forEach(function (key) {
if (/^on/.test(key)) {
var event = key.slice(2);
var prev = previous[key];
var curr = current[key];
var refreshPrev = previousCache[key];
var refreshCurr = currentCache[key];
if (prev !== undefined && curr === undefined) {
element.removeEventListener(event, refreshPrev);
} else if (prev !== undefined && curr !== undefined && prev !== curr) {
element.removeEventListener(event, refreshPrev);
element.addEventListener(event, refreshCurr);
} else if (prev === undefined && curr !== undefined) {
element.addEventListener(event, refreshCurr);
}
}
});
}
WindowWidget.prototype.update = function (previous) {
applyPropertyDiffs(window, previous.attributes, this.attributes, previous.cache, this.cache);
this.component = previous.component;
return this.element;
};
WindowWidget.prototype.destroy = function () {
applyPropertyDiffs(window, this.attributes, {}, this.cache, {});
};
module.exports = function (attributes) {
return new WindowWidget(attributes);
};
},{"./domComponent":4,"./rendering":36,"virtual-dom/vnode/vtext.js":32}],"hyperdom":[function(require,module,exports){
if (typeof window === 'object') {
console.log('\n\ncreated with \uD83D\uDE80 using https://github.com/featurist/hyperdom\n\n\n');
}
var rendering = require('./rendering');
var deprecations = require('./deprecations');
exports.html = rendering.html;
exports.jsx = rendering.jsx;
exports.attach = rendering.attach;
exports.replace = rendering.replace;
exports.append = rendering.append;
exports.appendVDom = rendering.appendVDom;
exports.merge = rendering.merge;
exports.binding = rendering.binding;
exports.meta = rendering.html.meta;
exports.refreshify = rendering.html.refreshify;
exports.norefresh = rendering.html.norefresh;
var windowEvents = require('./windowEvents');
exports.html.window = function (attributes) {
deprecations.window('hyperdom.window is deprecated');
return windowEvents(attributes);
};
exports.html.component = require('./component');
exports.currentRender = function () {
return exports._currentRender;
};
},{"./component":2,"./deprecations":3,"./rendering":36,"./windowEvents":43}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcmVzb2x2ZS9lbXB0eS5qcyIsImNvbXBvbmVudC5qcyIsImRlcHJlY2F0aW9ucy5qcyIsImRvbUNvbXBvbmVudC5qcyIsImlzVmRvbS5qcyIsIm1ldGEuanMiLCJtb3VudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9jcmVhdGUtZWxlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9kaWZmLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL25vZGVfbW9kdWxlcy9icm93c2VyLXNwbGl0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL25vZGVfbW9kdWxlcy9nbG9iYWwvZG9jdW1lbnQuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vbm9kZV9tb2R1bGVzL2lzLW9iamVjdC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9ub2RlX21vZHVsZXMveC1pcy1hcnJheS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS9wYXRjaC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL2FwcGx5LXByb3BlcnRpZXMuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdmRvbS9jcmVhdGUtZWxlbWVudC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL2RvbS1pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92ZG9tL3BhdGNoLW9wLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zkb20vcGF0Y2guanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdmRvbS91cGRhdGUtd2lkZ2V0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaG9va3Mvc29mdC1zZXQtaG9vay5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L3BhcnNlLXRhZy5qcyIsIm5vZGVfbW9kdWxlcy92aXJ0dWFsLWRvbS92bm9kZS9oYW5kbGUtdGh1bmsuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdGh1bmsuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdmhvb2suanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdm5vZGUuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtdnRleHQuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvaXMtd2lkZ2V0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zub2RlL3ZlcnNpb24uanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvdm5vZGUuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdm5vZGUvdnBhdGNoLmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Zub2RlL3Z0ZXh0LmpzIiwibm9kZV9tb2R1bGVzL3ZpcnR1YWwtZG9tL3Z0cmVlL2RpZmYtcHJvcHMuanMiLCJub2RlX21vZHVsZXMvdmlydHVhbC1kb20vdnRyZWUvZGlmZi5qcyIsInJlbmRlci5qcyIsInJlbmRlcmluZy5qcyIsInJ1blJlbmRlci5qcyIsInNldC5qcyIsInNpbXBsZVByb21pc2UuanMiLCJ0b1Zkb20uanMiLCJ2aHRtbC5qcyIsInZpZXdNb2RlbC5qcyIsIndpbmRvd0V2ZW50cy5qcyIsImh5cGVyZG9tIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdElBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcm9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiIiwidmFyIFZUZXh0ID0gcmVxdWlyZShcInZpcnR1YWwtZG9tL3Zub2RlL3Z0ZXh0LmpzXCIpXG52YXIgZG9tQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9kb21Db21wb25lbnQnKTtcbnZhciBoeXBlcmRvbSA9IHJlcXVpcmUoJy4nKTtcbnZhciBkZXByZWNhdGlvbnMgPSByZXF1aXJlKCcuL2RlcHJlY2F0aW9ucycpO1xuXG5mdW5jdGlvbiBDb21wb25lbnRXaWRnZXQoc3RhdGUsIHZkb20pIHtcbiAgaWYgKCF2ZG9tKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdoeXBlcmRvbS5odG1sLmNvbXBvbmVudChbb3B0aW9uc10sIHZkb20pIGV4cGVjdHMgYSB2ZG9tIGFyZ3VtZW50Jyk7XG4gIH1cblxuICB0aGlzLnN0YXRlID0gc3RhdGU7XG4gIHRoaXMua2V5ID0gc3RhdGUua2V5O1xuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICBpZiAodHlwZW9mIHZkb20gPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aGlzLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChjdXJyZW50UmVuZGVyKSB7XG4gICAgICAgIGN1cnJlbnRSZW5kZXIuZXZlbnRIYW5kbGVyV3JhcHBlciA9IHN0YXRlLm9uO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZkb20uYXBwbHkodGhpcy5zdGF0ZSwgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHRoaXMuY2FuUmVmcmVzaCA9IHRydWU7XG4gIH0gZWxzZSB7XG4gICAgdmRvbSA9IHZkb20gfHwgbmV3IFZUZXh0KCcnKTtcbiAgICB0aGlzLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB2ZG9tO1xuICAgIH1cbiAgfVxuICB0aGlzLmNhY2hlS2V5ID0gc3RhdGUuY2FjaGVLZXk7XG4gIHRoaXMuY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KCk7XG5cbiAgdmFyIHJlbmRlckZpbmlzaGVkID0gY3VycmVudFJlbmRlciAmJiBjdXJyZW50UmVuZGVyLmZpbmlzaGVkO1xuICBpZiAocmVuZGVyRmluaXNoZWQpIHtcbiAgICB0aGlzLmFmdGVyUmVuZGVyID0gZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZW5kZXJGaW5pc2hlZC50aGVuKGZuKTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHRoaXMuYWZ0ZXJSZW5kZXIgPSBmdW5jdGlvbiAoKSB7fTtcbiAgfVxufVxuXG5Db21wb25lbnRXaWRnZXQucHJvdG90eXBlLnR5cGUgPSAnV2lkZ2V0JztcblxuQ29tcG9uZW50V2lkZ2V0LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKHNlbGYuc3RhdGUub25iZWZvcmVhZGQpIHtcbiAgICBzZWxmLnN0YXRlLm9uYmVmb3JlYWRkKCk7XG4gIH1cblxuICB2YXIgdmRvbSA9IHRoaXMucmVuZGVyKHRoaXMpO1xuICBpZiAodmRvbSBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd2ZG9tIHJldHVybmVkIGZyb20gY29tcG9uZW50IGNhbm5vdCBiZSBhbiBhcnJheScpO1xuICB9XG5cbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC5jcmVhdGUodmRvbSk7XG5cbiAgaWYgKHNlbGYuc3RhdGUub25hZGQpIHtcbiAgICB0aGlzLmFmdGVyUmVuZGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuc3RhdGUub25hZGQoZWxlbWVudCk7XG4gICAgfSk7XG4gIH1cblxuICBpZiAoc2VsZi5zdGF0ZS5kZXRhY2hlZCkge1xuICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGVsZW1lbnQ7XG4gIH1cbn07XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKHByZXZpb3VzKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgcmVmcmVzaCA9ICF0aGlzLmNhY2hlS2V5IHx8IHRoaXMuY2FjaGVLZXkgIT09IHByZXZpb3VzLmNhY2hlS2V5O1xuXG4gIGlmIChyZWZyZXNoKSB7XG4gICAgaWYgKHNlbGYuc3RhdGUub251cGRhdGUpIHtcbiAgICAgIHRoaXMuYWZ0ZXJSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICBzZWxmLnN0YXRlLm9udXBkYXRlKHNlbGYuY29tcG9uZW50LmVsZW1lbnQpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5jb21wb25lbnQgPSBwcmV2aW91cy5jb21wb25lbnQ7XG5cbiAgaWYgKHByZXZpb3VzLnN0YXRlICYmIHRoaXMuc3RhdGUpIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuc3RhdGUpO1xuICAgIGZvcih2YXIgbiA9IDA7IG4gPCBrZXlzLmxlbmd0aDsgbisrKSB7XG4gICAgICB2YXIga2V5ID0ga2V5c1tuXTtcbiAgICAgIHByZXZpb3VzLnN0YXRlW2tleV0gPSBzZWxmLnN0YXRlW2tleV07XG4gICAgfVxuICAgIHRoaXMuc3RhdGUgPSBwcmV2aW91cy5zdGF0ZTtcbiAgfVxuXG4gIGlmIChyZWZyZXNoKSB7XG4gICAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIodGhpcykpO1xuXG4gICAgaWYgKHNlbGYuc3RhdGUuZGV0YWNoZWQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZSgnJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBlbGVtZW50O1xuICAgIH1cbiAgfVxufTtcblxuQ29tcG9uZW50V2lkZ2V0LnByb3RvdHlwZS5yZWZyZXNoID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIodGhpcykpO1xuICBpZiAodGhpcy5zdGF0ZS5vbnVwZGF0ZSkge1xuICAgIHRoaXMuc3RhdGUub251cGRhdGUodGhpcy5jb21wb25lbnQuZWxlbWVudCk7XG4gIH1cbn07XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUucmVyZW5kZXIgPSBDb21wb25lbnRXaWRnZXQucHJvdG90eXBlLnJlZnJlc2g7XG5cbkNvbXBvbmVudFdpZGdldC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBpZiAoc2VsZi5zdGF0ZS5vbnJlbW92ZSkge1xuICAgIHRoaXMuYWZ0ZXJSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi5zdGF0ZS5vbnJlbW92ZShlbGVtZW50KTtcbiAgICB9KTtcbiAgfVxuXG4gIHRoaXMuY29tcG9uZW50LmRlc3Ryb3koKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHN0YXRlLCB2ZG9tKSB7XG4gIGRlcHJlY2F0aW9ucy5jb21wb25lbnQoJ2h5cGVyZG9tLmh0bWwuY29tcG9uZW50IGlzIGRlcHJlY2F0ZWQsIHBsZWFzZSB1c2UgVmlld01vZGVscycpO1xuICBpZiAodHlwZW9mIHN0YXRlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRXaWRnZXQoe30sIHN0YXRlKTtcbiAgfSBlbHNlIGlmIChzdGF0ZS5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0KSB7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRXaWRnZXQoc3RhdGUsIHZkb20pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBuZXcgQ29tcG9uZW50V2lkZ2V0KHt9LCBzdGF0ZSk7XG4gIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzLkNvbXBvbmVudFdpZGdldCA9IENvbXBvbmVudFdpZGdldDtcbiIsImZ1bmN0aW9uIGRlcHJlY2F0aW9uV2FybmluZygpIHtcbiAgdmFyIHdhcm5pbmdJc3N1ZWQgPSBmYWxzZTtcblxuICByZXR1cm4gZnVuY3Rpb24gKGFyZykge1xuICAgIGlmICghd2FybmluZ0lzc3VlZCkge1xuICAgICAgY29uc29sZS53YXJuKGFyZyk7XG4gICAgICB3YXJuaW5nSXNzdWVkID0gdHJ1ZTtcbiAgICB9XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICByZWZyZXNoOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgY3VycmVudFJlbmRlcjogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIHdpbmRvdzogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIGNvbXBvbmVudDogZGVwcmVjYXRpb25XYXJuaW5nKCksXG4gIHJlbmRlckZ1bmN0aW9uOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgcmVmcmVzaEFmdGVyOiBkZXByZWNhdGlvbldhcm5pbmcoKSxcbiAgbm9yZWZyZXNoOiBkZXByZWNhdGlvbldhcm5pbmcoKVxufTtcbiIsInZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZSgndmlydHVhbC1kb20vY3JlYXRlLWVsZW1lbnQnKTtcbnZhciBkaWZmID0gcmVxdWlyZSgndmlydHVhbC1kb20vZGlmZicpO1xudmFyIHBhdGNoID0gcmVxdWlyZSgndmlydHVhbC1kb20vcGF0Y2gnKTtcbnZhciB0b1Zkb20gPSByZXF1aXJlKCcuL3RvVmRvbScpO1xudmFyIGlzVmRvbSA9IHJlcXVpcmUoJy4vaXNWZG9tJyk7XG5cbmZ1bmN0aW9uIERvbUNvbXBvbmVudChvcHRpb25zKSB7XG4gIHRoaXMuZG9jdW1lbnQgPSBvcHRpb25zICYmIG9wdGlvbnMuZG9jdW1lbnQ7XG59XG5cbmZ1bmN0aW9uIHByZXBhcmVWZG9tKG9iamVjdCkge1xuICB2YXIgdmRvbSA9IHRvVmRvbShvYmplY3QpO1xuICBpZiAoIWlzVmRvbSh2ZG9tKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0ZWQgcmVuZGVyIHRvIHJldHVybiB2ZG9tJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHZkb207XG4gIH1cbn1cblxuRG9tQ29tcG9uZW50LnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAodmRvbSkge1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGNyZWF0ZUVsZW1lbnQodGhpcy52ZG9tLCB7ZG9jdW1lbnQ6IHRoaXMuZG9jdW1lbnR9KTtcbn07XG5cbkRvbUNvbXBvbmVudC5wcm90b3R5cGUubWVyZ2UgPSBmdW5jdGlvbiAodmRvbSwgZWxlbWVudCkge1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG59O1xuXG5Eb21Db21wb25lbnQucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICh2ZG9tKSB7XG4gIHZhciBvbGRWZG9tID0gdGhpcy52ZG9tO1xuICB0aGlzLnZkb20gPSBwcmVwYXJlVmRvbSh2ZG9tKTtcbiAgdmFyIHBhdGNoZXMgPSBkaWZmKG9sZFZkb20sIHRoaXMudmRvbSk7XG4gIHJldHVybiB0aGlzLmVsZW1lbnQgPSBwYXRjaCh0aGlzLmVsZW1lbnQsIHBhdGNoZXMpO1xufTtcblxuRG9tQ29tcG9uZW50LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModmRvbSkge1xuICAgIGlmICh2ZG9tLnR5cGUgPT09ICdXaWRnZXQnKSB7XG4gICAgICB2ZG9tLmRlc3Ryb3koKTtcbiAgICB9IGVsc2UgaWYgKHZkb20uY2hpbGRyZW4pIHtcbiAgICAgIHZkb20uY2hpbGRyZW4uZm9yRWFjaChkZXN0cm95V2lkZ2V0cyk7XG4gICAgfVxuICB9XG5cbiAgZGVzdHJveVdpZGdldHModGhpcy52ZG9tKTtcblxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLnJlbW92ZUVsZW1lbnQgJiYgdGhpcy5lbGVtZW50LnBhcmVudE5vZGUpIHtcbiAgICB0aGlzLmVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmVsZW1lbnQpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBkb21Db21wb25lbnQob3B0aW9ucykge1xuICByZXR1cm4gbmV3IERvbUNvbXBvbmVudChvcHRpb25zKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkb21Db21wb25lbnQ7XG4iLCJ2YXIgdmlydHVhbERvbVZlcnNpb24gPSByZXF1aXJlKFwidmlydHVhbC1kb20vdm5vZGUvdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIHR5cGUgPSB4LnR5cGU7XG4gIGlmICh0eXBlID09ICdWaXJ0dWFsTm9kZScgfHwgdHlwZSA9PSAnVmlydHVhbFRleHQnKSB7XG4gICAgcmV0dXJuIHgudmVyc2lvbiA9PSB2aXJ0dWFsRG9tVmVyc2lvbjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdHlwZSA9PSAnV2lkZ2V0JyB8fCB0eXBlID09ICdUaHVuayc7XG4gIH1cbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChtb2RlbCwgcHJvcGVydHkpIHtcbiAgdmFyIGh5cGVyZG9tTWV0YSA9IG1vZGVsLl9oeXBlcmRvbU1ldGE7XG5cbiAgaWYgKCFoeXBlcmRvbU1ldGEpIHtcbiAgICBoeXBlcmRvbU1ldGEgPSB7fTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobW9kZWwsICdfaHlwZXJkb21NZXRhJywge3ZhbHVlOiBoeXBlcmRvbU1ldGF9KTtcbiAgfVxuXG4gIGlmIChwcm9wZXJ0eSkge1xuICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhW3Byb3BlcnR5XTtcblxuICAgIGlmICghbWV0YSkge1xuICAgICAgbWV0YSA9IGh5cGVyZG9tTWV0YVtwcm9wZXJ0eV0gPSB7fTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWV0YTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaHlwZXJkb21NZXRhO1xuICB9XG59O1xuIiwidmFyIGh5cGVyZG9tTWV0YSA9IHJlcXVpcmUoJy4vbWV0YScpO1xudmFyIHJ1blJlbmRlciA9IHJlcXVpcmUoJy4vcnVuUmVuZGVyJyk7XG52YXIgaHlwZXJkb20gPSByZXF1aXJlKCcuJyk7XG52YXIgU2V0ID0gcmVxdWlyZSgnLi9zZXQnKTtcblxudmFyIGxhc3RJZCA9IDA7XG5cbmZ1bmN0aW9uIE1vdW50KG1vZGVsLCBvcHRpb25zKSB7XG4gIHZhciB3aW4gPSAob3B0aW9ucyAmJiBvcHRpb25zLndpbmRvdykgfHwgd2luZG93O1xuICB0aGlzLnJlcXVlc3RSZW5kZXIgPSAob3B0aW9ucyAmJiBvcHRpb25zLnJlcXVlc3RSZW5kZXIpIHx8IHdpbi5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHwgd2luLnNldFRpbWVvdXQ7XG5cbiAgdGhpcy5tb2RlbCA9IG1vZGVsO1xuXG4gIHRoaXMucmVuZGVyUXVldWVkID0gZmFsc2U7XG4gIHRoaXMubW91bnRSZW5kZXJSZXF1ZXN0ZWQgPSBmYWxzZTtcbiAgdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkID0gdW5kZWZpbmVkO1xuICB0aGlzLmlkID0gKytsYXN0SWQ7XG4gIHRoaXMubW91bnRlZCA9IHRydWU7XG59XG5cbk1vdW50LnByb3RvdHlwZS5xdWV1ZVJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKCF0aGlzLnJlbmRlclF1ZXVlZCkge1xuICAgIHZhciByZXF1ZXN0UmVuZGVyID0gdGhpcy5yZXF1ZXN0UmVuZGVyO1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHJlcXVlc3RSZW5kZXIoZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi5yZW5kZXJRdWV1ZWQgPSBmYWxzZTtcblxuICAgICAgaWYgKHNlbGYubW91bnRlZCkge1xuICAgICAgICBydW5SZW5kZXIoc2VsZiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGlmIChzZWxmLm1vdW50UmVuZGVyUmVxdWVzdGVkKSB7XG4gICAgICAgICAgICB2YXIgdmRvbSA9IHNlbGYucmVuZGVyKCk7XG4gICAgICAgICAgICBzZWxmLmNvbXBvbmVudC51cGRhdGUodmRvbSk7XG4gICAgICAgICAgICBzZWxmLm1vdW50UmVuZGVyUmVxdWVzdGVkID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIGlmIChzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQgJiYgc2VsZi53aWRnZXRSZW5kZXJzUmVxdWVzdGVkLmxlbmd0aCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgIHZhciB3ID0gc2VsZi53aWRnZXRSZW5kZXJzUmVxdWVzdGVkW2ldO1xuICAgICAgICAgICAgICB3LnJlcmVuZGVyKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzZWxmLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRoaXMucmVuZGVyUXVldWVkID0gdHJ1ZTtcbiAgfVxufTtcblxuTW91bnQucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5yZW5kZXJWaWV3TW9kZWwodGhpcy5tb2RlbCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVyZW5kZXIgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMubW91bnRSZW5kZXJSZXF1ZXN0ZWQgPSB0cnVlO1xuICB0aGlzLnF1ZXVlUmVuZGVyKCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVyZW5kZXJXaWRnZXQgPSBmdW5jdGlvbiAod2lkZ2V0KSB7XG4gIGlmICghdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkKSB7XG4gICAgdGhpcy53aWRnZXRSZW5kZXJzUmVxdWVzdGVkID0gW107XG4gIH1cblxuICB0aGlzLndpZGdldFJlbmRlcnNSZXF1ZXN0ZWQucHVzaCh3aWRnZXQpO1xuICB0aGlzLnF1ZXVlUmVuZGVyKCk7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUuX3JlbmRlclZpZXdNb2RlbCA9IGZ1bmN0aW9uKG1vZGVsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICBtb2RlbC5yZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBzZWxmLnJlcmVuZGVyKCk7XG4gIH07XG4gIG1vZGVsLnJlcmVuZGVyVmlld01vZGVsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEodGhpcyk7XG4gICAgbWV0YS53aWRnZXRzLmZvckVhY2goZnVuY3Rpb24gKHcpIHtcbiAgICAgIHNlbGYucmVyZW5kZXJXaWRnZXQodyk7XG4gICAgfSk7XG4gIH07XG5cbiAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEobW9kZWwpO1xuICBpZiAoIW1ldGEubW91bnQpIHtcbiAgICBtZXRhLm1vdW50ID0gdGhpcztcbiAgfVxuXG4gIGlmICghbWV0YS53aWRnZXRzKSB7XG4gICAgbWV0YS53aWRnZXRzID0gbmV3IFNldCgpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBtb2RlbC5vbmxvYWQgPT0gJ2Z1bmN0aW9uJykge1xuICAgIGlmICghbWV0YS5sb2FkZWQpIHtcbiAgICAgIG1ldGEubG9hZGVkID0gdHJ1ZTtcbiAgICAgIGh5cGVyZG9tLnJlZnJlc2hpZnkoZnVuY3Rpb24gKCkgeyByZXR1cm4gbW9kZWwub25sb2FkKCk7IH0sIHtyZWZyZXNoOiAncHJvbWlzZSd9KSgpO1xuICAgIH1cbiAgfVxuXG4gIHZhciB2ZG9tID0gbW9kZWwucmVuZGVyKCk7XG5cbiAgaWYgKHZkb20gaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIHRocm93IG5ldyBFcnJvcigndmRvbSByZXR1cm5lZCBmcm9tIGNvbXBvbmVudCBjYW5ub3QgYmUgYW4gYXJyYXknKTtcbiAgfVxuXG4gIGlmICh2ZG9tICYmIHZkb20ucHJvcGVydGllcykge1xuICAgIHZkb20ucHJvcGVydGllcy5faHlwZXJkb21WaWV3TW9kZWwgPSBtb2RlbDtcbiAgfVxuXG4gIHJldHVybiB2ZG9tO1xufVxuXG5Nb3VudC5wcm90b3R5cGUucmVuZGVyVmlld01vZGVsID0gZnVuY3Rpb24obW9kZWwpIHtcbiAgaWYgKHR5cGVvZiBtb2RlbC5yZW5kZXJDYWNoZUtleSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhKG1vZGVsKTtcbiAgICB2YXIga2V5ID0gbW9kZWwucmVuZGVyQ2FjaGVLZXkoKTtcbiAgICBpZiAoa2V5ICE9PSB1bmRlZmluZWQgJiYgbWV0YS5jYWNoZUtleSA9PT0ga2V5ICYmIG1ldGEuY2FjaGVkVmRvbSkge1xuICAgICAgcmV0dXJuIG1ldGEuY2FjaGVkVmRvbTtcbiAgICB9IGVsc2Uge1xuICAgICAgbWV0YS5jYWNoZUtleSA9IGtleTtcbiAgICAgIHJldHVybiBtZXRhLmNhY2hlZFZkb20gPSB0aGlzLl9yZW5kZXJWaWV3TW9kZWwobW9kZWwpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdGhpcy5fcmVuZGVyVmlld01vZGVsKG1vZGVsKTtcbiAgfVxufTtcblxuTW91bnQucHJvdG90eXBlLmRldGFjaCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5tb3VudGVkID0gZmFsc2U7XG59O1xuXG5Nb3VudC5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmNvbXBvbmVudC5kZXN0cm95KHtyZW1vdmVFbGVtZW50OiB0cnVlfSk7XG4gIHRoaXMubW91bnRlZCA9IGZhbHNlO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNb3VudDtcbiIsInZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnRcbiIsInZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRpZmZcbiIsIi8qIVxuICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gKi9cblxuLyoqXG4gKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICogY3Jvc3MtYnJvd3Nlci5cbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICogQGV4YW1wbGVcbiAqXG4gKiAvLyBCYXNpYyB1c2VcbiAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gKlxuICogLy8gV2l0aCBsaW1pdFxuICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICogLy8gLT4gWydhJywgJ2InXVxuICpcbiAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgc2VsZjtcblxuICBzZWxmID0gZnVuY3Rpb24oc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgIH1cbiAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcbiAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICBzZXBhcmF0b3IyLCBtYXRjaCwgbGFzdEluZGV4LCBsYXN0TGVuZ3RoO1xuICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgfVxuICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgKi9cbiAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICB9O1xuXG4gIHJldHVybiBzZWxmO1xufSkoKTtcbiIsInZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDpcbiAgICB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHt9XG52YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbn0gZWxzZSB7XG4gICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbJ19fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDQnXTtcblxuICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgIH1cblxuICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG59XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG5cdHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xufTtcbiIsInZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheVxudmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheVxuXG5mdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIlxufVxuIiwidmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhdGNoXG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpXG52YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzXG5cbmZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdXG5cbiAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKVxuICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSxcbiAgICAgICAgICAgICAgICAgICAgcHJvcE5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXVxuXG4gICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKVxuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkXG5cbiAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXVxuXG4gICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiZcbiAgICAgICAgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZVxuICAgICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9XG4gICAgfVxuXG4gICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWRcblxuICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXVxuICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9ICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSA/IHJlcGxhY2VyIDogdmFsdWVcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSlcbiAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fXG4gICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlXG4gICAgfVxufVxuIiwidmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKVxuXG52YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKVxuXG52YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKVxudmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIilcbnZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIilcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50XG5cbmZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudFxuICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGxcblxuICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmFcblxuICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKVxuICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KVxuICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgdmFyIG5vZGUgPSAodm5vZGUubmFtZXNwYWNlID09PSBudWxsKSA/XG4gICAgICAgIGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDpcbiAgICAgICAgZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpXG5cbiAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzXG4gICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKVxuXG4gICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW5cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpXG4gICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGVcbn1cbiIsIi8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4vLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4vLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbi8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2Zcbi8vIGludGVyZXN0LlxuXG52YXIgbm9DaGlsZCA9IHt9XG5cbm1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXhcblxuZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpXG4gICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICBub2RlcyA9IG5vZGVzIHx8IHt9XG5cblxuICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlXG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlblxuXG4gICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzXG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxXG5cbiAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGRcbiAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKVxuXG4gICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZXNcbn1cblxuLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbmZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICB2YXIgbWluSW5kZXggPSAwXG4gICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxXG4gICAgdmFyIGN1cnJlbnRJbmRleFxuICAgIHZhciBjdXJyZW50SXRlbVxuXG4gICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgIGN1cnJlbnRJbmRleCA9ICgobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyKSA+PiAwXG4gICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdXG5cbiAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHRcbiAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMVxuICAgICAgICB9IGVsc2UgIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDFcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xXG59XG4iLCJ2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKVxuXG52YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpXG52YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKVxuXG52YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2hcblxuZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlXG4gICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlXG4gICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoXG5cbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpXG4gICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKVxuICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpXG4gICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpXG4gICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKVxuICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaClcbiAgICAgICAgICAgIHJldHVybiBkb21Ob2RlXG4gICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKVxuICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGVcbiAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSxcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSlcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBkb21Ob2RlXG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGVcblxuICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSlcbiAgICB9XG5cbiAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgIHJldHVybiBudWxsXG59XG5cbmZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKVxuICAgIH1cblxuICAgIHJldHVybiBwYXJlbnROb2RlXG59XG5cbmZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICB2YXIgbmV3Tm9kZVxuXG4gICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dClcbiAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGVcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZVxuICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpXG5cbiAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXdOb2RlXG59XG5cbmZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KVxuICAgIHZhciBuZXdOb2RlXG5cbiAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlXG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucylcbiAgICB9XG5cbiAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZVxuXG4gICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKVxuICAgIH1cblxuICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpXG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld05vZGVcbn1cblxuZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGVcbiAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKVxuICAgIH1cblxuICAgIHJldHVybiBuZXdOb2RlXG59XG5cbmZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpXG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2Rlc1xuICAgIHZhciBrZXlNYXAgPSB7fVxuICAgIHZhciBub2RlXG4gICAgdmFyIHJlbW92ZVxuICAgIHZhciBpbnNlcnRcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldXG4gICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXVxuICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZVxuICAgICAgICB9XG4gICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSlcbiAgICB9XG5cbiAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGhcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXVxuICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldXG4gICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSlcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdClcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3Um9vdDtcbn1cbiIsInZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIilcbnZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIilcblxudmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpXG52YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIilcbnZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIilcbm1vZHVsZS5leHBvcnRzID0gcGF0Y2hcblxuZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fVxuICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoXG4gICAgICAgID8gcmVuZGVyT3B0aW9ucy5wYXRjaFxuICAgICAgICA6IHBhdGNoUmVjdXJzaXZlXG4gICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXJcblxuICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKVxufVxuXG5mdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpXG5cbiAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJvb3ROb2RlXG4gICAgfVxuXG4gICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcylcbiAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnRcblxuICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudFxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXVxuICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsXG4gICAgICAgICAgICBpbmRleFtub2RlSW5kZXhdLFxuICAgICAgICAgICAgcGF0Y2hlc1tub2RlSW5kZXhdLFxuICAgICAgICAgICAgcmVuZGVyT3B0aW9ucylcbiAgICB9XG5cbiAgICByZXR1cm4gcm9vdE5vZGVcbn1cblxuZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgIHJldHVybiByb290Tm9kZVxuICAgIH1cblxuICAgIHZhciBuZXdOb2RlXG5cbiAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpXG5cbiAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKVxuXG4gICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcm9vdE5vZGVcbn1cblxuZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICB2YXIgaW5kaWNlcyA9IFtdXG5cbiAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGluZGljZXNcbn1cbiIsInZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIilcblxubW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXRcblxuZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG4iLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbmZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG59XG5cblNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICB9XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3BsaXQgPSByZXF1aXJlKCdicm93c2VyLXNwbGl0Jyk7XG5cbnZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbnZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbm1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbmZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICBpZiAoIXRhZykge1xuICAgICAgICByZXR1cm4gJ0RJVic7XG4gICAgfVxuXG4gICAgdmFyIG5vSWQgPSAhKHByb3BzLmhhc093blByb3BlcnR5KCdpZCcpKTtcblxuICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICB0YWdOYW1lID0gJ0RJVic7XG4gICAgfVxuXG4gICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnLicpIHtcbiAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJyMnICYmIG5vSWQpIHtcbiAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgIH1cblxuICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oJyAnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbn1cbiIsInZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIilcbnZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rXG5cbmZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICB2YXIgcmVuZGVyZWRBID0gYVxuICAgIHZhciByZW5kZXJlZEIgPSBiXG5cbiAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKVxuICAgIH1cblxuICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICBiOiByZW5kZXJlZEJcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGVcblxuICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpXG4gICAgfVxuXG4gICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fFxuICAgICAgICAgICAgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fFxuICAgICAgICAgICAgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVuZGVyZWRUaHVua1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rXHJcblxyXG5mdW5jdGlvbiBpc1RodW5rKHQpIHtcclxuICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiXHJcbn1cclxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc0hvb2tcblxuZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICByZXR1cm4gaG9vayAmJlxuICAgICAgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHxcbiAgICAgICB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSlcbn1cbiIsInZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGVcblxuZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uXG59XG4iLCJ2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIilcblxubW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0XG5cbmZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvblxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldFxuXG5mdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiXG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IFwiMlwiXG4iLCJ2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIilcbnZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIilcbnZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKVxudmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlXG5cbnZhciBub1Byb3BlcnRpZXMgPSB7fVxudmFyIG5vQ2hpbGRyZW4gPSBbXVxuXG5mdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lXG4gICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXNcbiAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlblxuICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZFxuICAgIHRoaXMubmFtZXNwYWNlID0gKHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIpID8gbmFtZXNwYWNlIDogbnVsbFxuXG4gICAgdmFyIGNvdW50ID0gKGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCkgfHwgMFxuICAgIHZhciBkZXNjZW5kYW50cyA9IDBcbiAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlXG4gICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlXG4gICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlXG4gICAgdmFyIGhvb2tzXG5cbiAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV1cbiAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge31cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldXG4gICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMFxuXG4gICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWVcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzXG4gICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0c1xuICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzXG4gICAgdGhpcy5ob29rcyA9IGhvb2tzXG4gICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3Ncbn1cblxuVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uXG5WaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIlxuIiwidmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpXG5cblZpcnR1YWxQYXRjaC5OT05FID0gMFxuVmlydHVhbFBhdGNoLlZURVhUID0gMVxuVmlydHVhbFBhdGNoLlZOT0RFID0gMlxuVmlydHVhbFBhdGNoLldJREdFVCA9IDNcblZpcnR1YWxQYXRjaC5QUk9QUyA9IDRcblZpcnR1YWxQYXRjaC5PUkRFUiA9IDVcblZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2XG5WaXJ0dWFsUGF0Y2guUkVNT1ZFID0gN1xuVmlydHVhbFBhdGNoLlRIVU5LID0gOFxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaFxuXG5mdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpXG4gICAgdGhpcy52Tm9kZSA9IHZOb2RlXG4gICAgdGhpcy5wYXRjaCA9IHBhdGNoXG59XG5cblZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb25cblZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCJcbiIsInZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0XG5cbmZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dClcbn1cblxuVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uXG5WaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIlxuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKVxudmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wc1xuXG5mdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgIHZhciBkaWZmXG5cbiAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge31cbiAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWRcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldXG4gICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldXG5cbiAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9XG4gICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZVxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fVxuICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKVxuICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9XG4gICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge31cbiAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWVcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fVxuICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBkaWZmXG59XG5cbmZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSlcbiAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICByZXR1cm4gdmFsdWUuX19wcm90b19fXG4gIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlXG4gIH1cbn1cbiIsInZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIilcblxudmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIilcbnZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpXG52YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKVxudmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKVxudmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIilcbnZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIilcblxudmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIilcblxubW9kdWxlLmV4cG9ydHMgPSBkaWZmXG5cbmZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgIHZhciBwYXRjaCA9IHsgYTogYSB9XG4gICAgd2FsayhhLCBiLCBwYXRjaCwgMClcbiAgICByZXR1cm4gcGF0Y2hcbn1cblxuZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICByZXR1cm5cbiAgICB9XG5cbiAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF1cbiAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlXG5cbiAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpXG4gICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KVxuICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF1cbiAgICAgICAgfVxuXG4gICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpXG4gICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiZcbiAgICAgICAgICAgICAgICBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiZcbiAgICAgICAgICAgICAgICBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LFxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpXG4gICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSlcbiAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpXG4gICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZVxuICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlXG4gICAgICAgIH1cblxuICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKVxuICAgIH1cblxuICAgIGlmIChhcHBseSkge1xuICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseVxuICAgIH1cblxuICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlblxuICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pXG4gICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW5cblxuICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aFxuICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aFxuICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuXG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXVxuICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldXG4gICAgICAgIGluZGV4ICs9IDFcblxuICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksXG4gICAgICAgICAgICAgICAgICAgIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goXG4gICAgICAgICAgICBWUGF0Y2guT1JERVIsXG4gICAgICAgICAgICBhLFxuICAgICAgICAgICAgb3JkZXJlZFNldC5tb3Zlc1xuICAgICAgICApKVxuICAgIH1cblxuICAgIHJldHVybiBhcHBseVxufVxuXG5mdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KVxuICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpXG59XG5cbi8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG5mdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2goXG4gICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdLFxuICAgICAgICAgICAgICAgIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpXG4gICAgICAgICAgICApXG4gICAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW5cbiAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aFxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXVxuICAgICAgICAgICAgaW5kZXggKz0gMVxuXG4gICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KVxuXG4gICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleClcbiAgICB9XG59XG5cbi8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG5mdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYilcbiAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYilcbiAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG59XG5cbi8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChcbiAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0sXG4gICAgICAgICAgICAgICAgbmV3IFZQYXRjaChcbiAgICAgICAgICAgICAgICAgICAgVlBhdGNoLlBST1BTLFxuICAgICAgICAgICAgICAgICAgICB2Tm9kZSxcbiAgICAgICAgICAgICAgICAgICAgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcylcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW5cbiAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGhcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXVxuICAgICAgICAgICAgICAgIGluZGV4ICs9IDFcblxuICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleClcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdFxufVxuXG4vLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pXG4gICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5c1xuICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWVcblxuICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbilcbiAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzXG4gICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZVxuXG4gICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgdmFyIG5ld0NoaWxkcmVuID0gW11cblxuICAgIHZhciBmcmVlSW5kZXggPSAwXG4gICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aFxuICAgIHZhciBkZWxldGVkSXRlbXMgPSAwXG5cbiAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAvLyBPKE4pIHRpbWUsXG4gICAgZm9yICh2YXIgaSA9IDAgOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXVxuICAgICAgICB2YXIgaXRlbUluZGV4XG5cbiAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSlcblxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdXG4gICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSlcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKytcbiAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggP1xuICAgICAgICBiQ2hpbGRyZW4ubGVuZ3RoIDpcbiAgICAgICAgYkZyZWVbZnJlZUluZGV4XVxuXG4gICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAvLyBPKE0pIHRpbWVcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXVxuXG4gICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKVxuICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMFxuICAgIHZhciByZW1vdmVzID0gW11cbiAgICB2YXIgaW5zZXJ0cyA9IFtdXG4gICAgdmFyIHNpbXVsYXRlSXRlbVxuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXVxuICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XVxuXG4gICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpXG4gICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goe2tleTogd2FudGVkSXRlbS5rZXksIHRvOiBrfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goe2tleTogd2FudGVkSXRlbS5rZXksIHRvOiBrfSlcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHtrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzoga30pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGsrK1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrK1xuICAgICAgICAgICAgaysrXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgIHdoaWxlKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF1cbiAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKVxuICAgIH1cblxuICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICB9XG4gICAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgYXJyLnNwbGljZShpbmRleCwgMSlcblxuICAgIHJldHVybiB7XG4gICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICBrZXk6IGtleVxuICAgIH1cbn1cblxuZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICB2YXIga2V5cyA9IHt9XG4gICAgdmFyIGZyZWUgPSBbXVxuICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGhcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV1cblxuICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcmVlLnB1c2goaSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIGtleXM6IGtleXMsICAgICAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgZnJlZTogZnJlZSAgICAgIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgfVxufVxuXG5mdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFwcGx5XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHBhdGNoXG4gICAgfVxufVxuIiwidmFyIHNpbXBsZVByb21pc2UgPSByZXF1aXJlKCcuL3NpbXBsZVByb21pc2UnKTtcblxuZnVuY3Rpb24gUmVuZGVyKG1vdW50KSB7XG4gIHRoaXMuZmluaXNoZWQgPSBzaW1wbGVQcm9taXNlKCk7XG4gIHRoaXMubW91bnQgPSBtb3VudDtcbiAgdGhpcy5hdHRhY2htZW50ID0gbW91bnQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gUmVuZGVyO1xuIiwidmFyIGggPSByZXF1aXJlKCcuL3ZodG1sJyk7XG52YXIgZG9tQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9kb21Db21wb25lbnQnKTtcbnZhciBiaW5kaW5nTWV0YSA9IHJlcXVpcmUoJy4vbWV0YScpO1xudmFyIHRvVmRvbSA9IHJlcXVpcmUoJy4vdG9WZG9tJyk7XG52YXIgcGFyc2VUYWcgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L3BhcnNlLXRhZycpO1xudmFyIFZpZXdNb2RlbCA9IHJlcXVpcmUoJy4vdmlld01vZGVsJyk7XG52YXIgTW91bnQgPSByZXF1aXJlKCcuL21vdW50Jyk7XG52YXIgcnVuUmVuZGVyID0gcmVxdWlyZSgnLi9ydW5SZW5kZXInKTtcbnZhciBkZXByZWNhdGlvbnMgPSByZXF1aXJlKCcuL2RlcHJlY2F0aW9ucycpO1xudmFyIGh5cGVyZG9tID0gcmVxdWlyZSgnLicpO1xuXG5mdW5jdGlvbiBpc1ZpZXdNb2RlbE9yQ29tcG9uZW50KGNvbXBvbmVudCkge1xuICByZXR1cm4gY29tcG9uZW50XG4gICAgJiYgKCh0eXBlb2YgY29tcG9uZW50LmluaXQgPT09ICdmdW5jdGlvbidcbiAgICAgICAmJiB0eXBlb2YgY29tcG9uZW50LnVwZGF0ZSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICAgICYmIHR5cGVvZiBjb21wb25lbnQuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykgfHwgKHR5cGVvZiBjb21wb25lbnQucmVuZGVyVmlld01vZGVsID09PSAnZnVuY3Rpb24nKSk7XG59XG5cbmV4cG9ydHMubWVyZ2UgPSBmdW5jdGlvbiAoZWxlbWVudCwgcmVuZGVyLCBtb2RlbCwgb3B0aW9ucykge1xuICB2YXIgbW91bnQgPSBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciBjdXJyZW50UmVuZGVyID0gaHlwZXJkb20uY3VycmVudFJlbmRlcjtcbiAgICBjdXJyZW50UmVuZGVyLmV2ZW50SGFuZGxlcldyYXBwZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG4gICAgdmFyIHZkb20gPSBtb3VudC5yZW5kZXIoKTtcbiAgICBjb21wb25lbnQubWVyZ2UodmRvbSwgZWxlbWVudCk7XG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgfSk7XG5cbiAgbW91bnQucmVyZW5kZXIoKTtcblxuICByZXR1cm4gbW91bnQ7XG59O1xuXG5leHBvcnRzLmFwcGVuZCA9IGZ1bmN0aW9uIChlbGVtZW50LCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciB2ZG9tID0gbW91bnQucmVuZGVyKCk7XG4gICAgZWxlbWVudC5hcHBlbmRDaGlsZChjb21wb25lbnQuY3JlYXRlKHZkb20pKTtcbiAgICByZXR1cm4gY29tcG9uZW50O1xuICB9KTtcbn07XG5cbmV4cG9ydHMucmVwbGFjZSA9IGZ1bmN0aW9uIChlbGVtZW50LCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICB2YXIgY29tcG9uZW50ID0gZG9tQ29tcG9uZW50KGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICAgIHZhciB2ZG9tID0gbW91bnQucmVuZGVyKCk7XG4gICAgZWxlbWVudC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChjb21wb25lbnQuY3JlYXRlKHZkb20pLCBlbGVtZW50KTtcbiAgICByZXR1cm4gY29tcG9uZW50O1xuICB9KTtcbn07XG5cbmV4cG9ydHMuYXBwZW5kVkRvbSA9IGZ1bmN0aW9uICh2ZG9tLCByZW5kZXIsIG1vZGVsLCBvcHRpb25zKSB7XG4gIHJldHVybiBzdGFydEF0dGFjaG1lbnQocmVuZGVyLCBtb2RlbCwgb3B0aW9ucywgZnVuY3Rpb24obW91bnQpIHtcbiAgICB2YXIgY29tcG9uZW50ID0ge1xuICAgICAgY3JlYXRlOiBmdW5jdGlvbihuZXdWRG9tKSB7XG4gICAgICAgIHZkb20uY2hpbGRyZW4gPSBbXTtcbiAgICAgICAgaWYgKG5ld1ZEb20pIHtcbiAgICAgICAgICB2ZG9tLmNoaWxkcmVuLnB1c2gobmV3VkRvbSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB1cGRhdGU6IGZ1bmN0aW9uKG5ld1ZEb20pIHtcbiAgICAgICAgdmRvbS5jaGlsZHJlbiA9IFtdO1xuICAgICAgICBpZiAobmV3VkRvbSkge1xuICAgICAgICAgIHZkb20uY2hpbGRyZW4ucHVzaChuZXdWRG9tKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG4gICAgY29tcG9uZW50LmNyZWF0ZShtb3VudC5yZW5kZXIoKSk7XG4gICAgcmV0dXJuIGNvbXBvbmVudDtcbiAgfSk7XG59O1xuXG5leHBvcnRzLlZpZXdNb2RlbCA9IFZpZXdNb2RlbDtcblxuZnVuY3Rpb24gc3RhcnRBdHRhY2htZW50KHJlbmRlciwgbW9kZWwsIG9wdGlvbnMsIGF0dGFjaFRvRG9tKSB7XG4gIGlmICh0eXBlb2YgcmVuZGVyID09ICdvYmplY3QnICYmIHR5cGVvZiByZW5kZXIucmVuZGVyID09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gc3RhcnQocmVuZGVyLCBhdHRhY2hUb0RvbSwgbW9kZWwpO1xuICB9IGVsc2Uge1xuICAgIGRlcHJlY2F0aW9ucy5yZW5kZXJGdW5jdGlvbignaHlwZXJkb20uYXBwZW5kIGFuZCBoeXBlcmRvbS5yZXBsYWNlIHdpdGggcmVuZGVyIGZ1bmN0aW9ucyBhcmUgZGVwcmVjYXRlZCwgcGxlYXNlIHBhc3MgYSBWaWV3TW9kZWwnKTtcbiAgICByZXR1cm4gc3RhcnQoe3JlbmRlcjogZnVuY3Rpb24gKCkgeyByZXR1cm4gcmVuZGVyKG1vZGVsKTsgfX0sIGF0dGFjaFRvRG9tLCBvcHRpb25zKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdGFydChtb2RlbCwgYXR0YWNoVG9Eb20sIG9wdGlvbnMpIHtcbiAgdmFyIG1vdW50ID0gbmV3IE1vdW50KG1vZGVsLCBvcHRpb25zKTtcbiAgcnVuUmVuZGVyKG1vdW50LCBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKG9wdGlvbnMpIHtcbiAgICAgIHZhciBkb21Db21wb25lbnRPcHRpb25zID0ge2RvY3VtZW50OiBvcHRpb25zLmRvY3VtZW50fTtcbiAgICB9XG4gICAgbW91bnQuY29tcG9uZW50ID0gYXR0YWNoVG9Eb20obW91bnQsIGRvbUNvbXBvbmVudE9wdGlvbnMpO1xuICB9KTtcbiAgcmV0dXJuIG1vdW50O1xufVxuXG52YXIgbm9yZWZyZXNoID0ge307XG5cbmZ1bmN0aW9uIG5vcmVmcmVzaEZ1bmN0aW9uKCkge1xuICByZXR1cm4gbm9yZWZyZXNoO1xufVxuXG5mdW5jdGlvbiByZWZyZXNoaWZ5KGZuLCBvcHRpb25zKSB7XG4gIGlmICghZm4pIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICBpZiAoIWN1cnJlbnRSZW5kZXIpIHtcbiAgICBpZiAodHlwZW9mIGdsb2JhbCA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiBmbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgY2Fubm90IGNyZWF0ZSB2aXJ0dWFsLWRvbSBldmVudCBoYW5kbGVycyBvdXRzaWRlIGEgcmVuZGVyIGZ1bmN0aW9uLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZlYXR1cmlzdC9oeXBlcmRvbSNvdXRzaWRlLXJlbmRlci1jeWNsZScpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBtb3VudCA9IGN1cnJlbnRSZW5kZXIubW91bnQ7XG4gIHZhciBoYW5kbGVFdmVudFJlc3VsdCA9IGV4cG9ydHMuY3JlYXRlRXZlbnRSZXN1bHRIYW5kbGVyKG1vdW50LCBvcHRpb25zKTtcblxuICBpZiAob3B0aW9ucyAmJiAob3B0aW9ucy5ub3JlZnJlc2ggPT0gdHJ1ZSB8fCBvcHRpb25zLnJlZnJlc2ggPT0gZmFsc2UpKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gaGFuZGxlRXZlbnRSZXN1bHQocmVzdWx0KTtcbiAgfTtcbn1cblxuZXhwb3J0cy5jcmVhdGVFdmVudFJlc3VsdEhhbmRsZXIgPSBmdW5jdGlvbihtb3VudCwgb3B0aW9ucykge1xuICB2YXIgb25seVJlZnJlc2hBZnRlclByb21pc2UgPSBvcHRpb25zICYmIG9wdGlvbnMucmVmcmVzaCA9PSAncHJvbWlzZSc7XG4gIHZhciB2aWV3TW9kZWxUb1JlZnJlc2ggPSBvcHRpb25zICYmIG9wdGlvbnMudmlld01vZGVsO1xuICB2YXIgY29tcG9uZW50VG9SZWZyZXNoID0gb3B0aW9ucyAmJiBvcHRpb25zLmNvbXBvbmVudDtcblxuICBmdW5jdGlvbiBoYW5kbGVFdmVudFJlc3VsdChyZXN1bHQsIHByb21pc2VSZXN1bHQpIHtcbiAgICBpZiAocmVzdWx0ICYmIHR5cGVvZihyZXN1bHQudGhlbikgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmVzdWx0LnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgeyBoYW5kbGVFdmVudFJlc3VsdChyZXN1bHQsIHRydWUpOyB9KTtcbiAgICB9XG5cbiAgICBpZiAob25seVJlZnJlc2hBZnRlclByb21pc2UgJiYgIXByb21pc2VSZXN1bHQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaXNWaWV3TW9kZWxPckNvbXBvbmVudChyZXN1bHQpKSB7XG4gICAgICBtb3VudC5yZXJlbmRlcldpZGdldChyZXN1bHQpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmVzdWx0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhhbmRsZUV2ZW50UmVzdWx0KHJlc3VsdFtpXSk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh2aWV3TW9kZWxUb1JlZnJlc2gpIHtcbiAgICAgIHZpZXdNb2RlbFRvUmVmcmVzaC5yZXJlbmRlclZpZXdNb2RlbCgpO1xuICAgIH0gZWxzZSBpZiAoY29tcG9uZW50VG9SZWZyZXNoKSB7XG4gICAgICBjb21wb25lbnRUb1JlZnJlc2gucmVmcmVzaCgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0ID09PSBub3JlZnJlc2gpIHtcbiAgICAgIC8vIGRvbid0IHJlZnJlc2g7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQgPT09IG5vcmVmcmVzaEZ1bmN0aW9uKSB7XG4gICAgICBkZXByZWNhdGlvbnMubm9yZWZyZXNoKCdoeXBlcmRvbS5odG1sLm5vcmVmcmVzaCBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIGh5cGVyZG9tLm5vcmVmcmVzaCgpJyk7XG4gICAgICAvLyBkb24ndCByZWZyZXNoO1xuICAgIH0gZWxzZSB7XG4gICAgICBtb3VudC5yZXJlbmRlcigpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaGFuZGxlRXZlbnRSZXN1bHQ7XG59O1xuXG5mdW5jdGlvbiBiaW5kVGV4dElucHV0KGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICB2YXIgdGV4dEV2ZW50TmFtZXMgPSBbJ29ua2V5dXAnLCAnb25pbnB1dCcsICdvbnBhc3RlJywgJ3RleHRJbnB1dCddO1xuXG4gIHZhciBiaW5kaW5nVmFsdWUgPSBnZXQoKTtcbiAgaWYgKCEoYmluZGluZ1ZhbHVlIGluc3RhbmNlb2YgRXJyb3IpKSB7XG4gICAgYXR0cmlidXRlcy52YWx1ZSA9IGJpbmRpbmdWYWx1ZSAhPSB1bmRlZmluZWQ/IGJpbmRpbmdWYWx1ZTogJyc7XG4gIH1cblxuICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgdGV4dEV2ZW50TmFtZXMsIGZ1bmN0aW9uIChldikge1xuICAgIGlmIChiaW5kaW5nVmFsdWUgIT0gZXYudGFyZ2V0LnZhbHVlKSB7XG4gICAgICBzZXQoZXYudGFyZ2V0LnZhbHVlKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzZXF1ZW5jZUZ1bmN0aW9ucyhoYW5kbGVyMSwgaGFuZGxlcjIpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChldikge1xuICAgIGhhbmRsZXIxKGV2KTtcbiAgICByZXR1cm4gaGFuZGxlcjIoZXYpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBpbnNlcnRFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgZXZlbnROYW1lLCBoYW5kbGVyKSB7XG4gIHZhciBwcmV2aW91c0hhbmRsZXIgPSBhdHRyaWJ1dGVzW2V2ZW50TmFtZV07XG4gIGlmIChwcmV2aW91c0hhbmRsZXIpIHtcbiAgICBhdHRyaWJ1dGVzW2V2ZW50TmFtZV0gPSBzZXF1ZW5jZUZ1bmN0aW9ucyhoYW5kbGVyLCBwcmV2aW91c0hhbmRsZXIpO1xuICB9IGVsc2Uge1xuICAgIGF0dHJpYnV0ZXNbZXZlbnROYW1lXSA9IGhhbmRsZXI7XG4gIH1cbn1cblxuZnVuY3Rpb24gYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsIGV2ZW50TmFtZXMsIGhhbmRsZXIpIHtcbiAgaWYgKGV2ZW50TmFtZXMgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIGZvciAodmFyIG4gPSAwOyBuIDwgZXZlbnROYW1lcy5sZW5ndGg7IG4rKykge1xuICAgICAgaW5zZXJ0RXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsIGV2ZW50TmFtZXNbbl0sIGhhbmRsZXIpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpbnNlcnRFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgZXZlbnROYW1lcywgaGFuZGxlcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gTGlzdGVuZXJIb29rKGxpc3RlbmVyKSB7XG4gIHRoaXMubGlzdGVuZXIgPSBleHBvcnRzLmh0bWwucmVmcmVzaGlmeShsaXN0ZW5lcik7XG59XG5cbkxpc3RlbmVySG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChlbGVtZW50LCBwcm9wZXJ0eU5hbWUpIHtcbiAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHByb3BlcnR5TmFtZS5zdWJzdHJpbmcoMiksIHRoaXMubGlzdGVuZXIsIGZhbHNlKTtcbn07XG5cbkxpc3RlbmVySG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKGVsZW1lbnQsIHByb3BlcnR5TmFtZSkge1xuICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIocHJvcGVydHlOYW1lLnN1YnN0cmluZygyKSwgdGhpcy5saXN0ZW5lcik7XG59O1xuXG5mdW5jdGlvbiBjdXN0b21FdmVudChuYW1lKSB7XG4gIGlmICh0eXBlb2YgRXZlbnQgPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBuZXcgRXZlbnQobmFtZSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XG4gICAgZXZlbnQuaW5pdEV2ZW50KG5hbWUsIGZhbHNlLCBmYWxzZSk7XG4gICAgcmV0dXJuIGV2ZW50O1xuICB9XG59XG5cbnZhciBpbnB1dFR5cGVCaW5kaW5ncyA9IHtcbiAgdGV4dDogYmluZFRleHRJbnB1dCxcblxuICB0ZXh0YXJlYTogYmluZFRleHRJbnB1dCxcblxuICBjaGVja2JveDogZnVuY3Rpb24gKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGdldCgpO1xuXG4gICAgYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsICdvbmNsaWNrJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBhdHRyaWJ1dGVzLmNoZWNrZWQgPSBldi50YXJnZXQuY2hlY2tlZDtcbiAgICAgIHNldChldi50YXJnZXQuY2hlY2tlZCk7XG4gICAgfSk7XG4gIH0sXG5cbiAgcmFkaW86IGZ1bmN0aW9uIChhdHRyaWJ1dGVzLCBjaGlsZHJlbiwgZ2V0LCBzZXQpIHtcbiAgICB2YXIgdmFsdWUgPSBhdHRyaWJ1dGVzLnZhbHVlO1xuICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGdldCgpID09IGF0dHJpYnV0ZXMudmFsdWU7XG4gICAgYXR0cmlidXRlcy5vbl9oeXBlcmRvbXN5bmNjaGVja2VkID0gbmV3IExpc3RlbmVySG9vayhmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGF0dHJpYnV0ZXMuY2hlY2tlZCA9IGV2ZW50LnRhcmdldC5jaGVja2VkO1xuICAgIH0pO1xuXG4gICAgYXR0YWNoRXZlbnRIYW5kbGVyKGF0dHJpYnV0ZXMsICdvbmNsaWNrJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICB2YXIgbmFtZSA9IGV2ZW50LnRhcmdldC5uYW1lO1xuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgdmFyIGlucHV0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlOYW1lKG5hbWUpO1xuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGlucHV0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICBpbnB1dHNbaV0uZGlzcGF0Y2hFdmVudChjdXN0b21FdmVudCgnX2h5cGVyZG9tc3luY2NoZWNrZWQnKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNldCh2YWx1ZSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgc2VsZWN0OiBmdW5jdGlvbiAoYXR0cmlidXRlcywgY2hpbGRyZW4sIGdldCwgc2V0KSB7XG4gICAgdmFyIGN1cnJlbnRWYWx1ZSA9IGdldCgpO1xuXG4gICAgdmFyIG9wdGlvbnMgPSBjaGlsZHJlbi5maWx0ZXIoZnVuY3Rpb24gKGNoaWxkKSB7XG4gICAgICByZXR1cm4gY2hpbGQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09ICdvcHRpb24nO1xuICAgIH0pO1xuXG4gICAgdmFyIHZhbHVlcyA9IFtdO1xuICAgIHZhciBzZWxlY3RlZEluZGV4O1xuXG4gICAgZm9yKHZhciBuID0gMDsgbiA8IG9wdGlvbnMubGVuZ3RoOyBuKyspIHtcbiAgICAgIHZhciBvcHRpb24gPSBvcHRpb25zW25dO1xuICAgICAgdmFyIGhhc1ZhbHVlID0gb3B0aW9uLnByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJyk7XG4gICAgICB2YXIgdmFsdWUgPSBvcHRpb24ucHJvcGVydGllcy52YWx1ZTtcbiAgICAgIHZhciB0ZXh0ID0gb3B0aW9uLmNoaWxkcmVuLm1hcChmdW5jdGlvbiAoeCkgeyByZXR1cm4geC50ZXh0OyB9KS5qb2luKCcnKTtcblxuICAgICAgdmFsdWVzLnB1c2goaGFzVmFsdWU/IHZhbHVlOiB0ZXh0KTtcblxuICAgICAgdmFyIHNlbGVjdGVkID0gdmFsdWUgPT0gY3VycmVudFZhbHVlIHx8IHRleHQgPT0gY3VycmVudFZhbHVlO1xuXG4gICAgICBpZiAoc2VsZWN0ZWQpIHtcbiAgICAgICAgc2VsZWN0ZWRJbmRleCA9IG47XG4gICAgICB9XG5cbiAgICAgIG9wdGlvbi5wcm9wZXJ0aWVzLnNlbGVjdGVkID0gc2VsZWN0ZWQ7XG4gICAgICBvcHRpb24ucHJvcGVydGllcy52YWx1ZSA9IG47XG4gICAgfVxuXG4gICAgaWYgKHNlbGVjdGVkSW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgYXR0cmlidXRlcy5zZWxlY3RlZEluZGV4ID0gc2VsZWN0ZWRJbmRleDtcbiAgICB9XG5cbiAgICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgJ29uY2hhbmdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBhdHRyaWJ1dGVzLnNlbGVjdGVkSW5kZXggPSBldi50YXJnZXQuc2VsZWN0ZWRJbmRleDtcbiAgICAgIHNldCh2YWx1ZXNbZXYudGFyZ2V0LnZhbHVlXSk7XG4gICAgfSk7XG4gIH0sXG5cbiAgZmlsZTogZnVuY3Rpb24gKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBnZXQsIHNldCkge1xuICAgIHZhciBtdWx0aXBsZSA9IGF0dHJpYnV0ZXMubXVsdGlwbGU7XG5cbiAgICBhdHRhY2hFdmVudEhhbmRsZXIoYXR0cmlidXRlcywgJ29uY2hhbmdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICBpZiAobXVsdGlwbGUpIHtcbiAgICAgICAgc2V0KGV2LnRhcmdldC5maWxlcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZXQoZXYudGFyZ2V0LmZpbGVzWzBdKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufTtcblxuZnVuY3Rpb24gYmluZE1vZGVsKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCB0eXBlKSB7XG4gIHZhciBiaW5kID0gaW5wdXRUeXBlQmluZGluZ3NbdHlwZV0gfHwgYmluZFRleHRJbnB1dDtcblxuICB2YXIgYmluZGluZ0F0dHIgPSBtYWtlQmluZGluZyhhdHRyaWJ1dGVzLmJpbmRpbmcpO1xuICBiaW5kKGF0dHJpYnV0ZXMsIGNoaWxkcmVuLCBiaW5kaW5nQXR0ci5nZXQsIGJpbmRpbmdBdHRyLnNldCk7XG59XG5cbmZ1bmN0aW9uIGlucHV0VHlwZShzZWxlY3RvciwgYXR0cmlidXRlcykge1xuICBpZiAoL150ZXh0YXJlYVxcYi9pLnRlc3Qoc2VsZWN0b3IpKSB7XG4gICAgcmV0dXJuICd0ZXh0YXJlYSc7XG4gIH0gZWxzZSBpZiAoL15zZWxlY3RcXGIvaS50ZXN0KHNlbGVjdG9yKSkge1xuICAgIHJldHVybiAnc2VsZWN0JztcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXR0cmlidXRlcy50eXBlIHx8ICd0ZXh0JztcbiAgfVxufVxuXG52YXIgcmVuYW1lcyA9IHtcbiAgZm9yOiAnaHRtbEZvcicsXG4gIGNsYXNzOiAnY2xhc3NOYW1lJyxcbiAgY29udGVudGVkaXRhYmxlOiAnY29udGVudEVkaXRhYmxlJyxcbiAgdGFiaW5kZXg6ICd0YWJJbmRleCcsXG4gIGNvbHNwYW46ICdjb2xTcGFuJ1xufTtcblxudmFyIGRhdGFBdHRyaWJ1dGVSZWdleCA9IC9eZGF0YS0vO1xuXG5mdW5jdGlvbiBwcmVwYXJlQXR0cmlidXRlcyh0YWcsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpIHtcbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKTtcbiAgdmFyIGRhdGFzZXQ7XG4gIHZhciBjdXJyZW50UmVuZGVyID0gaHlwZXJkb20uY3VycmVudFJlbmRlcigpO1xuICB2YXIgZXZlbnRIYW5kbGVyV3JhcHBlciA9IGN1cnJlbnRSZW5kZXIgJiYgY3VycmVudFJlbmRlci5ldmVudEhhbmRsZXJXcmFwcGVyO1xuXG4gIGZvciAodmFyIGsgPSAwOyBrIDwga2V5cy5sZW5ndGg7IGsrKykge1xuICAgIHZhciBrZXkgPSBrZXlzW2tdO1xuICAgIHZhciBhdHRyaWJ1dGUgPSBhdHRyaWJ1dGVzW2tleV07XG5cbiAgICBpZiAodHlwZW9mKGF0dHJpYnV0ZSkgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaWYgKGV2ZW50SGFuZGxlcldyYXBwZXIpIHtcbiAgICAgICAgdmFyIGZuID0gZXZlbnRIYW5kbGVyV3JhcHBlci5jYWxsKHVuZGVmaW5lZCwga2V5LnJlcGxhY2UoL15vbi8sICcnKSwgYXR0cmlidXRlKTtcbiAgICAgICAgYXR0cmlidXRlc1trZXldID0gdHlwZW9mIGZuID09PSAnZnVuY3Rpb24nPyByZWZyZXNoaWZ5KGZuKTogZm47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhdHRyaWJ1dGVzW2tleV0gPSByZWZyZXNoaWZ5KGF0dHJpYnV0ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIHJlbmFtZSA9IHJlbmFtZXNba2V5XTtcbiAgICBpZiAocmVuYW1lKSB7XG4gICAgICBhdHRyaWJ1dGVzW3JlbmFtZV0gPSBhdHRyaWJ1dGU7XG4gICAgICBkZWxldGUgYXR0cmlidXRlc1trZXldO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKGRhdGFBdHRyaWJ1dGVSZWdleC50ZXN0KGtleSkpIHtcbiAgICAgIGlmICghZGF0YXNldCkge1xuICAgICAgICBkYXRhc2V0ID0gYXR0cmlidXRlcy5kYXRhc2V0O1xuXG4gICAgICAgIGlmICghZGF0YXNldCkge1xuICAgICAgICAgIGRhdGFzZXQgPSBhdHRyaWJ1dGVzLmRhdGFzZXQgPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgZGF0YWtleSA9IGtleVxuICAgICAgICAucmVwbGFjZShkYXRhQXR0cmlidXRlUmVnZXgsICcnKVxuICAgICAgICAucmVwbGFjZSgvLShbYS16XSkvaWcsIGZ1bmN0aW9uKF8sIHgpIHsgcmV0dXJuIHgudG9VcHBlckNhc2UoKTsgfSk7XG5cbiAgICAgIGRhdGFzZXRbZGF0YWtleV0gPSBhdHRyaWJ1dGU7XG4gICAgICBkZWxldGUgYXR0cmlidXRlc1trZXldO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKGF0dHJpYnV0ZXMuY2xhc3NOYW1lKSB7XG4gICAgYXR0cmlidXRlcy5jbGFzc05hbWUgPSBnZW5lcmF0ZUNsYXNzTmFtZShhdHRyaWJ1dGVzLmNsYXNzTmFtZSk7XG4gIH1cblxuICBpZiAoYXR0cmlidXRlcy5iaW5kaW5nKSB7XG4gICAgYmluZE1vZGVsKGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMsIGlucHV0VHlwZSh0YWcsIGF0dHJpYnV0ZXMpKTtcbiAgICBkZWxldGUgYXR0cmlidXRlcy5iaW5kaW5nO1xuICB9XG59XG5cbi8qKlxuICogdGhpcyBmdW5jdGlvbiBpcyBxdWl0ZSB1Z2x5IGFuZCB5b3UgbWF5IGJlIHZlcnkgdGVtcHRlZFxuICogdG8gcmVmYWN0b3IgaXQgaW50byBzbWFsbGVyIGZ1bmN0aW9ucywgSSBjZXJ0YWlubHkgYW0uXG4gKiBob3dldmVyLCBpdCB3YXMgd3JpdHRlbiBsaWtlIHRoaXMgZm9yIHBlcmZvcm1hbmNlXG4gKiBzbyB0aGluayBvZiB0aGF0IGJlZm9yZSByZWZhY3RvcmluZyEgOilcbiAqL1xuZXhwb3J0cy5odG1sID0gZnVuY3Rpb24gKGhpZXJhcmNoeVNlbGVjdG9yKSB7XG4gIHZhciBoYXNIaWVyYXJjaHkgPSBoaWVyYXJjaHlTZWxlY3Rvci5pbmRleE9mKCcgJykgPj0gMDtcbiAgdmFyIHNlbGVjdG9yLCBzZWxlY3RvckVsZW1lbnRzO1xuXG4gIGlmIChoYXNIaWVyYXJjaHkpIHtcbiAgICBzZWxlY3RvckVsZW1lbnRzID0gaGllcmFyY2h5U2VsZWN0b3IubWF0Y2goL1xcUysvZyk7XG4gICAgc2VsZWN0b3IgPSBzZWxlY3RvckVsZW1lbnRzW3NlbGVjdG9yRWxlbWVudHMubGVuZ3RoIC0gMV07XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0b3IgPSBoaWVyYXJjaHlTZWxlY3RvcjtcbiAgfVxuXG4gIHZhciBjaGlsZEVsZW1lbnRzO1xuICB2YXIgdmRvbTtcbiAgdmFyIHRhZztcbiAgdmFyIGF0dHJpYnV0ZXMgPSBhcmd1bWVudHNbMV07XG5cbiAgaWYgKGF0dHJpYnV0ZXMgJiYgYXR0cmlidXRlcy5jb25zdHJ1Y3RvciA9PSBPYmplY3QgJiYgdHlwZW9mIGF0dHJpYnV0ZXMucmVuZGVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgY2hpbGRFbGVtZW50cyA9IHRvVmRvbS5yZWN1cnNpdmUoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSk7XG4gICAgcHJlcGFyZUF0dHJpYnV0ZXMoc2VsZWN0b3IsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpO1xuICAgIHRhZyA9IHBhcnNlVGFnKHNlbGVjdG9yLCBhdHRyaWJ1dGVzKTtcbiAgICB2ZG9tID0gaCh0YWcsIGF0dHJpYnV0ZXMsIGNoaWxkRWxlbWVudHMpO1xuICB9IGVsc2Uge1xuICAgIGF0dHJpYnV0ZXMgPSB7fTtcbiAgICBjaGlsZEVsZW1lbnRzID0gdG9WZG9tLnJlY3Vyc2l2ZShBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICB0YWcgPSBwYXJzZVRhZyhzZWxlY3RvciwgYXR0cmlidXRlcyk7XG4gICAgdmRvbSA9IGgodGFnLCBhdHRyaWJ1dGVzLCBjaGlsZEVsZW1lbnRzKTtcbiAgfVxuXG4gIGlmIChoYXNIaWVyYXJjaHkpIHtcbiAgICBmb3IodmFyIG4gPSBzZWxlY3RvckVsZW1lbnRzLmxlbmd0aCAtIDI7IG4gPj0gMDsgbi0tKSB7XG4gICAgICB2ZG9tID0gaChzZWxlY3RvckVsZW1lbnRzW25dLCB7fSwgW3Zkb21dKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmRvbTtcbn07XG5cbmV4cG9ydHMuanN4ID0gZnVuY3Rpb24gKHRhZywgYXR0cmlidXRlcykge1xuICB2YXIgY2hpbGRFbGVtZW50cyA9IHRvVmRvbS5yZWN1cnNpdmUoQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSk7XG4gIGlmIChhdHRyaWJ1dGVzKSB7XG4gICAgcHJlcGFyZUF0dHJpYnV0ZXModGFnLCBhdHRyaWJ1dGVzLCBjaGlsZEVsZW1lbnRzKTtcbiAgfVxuICByZXR1cm4gaCh0YWcsIGF0dHJpYnV0ZXMgfHwge30sIGNoaWxkRWxlbWVudHMpO1xufTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMuaHRtbCwgJ2N1cnJlbnRSZW5kZXInLCB7Z2V0OiBmdW5jdGlvbiAoKSB7XG4gIGRlcHJlY2F0aW9ucy5jdXJyZW50UmVuZGVyKCdoeXBlcmRvbS5odG1sLmN1cnJlbnRSZW5kZXIgaXMgZGVwcmVjYXRlZCwgcGxlYXNlIHVzZSBoeXBlcmRvbS5jdXJyZW50UmVuZGVyKCkgaW5zdGVhZCcpO1xuICByZXR1cm4gZXhwb3J0cy5odG1sLl9jdXJyZW50UmVuZGVyO1xufX0pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cy5odG1sLCAncmVmcmVzaCcsIHtnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgZGVwcmVjYXRpb25zLnJlZnJlc2goJ2h5cGVyZG9tLmh0bWwucmVmcmVzaCBpcyBkZXByZWNhdGVkLCBwbGVhc2UgdXNlIHZpZXdNb2RlbC5yZXJlbmRlcigpIGluc3RlYWQnKTtcbiAgcmV0dXJuIGV4cG9ydHMuaHRtbC5fcmVmcmVzaDtcbn19KTtcblxuZnVuY3Rpb24gcmVmcmVzaEFmdGVyKHByb21pc2UpIHtcbiAgZGVwcmVjYXRpb25zLnJlZnJlc2hBZnRlcignaHlwZXJkb20uaHRtbC5yZWZyZXNoQWZ0ZXIgaXMgZGVwcmVjYXRlZCcpO1xuICB2YXIgcmVmcmVzaCA9IGV4cG9ydHMuaHRtbC5yZWZyZXNoO1xuXG4gIHByb21pc2UudGhlbihyZWZyZXNoKTtcbn1cblxuZXhwb3J0cy5odG1sLnJlZnJlc2hpZnkgPSByZWZyZXNoaWZ5O1xuZXhwb3J0cy5odG1sLnJlZnJlc2hBZnRlciA9IHJlZnJlc2hBZnRlcjtcbmV4cG9ydHMuaHRtbC5ub3JlZnJlc2ggPSBub3JlZnJlc2g7XG5cbmZ1bmN0aW9uIG1ha2VCaW5kaW5nKGIsIG9wdGlvbnMpIHtcbiAgdmFyIGJpbmRpbmcgPSBiIGluc3RhbmNlb2YgQXJyYXlcbiAgICA/ICBiaW5kaW5nT2JqZWN0LmFwcGx5KHVuZGVmaW5lZCwgYilcbiAgICA6IGI7XG5cbiAgYmluZGluZy5zZXQgPSByZWZyZXNoaWZ5KGJpbmRpbmcuc2V0LCBvcHRpb25zKTtcblxuICByZXR1cm4gYmluZGluZztcbn1cblxuZnVuY3Rpb24gbWFrZUNvbnZlcnRlcihjb252ZXJ0ZXIpIHtcbiAgaWYgKHR5cGVvZiBjb252ZXJ0ZXIgPT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiB7XG4gICAgICB2aWV3OiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgcmV0dXJuIG1vZGVsO1xuICAgICAgfSxcbiAgICAgIG1vZGVsOiBmdW5jdGlvbiAodmlldykge1xuICAgICAgICByZXR1cm4gY29udmVydGVyKHZpZXcpO1xuICAgICAgfVxuICAgIH07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvbnZlcnRlcjtcbiAgfVxufVxuXG5mdW5jdGlvbiBjaGFpbkNvbnZlcnRlcnMoc3RhcnRJbmRleCwgY29udmVydGVycykge1xuICBmdW5jdGlvbiBtYWtlQ29udmVydGVycygpIHtcbiAgICBpZiAoIV9jb252ZXJ0ZXJzKSB7XG4gICAgICBfY29udmVydGVycyA9IG5ldyBBcnJheShjb252ZXJ0ZXJzLmxlbmd0aCAtIHN0YXJ0SW5kZXgpO1xuXG4gICAgICBmb3IodmFyIG4gPSBzdGFydEluZGV4OyBuIDwgY29udmVydGVycy5sZW5ndGg7IG4rKykge1xuICAgICAgICBfY29udmVydGVyc1tuIC0gc3RhcnRJbmRleF0gPSBtYWtlQ29udmVydGVyKGNvbnZlcnRlcnNbbl0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICgoY29udmVydGVycy5sZW5ndGggLSBzdGFydEluZGV4KSA9PSAxKSB7XG4gICAgcmV0dXJuIG1ha2VDb252ZXJ0ZXIoY29udmVydGVyc1tzdGFydEluZGV4XSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIF9jb252ZXJ0ZXJzO1xuICAgIHJldHVybiB7XG4gICAgICB2aWV3OiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgbWFrZUNvbnZlcnRlcnMoKTtcbiAgICAgICAgdmFyIGludGVybWVkaWF0ZVZhbHVlID0gbW9kZWw7XG4gICAgICAgIGZvcih2YXIgbiA9IDA7IG4gPCBfY29udmVydGVycy5sZW5ndGg7IG4rKykge1xuICAgICAgICAgIGludGVybWVkaWF0ZVZhbHVlID0gX2NvbnZlcnRlcnNbbl0udmlldyhpbnRlcm1lZGlhdGVWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludGVybWVkaWF0ZVZhbHVlO1xuICAgICAgfSxcblxuICAgICAgbW9kZWw6IGZ1bmN0aW9uICh2aWV3KSB7XG4gICAgICAgIG1ha2VDb252ZXJ0ZXJzKCk7XG4gICAgICAgIHZhciBpbnRlcm1lZGlhdGVWYWx1ZSA9IHZpZXc7XG4gICAgICAgIGZvcih2YXIgbiA9IF9jb252ZXJ0ZXJzLmxlbmd0aCAtIDE7IG4gPj0gMDsgbi0tKSB7XG4gICAgICAgICAgaW50ZXJtZWRpYXRlVmFsdWUgPSBfY29udmVydGVyc1tuXS5tb2RlbChpbnRlcm1lZGlhdGVWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludGVybWVkaWF0ZVZhbHVlO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn1cblxuZnVuY3Rpb24gYmluZGluZ09iamVjdChtb2RlbCwgcHJvcGVydHkpIHtcbiAgdmFyIF9tZXRhO1xuICBmdW5jdGlvbiBoeXBlcmRvbU1ldGEoKSB7XG4gICAgcmV0dXJuIF9tZXRhIHx8IChfbWV0YSA9IGJpbmRpbmdNZXRhKG1vZGVsLCBwcm9wZXJ0eSkpO1xuICB9XG5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKSB7XG4gICAgdmFyIGNvbnZlcnRlciA9IGNoYWluQ29udmVydGVycygyLCBhcmd1bWVudHMpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtZXRhID0gaHlwZXJkb21NZXRhKCk7XG4gICAgICAgIHZhciBtb2RlbFZhbHVlID0gbW9kZWxbcHJvcGVydHldO1xuICAgICAgICB2YXIgbW9kZWxUZXh0O1xuXG4gICAgICAgIGlmIChtZXRhLmVycm9yKSB7XG4gICAgICAgICAgcmV0dXJuIG1ldGEudmlldztcbiAgICAgICAgfSBlbHNlIGlmIChtZXRhLnZpZXcgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIG1vZGVsVGV4dCA9IGNvbnZlcnRlci52aWV3KG1vZGVsVmFsdWUpO1xuICAgICAgICAgIG1ldGEudmlldyA9IG1vZGVsVGV4dDtcbiAgICAgICAgICByZXR1cm4gbW9kZWxUZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gY29udmVydGVyLm1vZGVsKG1ldGEudmlldyk7XG4gICAgICAgICAgbW9kZWxUZXh0ID0gY29udmVydGVyLnZpZXcobW9kZWxWYWx1ZSk7XG4gICAgICAgICAgdmFyIG5vcm1hbGlzZWRQcmV2aW91c1RleHQgPSBjb252ZXJ0ZXIudmlldyhwcmV2aW91c1ZhbHVlKTtcblxuICAgICAgICAgIGlmIChtb2RlbFRleHQgPT09IG5vcm1hbGlzZWRQcmV2aW91c1RleHQpIHtcbiAgICAgICAgICAgIHJldHVybiBtZXRhLnZpZXc7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1ldGEudmlldyA9IG1vZGVsVGV4dDtcbiAgICAgICAgICAgIHJldHVybiBtb2RlbFRleHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuXG4gICAgICBzZXQ6IGZ1bmN0aW9uKHZpZXcpIHtcbiAgICAgICAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEoKTtcbiAgICAgICAgbWV0YS52aWV3ID0gdmlldztcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIG1vZGVsW3Byb3BlcnR5XSA9IGNvbnZlcnRlci5tb2RlbCh2aWV3LCBtb2RlbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgIGRlbGV0ZSBtZXRhLmVycm9yO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgbWV0YS5lcnJvciA9IGU7XG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIG1ldGE6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaHlwZXJkb21NZXRhKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBtb2RlbFtwcm9wZXJ0eV07XG4gICAgICB9LFxuXG4gICAgICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBtb2RlbFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgICAgIH0sXG5cbiAgICAgIG1ldGE6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gaHlwZXJkb21NZXRhKCk7XG4gICAgICB9XG4gICAgfTtcbiAgfVxufVxuXG5leHBvcnRzLmJpbmRpbmcgPSBtYWtlQmluZGluZztcbmV4cG9ydHMuaHRtbC5iaW5kaW5nID0gbWFrZUJpbmRpbmc7XG5leHBvcnRzLmh0bWwubWV0YSA9IGJpbmRpbmdNZXRhO1xuXG5mdW5jdGlvbiByYXdIdG1sKCkge1xuICB2YXIgc2VsZWN0b3I7XG4gIHZhciBodG1sO1xuICB2YXIgb3B0aW9ucztcblxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAyKSB7XG4gICAgc2VsZWN0b3IgPSBhcmd1bWVudHNbMF07XG4gICAgaHRtbCA9IGFyZ3VtZW50c1sxXTtcbiAgICBvcHRpb25zID0ge2lubmVySFRNTDogaHRtbH07XG4gICAgcmV0dXJuIGV4cG9ydHMuaHRtbChzZWxlY3Rvciwgb3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgc2VsZWN0b3IgPSBhcmd1bWVudHNbMF07XG4gICAgb3B0aW9ucyA9IGFyZ3VtZW50c1sxXTtcbiAgICBodG1sID0gYXJndW1lbnRzWzJdO1xuICAgIG9wdGlvbnMuaW5uZXJIVE1MID0gaHRtbDtcbiAgICByZXR1cm4gZXhwb3J0cy5odG1sKHNlbGVjdG9yLCBvcHRpb25zKTtcbiAgfVxufVxuXG5leHBvcnRzLmh0bWwucmF3SHRtbCA9IHJhd0h0bWw7XG5cblxuZnVuY3Rpb24gZ2VuZXJhdGVDb25kaXRpb25hbENsYXNzTmFtZXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmZpbHRlcihmdW5jdGlvbiAoa2V5KSB7XG4gICAgcmV0dXJuIG9ialtrZXldO1xuICB9KS5qb2luKCcgJykgfHwgdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUNsYXNzTmFtZShvYmopIHtcbiAgaWYgKHR5cGVvZihvYmopID09ICdvYmplY3QnKSB7XG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICB2YXIgbmFtZXMgPSBvYmoubWFwKGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgICAgcmV0dXJuIGdlbmVyYXRlQ2xhc3NOYW1lKGl0ZW0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gbmFtZXMuam9pbignICcpIHx8IHVuZGVmaW5lZDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGdlbmVyYXRlQ29uZGl0aW9uYWxDbGFzc05hbWVzKG9iaik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBvYmo7XG4gIH1cbn1cbiIsInZhciBoeXBlcmRvbSA9IHJlcXVpcmUoJy4nKTtcbnZhciBSZW5kZXIgPSByZXF1aXJlKCcuL3JlbmRlcicpO1xudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG5cbmZ1bmN0aW9uIHJlZnJlc2hPdXRPZlJlbmRlcigpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdQbGVhc2UgYXNzaWduIGh5cGVyZG9tLmh0bWwucmVmcmVzaCBkdXJpbmcgYSByZW5kZXIgY3ljbGUgaWYgeW91IHdhbnQgdG8gdXNlIGl0IGluIGV2ZW50IGhhbmRsZXJzLiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2ZlYXR1cmlzdC9oeXBlcmRvbSNyZWZyZXNoLW91dHNpZGUtcmVuZGVyLWN5Y2xlJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24obW91bnQsIGZuKSB7XG4gIHZhciByZW5kZXIgPSBuZXcgUmVuZGVyKG1vdW50KTtcblxuICB0cnkge1xuICAgIGh5cGVyZG9tLl9jdXJyZW50UmVuZGVyID0gcmVuZGVyO1xuXG4gICAgcmVuZGVyaW5nLmh0bWwuX2N1cnJlbnRSZW5kZXIgPSByZW5kZXI7XG4gICAgcmVuZGVyaW5nLmh0bWwuX3JlZnJlc2ggPSByZW5kZXJpbmcuY3JlYXRlRXZlbnRSZXN1bHRIYW5kbGVyKG1vdW50KTtcblxuICAgIGZuKCk7XG4gIH0gZmluYWxseSB7XG4gICAgcmVuZGVyLmZpbmlzaGVkLmZ1bGZpbGwoKTtcbiAgICBoeXBlcmRvbS5fY3VycmVudFJlbmRlciA9IHVuZGVmaW5lZDtcblxuICAgIHJlbmRlcmluZy5odG1sLl9yZWZyZXNoID0gcmVmcmVzaE91dE9mUmVuZGVyO1xuICAgIHJlbmRlcmluZy5odG1sLl9jdXJyZW50UmVuZGVyID0gdW5kZWZpbmVkO1xuICB9XG59O1xuIiwiaWYgKHR5cGVvZiBTZXQgPT09ICdmdW5jdGlvbicpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBTZXQ7XG59IGVsc2Uge1xuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaXRlbXMgPSBbXTtcbiAgfTtcblxuICBtb2R1bGUuZXhwb3J0cy5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24od2lkZ2V0KSB7XG4gICAgaWYgKHRoaXMuaXRlbXMuaW5kZXhPZih3aWRnZXQpID09IC0xKSB7XG4gICAgICB0aGlzLml0ZW1zLnB1c2god2lkZ2V0KTtcbiAgICB9XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMucHJvdG90eXBlLmRlbGV0ZSA9IGZ1bmN0aW9uKHdpZGdldCkge1xuICAgIHZhciBpID0gdGhpcy5pdGVtcy5pbmRleE9mKHdpZGdldCk7XG4gICAgaWYgKGkgIT09IC0xKSB7XG4gICAgICB0aGlzLml0ZW1zLnNwbGljZShpLCAxKTtcbiAgICB9XG4gIH07XG5cbiAgbW9kdWxlLmV4cG9ydHMucHJvdG90eXBlLmZvckVhY2ggPSBmdW5jdGlvbihmbikge1xuICAgIGZvcih2YXIgbiA9IDA7IG4gPCB0aGlzLml0ZW1zLmxlbmd0aDsgbisrKSB7XG4gICAgICBmbih0aGlzLml0ZW1zW25dKTtcbiAgICB9XG4gIH07XG59XG4iLCJmdW5jdGlvbiBTaW1wbGVQcm9taXNlICgpIHtcbiAgdGhpcy5saXN0ZW5lcnMgPSBbXTtcbn1cblxuU2ltcGxlUHJvbWlzZS5wcm90b3R5cGUuZnVsZmlsbCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICBpZiAoIXRoaXMuaXNGdWxmaWxsZWQpIHtcbiAgICB0aGlzLmlzRnVsZmlsbGVkID0gdHJ1ZTtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgdGhpcy5saXN0ZW5lcnMuZm9yRWFjaChmdW5jdGlvbiAobGlzdGVuZXIpIHtcbiAgICAgIGxpc3RlbmVyKCk7XG4gICAgfSk7XG4gIH1cbn07XG5cblNpbXBsZVByb21pc2UucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbiAoc3VjY2Vzcykge1xuICBpZiAodGhpcy5pc0Z1bGZpbGxlZCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgIHN1Y2Nlc3Moc2VsZi52YWx1ZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5saXN0ZW5lcnMucHVzaChzdWNjZXNzKTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBuZXcgU2ltcGxlUHJvbWlzZSgpO1xufTtcbiIsInZhciB2dGV4dCA9IHJlcXVpcmUoXCJ2aXJ0dWFsLWRvbS92bm9kZS92dGV4dC5qc1wiKVxudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgaXNWZG9tID0gcmVxdWlyZSgnLi9pc1Zkb20nKTtcblxuZnVuY3Rpb24gdG9WZG9tKG9iamVjdCkge1xuICBpZiAob2JqZWN0ID09PSB1bmRlZmluZWQgfHwgb2JqZWN0ID09PSBudWxsKSB7XG4gICAgcmV0dXJuIG5ldyB2dGV4dCgnJyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mKG9iamVjdCkgIT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KFN0cmluZyhvYmplY3QpKTtcbiAgfSBlbHNlIGlmIChvYmplY3QgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgcmV0dXJuIG5ldyB2dGV4dChTdHJpbmcob2JqZWN0KSk7XG4gIH0gZWxzZSBpZiAob2JqZWN0IGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KG9iamVjdC50b1N0cmluZygpKTtcbiAgfSBlbHNlIGlmIChpc1Zkb20ob2JqZWN0KSkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG9iamVjdC5yZW5kZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gbmV3IHJlbmRlcmluZy5WaWV3TW9kZWwob2JqZWN0KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbmV3IHZ0ZXh0KEpTT04uc3RyaW5naWZ5KG9iamVjdCkpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdG9WZG9tO1xuXG5mdW5jdGlvbiBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGQpIHtcbiAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICBmb3IgKHZhciBuID0gMDsgbiA8IGNoaWxkLmxlbmd0aDsgbisrKSB7XG4gICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGRbbl0pO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBjaGlsZHJlbi5wdXNoKHRvVmRvbShjaGlsZCkpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzLnJlY3Vyc2l2ZSA9IGZ1bmN0aW9uIChjaGlsZCkge1xuICB2YXIgY2hpbGRyZW4gPSBbXTtcbiAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkKTtcbiAgcmV0dXJuIGNoaWxkcmVuO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFZOb2RlID0gcmVxdWlyZSgndmlydHVhbC1kb20vdm5vZGUvdm5vZGUuanMnKTtcbnZhciBpc0hvb2sgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92bm9kZS9pcy12aG9vaycpO1xuXG52YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKCd2aXJ0dWFsLWRvbS92aXJ0dWFsLWh5cGVyc2NyaXB0L2hvb2tzL3NvZnQtc2V0LWhvb2suanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBoO1xuXG5mdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BzLCBjaGlsZHJlbikge1xuICB2YXIgdGFnID0gdGFnTmFtZTtcblxuICAvLyBzdXBwb3J0IGtleXNcbiAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgIHZhciBrZXkgPSBwcm9wcy5rZXk7XG4gICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCduYW1lc3BhY2UnKSkge1xuICAgIHZhciBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLy8gZml4IGN1cnNvciBidWdcbiAgaWYgKHRhZy50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnICYmXG4gICAgIW5hbWVzcGFjZSAmJlxuICAgIHByb3BzLmhhc093blByb3BlcnR5KCd2YWx1ZScpICYmXG4gICAgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJlxuICAgICFpc0hvb2socHJvcHMudmFsdWUpXG4gICkge1xuICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpO1xufVxuIiwidmFyIGRvbUNvbXBvbmVudCA9IHJlcXVpcmUoJy4vZG9tQ29tcG9uZW50Jyk7XG52YXIgaHlwZXJkb21NZXRhID0gcmVxdWlyZSgnLi9tZXRhJyk7XG52YXIgaHlwZXJkb20gPSByZXF1aXJlKCcuJyk7XG5cbmZ1bmN0aW9uIFZpZXdNb2RlbChtb2RlbCkge1xuICB2YXIgY3VycmVudFJlbmRlciA9IGh5cGVyZG9tLmN1cnJlbnRSZW5kZXIoKTtcblxuICB0aGlzLmN1cnJlbnRSZW5kZXIgPSBjdXJyZW50UmVuZGVyO1xuICB0aGlzLm1vZGVsID0gbW9kZWw7XG4gIHRoaXMua2V5ID0gbW9kZWwucmVuZGVyS2V5O1xuICB0aGlzLmNvbXBvbmVudCA9IHVuZGVmaW5lZDtcbiAgdGhpcy5tb3VudCA9IGN1cnJlbnRSZW5kZXIubW91bnQ7XG59XG5cblZpZXdNb2RlbC5wcm90b3R5cGUudHlwZSA9ICdXaWRnZXQnO1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgdmRvbSA9IHRoaXMucmVuZGVyKCk7XG5cbiAgdmFyIG1ldGEgPSBoeXBlcmRvbU1ldGEodGhpcy5tb2RlbCk7XG4gIG1ldGEud2lkZ2V0cy5hZGQodGhpcyk7XG5cbiAgdGhpcy5jb21wb25lbnQgPSBkb21Db21wb25lbnQoKTtcbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC5jcmVhdGUodmRvbSk7XG5cbiAgaWYgKHNlbGYubW9kZWwub25hZGQpIHtcbiAgICB0aGlzLmN1cnJlbnRSZW5kZXIuZmluaXNoZWQudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLm1vZGVsLm9uYWRkKGVsZW1lbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKHNlbGYubW9kZWwuZGV0YWNoZWQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG59O1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChwcmV2aW91cykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKHNlbGYubW9kZWwub251cGRhdGUpIHtcbiAgICB0aGlzLmN1cnJlbnRSZW5kZXIuZmluaXNoZWQudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLm1vZGVsLm9udXBkYXRlKHNlbGYuY29tcG9uZW50LmVsZW1lbnQpO1xuICAgIH0pO1xuICB9XG5cbiAgdGhpcy5jb21wb25lbnQgPSBwcmV2aW91cy5jb21wb25lbnQ7XG5cbiAgdmFyIGVsZW1lbnQgPSB0aGlzLmNvbXBvbmVudC51cGRhdGUodGhpcy5yZW5kZXIoKSk7XG5cbiAgaWYgKHNlbGYubW9kZWwuZGV0YWNoZWQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG59O1xuXG5WaWV3TW9kZWwucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMubW91bnQucmVuZGVyVmlld01vZGVsKHRoaXMubW9kZWwpO1xufTtcblxuVmlld01vZGVsLnByb3RvdHlwZS5yZXJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5jb21wb25lbnQudXBkYXRlKHRoaXMucmVuZGVyKCkpO1xuICBpZiAodGhpcy5tb2RlbC5vbnVwZGF0ZSkge1xuICAgIHRoaXMubW9kZWwub251cGRhdGUodGhpcy5jb21wb25lbnQuZWxlbWVudCk7XG4gIH1cbn07XG5cblZpZXdNb2RlbC5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gIHZhciBzZWxmID0gdGhpcztcblxuICB2YXIgbWV0YSA9IGh5cGVyZG9tTWV0YSh0aGlzLm1vZGVsKTtcbiAgbWV0YS53aWRnZXRzLmRlbGV0ZSh0aGlzKTtcblxuICBpZiAoc2VsZi5tb2RlbC5vbnJlbW92ZSkge1xuICAgIHRoaXMuY3VycmVudFJlbmRlci5maW5pc2hlZC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYubW9kZWwub25yZW1vdmUoZWxlbWVudCk7XG4gICAgfSk7XG4gIH1cblxuICB0aGlzLmNvbXBvbmVudC5kZXN0cm95KCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFZpZXdNb2RlbDtcbiIsInZhciBkb21Db21wb25lbnQgPSByZXF1aXJlKCcuL2RvbUNvbXBvbmVudCcpO1xudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgVlRleHQgPSByZXF1aXJlKFwidmlydHVhbC1kb20vdm5vZGUvdnRleHQuanNcIilcblxuZnVuY3Rpb24gV2luZG93V2lkZ2V0KGF0dHJpYnV0ZXMpIHtcbiAgdGhpcy5hdHRyaWJ1dGVzID0gYXR0cmlidXRlcztcbiAgdGhpcy52ZG9tID0gbmV3IFZUZXh0KCcnKTtcbiAgdGhpcy5jb21wb25lbnQgPSBkb21Db21wb25lbnQoKTtcblxuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHRoaXMuY2FjaGUgPSB7fTtcbiAgT2JqZWN0LmtleXModGhpcy5hdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICBzZWxmLmNhY2hlW2tleV0gPSByZW5kZXJpbmcuaHRtbC5yZWZyZXNoaWZ5KHNlbGYuYXR0cmlidXRlc1trZXldKTtcbiAgfSk7XG59XG5cbldpbmRvd1dpZGdldC5wcm90b3R5cGUudHlwZSA9ICdXaWRnZXQnO1xuXG5XaW5kb3dXaWRnZXQucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIGFwcGx5UHJvcGVydHlEaWZmcyh3aW5kb3csIHt9LCB0aGlzLmF0dHJpYnV0ZXMsIHt9LCB0aGlzLmNhY2hlKTtcbiAgcmV0dXJuIHRoaXMuZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKCcnKTtcbn07XG5cbmZ1bmN0aW9uIHVuaXEoYXJyYXkpIHtcbiAgdmFyIHNvcnRlZEFycmF5ID0gYXJyYXkuc2xpY2UoKTtcbiAgc29ydGVkQXJyYXkuc29ydCgpO1xuXG4gIHZhciBsYXN0O1xuXG4gIGZvcih2YXIgbiA9IDA7IG4gPCBzb3J0ZWRBcnJheS5sZW5ndGg7KSB7XG4gICAgdmFyIGN1cnJlbnQgPSBzb3J0ZWRBcnJheVtuXTtcblxuICAgIGlmIChsYXN0ID09PSBjdXJyZW50KSB7XG4gICAgICBzb3J0ZWRBcnJheS5zcGxpY2UobiwgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG4rKztcbiAgICB9XG4gICAgbGFzdCA9IGN1cnJlbnQ7XG4gIH1cblxuICByZXR1cm4gc29ydGVkQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5UHJvcGVydHlEaWZmcyhlbGVtZW50LCBwcmV2aW91cywgY3VycmVudCwgcHJldmlvdXNDYWNoZSwgY3VycmVudENhY2hlKSB7XG4gIHVuaXEoT2JqZWN0LmtleXMocHJldmlvdXMpLmNvbmNhdChPYmplY3Qua2V5cyhjdXJyZW50KSkpLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgIGlmICgvXm9uLy50ZXN0KGtleSkpIHtcbiAgICAgIHZhciBldmVudCA9IGtleS5zbGljZSgyKTtcblxuICAgICAgdmFyIHByZXYgPSBwcmV2aW91c1trZXldO1xuICAgICAgdmFyIGN1cnIgPSBjdXJyZW50W2tleV07XG4gICAgICB2YXIgcmVmcmVzaFByZXYgPSBwcmV2aW91c0NhY2hlW2tleV07XG4gICAgICB2YXIgcmVmcmVzaEN1cnIgPSBjdXJyZW50Q2FjaGVba2V5XTtcblxuICAgICAgaWYgKHByZXYgIT09IHVuZGVmaW5lZCAmJiBjdXJyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoUHJldik7XG4gICAgICB9IGVsc2UgaWYgKHByZXYgIT09IHVuZGVmaW5lZCAmJiBjdXJyICE9PSB1bmRlZmluZWQgJiYgcHJldiAhPT0gY3Vycikge1xuICAgICAgICBlbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIHJlZnJlc2hQcmV2KTtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoQ3Vycik7XG4gICAgICB9IGVsc2UgaWYgKHByZXYgPT09IHVuZGVmaW5lZCAmJiBjdXJyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCByZWZyZXNoQ3Vycik7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuV2luZG93V2lkZ2V0LnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAocHJldmlvdXMpIHtcbiAgYXBwbHlQcm9wZXJ0eURpZmZzKHdpbmRvdywgcHJldmlvdXMuYXR0cmlidXRlcywgdGhpcy5hdHRyaWJ1dGVzLCBwcmV2aW91cy5jYWNoZSwgdGhpcy5jYWNoZSk7XG4gIHRoaXMuY29tcG9uZW50ID0gcHJldmlvdXMuY29tcG9uZW50O1xuICByZXR1cm4gdGhpcy5lbGVtZW50O1xufTtcblxuV2luZG93V2lkZ2V0LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICBhcHBseVByb3BlcnR5RGlmZnMod2luZG93LCB0aGlzLmF0dHJpYnV0ZXMsIHt9LCB0aGlzLmNhY2hlLCB7fSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhdHRyaWJ1dGVzKSB7XG4gIHJldHVybiBuZXcgV2luZG93V2lkZ2V0KGF0dHJpYnV0ZXMpO1xufTtcbiIsImlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0Jykge1xuICBjb25zb2xlLmxvZygnXFxuXFxuY3JlYXRlZCB3aXRoIFxcdUQ4M0RcXHVERTgwIHVzaW5nIGh0dHBzOi8vZ2l0aHViLmNvbS9mZWF0dXJpc3QvaHlwZXJkb21cXG5cXG5cXG4nKTtcbn1cblxudmFyIHJlbmRlcmluZyA9IHJlcXVpcmUoJy4vcmVuZGVyaW5nJyk7XG52YXIgZGVwcmVjYXRpb25zID0gcmVxdWlyZSgnLi9kZXByZWNhdGlvbnMnKTtcblxuZXhwb3J0cy5odG1sID0gcmVuZGVyaW5nLmh0bWw7XG5leHBvcnRzLmpzeCA9IHJlbmRlcmluZy5qc3g7XG5leHBvcnRzLmF0dGFjaCA9IHJlbmRlcmluZy5hdHRhY2g7XG5leHBvcnRzLnJlcGxhY2UgPSByZW5kZXJpbmcucmVwbGFjZTtcbmV4cG9ydHMuYXBwZW5kID0gcmVuZGVyaW5nLmFwcGVuZDtcbmV4cG9ydHMuYXBwZW5kVkRvbSA9IHJlbmRlcmluZy5hcHBlbmRWRG9tO1xuZXhwb3J0cy5tZXJnZSA9IHJlbmRlcmluZy5tZXJnZTtcbmV4cG9ydHMuYmluZGluZyA9IHJlbmRlcmluZy5iaW5kaW5nO1xuZXhwb3J0cy5tZXRhID0gcmVuZGVyaW5nLmh0bWwubWV0YTtcbmV4cG9ydHMucmVmcmVzaGlmeSA9IHJlbmRlcmluZy5odG1sLnJlZnJlc2hpZnk7XG5leHBvcnRzLm5vcmVmcmVzaCA9IHJlbmRlcmluZy5odG1sLm5vcmVmcmVzaDtcblxudmFyIHdpbmRvd0V2ZW50cyA9IHJlcXVpcmUoJy4vd2luZG93RXZlbnRzJyk7XG5cbmV4cG9ydHMuaHRtbC53aW5kb3cgPSBmdW5jdGlvbiAoYXR0cmlidXRlcykge1xuICBkZXByZWNhdGlvbnMud2luZG93KCdoeXBlcmRvbS53aW5kb3cgaXMgZGVwcmVjYXRlZCcpO1xuICByZXR1cm4gd2luZG93RXZlbnRzKGF0dHJpYnV0ZXMpO1xufTtcblxuZXhwb3J0cy5odG1sLmNvbXBvbmVudCA9IHJlcXVpcmUoJy4vY29tcG9uZW50Jyk7XG5cbmV4cG9ydHMuY3VycmVudFJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGV4cG9ydHMuX2N1cnJlbnRSZW5kZXI7XG59O1xuIl19
var hyperdom = require('hyperdom')
var h = hyperdom.html
class App {
render() {
return h('.container',
h('#example',
h('div.foo div', h('input[type=submit]'))
),
h.component({
onadd: function(pre) {
pre.innerText = document.querySelector('#example').innerHTML
}
}, h('pre'))
)
}
}
hyperdom.append(document.body, new App())
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"hyperdom": "0.2.0"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment