UNPKG

@q149/angular-scrollspy

Version:

A simple lightweight library for Angular which automatically updates links to indicate the currently active section in the viewport

459 lines (445 loc) 46.9 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@q149/angular-inviewport')) : typeof define === 'function' && define.amd ? define('@q149/angular-scrollspy', ['exports', '@angular/core', '@q149/angular-inviewport'], factory) : (factory((global.q149 = global.q149 || {}, global.q149['angular-scrollspy'] = {}),global.ng.core,global.angularInviewport)); }(this, (function (exports,core,angularInviewport) { 'use strict'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * A directive used to add an `active` class to a nav item * when the section is in the viewport * * \@example * ```html * <a snScrollSpyItem for="foo" href="#section1">Section 1</a> * ``` * */ var ScrollSpyItemDirective = (function () { /** * Creates an instance of ScrollSpyItemDirective. * @memberof ScrollSpyItemDirective */ function ScrollSpyItemDirective(cdRef) { this.cdRef = cdRef; /** * True if the nav item is the active item in the `items` list * for `ScrollSpyDirective` instance * * \@memberof ScrollSpyItemDirective */ this.active = false; /** * If true means the section is in the viewport * * \@memberof ScrollSpyItemDirective */ this.inViewport = false; } Object.defineProperty(ScrollSpyItemDirective.prototype, "section", { get: /** * Id of section that links navigates to * * \@readonly * \@memberof ScrollSpyItemDirective * @return {?} */ function () { return this.href.replace('#', ''); }, enumerable: true, configurable: true }); /** * Manually trigger change detection * * \@memberof ScrollSpyItemDirective * @return {?} */ ScrollSpyItemDirective.prototype.detectChanges = /** * Manually trigger change detection * * \@memberof ScrollSpyItemDirective * @return {?} */ function () { this.cdRef.detectChanges(); }; ScrollSpyItemDirective.decorators = [ { type: core.Directive, args: [{ selector: '[snScrollSpyItem]' },] }, ]; /** @nocollapse */ ScrollSpyItemDirective.ctorParameters = function () { return [ { type: core.ChangeDetectorRef, }, ]; }; ScrollSpyItemDirective.propDecorators = { "active": [{ type: core.HostBinding, args: ['class.active',] },], "for": [{ type: core.Input },], "href": [{ type: core.Input },], }; return ScrollSpyItemDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Service that stores a list of `Spy`'s and the state * of their nav items `inViewport` and `active` state * */ var ScrollSpyService = (function () { function ScrollSpyService() { /** * List of `Spy`'s * * \@memberof ScrollSpyService */ this.spys = []; /** * Stores requests to add items to spy when spy hasn't been created * yet. Once spy has been added then request will be made again. * * \@memberof ScrollSpyService */ this.buffer = []; } /** * Add spy to list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @param {?} items * @return {?} */ ScrollSpyService.prototype.addSpy = /** * Add spy to list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @param {?} items * @return {?} */ function (id, items) { var _this = this; this.spys.push({ id: id, items: items }); var /** @type {?} */ buffer = this.buffer.filter(function (i) { return i.spyId === id; }); this.buffer = this.buffer.filter(function (i) { return i.spyId !== id; }); buffer.forEach(function (i) { return _this.setSpySectionStatus(i.sectionId, i.spyId, i.inViewport); }); }; /** * Remove spy from list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @return {?} */ ScrollSpyService.prototype.removeSpy = /** * Remove spy from list of `spys` * * \@memberof ScrollSpyService * @param {?} id * @return {?} */ function (id) { var /** @type {?} */ i = this.spys.findIndex(function (s) { return s.id === id; }); this.spys.splice(i, 1); }; /** * Set the `inViewport` status for a spy item then sets the active * to true for the first item in the list that has `inViewport` * set to true * * \@memberof ScrollSpyService * @param {?} sectionId * @param {?} spyId * @param {?} inViewport * @return {?} */ ScrollSpyService.prototype.setSpySectionStatus = /** * Set the `inViewport` status for a spy item then sets the active * to true for the first item in the list that has `inViewport` * set to true * * \@memberof ScrollSpyService * @param {?} sectionId * @param {?} spyId * @param {?} inViewport * @return {?} */ function (sectionId, spyId, inViewport) { var /** @type {?} */ spy = this.spys.find(function (s) { return s.id === spyId; }); if (!spy) { this.buffer.push({ sectionId: sectionId, spyId: spyId, inViewport: inViewport }); return; } var /** @type {?} */ item = spy.items.find(function (i) { return i.section === sectionId; }); if (!item) { return; } item.inViewport = inViewport; var /** @type {?} */ firstInViewport = spy.items.filter(function (i) { return i.inViewport; })[0]; spy.items.forEach(function (i) { return (i.active = false); }); if (firstInViewport) { firstInViewport.active = true; firstInViewport.detectChanges(); } }; ScrollSpyService.decorators = [ { type: core.Injectable }, ]; return ScrollSpyService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Adds `active` class to navigation links when section is in the viewport. * Used in conjuction with `snScrollItem` directive which should be added * to anchor links in the nav * * \@example * ``` * <ul role="navigation" snScrollSpy id="foo"> * <li><a snScrollSpyItem for="foo" href="#section1">Section 1</a></li> * <li><a snScrollSpyItem for="foo" href="#section2">Section 2</a></li> * <li><a snScrollSpyItem for="foo" href="#section3">Section 3</a></li> * <li><a snScrollSpyItem for="foo" href="#section4">Section 4</a></li> * </ul> * ``` * */ var ScrollSpyDirective = (function () { /** * Creates an instance of ScrollSpyDirective. * @memberof ScrollSpyDirective */ function ScrollSpyDirective(scrollSpySvc) { this.scrollSpySvc = scrollSpySvc; } /** * Adds spy to list of spys in `ScrollSpyService` * * \@memberof ScrollSpyDirective * @return {?} */ ScrollSpyDirective.prototype.ngAfterViewInit = /** * Adds spy to list of spys in `ScrollSpyService` * * \@memberof ScrollSpyDirective * @return {?} */ function () { this.scrollSpySvc.addSpy(this.id, this.items); }; /** * Remove spy from list of spys when directive is destroyed * * \@memberof ScrollSpyDirective * @return {?} */ ScrollSpyDirective.prototype.ngOnDestroy = /** * Remove spy from list of spys when directive is destroyed * * \@memberof ScrollSpyDirective * @return {?} */ function () { this.scrollSpySvc.removeSpy(this.id); }; ScrollSpyDirective.decorators = [ { type: core.Directive, args: [{ selector: '[snScrollSpy]' },] }, ]; /** @nocollapse */ ScrollSpyDirective.ctorParameters = function () { return [ { type: ScrollSpyService, }, ]; }; ScrollSpyDirective.propDecorators = { "items": [{ type: core.ContentChildren, args: [ScrollSpyItemDirective,] },], "id": [{ type: core.Input },], }; return ScrollSpyDirective; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * A component to wrap section content within that will update the * `ScrollSpyService` when it's in view * * \@example * ```html * <sn-scroll-spy-section id="section1" for="foo"> * ... * </sn-scroll-spy-section> * ``` */ var ScrollSpySectionComponent = (function () { /** * Creates an instance of ScrollSpySectionComponent. * @memberof ScrollSpySectionComponent */ function ScrollSpySectionComponent(scrollSpySvc) { this.scrollSpySvc = scrollSpySvc; /** * Amount of time in ms to wait for other scroll events * before running event handler * * \@default 0 * \@memberof ScrollSpySectionComponent */ this.debounce = 0; } /** * Updates `ScrollSpy` section when element enters/leaves viewport * * \@memberof ScrollSpySectionComponent * @param {?} inViewport * @return {?} */ ScrollSpySectionComponent.prototype.onInViewportChange = /** * Updates `ScrollSpy` section when element enters/leaves viewport * * \@memberof ScrollSpySectionComponent * @param {?} inViewport * @return {?} */ function (inViewport) { this.scrollSpySvc.setSpySectionStatus(this.id, this.for, inViewport); }; ScrollSpySectionComponent.decorators = [ { type: core.Component, args: [{ selector: 'sn-scroll-spy-section', template: "<div\n class=\"sn-hidden\"\n snInViewport\n [offsetTop]=\"500\"\n (inViewportChange)=\"onInViewportChange($event)\"\n [debounce]=\"debounce\">\n</div>\n<ng-content></ng-content>\n", styles: [":host{display:block;position:relative}.sn-hidden{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0;z-index:-1}"] },] }, ]; /** @nocollapse */ ScrollSpySectionComponent.ctorParameters = function () { return [ { type: ScrollSpyService, }, ]; }; ScrollSpySectionComponent.propDecorators = { "id": [{ type: core.Input },], "for": [{ type: core.Input },], "debounce": [{ type: core.Input },], }; return ScrollSpySectionComponent; }()); /*! ***************************************************************************** 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. ***************************************************************************** */ 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} checked by tsc */ var /** @type {?} */ directives = [ScrollSpyDirective, ScrollSpyItemDirective]; var /** @type {?} */ components = [ScrollSpySectionComponent]; var /** @type {?} */ providers = [ScrollSpyService]; /** * A simple lightweight library for Angular which automatically * updates links to indicate the currently active section in the viewport * */ var ScrollSpyModule = (function () { function ScrollSpyModule() { } /** * Specify a static method for root module to ensure providers are * only provided once but allows the module to still be imported * into other modules without reproviding services. * * \@memberof ScrollSpyModule * @return {?} */ ScrollSpyModule.forRoot = /** * Specify a static method for root module to ensure providers are * only provided once but allows the module to still be imported * into other modules without reproviding services. * * \@memberof ScrollSpyModule * @return {?} */ function () { return { ngModule: ScrollSpyModule, providers: __spread(providers) }; }; ScrollSpyModule.decorators = [ { type: core.NgModule, args: [{ imports: [angularInviewport.InViewportModule], declarations: __spread(directives, components), exports: __spread(directives, components) },] }, ]; return ScrollSpyModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ exports.ScrollSpyDirective = ScrollSpyDirective; exports.ScrollSpyItemDirective = ScrollSpyItemDirective; exports.ScrollSpySectionComponent = ScrollSpySectionComponent; exports.ScrollSpyService = ScrollSpyService; exports.ScrollSpyModule = ScrollSpyModule; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicTE0OS1hbmd1bGFyLXNjcm9sbHNweS51bWQuanMubWFwIiwic291cmNlcyI6WyJuZzovL0BxMTQ5L2FuZ3VsYXItc2Nyb2xsc3B5L2FwcC9zY3JvbGwtc3B5L3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlLnRzIiwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5LXNlcnZpY2Uvc2Nyb2xsLXNweS5zZXJ2aWNlLnRzIiwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5L3Njcm9sbC1zcHkuZGlyZWN0aXZlLnRzIiwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5LXNlY3Rpb24vc2Nyb2xsLXNweS1zZWN0aW9uLmNvbXBvbmVudC50cyIsbnVsbCwibmc6Ly9AcTE0OS9hbmd1bGFyLXNjcm9sbHNweS9hcHAvc2Nyb2xsLXNweS9zY3JvbGwtc3B5Lm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIERpcmVjdGl2ZSxcclxuICBJbnB1dCxcclxuICBIb3N0QmluZGluZyxcclxuICBDaGFuZ2VEZXRlY3RvclJlZlxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuLyoqXHJcbiAqIEEgZGlyZWN0aXZlIHVzZWQgdG8gYWRkIGFuIGBhY3RpdmVgIGNsYXNzIHRvIGEgbmF2IGl0ZW1cclxuICogd2hlbiB0aGUgc2VjdGlvbiBpcyBpbiB0aGUgdmlld3BvcnRcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiA8YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uMVwiPlNlY3Rpb24gMTwvYT5cclxuICogYGBgXHJcbiAqXHJcbiAqL1xyXG5ARGlyZWN0aXZlKHtcclxuICBzZWxlY3RvcjogJ1tzblNjcm9sbFNweUl0ZW1dJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB7XHJcbiAgLyoqXHJcbiAgICogVHJ1ZSBpZiB0aGUgbmF2IGl0ZW0gaXMgdGhlIGFjdGl2ZSBpdGVtIGluIHRoZSBgaXRlbXNgIGxpc3RcclxuICAgKiBmb3IgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcy5hY3RpdmUnKSBwdWJsaWMgYWN0aXZlID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSUQgb2YgYFNjcm9sbFNweURpcmVjdGl2ZWAgaW5zdGFuY2VcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGZvcjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIEhhc2ggZm9yIHNlY3Rpb24gdG8gbGluayB0b1xyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaHJlZjogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIElmIHRydWUgbWVhbnMgdGhlIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0XHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBpblZpZXdwb3J0ID0gZmFsc2U7XHJcbiAgLyoqXHJcbiAgICogSWQgb2Ygc2VjdGlvbiB0aGF0IGxpbmtzIG5hdmlnYXRlcyB0b1xyXG4gICAqXHJcbiAgICogQHJlYWRvbmx5XHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweUl0ZW1EaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgZ2V0IHNlY3Rpb24oKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmhyZWYucmVwbGFjZSgnIycsICcnKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXHJcbiAgICovXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XHJcbiAgLyoqXHJcbiAgICogTWFudWFsbHkgdHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBkZXRlY3RDaGFuZ2VzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IEluamVjdGFibGUsIFF1ZXJ5TGlzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU3B5IH0gZnJvbSAnLi4vc2hhcmVkL3NweS5tb2RlbCc7XHJcblxyXG4vKipcclxuICogU2VydmljZSB0aGF0IHN0b3JlcyBhIGxpc3Qgb2YgYFNweWAncyBhbmQgdGhlIHN0YXRlXHJcbiAqIG9mIHRoZWlyIG5hdiBpdGVtcyBgaW5WaWV3cG9ydGAgYW5kIGBhY3RpdmVgIHN0YXRlXHJcbiAqXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSgpXHJcbmV4cG9ydCBjbGFzcyBTY3JvbGxTcHlTZXJ2aWNlIHtcclxuICAvKipcclxuICAgKiBMaXN0IG9mIGBTcHlgJ3NcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHNweXM6IFNweVtdID0gW107XHJcbiAgLyoqXHJcbiAgICogU3RvcmVzIHJlcXVlc3RzIHRvIGFkZCBpdGVtcyB0byBzcHkgd2hlbiBzcHkgaGFzbid0IGJlZW4gY3JlYXRlZFxyXG4gICAqIHlldC4gT25jZSBzcHkgaGFzIGJlZW4gYWRkZWQgdGhlbiByZXF1ZXN0IHdpbGwgYmUgbWFkZSBhZ2Fpbi5cclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIGJ1ZmZlcjogYW55W10gPSBbXTtcclxuICAvKipcclxuICAgKiBBZGQgc3B5IHRvIGxpc3Qgb2YgYHNweXNgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBhZGRTcHkoaWQ6IHN0cmluZywgaXRlbXM6IFF1ZXJ5TGlzdDxTY3JvbGxTcHlJdGVtRGlyZWN0aXZlPik6IHZvaWQge1xyXG4gICAgdGhpcy5zcHlzLnB1c2goeyBpZCwgaXRlbXMgfSk7XHJcbiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmJ1ZmZlci5maWx0ZXIoaSA9PiBpLnNweUlkID09PSBpZCk7XHJcbiAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLmZpbHRlcihpID0+IGkuc3B5SWQgIT09IGlkKTtcclxuICAgIGJ1ZmZlci5mb3JFYWNoKGkgPT5cclxuICAgICAgdGhpcy5zZXRTcHlTZWN0aW9uU3RhdHVzKGkuc2VjdGlvbklkLCBpLnNweUlkLCBpLmluVmlld3BvcnQpXHJcbiAgICApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZW1vdmUgc3B5IGZyb20gbGlzdCBvZiBgc3B5c2BcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZXJ2aWNlXHJcbiAgICovXHJcbiAgcHVibGljIHJlbW92ZVNweShpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBpID0gdGhpcy5zcHlzLmZpbmRJbmRleChzID0+IHMuaWQgPT09IGlkKTtcclxuICAgIHRoaXMuc3B5cy5zcGxpY2UoaSwgMSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFNldCB0aGUgYGluVmlld3BvcnRgIHN0YXR1cyBmb3IgYSBzcHkgaXRlbSB0aGVuIHNldHMgdGhlIGFjdGl2ZVxyXG4gICAqIHRvIHRydWUgZm9yIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBsaXN0IHRoYXQgaGFzIGBpblZpZXdwb3J0YFxyXG4gICAqIHNldCB0byB0cnVlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VydmljZVxyXG4gICAqL1xyXG4gIHB1YmxpYyBzZXRTcHlTZWN0aW9uU3RhdHVzKFxyXG4gICAgc2VjdGlvbklkOiBzdHJpbmcsXHJcbiAgICBzcHlJZDogc3RyaW5nLFxyXG4gICAgaW5WaWV3cG9ydDogYm9vbGVhblxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3Qgc3B5ID0gdGhpcy5zcHlzLmZpbmQocyA9PiBzLmlkID09PSBzcHlJZCk7XHJcbiAgICBpZiAoIXNweSkge1xyXG4gICAgICB0aGlzLmJ1ZmZlci5wdXNoKHsgc2VjdGlvbklkLCBzcHlJZCwgaW5WaWV3cG9ydCB9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgY29uc3QgaXRlbSA9IHNweS5pdGVtcy5maW5kKGkgPT4gaS5zZWN0aW9uID09PSBzZWN0aW9uSWQpO1xyXG4gICAgaWYgKCFpdGVtKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpdGVtLmluVmlld3BvcnQgPSBpblZpZXdwb3J0O1xyXG4gICAgY29uc3QgZmlyc3RJblZpZXdwb3J0ID0gc3B5Lml0ZW1zLmZpbHRlcihpID0+IGkuaW5WaWV3cG9ydClbMF07XHJcbiAgICBzcHkuaXRlbXMuZm9yRWFjaChpID0+IChpLmFjdGl2ZSA9IGZhbHNlKSk7XHJcblxyXG4gICAgaWYgKGZpcnN0SW5WaWV3cG9ydCkge1xyXG4gICAgICBmaXJzdEluVmlld3BvcnQuYWN0aXZlID0gdHJ1ZTtcclxuICAgICAgZmlyc3RJblZpZXdwb3J0LmRldGVjdENoYW5nZXMoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiaW1wb3J0IHtcclxuICBEaXJlY3RpdmUsXHJcbiAgQ29udGVudENoaWxkcmVuLFxyXG4gIFF1ZXJ5TGlzdCxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIElucHV0LFxyXG4gIE9uRGVzdHJveVxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuaW1wb3J0IHsgU2Nyb2xsU3B5SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktaXRlbS9zY3JvbGwtc3B5LWl0ZW0uZGlyZWN0aXZlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEFkZHMgYGFjdGl2ZWAgY2xhc3MgdG8gbmF2aWdhdGlvbiBsaW5rcyB3aGVuIHNlY3Rpb24gaXMgaW4gdGhlIHZpZXdwb3J0LlxyXG4gKiBVc2VkIGluIGNvbmp1Y3Rpb24gd2l0aCBgc25TY3JvbGxJdGVtYCBkaXJlY3RpdmUgd2hpY2ggc2hvdWxkIGJlIGFkZGVkXHJcbiAqIHRvIGFuY2hvciBsaW5rcyBpbiB0aGUgbmF2XHJcbiAqXHJcbiAqIEBleGFtcGxlXHJcbiAqIGBgYFxyXG4gKiA8dWwgcm9sZT1cIm5hdmlnYXRpb25cIiBzblNjcm9sbFNweSBpZD1cImZvb1wiPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb24xXCI+U2VjdGlvbiAxPC9hPjwvbGk+XHJcbiAqICA8bGk+PGEgc25TY3JvbGxTcHlJdGVtIGZvcj1cImZvb1wiIGhyZWY9XCIjc2VjdGlvbjJcIj5TZWN0aW9uIDI8L2E+PC9saT5cclxuICogIDxsaT48YSBzblNjcm9sbFNweUl0ZW0gZm9yPVwiZm9vXCIgaHJlZj1cIiNzZWN0aW9uM1wiPlNlY3Rpb24gMzwvYT48L2xpPlxyXG4gKiAgPGxpPjxhIHNuU2Nyb2xsU3B5SXRlbSBmb3I9XCJmb29cIiBocmVmPVwiI3NlY3Rpb240XCI+U2VjdGlvbiA0PC9hPjwvbGk+XHJcbiAqIDwvdWw+XHJcbiAqIGBgYFxyXG4gKlxyXG4gKi9cclxuQERpcmVjdGl2ZSh7XHJcbiAgc2VsZWN0b3I6ICdbc25TY3JvbGxTcHldJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5RGlyZWN0aXZlIGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICAvKipcclxuICAgKiBDb2xsZWN0aW9uIG9mIGBTY3JvbGxTcHlJdGVtYC4gVGhleSBhcmUgdGhlIGxpc3Qgb2ZcclxuICAgKiBuYXYgaXRlbXMuXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgQENvbnRlbnRDaGlsZHJlbihTY3JvbGxTcHlJdGVtRGlyZWN0aXZlKVxyXG4gIHB1YmxpYyBpdGVtczogUXVlcnlMaXN0PFNjcm9sbFNweUl0ZW1EaXJlY3RpdmU+O1xyXG4gIC8qKlxyXG4gICAqIElEIG9mIHNjcm9sbFNweSBpbnN0YW5jZVxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweURpcmVjdGl2ZVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBpZDogc3RyaW5nO1xyXG4gIC8qKlxyXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgU2Nyb2xsU3B5RGlyZWN0aXZlLlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBBZGRzIHNweSB0byBsaXN0IG9mIHNweXMgaW4gYFNjcm9sbFNweVNlcnZpY2VgXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5RGlyZWN0aXZlXHJcbiAgICovXHJcbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuc2Nyb2xsU3B5U3ZjLmFkZFNweSh0aGlzLmlkLCB0aGlzLml0ZW1zKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogUmVtb3ZlIHNweSBmcm9tIGxpc3Qgb2Ygc3B5cyB3aGVuIGRpcmVjdGl2ZSBpcyBkZXN0cm95ZWRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlEaXJlY3RpdmVcclxuICAgKi9cclxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5yZW1vdmVTcHkodGhpcy5pZCk7XHJcbiAgfVxyXG59XHJcbiIsImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU2Nyb2xsU3B5U2VydmljZSB9IGZyb20gJy4uL3Njcm9sbC1zcHktc2VydmljZS9zY3JvbGwtc3B5LnNlcnZpY2UnO1xyXG5cclxuLyoqXHJcbiAqIEEgY29tcG9uZW50IHRvIHdyYXAgc2VjdGlvbiBjb250ZW50IHdpdGhpbiB0aGF0IHdpbGwgdXBkYXRlIHRoZVxyXG4gKiBgU2Nyb2xsU3B5U2VydmljZWAgd2hlbiBpdCdzIGluIHZpZXdcclxuICpcclxuICogQGV4YW1wbGVcclxuICogYGBgaHRtbFxyXG4gKiAgPHNuLXNjcm9sbC1zcHktc2VjdGlvbiBpZD1cInNlY3Rpb24xXCIgZm9yPVwiZm9vXCI+XHJcbiAqICAgIC4uLlxyXG4gKiAgPC9zbi1zY3JvbGwtc3B5LXNlY3Rpb24+XHJcbiAqIGBgYFxyXG4gKi9cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdzbi1zY3JvbGwtc3B5LXNlY3Rpb24nLFxyXG4gIHRlbXBsYXRlOiBgPGRpdlxuICBjbGFzcz1cInNuLWhpZGRlblwiXG4gIHNuSW5WaWV3cG9ydFxuICBbb2Zmc2V0VG9wXT1cIjUwMFwiXG4gIChpblZpZXdwb3J0Q2hhbmdlKT1cIm9uSW5WaWV3cG9ydENoYW5nZSgkZXZlbnQpXCJcbiAgW2RlYm91bmNlXT1cImRlYm91bmNlXCI+XG48L2Rpdj5cbjxuZy1jb250ZW50PjwvbmctY29udGVudD5cbmAsXHJcbiAgc3R5bGVzOiBbYDpob3N0e2Rpc3BsYXk6YmxvY2s7cG9zaXRpb246cmVsYXRpdmV9LnNuLWhpZGRlbntib3R0b206MDtsZWZ0OjA7b3BhY2l0eTowO3Bvc2l0aW9uOmFic29sdXRlO3JpZ2h0OjA7dG9wOjA7ei1pbmRleDotMX1gXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudCB7XHJcbiAgLyoqXHJcbiAgICogSWRlbnRpZmllcyB0aGUgc2VjdGlvblxyXG4gICAqXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBASW5wdXQoKSBwdWJsaWMgaWQ6IHN0cmluZztcclxuICAvKipcclxuICAgKiBTcGVjaWZpZXMgd2hpY2ggYFNjcm9sbFNweWAgaW5zdGFuY2UgdG8gdXBkYXRlXHJcbiAgICpcclxuICAgKiBAbWVtYmVyb2YgU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudFxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHB1YmxpYyBmb3I6IHN0cmluZztcclxuICAvKipcclxuICAgKiBBbW91bnQgb2YgdGltZSBpbiBtcyB0byB3YWl0IGZvciBvdGhlciBzY3JvbGwgZXZlbnRzXHJcbiAgICogYmVmb3JlIHJ1bm5pbmcgZXZlbnQgaGFuZGxlclxyXG4gICAqXHJcbiAgICogQGRlZmF1bHQgMFxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgQElucHV0KCkgcHVibGljIGRlYm91bmNlID0gMDtcclxuICAvKipcclxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnQuXHJcbiAgICogQG1lbWJlcm9mIFNjcm9sbFNweVNlY3Rpb25Db21wb25lbnRcclxuICAgKi9cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNjcm9sbFNweVN2YzogU2Nyb2xsU3B5U2VydmljZSkge31cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGBTY3JvbGxTcHlgIHNlY3Rpb24gd2hlbiBlbGVtZW50IGVudGVycy9sZWF2ZXMgdmlld3BvcnRcclxuICAgKlxyXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50XHJcbiAgICovXHJcbiAgcHVibGljIG9uSW5WaWV3cG9ydENoYW5nZShpblZpZXdwb3J0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLnNjcm9sbFNweVN2Yy5zZXRTcHlTZWN0aW9uU3RhdHVzKHRoaXMuaWQsIHRoaXMuZm9yLCBpblZpZXdwb3J0KTtcclxuICB9XHJcbn1cclxuIiwiLyohICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxyXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpOyB5b3UgbWF5IG5vdCB1c2VcclxudGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGVcclxuTGljZW5zZSBhdCBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcclxuXHJcblRISVMgQ09ERSBJUyBQUk9WSURFRCBPTiBBTiAqQVMgSVMqIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTllcclxuS0lORCwgRUlUSEVSIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiBBTlkgSU1QTElFRFxyXG5XQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgVElUTEUsIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLFxyXG5NRVJDSEFOVEFCTElUWSBPUiBOT04tSU5GUklOR0VNRU5ULlxyXG5cclxuU2VlIHRoZSBBcGFjaGUgVmVyc2lvbiAyLjAgTGljZW5zZSBmb3Igc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zXHJcbmFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UgKi9cclxuXHJcbnZhciBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XHJcbiAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChiLmhhc093blByb3BlcnR5KHApKSBkW3BdID0gYltwXTsgfTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxuICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxyXG4gICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xyXG59XHJcblxyXG5leHBvcnQgdmFyIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICBzID0gYXJndW1lbnRzW2ldO1xyXG4gICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdDtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVzdChzLCBlKSB7XHJcbiAgICB2YXIgdCA9IHt9O1xyXG4gICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApICYmIGUuaW5kZXhPZihwKSA8IDApXHJcbiAgICAgICAgdFtwXSA9IHNbcF07XHJcbiAgICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIHAgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHMpOyBpIDwgcC5sZW5ndGg7IGkrKykgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDApXHJcbiAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSkge1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0Lm1ldGFkYXRhID09PSBcImZ1bmN0aW9uXCIpIHJldHVybiBSZWZsZWN0Lm1ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXRlcih0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUocmVzdWx0LnZhbHVlKTsgfSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcclxuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XHJcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xyXG4gICAgICAgIHdoaWxlIChfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSB5W29wWzBdICYgMiA/IFwicmV0dXJuXCIgOiBvcFswXSA/IFwidGhyb3dcIiA6IFwibmV4dFwiXSkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbMCwgdC52YWx1ZV07XHJcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxyXG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19leHBvcnRTdGFyKG0sIGV4cG9ydHMpIHtcclxuICAgIGZvciAodmFyIHAgaW4gbSkgaWYgKCFleHBvcnRzLmhhc093blByb3BlcnR5KHApKSBleHBvcnRzW3BdID0gbVtwXTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcclxuICAgIHZhciBtID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIG9bU3ltYm9sLml0ZXJhdG9yXSwgaSA9IDA7XHJcbiAgICBpZiAobSkgcmV0dXJuIG0uY2FsbChvKTtcclxuICAgIHJldHVybiB7XHJcbiAgICAgICAgbmV4dDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xyXG4gICAgICAgICAgICByZXR1cm4geyB2YWx1ZTogbyAmJiBvW2krK10sIGRvbmU6ICFvIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fcmVhZChvLCBuKSB7XHJcbiAgICB2YXIgbSA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvW1N5bWJvbC5pdGVyYXRvcl07XHJcbiAgICBpZiAoIW0pIHJldHVybiBvO1xyXG4gICAgdmFyIGkgPSBtLmNhbGwobyksIHIsIGFyID0gW10sIGU7XHJcbiAgICB0cnkge1xyXG4gICAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGVycm9yKSB7IGUgPSB7IGVycm9yOiBlcnJvciB9OyB9XHJcbiAgICBmaW5hbGx5IHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBpZiAociAmJiAhci5kb25lICYmIChtID0gaVtcInJldHVyblwiXSkpIG0uY2FsbChpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZmluYWxseSB7IGlmIChlKSB0aHJvdyBlLmVycm9yOyB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYXI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZCgpIHtcclxuICAgIGZvciAodmFyIGFyID0gW10sIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKVxyXG4gICAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcclxuICAgIHJldHVybiBhcjtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xyXG4gICAgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jR2VuZXJhdG9yKHRoaXNBcmcsIF9hcmd1bWVudHMsIGdlbmVyYXRvcikge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cclxuICAgIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cclxuICAgIGZ1bmN0aW9uIHN0ZXAocikgeyByLnZhbHVlIGluc3RhbmNlb2YgX19hd2FpdCA/IFByb21pc2UucmVzb2x2ZShyLnZhbHVlLnYpLnRoZW4oZnVsZmlsbCwgcmVqZWN0KSA6IHNldHRsZShxWzBdWzJdLCByKTsgIH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlmIChvW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogbiA9PT0gXCJyZXR1cm5cIiB9IDogZiA/IGYodikgOiB2OyB9OyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcclxuICAgIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICB2YXIgbSA9IG9bU3ltYm9sLmFzeW5jSXRlcmF0b3JdO1xyXG4gICAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiB0eXBlb2YgX192YWx1ZXMgPT09IFwiZnVuY3Rpb25cIiA/IF9fdmFsdWVzKG8pIDogb1tTeW1ib2wuaXRlcmF0b3JdKCk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcbiIsImltcG9ydCB7IE5nTW9kdWxlLCBNb2R1bGVXaXRoUHJvdmlkZXJzLCBQcm92aWRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSW5WaWV3cG9ydE1vZHVsZSB9IGZyb20gJ0BxMTQ5L2FuZ3VsYXItaW52aWV3cG9ydCc7XG5cbmltcG9ydCB7IFNjcm9sbFNweURpcmVjdGl2ZSB9IGZyb20gJy4vc2Nyb2xsLXNweS9zY3JvbGwtc3B5LmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBTY3JvbGxTcHlTZWN0aW9uQ29tcG9uZW50IH0gZnJvbSAnLi9zY3JvbGwtc3B5LXNlY3Rpb24vc2Nyb2xsLXNweS1zZWN0aW9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlIH0gZnJvbSAnLi9zY3JvbGwtc3B5LWl0ZW0vc2Nyb2xsLXNweS1pdGVtLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBTY3JvbGxTcHlTZXJ2aWNlIH0gZnJvbSAnLi9zY3JvbGwtc3B5LXNlcnZpY2Uvc2Nyb2xsLXNweS5zZXJ2aWNlJztcblxuY29uc3QgZGlyZWN0aXZlczogYW55W10gPSBbU2Nyb2xsU3B5RGlyZWN0aXZlLCBTY3JvbGxTcHlJdGVtRGlyZWN0aXZlXTtcblxuY29uc3QgY29tcG9uZW50czogYW55W10gPSBbU2Nyb2xsU3B5U2VjdGlvbkNvbXBvbmVudF07XG5cbmNvbnN0IHByb3ZpZGVyczogUHJvdmlkZXJbXSA9IFtTY3JvbGxTcHlTZXJ2aWNlXTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsaWdodHdlaWdodCBsaWJyYXJ5IGZvciBBbmd1bGFyIHdoaWNoIGF1dG9tYXRpY2FsbHlcbiAqIHVwZGF0ZXMgbGlua3MgdG8gaW5kaWNhdGUgdGhlIGN1cnJlbnRseSBhY3RpdmUgc2VjdGlvbiBpbiB0aGUgdmlld3BvcnRcbiAqXG4gKi9cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtJblZpZXdwb3J0TW9kdWxlXSxcbiAgZGVjbGFyYXRpb25zOiBbLi4uZGlyZWN0aXZlcywgLi4uY29tcG9uZW50c10sXG4gIGV4cG9ydHM6IFsuLi5kaXJlY3RpdmVzLCAuLi5jb21wb25lbnRzXVxufSlcbmV4cG9ydCBjbGFzcyBTY3JvbGxTcHlNb2R1bGUge1xuICAvKipcbiAgICogU3BlY2lmeSBhIHN0YXRpYyBtZXRob2QgZm9yIHJvb3QgbW9kdWxlIHRvIGVuc3VyZSBwcm92aWRlcnMgYXJlXG4gICAqIG9ubHkgcHJvdmlkZWQgb25jZSBidXQgYWxsb3dzIHRoZSBtb2R1bGUgdG8gc3RpbGwgYmUgaW1wb3J0ZWRcbiAgICogaW50byBvdGhlciBtb2R1bGVzIHdpdGhvdXQgcmVwcm92aWRpbmcgc2VydmljZXMuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBTY3JvbGxTcHlNb2R1bGVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZm9yUm9vdCgpOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgbmdNb2R1bGU6IFNjcm9sbFNweU1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogWy4uLnByb3ZpZGVyc11cbiAgICB9O1xuICB9XG59XG4iXSwibmFtZXMiOlsiRGlyZWN0aXZlIiwiQ2hhbmdlRGV0ZWN0b3JSZWYiLCJIb3N0QmluZGluZyIsIklucHV0IiwiSW5qZWN0YWJsZSIsIkNvbnRlbnRDaGlsZHJlbiIsIkNvbXBvbmVudCIsIk5nTW9kdWxlIiwiSW5WaWV3cG9ydE1vZHVsZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7UUEyREUsZ0NBQW9CLEtBQXdCO1lBQXhCLFVBQUssR0FBTCxLQUFLLENBQW1COzs7Ozs7OzBCQWhDQyxLQUFLOzs7Ozs7OEJBa0I5QixLQUFLO1NBY3VCOzhCQVByQywyQ0FBTzs7Ozs7Ozs7Z0JBQ2hCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDOzs7Ozs7Ozs7OztRQVk3Qiw4Q0FBYTs7Ozs7OztnQkFDbEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQzs7O29CQWpEOUJBLGNBQVMsU0FBQzt3QkFDVCxRQUFRLEVBQUUsbUJBQW1CO3FCQUM5Qjs7Ozs7d0JBZkNDLHNCQUFpQjs7OzsrQkF1QmhCQyxnQkFBVyxTQUFDLGNBQWM7NEJBTTFCQyxVQUFLOzZCQU1MQSxVQUFLOztxQ0F2Q1I7Ozs7Ozs7QUNBQTs7Ozs7Ozs7Ozs7O3dCQWlCdUIsRUFBRTs7Ozs7OzswQkFPQSxFQUFFOzs7Ozs7Ozs7O1FBTWxCLGlDQUFN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