contextMenuContent.component.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import * as tslib_1 from "tslib";
  6. import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
  7. import { OverlayRef } from '@angular/cdk/overlay';
  8. import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Inject, Input, Optional, Output, QueryList, ViewChild, ViewChildren } from '@angular/core';
  9. import { Subscription } from 'rxjs';
  10. import { CONTEXT_MENU_OPTIONS } from './contextMenu.tokens';
  11. /**
  12. * @record
  13. */
  14. export function ILinkConfig() { }
  15. if (false) {
  16. /** @type {?} */
  17. ILinkConfig.prototype.click;
  18. /** @type {?|undefined} */
  19. ILinkConfig.prototype.enabled;
  20. /** @type {?} */
  21. ILinkConfig.prototype.html;
  22. }
  23. /** @type {?} */
  24. var ARROW_LEFT_KEYCODE = 37;
  25. var ContextMenuContentComponent = /** @class */ (function () {
  26. function ContextMenuContentComponent(changeDetector, elementRef, options) {
  27. this.changeDetector = changeDetector;
  28. this.elementRef = elementRef;
  29. this.options = options;
  30. this.menuItems = [];
  31. this.isLeaf = false;
  32. this.execute = new EventEmitter();
  33. this.openSubMenu = new EventEmitter();
  34. this.closeLeafMenu = new EventEmitter();
  35. this.closeAllMenus = new EventEmitter();
  36. this.autoFocus = false;
  37. this.useBootstrap4 = false;
  38. this.subscription = new Subscription();
  39. if (options) {
  40. this.autoFocus = options.autoFocus;
  41. this.useBootstrap4 = options.useBootstrap4;
  42. }
  43. }
  44. /**
  45. * @return {?}
  46. */
  47. ContextMenuContentComponent.prototype.ngOnInit = /**
  48. * @return {?}
  49. */
  50. function () {
  51. var _this = this;
  52. this.menuItems.forEach((/**
  53. * @param {?} menuItem
  54. * @return {?}
  55. */
  56. function (menuItem) {
  57. menuItem.currentItem = _this.item;
  58. _this.subscription.add(menuItem.execute.subscribe((/**
  59. * @param {?} event
  60. * @return {?}
  61. */
  62. function (event) {
  63. return _this.execute.emit(tslib_1.__assign({}, event, { menuItem: menuItem }));
  64. })));
  65. }));
  66. /** @type {?} */
  67. var queryList = new QueryList();
  68. queryList.reset(this.menuItems);
  69. this._keyManager = new ActiveDescendantKeyManager(queryList).withWrap();
  70. };
  71. /**
  72. * @return {?}
  73. */
  74. ContextMenuContentComponent.prototype.ngAfterViewInit = /**
  75. * @return {?}
  76. */
  77. function () {
  78. var _this = this;
  79. if (this.autoFocus) {
  80. setTimeout((/**
  81. * @return {?}
  82. */
  83. function () { return _this.focus(); }));
  84. }
  85. this.overlay.updatePosition();
  86. };
  87. /**
  88. * @return {?}
  89. */
  90. ContextMenuContentComponent.prototype.ngOnDestroy = /**
  91. * @return {?}
  92. */
  93. function () {
  94. this.subscription.unsubscribe();
  95. };
  96. /**
  97. * @return {?}
  98. */
  99. ContextMenuContentComponent.prototype.focus = /**
  100. * @return {?}
  101. */
  102. function () {
  103. if (this.autoFocus) {
  104. this.menuElement.nativeElement.focus();
  105. }
  106. };
  107. /**
  108. * @param {?} $event
  109. * @return {?}
  110. */
  111. ContextMenuContentComponent.prototype.stopEvent = /**
  112. * @param {?} $event
  113. * @return {?}
  114. */
  115. function ($event) {
  116. $event.stopPropagation();
  117. };
  118. /**
  119. * @param {?} menuItem
  120. * @return {?}
  121. */
  122. ContextMenuContentComponent.prototype.isMenuItemEnabled = /**
  123. * @param {?} menuItem
  124. * @return {?}
  125. */
  126. function (menuItem) {
  127. return this.evaluateIfFunction(menuItem && menuItem.enabled);
  128. };
  129. /**
  130. * @param {?} menuItem
  131. * @return {?}
  132. */
  133. ContextMenuContentComponent.prototype.isMenuItemVisible = /**
  134. * @param {?} menuItem
  135. * @return {?}
  136. */
  137. function (menuItem) {
  138. return this.evaluateIfFunction(menuItem && menuItem.visible);
  139. };
  140. /**
  141. * @param {?} value
  142. * @return {?}
  143. */
  144. ContextMenuContentComponent.prototype.evaluateIfFunction = /**
  145. * @param {?} value
  146. * @return {?}
  147. */
  148. function (value) {
  149. if (value instanceof Function) {
  150. return value(this.item);
  151. }
  152. return value;
  153. };
  154. /**
  155. * @param {?} link
  156. * @return {?}
  157. */
  158. ContextMenuContentComponent.prototype.isDisabled = /**
  159. * @param {?} link
  160. * @return {?}
  161. */
  162. function (link) {
  163. return link.enabled && !link.enabled(this.item);
  164. };
  165. /**
  166. * @param {?} event
  167. * @return {?}
  168. */
  169. ContextMenuContentComponent.prototype.onKeyEvent = /**
  170. * @param {?} event
  171. * @return {?}
  172. */
  173. function (event) {
  174. if (!this.isLeaf) {
  175. return;
  176. }
  177. this._keyManager.onKeydown(event);
  178. };
  179. /**
  180. * @param {?=} event
  181. * @return {?}
  182. */
  183. ContextMenuContentComponent.prototype.keyboardOpenSubMenu = /**
  184. * @param {?=} event
  185. * @return {?}
  186. */
  187. function (event) {
  188. if (!this.isLeaf) {
  189. return;
  190. }
  191. this.cancelEvent(event);
  192. /** @type {?} */
  193. var menuItem = this.menuItems[this._keyManager.activeItemIndex];
  194. if (menuItem) {
  195. this.onOpenSubMenu(menuItem);
  196. }
  197. };
  198. /**
  199. * @param {?=} event
  200. * @return {?}
  201. */
  202. ContextMenuContentComponent.prototype.keyboardMenuItemSelect = /**
  203. * @param {?=} event
  204. * @return {?}
  205. */
  206. function (event) {
  207. if (!this.isLeaf) {
  208. return;
  209. }
  210. this.cancelEvent(event);
  211. /** @type {?} */
  212. var menuItem = this.menuItems[this._keyManager.activeItemIndex];
  213. if (menuItem) {
  214. this.onMenuItemSelect(menuItem, event);
  215. }
  216. };
  217. /**
  218. * @param {?} event
  219. * @return {?}
  220. */
  221. ContextMenuContentComponent.prototype.onCloseLeafMenu = /**
  222. * @param {?} event
  223. * @return {?}
  224. */
  225. function (event) {
  226. if (!this.isLeaf) {
  227. return;
  228. }
  229. this.cancelEvent(event);
  230. this.closeLeafMenu.emit({
  231. exceptRootMenu: event.keyCode === ARROW_LEFT_KEYCODE,
  232. event: event
  233. });
  234. };
  235. /**
  236. * @param {?} event
  237. * @return {?}
  238. */
  239. ContextMenuContentComponent.prototype.closeMenu = /**
  240. * @param {?} event
  241. * @return {?}
  242. */
  243. function (event) {
  244. if (event.type === 'click' && event.button === 2) {
  245. return;
  246. }
  247. this.closeAllMenus.emit({ event: event });
  248. };
  249. /**
  250. * @param {?} menuItem
  251. * @param {?=} event
  252. * @return {?}
  253. */
  254. ContextMenuContentComponent.prototype.onOpenSubMenu = /**
  255. * @param {?} menuItem
  256. * @param {?=} event
  257. * @return {?}
  258. */
  259. function (menuItem, event) {
  260. /** @type {?} */
  261. var anchorElementRef = this.menuItemElements.toArray()[this._keyManager.activeItemIndex];
  262. /** @type {?} */
  263. var anchorElement = anchorElementRef && anchorElementRef.nativeElement;
  264. this.openSubMenu.emit({
  265. anchorElement: anchorElement,
  266. contextMenu: menuItem.subMenu,
  267. event: event,
  268. item: this.item,
  269. parentContextMenu: this
  270. });
  271. };
  272. /**
  273. * @param {?} menuItem
  274. * @param {?} event
  275. * @return {?}
  276. */
  277. ContextMenuContentComponent.prototype.onMenuItemSelect = /**
  278. * @param {?} menuItem
  279. * @param {?} event
  280. * @return {?}
  281. */
  282. function (menuItem, event) {
  283. event.preventDefault();
  284. event.stopPropagation();
  285. this.onOpenSubMenu(menuItem, event);
  286. if (!menuItem.subMenu) {
  287. menuItem.triggerExecute(this.item, event);
  288. }
  289. };
  290. /**
  291. * @private
  292. * @param {?} event
  293. * @return {?}
  294. */
  295. ContextMenuContentComponent.prototype.cancelEvent = /**
  296. * @private
  297. * @param {?} event
  298. * @return {?}
  299. */
  300. function (event) {
  301. if (!event) {
  302. return;
  303. }
  304. /** @type {?} */
  305. var target = event.target;
  306. if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(target.tagName) > -1 ||
  307. target.isContentEditable) {
  308. return;
  309. }
  310. event.preventDefault();
  311. event.stopPropagation();
  312. };
  313. ContextMenuContentComponent.decorators = [
  314. { type: Component, args: [{
  315. selector: 'context-menu-content',
  316. template: "\n <div\n class=\"dropdown open show ngx-contextmenu\"\n [ngClass]=\"menuClass\"\n tabindex=\"0\"\n >\n <ul\n #menu\n class=\"dropdown-menu show\"\n style=\"position: static; float: none;\"\n tabindex=\"0\"\n >\n <li\n #li\n *ngFor=\"let menuItem of menuItems; let i = index\"\n [class.disabled]=\"!isMenuItemEnabled(menuItem)\"\n [class.divider]=\"menuItem.divider\"\n [class.dropdown-divider]=\"useBootstrap4 && menuItem.divider\"\n [class.active]=\"menuItem.isActive && isMenuItemEnabled(menuItem)\"\n [attr.role]=\"menuItem.divider ? 'separator' : undefined\"\n >\n <a\n *ngIf=\"!menuItem.divider && !menuItem.passive\"\n href\n [class.dropdown-item]=\"useBootstrap4\"\n [class.active]=\"menuItem.isActive && isMenuItemEnabled(menuItem)\"\n [class.disabled]=\"useBootstrap4 && !isMenuItemEnabled(menuItem)\"\n [class.hasSubMenu]=\"!!menuItem.subMenu\"\n (click)=\"onMenuItemSelect(menuItem, $event)\"\n (mouseenter)=\"onOpenSubMenu(menuItem, $event)\"\n >\n <ng-template\n [ngTemplateOutlet]=\"menuItem.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-template>\n </a>\n\n <span\n (click)=\"stopEvent($event)\"\n (contextmenu)=\"stopEvent($event)\"\n class=\"passive\"\n *ngIf=\"!menuItem.divider && menuItem.passive\"\n [class.dropdown-item]=\"useBootstrap4\"\n [class.disabled]=\"useBootstrap4 && !isMenuItemEnabled(menuItem)\"\n >\n <ng-template\n [ngTemplateOutlet]=\"menuItem.template\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n ></ng-template>\n </span>\n </li>\n </ul>\n </div>\n ",
  317. styles: ["\n .passive {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n white-space: nowrap;\n }\n .hasSubMenu:before {\n content: '\u25B6';\n float: right;\n }\n "]
  318. }] }
  319. ];
  320. /** @nocollapse */
  321. ContextMenuContentComponent.ctorParameters = function () { return [
  322. { type: ChangeDetectorRef },
  323. { type: ElementRef },
  324. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [CONTEXT_MENU_OPTIONS,] }] }
  325. ]; };
  326. ContextMenuContentComponent.propDecorators = {
  327. menuItems: [{ type: Input }],
  328. item: [{ type: Input }],
  329. event: [{ type: Input }],
  330. parentContextMenu: [{ type: Input }],
  331. menuClass: [{ type: Input }],
  332. overlay: [{ type: Input }],
  333. isLeaf: [{ type: Input }],
  334. execute: [{ type: Output }],
  335. openSubMenu: [{ type: Output }],
  336. closeLeafMenu: [{ type: Output }],
  337. closeAllMenus: [{ type: Output }],
  338. menuElement: [{ type: ViewChild, args: ['menu', { static: true },] }],
  339. menuItemElements: [{ type: ViewChildren, args: ['li',] }],
  340. onKeyEvent: [{ type: HostListener, args: ['window:keydown.ArrowDown', ['$event'],] }, { type: HostListener, args: ['window:keydown.ArrowUp', ['$event'],] }],
  341. keyboardOpenSubMenu: [{ type: HostListener, args: ['window:keydown.ArrowRight', ['$event'],] }],
  342. keyboardMenuItemSelect: [{ type: HostListener, args: ['window:keydown.Enter', ['$event'],] }, { type: HostListener, args: ['window:keydown.Space', ['$event'],] }],
  343. onCloseLeafMenu: [{ type: HostListener, args: ['window:keydown.Escape', ['$event'],] }, { type: HostListener, args: ['window:keydown.ArrowLeft', ['$event'],] }],
  344. closeMenu: [{ type: HostListener, args: ['document:click', ['$event'],] }, { type: HostListener, args: ['document:contextmenu', ['$event'],] }]
  345. };
  346. return ContextMenuContentComponent;
  347. }());
  348. export { ContextMenuContentComponent };
  349. if (false) {
  350. /** @type {?} */
  351. ContextMenuContentComponent.prototype.menuItems;
  352. /** @type {?} */
  353. ContextMenuContentComponent.prototype.item;
  354. /** @type {?} */
  355. ContextMenuContentComponent.prototype.event;
  356. /** @type {?} */
  357. ContextMenuContentComponent.prototype.parentContextMenu;
  358. /** @type {?} */
  359. ContextMenuContentComponent.prototype.menuClass;
  360. /** @type {?} */
  361. ContextMenuContentComponent.prototype.overlay;
  362. /** @type {?} */
  363. ContextMenuContentComponent.prototype.isLeaf;
  364. /** @type {?} */
  365. ContextMenuContentComponent.prototype.execute;
  366. /** @type {?} */
  367. ContextMenuContentComponent.prototype.openSubMenu;
  368. /** @type {?} */
  369. ContextMenuContentComponent.prototype.closeLeafMenu;
  370. /** @type {?} */
  371. ContextMenuContentComponent.prototype.closeAllMenus;
  372. /** @type {?} */
  373. ContextMenuContentComponent.prototype.menuElement;
  374. /** @type {?} */
  375. ContextMenuContentComponent.prototype.menuItemElements;
  376. /** @type {?} */
  377. ContextMenuContentComponent.prototype.autoFocus;
  378. /** @type {?} */
  379. ContextMenuContentComponent.prototype.useBootstrap4;
  380. /**
  381. * @type {?}
  382. * @private
  383. */
  384. ContextMenuContentComponent.prototype._keyManager;
  385. /**
  386. * @type {?}
  387. * @private
  388. */
  389. ContextMenuContentComponent.prototype.subscription;
  390. /**
  391. * @type {?}
  392. * @private
  393. */
  394. ContextMenuContentComponent.prototype.changeDetector;
  395. /**
  396. * @type {?}
  397. * @private
  398. */
  399. ContextMenuContentComponent.prototype.elementRef;
  400. /**
  401. * @type {?}
  402. * @private
  403. */
  404. ContextMenuContentComponent.prototype.options;
  405. }
  406. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dE1lbnVDb250ZW50LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1jb250ZXh0bWVudS8iLCJzb3VyY2VzIjpbImxpYi9jb250ZXh0TWVudUNvbnRlbnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDL0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xELE9BQU8sRUFFTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBR0wsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNULFlBQVksRUFDYixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBT3BDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7O0FBRTVELGlDQUlDOzs7SUFIQyw0QkFBZ0Q7O0lBQ2hELDhCQUFpQzs7SUFDakMsMkJBQTRCOzs7SUFHeEIsa0JBQWtCLEdBQUcsRUFBRTtBQUU3QjtJQXVHRSxxQ0FDVSxjQUFpQyxFQUNqQyxVQUFzQixFQUd0QixPQUE0QjtRQUo1QixtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUFDakMsZUFBVSxHQUFWLFVBQVUsQ0FBWTtRQUd0QixZQUFPLEdBQVAsT0FBTyxDQUFxQjtRQWpDdEIsY0FBUyxHQUErQixFQUFFLENBQUM7UUFNM0MsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUNkLFlBQU8sR0FJbkIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNQLGdCQUFXLEdBRXhCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDTixrQkFBYSxHQUUxQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ04sa0JBQWEsR0FFekIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUlqQixjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLGtCQUFhLEdBQUcsS0FBSyxDQUFDO1FBRXJCLGlCQUFZLEdBQWlCLElBQUksWUFBWSxFQUFFLENBQUM7UUFRdEQsSUFBSSxPQUFPLEVBQUU7WUFDWCxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDbkMsSUFBSSxDQUFDLGFBQWEsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDO1NBQzVDO0lBQ0gsQ0FBQzs7OztJQUVELDhDQUFROzs7SUFBUjtRQUFBLGlCQWNDO1FBYkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPOzs7O1FBQUMsVUFBQSxRQUFRO1lBQzdCLFFBQVEsQ0FBQyxXQUFXLEdBQUcsS0FBSSxDQUFDLElBQUksQ0FBQztZQUNqQyxLQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FDbkIsUUFBUSxDQUFDLE9BQU8sQ0FBQyxTQUFTOzs7O1lBQUMsVUFBQSxLQUFLO2dCQUM5QixPQUFBLEtBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxzQkFBTSxLQUFLLElBQUUsUUFBUSxVQUFBLElBQUc7WUFBekMsQ0FBeUMsRUFDMUMsQ0FDRixDQUFDO1FBQ0osQ0FBQyxFQUFDLENBQUM7O1lBQ0csU0FBUyxHQUFHLElBQUksU0FBUyxFQUE0QjtRQUMzRCxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksMEJBQTBCLENBQy9DLFNBQVMsQ0FDVixDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2YsQ0FBQzs7OztJQUVELHFEQUFlOzs7SUFBZjtRQUFBLGlCQUtDO1FBSkMsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLFVBQVU7OztZQUFDLGNBQU0sT0FBQSxLQUFJLENBQUMsS0FBSyxFQUFFLEVBQVosQ0FBWSxFQUFDLENBQUM7U0FDaEM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ2hDLENBQUM7Ozs7SUFFRCxpREFBVzs7O0lBQVg7UUFDRSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2xDLENBQUM7Ozs7SUFFRCwyQ0FBSzs7O0lBQUw7UUFDRSxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDbEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDeEM7SUFDSCxDQUFDOzs7OztJQUVELCtDQUFTOzs7O0lBQVQsVUFBVSxNQUFrQjtRQUMxQixNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDM0IsQ0FBQzs7Ozs7SUFFTSx1REFBaUI7Ozs7SUFBeEIsVUFBeUIsUUFBa0M7UUFDekQsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMvRCxDQUFDOzs7OztJQUVNLHVEQUFpQjs7OztJQUF4QixVQUF5QixRQUFrQztRQUN6RCxPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9ELENBQUM7Ozs7O0lBRU0sd0RBQWtCOzs7O0lBQXpCLFVBQTBCLEtBQVU7UUFDbEMsSUFBSSxLQUFLLFlBQVksUUFBUSxFQUFFO1lBQzdCLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN6QjtRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzs7Ozs7SUFFTSxnREFBVTs7OztJQUFqQixVQUFrQixJQUFpQjtRQUNqQyxPQUFPLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsRCxDQUFDOzs7OztJQUlNLGdEQUFVOzs7O0lBRmpCLFVBRWtCLEtBQW9CO1FBQ3BDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLENBQUM7Ozs7O0lBR00seURBQW1COzs7O0lBRDFCLFVBQzJCLEtBQXFCO1FBQzlDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7O1lBQ2xCLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDO1FBQ2pFLElBQUksUUFBUSxFQUFFO1lBQ1osSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUM5QjtJQUNILENBQUM7Ozs7O0lBSU0sNERBQXNCOzs7O0lBRjdCLFVBRThCLEtBQXFCO1FBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFO1lBQ2hCLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7O1lBQ2xCLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDO1FBQ2pFLElBQUksUUFBUSxFQUFFO1lBQ1osSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN4QztJQUNILENBQUM7Ozs7O0lBSU0scURBQWU7Ozs7SUFGdEIsVUFFdUIsS0FBb0I7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsT0FBTztTQUNSO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQztZQUN0QixjQUFjLEVBQUUsS0FBSyxDQUFDLE9BQU8sS0FBSyxrQkFBa0I7WUFDcEQsS0FBSyxPQUFBO1NBQ04sQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7Ozs7SUFJTSwrQ0FBUzs7OztJQUZoQixVQUVpQixLQUFpQjtRQUNoQyxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ2hELE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxPQUFBLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7Ozs7OztJQUVNLG1EQUFhOzs7OztJQUFwQixVQUNFLFFBQWtDLEVBQ2xDLEtBQWtDOztZQUU1QixnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLENBQ3RELElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUNqQzs7WUFDSyxhQUFhLEdBQUcsZ0JBQWdCLElBQUksZ0JBQWdCLENBQUMsYUFBYTtRQUN4RSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztZQUNwQixhQUFhLGVBQUE7WUFDYixXQUFXLEVBQUUsUUFBUSxDQUFDLE9BQU87WUFDN0IsS0FBSyxPQUFBO1lBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO1lBQ2YsaUJBQWlCLEVBQUUsSUFBSTtTQUN4QixDQUFDLENBQUM7SUFDTCxDQUFDOzs7Ozs7SUFFTSxzREFBZ0I7Ozs7O0lBQXZCLFVBQ0UsUUFBa0MsRUFDbEMsS0FBaUM7UUFFakMsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRTtZQUNyQixRQUFRLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDM0M7SUFDSCxDQUFDOzs7Ozs7SUFFTyxpREFBVzs7Ozs7SUFBbkIsVUFBb0IsS0FBSztRQUN2QixJQUFJLENBQUMsS0FBSyxFQUFFO1lBQ1YsT0FBTztTQUNSOztZQUVLLE1BQU0sR0FBZ0IsS0FBSyxDQUFDLE1BQU07UUFDeEMsSUFDRSxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUQsTUFBTSxDQUFDLGlCQUFpQixFQUN4QjtZQUNBLE9BQU87U0FDUjtRQUVELEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDMUIsQ0FBQzs7Z0JBaFJGLFNBQVMsU0FBQztvQkFDVCxRQUFRLEVBQUUsc0JBQXNCO29CQWlCaEMsUUFBUSxFQUFFLCs3REFxRFQ7NkJBcEVDLDJTQWFDO2lCQXdESjs7OztnQkF4R0MsaUJBQWlCO2dCQUVqQixVQUFVO2dEQXdJUCxRQUFRLFlBQ1IsTUFBTSxTQUFDLG9CQUFvQjs7OzRCQWhDN0IsS0FBSzt1QkFDTCxLQUFLO3dCQUNMLEtBQUs7b0NBQ0wsS0FBSzs0QkFDTCxLQUFLOzBCQUNMLEtBQUs7eUJBQ0wsS0FBSzswQkFDTCxNQUFNOzhCQUtOLE1BQU07Z0NBR04sTUFBTTtnQ0FHTixNQUFNOzhCQUdOLFNBQVMsU0FBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO21DQUNsQyxZQUFZLFNBQUMsSUFBSTs2QkEyRWpCLFlBQVksU0FBQywwQkFBMEIsRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUNuRCxZQUFZLFNBQUMsd0JBQXdCLEVBQUUsQ0FBQyxRQUFRLENBQUM7c0NBUWpELFlBQVksU0FBQywyQkFBMkIsRUFBRSxDQUFDLFFBQVEsQ0FBQzt5Q0FZcEQsWUFBWSxTQUFDLHNCQUFzQixFQUFFLENBQUMsUUFBUSxDQUFDLGNBQy9DLFlBQVksU0FBQyxzQkFBc0IsRUFBRSxDQUFDLFFBQVEsQ0FBQztrQ0FZL0MsWUFBWSxTQUFDLHVCQUF1QixFQUFFLENBQUMsUUFBUSxDQUFDLGNBQ2hELFlBQVksU0FBQywwQkFBMEIsRUFBRSxDQUFDLFFBQVEsQ0FBQzs0QkFZbkQsWUFBWSxTQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDLGNBQ3pDLFlBQVksU0FBQyxzQkFBc0IsRUFBRSxDQUFDLFFBQVEsQ0FBQzs7SUFxRGxELGtDQUFDO0NBQUEsQUFqUkQsSUFpUkM7U0F4TVksMkJBQTJCOzs7SUFFdEMsZ0RBQTJEOztJQUMzRCwyQ0FBMEI7O0lBQzFCLDRDQUFrRDs7SUFDbEQsd0RBQStEOztJQUMvRCxnREFBa0M7O0lBQ2xDLDhDQUFvQzs7SUFDcEMsNkNBQStCOztJQUMvQiw4Q0FJd0I7O0lBQ3hCLGtEQUV1Qjs7SUFDdkIsb0RBRXVCOztJQUN2QixvREFFd0I7O0lBQ3hCLGtEQUFvRTs7SUFDcEUsdURBQW1FOztJQUVuRSxnREFBeUI7O0lBQ3pCLG9EQUE2Qjs7Ozs7SUFDN0Isa0RBQTBFOzs7OztJQUMxRSxtREFBd0Q7Ozs7O0lBRXRELHFEQUF5Qzs7Ozs7SUFDekMsaURBQThCOzs7OztJQUM5Qiw4Q0FFb0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlciB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IE92ZXJsYXlSZWYgfSBmcm9tICdAYW5ndWxhci9jZGsvb3ZlcmxheSc7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgVmlld0NoaWxkLFxuICBWaWV3Q2hpbGRyZW5cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSB9IGZyb20gJy4vY29udGV4dE1lbnUuaXRlbS5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSUNvbnRleHRNZW51T3B0aW9ucyB9IGZyb20gJy4vY29udGV4dE1lbnUub3B0aW9ucyc7XG5pbXBvcnQge1xuICBDbG9zZUxlYWZNZW51RXZlbnQsXG4gIElDb250ZXh0TWVudUNsaWNrRXZlbnRcbn0gZnJvbSAnLi9jb250ZXh0TWVudS5zZXJ2aWNlJztcbmltcG9ydCB7IENPTlRFWFRfTUVOVV9PUFRJT05TIH0gZnJvbSAnLi9jb250ZXh0TWVudS50b2tlbnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIElMaW5rQ29uZmlnIHtcbiAgY2xpY2s6IChpdGVtOiBhbnksICRldmVudD86IE1vdXNlRXZlbnQpID0+IHZvaWQ7XG4gIGVuYWJsZWQ/OiAoaXRlbTogYW55KSA9PiBib29sZWFuO1xuICBodG1sOiAoaXRlbTogYW55KSA9PiBzdHJpbmc7XG59XG5cbmNvbnN0IEFSUk9XX0xFRlRfS0VZQ09ERSA9IDM3O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjb250ZXh0LW1lbnUtY29udGVudCcsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC5wYXNzaXZlIHtcbiAgICAgICAgZGlzcGxheTogYmxvY2s7XG4gICAgICAgIHBhZGRpbmc6IDNweCAyMHB4O1xuICAgICAgICBjbGVhcjogYm90aDtcbiAgICAgICAgZm9udC13ZWlnaHQ6IG5vcm1hbDtcbiAgICAgICAgbGluZS1oZWlnaHQ6IEBsaW5lLWhlaWdodC1iYXNlO1xuICAgICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgICAgfVxuICAgICAgLmhhc1N1Yk1lbnU6YmVmb3JlIHtcbiAgICAgICAgY29udGVudDogJ1xcdTI1QjYnO1xuICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICB9XG4gICAgYFxuICBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiZHJvcGRvd24gb3BlbiBzaG93IG5neC1jb250ZXh0bWVudVwiXG4gICAgICBbbmdDbGFzc109XCJtZW51Q2xhc3NcIlxuICAgICAgdGFiaW5kZXg9XCIwXCJcbiAgICA+XG4gICAgICA8dWxcbiAgICAgICAgI21lbnVcbiAgICAgICAgY2xhc3M9XCJkcm9wZG93bi1tZW51IHNob3dcIlxuICAgICAgICBzdHlsZT1cInBvc2l0aW9uOiBzdGF0aWM7IGZsb2F0OiBub25lO1wiXG4gICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICA+XG4gICAgICAgIDxsaVxuICAgICAgICAgICNsaVxuICAgICAgICAgICpuZ0Zvcj1cImxldCBtZW51SXRlbSBvZiBtZW51SXRlbXM7IGxldCBpID0gaW5kZXhcIlxuICAgICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCIhaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCJcbiAgICAgICAgICBbY2xhc3MuZGl2aWRlcl09XCJtZW51SXRlbS5kaXZpZGVyXCJcbiAgICAgICAgICBbY2xhc3MuZHJvcGRvd24tZGl2aWRlcl09XCJ1c2VCb290c3RyYXA0ICYmIG1lbnVJdGVtLmRpdmlkZXJcIlxuICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwibWVudUl0ZW0uaXNBY3RpdmUgJiYgaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCJcbiAgICAgICAgICBbYXR0ci5yb2xlXT1cIm1lbnVJdGVtLmRpdmlkZXIgPyAnc2VwYXJhdG9yJyA6IHVuZGVmaW5lZFwiXG4gICAgICAgID5cbiAgICAgICAgICA8YVxuICAgICAgICAgICAgKm5nSWY9XCIhbWVudUl0ZW0uZGl2aWRlciAmJiAhbWVudUl0ZW0ucGFzc2l2ZVwiXG4gICAgICAgICAgICBocmVmXG4gICAgICAgICAgICBbY2xhc3MuZHJvcGRvd24taXRlbV09XCJ1c2VCb290c3RyYXA0XCJcbiAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwibWVudUl0ZW0uaXNBY3RpdmUgJiYgaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCJcbiAgICAgICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJ1c2VCb290c3RyYXA0ICYmICFpc01lbnVJdGVtRW5hYmxlZChtZW51SXRlbSlcIlxuICAgICAgICAgICAgW2NsYXNzLmhhc1N1Yk1lbnVdPVwiISFtZW51SXRlbS5zdWJNZW51XCJcbiAgICAgICAgICAgIChjbGljayk9XCJvbk1lbnVJdGVtU2VsZWN0KG1lbnVJdGVtLCAkZXZlbnQpXCJcbiAgICAgICAgICAgIChtb3VzZWVudGVyKT1cIm9uT3BlblN1Yk1lbnUobWVudUl0ZW0sICRldmVudClcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJtZW51SXRlbS50ZW1wbGF0ZVwiXG4gICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ICRpbXBsaWNpdDogaXRlbSB9XCJcbiAgICAgICAgICAgID48L25nLXRlbXBsYXRlPlxuICAgICAgICAgIDwvYT5cblxuICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAoY2xpY2spPVwic3RvcEV2ZW50KCRldmVudClcIlxuICAgICAgICAgICAgKGNvbnRleHRtZW51KT1cInN0b3BFdmVudCgkZXZlbnQpXCJcbiAgICAgICAgICAgIGNsYXNzPVwicGFzc2l2ZVwiXG4gICAgICAgICAgICAqbmdJZj1cIiFtZW51SXRlbS5kaXZpZGVyICYmIG1lbnVJdGVtLnBhc3NpdmVcIlxuICAgICAgICAgICAgW2NsYXNzLmRyb3Bkb3duLWl0ZW1dPVwidXNlQm9vdHN0cmFwNFwiXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwidXNlQm9vdHN0cmFwNCAmJiAhaXNNZW51SXRlbUVuYWJsZWQobWVudUl0ZW0pXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwibWVudUl0ZW0udGVtcGxhdGVcIlxuICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IGl0ZW0gfVwiXG4gICAgICAgICAgICA+PC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvbGk+XG4gICAgICA8L3VsPlxuICAgIDwvZGl2PlxuICBgXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRNZW51Q29udGVudENvbXBvbmVudFxuICBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcbiAgQElucHV0KCkgcHVibGljIG1lbnVJdGVtczogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlW10gPSBbXTtcbiAgQElucHV0KCkgcHVibGljIGl0ZW06IGFueTtcbiAgQElucHV0KCkgcHVibGljIGV2ZW50OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbiAgQElucHV0KCkgcHVibGljIHBhcmVudENvbnRleHRNZW51OiBDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQ7XG4gIEBJbnB1dCgpIHB1YmxpYyBtZW51Q2xhc3M6IHN0cmluZztcbiAgQElucHV0KCkgcHVibGljIG92ZXJsYXk6IE92ZXJsYXlSZWY7XG4gIEBJbnB1dCgpIHB1YmxpYyBpc0xlYWYgPSBmYWxzZTtcbiAgQE91dHB1dCgpIHB1YmxpYyBleGVjdXRlOiBFdmVudEVtaXR0ZXI8e1xuICAgIGV2ZW50OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbiAgICBpdGVtOiBhbnk7XG4gICAgbWVudUl0ZW06IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZTtcbiAgfT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb3BlblN1Yk1lbnU6IEV2ZW50RW1pdHRlcjxcbiAgICBJQ29udGV4dE1lbnVDbGlja0V2ZW50XG4gID4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgY2xvc2VMZWFmTWVudTogRXZlbnRFbWl0dGVyPFxuICAgIENsb3NlTGVhZk1lbnVFdmVudFxuICA+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcHVibGljIGNsb3NlQWxsTWVudXM6IEV2ZW50RW1pdHRlcjx7XG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQ7XG4gIH0+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAVmlld0NoaWxkKCdtZW51JywgeyBzdGF0aWM6IHRydWUgfSkgcHVibGljIG1lbnVFbGVtZW50OiBFbGVtZW50UmVmO1xuICBAVmlld0NoaWxkcmVuKCdsaScpIHB1YmxpYyBtZW51SXRlbUVsZW1lbnRzOiBRdWVyeUxpc3Q8RWxlbWVudFJlZj47XG5cbiAgcHVibGljIGF1dG9Gb2N1cyA9IGZhbHNlO1xuICBwdWJsaWMgdXNlQm9vdHN0cmFwNCA9IGZhbHNlO1xuICBwcml2YXRlIF9rZXlNYW5hZ2VyOiBBY3RpdmVEZXNjZW5kYW50S2V5TWFuYWdlcjxDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmU+O1xuICBwcml2YXRlIHN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgQE9wdGlvbmFsKClcbiAgICBASW5qZWN0KENPTlRFWFRfTUVOVV9PUFRJT05TKVxuICAgIHByaXZhdGUgb3B0aW9uczogSUNvbnRleHRNZW51T3B0aW9uc1xuICApIHtcbiAgICBpZiAob3B0aW9ucykge1xuICAgICAgdGhpcy5hdXRvRm9jdXMgPSBvcHRpb25zLmF1dG9Gb2N1cztcbiAgICAgIHRoaXMudXNlQm9vdHN0cmFwNCA9IG9wdGlvbnMudXNlQm9vdHN0cmFwNDtcbiAgICB9XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnVJdGVtcy5mb3JFYWNoKG1lbnVJdGVtID0+IHtcbiAgICAgIG1lbnVJdGVtLmN1cnJlbnRJdGVtID0gdGhpcy5pdGVtO1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb24uYWRkKFxuICAgICAgICBtZW51SXRlbS5leGVjdXRlLnN1YnNjcmliZShldmVudCA9PlxuICAgICAgICAgIHRoaXMuZXhlY3V0ZS5lbWl0KHsgLi4uZXZlbnQsIG1lbnVJdGVtIH0pXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfSk7XG4gICAgY29uc3QgcXVlcnlMaXN0ID0gbmV3IFF1ZXJ5TGlzdDxDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmU+KCk7XG4gICAgcXVlcnlMaXN0LnJlc2V0KHRoaXMubWVudUl0ZW1zKTtcbiAgICB0aGlzLl9rZXlNYW5hZ2VyID0gbmV3IEFjdGl2ZURlc2NlbmRhbnRLZXlNYW5hZ2VyPENvbnRleHRNZW51SXRlbURpcmVjdGl2ZT4oXG4gICAgICBxdWVyeUxpc3RcbiAgICApLndpdGhXcmFwKCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgaWYgKHRoaXMuYXV0b0ZvY3VzKSB7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuZm9jdXMoKSk7XG4gICAgfVxuICAgIHRoaXMub3ZlcmxheS51cGRhdGVQb3NpdGlvbigpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIGZvY3VzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmF1dG9Gb2N1cykge1xuICAgICAgdGhpcy5tZW51RWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgfVxuICB9XG5cbiAgc3RvcEV2ZW50KCRldmVudDogTW91c2VFdmVudCkge1xuICAgICRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHB1YmxpYyBpc01lbnVJdGVtRW5hYmxlZChtZW51SXRlbTogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZXZhbHVhdGVJZkZ1bmN0aW9uKG1lbnVJdGVtICYmIG1lbnVJdGVtLmVuYWJsZWQpO1xuICB9XG5cbiAgcHVibGljIGlzTWVudUl0ZW1WaXNpYmxlKG1lbnVJdGVtOiBDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmUpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5ldmFsdWF0ZUlmRnVuY3Rpb24obWVudUl0ZW0gJiYgbWVudUl0ZW0udmlzaWJsZSk7XG4gIH1cblxuICBwdWJsaWMgZXZhbHVhdGVJZkZ1bmN0aW9uKHZhbHVlOiBhbnkpOiBhbnkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gdmFsdWUodGhpcy5pdGVtKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHVibGljIGlzRGlzYWJsZWQobGluazogSUxpbmtDb25maWcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gbGluay5lbmFibGVkICYmICFsaW5rLmVuYWJsZWQodGhpcy5pdGVtKTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkFycm93RG93bicsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkFycm93VXAnLCBbJyRldmVudCddKVxuICBwdWJsaWMgb25LZXlFdmVudChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc0xlYWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fa2V5TWFuYWdlci5vbktleWRvd24oZXZlbnQpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleWRvd24uQXJyb3dSaWdodCcsIFsnJGV2ZW50J10pXG4gIHB1YmxpYyBrZXlib2FyZE9wZW5TdWJNZW51KGV2ZW50PzogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc0xlYWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jYW5jZWxFdmVudChldmVudCk7XG4gICAgY29uc3QgbWVudUl0ZW0gPSB0aGlzLm1lbnVJdGVtc1t0aGlzLl9rZXlNYW5hZ2VyLmFjdGl2ZUl0ZW1JbmRleF07XG4gICAgaWYgKG1lbnVJdGVtKSB7XG4gICAgICB0aGlzLm9uT3BlblN1Yk1lbnUobWVudUl0ZW0pO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ3dpbmRvdzprZXlkb3duLkVudGVyJywgWyckZXZlbnQnXSlcbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleWRvd24uU3BhY2UnLCBbJyRldmVudCddKVxuICBwdWJsaWMga2V5Ym9hcmRNZW51SXRlbVNlbGVjdChldmVudD86IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNMZWFmKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY2FuY2VsRXZlbnQoZXZlbnQpO1xuICAgIGNvbnN0IG1lbnVJdGVtID0gdGhpcy5tZW51SXRlbXNbdGhpcy5fa2V5TWFuYWdlci5hY3RpdmVJdGVtSW5kZXhdO1xuICAgIGlmIChtZW51SXRlbSkge1xuICAgICAgdGhpcy5vbk1lbnVJdGVtU2VsZWN0KG1lbnVJdGVtLCBldmVudCk7XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleWRvd24uRXNjYXBlJywgWyckZXZlbnQnXSlcbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmtleWRvd24uQXJyb3dMZWZ0JywgWyckZXZlbnQnXSlcbiAgcHVibGljIG9uQ2xvc2VMZWFmTWVudShldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc0xlYWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jYW5jZWxFdmVudChldmVudCk7XG4gICAgdGhpcy5jbG9zZUxlYWZNZW51LmVtaXQoe1xuICAgICAgZXhjZXB0Um9vdE1lbnU6IGV2ZW50LmtleUNvZGUgPT09IEFSUk9XX0xFRlRfS0VZQ09ERSxcbiAgICAgIGV2ZW50XG4gICAgfSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNvbnRleHRtZW51JywgWyckZXZlbnQnXSlcbiAgcHVibGljIGNsb3NlTWVudShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmIChldmVudC50eXBlID09PSAnY2xpY2snICYmIGV2ZW50LmJ1dHRvbiA9PT0gMikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNsb3NlQWxsTWVudXMuZW1pdCh7IGV2ZW50IH0pO1xuICB9XG5cbiAgcHVibGljIG9uT3BlblN1Yk1lbnUoXG4gICAgbWVudUl0ZW06IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSxcbiAgICBldmVudD86IE1vdXNlRXZlbnQgfCBLZXlib2FyZEV2ZW50XG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGFuY2hvckVsZW1lbnRSZWYgPSB0aGlzLm1lbnVJdGVtRWxlbWVudHMudG9BcnJheSgpW1xuICAgICAgdGhpcy5fa2V5TWFuYWdlci5hY3RpdmVJdGVtSW5kZXhcbiAgICBdO1xuICAgIGNvbnN0IGFuY2hvckVsZW1lbnQgPSBhbmNob3JFbGVtZW50UmVmICYmIGFuY2hvckVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcbiAgICB0aGlzLm9wZW5TdWJNZW51LmVtaXQoe1xuICAgICAgYW5jaG9yRWxlbWVudCxcbiAgICAgIGNvbnRleHRNZW51OiBtZW51SXRlbS5zdWJNZW51LFxuICAgICAgZXZlbnQsXG4gICAgICBpdGVtOiB0aGlzLml0ZW0sXG4gICAgICBwYXJlbnRDb250ZXh0TWVudTogdGhpc1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG9uTWVudUl0ZW1TZWxlY3QoXG4gICAgbWVudUl0ZW06IENvbnRleHRNZW51SXRlbURpcmVjdGl2ZSxcbiAgICBldmVudDogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnRcbiAgKTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLm9uT3BlblN1Yk1lbnUobWVudUl0ZW0sIGV2ZW50KTtcbiAgICBpZiAoIW1lbnVJdGVtLnN1Yk1lbnUpIHtcbiAgICAgIG1lbnVJdGVtLnRyaWdnZXJFeGVjdXRlKHRoaXMuaXRlbSwgZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2FuY2VsRXZlbnQoZXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIWV2ZW50KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0OiBIVE1MRWxlbWVudCA9IGV2ZW50LnRhcmdldDtcbiAgICBpZiAoXG4gICAgICBbJ0lOUFVUJywgJ1RFWFRBUkVBJywgJ1NFTEVDVCddLmluZGV4T2YodGFyZ2V0LnRhZ05hbWUpID4gLTEgfHxcbiAgICAgIHRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cbn1cbiJdfQ==