ngx-teximate
Version:
Angular text animations component
255 lines • 19.8 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { Component, Input, Output, NgZone, ElementRef, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
import { style, query, stagger, useAnimation, AnimationBuilder } from '@angular/animations';
import { BehaviorSubject } from 'rxjs';
import { map } from 'rxjs/operators';
export class Teximate {
/**
* @param {?} animationBuilder
* @param {?} zone
* @param {?} el
*/
constructor(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((text) => teximateFactory(text)));
}
/**
* Set animated text
* @param {?} text
* @return {?}
*/
set setText(text) {
this._state.next(text);
}
/**
* @return {?}
*/
get isPlaying() {
return this._isPlaying;
}
/**
* @return {?}
*/
get enterPlayer() {
return this.players.get('enter');
}
/**
* @return {?}
*/
get leavePlayer() {
return this.players.get('leave');
}
/**
* @return {?}
*/
get defaultPlayer() {
return this.players.get('default');
}
/**
* @return {?}
*/
ngAfterViewInit() {
this._isViewInit = true;
this.updateAnimations(true);
}
/**
* @return {?}
*/
ngOnChanges() {
if (this._isViewInit) {
this.updateAnimations();
}
}
/**
* @return {?}
*/
ngOnDestroy() {
// 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
* @param {?} config
* @return {?}
*/
registerAnimation(config) {
/** @type {?} */
const player = this.buildAnimation(config).create(this.el.nativeElement);
/** TODO: Investigate why onStart and onDone fire only once */
player.onStart(() => {
this._isPlaying = true;
this.playEmitter.emit(config.id);
});
player.onDone(() => {
this._isPlaying = false;
this.finishEmitter.emit(config.id);
});
return this.players.set(config.id, player).get(config.id);
}
/**
* @param {?=} autoPlayEnter
* @return {?}
*/
updateAnimations(autoPlayEnter) {
this.zone.runOutsideAngular(() => {
if (this.enter) {
/** @type {?} */
const enterPlayer = this.registerAnimation(Object.assign({}, this.enter, { id: 'enter', isEnter: true }));
if (autoPlayEnter) {
enterPlayer.play();
}
}
if (this.leave) {
this.registerAnimation(Object.assign({}, this.leave, { id: 'leave' }));
}
if (this.animation) {
this.registerAnimation(Object.assign({ id: 'default' }, this.animation));
}
});
}
/**
* Build animation
* @param {?} config
* @return {?}
*/
buildAnimation(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 = () => [
{ 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',] }]
};
if (false) {
/**
* Animation that triggers on init
* @type {?}
*/
Teximate.prototype.enter;
/**
* Animation that triggers on destroy
* @type {?}
*/
Teximate.prototype.leave;
/**
* Animation that triggers with the play() function
* @type {?}
*/
Teximate.prototype.animation;
/**
* Stream that emits when animation is started
* @type {?}
*/
Teximate.prototype.playEmitter;
/**
* Stream that emits when animation is done
* @type {?}
*/
Teximate.prototype.finishEmitter;
/**
* Teximate animations
* @type {?}
*/
Teximate.prototype.players;
/**
* Teximate state
* @type {?}
*/
Teximate.prototype._state;
/** @type {?} */
Teximate.prototype.state;
/**
* Teximate playing state
* @type {?}
*/
Teximate.prototype._isPlaying;
/** @type {?} */
Teximate.prototype._isViewInit;
/** @type {?} */
Teximate.prototype.animationBuilder;
/** @type {?} */
Teximate.prototype.zone;
/** @type {?} */
Teximate.prototype.el;
}
/**
* Convert text string into a workable text
* @param {?} text
* @return {?}
*/
export function teximateFactory(text) {
/** @type {?} */
const paragraphs = [];
// Split text into paragraphs
text.split('\n').map((paragraph) => {
/** @type {?} */
const words = [];
// Split paragraph into words
paragraph
.split(' ')
.filter(word => word !== '')
.map((word) =>
// Split word into letters
words.push(word.split(/(?!$)/u)));
paragraphs.push(words);
});
return paragraphs;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4aW1hdGUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtdGV4aW1hdGUvIiwic291cmNlcyI6WyJsaWIvdGV4aW1hdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUNMLE1BQU0sRUFJTixNQUFNLEVBQ04sVUFBVSxFQUNWLFlBQVksRUFDWix1QkFBdUIsRUFDeEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLEtBQUssRUFDTCxLQUFLLEVBQ0wsT0FBTyxFQUNQLFlBQVksRUFFWixnQkFBZ0IsRUFFakIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsZUFBZSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVlyQyxNQUFNLE9BQU8sUUFBUTs7Ozs7O0lBaURuQixZQUFvQixnQkFBa0MsRUFBVSxJQUFZLEVBQVUsRUFBYztRQUFoRixxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFVLE9BQUUsR0FBRixFQUFFLENBQVk7Ozs7UUFoQ3BGLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQzs7OztRQUcvQixrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7Ozs7UUFHckQsWUFBTyxHQUFHLElBQUksR0FBRyxFQUEyQixDQUFDOzs7O1FBR3JDLFdBQU0sR0FBRyxJQUFJLGVBQWUsQ0FBUyxFQUFFLENBQUMsQ0FBQztRQXdCL0MsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUUsQ0FBQzs7Ozs7O0lBaERELElBQW1CLE9BQU8sQ0FBQyxJQUFZO1FBQ3JDLElBQUksQ0FB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QThCOzs7OztJQUc5Qix5QkFBOEI7Ozs7O0lBRzlCLDZCQUFrQzs7Ozs7SUFHbEMsK0JBQWlEOzs7OztJQUdqRCxpQ0FBcUQ7Ozs7O0lBR3JELDJCQUE2Qzs7Ozs7SUFHN0MsMEJBQWlEOztJQUNqRCx5QkFBZ0M7Ozs7O0lBR2hDLDhCQUE0Qjs7SUFDNUIsK0JBQTZCOztJQWtCakIsb0NBQTBDOztJQUFFLHdCQUFvQjs7SUFBRSxzQkFBc0I7Ozs7Ozs7QUFpRnRHLE1BQU0sVUFBVSxlQUFlLENBQUMsSUFBWTs7VUFDcEMsVUFBVSxHQUFpQixFQUFFO0lBQ25DLDZCQUE2QjtJQUM3QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQWlCLEVBQUUsRUFBRTs7Y0FDbkMsS0FBSyxHQUFlLEVBQUU7UUFDNUIsNkJBQTZCO1FBQzdCLFNBQVM7YUFDTixLQUFLLENBQUMsR0FBRyxDQUFDO2FBQ1YsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxLQUFLLEVBQUUsQ0FBQzthQUMzQixHQUFHLENBQUMsQ0FBQyxJQUFZLEVBQUUsRUFBRTtRQUNwQiwwQkFBMEI7UUFDMUIsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQ2pDLENBQUM7UUFDSixVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pCLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE5nWm9uZSxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIHN0eWxlLFxuICBxdWVyeSxcbiAgc3RhZ2dlcixcbiAgdXNlQW5pbWF0aW9uLFxuICBBbmltYXRpb25QbGF5ZXIsXG4gIEFuaW1hdGlvbkJ1aWxkZXIsXG4gIEFuaW1hdGlvbkZhY3Rvcnlcbn0gZnJvbSAnQGFuZ3VsYXIvYW5pbWF0aW9ucyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFRleHRBbmltYXRpb24gfSBmcm9tICcuL3RleGltYXRlLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGV4aW1hdGUnLFxuICBob3N0OiB7XG4gICAgJ2FyaWEtbGFiZWwnOiAndGV4dCdcbiAgfSxcbiAgdGVtcGxhdGVVcmw6ICcuL3RleGltYXRlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90ZXhpbWF0ZS5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIFRleGltYXRlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuXG4gIC8qKiBTZXQgYW5pbWF0ZWQgdGV4dCAqL1xuICBASW5wdXQoJ3RleHQnKSBzZXQgc2V0VGV4dCh0ZXh0OiBzdHJpbmcpIHtcbiAgICB0aGlzLl9zdGF0ZS5uZXh0KHRleHQpO1xuICB9XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIG9uIGluaXQgKi9cbiAgQElucHV0KCkgZW50ZXI6IFRleHRBbmltYXRpb247XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIG9uIGRlc3Ryb3kgKi9cbiAgQElucHV0KCkgbGVhdmU6IFRleHRBbmltYXRpb247XG5cbiAgLyoqIEFuaW1hdGlvbiB0aGF0IHRyaWdnZXJzIHdpdGggdGhlIHBsYXkoKSBmdW5jdGlvbiAqL1xuICBASW5wdXQoKSBhbmltYXRpb246IFRleHRBbmltYXRpb247XG5cbiAgLyoqIFN0cmVhbSB0aGF0IGVtaXRzIHdoZW4gYW5pbWF0aW9uIGlzIHN0YXJ0ZWQgKi9cbiAgQE91dHB1dCgncGxheScpIHBsYXlFbWl0dGVyID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIC8qKiBTdHJlYW0gdGhhdCBlbWl0cyB3aGVuIGFuaW1hdGlvbiBpcyBkb25lICovXG4gIEBPdXRwdXQoJ2ZpbmlzaCcpIGZpbmlzaEVtaXR0ZXIgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgLyoqIFRleGltYXRlIGFuaW1hdGlvbnMgKi9cbiAgcGxheWVycyA9IG5ldyBNYXA8c3RyaW5nLCBBbmltYXRpb25QbGF5ZXI+KCk7XG5cbiAgLyoqIFRleGltYXRlIHN0YXRlICovXG4gIHByaXZhdGUgX3N0YXRlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgc3RhdGU6IE9ic2VydmFibGU8c3RyaW5nW11bXVtdPjtcblxuICAvKiogVGV4aW1hdGUgcGxheWluZyBzdGF0ZSAqL1xuICBwcml2YXRlIF9pc1BsYXlpbmc6IGJvb2xlYW47XG4gIHByaXZhdGUgX2lzVmlld0luaXQ6IGJvb2xlYW47XG5cbiAgZ2V0IGlzUGxheWluZygpIHtcbiAgICByZXR1cm4gdGhpcy5faXNQbGF5aW5nO1xuICB9XG5cbiAgZ2V0IGVudGVyUGxheWVyKCk6IEFuaW1hdGlvblBsYXllciB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5nZXQoJ2VudGVyJyk7XG4gIH1cblxuICBnZXQgbGVhdmVQbGF5ZXIoKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICByZXR1cm4gdGhpcy5wbGF5ZXJzLmdldCgnbGVhdmUnKTtcbiAgfVxuXG4gIGdldCBkZWZhdWx0UGxheWVyKCk6IEFuaW1hdGlvblBsYXllciB7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5nZXQoJ2RlZmF1bHQnKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgYW5pbWF0aW9uQnVpbGRlcjogQW5pbWF0aW9uQnVpbGRlciwgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYpIHtcbiAgICB0aGlzLnN0YXRlID0gdGhpcy5fc3RhdGUucGlwZShtYXAoKHRleHQ6IHN0cmluZykgPT4gdGV4aW1hdGVGYWN0b3J5KHRleHQpKSk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5faXNWaWV3SW5pdCA9IHRydWU7XG4gICAgdGhpcy51cGRhdGVBbmltYXRpb25zKHRydWUpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoKSB7XG4gICAgaWYgKHRoaXMuX2lzVmlld0luaXQpIHtcbiAgICAgIHRoaXMudXBkYXRlQW5pbWF0aW9ucygpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIC8vIFRPRE86IFVzZSBwbGF5ZXJzLmZvckVhY2ggdG8gZGVzdHJveSBwbGF5ZXJzXG4gICAgaWYgKHRoaXMucGxheWVycy5oYXMoJ2VudGVyJykpIHtcbiAgICAgIHRoaXMucGxheWVycy5nZXQoJ2VudGVyJykuZGVzdHJveSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5wbGF5ZXJzLmhhcygnbGVhdmUnKSkge1xuICAgICAgdGhpcy5wbGF5ZXJzLmdldCgnbGVhdmUnKS5kZXN0cm95KCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBsYXllcnMuaGFzKCdkZWZhdWx0JykpIHtcbiAgICAgIHRoaXMucGxheWVycy5nZXQoJ2RlZmF1bHQnKS5kZXN0cm95KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgbmV3IGFuaW1hdGlvblxuICAgKi9cbiAgcmVnaXN0ZXJBbmltYXRpb24oY29uZmlnOiBUZXh0QW5pbWF0aW9uKTogQW5pbWF0aW9uUGxheWVyIHtcbiAgICBjb25zdCBwbGF5ZXIgPSB0aGlzLmJ1aWxkQW5pbWF0aW9uKGNvbmZpZykuY3JlYXRlKHRoaXMuZWwubmF0aXZlRWxlbWVudCk7XG4gICAgLyoqIFRPRE86IEludmVzdGlnYXRlIHdoeSBvblN0YXJ0IGFuZCBvbkRvbmUgZmlyZSBvbmx5IG9uY2UgKi9cbiAgICBwbGF5ZXIub25TdGFydCgoKSA9PiB7XG4gICAgICB0aGlzLl9pc1BsYXlpbmcgPSB0cnVlO1xuICAgICAgdGhpcy5wbGF5RW1pdHRlci5lbWl0KGNvbmZpZy5pZCk7XG4gICAgfSk7XG4gICAgcGxheWVyLm9uRG9uZSgoKSA9PiB7XG4gICAgICB0aGlzLl9pc1BsYXlpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuZmluaXNoRW1pdHRlci5lbWl0KGNvbmZpZy5pZCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMucGxheWVycy5zZXQoY29uZmlnLmlkLCBwbGF5ZXIpLmdldChjb25maWcuaWQpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVBbmltYXRpb25zKGF1dG9QbGF5RW50ZXI/OiBib29sZWFuKSB7XG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIGlmICh0aGlzLmVudGVyKSB7XG4gICAgICAgIGNvbnN0IGVudGVyUGxheWVyID0gdGhpcy5yZWdpc3RlckFuaW1hdGlvbih7Li4udGhpcy5lbnRlciwgaWQ6ICdlbnRlcicsIGlzRW50ZXI6IHRydWV9KTtcbiAgICAgICAgaWYgKGF1dG9QbGF5RW50ZXIpIHtcbiAgICAgICAgICBlbnRlclBsYXllci5wbGF5KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLmxlYXZlKSB7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJBbmltYXRpb24oey4uLnRoaXMubGVhdmUsIGlkOiAnbGVhdmUnfSk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5hbmltYXRpb24pIHtcbiAgICAgICAgdGhpcy5yZWdpc3RlckFuaW1hdGlvbih7aWQ6ICdkZWZhdWx0JywgLi4udGhpcy5hbmltYXRpb259KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhbmltYXRpb25cbiAgICovXG4gIHByaXZhdGUgYnVpbGRBbmltYXRpb24oY29uZmlnOiBUZXh0QW5pbWF0aW9uKTogQW5pbWF0aW9uRmFjdG9yeSB7XG4gICAgLyoqIFRPRE86IFVzZSAnOmVudGVyJyBhbmQgJzpsZWF2ZScgZm9yIGVudGVyIGFuZCBsZWF2ZSBhbmltYXRpb25zICovXG4gICAgcmV0dXJuIHRoaXMuYW5pbWF0aW9uQnVpbGRlci5idWlsZChbXG4gICAgICBxdWVyeShcbiAgICAgICAgYC50ZXhpbWF0ZS0ke2NvbmZpZy50eXBlfWAsXG4gICAgICAgIFtcbiAgICAgICAgICAvLyBUaGlzIGlzIGEgd29ya2Fyb3VuZCBmb3IgZW50ZXIgYW5pbWF0aW9uIHRvIHdvcmtcbiAgICAgICAgICBzdHlsZSh7b3BhY2l0eTogY29uZmlnLmlzRW50ZXIgPyAwIDogMX0pLFxuICAgICAgICAgIHN0YWdnZXIoY29uZmlnLmRlbGF5LCBbdXNlQW5pbWF0aW9uKGNvbmZpZy5hbmltYXRpb24pXSlcbiAgICAgICAgXVxuICAgICAgKVxuICAgIF0pO1xuICB9XG59XG5cbi8qKiBDb252ZXJ0IHRleHQgc3RyaW5nIGludG8gYSB3b3JrYWJsZSB0ZXh0ICovXG5leHBvcnQgZnVuY3Rpb24gdGV4aW1hdGVGYWN0b3J5KHRleHQ6IHN0cmluZyk6IHN0cmluZ1tdW11bXSB7XG4gIGNvbnN0IHBhcmFncmFwaHM6IHN0cmluZ1tdW11bXSA9IFtdO1xuICAvLyBTcGxpdCB0ZXh0IGludG8gcGFyYWdyYXBoc1xuICB0ZXh0LnNwbGl0KCdcXG4nKS5tYXAoKHBhcmFncmFwaDogc3RyaW5nKSA9PiB7XG4gICAgY29uc3Qgd29yZHM6IHN0cmluZ1tdW10gPSBbXTtcbiAgICAvLyBTcGxpdCBwYXJhZ3JhcGggaW50byB3b3Jkc1xuICAgIHBhcmFncmFwaFxuICAgICAgLnNwbGl0KCcgJylcbiAgICAgIC5maWx0ZXIod29yZCA9PiB3b3JkICE9PSAnJylcbiAgICAgIC5tYXAoKHdvcmQ6IHN0cmluZykgPT5cbiAgICAgICAgLy8gU3BsaXQgd29yZCBpbnRvIGxldHRlcnNcbiAgICAgICAgd29yZHMucHVzaCh3b3JkLnNwbGl0KC8oPyEkKS91KSlcbiAgICAgICk7XG4gICAgcGFyYWdyYXBocy5wdXNoKHdvcmRzKTtcbiAgfSk7XG4gIHJldHVybiBwYXJhZ3JhcGhzO1xufVxuIl19