@ifsworld/granite-components 10.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +4 -28
  2. package/date-picker/lib/date-picker-base.d.ts +1 -1
  3. package/date-picker/lib/date-picker-trigger-for.directive.d.ts +1 -1
  4. package/date-picker/lib/date-picker.component.d.ts +1 -1
  5. package/date-picker/lib/date-range-picker.component.d.ts +1 -1
  6. package/{esm2020 → esm2022}/date-picker/lib/date-picker-base.mjs +4 -4
  7. package/{esm2020 → esm2022}/date-picker/lib/date-picker-trigger-for.directive.mjs +4 -4
  8. package/esm2022/date-picker/lib/date-picker.component.mjs +30 -0
  9. package/{esm2020 → esm2022}/date-picker/lib/date-picker.module.mjs +21 -21
  10. package/esm2022/date-picker/lib/date-range-picker.component.mjs +46 -0
  11. package/{esm2020 → esm2022}/lib/arrange-grid/arrange-grid-item.component.mjs +12 -12
  12. package/{esm2020 → esm2022}/lib/arrange-grid/arrange-grid.component.mjs +7 -7
  13. package/{esm2020 → esm2022}/lib/arrange-grid/arrange-grid.module.mjs +5 -5
  14. package/{esm2020 → esm2022}/lib/badge/badge.component.mjs +5 -5
  15. package/{esm2020 → esm2022}/lib/badge/badge.module.mjs +5 -5
  16. package/esm2022/lib/badge/testing/badge.harness.mjs +25 -0
  17. package/esm2022/lib/button/button.component.mjs +87 -0
  18. package/{esm2020 → esm2022}/lib/button/button.module.mjs +5 -5
  19. package/{esm2020 → esm2022}/lib/checkbox/checkbox-group.component.mjs +4 -4
  20. package/{esm2020 → esm2022}/lib/checkbox/checkbox.component.mjs +4 -4
  21. package/{esm2020 → esm2022}/lib/checkbox/checkbox.module.mjs +5 -5
  22. package/esm2022/lib/chips/chip-input.mjs +195 -0
  23. package/esm2022/lib/chips/chip-list.component.mjs +567 -0
  24. package/esm2022/lib/chips/chip.component.mjs +287 -0
  25. package/{esm2020 → esm2022}/lib/chips/chips.module.mjs +9 -9
  26. package/{esm2020 → esm2022}/lib/core/common-behaviors/disabled.mjs +4 -4
  27. package/{esm2020 → esm2022}/lib/core/core.module.mjs +11 -11
  28. package/esm2022/lib/core/devices/client-input-desktop.directive.mjs +29 -0
  29. package/esm2022/lib/core/devices/client-input-touch.directive.mjs +29 -0
  30. package/esm2022/lib/core/devices/client-output-desktop.directive.mjs +29 -0
  31. package/esm2022/lib/core/devices/client-output-touch.directive.mjs +29 -0
  32. package/{esm2020 → esm2022}/lib/core/pipes/pure-pipes.module.mjs +5 -5
  33. package/{esm2020 → esm2022}/lib/core/pipes/title.pipe.mjs +4 -4
  34. package/{esm2020 → esm2022}/lib/core/radio-checkbox-base.mjs +4 -4
  35. package/{esm2020 → esm2022}/lib/grid/grid.component.mjs +7 -7
  36. package/{esm2020 → esm2022}/lib/grid/grid.module.mjs +5 -5
  37. package/{esm2020 → esm2022}/lib/icon/icon.component.mjs +4 -4
  38. package/{esm2020 → esm2022}/lib/icon/icon.module.mjs +5 -5
  39. package/{esm2020 → esm2022}/lib/input-field/input-field.component.mjs +5 -5
  40. package/{esm2020 → esm2022}/lib/input-field/input-field.module.mjs +5 -5
  41. package/{esm2020 → esm2022}/lib/label/label.component.mjs +4 -4
  42. package/{esm2020 → esm2022}/lib/label/label.module.mjs +5 -5
  43. package/{esm2020 → esm2022}/lib/menu/divider.directive.mjs +4 -4
  44. package/{esm2020 → esm2022}/lib/menu/menu-base.mjs +4 -4
  45. package/{esm2020 → esm2022}/lib/menu/menu-item.component.mjs +6 -6
  46. package/{esm2020 → esm2022}/lib/menu/menu-touch-close.component.mjs +4 -4
  47. package/{esm2020 → esm2022}/lib/menu/menu-touch-title.component.mjs +6 -6
  48. package/esm2022/lib/menu/menu-trigger-for.directive.mjs +704 -0
  49. package/esm2022/lib/menu/menu.component.mjs +30 -0
  50. package/{esm2020 → esm2022}/lib/menu/menu.module.mjs +17 -17
  51. package/esm2022/lib/menu/testing/menu.harness.mjs +109 -0
  52. package/{esm2020 → esm2022}/lib/menu/title.directive.mjs +4 -4
  53. package/{esm2020 → esm2022}/lib/radio-button/radio-button.component.mjs +4 -4
  54. package/{esm2020 → esm2022}/lib/radio-button/radio-button.module.mjs +5 -5
  55. package/{esm2020 → esm2022}/lib/radio-button/radio-group.component.mjs +4 -4
  56. package/{esm2020 → esm2022}/lib/toggle-switch/toggle-switch.component.mjs +4 -4
  57. package/{esm2020 → esm2022}/lib/toggle-switch/toggle-switch.module.mjs +5 -5
  58. package/{esm2020 → esm2022}/table/lib/cell/cell-align/cell-align-classes.directive.mjs +4 -4
  59. package/{esm2020 → esm2022}/table/lib/cell/cell.mjs +4 -4
  60. package/{esm2020 → esm2022}/table/lib/cell/table-data-cell.component.mjs +5 -5
  61. package/{esm2020 → esm2022}/table/lib/cell/table-header-cell.component.mjs +4 -4
  62. package/{esm2020 → esm2022}/table/lib/column/table-column.directive.mjs +4 -4
  63. package/esm2022/table/lib/table-constants.library.mjs +9 -0
  64. package/{esm2020 → esm2022}/table/lib/table.component.mjs +4 -4
  65. package/{esm2020 → esm2022}/table/lib/table.module.mjs +9 -9
  66. package/{esm2020 → esm2022}/tooltip/lib/tooltip-constants.library.mjs +2 -2
  67. package/{esm2020 → esm2022}/tooltip/lib/tooltip-trigger-for.directive.mjs +4 -4
  68. package/{esm2020 → esm2022}/tooltip/lib/tooltip.component.mjs +5 -5
  69. package/{esm2020 → esm2022}/tooltip/lib/tooltip.module.mjs +5 -5
  70. package/fesm2022/ifsworld-granite-components-date-picker.mjs +396 -0
  71. package/{fesm2020 → fesm2022}/ifsworld-granite-components-date-picker.mjs.map +1 -1
  72. package/fesm2022/ifsworld-granite-components-table.mjs +190 -0
  73. package/{fesm2015 → fesm2022}/ifsworld-granite-components-table.mjs.map +1 -1
  74. package/{fesm2020 → fesm2022}/ifsworld-granite-components-tooltip.mjs +12 -12
  75. package/{fesm2020 → fesm2022}/ifsworld-granite-components-tooltip.mjs.map +1 -1
  76. package/{fesm2020 → fesm2022}/ifsworld-granite-components.mjs +340 -341
  77. package/fesm2022/ifsworld-granite-components.mjs.map +1 -0
  78. package/lib/arrange-grid/arrange-grid-item.component.d.ts +5 -5
  79. package/lib/arrange-grid/arrange-grid.component.d.ts +3 -3
  80. package/lib/badge/badge.component.d.ts +1 -1
  81. package/lib/button/button.component.d.ts +2 -2
  82. package/lib/checkbox/checkbox.component.d.ts +1 -1
  83. package/lib/chips/chip-input.d.ts +9 -9
  84. package/lib/chips/chip-list.component.d.ts +33 -33
  85. package/lib/chips/chip.component.d.ts +22 -22
  86. package/lib/core/radio-checkbox-base.d.ts +1 -1
  87. package/lib/grid/grid.component.d.ts +2 -2
  88. package/lib/icon/icon.component.d.ts +1 -1
  89. package/lib/input-field/input-field.component.d.ts +1 -1
  90. package/lib/label/label.component.d.ts +1 -1
  91. package/lib/menu/divider.directive.d.ts +1 -1
  92. package/lib/menu/menu-base.d.ts +1 -1
  93. package/lib/menu/menu-item.component.d.ts +1 -1
  94. package/lib/menu/menu-trigger-for.directive.d.ts +1 -1
  95. package/lib/radio-button/radio-button.component.d.ts +1 -1
  96. package/lib/toggle-switch/toggle-switch.component.d.ts +1 -1
  97. package/package.json +21 -40
  98. package/table/lib/cell/cell-align/cell-align-classes.directive.d.ts +1 -1
  99. package/table/lib/cell/cell.d.ts +1 -1
  100. package/table/lib/cell/table-data-cell.component.d.ts +1 -1
  101. package/table/lib/column/table-column.directive.d.ts +1 -1
  102. package/table/lib/table.component.d.ts +1 -1
  103. package/tooltip/lib/tooltip-trigger-for.directive.d.ts +1 -1
  104. package/esm2020/date-picker/lib/date-picker.component.mjs +0 -30
  105. package/esm2020/date-picker/lib/date-range-picker.component.mjs +0 -46
  106. package/esm2020/lib/badge/testing/badge.harness.mjs +0 -25
  107. package/esm2020/lib/button/button.component.mjs +0 -87
  108. package/esm2020/lib/chips/chip-input.mjs +0 -195
  109. package/esm2020/lib/chips/chip-list.component.mjs +0 -567
  110. package/esm2020/lib/chips/chip.component.mjs +0 -287
  111. package/esm2020/lib/core/devices/client-input-desktop.directive.mjs +0 -29
  112. package/esm2020/lib/core/devices/client-input-touch.directive.mjs +0 -29
  113. package/esm2020/lib/core/devices/client-output-desktop.directive.mjs +0 -29
  114. package/esm2020/lib/core/devices/client-output-touch.directive.mjs +0 -29
  115. package/esm2020/lib/menu/menu-trigger-for.directive.mjs +0 -705
  116. package/esm2020/lib/menu/menu.component.mjs +0 -30
  117. package/esm2020/lib/menu/testing/menu.harness.mjs +0 -109
  118. package/esm2020/table/lib/table-constants.library.mjs +0 -9
  119. package/fesm2015/ifsworld-granite-components-date-picker.mjs +0 -401
  120. package/fesm2015/ifsworld-granite-components-date-picker.mjs.map +0 -1
  121. package/fesm2015/ifsworld-granite-components-table.mjs +0 -190
  122. package/fesm2015/ifsworld-granite-components-tooltip.mjs +0 -169
  123. package/fesm2015/ifsworld-granite-components-tooltip.mjs.map +0 -1
  124. package/fesm2015/ifsworld-granite-components.mjs +0 -4133
  125. package/fesm2015/ifsworld-granite-components.mjs.map +0 -1
  126. package/fesm2020/ifsworld-granite-components-date-picker.mjs +0 -396
  127. package/fesm2020/ifsworld-granite-components-table.mjs +0 -190
  128. package/fesm2020/ifsworld-granite-components-table.mjs.map +0 -1
  129. package/fesm2020/ifsworld-granite-components.mjs.map +0 -1
  130. /package/{esm2020 → esm2022}/date-picker/ifsworld-granite-components-date-picker.mjs +0 -0
  131. /package/{esm2020 → esm2022}/date-picker/index.mjs +0 -0
  132. /package/{esm2020 → esm2022}/ifsworld-granite-components.mjs +0 -0
  133. /package/{esm2020 → esm2022}/index.mjs +0 -0
  134. /package/{esm2020 → esm2022}/lib/core/animation.mjs +0 -0
  135. /package/{esm2020 → esm2022}/lib/core/client-environment.mjs +0 -0
  136. /package/{esm2020 → esm2022}/lib/core/theme.library.mjs +0 -0
  137. /package/{esm2020 → esm2022}/lib/core/types.mjs +0 -0
  138. /package/{esm2020 → esm2022}/lib/menu/menu-desktop-animations.mjs +0 -0
  139. /package/{esm2020 → esm2022}/lib/menu/menu-errors.mjs +0 -0
  140. /package/{esm2020 → esm2022}/lib/menu/menu-panel.mjs +0 -0
  141. /package/{esm2020 → esm2022}/lib/menu/menu-positions.mjs +0 -0
  142. /package/{esm2020 → esm2022}/lib/menu/menu-touch-animations.mjs +0 -0
  143. /package/{esm2020 → esm2022}/table/ifsworld-granite-components-table.mjs +0 -0
  144. /package/{esm2020 → esm2022}/table/index.mjs +0 -0
  145. /package/{esm2020 → esm2022}/table/lib/table.types.mjs +0 -0
  146. /package/{esm2020 → esm2022}/tooltip/ifsworld-granite-components-tooltip.mjs +0 -0
  147. /package/{esm2020 → esm2022}/tooltip/index.mjs +0 -0
@@ -1,705 +0,0 @@
1
- import { Directive, ElementRef, Inject, Input, Optional, Self, ViewContainerRef, } from '@angular/core';
2
- import { DOCUMENT } from '@angular/common';
3
- import { FocusMonitor, isFakeMousedownFromScreenReader, } from '@angular/cdk/a11y';
4
- import { Directionality } from '@angular/cdk/bidi';
5
- import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
6
- import { Overlay, OverlayConfig, } from '@angular/cdk/overlay';
7
- import { TemplatePortal } from '@angular/cdk/portal';
8
- import { asapScheduler, fromEvent, merge, of as observableOf, Subscription, } from 'rxjs';
9
- import { delay, filter, take, takeUntil } from 'rxjs/operators';
10
- import { _MenuBaseComponent } from './menu-base';
11
- import { GraniteMenuItemComponent } from './menu-item.component';
12
- import { GRANITE_MENU_PANEL } from './menu-panel';
13
- //#region --- Touch device customizations ---
14
- import { GRANITE_CLIENT_INPUT, GRANITE_CLIENT_OUTPUT, } from '../core/client-environment';
15
- import { throwGraniteMenuMissingError } from './menu-errors';
16
- import * as i0 from "@angular/core";
17
- import * as i1 from "@angular/cdk/overlay";
18
- import * as i2 from "./menu-item.component";
19
- import * as i3 from "@angular/cdk/bidi";
20
- import * as i4 from "@angular/cdk/a11y";
21
- import * as i5 from "./menu-base";
22
- /** Options for binding a passive event listener. */
23
- const passiveEventListenerOptions = normalizePassiveListenerOptions({
24
- passive: true,
25
- });
26
- //#endregion --- Touch device customizations ---
27
- /**
28
- * Directive used to turn a button element into a (popup) menu trigger
29
- *
30
- * Stripped-down version of Angular Material's menu trigger directive (.../menu/menu-trigger.ts)
31
- */
32
- export class GraniteMenuTriggerForDirective {
33
- constructor(_overlay, _element, _viewContainerRef,
34
- /** If this is a _submenu_ trigger, it will have a parent menu */
35
- _parentMenu,
36
- //#region --- Touch device customizations ---
37
- /** Client input device information */
38
- _clientInput,
39
- /** Client output device information */
40
- _clientOutput,
41
- //#endregion --- Touch device customizations ---
42
- /**
43
- * If this is a _submenu_ trigger, there should be a corresponding menu
44
- * item directive present as well:
45
- *
46
- * <button graniteMenuItem [graniteMenuTriggerFor]="...">
47
- * ^-- This one
48
- */
49
- _menuItemInstance, _dir, _focusMonitor,
50
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
51
- document) {
52
- this._overlay = _overlay;
53
- this._element = _element;
54
- this._viewContainerRef = _viewContainerRef;
55
- this._parentMenu = _parentMenu;
56
- this._clientInput = _clientInput;
57
- this._clientOutput = _clientOutput;
58
- this._menuItemInstance = _menuItemInstance;
59
- this._dir = _dir;
60
- this._focusMonitor = _focusMonitor;
61
- this.openOnClick = true;
62
- /** Whether the associated menu is open */
63
- this._isMenuOpen = false;
64
- // Tracking input type is necessary so it's possible to only auto-focus
65
- // the first item of the list when the menu is opened via the keyboard
66
- this._openedBy = null;
67
- this._hoverSubscription = Subscription.EMPTY;
68
- this._menuCloseSubscription = Subscription.EMPTY;
69
- this._closingActionsSubscription = Subscription.EMPTY;
70
- this._portal = null;
71
- this._overlayRef = null;
72
- this._touchTouchingElement = false;
73
- /**
74
- * Handles touch start events on the trigger.
75
- * Needs to be an arrow function so we can easily use addEventListener and removeEventListener.
76
- */
77
- this._handleTouchStart = () => {
78
- this._openedBy = 'touch';
79
- };
80
- // ----------------------------------------- //
81
- // --- Here be poor man's touch gestures --- //
82
- // ----------------------------------------- //
83
- // TODO: Replace with Hammer or other gesture library
84
- /**
85
- * Handles touch start events on the overlay host element (wrapper).
86
- * Needs to be an arrow function so we can easily use addEventListener and removeEventListener.
87
- */
88
- this._handleOverlayTouchStart = (event) => {
89
- if (this.menu._isAnimating) {
90
- return;
91
- }
92
- this._touchStartTime = new Date().getTime();
93
- this._touchStartX = event.changedTouches[0].clientX;
94
- this._touchStartY = event.changedTouches[0].clientY;
95
- this._touchCurrentX = this._touchStartX;
96
- this._touchCurrentY = this._touchStartY;
97
- this._touchTranslateX = 0;
98
- this._touchMaxX =
99
- this._overlayRef.hostElement.getBoundingClientRect().width;
100
- this._touchLockedX = null;
101
- this._touchTouchingElement = true;
102
- };
103
- this._handleOverlayTouchMove = (event) => {
104
- if (!this._touchTouchingElement || this.menu._isAnimating) {
105
- return;
106
- }
107
- if (this._touchLockedX) {
108
- return;
109
- }
110
- this._touchCurrentX = event.changedTouches[0].clientX;
111
- this._touchCurrentY = event.changedTouches[0].clientY;
112
- // Lock X-axis pan if initiating pan on Y-axis
113
- if (this._touchLockedX === null) {
114
- const dy = Math.abs(this._touchCurrentY - this._touchStartY);
115
- const dx = Math.abs(this._touchCurrentX - this._touchStartX);
116
- if (dx > 10 || dy > 10) {
117
- this._touchLockedX = dy > dx;
118
- return;
119
- }
120
- }
121
- // Restrict to right pan/swipe and make menu movement extremely slow when
122
- // moved past allowed limits.
123
- const menuMargin = 16;
124
- this._touchTranslateX = this._touchCurrentX - this._touchStartX;
125
- if (this._touchTranslateX < 0) {
126
- this._touchTranslateX = this.easeOutExpo(this._touchTranslateX, 0, -menuMargin / 2, this._touchMaxX * -4);
127
- }
128
- else if (!this._parentMenu) {
129
- this._touchTranslateX = this.easeOutExpo(this._touchTranslateX, 0, menuMargin / 2, this._touchMaxX * 4);
130
- }
131
- else if (this._touchTranslateX > this._touchMaxX) {
132
- this._touchTranslateX = this.easeOutExpo(this._touchTranslateX - this._touchMaxX, this._touchMaxX, menuMargin / 2, this._touchMaxX * 4);
133
- }
134
- // Set new sub menu position and tell any parent to follow;
135
- this.animateSetMenuPosition(this._touchTranslateX);
136
- };
137
- this._handleOverlayTouchEnd = () => {
138
- if (!this._touchTouchingElement || this.menu._isAnimating) {
139
- return;
140
- }
141
- this._touchTranslateX = this._touchCurrentX - this._touchStartX;
142
- if (this._touchTranslateX === 0) {
143
- return;
144
- }
145
- this._touchTouchingElement = false;
146
- this._touchTimeTaken = new Date().getTime() - this._touchStartTime;
147
- const swipeMinDistance = 10;
148
- const swipeMinTime = 50;
149
- const swipeMaxTime = 300;
150
- const pannedHalfwayRight = this._touchTranslateX > this._touchMaxX / 2;
151
- const swipedRight = this._touchTranslateX > this._touchMaxX / swipeMinDistance &&
152
- this._touchTimeTaken > swipeMinTime &&
153
- this._touchTimeTaken < swipeMaxTime;
154
- if (!!this._parentMenu && (swipedRight || pannedHalfwayRight)) {
155
- // Close submenu keydown-style: close only this menu and leave parents open
156
- this.menu.closed.emit('keydown');
157
- }
158
- else {
159
- // Pan ended but the menu was not moved far enough. Reset menus to
160
- // where they were before panning stared.
161
- this.animateOpenMenu();
162
- }
163
- };
164
- _element.nativeElement.addEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
165
- if (_menuItemInstance) {
166
- _menuItemInstance._triggersSubmenu = this.triggersSubmenu();
167
- }
168
- this._document = document;
169
- }
170
- ngOnChanges(changes) {
171
- if (changes.menu) {
172
- this._handleMenuChange();
173
- }
174
- }
175
- ngAfterContentInit() {
176
- // removed checkMenu here to avoid errors in dynamically genarated menus
177
- // menu is checked when opening the menu
178
- // this._checkMenu();
179
- this._handleHover();
180
- }
181
- ngOnDestroy() {
182
- if (this._overlayRef) {
183
- //#region --- Touch device customizations ---
184
- this.removeOverlayListeners();
185
- //#endregion --- Touch device customizations ---
186
- this._overlayRef.dispose();
187
- this._overlayRef = null;
188
- }
189
- this._element.nativeElement.removeEventListener('touchstart', this._handleTouchStart, passiveEventListenerOptions);
190
- this._hoverSubscription.unsubscribe();
191
- this._menuCloseSubscription.unsubscribe();
192
- this._closingActionsSubscription.unsubscribe();
193
- }
194
- /** Handles change of associated menu */
195
- _handleMenuChange() {
196
- this._menuCloseSubscription.unsubscribe();
197
- // Close the menu overlay when the menu itself says it wants to be closed
198
- if (this.menu) {
199
- const closed = this.menu.closed;
200
- this._menuCloseSubscription = closed.subscribe((reason) => {
201
- //#region --- Touch device customizations ---
202
- if (this.menu._isClosing) {
203
- return;
204
- }
205
- this.menu._isClosing = true;
206
- // Get rid of the menu and tell any parent to restore its position
207
- if (this._clientOutput.device === 'touch') {
208
- // First we wait for any running animation to complete
209
- const runningAnimationDone = this.menu._isAnimating
210
- ? this.menu._animationDone
211
- : observableOf([null]);
212
- runningAnimationDone
213
- .pipe(take(1), delay(0, asapScheduler))
214
- // eslint-disable-next-line rxjs/no-nested-subscribe
215
- .subscribe(() => {
216
- this.animateCloseMenu(reason !== 'keydown', reason === 'click');
217
- this.menu._animationDone
218
- .pipe(take(1), delay(0, asapScheduler))
219
- // eslint-disable-next-line rxjs/no-nested-subscribe
220
- .subscribe(() => this._destroyMenu());
221
- });
222
- }
223
- else {
224
- //#endregion --- Touch device customizations ---
225
- this._destroyMenu();
226
- }
227
- // If a click closed the menu, we should close the entire chain of nested menus.
228
- if ((reason === 'click' || reason === 'tab') && this._parentMenu) {
229
- this._parentMenu.closed.emit(reason);
230
- }
231
- });
232
- }
233
- }
234
- isOpen() {
235
- return this._isMenuOpen;
236
- }
237
- /** Open the associated menu */
238
- openMenu() {
239
- if (this._isMenuOpen) {
240
- return;
241
- }
242
- this._checkMenu();
243
- this.menu.parentMenu = this.triggersSubmenu()
244
- ? this._parentMenu
245
- : undefined;
246
- this.menu.direction = this._dir.value === 'rtl' ? 'rtl' : 'ltr';
247
- if (this._parentMenu) {
248
- // Menu triggers inherit target device types from their parent.
249
- // Ultimately it is the root trigger that determines device types for
250
- // the whole menu hierarchy.
251
- this._clientInput = this._parentMenu._clientInput;
252
- this._clientOutput = this._parentMenu._clientOutput;
253
- }
254
- //#region --- Touch device customizations ---
255
- // Make the menu we're about to open use the same devices as the trigger
256
- this.menu._setDevice(this._clientInput, this._clientOutput);
257
- if (this._clientOutput.device === 'touch') {
258
- this.menu.showBackButton = !!this._parentMenu;
259
- this.menu._updateShowTitle();
260
- if (!this.menu.closeLabel) {
261
- this.menu.closeLabel = this._parentMenu?.closeLabel;
262
- }
263
- this.menu.showCloseButton = !!this.menu.closeLabel;
264
- }
265
- this.menu._isClosing = false;
266
- const panelClass = [];
267
- if (this._clientOutput.device === 'touch') {
268
- panelClass.push('granite-overlay-pane-fill-width-bottom');
269
- }
270
- const scrollStrategy = this._clientOutput.device !== 'touch'
271
- ? this._overlay.scrollStrategies.reposition()
272
- : undefined;
273
- const hasBackdrop = this._clientOutput.device === 'touch' && !this.triggersSubmenu();
274
- //#endregion --- Touch device customizations ---
275
- // Create an overlay to stuff the menu (portal) into below
276
- if (!this._overlayRef) {
277
- const config = new OverlayConfig({
278
- positionStrategy: this._positionStrategy(),
279
- backdropClass: 'granite-overlay-dark-glass-backdrop',
280
- scrollStrategy,
281
- direction: this._dir,
282
- panelClass,
283
- hasBackdrop,
284
- });
285
- this._overlayRef = this._overlay.create(config);
286
- //#region --- Touch device customizations ---
287
- // Add touch listener for submenu back pan/swipe
288
- if (this._clientOutput.device === 'touch') {
289
- this.addOverlayListeners();
290
- }
291
- //#endregion --- Touch device customizations ---
292
- }
293
- else {
294
- // Reset animation state for reused overlays
295
- if (this._clientOutput.device === 'touch') {
296
- this.menu._panelAnimationState = 'void';
297
- }
298
- }
299
- // Create portal from associated menu's template
300
- if (!this._portal || this._portal.templateRef !== this.menu.templateRef) {
301
- this._portal = new TemplatePortal(this.menu.templateRef, this._viewContainerRef);
302
- }
303
- // Attach menu portal to overlay ref (which is a portal outlet)
304
- this._overlayRef.attach(this._portal);
305
- // Subscribe to stream that emits whenever an action that should close the menu occurs
306
- this._closingActionsSubscription = this._menuClosingActions().subscribe(() => this.closeMenu());
307
- this.animateOpenMenu();
308
- this._setIsMenuOpen(true);
309
- this.menu.focusFirstItem(this._openedBy || 'program');
310
- }
311
- /** Whether the menu triggers a sub-menu or a top-level one. */
312
- triggersSubmenu() {
313
- return !!(this._menuItemInstance && this._parentMenu);
314
- }
315
- /** Toggles the menu between the open and closed states. */
316
- toggleMenu() {
317
- if (this._isMenuOpen) {
318
- this.closeMenu();
319
- }
320
- else if (this.openOnClick) {
321
- this.openMenu();
322
- }
323
- }
324
- /** Close the associated menu */
325
- closeMenu() {
326
- this.menu.closed.emit();
327
- }
328
- /**
329
- * Focuses the menu trigger.
330
- * @param origin Source of the menu trigger's focus.
331
- */
332
- focus(origin = 'program', options) {
333
- if (this._focusMonitor) {
334
- this._focusMonitor.focusVia(this._element, origin, options);
335
- }
336
- else {
337
- this._element.nativeElement.focus(options);
338
- }
339
- }
340
- /** Detach menu portal from overlay and update open state */
341
- _destroyMenu() {
342
- if (!this._overlayRef || !this._isMenuOpen) {
343
- return;
344
- }
345
- this._closingActionsSubscription.unsubscribe();
346
- this._overlayRef.detach();
347
- this._restoreFocus();
348
- this.menu._resetAnimation();
349
- this._setIsMenuOpen(false);
350
- }
351
- /** Handles mouse presses on the trigger. */
352
- _handleMousedown(event) {
353
- if (!isFakeMousedownFromScreenReader(event)) {
354
- if (this._openedBy !== 'touch') {
355
- // Since right or middle button clicks won't trigger the `click` event,
356
- // we shouldn't consider the menu as opened by mouse in those cases.
357
- this._openedBy = event.button === 0 ? 'mouse' : null;
358
- }
359
- // Since clicking on the trigger won't close the menu if it opens a sub-menu,
360
- // we should prevent focus from moving onto it via click to avoid the
361
- // highlight from lingering on the menu item.
362
- if (this.triggersSubmenu() && !this._toggleOnSubmenuClick()) {
363
- event.preventDefault();
364
- }
365
- }
366
- }
367
- /** Handles key presses on the trigger. */
368
- _handleKeydown(event) {
369
- const key = event.key;
370
- if (this.triggersSubmenu() &&
371
- ((key === 'ArrowRight' && this._dir.value === 'ltr') ||
372
- (key === 'ArrowLeft' && this._dir.value === 'rtl'))) {
373
- this.openMenu();
374
- }
375
- }
376
- /** Handles click events on the trigger. */
377
- _handleClick(event) {
378
- if (this.triggersSubmenu()) {
379
- // Stop event propagation to avoid closing the parent menu.
380
- event.stopPropagation();
381
- this._toggleOnSubmenuClick() ? this.toggleMenu() : this.openMenu();
382
- }
383
- else {
384
- this.toggleMenu();
385
- }
386
- }
387
- /** Handles the cases where the user hovers over the trigger. */
388
- _handleHover() {
389
- // Subscribe to changes in the hovered item in order to toggle the panel.
390
- if (!this.triggersSubmenu() || !this._parentMenu) {
391
- return;
392
- }
393
- this._hoverSubscription = this._parentMenu
394
- ._hovered()
395
- .pipe(filter(() => this._openOnHover()),
396
- // Since we might have multiple competing triggers for the same menu (e.g. a sub-menu
397
- // with different data and triggers), we have to delay it by a tick to ensure that
398
- // it won't be closed immediately after it is opened.
399
- filter((active) => active === this._menuItemInstance /*&& !active.disabled*/), delay(0, asapScheduler))
400
- .subscribe(() => {
401
- this._openedBy = 'mouse';
402
- // If the same menu is used between multiple triggers, it might still be animating
403
- // while the new trigger tries to re-open it. Wait for the animation to finish
404
- // before doing so. Also interrupt if the user moves to another item.
405
- if (this.menu instanceof _MenuBaseComponent && this.menu._isAnimating) {
406
- // We need the `delay(0)` here in order to avoid
407
- // 'changed after checked' errors in some cases. See Angular Material #12194.
408
- this.menu._animationDone
409
- .pipe(take(1), delay(0, asapScheduler), takeUntil(this._parentMenu._hovered()))
410
- // eslint-disable-next-line rxjs/no-nested-subscribe
411
- .subscribe(() => this.openMenu());
412
- }
413
- else {
414
- this.openMenu();
415
- }
416
- });
417
- }
418
- /**
419
- * Restores focus to the element that was focused before the menu was open.
420
- * Could be the root trigger button or a submenu trigger item
421
- */
422
- _restoreFocus() {
423
- // We should reset focus if the user is navigating using a keyboard or
424
- // if we have a top-level trigger which might cause focus to be lost
425
- // when clicking outside of the menu.
426
- if (!this._openedBy) {
427
- // Note that the focus style will show up both for `program` and
428
- // `keyboard` so we don't have to specify which one it is.
429
- this.focus();
430
- }
431
- else if (!this.triggersSubmenu()) {
432
- this.focus(this._openedBy);
433
- }
434
- this._openedBy = null;
435
- }
436
- // Set state rather than toggle to support triggers sharing a menu
437
- _setIsMenuOpen(isOpen) {
438
- this._isMenuOpen = isOpen;
439
- if (this.triggersSubmenu()) {
440
- this._menuItemInstance._highlighted =
441
- isOpen && this._clientOutput.device !== 'touch';
442
- }
443
- }
444
- /**
445
- * This method checks that a valid instance of MenuComponent has been passed into
446
- * graniteMenuTriggerFor. If not, an exception is thrown.
447
- */
448
- _checkMenu() {
449
- if (!this.menu) {
450
- throwGraniteMenuMissingError();
451
- }
452
- }
453
- /**
454
- * Returns strategy for positioning the overlay for desktop devices:
455
- * Place adjacent to the trigger button (preferably immediately below)
456
- * in order to show as much of the menu as possible.
457
- */
458
- _desktopPositionStrategy() {
459
- const positionStrategy = this._overlay
460
- .position()
461
- .flexibleConnectedTo(this._element)
462
- .withLockedPosition()
463
- .withTransformOriginOn('.granite-menu')
464
- .withPush(false);
465
- this._setPosition(positionStrategy);
466
- return positionStrategy;
467
- }
468
- /**
469
- * Sets the appropriate positions on a position strategy
470
- * so the overlay connects with the trigger correctly.
471
- * @param positionStrategy Strategy whose position to update.
472
- */
473
- _setPosition(positionStrategy) {
474
- const MENU_PANEL_TOP_PADDING = 0;
475
- let [originX, originFallbackX] = this.menu.xPosition === 'before' ? ['end', 'start'] : ['start', 'end'];
476
- const [overlayY, overlayFallbackY] = this.menu.yPosition === 'above' ? ['bottom', 'top'] : ['top', 'bottom'];
477
- let [originY, originFallbackY] = [overlayY, overlayFallbackY];
478
- let [overlayX, overlayFallbackX] = [originX, originFallbackX];
479
- let offsetY = 0;
480
- if (this.triggersSubmenu()) {
481
- // When the menu is a sub-menu, it should always align itself
482
- // to the edges of the trigger, instead of overlapping it.
483
- overlayFallbackX = originX =
484
- this.menu.xPosition === 'before' ? 'start' : 'end';
485
- originFallbackX = overlayX = originX === 'end' ? 'start' : 'end';
486
- offsetY =
487
- overlayY === 'bottom'
488
- ? MENU_PANEL_TOP_PADDING
489
- : -MENU_PANEL_TOP_PADDING;
490
- }
491
- else {
492
- originY = overlayY === 'top' ? 'bottom' : 'top';
493
- originFallbackY = overlayFallbackY === 'top' ? 'bottom' : 'top';
494
- }
495
- positionStrategy.withPositions([
496
- { originX, originY, overlayX, overlayY, offsetY },
497
- {
498
- originX: originFallbackX,
499
- originY,
500
- overlayX: overlayFallbackX,
501
- overlayY,
502
- offsetY,
503
- },
504
- {
505
- originX,
506
- originY: originFallbackY,
507
- overlayX,
508
- overlayY: overlayFallbackY,
509
- offsetY: -offsetY,
510
- },
511
- {
512
- originX: originFallbackX,
513
- originY: originFallbackY,
514
- overlayX: overlayFallbackX,
515
- overlayY: overlayFallbackY,
516
- offsetY: -offsetY,
517
- },
518
- ]);
519
- }
520
- /** Returns a stream that emits whenever an action that should close the menu occurs. */
521
- _menuClosingActions() {
522
- const detachments = this._overlayRef?.detachments();
523
- const parentClose = this._parentMenu
524
- ? this._parentMenu.closed
525
- : observableOf();
526
- const hover = this._clientOutput.device === 'desktop' && this._parentMenu
527
- ? this._parentMenu._hovered().pipe(filter((item) => item !== this._menuItemInstance), filter(() => this._isMenuOpen))
528
- : observableOf();
529
- // Note: Quick fix. Feature reportedly exists in CDK for Angular 10
530
- // Filter to prevent closing when animating added though. Applied to
531
- // root menu only.
532
- const outsideClick = !this._parentMenu
533
- ? fromEvent(this._document, 'click').pipe(filter((e) => e.target !== this._element.nativeElement &&
534
- e.target.closest('.granite-menu') === null), filter(() => !this.menu._isAnimating))
535
- : observableOf();
536
- return merge(detachments, hover, parentClose, outsideClick);
537
- }
538
- /**
539
- * Whether to automatically open submenus on hover. This is true when showing
540
- * desktop menus and having mouse support.
541
- */
542
- _openOnHover() {
543
- return ((this.triggersSubmenu()
544
- ? this._parentMenu.openOnHover
545
- : this.menu.openOnHover) &&
546
- this._parentMenu._clientOutput?.device === 'desktop' &&
547
- this._parentMenu._clientInput?.devices.includes('mouse'));
548
- }
549
- /**
550
- * Whether to toggle submenus on click. This is true when showing desktop menus
551
- * without mouse support. Which, by the way, is not a great idea to begin with.
552
- */
553
- _toggleOnSubmenuClick() {
554
- return (!(this.triggersSubmenu()
555
- ? this._parentMenu.openOnHover
556
- : this.menu.openOnHover) ||
557
- (this._parentMenu._clientOutput?.device === 'desktop' &&
558
- !this._parentMenu._clientInput?.devices.includes('mouse')));
559
- }
560
- // ------------------------------------------- //
561
- // --- Here be touch device customizations --- //
562
- // ------------------------------------------- //
563
- /** Set animation state to bring a newly opened menu into view */
564
- animateOpenMenu() {
565
- this._clientOutput.device === 'touch'
566
- ? this.animateTouchOpenMenu()
567
- : this.menu._startAnimation();
568
- }
569
- animateTouchOpenMenu() {
570
- if (this.triggersSubmenu()) {
571
- // Slide newly opened sub menu into view from the side,
572
- // pushing any parent menu out of view on the other side
573
- this.menu._startTouchSubmenuEnterAnimation();
574
- this._parentMenu._startTouchHideAnimation();
575
- }
576
- else {
577
- // Slide root menu into view from below
578
- this.menu._startTouchRootEnterAnimation();
579
- }
580
- }
581
- /** Set animation state to close the active menu */
582
- animateCloseMenu(toBelow, withDelay) {
583
- this._clientOutput.device === 'touch'
584
- ? this._animateTouchCloseMenu(toBelow, withDelay)
585
- : this._parentMenu._resetAnimation();
586
- }
587
- _animateTouchCloseMenu(toBelow, withDelay) {
588
- if (toBelow) {
589
- // Slide menu out of view below the viewport
590
- withDelay
591
- ? this.menu._startTouchCloseDownAnimationWithDelay()
592
- : this.menu._startTouchCloseDownAnimation();
593
- }
594
- else {
595
- // Slide the closed menu out of view to the side
596
- // and slide any parent menu back into view
597
- this.menu._startTouchCloseSideAnimation();
598
- this._parentMenu?._startTouchSubmenuEnterAnimation();
599
- }
600
- }
601
- /**
602
- * Set animation state to place the menu and any parent at the given
603
- * horizontal position, i.e. following touch pan movement.
604
- *
605
- * @param xOffset Horizontal offset
606
- */
607
- animateSetMenuPosition(xOffset) {
608
- this.menu._startTouchPanAnimation(xOffset);
609
- if (this._parentMenu) {
610
- this._parentMenu._startTouchHidePanAnimation(xOffset);
611
- }
612
- }
613
- /**
614
- * Returns strategy for positioning the overlay depending on what type of
615
- * device the menu is being shown on
616
- */
617
- _positionStrategy() {
618
- return this._clientOutput.device === 'touch'
619
- ? this._touchPositionStrategy()
620
- : this._desktopPositionStrategy();
621
- }
622
- /**
623
- * Returns strategy for positioning the overlay for touch devices:
624
- * Place centered at the bottom of the screen.
625
- */
626
- _touchPositionStrategy() {
627
- return this._overlay.position().global();
628
- }
629
- /**
630
- * Remove touch device pan/swipe listeners from overlay host element
631
- */
632
- addOverlayListeners() {
633
- this._overlayRef.hostElement.addEventListener('touchstart', this._handleOverlayTouchStart, passiveEventListenerOptions);
634
- this._overlayRef.hostElement.addEventListener('touchmove', this._handleOverlayTouchMove, passiveEventListenerOptions);
635
- this._overlayRef.hostElement.addEventListener('touchend', this._handleOverlayTouchEnd, passiveEventListenerOptions);
636
- }
637
- /**
638
- * Remove touch device pan/swipe listeners from overlay host element
639
- */
640
- removeOverlayListeners() {
641
- this._overlayRef.hostElement.removeEventListener('touchstart', this._handleOverlayTouchStart, passiveEventListenerOptions);
642
- this._overlayRef.hostElement.removeEventListener('touchmove', this._handleOverlayTouchMove, passiveEventListenerOptions);
643
- this._overlayRef.hostElement.removeEventListener('touchend', this._handleOverlayTouchEnd, passiveEventListenerOptions);
644
- }
645
- /**
646
- * Standard exponential ease out function
647
- *
648
- * @param current Current value
649
- * @param offset Offset value, to which calculated value will be added
650
- * @param target The target value
651
- * @param end Value to which current value is compared
652
- */
653
- easeOutExpo(current, offset, target, end) {
654
- return current === end
655
- ? offset + target
656
- : target * (-Math.pow(2, (-10 * current) / end) + 1) + offset;
657
- }
658
- }
659
- GraniteMenuTriggerForDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GraniteMenuTriggerForDirective, deps: [{ token: i1.Overlay }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: GRANITE_MENU_PANEL, optional: true }, { token: GRANITE_CLIENT_INPUT, optional: true }, { token: GRANITE_CLIENT_OUTPUT, optional: true }, { token: i2.GraniteMenuItemComponent, optional: true, self: true }, { token: i3.Directionality, optional: true }, { token: i4.FocusMonitor }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive });
660
- GraniteMenuTriggerForDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: GraniteMenuTriggerForDirective, selector: "[graniteMenuTriggerFor]", inputs: { menu: ["graniteMenuTriggerFor", "menu"], openOnClick: "openOnClick" }, host: { attributes: { "aria-haspopup": "true" }, listeners: { "mousedown": "_handleMousedown($event)", "keydown": "_handleKeydown($event)", "click": "_handleClick($event)" }, properties: { "attr.aria-expanded": "_isMenuOpen || null", "attr.aria-controls": "_isMenuOpen ? menu.panelId : null" }, classAttribute: "granite-menu-trigger" }, usesOnChanges: true, ngImport: i0 });
661
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: GraniteMenuTriggerForDirective, decorators: [{
662
- type: Directive,
663
- args: [{
664
- selector: `[graniteMenuTriggerFor]`,
665
- host: {
666
- class: 'granite-menu-trigger',
667
- 'aria-haspopup': 'true',
668
- '[attr.aria-expanded]': '_isMenuOpen || null',
669
- '[attr.aria-controls]': '_isMenuOpen ? menu.panelId : null',
670
- '(mousedown)': '_handleMousedown($event)',
671
- '(keydown)': '_handleKeydown($event)',
672
- '(click)': '_handleClick($event)',
673
- },
674
- }]
675
- }], ctorParameters: function () { return [{ type: i1.Overlay }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i5._MenuBaseComponent, decorators: [{
676
- type: Inject,
677
- args: [GRANITE_MENU_PANEL]
678
- }, {
679
- type: Optional
680
- }] }, { type: undefined, decorators: [{
681
- type: Inject,
682
- args: [GRANITE_CLIENT_INPUT]
683
- }, {
684
- type: Optional
685
- }] }, { type: undefined, decorators: [{
686
- type: Inject,
687
- args: [GRANITE_CLIENT_OUTPUT]
688
- }, {
689
- type: Optional
690
- }] }, { type: i2.GraniteMenuItemComponent, decorators: [{
691
- type: Optional
692
- }, {
693
- type: Self
694
- }] }, { type: i3.Directionality, decorators: [{
695
- type: Optional
696
- }] }, { type: i4.FocusMonitor }, { type: undefined, decorators: [{
697
- type: Inject,
698
- args: [DOCUMENT]
699
- }] }]; }, propDecorators: { menu: [{
700
- type: Input,
701
- args: ['graniteMenuTriggerFor']
702
- }], openOnClick: [{
703
- type: Input
704
- }] } });
705
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVudS10cmlnZ2VyLWZvci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2dyYW5pdGUtY29tcG9uZW50cy9zcmMvbGliL21lbnUvbWVudS10cmlnZ2VyLWZvci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUVMLFNBQVMsRUFDVCxVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFHTCxRQUFRLEVBQ1IsSUFBSSxFQUVKLGdCQUFnQixHQUNqQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFM0MsT0FBTyxFQUNMLFlBQVksRUFFWiwrQkFBK0IsR0FDaEMsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEUsT0FBTyxFQUdMLE9BQU8sRUFDUCxhQUFhLEdBSWQsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFckQsT0FBTyxFQUNMLGFBQWEsRUFDYixTQUFTLEVBQ1QsS0FBSyxFQUVMLEVBQUUsSUFBSSxZQUFZLEVBQ2xCLFlBQVksR0FDYixNQUFNLE1BQU0sQ0FBQztBQUNkLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVoRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDakQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakUsT0FBTyxFQUFtQixrQkFBa0IsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUVuRSw2Q0FBNkM7QUFDN0MsT0FBTyxFQUdM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NkJBTWxCLG9CQUFvQiw2QkFLcEIscUJBQXFCLDJLQWlCckIsUUFBUTsrR0E1RVAsOEJBQThCOzJGQUE5Qiw4QkFBOEI7a0JBWjFDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLHlCQUF5QjtvQkFDbkMsSUFBSSxFQUFFO3dCQUNKLEtBQUssRUFBRSxzQkFBc0I7d0JBQzdCLGVBQWUsRUFBRSxNQUFNO3dCQUN2QixzQkFBc0IsRUFBRSxxQkFBcUI7d0JBQzdDLHNCQUFzQixFQUFFLG1DQUFtQzt3QkFDM0QsYUFBYSxFQUFFLDBCQUEwQjt3QkFDekMsV0FBVyxFQUFFLHdCQUF3Qjt3QkFDckMsU0FBUyxFQUFFLHNCQUFzQjtxQkFDbEM7aUJBQ0Y7OzBCQWlESSxNQUFNOzJCQUFDLGtCQUFrQjs7MEJBQ3pCLFFBQVE7OzBCQUtSLE1BQU07MkJBQUMsb0JBQW9COzswQkFDM0IsUUFBUTs7MEJBSVIsTUFBTTsyQkFBQyxxQkFBcUI7OzBCQUM1QixRQUFROzswQkFXUixRQUFROzswQkFBSSxJQUFJOzswQkFFaEIsUUFBUTs7MEJBR1IsTUFBTTsyQkFBQyxRQUFROzRDQXRFbEIsSUFBSTtzQkFESCxLQUFLO3VCQUFDLHVCQUF1QjtnQkFHckIsV0FBVztzQkFBbkIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9wdGlvbmFsLFxuICBTZWxmLFxuICBTaW1wbGVDaGFuZ2VzLFxuICBWaWV3Q29udGFpbmVyUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERPQ1VNRU5UIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHtcbiAgRm9jdXNNb25pdG9yLFxuICBGb2N1c09yaWdpbixcbiAgaXNGYWtlTW91c2Vkb3duRnJvbVNjcmVlblJlYWRlcixcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL2ExMXknO1xuaW1wb3J0IHsgRGlyZWN0aW9uYWxpdHkgfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcbmltcG9ydCB7XG4gIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSxcbiAgSG9yaXpvbnRhbENvbm5lY3Rpb25Qb3MsXG4gIE92ZXJsYXksXG4gIE92ZXJsYXlDb25maWcsXG4gIE92ZXJsYXlSZWYsXG4gIFBvc2l0aW9uU3RyYXRlZ3ksXG4gIFZlcnRpY2FsQ29ubmVjdGlvblBvcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgVGVtcGxhdGVQb3J0YWwgfSBmcm9tICdAYW5ndWxhci9jZGsvcG9ydGFsJztcblxuaW1wb3J0IHtcbiAgYXNhcFNjaGVkdWxlcixcbiAgZnJvbUV2ZW50LFxuICBtZXJnZSxcbiAgT2JzZXJ2YWJsZSxcbiAgb2YgYXMgb2JzZXJ2YWJsZU9mLFxuICBTdWJzY3JpcHRpb24sXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVsYXksIGZpbHRlciwgdGFrZSwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBfTWVudUJhc2VDb21wb25lbnQgfSBmcm9tICcuL21lbnUtYmFzZSc7XG5pbXBvcnQgeyBHcmFuaXRlTWVudUl0ZW1Db21wb25lbnQgfSBmcm9tICcuL21lbnUtaXRlbS5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ2xvc2VkRXZlbnRUeXBlLCBHUkFOSVRFX01FTlVfUEFORUwgfSBmcm9tICcuL21lbnUtcGFuZWwnO1xuXG4vLyNyZWdpb24gLS0tIFRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS1cbmltcG9ydCB7XG4gIENsaWVudElucHV0SW50ZXJmYWNlLFxuICBDbGllbnRPdXRwdXRJbnRlcmZhY2UsXG4gIEdSQU5JVEVfQ0xJRU5UX0lOUFVULFxuICBHUkFOSVRFX0NMSUVOVF9PVVRQVVQsXG59IGZyb20gJy4uL2NvcmUvY2xpZW50LWVudmlyb25tZW50JztcbmltcG9ydCB7IHRocm93R3Jhbml0ZU1lbnVNaXNzaW5nRXJyb3IgfSBmcm9tICcuL21lbnUtZXJyb3JzJztcblxuLyoqIE9wdGlvbnMgZm9yIGJpbmRpbmcgYSBwYXNzaXZlIGV2ZW50IGxpc3RlbmVyLiAqL1xuY29uc3QgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zID0gbm9ybWFsaXplUGFzc2l2ZUxpc3RlbmVyT3B0aW9ucyh7XG4gIHBhc3NpdmU6IHRydWUsXG59KTtcbi8vI2VuZHJlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuXG4vKipcbiAqIERpcmVjdGl2ZSB1c2VkIHRvIHR1cm4gYSBidXR0b24gZWxlbWVudCBpbnRvIGEgKHBvcHVwKSBtZW51IHRyaWdnZXJcbiAqXG4gKiBTdHJpcHBlZC1kb3duIHZlcnNpb24gb2YgQW5ndWxhciBNYXRlcmlhbCdzIG1lbnUgdHJpZ2dlciBkaXJlY3RpdmUgKC4uLi9tZW51L21lbnUtdHJpZ2dlci50cylcbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiBgW2dyYW5pdGVNZW51VHJpZ2dlckZvcl1gLFxuICBob3N0OiB7XG4gICAgY2xhc3M6ICdncmFuaXRlLW1lbnUtdHJpZ2dlcicsIC8vIFJlcXVpcmVkIGZvciB0ZXN0IGhhcm5lc3MgaG9zdCBzZWxlY3RvclxuICAgICdhcmlhLWhhc3BvcHVwJzogJ3RydWUnLFxuICAgICdbYXR0ci5hcmlhLWV4cGFuZGVkXSc6ICdfaXNNZW51T3BlbiB8fCBudWxsJyxcbiAgICAnW2F0dHIuYXJpYS1jb250cm9sc10nOiAnX2lzTWVudU9wZW4gPyBtZW51LnBhbmVsSWQgOiBudWxsJyxcbiAgICAnKG1vdXNlZG93biknOiAnX2hhbmRsZU1vdXNlZG93bigkZXZlbnQpJyxcbiAgICAnKGtleWRvd24pJzogJ19oYW5kbGVLZXlkb3duKCRldmVudCknLFxuICAgICcoY2xpY2spJzogJ19oYW5kbGVDbGljaygkZXZlbnQpJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgR3Jhbml0ZU1lbnVUcmlnZ2VyRm9yRGlyZWN0aXZlXG4gIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXNcbntcbiAgLyoqIFJlZmVyZW5jZXMgdGhlIG1lbnUgaW5zdGFuY2UgdGhhdCB0aGUgdHJpZ2dlciBpcyBhc3NvY2lhdGVkIHdpdGguICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvbm8taW5wdXQtcmVuYW1lXG4gIEBJbnB1dCgnZ3Jhbml0ZU1lbnVUcmlnZ2VyRm9yJylcbiAgbWVudTogX01lbnVCYXNlQ29tcG9uZW50O1xuXG4gIEBJbnB1dCgpIG9wZW5PbkNsaWNrPzogYm9vbGVhbiA9IHRydWU7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIGFzc29jaWF0ZWQgbWVudSBpcyBvcGVuICovXG4gIF9pc01lbnVPcGVuOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLy8gVHJhY2tpbmcgaW5wdXQgdHlwZSBpcyBuZWNlc3Nhcnkgc28gaXQncyBwb3NzaWJsZSB0byBvbmx5IGF1dG8tZm9jdXNcbiAgLy8gdGhlIGZpcnN0IGl0ZW0gb2YgdGhlIGxpc3Qgd2hlbiB0aGUgbWVudSBpcyBvcGVuZWQgdmlhIHRoZSBrZXlib2FyZFxuICBfb3BlbmVkQnk6ICdtb3VzZScgfCAndG91Y2gnIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBfaG92ZXJTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG4gIHByaXZhdGUgX21lbnVDbG9zZVN1YnNjcmlwdGlvbiA9IFN1YnNjcmlwdGlvbi5FTVBUWTtcbiAgcHJpdmF0ZSBfY2xvc2luZ0FjdGlvbnNTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cbiAgcHJpdmF0ZSBfcG9ydGFsOiBUZW1wbGF0ZVBvcnRhbCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgX2RvY3VtZW50PzogRG9jdW1lbnQ7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cbiAgLy8gLS0tIEhlcmUgYmUgcG9vciBtYW4ncyB0b3VjaCBnZXN0dXJlcyAtLS0gLy9cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggSGFtbWVyIG9yIG90aGVyIGdlc3R1cmUgbGlicmFyeVxuXG4gIHByaXZhdGUgX3RvdWNoU3RhcnRUaW1lOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoVGltZVRha2VuOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoU3RhcnRYOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoU3RhcnRZOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoQ3VycmVudFg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfdG91Y2hDdXJyZW50WTogbnVtYmVyO1xuICBwcml2YXRlIF90b3VjaFRyYW5zbGF0ZVg6IG51bWJlcjtcbiAgcHJpdmF0ZSBfdG91Y2hMb2NrZWRYOiBib29sZWFuIHwgbnVsbDtcbiAgcHJpdmF0ZSBfdG91Y2hNYXhYOiBudW1iZXI7XG4gIHByaXZhdGUgX3RvdWNoVG91Y2hpbmdFbGVtZW50OiBib29sZWFuID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfb3ZlcmxheTogT3ZlcmxheSxcbiAgICBwcml2YXRlIF9lbGVtZW50OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgICBwcml2YXRlIF92aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLFxuXG4gICAgLyoqIElmIHRoaXMgaXMgYSBfc3VibWVudV8gdHJpZ2dlciwgaXQgd2lsbCBoYXZlIGEgcGFyZW50IG1lbnUgKi9cbiAgICBASW5qZWN0KEdSQU5JVEVfTUVOVV9QQU5FTClcbiAgICBAT3B0aW9uYWwoKVxuICAgIHByaXZhdGUgX3BhcmVudE1lbnU6IF9NZW51QmFzZUNvbXBvbmVudCxcblxuICAgIC8vI3JlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgIC8qKiBDbGllbnQgaW5wdXQgZGV2aWNlIGluZm9ybWF0aW9uICovXG4gICAgQEluamVjdChHUkFOSVRFX0NMSUVOVF9JTlBVVClcbiAgICBAT3B0aW9uYWwoKVxuICAgIHB1YmxpYyBfY2xpZW50SW5wdXQ6IENsaWVudElucHV0SW50ZXJmYWNlLFxuXG4gICAgLyoqIENsaWVudCBvdXRwdXQgZGV2aWNlIGluZm9ybWF0aW9uICovXG4gICAgQEluamVjdChHUkFOSVRFX0NMSUVOVF9PVVRQVVQpXG4gICAgQE9wdGlvbmFsKClcbiAgICBwdWJsaWMgX2NsaWVudE91dHB1dDogQ2xpZW50T3V0cHV0SW50ZXJmYWNlLFxuICAgIC8vI2VuZHJlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuXG4gICAgLyoqXG4gICAgICogSWYgdGhpcyBpcyBhIF9zdWJtZW51XyB0cmlnZ2VyLCB0aGVyZSBzaG91bGQgYmUgYSBjb3JyZXNwb25kaW5nIG1lbnVcbiAgICAgKiBpdGVtIGRpcmVjdGl2ZSBwcmVzZW50IGFzIHdlbGw6XG4gICAgICpcbiAgICAgKiAgICAgPGJ1dHRvbiBncmFuaXRlTWVudUl0ZW0gW2dyYW5pdGVNZW51VHJpZ2dlckZvcl09XCIuLi5cIj5cbiAgICAgKiAgICAgICAgICAgICAgICAgICBeLS0gVGhpcyBvbmVcbiAgICAgKi9cbiAgICBAT3B0aW9uYWwoKSBAU2VsZigpIHByaXZhdGUgX21lbnVJdGVtSW5zdGFuY2U6IEdyYW5pdGVNZW51SXRlbUNvbXBvbmVudCxcblxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgX2RpcjogRGlyZWN0aW9uYWxpdHksXG4gICAgcHJpdmF0ZSBfZm9jdXNNb25pdG9yOiBGb2N1c01vbml0b3IsXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1tb2R1bGUtYm91bmRhcnktdHlwZXNcbiAgICBASW5qZWN0KERPQ1VNRU5UKSBkb2N1bWVudD86IGFueVxuICApIHtcbiAgICBfZWxlbWVudC5uYXRpdmVFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAndG91Y2hzdGFydCcsXG4gICAgICB0aGlzLl9oYW5kbGVUb3VjaFN0YXJ0LFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIGlmIChfbWVudUl0ZW1JbnN0YW5jZSkge1xuICAgICAgX21lbnVJdGVtSW5zdGFuY2UuX3RyaWdnZXJzU3VibWVudSA9IHRoaXMudHJpZ2dlcnNTdWJtZW51KCk7XG4gICAgfVxuXG4gICAgdGhpcy5fZG9jdW1lbnQgPSBkb2N1bWVudCBhcyBEb2N1bWVudDtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlcy5tZW51KSB7XG4gICAgICB0aGlzLl9oYW5kbGVNZW51Q2hhbmdlKCk7XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIC8vIHJlbW92ZWQgY2hlY2tNZW51IGhlcmUgdG8gYXZvaWQgZXJyb3JzIGluIGR5bmFtaWNhbGx5IGdlbmFyYXRlZCBtZW51c1xuICAgIC8vIG1lbnUgaXMgY2hlY2tlZCB3aGVuIG9wZW5pbmcgdGhlIG1lbnVcbiAgICAvLyB0aGlzLl9jaGVja01lbnUoKTtcbiAgICB0aGlzLl9oYW5kbGVIb3ZlcigpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX292ZXJsYXlSZWYpIHtcbiAgICAgIC8vI3JlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgICAgdGhpcy5yZW1vdmVPdmVybGF5TGlzdGVuZXJzKCk7XG4gICAgICAvLyNlbmRyZWdpb24gLS0tIFRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS1cbiAgICAgIHRoaXMuX292ZXJsYXlSZWYuZGlzcG9zZSgpO1xuICAgICAgdGhpcy5fb3ZlcmxheVJlZiA9IG51bGw7XG4gICAgfVxuXG4gICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAndG91Y2hzdGFydCcsXG4gICAgICB0aGlzLl9oYW5kbGVUb3VjaFN0YXJ0LFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIHRoaXMuX2hvdmVyU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fbWVudUNsb3NlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5fY2xvc2luZ0FjdGlvbnNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIC8qKiBIYW5kbGVzIGNoYW5nZSBvZiBhc3NvY2lhdGVkIG1lbnUgKi9cbiAgX2hhbmRsZU1lbnVDaGFuZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5fbWVudUNsb3NlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG5cbiAgICAvLyBDbG9zZSB0aGUgbWVudSBvdmVybGF5IHdoZW4gdGhlIG1lbnUgaXRzZWxmIHNheXMgaXQgd2FudHMgdG8gYmUgY2xvc2VkXG4gICAgaWYgKHRoaXMubWVudSkge1xuICAgICAgY29uc3QgY2xvc2VkID0gdGhpcy5tZW51LmNsb3NlZCBhcyBPYnNlcnZhYmxlPENsb3NlZEV2ZW50VHlwZT47XG5cbiAgICAgIHRoaXMuX21lbnVDbG9zZVN1YnNjcmlwdGlvbiA9IGNsb3NlZC5zdWJzY3JpYmUoKHJlYXNvbikgPT4ge1xuICAgICAgICAvLyNyZWdpb24gLS0tIFRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS1cbiAgICAgICAgaWYgKHRoaXMubWVudS5faXNDbG9zaW5nKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWVudS5faXNDbG9zaW5nID0gdHJ1ZTtcblxuICAgICAgICAvLyBHZXQgcmlkIG9mIHRoZSBtZW51IGFuZCB0ZWxsIGFueSBwYXJlbnQgdG8gcmVzdG9yZSBpdHMgcG9zaXRpb25cbiAgICAgICAgaWYgKHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcpIHtcbiAgICAgICAgICAvLyBGaXJzdCB3ZSB3YWl0IGZvciBhbnkgcnVubmluZyBhbmltYXRpb24gdG8gY29tcGxldGVcbiAgICAgICAgICBjb25zdCBydW5uaW5nQW5pbWF0aW9uRG9uZTogT2JzZXJ2YWJsZTxhbnk+ID0gdGhpcy5tZW51Ll9pc0FuaW1hdGluZ1xuICAgICAgICAgICAgPyB0aGlzLm1lbnUuX2FuaW1hdGlvbkRvbmVcbiAgICAgICAgICAgIDogb2JzZXJ2YWJsZU9mKFtudWxsXSk7XG5cbiAgICAgICAgICBydW5uaW5nQW5pbWF0aW9uRG9uZVxuICAgICAgICAgICAgLnBpcGUodGFrZSgxKSwgZGVsYXkoMCwgYXNhcFNjaGVkdWxlcikpXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcnhqcy9uby1uZXN0ZWQtc3Vic2NyaWJlXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgICAgdGhpcy5hbmltYXRlQ2xvc2VNZW51KHJlYXNvbiAhPT0gJ2tleWRvd24nLCByZWFzb24gPT09ICdjbGljaycpO1xuICAgICAgICAgICAgICB0aGlzLm1lbnUuX2FuaW1hdGlvbkRvbmVcbiAgICAgICAgICAgICAgICAucGlwZSh0YWtlKDEpLCBkZWxheSgwLCBhc2FwU2NoZWR1bGVyKSlcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcnhqcy9uby1uZXN0ZWQtc3Vic2NyaWJlXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9kZXN0cm95TWVudSgpKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vI2VuZHJlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgICAgICAgIHRoaXMuX2Rlc3Ryb3lNZW51KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBhIGNsaWNrIGNsb3NlZCB0aGUgbWVudSwgd2Ugc2hvdWxkIGNsb3NlIHRoZSBlbnRpcmUgY2hhaW4gb2YgbmVzdGVkIG1lbnVzLlxuICAgICAgICBpZiAoKHJlYXNvbiA9PT0gJ2NsaWNrJyB8fCByZWFzb24gPT09ICd0YWInKSAmJiB0aGlzLl9wYXJlbnRNZW51KSB7XG4gICAgICAgICAgdGhpcy5fcGFyZW50TWVudS5jbG9zZWQuZW1pdChyZWFzb24pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBpc09wZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2lzTWVudU9wZW47XG4gIH1cblxuICAvKiogT3BlbiB0aGUgYXNzb2NpYXRlZCBtZW51ICovXG4gIG9wZW5NZW51KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9pc01lbnVPcGVuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY2hlY2tNZW51KCk7XG5cbiAgICB0aGlzLm1lbnUucGFyZW50TWVudSA9IHRoaXMudHJpZ2dlcnNTdWJtZW51KClcbiAgICAgID8gdGhpcy5fcGFyZW50TWVudVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgdGhpcy5tZW51LmRpcmVjdGlvbiA9IHRoaXMuX2Rpci52YWx1ZSA9PT0gJ3J0bCcgPyAncnRsJyA6ICdsdHInO1xuXG4gICAgaWYgKHRoaXMuX3BhcmVudE1lbnUpIHtcbiAgICAgIC8vIE1lbnUgdHJpZ2dlcnMgaW5oZXJpdCB0YXJnZXQgZGV2aWNlIHR5cGVzIGZyb20gdGhlaXIgcGFyZW50LlxuICAgICAgLy8gVWx0aW1hdGVseSBpdCBpcyB0aGUgcm9vdCB0cmlnZ2VyIHRoYXQgZGV0ZXJtaW5lcyBkZXZpY2UgdHlwZXMgZm9yXG4gICAgICAvLyB0aGUgd2hvbGUgbWVudSBoaWVyYXJjaHkuXG4gICAgICB0aGlzLl9jbGllbnRJbnB1dCA9IHRoaXMuX3BhcmVudE1lbnUuX2NsaWVudElucHV0O1xuICAgICAgdGhpcy5fY2xpZW50T3V0cHV0ID0gdGhpcy5fcGFyZW50TWVudS5fY2xpZW50T3V0cHV0O1xuICAgIH1cblxuICAgIC8vI3JlZ2lvbiAtLS0gVG91Y2ggZGV2aWNlIGN1c3RvbWl6YXRpb25zIC0tLVxuICAgIC8vIE1ha2UgdGhlIG1lbnUgd2UncmUgYWJvdXQgdG8gb3BlbiB1c2UgdGhlIHNhbWUgZGV2aWNlcyBhcyB0aGUgdHJpZ2dlclxuICAgIHRoaXMubWVudS5fc2V0RGV2aWNlKHRoaXMuX2NsaWVudElucHV0LCB0aGlzLl9jbGllbnRPdXRwdXQpO1xuXG4gICAgaWYgKHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcpIHtcbiAgICAgIHRoaXMubWVudS5zaG93QmFja0J1dHRvbiA9ICEhdGhpcy5fcGFyZW50TWVudTtcbiAgICAgIHRoaXMubWVudS5fdXBkYXRlU2hvd1RpdGxlKCk7XG5cbiAgICAgIGlmICghdGhpcy5tZW51LmNsb3NlTGFiZWwpIHtcbiAgICAgICAgdGhpcy5tZW51LmNsb3NlTGFiZWwgPSB0aGlzLl9wYXJlbnRNZW51Py5jbG9zZUxhYmVsO1xuICAgICAgfVxuXG4gICAgICB0aGlzLm1lbnUuc2hvd0Nsb3NlQnV0dG9uID0gISF0aGlzLm1lbnUuY2xvc2VMYWJlbDtcbiAgICB9XG4gICAgdGhpcy5tZW51Ll9pc0Nsb3NpbmcgPSBmYWxzZTtcblxuICAgIGNvbnN0IHBhbmVsQ2xhc3M6IHN0cmluZ1tdID0gW107XG4gICAgaWYgKHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcpIHtcbiAgICAgIHBhbmVsQ2xhc3MucHVzaCgnZ3Jhbml0ZS1vdmVybGF5LXBhbmUtZmlsbC13aWR0aC1ib3R0b20nKTtcbiAgICB9XG5cbiAgICBjb25zdCBzY3JvbGxTdHJhdGVneSA9XG4gICAgICB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlICE9PSAndG91Y2gnXG4gICAgICAgID8gdGhpcy5fb3ZlcmxheS5zY3JvbGxTdHJhdGVnaWVzLnJlcG9zaXRpb24oKVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGhhc0JhY2tkcm9wID1cbiAgICAgIHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCcgJiYgIXRoaXMudHJpZ2dlcnNTdWJtZW51KCk7XG4gICAgLy8jZW5kcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG5cbiAgICAvLyBDcmVhdGUgYW4gb3ZlcmxheSB0byBzdHVmZiB0aGUgbWVudSAocG9ydGFsKSBpbnRvIGJlbG93XG4gICAgaWYgKCF0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICBjb25zdCBjb25maWcgPSBuZXcgT3ZlcmxheUNvbmZpZyh7XG4gICAgICAgIHBvc2l0aW9uU3RyYXRlZ3k6IHRoaXMuX3Bvc2l0aW9uU3RyYXRlZ3koKSxcbiAgICAgICAgYmFja2Ryb3BDbGFzczogJ2dyYW5pdGUtb3ZlcmxheS1kYXJrLWdsYXNzLWJhY2tkcm9wJyxcbiAgICAgICAgc2Nyb2xsU3RyYXRlZ3ksXG4gICAgICAgIGRpcmVjdGlvbjogdGhpcy5fZGlyLFxuICAgICAgICBwYW5lbENsYXNzLFxuICAgICAgICBoYXNCYWNrZHJvcCxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fb3ZlcmxheS5jcmVhdGUoY29uZmlnKTtcblxuICAgICAgLy8jcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgICAvLyBBZGQgdG91Y2ggbGlzdGVuZXIgZm9yIHN1Ym1lbnUgYmFjayBwYW4vc3dpcGVcbiAgICAgIGlmICh0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnKSB7XG4gICAgICAgIHRoaXMuYWRkT3ZlcmxheUxpc3RlbmVycygpO1xuICAgICAgfVxuICAgICAgLy8jZW5kcmVnaW9uIC0tLSBUb3VjaCBkZXZpY2UgY3VzdG9taXphdGlvbnMgLS0tXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlc2V0IGFuaW1hdGlvbiBzdGF0ZSBmb3IgcmV1c2VkIG92ZXJsYXlzXG4gICAgICBpZiAodGhpcy5fY2xpZW50T3V0cHV0LmRldmljZSA9PT0gJ3RvdWNoJykge1xuICAgICAgICB0aGlzLm1lbnUuX3BhbmVsQW5pbWF0aW9uU3RhdGUgPSAndm9pZCc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIHBvcnRhbCBmcm9tIGFzc29jaWF0ZWQgbWVudSdzIHRlbXBsYXRlXG4gICAgaWYgKCF0aGlzLl9wb3J0YWwgfHwgdGhpcy5fcG9ydGFsLnRlbXBsYXRlUmVmICE9PSB0aGlzLm1lbnUudGVtcGxhdGVSZWYpIHtcbiAgICAgIHRoaXMuX3BvcnRhbCA9IG5ldyBUZW1wbGF0ZVBvcnRhbChcbiAgICAgICAgdGhpcy5tZW51LnRlbXBsYXRlUmVmLFxuICAgICAgICB0aGlzLl92aWV3Q29udGFpbmVyUmVmXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEF0dGFjaCBtZW51IHBvcnRhbCB0byBvdmVybGF5IHJlZiAod2hpY2ggaXMgYSBwb3J0YWwgb3V0bGV0KVxuICAgIHRoaXMuX292ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCk7XG5cbiAgICAvLyBTdWJzY3JpYmUgdG8gc3RyZWFtIHRoYXQgZW1pdHMgd2hlbmV2ZXIgYW4gYWN0aW9uIHRoYXQgc2hvdWxkIGNsb3NlIHRoZSBtZW51IG9jY3Vyc1xuICAgIHRoaXMuX2Nsb3NpbmdBY3Rpb25zU3Vic2NyaXB0aW9uID0gdGhpcy5fbWVudUNsb3NpbmdBY3Rpb25zKCkuc3Vic2NyaWJlKFxuICAgICAgKCkgPT4gdGhpcy5jbG9zZU1lbnUoKVxuICAgICk7XG5cbiAgICB0aGlzLmFuaW1hdGVPcGVuTWVudSgpO1xuXG4gICAgdGhpcy5fc2V0SXNNZW51T3Blbih0cnVlKTtcbiAgICB0aGlzLm1lbnUuZm9jdXNGaXJzdEl0ZW0odGhpcy5fb3BlbmVkQnkgfHwgJ3Byb2dyYW0nKTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSBtZW51IHRyaWdnZXJzIGEgc3ViLW1lbnUgb3IgYSB0b3AtbGV2ZWwgb25lLiAqL1xuICB0cmlnZ2Vyc1N1Ym1lbnUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKHRoaXMuX21lbnVJdGVtSW5zdGFuY2UgJiYgdGhpcy5fcGFyZW50TWVudSk7XG4gIH1cblxuICAvKiogVG9nZ2xlcyB0aGUgbWVudSBiZXR3ZWVuIHRoZSBvcGVuIGFuZCBjbG9zZWQgc3RhdGVzLiAqL1xuICB0b2dnbGVNZW51KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9pc01lbnVPcGVuKSB7XG4gICAgICB0aGlzLmNsb3NlTWVudSgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5vcGVuT25DbGljaykge1xuICAgICAgdGhpcy5vcGVuTWVudSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBDbG9zZSB0aGUgYXNzb2NpYXRlZCBtZW51ICovXG4gIGNsb3NlTWVudSgpOiB2b2lkIHtcbiAgICB0aGlzLm1lbnUuY2xvc2VkLmVtaXQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1c2VzIHRoZSBtZW51IHRyaWdnZXIuXG4gICAqIEBwYXJhbSBvcmlnaW4gU291cmNlIG9mIHRoZSBtZW51IHRyaWdnZXIncyBmb2N1cy5cbiAgICovXG4gIGZvY3VzKG9yaWdpbjogRm9jdXNPcmlnaW4gPSAncHJvZ3JhbScsIG9wdGlvbnM/OiBGb2N1c09wdGlvbnMpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZm9jdXNNb25pdG9yKSB7XG4gICAgICB0aGlzLl9mb2N1c01vbml0b3IuZm9jdXNWaWEodGhpcy5fZWxlbWVudCwgb3JpZ2luLCBvcHRpb25zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBEZXRhY2ggbWVudSBwb3J0YWwgZnJvbSBvdmVybGF5IGFuZCB1cGRhdGUgb3BlbiBzdGF0ZSAqL1xuICBfZGVzdHJveU1lbnUoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9vdmVybGF5UmVmIHx8ICF0aGlzLl9pc01lbnVPcGVuKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fY2xvc2luZ0FjdGlvbnNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLl9vdmVybGF5UmVmLmRldGFjaCgpO1xuICAgIHRoaXMuX3Jlc3RvcmVGb2N1cygpO1xuICAgIHRoaXMubWVudS5fcmVzZXRBbmltYXRpb24oKTtcblxuICAgIHRoaXMuX3NldElzTWVudU9wZW4oZmFsc2UpO1xuICB9XG5cbiAgLyoqIEhhbmRsZXMgbW91c2UgcHJlc3NlcyBvbiB0aGUgdHJpZ2dlci4gKi9cbiAgX2hhbmRsZU1vdXNlZG93bihldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICghaXNGYWtlTW91c2Vkb3duRnJvbVNjcmVlblJlYWRlcihldmVudCkpIHtcbiAgICAgIGlmICh0aGlzLl9vcGVuZWRCeSAhPT0gJ3RvdWNoJykge1xuICAgICAgICAvLyBTaW5jZSByaWdodCBvciBtaWRkbGUgYnV0dG9uIGNsaWNrcyB3b24ndCB0cmlnZ2VyIHRoZSBgY2xpY2tgIGV2ZW50LFxuICAgICAgICAvLyB3ZSBzaG91bGRuJ3QgY29uc2lkZXIgdGhlIG1lbnUgYXMgb3BlbmVkIGJ5IG1vdXNlIGluIHRob3NlIGNhc2VzLlxuICAgICAgICB0aGlzLl9vcGVuZWRCeSA9IGV2ZW50LmJ1dHRvbiA9PT0gMCA/ICdtb3VzZScgOiBudWxsO1xuICAgICAgfVxuXG4gICAgICAvLyBTaW5jZSBjbGlja2luZyBvbiB0aGUgdHJpZ2dlciB3b24ndCBjbG9zZSB0aGUgbWVudSBpZiBpdCBvcGVucyBhIHN1Yi1tZW51LFxuICAgICAgLy8gd2Ugc2hvdWxkIHByZXZlbnQgZm9jdXMgZnJvbSBtb3Zpbmcgb250byBpdCB2aWEgY2xpY2sgdG8gYXZvaWQgdGhlXG4gICAgICAvLyBoaWdobGlnaHQgZnJvbSBsaW5nZXJpbmcgb24gdGhlIG1lbnUgaXRlbS5cbiAgICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpICYmICF0aGlzLl90b2dnbGVPblN1Ym1lbnVDbGljaygpKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqIEhhbmRsZXMga2V5IHByZXNzZXMgb24gdGhlIHRyaWdnZXIuICovXG4gIF9oYW5kbGVLZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3Qga2V5ID0gZXZlbnQua2V5O1xuXG4gICAgaWYgKFxuICAgICAgdGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSAmJlxuICAgICAgKChrZXkgPT09ICdBcnJvd1JpZ2h0JyAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdsdHInKSB8fFxuICAgICAgICAoa2V5ID09PSAnQXJyb3dMZWZ0JyAmJiB0aGlzLl9kaXIudmFsdWUgPT09ICdydGwnKSlcbiAgICApIHtcbiAgICAgIHRoaXMub3Blbk1lbnUoKTtcbiAgICB9XG4gIH1cblxuICAvKiogSGFuZGxlcyBjbGljayBldmVudHMgb24gdGhlIHRyaWdnZXIuICovXG4gIF9oYW5kbGVDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpKSB7XG4gICAgICAvLyBTdG9wIGV2ZW50IHByb3BhZ2F0aW9uIHRvIGF2b2lkIGNsb3NpbmcgdGhlIHBhcmVudCBtZW51LlxuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIHRoaXMuX3RvZ2dsZU9uU3VibWVudUNsaWNrKCkgPyB0aGlzLnRvZ2dsZU1lbnUoKSA6IHRoaXMub3Blbk1lbnUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy50b2dnbGVNZW51KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZXMgdG91Y2ggc3RhcnQgZXZlbnRzIG9uIHRoZSB0cmlnZ2VyLlxuICAgKiBOZWVkcyB0byBiZSBhbiBhcnJvdyBmdW5jdGlvbiBzbyB3ZSBjYW4gZWFzaWx5IHVzZSBhZGRFdmVudExpc3RlbmVyIGFuZCByZW1vdmVFdmVudExpc3RlbmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlVG91Y2hTdGFydCA9ICgpID0+IHtcbiAgICB0aGlzLl9vcGVuZWRCeSA9ICd0b3VjaCc7XG4gIH07XG5cbiAgLyoqIEhhbmRsZXMgdGhlIGNhc2VzIHdoZXJlIHRoZSB1c2VyIGhvdmVycyBvdmVyIHRoZSB0cmlnZ2VyLiAqL1xuICBwcml2YXRlIF9oYW5kbGVIb3ZlcigpIHtcbiAgICAvLyBTdWJzY3JpYmUgdG8gY2hhbmdlcyBpbiB0aGUgaG92ZXJlZCBpdGVtIGluIG9yZGVyIHRvIHRvZ2dsZSB0aGUgcGFuZWwuXG4gICAgaWYgKCF0aGlzLnRyaWdnZXJzU3VibWVudSgpIHx8ICF0aGlzLl9wYXJlbnRNZW51KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5faG92ZXJTdWJzY3JpcHRpb24gPSB0aGlzLl9wYXJlbnRNZW51XG4gICAgICAuX2hvdmVyZWQoKVxuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLl9vcGVuT25Ib3ZlcigpKSxcbiAgICAgICAgLy8gU2luY2Ugd2UgbWlnaHQgaGF2ZSBtdWx0aXBsZSBjb21wZXRpbmcgdHJpZ2dlcnMgZm9yIHRoZSBzYW1lIG1lbnUgKGUuZy4gYSBzdWItbWVudVxuICAgICAgICAvLyB3aXRoIGRpZmZlcmVudCBkYXRhIGFuZCB0cmlnZ2VycyksIHdlIGhhdmUgdG8gZGVsYXkgaXQgYnkgYSB0aWNrIHRvIGVuc3VyZSB0aGF0XG4gICAgICAgIC8vIGl0IHdvbid0IGJlIGNsb3NlZCBpbW1lZGlhdGVseSBhZnRlciBpdCBpcyBvcGVuZWQuXG4gICAgICAgIGZpbHRlcihcbiAgICAgICAgICAoYWN0aXZlKSA9PiBhY3RpdmUgPT09IHRoaXMuX21lbnVJdGVtSW5zdGFuY2UgLyomJiAhYWN0aXZlLmRpc2FibGVkKi9cbiAgICAgICAgKSxcbiAgICAgICAgZGVsYXkoMCwgYXNhcFNjaGVkdWxlcilcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLl9vcGVuZWRCeSA9ICdtb3VzZSc7XG5cbiAgICAgICAgLy8gSWYgdGhlIHNhbWUgbWVudSBpcyB1c2VkIGJldHdlZW4gbXVsdGlwbGUgdHJpZ2dlcnMsIGl0IG1pZ2h0IHN0aWxsIGJlIGFuaW1hdGluZ1xuICAgICAgICAvLyB3aGlsZSB0aGUgbmV3IHRyaWdnZXIgdHJpZXMgdG8gcmUtb3BlbiBpdC4gV2FpdCBmb3IgdGhlIGFuaW1hdGlvbiB0byBmaW5pc2hcbiAgICAgICAgLy8gYmVmb3JlIGRvaW5nIHNvLiBBbHNvIGludGVycnVwdCBpZiB0aGUgdXNlciBtb3ZlcyB0byBhbm90aGVyIGl0ZW0uXG4gICAgICAgIGlmICh0aGlzLm1lbnUgaW5zdGFuY2VvZiBfTWVudUJhc2VDb21wb25lbnQgJiYgdGhpcy5tZW51Ll9pc0FuaW1hdGluZykge1xuICAgICAgICAgIC8vIFdlIG5lZWQgdGhlIGBkZWxheSgwKWAgaGVyZSBpbiBvcmRlciB0byBhdm9pZFxuICAgICAgICAgIC8vICdjaGFuZ2VkIGFmdGVyIGNoZWNrZWQnIGVycm9ycyBpbiBzb21lIGNhc2VzLiBTZWUgQW5ndWxhciBNYXRlcmlhbCAjMTIxOTQuXG4gICAgICAgICAgdGhpcy5tZW51Ll9hbmltYXRpb25Eb25lXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICAgICAgZGVsYXkoMCwgYXNhcFNjaGVkdWxlciksXG4gICAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl9wYXJlbnRNZW51Ll9ob3ZlcmVkKCkpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcnhqcy9uby1uZXN0ZWQtc3Vic2NyaWJlXG4gICAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMub3Blbk1lbnUoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5vcGVuTWVudSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXN0b3JlcyBmb2N1cyB0byB0aGUgZWxlbWVudCB0aGF0IHdhcyBmb2N1c2VkIGJlZm9yZSB0aGUgbWVudSB3YXMgb3Blbi5cbiAgICogQ291bGQgYmUgdGhlIHJvb3QgdHJpZ2dlciBidXR0b24gb3IgYSBzdWJtZW51IHRyaWdnZXIgaXRlbVxuICAgKi9cbiAgcHJpdmF0ZSBfcmVzdG9yZUZvY3VzKCkge1xuICAgIC8vIFdlIHNob3VsZCByZXNldCBmb2N1cyBpZiB0aGUgdXNlciBpcyBuYXZpZ2F0aW5nIHVzaW5nIGEga2V5Ym9hcmQgb3JcbiAgICAvLyBpZiB3ZSBoYXZlIGEgdG9wLWxldmVsIHRyaWdnZXIgd2hpY2ggbWlnaHQgY2F1c2UgZm9jdXMgdG8gYmUgbG9zdFxuICAgIC8vIHdoZW4gY2xpY2tpbmcgb3V0c2lkZSBvZiB0aGUgbWVudS5cbiAgICBpZiAoIXRoaXMuX29wZW5lZEJ5KSB7XG4gICAgICAvLyBOb3RlIHRoYXQgdGhlIGZvY3VzIHN0eWxlIHdpbGwgc2hvdyB1cCBib3RoIGZvciBgcHJvZ3JhbWAgYW5kXG4gICAgICAvLyBga2V5Ym9hcmRgIHNvIHdlIGRvbid0IGhhdmUgdG8gc3BlY2lmeSB3aGljaCBvbmUgaXQgaXMuXG4gICAgICB0aGlzLmZvY3VzKCk7XG4gICAgfSBlbHNlIGlmICghdGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSkge1xuICAgICAgdGhpcy5mb2N1cyh0aGlzLl9vcGVuZWRCeSk7XG4gICAgfVxuXG4gICAgdGhpcy5fb3BlbmVkQnkgPSBudWxsO1xuICB9XG5cbiAgLy8gU2V0IHN0YXRlIHJhdGhlciB0aGFuIHRvZ2dsZSB0byBzdXBwb3J0IHRyaWdnZXJzIHNoYXJpbmcgYSBtZW51XG4gIHByaXZhdGUgX3NldElzTWVudU9wZW4oaXNPcGVuOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5faXNNZW51T3BlbiA9IGlzT3BlbjtcblxuICAgIGlmICh0aGlzLnRyaWdnZXJzU3VibWVudSgpKSB7XG4gICAgICB0aGlzLl9tZW51SXRlbUluc3RhbmNlLl9oaWdobGlnaHRlZCA9XG4gICAgICAgIGlzT3BlbiAmJiB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlICE9PSAndG91Y2gnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCBjaGVja3MgdGhhdCBhIHZhbGlkIGluc3RhbmNlIG9mIE1lbnVDb21wb25lbnQgaGFzIGJlZW4gcGFzc2VkIGludG9cbiAgICogZ3Jhbml0ZU1lbnVUcmlnZ2VyRm9yLiBJZiBub3QsIGFuIGV4Y2VwdGlvbiBpcyB0aHJvd24uXG4gICAqL1xuICBwcml2YXRlIF9jaGVja01lbnUoKSB7XG4gICAgaWYgKCF0aGlzLm1lbnUpIHtcbiAgICAgIHRocm93R3Jhbml0ZU1lbnVNaXNzaW5nRXJyb3IoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBzdHJhdGVneSBmb3IgcG9zaXRpb25pbmcgdGhlIG92ZXJsYXkgZm9yIGRlc2t0b3AgZGV2aWNlczpcbiAgICogUGxhY2UgYWRqYWNlbnQgdG8gdGhlIHRyaWdnZXIgYnV0dG9uIChwcmVmZXJhYmx5IGltbWVkaWF0ZWx5IGJlbG93KVxuICAgKiBpbiBvcmRlciB0byBzaG93IGFzIG11Y2ggb2YgdGhlIG1lbnUgYXMgcG9zc2libGUuXG4gICAqL1xuICBwcml2YXRlIF9kZXNrdG9wUG9zaXRpb25TdHJhdGVneSgpOiBQb3NpdGlvblN0cmF0ZWd5IHtcbiAgICBjb25zdCBwb3NpdGlvblN0cmF0ZWd5OiBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kgPSB0aGlzLl9vdmVybGF5XG4gICAgICAucG9zaXRpb24oKVxuICAgICAgLmZsZXhpYmxlQ29ubmVjdGVkVG8odGhpcy5fZWxlbWVudClcbiAgICAgIC53aXRoTG9ja2VkUG9zaXRpb24oKVxuICAgICAgLndpdGhUcmFuc2Zvcm1PcmlnaW5PbignLmdyYW5pdGUtbWVudScpXG4gICAgICAud2l0aFB1c2goZmFsc2UpO1xuXG4gICAgdGhpcy5fc2V0UG9zaXRpb24ocG9zaXRpb25TdHJhdGVneSk7XG4gICAgcmV0dXJuIHBvc2l0aW9uU3RyYXRlZ3k7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgYXBwcm9wcmlhdGUgcG9zaXRpb25zIG9uIGEgcG9zaXRpb24gc3RyYXRlZ3lcbiAgICogc28gdGhlIG92ZXJsYXkgY29ubmVjdHMgd2l0aCB0aGUgdHJpZ2dlciBjb3JyZWN0bHkuXG4gICAqIEBwYXJhbSBwb3NpdGlvblN0cmF0ZWd5IFN0cmF0ZWd5IHdob3NlIHBvc2l0aW9uIHRvIHVwZGF0ZS5cbiAgICovXG4gIHByaXZhdGUgX3NldFBvc2l0aW9uKHBvc2l0aW9uU3RyYXRlZ3k6IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSkge1xuICAgIGNvbnN0IE1FTlVfUEFORUxfVE9QX1BBRERJTkcgPSAwO1xuXG4gICAgbGV0IFtvcmlnaW5YLCBvcmlnaW5GYWxsYmFja1hdOiBIb3Jpem9udGFsQ29ubmVjdGlvblBvc1tdID1cbiAgICAgIHRoaXMubWVudS54UG9zaXRpb24gPT09ICdiZWZvcmUnID8gWydlbmQnLCAnc3RhcnQnXSA6IFsnc3RhcnQnLCAnZW5kJ107XG5cbiAgICBjb25zdCBbb3ZlcmxheVksIG92ZXJsYXlGYWxsYmFja1ldOiBWZXJ0aWNhbENvbm5lY3Rpb25Qb3NbXSA9XG4gICAgICB0aGlzLm1lbnUueVBvc2l0aW9uID09PSAnYWJvdmUnID8gWydib3R0b20nLCAndG9wJ10gOiBbJ3RvcCcsICdib3R0b20nXTtcblxuICAgIGxldCBbb3JpZ2luWSwgb3JpZ2luRmFsbGJhY2tZXSA9IFtvdmVybGF5WSwgb3ZlcmxheUZhbGxiYWNrWV07XG4gICAgbGV0IFtvdmVybGF5WCwgb3ZlcmxheUZhbGxiYWNrWF0gPSBbb3JpZ2luWCwgb3JpZ2luRmFsbGJhY2tYXTtcbiAgICBsZXQgb2Zmc2V0WSA9IDA7XG5cbiAgICBpZiAodGhpcy50cmlnZ2Vyc1N1Ym1lbnUoKSkge1xuICAgICAgLy8gV2hlbiB0aGUgbWVudSBpcyBhIHN1Yi1tZW51LCBpdCBzaG91bGQgYWx3YXlzIGFsaWduIGl0c2VsZlxuICAgICAgLy8gdG8gdGhlIGVkZ2VzIG9mIHRoZSB0cmlnZ2VyLCBpbnN0ZWFkIG9mIG92ZXJsYXBwaW5nIGl0LlxuICAgICAgb3ZlcmxheUZhbGxiYWNrWCA9IG9yaWdpblggPVxuICAgICAgICB0aGlzLm1lbnUueFBvc2l0aW9uID09PSAnYmVmb3JlJyA/ICdzdGFydCcgOiAnZW5kJztcbiAgICAgIG9yaWdpbkZhbGxiYWNrWCA9IG92ZXJsYXlYID0gb3JpZ2luWCA9PT0gJ2VuZCcgPyAnc3RhcnQnIDogJ2VuZCc7XG4gICAgICBvZmZzZXRZID1cbiAgICAgICAgb3ZlcmxheVkgPT09ICdib3R0b20nXG4gICAgICAgICAgPyBNRU5VX1BBTkVMX1RPUF9QQURESU5HXG4gICAgICAgICAgOiAtTUVOVV9QQU5FTF9UT1BfUEFERElORztcbiAgICB9IGVsc2Uge1xuICAgICAgb3JpZ2luWSA9IG92ZXJsYXlZID09PSAndG9wJyA/ICdib3R0b20nIDogJ3RvcCc7XG4gICAgICBvcmlnaW5GYWxsYmFja1kgPSBvdmVybGF5RmFsbGJhY2tZID09PSAndG9wJyA/ICdib3R0b20nIDogJ3RvcCc7XG4gICAgfVxuXG4gICAgcG9zaXRpb25TdHJhdGVneS53aXRoUG9zaXRpb25zKFtcbiAgICAgIHsgb3JpZ2luWCwgb3JpZ2luWSwgb3ZlcmxheVgsIG92ZXJsYXlZLCBvZmZzZXRZIH0sXG4gICAgICB7XG4gICAgICAgIG9yaWdpblg6IG9yaWdpbkZhbGxiYWNrWCxcbiAgICAgICAgb3JpZ2luWSxcbiAgICAgICAgb3ZlcmxheVg6IG92ZXJsYXlGYWxsYmFja1gsXG4gICAgICAgIG92ZXJsYXlZLFxuICAgICAgICBvZmZzZXRZLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgb3JpZ2luWCxcbiAgICAgICAgb3JpZ2luWTogb3JpZ2luRmFsbGJhY2tZLFxuICAgICAgICBvdmVybGF5WCxcbiAgICAgICAgb3ZlcmxheVk6IG92ZXJsYXlGYWxsYmFja1ksXG4gICAgICAgIG9mZnNldFk6IC1vZmZzZXRZLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgb3JpZ2luWDogb3JpZ2luRmFsbGJhY2tYLFxuICAgICAgICBvcmlnaW5ZOiBvcmlnaW5GYWxsYmFja1ksXG4gICAgICAgIG92ZXJsYXlYOiBvdmVybGF5RmFsbGJhY2tYLFxuICAgICAgICBvdmVybGF5WTogb3ZlcmxheUZhbGxiYWNrWSxcbiAgICAgICAgb2Zmc2V0WTogLW9mZnNldFksXG4gICAgICB9LFxuICAgIF0pO1xuICB9XG5cbiAgLyoqIFJldHVybnMgYSBzdHJlYW0gdGhhdCBlbWl0cyB3aGVuZXZlciBhbiBhY3Rpb24gdGhhdCBzaG91bGQgY2xvc2UgdGhlIG1lbnUgb2NjdXJzLiAqL1xuICBwcml2YXRlIF9tZW51Q2xvc2luZ0FjdGlvbnMoKSB7XG4gICAgY29uc3QgZGV0YWNobWVudHMgPSB0aGlzLl9vdmVybGF5UmVmPy5kZXRhY2htZW50cygpO1xuICAgIGNvbnN0IHBhcmVudENsb3NlID0gdGhpcy5fcGFyZW50TWVudVxuICAgICAgPyB0aGlzLl9wYXJlbnRNZW51LmNsb3NlZFxuICAgICAgOiBvYnNlcnZhYmxlT2YoKTtcblxuICAgIGNvbnN0IGhvdmVyID1cbiAgICAgIHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICdkZXNrdG9wJyAmJiB0aGlzLl9wYXJlbnRNZW51XG4gICAgICAgID8gdGhpcy5fcGFyZW50TWVudS5faG92ZXJlZCgpLnBpcGUoXG4gICAgICAgICAgICBmaWx0ZXIoKGl0ZW0pID0+IGl0ZW0gIT09IHRoaXMuX21lbnVJdGVtSW5zdGFuY2UpLFxuICAgICAgICAgICAgZmlsdGVyKCgpID0+IHRoaXMuX2lzTWVudU9wZW4pXG4gICAgICAgICAgKVxuICAgICAgICA6IG9ic2VydmFibGVPZigpO1xuXG4gICAgLy8gTm90ZTogUXVpY2sgZml4LiBGZWF0dXJlIHJlcG9ydGVkbHkgZXhpc3RzIGluIENESyBmb3IgQW5ndWxhciAxMFxuICAgIC8vIEZpbHRlciB0byBwcmV2ZW50IGNsb3Npbmcgd2hlbiBhbmltYXRpbmcgYWRkZWQgdGhvdWdoLiBBcHBsaWVkIHRvXG4gICAgLy8gcm9vdCBtZW51IG9ubHkuXG4gICAgY29uc3Qgb3V0c2lkZUNsaWNrID0gIXRoaXMuX3BhcmVudE1lbnVcbiAgICAgID8gZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KHRoaXMuX2RvY3VtZW50LCAnY2xpY2snKS5waXBlKFxuICAgICAgICAgIGZpbHRlcihcbiAgICAgICAgICAgIChlOiBNb3VzZUV2ZW50KSA9PlxuICAgICAgICAgICAgICAoZS50YXJnZXQgYXMgSFRNTEVsZW1lbnQpICE9PSB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQgJiZcbiAgICAgICAgICAgICAgKGUudGFyZ2V0IGFzIEhUTUxFbGVtZW50KS5jbG9zZXN0KCcuZ3Jhbml0ZS1tZW51JykgPT09IG51bGxcbiAgICAgICAgICApLFxuICAgICAgICAgIGZpbHRlcigoKSA9PiAhdGhpcy5tZW51Ll9pc0FuaW1hdGluZylcbiAgICAgICAgKVxuICAgICAgOiBvYnNlcnZhYmxlT2YoKTtcblxuICAgIHJldHVybiBtZXJnZShkZXRhY2htZW50cywgaG92ZXIsIHBhcmVudENsb3NlLCBvdXRzaWRlQ2xpY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSBvcGVuIHN1Ym1lbnVzIG9uIGhvdmVyLiBUaGlzIGlzIHRydWUgd2hlbiBzaG93aW5nXG4gICAqIGRlc2t0b3AgbWVudXMgYW5kIGhhdmluZyBtb3VzZSBzdXBwb3J0LlxuICAgKi9cbiAgcHJpdmF0ZSBfb3Blbk9uSG92ZXIoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgICh0aGlzLnRyaWdnZXJzU3VibWVudSgpXG4gICAgICAgID8gdGhpcy5fcGFyZW50TWVudS5vcGVuT25Ib3ZlclxuICAgICAgICA6IHRoaXMubWVudS5vcGVuT25Ib3ZlcikgJiZcbiAgICAgIHRoaXMuX3BhcmVudE1lbnUuX2NsaWVudE91dHB1dD8uZGV2aWNlID09PSAnZGVza3RvcCcgJiZcbiAgICAgIHRoaXMuX3BhcmVudE1lbnUuX2NsaWVudElucHV0Py5kZXZpY2VzLmluY2x1ZGVzKCdtb3VzZScpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHRvZ2dsZSBzdWJtZW51cyBvbiBjbGljay4gVGhpcyBpcyB0cnVlIHdoZW4gc2hvd2luZyBkZXNrdG9wIG1lbnVzXG4gICAqIHdpdGhvdXQgbW91c2Ugc3VwcG9ydC4gV2hpY2gsIGJ5IHRoZSB3YXksIGlzIG5vdCBhIGdyZWF0IGlkZWEgdG8gYmVnaW4gd2l0aC5cbiAgICovXG4gIHByaXZhdGUgX3RvZ2dsZU9uU3VibWVudUNsaWNrKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoXG4gICAgICAhKHRoaXMudHJpZ2dlcnNTdWJtZW51KClcbiAgICAgICAgPyB0aGlzLl9wYXJlbnRNZW51Lm9wZW5PbkhvdmVyXG4gICAgICAgIDogdGhpcy5tZW51Lm9wZW5PbkhvdmVyKSB8fFxuICAgICAgKHRoaXMuX3BhcmVudE1lbnUuX2NsaWVudE91dHB1dD8uZGV2aWNlID09PSAnZGVza3RvcCcgJiZcbiAgICAgICAgIXRoaXMuX3BhcmVudE1lbnUuX2NsaWVudElucHV0Py5kZXZpY2VzLmluY2x1ZGVzKCdtb3VzZScpKVxuICAgICk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIC8vXG4gIC8vIC0tLSBIZXJlIGJlIHRvdWNoIGRldmljZSBjdXN0b21pemF0aW9ucyAtLS0gLy9cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAvL1xuXG4gIC8qKiBTZXQgYW5pbWF0aW9uIHN0YXRlIHRvIGJyaW5nIGEgbmV3bHkgb3BlbmVkIG1lbnUgaW50byB2aWV3ICovXG4gIHByaXZhdGUgYW5pbWF0ZU9wZW5NZW51KCkge1xuICAgIHRoaXMuX2NsaWVudE91dHB1dC5kZXZpY2UgPT09ICd0b3VjaCdcbiAgICAgID8gdGhpcy5hbmltYXRlVG91Y2hPcGVuTWVudSgpXG4gICAgICA6IHRoaXMubWVudS5fc3RhcnRBbmltYXRpb24oKTtcbiAgfVxuXG4gIHByaXZhdGUgYW5pbWF0ZVRvdWNoT3Blbk1lbnUoKSB7XG4gICAgaWYgKHRoaXMudHJpZ2dlcnNTdWJtZW51KCkpIHtcbiAgICAgIC8vIFNsaWRlIG5ld2x5IG9wZW5lZCBzdWIgbWVudSBpbnRvIHZpZXcgZnJvbSB0aGUgc2lkZSxcbiAgICAgIC8vIHB1c2hpbmcgYW55IHBhcmVudCBtZW51IG91dCBvZiB2aWV3IG9uIHRoZSBvdGhlciBzaWRlXG4gICAgICB0aGlzLm1lbnUuX3N0YXJ0VG91Y2hTdWJtZW51RW50ZXJBbmltYXRpb24oKTtcbiAgICAgIHRoaXMuX3BhcmVudE1lbnUuX3N0YXJ0VG91Y2hIaWRlQW5pbWF0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFNsaWRlIHJvb3QgbWVudSBpbnRvIHZpZXcgZnJvbSBiZWxvd1xuICAgICAgdGhpcy5tZW51Ll9zdGFydFRvdWNoUm9vdEVudGVyQW5pbWF0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFNldCBhbmltYXRpb24gc3RhdGUgdG8gY2xvc2UgdGhlIGFjdGl2ZSBtZW51ICovXG4gIHByaXZhdGUgYW5pbWF0ZUNsb3NlTWVudSh0b0JlbG93OiBib29sZWFuLCB3aXRoRGVsYXk6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnXG4gICAgICA/IHRoaXMuX2FuaW1hdGVUb3VjaENsb3NlTWVudSh0b0JlbG93LCB3aXRoRGVsYXkpXG4gICAgICA6IHRoaXMuX3BhcmVudE1lbnUuX3Jlc2V0QW5pbWF0aW9uKCk7XG4gIH1cblxuICBwcml2YXRlIF9hbmltYXRlVG91Y2hDbG9zZU1lbnUodG9CZWxvdzogYm9vbGVhbiwgd2l0aERlbGF5OiBib29sZWFuKSB7XG4gICAgaWYgKHRvQmVsb3cpIHtcbiAgICAgIC8vIFNsaWRlIG1lbnUgb3V0IG9mIHZpZXcgYmVsb3cgdGhlIHZpZXdwb3J0XG4gICAgICB3aXRoRGVsYXlcbiAgICAgICAgPyB0aGlzLm1lbnUuX3N0YXJ0VG91Y2hDbG9zZURvd25BbmltYXRpb25XaXRoRGVsYXkoKVxuICAgICAgICA6IHRoaXMubWVudS5fc3RhcnRUb3VjaENsb3NlRG93bkFuaW1hdGlvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTbGlkZSB0aGUgY2xvc2VkIG1lbnUgb3V0IG9mIHZpZXcgdG8gdGhlIHNpZGVcbiAgICAgIC8vIGFuZCBzbGlkZSBhbnkgcGFyZW50IG1lbnUgYmFjayBpbnRvIHZpZXdcbiAgICAgIHRoaXMubWVudS5fc3RhcnRUb3VjaENsb3NlU2lkZUFuaW1hdGlvbigpO1xuICAgICAgdGhpcy5fcGFyZW50TWVudT8uX3N0YXJ0VG91Y2hTdWJtZW51RW50ZXJBbmltYXRpb24oKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IGFuaW1hdGlvbiBzdGF0ZSB0byBwbGFjZSB0aGUgbWVudSBhbmQgYW55IHBhcmVudCBhdCB0aGUgZ2l2ZW5cbiAgICogaG9yaXpvbnRhbCBwb3NpdGlvbiwgaS5lLiBmb2xsb3dpbmcgdG91Y2ggcGFuIG1vdmVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0geE9mZnNldCBIb3Jpem9udGFsIG9mZnNldFxuICAgKi9cbiAgcHJpdmF0ZSBhbmltYXRlU2V0TWVudVBvc2l0aW9uKHhPZmZzZXQ6IG51bWJlcikge1xuICAgIHRoaXMubWVudS5fc3RhcnRUb3VjaFBhbkFuaW1hdGlvbih4T2Zmc2V0KTtcbiAgICBpZiAodGhpcy5fcGFyZW50TWVudSkge1xuICAgICAgdGhpcy5fcGFyZW50TWVudS5fc3RhcnRUb3VjaEhpZGVQYW5BbmltYXRpb24oeE9mZnNldCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgc3RyYXRlZ3kgZm9yIHBvc2l0aW9uaW5nIHRoZSBvdmVybGF5IGRlcGVuZGluZyBvbiB3aGF0IHR5cGUgb2ZcbiAgICogZGV2aWNlIHRoZSBtZW51IGlzIGJlaW5nIHNob3duIG9uXG4gICAqL1xuICBwcml2YXRlIF9wb3NpdGlvblN0cmF0ZWd5KCk6IFBvc2l0aW9uU3RyYXRlZ3kge1xuICAgIHJldHVybiB0aGlzLl9jbGllbnRPdXRwdXQuZGV2aWNlID09PSAndG91Y2gnXG4gICAgICA/IHRoaXMuX3RvdWNoUG9zaXRpb25TdHJhdGVneSgpXG4gICAgICA6IHRoaXMuX2Rlc2t0b3BQb3NpdGlvblN0cmF0ZWd5KCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBzdHJhdGVneSBmb3IgcG9zaXRpb25pbmcgdGhlIG92ZXJsYXkgZm9yIHRvdWNoIGRldmljZXM6XG4gICAqIFBsYWNlIGNlbnRlcmVkIGF0IHRoZSBib3R0b20gb2YgdGhlIHNjcmVlbi5cbiAgICovXG4gIHByaXZhdGUgX3RvdWNoUG9zaXRpb25TdHJhdGVneSgpOiBQb3NpdGlvblN0cmF0ZWd5IHtcbiAgICByZXR1cm4gdGhpcy5fb3ZlcmxheS5wb3NpdGlvbigpLmdsb2JhbCgpO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cbiAgLy8gLS0tIEhlcmUgYmUgcG9vciBtYW4ncyB0b3VjaCBnZXN0dXJlcyAtLS0gLy9cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gLy9cblxuICAvLyBUT0RPOiBSZXBsYWNlIHdpdGggSGFtbWVyIG9yIG90aGVyIGdlc3R1cmUgbGlicmFyeVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHRvdWNoIHN0YXJ0IGV2ZW50cyBvbiB0aGUgb3ZlcmxheSBob3N0IGVsZW1lbnQgKHdyYXBwZXIpLlxuICAgKiBOZWVkcyB0byBiZSBhbiBhcnJvdyBmdW5jdGlvbiBzbyB3ZSBjYW4gZWFzaWx5IHVzZSBhZGRFdmVudExpc3RlbmVyIGFuZCByZW1vdmVFdmVudExpc3RlbmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfaGFuZGxlT3ZlcmxheVRvdWNoU3RhcnQgPSAoZXZlbnQ6IFRvdWNoRXZlbnQpID0+IHtcbiAgICBpZiAodGhpcy5tZW51Ll9pc0FuaW1hdGluZykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3RvdWNoU3RhcnRUaW1lID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICB0aGlzLl90b3VjaFN0YXJ0WCA9IGV2ZW50LmNoYW5nZWRUb3VjaGVzWzBdLmNsaWVudFg7XG4gICAgdGhpcy5fdG91Y2hTdGFydFkgPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRZO1xuICAgIHRoaXMuX3RvdWNoQ3VycmVudFggPSB0aGlzLl90b3VjaFN0YXJ0WDtcbiAgICB0aGlzLl90b3VjaEN1cnJlbnRZID0gdGhpcy5fdG91Y2hTdGFydFk7XG4gICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYID0gMDtcbiAgICB0aGlzLl90b3VjaE1heFggPVxuICAgICAgdGhpcy5fb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aDtcbiAgICB0aGlzLl90b3VjaExvY2tlZFggPSBudWxsO1xuICAgIHRoaXMuX3RvdWNoVG91Y2hpbmdFbGVtZW50ID0gdHJ1ZTtcbiAgfTtcblxuICBwcml2YXRlIF9oYW5kbGVPdmVybGF5VG91Y2hNb3ZlID0gKGV2ZW50OiBUb3VjaEV2ZW50KSA9PiB7XG4gICAgaWYgKCF0aGlzLl90b3VjaFRvdWNoaW5nRWxlbWVudCB8fCB0aGlzLm1lbnUuX2lzQW5pbWF0aW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3RvdWNoTG9ja2VkWCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3RvdWNoQ3VycmVudFggPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRYO1xuICAgIHRoaXMuX3RvdWNoQ3VycmVudFkgPSBldmVudC5jaGFuZ2VkVG91Y2hlc1swXS5jbGllbnRZO1xuXG4gICAgLy8gTG9jayBYLWF4aXMgcGFuIGlmIGluaXRpYXRpbmcgcGFuIG9uIFktYXhpc1xuICAgIGlmICh0aGlzLl90b3VjaExvY2tlZFggPT09IG51bGwpIHtcbiAgICAgIGNvbnN0IGR5ID0gTWF0aC5hYnModGhpcy5fdG91Y2hDdXJyZW50WSAtIHRoaXMuX3RvdWNoU3RhcnRZKTtcbiAgICAgIGNvbnN0IGR4ID0gTWF0aC5hYnModGhpcy5fdG91Y2hDdXJyZW50WCAtIHRoaXMuX3RvdWNoU3RhcnRYKTtcbiAgICAgIGlmIChkeCA+IDEwIHx8IGR5ID4gMTApIHtcbiAgICAgICAgdGhpcy5fdG91Y2hMb2NrZWRYID0gZHkgPiBkeDtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlc3RyaWN0IHRvIHJpZ2h0IHBhbi9zd2lwZSBhbmQgbWFrZSBtZW51IG1vdmVtZW50IGV4dHJlbWVseSBzbG93IHdoZW5cbiAgICAvLyBtb3ZlZCBwYXN0IGFsbG93ZWQgbGltaXRzLlxuICAgIGNvbnN0IG1lbnVNYXJnaW4gPSAxNjtcbiAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVggPSB0aGlzLl90b3VjaEN1cnJlbnRYIC0gdGhpcy5fdG91Y2hTdGFydFg7XG5cbiAgICBpZiAodGhpcy5fdG91Y2hUcmFuc2xhdGVYIDwgMCkge1xuICAgICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYID0gdGhpcy5lYXNlT3V0RXhwbyhcbiAgICAgICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYLFxuICAgICAgICAwLFxuICAgICAgICAtbWVudU1hcmdpbiAvIDIsXG4gICAgICAgIHRoaXMuX3RvdWNoTWF4WCAqIC00XG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAoIXRoaXMuX3BhcmVudE1lbnUpIHtcbiAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA9IHRoaXMuZWFzZU91dEV4cG8oXG4gICAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCxcbiAgICAgICAgMCxcbiAgICAgICAgbWVudU1hcmdpbiAvIDIsXG4gICAgICAgIHRoaXMuX3RvdWNoTWF4WCAqIDRcbiAgICAgICk7XG4gICAgfSBlbHNlIGlmICh0aGlzLl90b3VjaFRyYW5zbGF0ZVggPiB0aGlzLl90b3VjaE1heFgpIHtcbiAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA9IHRoaXMuZWFzZU91dEV4cG8oXG4gICAgICAgIHRoaXMuX3RvdWNoVHJhbnNsYXRlWCAtIHRoaXMuX3RvdWNoTWF4WCxcbiAgICAgICAgdGhpcy5fdG91Y2hNYXhYLFxuICAgICAgICBtZW51TWFyZ2luIC8gMixcbiAgICAgICAgdGhpcy5fdG91Y2hNYXhYICogNFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBTZXQgbmV3IHN1YiBtZW51IHBvc2l0aW9uIGFuZCB0ZWxsIGFueSBwYXJlbnQgdG8gZm9sbG93O1xuICAgIHRoaXMuYW5pbWF0ZVNldE1lbnVQb3NpdGlvbih0aGlzLl90b3VjaFRyYW5zbGF0ZVgpO1xuICB9O1xuXG4gIHByaXZhdGUgX2hhbmRsZU92ZXJsYXlUb3VjaEVuZCA9ICgpID0+IHtcbiAgICBpZiAoIXRoaXMuX3RvdWNoVG91Y2hpbmdFbGVtZW50IHx8IHRoaXMubWVudS5faXNBbmltYXRpbmcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl90b3VjaFRyYW5zbGF0ZVggPSB0aGlzLl90b3VjaEN1cnJlbnRYIC0gdGhpcy5fdG91Y2hTdGFydFg7XG4gICAgaWYgKHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX3RvdWNoVG91Y2hpbmdFbGVtZW50ID0gZmFsc2U7XG4gICAgdGhpcy5fdG91Y2hUaW1lVGFrZW4gPSBuZXcgRGF0ZSgpLmdldFRpbWUoKSAtIHRoaXMuX3RvdWNoU3RhcnRUaW1lO1xuXG4gICAgY29uc3Qgc3dpcGVNaW5EaXN0YW5jZSA9IDEwO1xuICAgIGNvbnN0IHN3aXBlTWluVGltZSA9IDUwO1xuICAgIGNvbnN0IHN3aXBlTWF4VGltZSA9IDMwMDtcblxuICAgIGNvbnN0IHBhbm5lZEhhbGZ3YXlSaWdodCA9IHRoaXMuX3RvdWNoVHJhbnNsYXRlWCA+IHRoaXMuX3RvdWNoTWF4WCAvIDI7XG4gICAgY29uc3Qgc3dpcGVkUmlnaHQgPVxuICAgICAgdGhpcy5fdG91Y2hUcmFuc2xhdGVYID4gdGhpcy5fdG91Y2hNYXhYIC8gc3dpcGVNaW5EaXN0YW5jZSAmJlxuICAgICAgdGhpcy5fdG91Y2hUaW1lVGFrZW4gPiBzd2lwZU1pblRpbWUgJiZcbiAgICAgIHRoaXMuX3RvdWNoVGltZVRha2VuIDwgc3dpcGVNYXhUaW1lO1xuXG4gICAgaWYgKCEhdGhpcy5fcGFyZW50TWVudSAmJiAoc3dpcGVkUmlnaHQgfHwgcGFubmVkSGFsZndheVJpZ2h0KSkge1xuICAgICAgLy8gQ2xvc2Ugc3VibWVudSBrZXlkb3duLXN0eWxlOiBjbG9zZSBvbmx5IHRoaXMgbWVudSBhbmQgbGVhdmUgcGFyZW50cyBvcGVuXG4gICAgICB0aGlzLm1lbnUuY2xvc2VkLmVtaXQoJ2tleWRvd24nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gUGFuIGVuZGVkIGJ1dCB0aGUgbWVudSB3YXMgbm90IG1vdmVkIGZhciBlbm91Z2guIFJlc2V0IG1lbnVzIHRvXG4gICAgICAvLyB3aGVyZSB0aGV5IHdlcmUgYmVmb3JlIHBhbm5pbmcgc3RhcmVkLlxuICAgICAgdGhpcy5hbmltYXRlT3Blbk1lbnUoKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0b3VjaCBkZXZpY2UgcGFuL3N3aXBlIGxpc3RlbmVycyBmcm9tIG92ZXJsYXkgaG9zdCBlbGVtZW50XG4gICAqL1xuICBwcml2YXRlIGFkZE92ZXJsYXlMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoU3RhcnQsXG4gICAgICBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnNcbiAgICApO1xuXG4gICAgdGhpcy5fb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNobW92ZScsXG4gICAgICB0aGlzLl9oYW5kbGVPdmVybGF5VG91Y2hNb3ZlLFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaGVuZCcsXG4gICAgICB0aGlzLl9oYW5kbGVPdmVybGF5VG91Y2hFbmQsXG4gICAgICBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnNcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0b3VjaCBkZXZpY2UgcGFuL3N3aXBlIGxpc3RlbmVycyBmcm9tIG92ZXJsYXkgaG9zdCBlbGVtZW50XG4gICAqL1xuICBwcml2YXRlIHJlbW92ZU92ZXJsYXlMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5fb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNoc3RhcnQnLFxuICAgICAgdGhpcy5faGFuZGxlT3ZlcmxheVRvdWNoU3RhcnQsXG4gICAgICBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnNcbiAgICApO1xuXG4gICAgdGhpcy5fb3ZlcmxheVJlZi5ob3N0RWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgJ3RvdWNobW92ZScsXG4gICAgICB0aGlzLl9oYW5kbGVPdmVybGF5VG91Y2hNb3ZlLFxuICAgICAgcGFzc2l2ZUV2ZW50TGlzdGVuZXJPcHRpb25zXG4gICAgKTtcblxuICAgIHRoaXMuX292ZXJsYXlSZWYuaG9zdEVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICd0b3VjaGVuZCcsXG4gICAgICB0aGlzLl9oYW5kbGVPdmVybGF5VG91Y2hFbmQsXG4gICAgICBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnNcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YW5kYXJkIGV4cG9uZW50aWFsIGVhc2Ugb3V0IGZ1bmN0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBjdXJyZW50IEN1cnJlbnQgdmFsdWVcbiAgICogQHBhcmFtIG9mZnNldCBPZmZzZXQgdmFsdWUsIHRvIHdoaWNoIGNhbGN1bGF0ZWQgdmFsdWUgd2lsbCBiZSBhZGRlZFxuICAgKiBAcGFyYW0gdGFyZ2V0IFRoZSB0YXJnZXQgdmFsdWVcbiAgICogQHBhcmFtIGVuZCBWYWx1ZSB0byB3aGljaCBjdXJyZW50IHZhbHVlIGlzIGNvbXBhcmVkXG4gICAqL1xuICBwcml2YXRlIGVhc2VPdXRFeHBvKFxuICAgIGN1cnJlbnQ6IG51bWJlcixcbiAgICBvZmZzZXQ6IG51bWJlcixcbiAgICB0YXJnZXQ6IG51bWJlcixcbiAgICBlbmQ6IG51bWJlclxuICApOiBudW1iZXIge1xuICAgIHJldHVybiBjdXJyZW50ID09PSBlbmRcbiAgICAgID8gb2Zmc2V0ICsgdGFyZ2V0XG4gICAgICA6IHRhcmdldCAqICgtTWF0aC5wb3coMiwgKC0xMCAqIGN1cnJlbnQpIC8gZW5kKSArIDEpICsgb2Zmc2V0O1xuICB9XG59XG4iXX0=