UNPKG

ngx-teximate

Version:
436 lines (428 loc) 35 kB
import { __spread, __extends, __assign } from 'tslib'; import { Component, Input, Output, NgZone, ElementRef, EventEmitter, ChangeDetectionStrategy, Directive, Inject, forwardRef, NgModule } from '@angular/core'; import { style, query, stagger, useAnimation, AnimationBuilder } from '@angular/animations'; import { BehaviorSubject, Subscription, fromEvent, merge, of } from 'rxjs'; import { map, filter, switchMap, tap } from 'rxjs/operators'; import { CommonModule } from '@angular/common'; /** * @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 EventEmitter(); /** * Stream that emits when animation is done */ this.finishEmitter = new EventEmitter(); /** * Teximate animations */ this.players = new Map(); /** * Teximate state */ this._state = new BehaviorSubject(''); this.state = this._state.pipe(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([ query(".teximate-" + config.type, [ // This is a workaround for enter animation to work style({ opacity: config.isEnter ? 0 : 1 }), stagger(config.delay, [useAnimation(config.animation)]) ]) ]); }; Teximate.decorators = [ { type: 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: ChangeDetectionStrategy.OnPush, styles: [".teximate-letter,.teximate-word{display:inline-block}.teximate-word{margin-right:8px}"] }] } ]; /** @nocollapse */ Teximate.ctorParameters = function () { return [ { type: AnimationBuilder }, { type: NgZone }, { type: ElementRef } ]; }; Teximate.propDecorators = { setText: [{ type: Input, args: ['text',] }], enter: [{ type: Input }], leave: [{ type: Input }], animation: [{ type: Input }], playEmitter: [{ type: Output, args: ['play',] }], finishEmitter: [{ type: 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 */ /** * @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 = Subscription.EMPTY; this.click = new EventEmitter(); this.hover = new EventEmitter(); } /** * @return {?} */ TeximateEvents.prototype.ngAfterViewInit = /** * @return {?} */ function () { var _this = this; this.events = this.teximate.state.pipe(filter(function () { return !!_this.click.observers.length || !!_this.hover.observers.length; }), switchMap(function () { /** @type {?} */ var clickEvents = of(null); /** @type {?} */ var hoverEvents = 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 fromEvent(el, 'click'); }); clickEvents = merge.apply(void 0, __spread(events)).pipe(tap(function (e) { return _this.click.emit(e); })); } if (_this.hover.observers.length) { /** @type {?} */ var events = Array.from(words).map(function (el) { return fromEvent(el, 'mouseenter'); }); hoverEvents = merge.apply(void 0, __spread(events)).pipe(tap(function (e) { return _this.hover.emit(e); })); } return merge(clickEvents, hoverEvents); })).subscribe(); }; /** * @return {?} */ TeximateEvents.prototype.ngOnDestroy = /** * @return {?} */ function () { this.events.unsubscribe(); }; /** @nocollapse */ TeximateEvents.ctorParameters = function () { return [ { type: ElementRef }, { type: Teximate, decorators: [{ type: Inject, args: [forwardRef(function () { return Teximate; }),] }] } ]; }; TeximateEvents.propDecorators = { click: [{ type: Output, args: ['',] }], hover: [{ type: 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 EventEmitter(); _this.hover = new EventEmitter(); _this.selector = '.teximate-paragraph'; return _this; } ParagraphEvents.decorators = [ { type: Directive, args: [{ selector: 'teximate[paragraphClick], teximate[paragraphHover]' },] } ]; /** @nocollapse */ ParagraphEvents.ctorParameters = function () { return [ { type: ElementRef }, { type: Teximate, decorators: [{ type: Inject, args: [forwardRef(function () { return Teximate; }),] }] } ]; }; ParagraphEvents.propDecorators = { click: [{ type: Output, args: ['paragraphClick',] }], hover: [{ type: 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 EventEmitter(); _this.hover = new EventEmitter(); _this.selector = '.teximate-word'; return _this; } WordEvents.decorators = [ { type: Directive, args: [{ selector: 'teximate[wordClick], teximate[wordHover]' },] } ]; /** @nocollapse */ WordEvents.ctorParameters = function () { return [ { type: ElementRef }, { type: Teximate, decorators: [{ type: Inject, args: [forwardRef(function () { return Teximate; }),] }] } ]; }; WordEvents.propDecorators = { click: [{ type: Output, args: ['wordClick',] }], hover: [{ type: 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 EventEmitter(); _this.hover = new EventEmitter(); _this.selector = '.teximate-letter'; return _this; } LetterEvents.decorators = [ { type: Directive, args: [{ selector: 'teximate[letterClick], teximate[letterHover]' },] } ]; /** @nocollapse */ LetterEvents.ctorParameters = function () { return [ { type: ElementRef }, { type: Teximate, decorators: [{ type: Inject, args: [forwardRef(function () { return Teximate; }),] }] } ]; }; LetterEvents.propDecorators = { click: [{ type: Output, args: ['letterClick',] }], hover: [{ type: 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: NgModule, args: [{ imports: [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 */ export { teximateFactory, Teximate, TeximateModule, LetterEvents as ɵd, ParagraphEvents as ɵb, TeximateEvents as ɵa, WordEvents as ɵc }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LXRleGltYXRlLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9uZ3gtdGV4aW1hdGUvbGliL3RleGltYXRlLnRzIiwibmc6Ly9uZ3gtdGV4aW1hdGUvbGliL3RleGltYXRlLWV2ZW50cy50cyIsIm5nOi8vbmd4LXRleGltYXRlL2xpYi90ZXhpbWF0ZS5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBBZnRlclZpZXdJbml0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgTmdab25lLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgc3R5bGUsXG4gIHF1ZXJ5LFxuICBzdGFnZ2VyLFxuICB1c2VBbmltYXRpb24sXG4gIEFuaW1hdGlvblBsYXllcixcbiAgQW5pbWF0aW9uQnVpbGRlcixcbiAgQW5pbWF0aW9uRmFjdG9yeVxufSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgVGV4dEFuaW1hdGlvbiB9IGZyb20gJy4vdGV4aW1hdGUubW9kZWwnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0ZXhpbWF0ZScsXG4gIGhvc3Q6IHtcbiAgICAnYXJpYS1sYWJlbCc6ICd0ZXh0J1xuICB9LFxuICB0ZW1wbGF0ZVVybDogJy4vdGV4aW1hdGUuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3RleGltYXRlLnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgVGV4aW1hdGUgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG5cbiAgLyoqIFNldCBhbmltYXRlZCB0ZXh0ICovXG4gIEBJbnB1dCgndGV4dCcpIHNldCBzZXRUZXh0KHRleHQ6IHN0cmluZykge1xuICAgIHRoaXMuX3N0YXRlLm5leHQodGV4dCk7XG4gIH1cblxuICAvKiogQW5pbWF0aW9uIHRoYXQgdHJpZ2dlcnMgb24gaW5pdCAqL1xuICBASW5wdXQoKSBlbnRlcjogVGV4dEFuaW1hdGlvbjtcblxuICAvKiogQW5pbWF0aW9uIHRoYXQgdHJpZ2dlcnMgb24gZGVzdHJveSAqL1xuICBASW5wdXQoKSBsZWF2ZTogVGV4dEFuaW1hdGlvbjtcblxuICAvKiogQW5pbWF0aW9uIHRoYXQgdHJpZ2dlcnMgd2l0aCB0aGUgcGxheSgpIGZ1bmN0aW9uICovXG4gIEBJbnB1dCgpIGFuaW1hdGlvbjogVGV4dEFuaW1hdGlvbjtcblxuICAvKiogU3RyZWFtIHRoYXQgZW1pdHMgd2hlbiBhbmltYXRpb24gaXMgc3RhcnRlZCAqL1xuICBAT3V0cHV0KCdwbGF5JykgcGxheUVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgLyoqIFN0cmVhbSB0aGF0IGVtaXRzIHdoZW4gYW5pbWF0aW9uIGlzIGRvbmUgKi9cbiAgQE91dHB1dCgnZmluaXNoJykgZmluaXNoRW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAvKiogVGV4aW1hdGUgYW5pbWF0aW9ucyAqL1xuICBwbGF5ZXJzID0gbmV3IE1hcDxzdHJpbmcsIEFuaW1hdGlvblBsYXllcj4oKTtcblxuICAvKiogVGV4aW1hdGUgc3RhdGUgKi9cbiAgcHJpdmF0ZSBfc3RhdGUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4oJycpO1xuICBzdGF0ZTogT2JzZXJ2YWJsZTxzdHJpbmdbXVtdW10+O1xuXG4gIC8qKiBUZXhpbWF0ZSBwbGF5aW5nIHN0YXRlICovXG4gIHByaXZhdGUgX2lzUGxheWluZzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBfaXNWaWV3SW5pdDogYm9vbGVhbjtcblxuICBnZXQgaXNQbGF5aW5nKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1BsYXlpbmc7XG4gIH1cblxuICBnZXQgZW50ZXJQbGF5ZXIoKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXJzLmdldCgnZW50ZXInKTtcbiAgfVxuXG4gIGdldCBsZWF2ZVBsYXllcigpOiBBbmltYXRpb25QbGF5ZXIge1xuICAgIHJldHVybiB0aGlzLnBsYXllcnMuZ2V0KCdsZWF2ZScpO1xuICB9XG5cbiAgZ2V0IGRlZmF1bHRQbGF5ZXIoKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXJzLmdldCgnZGVmYXVsdCcpO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBhbmltYXRpb25CdWlsZGVyOiBBbmltYXRpb25CdWlsZGVyLCBwcml2YXRlIHpvbmU6IE5nWm9uZSwgcHJpdmF0ZSBlbDogRWxlbWVudFJlZikge1xuICAgIHRoaXMuc3RhdGUgPSB0aGlzLl9zdGF0ZS5waXBlKG1hcCgodGV4dDogc3RyaW5nKSA9PiB0ZXhpbWF0ZUZhY3RvcnkodGV4dCkpKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLl9pc1ZpZXdJbml0ID0gdHJ1ZTtcbiAgICB0aGlzLnVwZGF0ZUFuaW1hdGlvbnModHJ1ZSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcygpIHtcbiAgICBpZiAodGhpcy5faXNWaWV3SW5pdCkge1xuICAgICAgdGhpcy51cGRhdGVBbmltYXRpb25zKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgLy8gVE9ETzogVXNlIHBsYXllcnMuZm9yRWFjaCB0byBkZXN0cm95IHBsYXllcnNcbiAgICBpZiAodGhpcy5wbGF5ZXJzLmhhcygnZW50ZXInKSkge1xuICAgICAgdGhpcy5wbGF5ZXJzLmdldCgnZW50ZXInKS5kZXN0cm95KCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBsYXllcnMuaGFzKCdsZWF2ZScpKSB7XG4gICAgICB0aGlzLnBsYXllcnMuZ2V0KCdsZWF2ZScpLmRlc3Ryb3koKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucGxheWVycy5oYXMoJ2RlZmF1bHQnKSkge1xuICAgICAgdGhpcy5wbGF5ZXJzLmdldCgnZGVmYXVsdCcpLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBuZXcgYW5pbWF0aW9uXG4gICAqL1xuICByZWdpc3RlckFuaW1hdGlvbihjb25maWc6IFRleHRBbmltYXRpb24pOiBBbmltYXRpb25QbGF5ZXIge1xuICAgIGNvbnN0IHBsYXllciA9IHRoaXMuYnVpbGRBbmltYXRpb24oY29uZmlnKS5jcmVhdGUodGhpcy5lbC5uYXRpdmVFbGVtZW50KTtcbiAgICAvKiogVE9ETzogSW52ZXN0aWdhdGUgd2h5IG9uU3RhcnQgYW5kIG9uRG9uZSBmaXJlIG9ubHkgb25jZSAqL1xuICAgIHBsYXllci5vblN0YXJ0KCgpID0+IHtcbiAgICAgIHRoaXMuX2lzUGxheWluZyA9IHRydWU7XG4gICAgICB0aGlzLnBsYXlFbWl0dGVyLmVtaXQoY29uZmlnLmlkKTtcbiAgICB9KTtcbiAgICBwbGF5ZXIub25Eb25lKCgpID0+IHtcbiAgICAgIHRoaXMuX2lzUGxheWluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5maW5pc2hFbWl0dGVyLmVtaXQoY29uZmlnLmlkKTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXJzLnNldChjb25maWcuaWQsIHBsYXllcikuZ2V0KGNvbmZpZy5pZCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUFuaW1hdGlvbnMoYXV0b1BsYXlFbnRlcj86IGJvb2xlYW4pIHtcbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuZW50ZXIpIHtcbiAgICAgICAgY29uc3QgZW50ZXJQbGF5ZXIgPSB0aGlzLnJlZ2lzdGVyQW5pbWF0aW9uKHsuLi50aGlzLmVudGVyLCBpZDogJ2VudGVyJywgaXNFbnRlcjogdHJ1ZX0pO1xuICAgICAgICBpZiAoYXV0b1BsYXlFbnRlcikge1xuICAgICAgICAgIGVudGVyUGxheWVyLnBsYXkoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMubGVhdmUpIHtcbiAgICAgICAgdGhpcy5yZWdpc3RlckFuaW1hdGlvbih7Li4udGhpcy5sZWF2ZSwgaWQ6ICdsZWF2ZSd9KTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmFuaW1hdGlvbikge1xuICAgICAgICB0aGlzLnJlZ2lzdGVyQW5pbWF0aW9uKHtpZDogJ2RlZmF1bHQnLCAuLi50aGlzLmFuaW1hdGlvbn0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGFuaW1hdGlvblxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZEFuaW1hdGlvbihjb25maWc6IFRleHRBbmltYXRpb24pOiBBbmltYXRpb25GYWN0b3J5IHtcbiAgICAvKiogVE9ETzogVXNlICc6ZW50ZXInIGFuZCAnOmxlYXZlJyBmb3IgZW50ZXIgYW5kIGxlYXZlIGFuaW1hdGlvbnMgKi9cbiAgICByZXR1cm4gdGhpcy5hbmltYXRpb25CdWlsZGVyLmJ1aWxkKFtcbiAgICAgIHF1ZXJ5KFxuICAgICAgICBgLnRleGltYXRlLSR7Y29uZmlnLnR5cGV9YCxcbiAgICAgICAgW1xuICAgICAgICAgIC8vIFRoaXMgaXMgYSB3b3JrYXJvdW5kIGZvciBlbnRlciBhbmltYXRpb24gdG8gd29ya1xuICAgICAgICAgIHN0eWxlKHtvcGFjaXR5OiBjb25maWcuaXNFbnRlciA/IDAgOiAxfSksXG4gICAgICAgICAgc3RhZ2dlcihjb25maWcuZGVsYXksIFt1c2VBbmltYXRpb24oY29uZmlnLmFuaW1hdGlvbildKVxuICAgICAgICBdXG4gICAgICApXG4gICAgXSk7XG4gIH1cbn1cblxuLyoqIENvbnZlcnQgdGV4dCBzdHJpbmcgaW50byBhIHdvcmthYmxlIHRleHQgKi9cbmV4cG9ydCBmdW5jdGlvbiB0ZXhpbWF0ZUZhY3RvcnkodGV4dDogc3RyaW5nKTogc3RyaW5nW11bXVtdIHtcbiAgY29uc3QgcGFyYWdyYXBoczogc3RyaW5nW11bXVtdID0gW107XG4gIC8vIFNwbGl0IHRleHQgaW50byBwYXJhZ3JhcGhzXG4gIHRleHQuc3BsaXQoJ1xcbicpLm1hcCgocGFyYWdyYXBoOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCB3b3Jkczogc3RyaW5nW11bXSA9IFtdO1xuICAgIC8vIFNwbGl0IHBhcmFncmFwaCBpbnRvIHdvcmRzXG4gICAgcGFyYWdyYXBoXG4gICAgICAuc3BsaXQoJyAnKVxuICAgICAgLmZpbHRlcih3b3JkID0+IHdvcmQgIT09ICcnKVxuICAgICAgLm1hcCgod29yZDogc3RyaW5nKSA9PlxuICAgICAgICAvLyBTcGxpdCB3b3JkIGludG8gbGV0dGVyc1xuICAgICAgICB3b3Jkcy5wdXNoKHdvcmQuc3BsaXQoLyg/ISQpL3UpKVxuICAgICAgKTtcbiAgICBwYXJhZ3JhcGhzLnB1c2god29yZHMpO1xuICB9KTtcbiAgcmV0dXJuIHBhcmFncmFwaHM7XG59XG4iLCJpbXBvcnQgeyBEaXJlY3RpdmUsIE91dHB1dCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95LCBJbmplY3QsIEVsZW1lbnRSZWYsIEV2ZW50RW1pdHRlciwgZm9yd2FyZFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBmcm9tRXZlbnQsIG1lcmdlLCBTdWJzY3JpcHRpb25MaWtlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRleGltYXRlIH0gZnJvbSAnLi90ZXhpbWF0ZSc7XG5cbmV4cG9ydCBjbGFzcyBUZXhpbWF0ZUV2ZW50cyBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgc2VsZWN0b3I6IHN0cmluZztcbiAgZXZlbnRzOiBTdWJzY3JpcHRpb25MaWtlID0gU3Vic2NyaXB0aW9uLkVNUFRZO1xuICBAT3V0cHV0KCcnKSBjbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgnJykgaG92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY29uc3RydWN0b3IocHVibGljIGVsZW1lbnQ6IEVsZW1lbnRSZWYsIEBJbmplY3QoZm9yd2FyZFJlZigoKSA9PiBUZXhpbWF0ZSkpIHB1YmxpYyB0ZXhpbWF0ZTogVGV4aW1hdGUpIHtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmV2ZW50cyA9IHRoaXMudGV4aW1hdGUuc3RhdGUucGlwZShcbiAgICAgIGZpbHRlcigoKSA9PiAhIXRoaXMuY2xpY2sub2JzZXJ2ZXJzLmxlbmd0aCB8fCAhIXRoaXMuaG92ZXIub2JzZXJ2ZXJzLmxlbmd0aCksXG4gICAgICBzd2l0Y2hNYXAoKCkgPT4ge1xuICAgICAgICBsZXQgY2xpY2tFdmVudHMgPSBvZihudWxsKTtcbiAgICAgICAgbGV0IGhvdmVyRXZlbnRzID0gb2YobnVsbCk7XG4gICAgICAgIGNvbnN0IHdvcmRzID0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvckFsbCh0aGlzLnNlbGVjdG9yKTtcbiAgICAgICAgaWYgKHRoaXMuY2xpY2sub2JzZXJ2ZXJzLmxlbmd0aCkge1xuICAgICAgICAgIGNvbnN0IGV2ZW50cyA9IEFycmF5LmZyb20od29yZHMpLm1hcCgoZWw6IEhUTUxFbGVtZW50KSA9PiBmcm9tRXZlbnQoZWwsICdjbGljaycpKTtcbiAgICAgICAgICBjbGlja0V2ZW50cyA9IG1lcmdlKC4uLmV2ZW50cykucGlwZSh0YXAoZSA9PiB0aGlzLmNsaWNrLmVtaXQoZSkpKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5ob3Zlci5vYnNlcnZlcnMubGVuZ3RoKSB7XG4gICAgICAgICAgY29uc3QgZXZlbnRzID0gQXJyYXkuZnJvbSh3b3JkcykubWFwKChlbDogSFRNTEVsZW1lbnQpID0+IGZyb21FdmVudChlbCwgJ21vdXNlZW50ZXInKSk7XG4gICAgICAgICAgaG92ZXJFdmVudHMgPSBtZXJnZSguLi5ldmVudHMpLnBpcGUodGFwKGUgPT4gdGhpcy5ob3Zlci5lbWl0KGUpKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1lcmdlKGNsaWNrRXZlbnRzLCBob3ZlckV2ZW50cyk7XG4gICAgICB9KVxuICAgICkuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICB0aGlzLmV2ZW50cy51bnN1YnNjcmliZSgpO1xuICB9XG5cbn1cblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAndGV4aW1hdGVbcGFyYWdyYXBoQ2xpY2tdLCB0ZXhpbWF0ZVtwYXJhZ3JhcGhIb3Zlcl0nXG59KVxuZXhwb3J0IGNsYXNzIFBhcmFncmFwaEV2ZW50cyBleHRlbmRzIFRleGltYXRlRXZlbnRzIHtcbiAgQE91dHB1dCgncGFyYWdyYXBoQ2xpY2snKSBjbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgncGFyYWdyYXBoSG92ZXInKSBob3ZlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBjb25zdHJ1Y3RvcihlbGVtZW50OiBFbGVtZW50UmVmLCBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gVGV4aW1hdGUpKSB0ZXhpbWF0ZTogVGV4aW1hdGUpIHtcbiAgICBzdXBlcihlbGVtZW50LCB0ZXhpbWF0ZSk7XG4gICAgdGhpcy5zZWxlY3RvciA9ICcudGV4aW1hdGUtcGFyYWdyYXBoJztcbiAgfVxufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICd0ZXhpbWF0ZVt3b3JkQ2xpY2tdLCB0ZXhpbWF0ZVt3b3JkSG92ZXJdJ1xufSlcbmV4cG9ydCBjbGFzcyBXb3JkRXZlbnRzIGV4dGVuZHMgVGV4aW1hdGVFdmVudHMge1xuICBAT3V0cHV0KCd3b3JkQ2xpY2snKSBjbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgnd29yZEhvdmVyJykgaG92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudDogRWxlbWVudFJlZiwgQEluamVjdChmb3J3YXJkUmVmKCgpID0+IFRleGltYXRlKSkgdGV4aW1hdGU6IFRleGltYXRlKSB7XG4gICAgc3VwZXIoZWxlbWVudCwgdGV4aW1hdGUpO1xuICAgIHRoaXMuc2VsZWN0b3IgPSAnLnRleGltYXRlLXdvcmQnO1xuICB9XG59XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ3RleGltYXRlW2xldHRlckNsaWNrXSwgdGV4aW1hdGVbbGV0dGVySG92ZXJdJ1xufSlcbmV4cG9ydCBjbGFzcyBMZXR0ZXJFdmVudHMgZXh0ZW5kcyBUZXhpbWF0ZUV2ZW50cyB7XG4gIEBPdXRwdXQoJ2xldHRlckNsaWNrJykgY2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoJ2xldHRlckhvdmVyJykgaG92ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY29uc3RydWN0b3IoZWxlbWVudDogRWxlbWVudFJlZiwgQEluamVjdChmb3J3YXJkUmVmKCgpID0+IFRleGltYXRlKSkgdGV4aW1hdGU6IFRleGltYXRlKSB7XG4gICAgc3VwZXIoZWxlbWVudCwgdGV4aW1hdGUpO1xuICAgIHRoaXMuc2VsZWN0b3IgPSAnLnRleGltYXRlLWxldHRlcic7XG4gIH1cbn1cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgVGV4aW1hdGUgfSBmcm9tICcuL3RleGltYXRlJztcbmltcG9ydCB7IFBhcmFncmFwaEV2ZW50cywgV29yZEV2ZW50cywgTGV0dGVyRXZlbnRzIH0gZnJvbSAnLi90ZXhpbWF0ZS1ldmVudHMnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgVGV4aW1hdGUsXG4gICAgUGFyYWdyYXBoRXZlbnRzLFxuICAgIFdvcmRFdmVudHMsXG4gICAgTGV0dGVyRXZlbnRzXG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBUZXhpbWF0ZSxcbiAgICBQYXJhZ3JhcGhFdmVudHMsXG4gICAgV29yZEV2ZW50cyxcbiAgICBMZXR0ZXJFdmVudHNcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBUZXhpbWF0ZU1vZHVsZSB7XG59XG4iXSwibmFtZXMiOlsidHNsaWJfMS5fX2V4dGVuZHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7OztJQW1GRSxrQkFBb0IsZ0JBQWtDLEVBQVUsSUFBWSxFQUFVLEVBQWM7UUFBaEYscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUFVLFNBQUksR0FBSixJQUFJLENBQVE7UUFBVSxPQUFFLEdBQUYsRUFBRSxDQUFZOzs7O1FBaENwRixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7Ozs7UUFHL0Isa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDOzs7O1FBR3JELFlBQU8sR0FBRyxJQUFJLEdBQUcsRUFBMkIsQ0FBQzs7OztRQUdyQyxXQUFNLEdBQUcsSUFBSSxlQUFlLENBQVMsRUFBRSxDQUFDLENBQUM7UUF3Qi9DLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQUMsSUFBWSxJQUFLLE9BQUEsZUFBZSxDQUFDLElBQUksQ0FBQyxHQUFBLENBQUMsQ0FBQyxDQUFDO0tBQzdFO0lBaERELHNCQUFtQiw2QkFBTzs7Ozs7OztRQUExQixVQUEyQixJQUFZO1lBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3hCOzs7T0FBQTtJQTRCRCxzQkFBSSwrQkFBUzs7OztRQUFiO1lBQ0UsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO1NBQ3hCOzs7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