ngx-teximate
Version:
Angular text animations component
515 lines (503 loc) • 56.7 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/animations'), require('rxjs'), require('rxjs/operators'), require('@angular/common')) :
typeof define === 'function' && define.amd ? define('ngx-teximate', ['exports', '@angular/core', '@angular/animations', 'rxjs', 'rxjs/operators', '@angular/common'], factory) :
(factory((global['ngx-teximate'] = {}),global.ng.core,global.ng.animations,global.rxjs,global.rxjs.operators,global.ng.common));
}(this, (function (exports,core,animations,rxjs,operators,common) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b)
if (b.hasOwnProperty(p))
d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function () {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s)
if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m)
return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
ar.push(r.value);
}
catch (error) {
e = { error: error };
}
finally {
try {
if (r && !r.done && (m = i["return"]))
m.call(i);
}
finally {
if (e)
throw e.error;
}
}
return ar;
}
function __spread() {
for (var ar = [], i = 0; i < arguments.length; i++)
ar = ar.concat(__read(arguments[i]));
return ar;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var Teximate = /** @class */ (function () {
function Teximate(animationBuilder, zone, el) {
this.animationBuilder = animationBuilder;
this.zone = zone;
this.el = el;
/**
* Stream that emits when animation is started
*/
this.playEmitter = new core.EventEmitter();
/**
* Stream that emits when animation is done
*/
this.finishEmitter = new core.EventEmitter();
/**
* Teximate animations
*/
this.players = new Map();
/**
* Teximate state
*/
this._state = new rxjs.BehaviorSubject('');
this.state = this._state.pipe(operators.map(function (text) { return teximateFactory(text); }));
}
Object.defineProperty(Teximate.prototype, "setText", {
/** Set animated text */
set: /**
* Set animated text
* @param {?} text
* @return {?}
*/ function (text) {
this._state.next(text);
},
enumerable: true,
configurable: true
});
Object.defineProperty(Teximate.prototype, "isPlaying", {
get: /**
* @return {?}
*/ function () {
return this._isPlaying;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Teximate.prototype, "enterPlayer", {
get: /**
* @return {?}
*/ function () {
return this.players.get('enter');
},
enumerable: true,
configurable: true
});
Object.defineProperty(Teximate.prototype, "leavePlayer", {
get: /**
* @return {?}
*/ function () {
return this.players.get('leave');
},
enumerable: true,
configurable: true
});
Object.defineProperty(Teximate.prototype, "defaultPlayer", {
get: /**
* @return {?}
*/ function () {
return this.players.get('default');
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
Teximate.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
this._isViewInit = true;
this.updateAnimations(true);
};
/**
* @return {?}
*/
Teximate.prototype.ngOnChanges = /**
* @return {?}
*/
function () {
if (this._isViewInit) {
this.updateAnimations();
}
};
/**
* @return {?}
*/
Teximate.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
// TODO: Use players.forEach to destroy players
if (this.players.has('enter')) {
this.players.get('enter').destroy();
}
if (this.players.has('leave')) {
this.players.get('leave').destroy();
}
if (this.players.has('default')) {
this.players.get('default').destroy();
}
};
/**
* Register a new animation
*/
/**
* Register a new animation
* @param {?} config
* @return {?}
*/
Teximate.prototype.registerAnimation = /**
* Register a new animation
* @param {?} config
* @return {?}
*/
function (config) {
var _this = this;
/** @type {?} */
var player = this.buildAnimation(config).create(this.el.nativeElement);
/** TODO: Investigate why onStart and onDone fire only once */
player.onStart(function () {
_this._isPlaying = true;
_this.playEmitter.emit(config.id);
});
player.onDone(function () {
_this._isPlaying = false;
_this.finishEmitter.emit(config.id);
});
return this.players.set(config.id, player).get(config.id);
};
/**
* @param {?=} autoPlayEnter
* @return {?}
*/
Teximate.prototype.updateAnimations = /**
* @param {?=} autoPlayEnter
* @return {?}
*/
function (autoPlayEnter) {
var _this = this;
this.zone.runOutsideAngular(function () {
if (_this.enter) {
/** @type {?} */
var enterPlayer = _this.registerAnimation(__assign({}, _this.enter, { id: 'enter', isEnter: true }));
if (autoPlayEnter) {
enterPlayer.play();
}
}
if (_this.leave) {
_this.registerAnimation(__assign({}, _this.leave, { id: 'leave' }));
}
if (_this.animation) {
_this.registerAnimation(__assign({ id: 'default' }, _this.animation));
}
});
};
/**
* Build animation
*/
/**
* Build animation
* @param {?} config
* @return {?}
*/
Teximate.prototype.buildAnimation = /**
* Build animation
* @param {?} config
* @return {?}
*/
function (config) {
/** TODO: Use ':enter' and ':leave' for enter and leave animations */
return this.animationBuilder.build([
animations.query(".teximate-" + config.type, [
// This is a workaround for enter animation to work
animations.style({ opacity: config.isEnter ? 0 : 1 }),
animations.stagger(config.delay, [animations.useAnimation(config.animation)])
])
]);
};
Teximate.decorators = [
{ type: core.Component, args: [{
selector: 'teximate',
host: {
'aria-label': 'text'
},
template: "<p *ngFor=\"let paragraph of state | async; index as i\"\r\n class=\"teximate-paragraph teximate-paragraph-{{i}}\">\r\n\r\n <span *ngFor=\"let word of paragraph; index as j\"\r\n class=\"teximate-word teximate-word-{{j}}\">\r\n\r\n <span *ngFor=\"let letter of word; index as k\"\r\n class=\"teximate-letter teximate-letter-{{k}}\">\r\n {{letter}}\r\n </span>\r\n </span>\r\n</p>\r\n",
changeDetection: core.ChangeDetectionStrategy.OnPush,
styles: [".teximate-letter,.teximate-word{display:inline-block}.teximate-word{margin-right:8px}"]
}] }
];
/** @nocollapse */
Teximate.ctorParameters = function () {
return [
{ type: animations.AnimationBuilder },
{ type: core.NgZone },
{ type: core.ElementRef }
];
};
Teximate.propDecorators = {
setText: [{ type: core.Input, args: ['text',] }],
enter: [{ type: core.Input }],
leave: [{ type: core.Input }],
animation: [{ type: core.Input }],
playEmitter: [{ type: core.Output, args: ['play',] }],
finishEmitter: [{ type: core.Output, args: ['finish',] }]
};
return Teximate;
}());
/**
* Convert text string into a workable text
* @param {?} text
* @return {?}
*/
function teximateFactory(text) {
/** @type {?} */
var paragraphs = [];
// Split text into paragraphs
text.split('\n').map(function (paragraph) {
/** @type {?} */
var words = [];
// Split paragraph into words
paragraph
.split(' ')
.filter(function (word) { return word !== ''; })
.map(function (word) {
// Split word into letters
return words.push(word.split(/(?!$)/u));
});
paragraphs.push(words);
});
return paragraphs;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var TeximateEvents = /** @class */ (function () {
function TeximateEvents(element, teximate) {
this.element = element;
this.teximate = teximate;
this.events = rxjs.Subscription.EMPTY;
this.click = new core.EventEmitter();
this.hover = new core.EventEmitter();
}
/**
* @return {?}
*/
TeximateEvents.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
var _this = this;
this.events = this.teximate.state.pipe(operators.filter(function () { return !!_this.click.observers.length || !!_this.hover.observers.length; }), operators.switchMap(function () {
/** @type {?} */
var clickEvents = rxjs.of(null);
/** @type {?} */
var hoverEvents = rxjs.of(null);
/** @type {?} */
var words = _this.element.nativeElement.querySelectorAll(_this.selector);
if (_this.click.observers.length) {
/** @type {?} */
var events = Array.from(words).map(function (el) { return rxjs.fromEvent(el, 'click'); });
clickEvents = rxjs.merge.apply(void 0, __spread(events)).pipe(operators.tap(function (e) { return _this.click.emit(e); }));
}
if (_this.hover.observers.length) {
/** @type {?} */
var events = Array.from(words).map(function (el) { return rxjs.fromEvent(el, 'mouseenter'); });
hoverEvents = rxjs.merge.apply(void 0, __spread(events)).pipe(operators.tap(function (e) { return _this.hover.emit(e); }));
}
return rxjs.merge(clickEvents, hoverEvents);
})).subscribe();
};
/**
* @return {?}
*/
TeximateEvents.prototype.ngOnDestroy = /**
* @return {?}
*/
function () {
this.events.unsubscribe();
};
/** @nocollapse */
TeximateEvents.ctorParameters = function () {
return [
{ type: core.ElementRef },
{ type: Teximate, decorators: [{ type: core.Inject, args: [core.forwardRef(function () { return Teximate; }),] }] }
];
};
TeximateEvents.propDecorators = {
click: [{ type: core.Output, args: ['',] }],
hover: [{ type: core.Output, args: ['',] }]
};
return TeximateEvents;
}());
var ParagraphEvents = /** @class */ (function (_super) {
__extends(ParagraphEvents, _super);
function ParagraphEvents(element, teximate) {
var _this = _super.call(this, element, teximate) || this;
_this.click = new core.EventEmitter();
_this.hover = new core.EventEmitter();
_this.selector = '.teximate-paragraph';
return _this;
}
ParagraphEvents.decorators = [
{ type: core.Directive, args: [{
selector: 'teximate[paragraphClick], teximate[paragraphHover]'
},] }
];
/** @nocollapse */
ParagraphEvents.ctorParameters = function () {
return [
{ type: core.ElementRef },
{ type: Teximate, decorators: [{ type: core.Inject, args: [core.forwardRef(function () { return Teximate; }),] }] }
];
};
ParagraphEvents.propDecorators = {
click: [{ type: core.Output, args: ['paragraphClick',] }],
hover: [{ type: core.Output, args: ['paragraphHover',] }]
};
return ParagraphEvents;
}(TeximateEvents));
var WordEvents = /** @class */ (function (_super) {
__extends(WordEvents, _super);
function WordEvents(element, teximate) {
var _this = _super.call(this, element, teximate) || this;
_this.click = new core.EventEmitter();
_this.hover = new core.EventEmitter();
_this.selector = '.teximate-word';
return _this;
}
WordEvents.decorators = [
{ type: core.Directive, args: [{
selector: 'teximate[wordClick], teximate[wordHover]'
},] }
];
/** @nocollapse */
WordEvents.ctorParameters = function () {
return [
{ type: core.ElementRef },
{ type: Teximate, decorators: [{ type: core.Inject, args: [core.forwardRef(function () { return Teximate; }),] }] }
];
};
WordEvents.propDecorators = {
click: [{ type: core.Output, args: ['wordClick',] }],
hover: [{ type: core.Output, args: ['wordHover',] }]
};
return WordEvents;
}(TeximateEvents));
var LetterEvents = /** @class */ (function (_super) {
__extends(LetterEvents, _super);
function LetterEvents(element, teximate) {
var _this = _super.call(this, element, teximate) || this;
_this.click = new core.EventEmitter();
_this.hover = new core.EventEmitter();
_this.selector = '.teximate-letter';
return _this;
}
LetterEvents.decorators = [
{ type: core.Directive, args: [{
selector: 'teximate[letterClick], teximate[letterHover]'
},] }
];
/** @nocollapse */
LetterEvents.ctorParameters = function () {
return [
{ type: core.ElementRef },
{ type: Teximate, decorators: [{ type: core.Inject, args: [core.forwardRef(function () { return Teximate; }),] }] }
];
};
LetterEvents.propDecorators = {
click: [{ type: core.Output, args: ['letterClick',] }],
hover: [{ type: core.Output, args: ['letterHover',] }]
};
return LetterEvents;
}(TeximateEvents));
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
var TeximateModule = /** @class */ (function () {
function TeximateModule() {
}
TeximateModule.decorators = [
{ type: core.NgModule, args: [{
imports: [common.CommonModule],
declarations: [
Teximate,
ParagraphEvents,
WordEvents,
LetterEvents
],
exports: [
Teximate,
ParagraphEvents,
WordEvents,
LetterEvents
]
},] }
];
return TeximateModule;
}());
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
exports.teximateFactory = teximateFactory;
exports.Teximate = Teximate;
exports.TeximateModule = TeximateModule;
exports.ɵd = LetterEvents;
exports.ɵb = ParagraphEvents;
exports.ɵa = TeximateEvents;
exports.ɵc = WordEvents;
Object.defineProperty(exports, '__esModule', { value: true });
})));
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRleGltYXRlLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCJuZzovL25neC10ZXhpbWF0ZS9saWIvdGV4aW1hdGUudHMiLCJuZzovL25neC10ZXhpbWF0ZS9saWIvdGV4aW1hdGUtZXZlbnRzLnRzIiwibmc6Ly9uZ3gtdGV4aW1hdGUvbGliL3RleGltYXRlLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcbkxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7IHlvdSBtYXkgbm90IHVzZVxyXG50aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZVxyXG5MaWNlbnNlIGF0IGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxyXG5cclxuVEhJUyBDT0RFIElTIFBST1ZJREVEIE9OIEFOICpBUyBJUyogQkFTSVMsIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWVxyXG5LSU5ELCBFSVRIRVIgRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OIEFOWSBJTVBMSUVEXHJcbldBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBUSVRMRSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UsXHJcbk1FUkNIQU5UQUJMSVRZIE9SIE5PTi1JTkZSSU5HRU1FTlQuXHJcblxyXG5TZWUgdGhlIEFwYWNoZSBWZXJzaW9uIDIuMCBMaWNlbnNlIGZvciBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcclxuYW5kIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqL1xyXG4vKiBnbG9iYWwgUmVmbGVjdCwgUHJvbWlzZSAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKGIuaGFzT3duUHJvcGVydHkocCkpIGRbcF0gPSBiW3BdOyB9O1xyXG4gICAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcclxuICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XHJcbiAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cclxuICAgIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcclxufVxyXG5cclxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gX19hc3NpZ24uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDApXHJcbiAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUocmVzdWx0LnZhbHVlKTsgfSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgZXhwb3J0cykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAoIWV4cG9ydHMuaGFzT3duUHJvcGVydHkocCkpIGV4cG9ydHNbcF0gPSBtW3BdO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIGlmIChvICYmIGkgPj0gby5sZW5ndGgpIG8gPSB2b2lkIDA7XHJcbiAgICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXTtcclxuICAgIGlmICghbSkgcmV0dXJuIG87XHJcbiAgICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgd2hpbGUgKChuID09PSB2b2lkIDAgfHwgbi0tID4gMCkgJiYgIShyID0gaS5uZXh0KCkpLmRvbmUpIGFyLnB1c2goci52YWx1ZSk7XHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZXJyb3IpIHsgZSA9IHsgZXJyb3I6IGVycm9yIH07IH1cclxuICAgIGZpbmFsbHkge1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGlmIChyICYmICFyLmRvbmUgJiYgKG0gPSBpW1wicmV0dXJuXCJdKSkgbS5jYWxsKGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cclxuICAgIH1cclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyBpZiAoZ1tuXSkgaVtuXSA9IGZ1bmN0aW9uICh2KSB7IHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAoYSwgYikgeyBxLnB1c2goW24sIHYsIGEsIGJdKSA+IDEgfHwgcmVzdW1lKG4sIHYpOyB9KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gcmVzdW1lKG4sIHYpIHsgdHJ5IHsgc3RlcChnW25dKHYpKTsgfSBjYXRjaCAoZSkgeyBzZXR0bGUocVswXVszXSwgZSk7IH0gfVxyXG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XHJcbiAgICBmdW5jdGlvbiBmdWxmaWxsKHZhbHVlKSB7IHJlc3VtZShcIm5leHRcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiByZWplY3QodmFsdWUpIHsgcmVzdW1lKFwidGhyb3dcIiwgdmFsdWUpOyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcclxuICAgIHZhciBpLCBwO1xyXG4gICAgcmV0dXJuIGkgPSB7fSwgdmVyYihcIm5leHRcIiksIHZlcmIoXCJ0aHJvd1wiLCBmdW5jdGlvbiAoZSkgeyB0aHJvdyBlOyB9KSwgdmVyYihcInJldHVyblwiKSwgaVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcclxuICAgIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IG4gPT09IFwicmV0dXJuXCIgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xyXG4gICAgaWYgKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgcmV0dXJuIG1vZDtcclxuICAgIHZhciByZXN1bHQgPSB7fTtcclxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChtb2QsIGspKSByZXN1bHRba10gPSBtb2Rba107XHJcbiAgICByZXN1bHQuZGVmYXVsdCA9IG1vZDtcclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydERlZmF1bHQobW9kKSB7XHJcbiAgICByZXR1cm4gKG1vZCAmJiBtb2QuX19lc01vZHVsZSkgPyBtb2QgOiB7IGRlZmF1bHQ6IG1vZCB9O1xyXG59XHJcbiIsImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE5nWm9uZSxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIHN0eWxlLFxuICBxdWVyeSxcbiAgc3RhZ2dlcixcbiAgdXNlQW5pbWF0aW9uLFxuICBBbmltYXRpb25QbGF5ZXIsXG4gIEFuaW1hdGlvbkJ1aWxkZXIsXG4gIEFuaW1hdGlvbkZhY3Rvcnlcbn0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRleHRBbmltYXRpb24gfSBmcm9tICcuL3RleGltYXRlLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGV4aW1hdGUnLFxuICBob3N0OiB7XG4gICAgJ2FyaWEtbGFiZWwnOiAndGV4dCdcbiAgfSxcbiAgdGVtcGxhdGVVcmw6ICcuL3RleGltYXRlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90ZXhpbWF0ZS5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIFRleGltYXRlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuXG4gIC8qKiBTZXQgYW5pbWF0ZWQgdGV4dCAqL1xuICBASW5wdXQoJ3RleHQnKSBzZXQgc2V0VGV4dCh0ZXh0OiBzdHJpbmcpIHtcbiAgICB0aGlzLl9zdGF0ZS5uZXh0KHRleHQpO1xuICB9XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIG9uIGluaXQgKi9cbiAgQElucHV0KCkgZW50ZXI6IFRleHRBbmltYXRpb247XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIG9uIGRlc3Ryb3kgKi9cbiAgQElucHV0KCkgbGVhdmU6IFRleHRBbmltYXRpb247XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIHdpdGggdGhlIHBsYXkoKSBmdW5jdGlvbiAqL1xuICBASW5wdXQoKSBhbmltYXRpb246IFRleHRBbmltYXRpb247XG5cbiAgLyoqIFN0cmVhbSB0aGF0IGVtaXRzIHdoZW4gYW5pbWF0aW9uIGlzIHN0YXJ0ZWQgKi9cbiAgQE91dHB1dCgncGxheScpIHBsYXlFbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIC8qKiBTdHJlYW0gdGhhdCBlbWl0cyB3aGVuIGFuaW1hdGlvbiBpcyBkb25lICovXG4gIEBPdXRwdXQoJ2ZpbmlzaCcpIGZpbmlzaEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgLyoqIFRleGltYXRlIGFuaW1hdGlvbnMgKi9cbiAgcGxheWVycyA9IG5ldyBNYXA8c3RyaW5nLCBBbmltYXRpb25QbGF5ZXI+KCk7XG5cbiAgLyoqIFRleGltYXRlIHN0YXRlICovXG4gIHByaXZhdGUgX3N0YXRlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgc3RhdGU6IE9ic2VydmFibGU8c3RyaW5nW11bXVtdPjtcblxuICAvKiogVGV4aW1hdGUgcGxheWluZyBzdGF0ZSAqL1xuICBwcml2YXRlIF9pc1BsYXlpbmc6IGJvb2xlYW47XG4gIHByaXZhdGUgX2lzVmlld0luaXQ6IGJvb2xlYW47XG5cbiAgZ2V0IGlzUGxheWluZygpIHtcbiAgICByZXR1cm4gdGhpcy5faXNQbGF5aW5nO1xuICB9XG5cbiAgZ2V0IGVudGVyUGxheWVyKCk6IEFuaW1hdGlvblBsYXllciB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5nZXQoJ2VudGVyJyk7XG4gIH1cblxuICBnZXQgbGVhdmVQbGF5ZXIoKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXJzLmdldCgnbGVhdmUnKTtcbiAgfVxuXG4gIGdldCBkZWZhdWx0UGxheWVyKCk6IEFuaW1hdGlvblBsYXllciB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5nZXQoJ2RlZmF1bHQnKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYW5pbWF0aW9uQnVpbGRlcjogQW5pbWF0aW9uQnVpbGRlciwgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYpIHtcbiAgICB0aGlzLnN0YXRlID0gdGhpcy5fc3RhdGUucGlwZShtYXAoKHRleHQ6IHN0cmluZykgPT4gdGV4aW1hdGVGYWN0b3J5KHRleHQpKSk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5faXNWaWV3SW5pdCA9IHRydWU7XG4gICAgdGhpcy51cGRhdGVBbmltYXRpb25zKHRydWUpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoKSB7XG4gICAgaWYgKHRoaXMuX2lzVmlld0luaXQpIHtcbiAgICAgIHRoaXMudXBkYXRlQW5pbWF0aW9ucygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIC8vIFRPRE86IFVzZSBwbGF5ZXJzLmZvckVhY2ggdG8gZGVzdHJveSBwbGF5ZXJzXG4gICAgaWYgKHRoaXMucGxheWVycy5oYXMoJ2VudGVyJykpIHtcbiAgICAgIHRoaXMucGxheWVycy5nZXQoJ2VudGVyJykuZGVzdHJveSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5wbGF5ZXJzLmhhcygnbGVhdmUnKSkge1xuICAgICAgdGhpcy5wbGF5ZXJzLmdldCgnbGVhdmUnKS5kZXN0cm95KCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBsYXllcnMuaGFzKCdkZWZhdWx0JykpIHtcbiAgICAgIHRoaXMucGxheWVycy5nZXQoJ2RlZmF1bHQnKS5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgbmV3IGFuaW1hdGlvblxuICAgKi9cbiAgcmVnaXN0ZXJBbmltYXRpb24oY29uZmlnOiBUZXh0QW5pbWF0aW9uKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICBjb25zdCBwbGF5ZXIgPSB0aGlzLmJ1aWxkQW5pbWF0aW9uKGNvbmZpZykuY3JlYXRlKHRoaXMuZWwubmF0aXZlRWxlbWVudCk7XG4gICAgLyoqIFRPRE86IEludmVzdGlnYXRlIHdoeSBvblN0YXJ0IGFuZCBvbkRvbmUgZmlyZSBvbmx5IG9uY2UgKi9cbiAgICBwbGF5ZXIub25TdGFydCgoKSA9PiB7XG4gICAgICB0aGlzLl9pc1BsYXlpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5wbGF5RW1pdHRlci5lbWl0KGNvbmZpZy5pZCk7XG4gICAgfSk7XG4gICAgcGxheWVyLm9uRG9uZSgoKSA9PiB7XG4gICAgICB0aGlzLl9pc1BsYXlpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuZmluaXNoRW1pdHRlci5lbWl0KGNvbmZpZy5pZCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5zZXQoY29uZmlnLmlkLCBwbGF5ZXIpLmdldChjb25maWcuaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVBbmltYXRpb25zKGF1dG9QbGF5RW50ZXI/OiBib29sZWFuKSB7XG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmVudGVyKSB7XG4gICAgICAgIGNvbnN0IGVudGVyUGxheWVyID0gdGhpcy5yZWdpc3RlckFuaW1hdGlvbih7Li4udGhpcy5lbnRlciwgaWQ6ICdlbnRlcicsIGlzRW50ZXI6IHRydWV9KTtcbiAgICAgICAgaWYgKGF1dG9QbGF5RW50ZXIpIHtcbiAgICAgICAgICBlbnRlclBsYXllci5wbGF5KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmxlYXZlKSB7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJBbmltYXRpb24oey4uLnRoaXMubGVhdmUsIGlkOiAnbGVhdmUnfSk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5hbmltYXRpb24pIHtcbiAgICAgICAgdGhpcy5yZWdpc3RlckFuaW1hdGlvbih7aWQ6ICdkZWZhdWx0JywgLi4udGhpcy5hbmltYXRpb259KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhbmltYXRpb25cbiAgICovXG4gIHByaXZhdGUgYnVpbGRBbmltYXRpb24oY29uZmlnOiBUZXh0QW5pbWF0aW9uKTogQW5pbWF0aW9uRmFjdG9yeSB7XG4gICAgLyoqIFRPRE86IFVzZSAnOmVudGVyJyBhbmQgJzpsZWF2ZScgZm9yIGVudGVyIGFuZCBsZWF2ZSBhbmltYXRpb25zICovXG4gICAgcmV0dXJuIHRoaXMuYW5pbWF0aW9uQnVpbGRlci5idWlsZChbXG4gICAgICBxdWVyeShcbiAgICAgICAgYC50ZXhpbWF0ZS0ke2NvbmZpZy50eXBlfWAsXG4gICAgICAgIFtcbiAgICAgICAgICAvLyBUaGlzIGlzIGEgd29ya2Fyb3VuZCBmb3IgZW50ZXIgYW5pbWF0aW9uIHRvIHdvcmtcbiAgICAgICAgICBzdHlsZSh7b3BhY2l0eTogY29uZmlnLmlzRW50ZXIgPyAwIDogMX0pLFxuICAgICAgICAgIHN0YWdnZXIoY29uZmlnLmRlbGF5LCBbdXNlQW5pbWF0aW9uKGNvbmZpZy5hbmltYXRpb24pXSlcbiAgICAgICAgXVxuICAgICAgKVxuICAgIF0pO1xuICB9XG59XG5cbi8qKiBDb252ZXJ0IHRleHQgc3RyaW5nIGludG8gYSB3b3JrYWJsZSB0ZXh0ICovXG5leHBvcnQgZnVuY3Rpb24gdGV4aW1hdGVGYWN0b3J5KHRleHQ6IHN0cmluZyk6IHN0cmluZ1tdW11bXSB7XG4gIGNvbnN0IHBhcmFncmFwaHM6IHN0cmluZ1tdW11bXSA9IFtdO1xuICAvLyBTcGxpdCB0ZXh0IGludG8gcGFyYWdyYXBoc1xuICB0ZXh0LnNwbGl0KCdcXG4nKS5tYXAoKHBhcmFncmFwaDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3Qgd29yZHM6IHN0cmluZ1tdW10gPSBbXTtcbiAgICAvLyBTcGxpdCBwYXJhZ3JhcGggaW50byB3b3Jkc1xuICAgIHBhcmFncmFwaFxuICAgICAgLnNwbGl0KCcgJylcbiAgICAgIC5maWx0ZXIod29yZCA9PiB3b3JkICE9PSAnJylcbiAgICAgIC5tYXAoKHdvcmQ6IHN0cmluZykgPT5cbiAgICAgICAgLy8gU3BsaXQgd29yZCBpbnRvIGxldHRlcnNcbiAgICAgICAgd29yZHMucHVzaCh3b3JkLnNwbGl0KC8oPyEkKS91KSlcbiAgICAgICk7XG4gICAgcGFyYWdyYXBocy5wdXNoKHdvcmRzKTtcbiAgfSk7XG4gIHJldHVybiBwYXJhZ3JhcGhzO1xufVxuIiwiaW1wb3J0IHsgRGlyZWN0aXZlLCBPdXRwdXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSwgSW5qZWN0LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiwgZnJvbUV2ZW50LCBtZXJnZSwgU3Vic2NyaXB0aW9uTGlrZSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGZpbHRlciwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBUZXhpbWF0ZSB9IGZyb20gJy4vdGV4aW1hdGUnO1xuXG5leHBvcnQgY2xhc3MgVGV4aW1hdGVFdmVudHMgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuXG4gIHNlbGVjdG9yOiBzdHJpbmc7XG4gIGV2ZW50czogU3Vic2NyaXB0aW9uTGlrZSA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcbiAgQE91dHB1dCgnJykgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoJycpIGhvdmVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBlbGVtZW50OiBFbGVtZW50UmVmLCBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gVGV4aW1hdGUpKSBwdWJsaWMgdGV4aW1hdGU6IFRleGltYXRlKSB7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5ldmVudHMgPSB0aGlzLnRleGltYXRlLnN0YXRlLnBpcGUoXG4gICAgICBmaWx0ZXIoKCkgPT4gISF0aGlzLmNsaWNrLm9ic2VydmVycy5sZW5ndGggfHwgISF0aGlzLmhvdmVyLm9ic2VydmVycy5sZW5ndGgpLFxuICAgICAgc3dpdGNoTWFwKCgpID0+IHtcbiAgICAgICAgbGV0IGNsaWNrRXZlbnRzID0gb2YobnVsbCk7XG4gICAgICAgIGxldCBob3ZlckV2ZW50cyA9IG9mKG51bGwpO1xuICAgICAgICBjb25zdCB3b3JkcyA9IHRoaXMuZWxlbWVudC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5zZWxlY3Rvcik7XG4gICAgICAgIGlmICh0aGlzLmNsaWNrLm9ic2VydmVycy5sZW5ndGgpIHtcbiAgICAgICAgICBjb25zdCBldmVudHMgPSBBcnJheS5mcm9tKHdvcmRzKS5tYXAoKGVsOiBIVE1MRWxlbWVudCkgPT4gZnJvbUV2ZW50KGVsLCAnY2xpY2snKSk7XG4gICAgICAgICAgY2xpY2tFdmVudHMgPSBtZXJnZSguLi5ldmVudHMpLnBpcGUodGFwKGUgPT4gdGhpcy5jbGljay5lbWl0KGUpKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuaG92ZXIub2JzZXJ2ZXJzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IEFycmF5LmZyb20od29yZHMpLm1hcCgoZWw6IEhUTUxFbGVtZW50KSA9PiBmcm9tRXZlbnQoZWwsICdtb3VzZWVudGVyJykpO1xuICAgICAgICAgIGhvdmVyRXZlbnRzID0gbWVyZ2UoLi4uZXZlbnRzKS5waXBlKHRhcChlID0+IHRoaXMuaG92ZXIuZW1pdChlKSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtZXJnZShjbGlja0V2ZW50cywgaG92ZXJFdmVudHMpO1xuICAgICAgfSlcbiAgICApLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5ldmVudHMudW5zdWJzY3JpYmUoKTtcbiAgfVxuXG59XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ3RleGltYXRlW3BhcmFncmFwaENsaWNrXSwgdGV4aW1hdGVbcGFyYWdyYXBoSG92ZXJdJ1xufSlcbmV4cG9ydCBjbGFzcyBQYXJhZ3JhcGhFdmVudHMgZXh0ZW5kcyBUZXhpbWF0ZUV2ZW50cyB7XG4gIEBPdXRwdXQoJ3BhcmFncmFwaENsaWNrJykgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoJ3BhcmFncmFwaEhvdmVyJykgaG92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudDogRWxlbWVudFJlZiwgQEluamVjdChmb3J3YXJkUmVmKCgpID0+IFRleGltYXRlKSkgdGV4aW1hdGU6IFRleGltYXRlKSB7XG4gICAgc3VwZXIoZWxlbWVudCwgdGV4aW1hdGUpO1xuICAgIHRoaXMuc2VsZWN0b3IgPSAnLnRleGltYXRlLXBhcmFncmFwaCc7XG4gIH1cbn1cblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAndGV4aW1hdGVbd29yZENsaWNrXSwgdGV4aW1hdGVbd29yZEhvdmVyXSdcbn0pXG5leHBvcnQgY2xhc3MgV29yZEV2ZW50cyBleHRlbmRzIFRleGltYXRlRXZlbnRzIHtcbiAgQE91dHB1dCgnd29yZENsaWNrJykgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoJ3dvcmRIb3ZlcicpIGhvdmVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEVsZW1lbnRSZWYsIEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBUZXhpbWF0ZSkpIHRleGltYXRlOiBUZXhpbWF0ZSkge1xuICAgIHN1cGVyKGVsZW1lbnQsIHRleGltYXRlKTtcbiAgICB0aGlzLnNlbGVjdG9yID0gJy50ZXhpbWF0ZS13b3JkJztcbiAgfVxufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICd0ZXhpbWF0ZVtsZXR0ZXJDbGlja10sIHRleGltYXRlW2xldHRlckhvdmVyXSdcbn0pXG5leHBvcnQgY2xhc3MgTGV0dGVyRXZlbnRzIGV4dGVuZHMgVGV4aW1hdGVFdmVudHMge1xuICBAT3V0cHV0KCdsZXR0ZXJDbGljaycpIGNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCdsZXR0ZXJIb3ZlcicpIGhvdmVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGNvbnN0cnVjdG9yKGVsZW1lbnQ6IEVsZW1lbnRSZWYsIEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBUZXhpbWF0ZSkpIHRleGltYXRlOiBUZXhpbWF0ZSkge1xuICAgIHN1cGVyKGVsZW1lbnQsIHRleGltYXRlKTtcbiAgICB0aGlzLnNlbGVjdG9yID0gJy50ZXhpbWF0ZS1sZXR0ZXInO1xuICB9XG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFRleGltYXRlIH0gZnJvbSAnLi90ZXhpbWF0ZSc7XG5pbXBvcnQgeyBQYXJhZ3JhcGhFdmVudHMsIFdvcmRFdmVudHMsIExldHRlckV2ZW50cyB9IGZyb20gJy4vdGV4aW1hdGUtZXZlbnRzJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGRlY2xhcmF0aW9uczogW1xuICAgIFRleGltYXRlLFxuICAgIFBhcmFncmFwaEV2ZW50cyxcbiAgICBXb3JkRXZlbnRzLFxuICAgIExldHRlckV2ZW50c1xuICBdLFxuICBleHBvcnRzOiBbXG4gICAgVGV4aW1hdGUsXG4gICAgUGFyYWdyYXBoRXZlbnRzLFxuICAgIFdvcmRFdmVudHMsXG4gICAgTGV0dGVyRXZlbnRzXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgVGV4aW1hdGVNb2R1bGUge1xufVxuIl0sIm5hbWVzIjpbIkV2ZW50RW1pdHRlciIsIkJlaGF2aW9yU3ViamVjdCIsIm1hcCIsInF1ZXJ5Iiwic3R5bGUiLCJzdGFnZ2VyIiwidXNlQW5pbWF0aW9uIiwiQ29tcG9uZW50IiwiQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kiLCJBbmltYXRpb25CdWlsZGVyIiwiTmdab25lIiwiRWxlbWVudFJlZiIsIklucHV0IiwiT3V0cHV0IiwiU3Vic2NyaXB0aW9uIiwiZmlsdGVyIiwic3dpdGNoTWFwIiwib2YiLCJmcm9tRXZlbnQiLCJtZXJnZSIsInRhcCIsIkluamVjdCIsImZvcndhcmRSZWYiLCJ0c2xpYl8xLl9fZXh0ZW5kcyIsIkRpcmVjdGl2ZSIsIk5nTW9kdWxlIiwiQ29tbW9uTW9kdWxlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7SUFBQTs7Ozs7Ozs7Ozs7Ozs7SUFjQTtJQUVBLElBQUksYUFBYSxHQUFHLFVBQVMsQ0FBQyxFQUFFLENBQUM7UUFDN0IsYUFBYSxHQUFHLE1BQU0sQ0FBQyxjQUFjO2FBQ2hDLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxZQUFZLEtBQUssSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzVFLFVBQVUsQ0FBQyxFQUFFLENBQUMsSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQUUsSUFBSSxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztvQkFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvRSxPQUFPLGFBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0IsQ0FBQyxDQUFDO0FBRUYsYUFBZ0IsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFCLGFBQWEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDcEIsU0FBUyxFQUFFLEtBQUssSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsRUFBRTtRQUN2QyxDQUFDLENBQUMsU0FBUyxHQUFHLENBQUMsS0FBSyxJQUFJLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FB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