@ks89/angular-modal-gallery 10.0.1 → 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 (123) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/CONTRIBUTING.md +3 -3
  3. package/LICENSE +1 -1
  4. package/README.md +12 -14
  5. package/esm2022/lib/components/accessible.component.mjs +131 -0
  6. package/esm2022/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +457 -0
  7. package/esm2022/lib/components/carousel/carousel.component.mjs +739 -0
  8. package/{esm2020 → esm2022}/lib/components/components.mjs +2 -2
  9. package/esm2022/lib/components/current-image/current-image.component.mjs +608 -0
  10. package/esm2022/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +81 -0
  11. package/esm2022/lib/components/dots/dots.component.mjs +125 -0
  12. package/{esm2020 → esm2022}/lib/components/modal-gallery/modal-gallery-ref.mjs +2 -2
  13. package/esm2022/lib/components/modal-gallery/modal-gallery.component.mjs +500 -0
  14. package/esm2022/lib/components/modal-gallery/modal-gallery.service.mjs +188 -0
  15. package/{esm2020 → esm2022}/lib/components/modal-gallery/modal-gallery.tokens.mjs +2 -2
  16. package/esm2022/lib/components/plain-gallery/plain-gallery.component.mjs +250 -0
  17. package/esm2022/lib/components/previews/previews.component.mjs +264 -0
  18. package/esm2022/lib/components/upper-buttons/upper-buttons.component.mjs +244 -0
  19. package/esm2022/lib/directives/a-tag-bg-image.directive.mjs +79 -0
  20. package/esm2022/lib/directives/click-outside.directive.mjs +92 -0
  21. package/esm2022/lib/directives/description.directive.mjs +99 -0
  22. package/esm2022/lib/directives/direction.directive.mjs +74 -0
  23. package/esm2022/lib/directives/directives.mjs +51 -0
  24. package/esm2022/lib/directives/fallback-image.directive.mjs +60 -0
  25. package/esm2022/lib/directives/keyboard-navigation.directive.mjs +59 -0
  26. package/esm2022/lib/directives/margin.directive.mjs +85 -0
  27. package/esm2022/lib/directives/max-size.directive.mjs +76 -0
  28. package/esm2022/lib/directives/size.directive.mjs +77 -0
  29. package/esm2022/lib/directives/swipe.directive.mjs +115 -0
  30. package/esm2022/lib/directives/wrap.directive.mjs +75 -0
  31. package/esm2022/lib/modal-gallery.module.mjs +69 -0
  32. package/{esm2020 → esm2022}/lib/model/accessibility.interface.mjs +2 -2
  33. package/{esm2020 → esm2022}/lib/model/action.enum.mjs +2 -2
  34. package/{esm2020 → esm2022}/lib/model/buttons-config.interface.mjs +2 -2
  35. package/{esm2020 → esm2022}/lib/model/carousel-config.interface.mjs +2 -2
  36. package/{esm2020 → esm2022}/lib/model/carousel-image-config.interface.mjs +2 -2
  37. package/{esm2020 → esm2022}/lib/model/carousel-preview-config.interface.mjs +2 -2
  38. package/{esm2020 → esm2022}/lib/model/current-image-config.interface.mjs +2 -2
  39. package/{esm2020 → esm2022}/lib/model/description.interface.mjs +2 -2
  40. package/{esm2020 → esm2022}/lib/model/dots-config.interface.mjs +2 -2
  41. package/{esm2020 → esm2022}/lib/model/image-internal.class.mjs +2 -2
  42. package/{esm2020 → esm2022}/lib/model/image.class.mjs +2 -2
  43. package/{esm2020 → esm2022}/lib/model/keyboard-config.interface.mjs +2 -2
  44. package/{esm2020 → esm2022}/lib/model/keyboard.enum.mjs +2 -2
  45. package/{esm2020 → esm2022}/lib/model/lib-config.interface.mjs +2 -2
  46. package/{esm2020 → esm2022}/lib/model/loading-config.interface.mjs +2 -2
  47. package/{esm2020 → esm2022}/lib/model/max-size.interface.mjs +2 -2
  48. package/{esm2020 → esm2022}/lib/model/modal-gallery-config.interface.mjs +2 -2
  49. package/{esm2020 → esm2022}/lib/model/plain-gallery-config.interface.mjs +2 -2
  50. package/{esm2020 → esm2022}/lib/model/play-config.interface.mjs +2 -2
  51. package/{esm2020 → esm2022}/lib/model/preview-config.interface.mjs +2 -2
  52. package/{esm2020 → esm2022}/lib/model/size.interface.mjs +2 -2
  53. package/{esm2020 → esm2022}/lib/model/slide-config.interface.mjs +2 -2
  54. package/esm2022/lib/services/config.service.mjs +389 -0
  55. package/esm2022/lib/services/id-validator.service.mjs +72 -0
  56. package/{esm2020 → esm2022}/lib/utils/image.util.mjs +4 -4
  57. package/{esm2020 → esm2022}/lib/utils/user-input.util.mjs +2 -2
  58. package/{esm2020 → esm2022}/public-api.mjs +2 -2
  59. package/{fesm2020 → fesm2022}/ks89-angular-modal-gallery.mjs +382 -471
  60. package/fesm2022/ks89-angular-modal-gallery.mjs.map +1 -0
  61. package/lib/components/carousel/carousel-previews/carousel-previews.component.d.ts +4 -4
  62. package/lib/components/carousel/carousel.component.d.ts +5 -8
  63. package/lib/components/current-image/current-image.component.d.ts +6 -10
  64. package/lib/components/current-image/loading-spinner/loading-spinner.component.d.ts +3 -3
  65. package/lib/components/dots/dots.component.d.ts +5 -5
  66. package/lib/components/modal-gallery/modal-gallery.component.d.ts +11 -17
  67. package/lib/components/plain-gallery/plain-gallery.component.d.ts +3 -3
  68. package/lib/components/previews/previews.component.d.ts +6 -6
  69. package/lib/components/upper-buttons/upper-buttons.component.d.ts +4 -4
  70. package/lib/directives/a-tag-bg-image.directive.d.ts +3 -3
  71. package/lib/directives/click-outside.directive.d.ts +2 -2
  72. package/lib/directives/description.directive.d.ts +3 -3
  73. package/lib/directives/direction.directive.d.ts +3 -3
  74. package/lib/directives/directives.d.ts +2 -1
  75. package/lib/directives/fallback-image.directive.d.ts +1 -1
  76. package/lib/directives/keyboard-navigation.directive.d.ts +1 -1
  77. package/lib/directives/margin.directive.d.ts +3 -3
  78. package/lib/directives/max-size.directive.d.ts +3 -3
  79. package/lib/directives/size.directive.d.ts +1 -1
  80. package/lib/directives/swipe.directive.d.ts +33 -0
  81. package/lib/directives/wrap.directive.d.ts +3 -3
  82. package/lib/modal-gallery.module.d.ts +4 -10
  83. package/lib/model/keyboard.enum.d.ts +1 -1
  84. package/lib/model/lib-config.interface.d.ts +2 -6
  85. package/lib/services/config.service.d.ts +0 -2
  86. package/lib/utils/image.util.d.ts +2 -2
  87. package/package.json +10 -18
  88. package/esm2020/lib/components/accessible.component.mjs +0 -130
  89. package/esm2020/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +0 -462
  90. package/esm2020/lib/components/carousel/carousel.component.mjs +0 -747
  91. package/esm2020/lib/components/current-image/current-image.component.mjs +0 -616
  92. package/esm2020/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +0 -80
  93. package/esm2020/lib/components/dots/dots.component.mjs +0 -127
  94. package/esm2020/lib/components/modal-gallery/modal-gallery.component.mjs +0 -524
  95. package/esm2020/lib/components/modal-gallery/modal-gallery.service.mjs +0 -187
  96. package/esm2020/lib/components/plain-gallery/plain-gallery.component.mjs +0 -249
  97. package/esm2020/lib/components/previews/previews.component.mjs +0 -272
  98. package/esm2020/lib/components/upper-buttons/upper-buttons.component.mjs +0 -249
  99. package/esm2020/lib/directives/a-tag-bg-image.directive.mjs +0 -78
  100. package/esm2020/lib/directives/click-outside.directive.mjs +0 -91
  101. package/esm2020/lib/directives/description.directive.mjs +0 -98
  102. package/esm2020/lib/directives/direction.directive.mjs +0 -73
  103. package/esm2020/lib/directives/directives.mjs +0 -49
  104. package/esm2020/lib/directives/fallback-image.directive.mjs +0 -59
  105. package/esm2020/lib/directives/keyboard-navigation.directive.mjs +0 -58
  106. package/esm2020/lib/directives/margin.directive.mjs +0 -84
  107. package/esm2020/lib/directives/max-size.directive.mjs +0 -75
  108. package/esm2020/lib/directives/size.directive.mjs +0 -76
  109. package/esm2020/lib/directives/wrap.directive.mjs +0 -74
  110. package/esm2020/lib/modal-gallery.module.mjs +0 -94
  111. package/esm2020/lib/model/keyboard-service-config.interface.mjs +0 -25
  112. package/esm2020/lib/services/config.service.mjs +0 -396
  113. package/esm2020/lib/services/id-validator.service.mjs +0 -71
  114. package/esm2020/lib/services/keyboard.service.mjs +0 -111
  115. package/fesm2015/ks89-angular-modal-gallery.mjs +0 -5728
  116. package/fesm2015/ks89-angular-modal-gallery.mjs.map +0 -1
  117. package/fesm2020/ks89-angular-modal-gallery.mjs.map +0 -1
  118. package/lib/model/keyboard-service-config.interface.d.ts +0 -8
  119. package/lib/services/keyboard.service.d.ts +0 -26
  120. /package/{esm2020 → esm2022}/ks89-angular-modal-gallery.mjs +0 -0
  121. /package/{esm2020 → esm2022}/lib/components/accessibility-default.mjs +0 -0
  122. /package/{esm2020 → esm2022}/lib/components/upper-buttons/upper-buttons-default.mjs +0 -0
  123. /package/{esm2020 → esm2022}/lib/model/interaction-event.interface.mjs +0 -0
@@ -0,0 +1,608 @@
1
+ /*
2
+ The MIT License (MIT)
3
+
4
+ Copyright (C) 2017-2023 Stefano Cappa (Ks89)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ */
24
+ import { ChangeDetectionStrategy, Component, EventEmitter, HostListener, Inject, Input, Output, PLATFORM_ID } from '@angular/core';
25
+ import { isPlatformBrowser } from '@angular/common';
26
+ import { Subject, timer } from 'rxjs';
27
+ import { filter, map, switchMap, takeUntil } from 'rxjs/operators';
28
+ import { AccessibleComponent } from '../accessible.component';
29
+ import { Action } from '../../model/action.enum';
30
+ import { DescriptionStrategy } from '../../model/description.interface';
31
+ import { ImageModalEvent } from '../../model/image.class';
32
+ import { Keyboard } from '../../model/keyboard.enum';
33
+ import { NEXT, PREV } from '../../utils/user-input.util';
34
+ import { getIndex } from '../../utils/image.util';
35
+ import * as i0 from "@angular/core";
36
+ import * as i1 from "../../services/config.service";
37
+ import * as i2 from "@angular/common";
38
+ import * as i3 from "./loading-spinner/loading-spinner.component";
39
+ import * as i4 from "../../directives/size.directive";
40
+ import * as i5 from "../../directives/keyboard-navigation.directive";
41
+ import * as i6 from "../../directives/description.directive";
42
+ import * as i7 from "../../directives/fallback-image.directive";
43
+ import * as i8 from "../../directives/swipe.directive";
44
+ /**
45
+ * Component with the current image with some additional elements like arrows and side previews.
46
+ */
47
+ class CurrentImageComponent extends AccessibleComponent {
48
+ // use public ChangeDetectorRef to be able to call it from spec files to trigger change detection
49
+ // tslint:disable-next-line:no-any
50
+ constructor(platformId, ngZone, ref, configService) {
51
+ super();
52
+ this.platformId = platformId;
53
+ this.ngZone = ngZone;
54
+ this.ref = ref;
55
+ this.configService = configService;
56
+ /**
57
+ * Boolean that it is true if the modal gallery is visible.
58
+ * If yes, also this component should be visible.
59
+ */
60
+ this.isOpen = false;
61
+ /**
62
+ * Output to emit an event when images are loaded. The payload contains an `ImageLoadEvent`.
63
+ */
64
+ this.loadImage = new EventEmitter();
65
+ /**
66
+ * Output to emit any changes of the current image. The payload contains an `ImageModalEvent`.
67
+ */
68
+ this.changeImage = new EventEmitter();
69
+ /**
70
+ * Output to emit an event when the modal gallery is closed. The payload contains an `ImageModalEvent`.
71
+ */
72
+ this.closeGallery = new EventEmitter();
73
+ /**
74
+ * Subject to play modal-gallery.
75
+ */
76
+ this.start$ = new Subject();
77
+ /**
78
+ * Subject to stop modal-gallery.
79
+ */
80
+ this.stop$ = new Subject();
81
+ /**
82
+ * Enum of type `Action` that represents a normal action.
83
+ * Declared here to be used inside the template.
84
+ */
85
+ this.normalAction = Action.NORMAL;
86
+ /**
87
+ * Enum of type `Action` that represents a mouse click on a button.
88
+ * Declared here to be used inside the template.
89
+ */
90
+ this.clickAction = Action.CLICK;
91
+ /**
92
+ * Enum of type `Action` that represents a keyboard action.
93
+ * Declared here to be used inside the template.
94
+ */
95
+ this.keyboardAction = Action.KEYBOARD;
96
+ /**
97
+ * Boolean that it's true when you are watching the first image (currently visible).
98
+ * False by default
99
+ */
100
+ this.isFirstImage = false;
101
+ /**
102
+ * Boolean that it's true when you are watching the last image (currently visible).
103
+ * False by default
104
+ */
105
+ this.isLastImage = false;
106
+ /**
107
+ * Boolean that it's true if an image of the modal gallery is still loading.
108
+ * True by default
109
+ */
110
+ this.loading = true;
111
+ }
112
+ /**
113
+ * Listener to stop the gallery when the mouse pointer is over the current image.
114
+ */
115
+ onMouseEnter() {
116
+ // if carousel feature is disable, don't do anything in any case
117
+ if (!this.slideConfig || !this.slideConfig.playConfig) {
118
+ return;
119
+ }
120
+ if (!this.slideConfig.playConfig.pauseOnHover) {
121
+ return;
122
+ }
123
+ this.stopCarousel();
124
+ }
125
+ /**
126
+ * Listener to play the gallery when the mouse pointer leave the current image.
127
+ */
128
+ onMouseLeave() {
129
+ // if carousel feature is disable, don't do anything in any case
130
+ if (!this.slideConfig || !this.slideConfig.playConfig) {
131
+ return;
132
+ }
133
+ if (!this.slideConfig.playConfig.pauseOnHover || !this.slideConfig.playConfig.autoPlay) {
134
+ return;
135
+ }
136
+ this.playCarousel();
137
+ }
138
+ /**
139
+ * Method ´ngOnInit´ to init configuration.
140
+ * This is an angular lifecycle hook, so its called automatically by Angular itself.
141
+ * In particular, it's called only one time!!!
142
+ */
143
+ ngOnInit() {
144
+ const libConfig = this.configService.getConfig(this.id);
145
+ if (!libConfig || !libConfig.buttonsConfig) {
146
+ throw new Error('Internal library error - libConfig and buttonsConfig must be defined');
147
+ }
148
+ this.slideConfig = libConfig.slideConfig;
149
+ this.accessibilityConfig = libConfig.accessibilityConfig;
150
+ this.currentImageConfig = libConfig.currentImageConfig;
151
+ this.keyboardConfig = libConfig.keyboardConfig;
152
+ }
153
+ /**
154
+ * Method ´ngOnChanges´ to update `loading` status and emit events.
155
+ * If the gallery is open, then it will also manage boundary arrows and sliding.
156
+ * This is an angular lifecycle hook, so its called automatically by Angular itself.
157
+ * In particular, it's called when any data-bound property of a directive changes!!!
158
+ */
159
+ ngOnChanges(changes) {
160
+ const libConfig = this.configService.getConfig(this.id);
161
+ if (!libConfig) {
162
+ throw new Error('Internal library error - libConfig must be defined');
163
+ }
164
+ const images = changes.images;
165
+ const currentImage = changes.currentImage;
166
+ if (currentImage && currentImage.previousValue !== currentImage.currentValue) {
167
+ this.updateIndexes();
168
+ }
169
+ else if (images && images.previousValue !== images.currentValue) {
170
+ this.updateIndexes();
171
+ }
172
+ const slideConfig = changes.slideConfig;
173
+ if (slideConfig && slideConfig.previousValue !== slideConfig.currentValue) {
174
+ this.slideConfig = libConfig.slideConfig;
175
+ }
176
+ }
177
+ /**
178
+ * This is an angular lifecycle hook, so its called automatically by Angular itself.
179
+ */
180
+ ngAfterContentInit() {
181
+ // interval doesn't play well with SSR and protractor,
182
+ // so we should run it in the browser and outside Angular
183
+ if (isPlatformBrowser(this.platformId)) {
184
+ this.ngZone.runOutsideAngular(() => {
185
+ this.start$
186
+ .pipe(map(() => this.slideConfig && this.slideConfig.playConfig && this.slideConfig.playConfig.autoPlay && this.slideConfig.playConfig.interval),
187
+ // tslint:disable-next-line:no-any
188
+ filter((interval) => interval > 0), switchMap(interval => timer(interval).pipe(takeUntil(this.stop$))))
189
+ .subscribe(() => this.ngZone.run(() => {
190
+ if (!this.isLastImage) {
191
+ this.nextImage(Action.AUTOPLAY);
192
+ }
193
+ this.ref.markForCheck();
194
+ }));
195
+ this.start$.next();
196
+ });
197
+ }
198
+ }
199
+ /**
200
+ * Method to handle keypress based on the `keyboardConfig` input. It gets the code of
201
+ * the key that triggered the keypress event to navigate between images or to close the modal gallery.
202
+ * @param code string of the key that triggered the keypress event
203
+ */
204
+ onKeyPress(code) {
205
+ const esc = this.keyboardConfig && this.keyboardConfig.esc ? this.keyboardConfig.esc : Keyboard.ESC;
206
+ const right = this.keyboardConfig && this.keyboardConfig.right ? this.keyboardConfig.right : Keyboard.RIGHT_ARROW;
207
+ const left = this.keyboardConfig && this.keyboardConfig.left ? this.keyboardConfig.left : Keyboard.LEFT_ARROW;
208
+ switch (code) {
209
+ case esc:
210
+ this.closeGallery.emit(new ImageModalEvent(this.id, Action.KEYBOARD, true));
211
+ break;
212
+ case right:
213
+ this.nextImage(Action.KEYBOARD);
214
+ break;
215
+ case left:
216
+ this.prevImage(Action.KEYBOARD);
217
+ break;
218
+ }
219
+ }
220
+ /**
221
+ * Method to get the image description based on input params.
222
+ * If you provide a full description this will be the visible description, otherwise,
223
+ * it will be built using the `Description` object, concatenating its fields.
224
+ * @param Image image to get its description. If not provided it will be the current image
225
+ * @returns String description of the image (or the current image if not provided)
226
+ * @throws an Error if description isn't available
227
+ */
228
+ getDescriptionToDisplay(image = this.currentImage) {
229
+ if (!this.currentImageConfig || !this.currentImageConfig.description) {
230
+ throw new Error('Description input must be a valid object implementing the Description interface');
231
+ }
232
+ const imageWithoutDescription = !image.modal || !image.modal.description || image.modal.description === '';
233
+ switch (this.currentImageConfig.description.strategy) {
234
+ case DescriptionStrategy.HIDE_IF_EMPTY:
235
+ return imageWithoutDescription ? '' : image.modal.description + '';
236
+ case DescriptionStrategy.ALWAYS_HIDDEN:
237
+ return '';
238
+ default:
239
+ // ----------- DescriptionStrategy.ALWAYS_VISIBLE -----------------
240
+ return this.buildTextDescription(image, imageWithoutDescription);
241
+ }
242
+ }
243
+ /**
244
+ * Method to get `alt attribute`.
245
+ * `alt` specifies an alternate text for an image, if the image cannot be displayed.
246
+ * @param Image image to get its alt description. If not provided it will be the current image
247
+ * @returns String alt description of the image (or the current image if not provided)
248
+ */
249
+ getAltDescriptionByImage(image = this.currentImage) {
250
+ if (!image) {
251
+ return '';
252
+ }
253
+ return image.modal && image.modal.description ? image.modal.description : `Image ${getIndex(image, this.images) + 1}`;
254
+ }
255
+ /**
256
+ * Method to get the title attributes based on descriptions.
257
+ * This is useful to prevent accessibility issues, because if DescriptionStrategy is ALWAYS_HIDDEN,
258
+ * it prevents an empty string as title.
259
+ * @param Image image to get its description. If not provided it will be the current image
260
+ * @returns String title of the image based on descriptions
261
+ * @throws an Error if description isn't available
262
+ */
263
+ getTitleToDisplay(image = this.currentImage) {
264
+ if (!this.currentImageConfig || !this.currentImageConfig.description) {
265
+ throw new Error('Description input must be a valid object implementing the Description interface');
266
+ }
267
+ const imageWithoutDescription = !image.modal || !image.modal.description || image.modal.description === '';
268
+ const description = this.buildTextDescription(image, imageWithoutDescription);
269
+ return description;
270
+ }
271
+ /**
272
+ * Method to get the left side preview image.
273
+ * @returns Image the image to show as size preview on the left
274
+ */
275
+ getLeftPreviewImage() {
276
+ if (!this.slideConfig) {
277
+ throw new Error('Internal library error - slideConfig must be defined');
278
+ }
279
+ const currentIndex = getIndex(this.currentImage, this.images);
280
+ if (currentIndex === 0 && this.slideConfig.infinite) {
281
+ // the current image is the first one,
282
+ // so the previous one is the last image
283
+ // because infinite is true
284
+ return this.images[this.images.length - 1];
285
+ }
286
+ this.handleBoundaries(currentIndex);
287
+ return this.images[Math.max(currentIndex - 1, 0)];
288
+ }
289
+ /**
290
+ * Method to get the right side preview image.
291
+ * @returns Image the image to show as size preview on the right
292
+ */
293
+ getRightPreviewImage() {
294
+ if (!this.slideConfig) {
295
+ throw new Error('Internal library error - slideConfig must be defined');
296
+ }
297
+ const currentIndex = getIndex(this.currentImage, this.images);
298
+ if (currentIndex === this.images.length - 1 && this.slideConfig.infinite) {
299
+ // the current image is the last one,
300
+ // so the next one is the first image
301
+ // because infinite is true
302
+ return this.images[0];
303
+ }
304
+ this.handleBoundaries(currentIndex);
305
+ return this.images[Math.min(currentIndex + 1, this.images.length - 1)];
306
+ }
307
+ /**
308
+ * Method called by events from both keyboard and mouse on an image.
309
+ * This will invoke the nextImage method.
310
+ * @param KeyboardEvent | MouseEvent event payload
311
+ * @param Action action that triggered the event or `Action.NORMAL` if not provided
312
+ */
313
+ onImageEvent(event, action = Action.NORMAL) {
314
+ if (!this.currentImageConfig) {
315
+ throw new Error('Internal library error - currentImageConfig must be defined');
316
+ }
317
+ // check if triggered by a mouse click
318
+ // If yes, It should block navigation when navigateOnClick is false
319
+ if (action === Action.CLICK && !this.currentImageConfig.navigateOnClick) {
320
+ // a user has requested to block navigation via configCurrentImage.navigateOnClick property
321
+ return;
322
+ }
323
+ const result = super.handleImageEvent(event);
324
+ if (result === NEXT) {
325
+ this.nextImage(action);
326
+ }
327
+ }
328
+ /**
329
+ * Method called by events from both keyboard and mouse on a navigation arrow.
330
+ * @param string direction of the navigation that can be either 'next' or 'prev'
331
+ * @param KeyboardEvent | MouseEvent event payload
332
+ * @param Action action that triggered the event or `Action.NORMAL` if not provided
333
+ * @param boolean disable to disable navigation
334
+ */
335
+ onNavigationEvent(direction, event, action = Action.NORMAL, disable = false) {
336
+ if (disable) {
337
+ return;
338
+ }
339
+ const result = super.handleNavigationEvent(direction, event);
340
+ if (result === NEXT) {
341
+ this.nextImage(action);
342
+ }
343
+ else if (result === PREV) {
344
+ this.prevImage(action);
345
+ }
346
+ }
347
+ /**
348
+ * Method to go back to the previous image.
349
+ * @param action Enum of type `Action` that represents the source
350
+ * action that moved back to the previous image. `Action.NORMAL` by default.
351
+ */
352
+ prevImage(action = Action.NORMAL) {
353
+ // check if prevImage should be blocked
354
+ if (this.isPreventSliding(0)) {
355
+ return;
356
+ }
357
+ const prevImage = this.getPrevImage();
358
+ this.loading = !prevImage.previouslyLoaded;
359
+ this.changeImage.emit(new ImageModalEvent(this.id, action, getIndex(prevImage, this.images)));
360
+ this.start$.next();
361
+ }
362
+ /**
363
+ * Method to go back to the previous image.
364
+ * @param action Enum of type `Action` that represents the source
365
+ * action that moved to the next image. `Action.NORMAL` by default.
366
+ */
367
+ nextImage(action = Action.NORMAL) {
368
+ // check if nextImage should be blocked
369
+ if (this.isPreventSliding(this.images.length - 1)) {
370
+ return;
371
+ }
372
+ const nextImage = this.getNextImage();
373
+ this.loading = !nextImage.previouslyLoaded;
374
+ this.changeImage.emit(new ImageModalEvent(this.id, action, getIndex(nextImage, this.images)));
375
+ this.start$.next();
376
+ }
377
+ /**
378
+ * Method to emit an event as loadImage output to say that the requested image if loaded.
379
+ * This method is invoked by the javascript's 'load' event on an img tag.
380
+ * @param Event event that triggered the load
381
+ */
382
+ onImageLoad(event) {
383
+ const loadImageData = {
384
+ status: true,
385
+ index: getIndex(this.currentImage, this.images),
386
+ id: this.currentImage.id
387
+ };
388
+ this.loadImage.emit(loadImageData);
389
+ this.loading = false;
390
+ }
391
+ /**
392
+ * Method used by SwipeDirective to support touch gestures (you can also invert the swipe direction with configCurrentImage.invertSwipe).
393
+ * @param action String that represent the direction of the swipe action. 'swiperight' by default.
394
+ */
395
+ swipe(action = 'swiperight') {
396
+ if (!this.currentImageConfig) {
397
+ throw new Error('Internal library error - currentImageConfig must be defined');
398
+ }
399
+ switch (action) {
400
+ case 'swiperight':
401
+ if (this.currentImageConfig.invertSwipe) {
402
+ this.prevImage(Action.SWIPE);
403
+ }
404
+ else {
405
+ this.nextImage(Action.SWIPE);
406
+ }
407
+ break;
408
+ case 'swipeleft':
409
+ if (this.currentImageConfig.invertSwipe) {
410
+ this.nextImage(Action.SWIPE);
411
+ }
412
+ else {
413
+ this.prevImage(Action.SWIPE);
414
+ }
415
+ break;
416
+ // case this.SWIPE_ACTION.UP:
417
+ // break;
418
+ // case this.SWIPE_ACTION.DOWN:
419
+ // break;
420
+ }
421
+ }
422
+ /**
423
+ * Method used in `modal-gallery.component` to get the index of an image to delete.
424
+ * @param Image image to get the index, or the visible image, if not passed
425
+ * @returns number the index of the image
426
+ */
427
+ getIndexToDelete(image = this.currentImage) {
428
+ return getIndex(image, this.images);
429
+ }
430
+ /**
431
+ * Method to play modal gallery.
432
+ */
433
+ playCarousel() {
434
+ this.start$.next();
435
+ }
436
+ /**
437
+ * Stops modal gallery from cycling through items.
438
+ */
439
+ stopCarousel() {
440
+ this.stop$.next();
441
+ }
442
+ /**
443
+ * Method to cleanup resources. In fact, this will stop the modal gallery.
444
+ * This is an angular lifecycle hook that is called when this component is destroyed.
445
+ */
446
+ ngOnDestroy() {
447
+ this.stopCarousel();
448
+ }
449
+ /**
450
+ * Private method to update both `isFirstImage` and `isLastImage` based on
451
+ * the index of the current image.
452
+ * @param number currentIndex is the index of the current image
453
+ */
454
+ handleBoundaries(currentIndex) {
455
+ if (this.images.length === 1) {
456
+ this.isFirstImage = true;
457
+ this.isLastImage = true;
458
+ this.ref.markForCheck();
459
+ return;
460
+ }
461
+ if (!this.slideConfig || this.slideConfig.infinite === true) {
462
+ // infinite sliding enabled
463
+ this.isFirstImage = false;
464
+ this.isLastImage = false;
465
+ this.ref.markForCheck();
466
+ }
467
+ else {
468
+ // execute this only if infinite sliding is disabled
469
+ switch (currentIndex) {
470
+ case 0:
471
+ this.isFirstImage = true;
472
+ this.isLastImage = false;
473
+ this.ref.markForCheck();
474
+ break;
475
+ case this.images.length - 1:
476
+ this.isFirstImage = false;
477
+ this.isLastImage = true;
478
+ this.ref.markForCheck();
479
+ break;
480
+ default:
481
+ this.isFirstImage = false;
482
+ this.isLastImage = false;
483
+ this.ref.markForCheck();
484
+ break;
485
+ }
486
+ }
487
+ }
488
+ /**
489
+ * Private method to check if next/prev actions should be blocked.
490
+ * It checks if slideConfig.infinite === false and if the image index is equals to the input parameter.
491
+ * If yes, it returns true to say that sliding should be blocked, otherwise not.
492
+ * @param number boundaryIndex that could be either the beginning index (0) or the last index
493
+ * of images (this.images.length - 1).
494
+ * @returns boolean true if slideConfig.infinite === false and the current index is
495
+ * either the first or the last one.
496
+ */
497
+ isPreventSliding(boundaryIndex) {
498
+ return !!this.slideConfig && this.slideConfig.infinite === false && getIndex(this.currentImage, this.images) === boundaryIndex;
499
+ }
500
+ /**
501
+ * Private method to get the next index.
502
+ * This is necessary because at the end, when you call next again, you'll go to the first image.
503
+ * That happens because all modal images are shown like in a circle.
504
+ */
505
+ getNextImage() {
506
+ const currentIndex = getIndex(this.currentImage, this.images);
507
+ let newIndex = 0;
508
+ if (currentIndex >= 0 && currentIndex < this.images.length - 1) {
509
+ newIndex = currentIndex + 1;
510
+ }
511
+ else {
512
+ newIndex = 0; // start from the first index
513
+ }
514
+ return this.images[newIndex];
515
+ }
516
+ /**
517
+ * Private method to get the previous index.
518
+ * This is necessary because at index 0, when you call prev again, you'll go to the last image.
519
+ * That happens because all modal images are shown like in a circle.
520
+ */
521
+ getPrevImage() {
522
+ const currentIndex = getIndex(this.currentImage, this.images);
523
+ let newIndex = 0;
524
+ if (currentIndex > 0 && currentIndex <= this.images.length - 1) {
525
+ newIndex = currentIndex - 1;
526
+ }
527
+ else {
528
+ newIndex = this.images.length - 1; // start from the last index
529
+ }
530
+ return this.images[newIndex];
531
+ }
532
+ /**
533
+ * Private method to build a text description.
534
+ * This is used also to create titles.
535
+ * @param Image image to get its description. If not provided it will be the current image.
536
+ * @param boolean imageWithoutDescription is a boolean that it's true if the image hasn't a 'modal' description.
537
+ * @returns String description built concatenating image fields with a specific logic.
538
+ */
539
+ buildTextDescription(image, imageWithoutDescription) {
540
+ if (!this.currentImageConfig || !this.currentImageConfig.description) {
541
+ throw new Error('Description input must be a valid object implementing the Description interface');
542
+ }
543
+ // If customFullDescription use it, otherwise proceed to build a description
544
+ if (this.currentImageConfig.description.customFullDescription && this.currentImageConfig.description.customFullDescription !== '') {
545
+ return this.currentImageConfig.description.customFullDescription;
546
+ }
547
+ const currentIndex = getIndex(image, this.images);
548
+ // If the current image hasn't a description,
549
+ // prevent to write the ' - ' (or this.description.beforeTextDescription)
550
+ const prevDescription = this.currentImageConfig.description.imageText ? this.currentImageConfig.description.imageText : '';
551
+ const midSeparator = this.currentImageConfig.description.numberSeparator ? this.currentImageConfig.description.numberSeparator : '';
552
+ const middleDescription = currentIndex + 1 + midSeparator + this.images.length;
553
+ if (imageWithoutDescription) {
554
+ return prevDescription + middleDescription;
555
+ }
556
+ const currImgDescription = image.modal && image.modal.description ? image.modal.description : '';
557
+ const endDescription = this.currentImageConfig.description.beforeTextDescription + currImgDescription;
558
+ return prevDescription + middleDescription + endDescription;
559
+ }
560
+ /**
561
+ * Private method to call handleBoundaries when ngOnChanges is called.
562
+ */
563
+ updateIndexes() {
564
+ try {
565
+ if (this.isOpen) {
566
+ const index = getIndex(this.currentImage, this.images);
567
+ this.handleBoundaries(index);
568
+ }
569
+ }
570
+ catch (err) {
571
+ console.error('Cannot get the current image index in current-image');
572
+ throw err;
573
+ }
574
+ }
575
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: CurrentImageComponent, deps: [{ token: PLATFORM_ID }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1.ConfigService }], target: i0.ɵɵFactoryTarget.Component }); }
576
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: CurrentImageComponent, selector: "ks-current-image", inputs: { id: "id", currentImage: "currentImage", images: "images", isOpen: "isOpen" }, outputs: { loadImage: "loadImage", changeImage: "changeImage", closeGallery: "closeGallery" }, host: { listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave()" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<main class=\"main-image-container\"\n ksKeyboardNavigation [isOpen]=\"isOpen\" (keyboardNavigation)=\"onKeyPress($event)\"\n [attr.aria-label]=\"accessibilityConfig?.mainContainerAriaLabel\"\n [title]=\"accessibilityConfig?.mainContainerTitle\">\n\n <div class=\"left-sub-container\">\n <a class=\"nav-left {{isFirstImage ? 'no-pointer' : ''}}\"\n [attr.aria-label]=\"accessibilityConfig?.mainPrevImageAriaLabel\"\n [tabIndex]=\"isFirstImage ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event)\" (keyup)=\"onNavigationEvent('left', $event)\">\n <div class=\"inside {{isFirstImage ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"isFirstImage ? '' : accessibilityConfig?.mainPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngIf=\"slideConfig?.sidePreviews?.show\">\n <ng-container *ngIf=\"getLeftPreviewImage() as leftPreview\">\n <img *ngIf=\"!isFirstImage; else firstImage\"\n class=\"inside current-image-previous\"\n [src]=\"leftPreview.plain?.img ? leftPreview.plain?.img : leftPreview.modal.img\"\n ksFallbackImage [fallbackImg]=\"leftPreview.plain?.fallbackImg ? leftPreview.plain?.fallbackImg : leftPreview.modal.fallbackImg\"\n [hidden]=\"loading\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"\n [attr.aria-label]=\"leftPreview.modal.ariaLabel\"\n [title]=\"(leftPreview.modal.title || leftPreview.modal.title === '') ? leftPreview.modal.title : getDescriptionToDisplay(leftPreview)\"\n alt=\"{{leftPreview.modal.alt ? leftPreview.modal.alt : getAltDescriptionByImage(leftPreview)}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\"/>\n <ng-template #firstImage>\n <div class=\"current-image-previous hidden\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"></div>\n </ng-template>\n </ng-container>\n </ng-container>\n </div>\n\n\n <figure id=\"current-figure\" [style.display]=\"loading ? 'none' : ''\">\n <img id=\"current-image\"\n class=\"inside\"\n [ngClass]=\"currentImageConfig?.navigateOnClick ? '' : 'unclickable'\"\n [src]=\"currentImage.modal.img\"\n ksFallbackImage [fallbackImg]=\"currentImage.modal.fallbackImg\"\n [attr.aria-label]=\"currentImage.modal.ariaLabel\"\n [title]=\"(currentImage.modal.title || currentImage.modal.title === '') ? currentImage.modal.title : getTitleToDisplay()\"\n alt=\"{{currentImage.modal.alt ? currentImage.modal.alt : getAltDescriptionByImage()}}\"\n [tabIndex]=\"0\" role=\"img\"\n (load)=\"onImageLoad($event)\"\n (click)=\"onImageEvent($event, clickAction)\" (keyup)=\"onImageEvent($event, keyboardAction)\"\n ksSwipe\n (swipeLeft)=\"swipe('swipeleft')\"\n (swipeRight)=\"swipe('swiperight')\"/>\n <figcaption *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"inside description\"\n ksDescription [description]=\"currentImageConfig?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\">\n </figcaption>\n </figure>\n\n <div class=\"right-sub-container\">\n <ng-container *ngIf=\"slideConfig?.sidePreviews?.show\">\n <ng-container *ngIf=\"getRightPreviewImage() as rightPreview\">\n <img *ngIf=\"!isLastImage; else lastImage\"\n class=\"inside current-image-next\"\n [src]=\"rightPreview.plain?.img ? rightPreview.plain?.img : rightPreview.modal.img\"\n ksFallbackImage [fallbackImg]=\"rightPreview.plain?.fallbackImg ? rightPreview.plain?.fallbackImg : rightPreview.modal.fallbackImg\"\n [hidden]=\"loading\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"\n [attr.aria-label]=\"rightPreview.modal.ariaLabel\"\n [title]=\"(rightPreview.modal.title || rightPreview.modal.title === '') ? rightPreview.modal.title : getDescriptionToDisplay(rightPreview)\"\n alt=\"{{rightPreview.modal.alt ? rightPreview.modal.alt : getAltDescriptionByImage(rightPreview)}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\"/>\n <ng-template #lastImage>\n <div class=\"current-image-next hidden\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\">\n </div>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"loading && currentImageConfig?.loadingConfig?.enable\">\n <ks-loading-spinner [loadingConfig]=\"currentImageConfig?.loadingConfig\"\n [accessibilityConfig]=\"accessibilityConfig\"></ks-loading-spinner>\n </ng-container>\n\n <a class=\"nav-right {{isFirstImage ? 'no-pointer' : ''}}\"\n [attr.aria-label]=\"accessibilityConfig?.mainNextImageAriaLabel\"\n [tabIndex]=\"isLastImage ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event)\" (keyup)=\"onNavigationEvent('right', $event)\">\n <div class=\"inside {{isLastImage ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"isLastImage ? '' : accessibilityConfig?.mainNextImageTitle\"></div>\n </a>\n </div>\n</main>\n", styles: [":host{display:flex;flex-direction:column;justify-content:center}.main-image-container{display:flex;flex-direction:row;align-items:center;justify-content:space-between}.main-image-container .nav,.main-image-container>.right-sub-container>.nav-right,.main-image-container>.left-sub-container>.nav-left{animation:animatezoom 1s;cursor:pointer;transition:all .5s}.main-image-container .nav:hover,.main-image-container>.right-sub-container>.nav-right:hover,.main-image-container>.left-sub-container>.nav-left:hover{transform:scale(1.1)}.main-image-container>.left-sub-container{display:flex;flex-direction:row;justify-content:space-around;align-items:center}.main-image-container>.left-sub-container>.nav-left{margin-right:5px;margin-left:15px}.main-image-container>.left-sub-container>.nav-left.no-pointer{cursor:default!important}.main-image-container>.right-sub-container{display:flex;flex-direction:row;justify-content:space-around;align-items:center}.main-image-container>.right-sub-container>.nav-right{margin-right:15px;margin-left:5px}.main-image-container>.right-sub-container>.nav-right.no-pointer{cursor:default!important}.main-image-container #current-figure{animation:fadein-visible .8s;text-align:center;margin:0;position:relative}.main-image-container #current-figure>#current-image{max-width:100%;height:auto;display:block}.main-image-container #current-figure>#current-image.unclickable{cursor:not-allowed}.main-image-container #current-figure figcaption{padding:10px;position:absolute;bottom:0;left:0;right:0}.main-image-container #current-figure figcaption .description{font-weight:700;text-align:center}#current-image{height:auto;max-width:80vw;max-height:60vh;cursor:pointer}@media screen and (min-width: 70vw){#current-image{max-width:70vw}}@keyframes fadein-visible{0%{opacity:0}to{opacity:1}}@keyframes fadein-semi-visible05{0%{opacity:0}to{opacity:.5}}@keyframes fadein-semi-visible08{0%{opacity:0}to{opacity:.8}}@keyframes fadein-semi-visible09{0%{opacity:0}to{opacity:.9}}\n", ".arrow-image,.right-arrow-image,.left-arrow-image,.empty-arrow-image{width:30px;height:30px;background-size:30px}.empty-arrow-image{background:black;opacity:0}.left-arrow-image{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMTQ1LjE4OCwyMzguNTc1bDIxNS41LTIxNS41YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xcy0xMy44LTUuMy0xOS4xLDBsLTIyNS4xLDIyNS4xYy01LjMsNS4zLTUuMywxMy44LDAsMTkuMWwyMjUuMSwyMjUgICBjMi42LDIuNiw2LjEsNCw5LjUsNHM2LjktMS4zLDkuNS00YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xTDE0NS4xODgsMjM4LjU3NXoiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+);opacity:.8;transition:all .5s}.left-arrow-image:hover{transform:scale(1.2)}.right-arrow-image{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMzYwLjczMSwyMjkuMDc1bC0yMjUuMS0yMjUuMWMtNS4zLTUuMy0xMy44LTUuMy0xOS4xLDBzLTUuMywxMy44LDAsMTkuMWwyMTUuNSwyMTUuNWwtMjE1LjUsMjE1LjUgICBjLTUuMyw1LjMtNS4zLDEzLjgsMCwxOS4xYzIuNiwyLjYsNi4xLDQsOS41LDRjMy40LDAsNi45LTEuMyw5LjUtNGwyMjUuMS0yMjUuMUMzNjUuOTMxLDI0Mi44NzUsMzY1LjkzMSwyMzQuMjc1LDM2MC43MzEsMjI5LjA3NXogICAiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+);opacity:.8;transition:all .5s}.right-arrow-image:hover{transform:scale(1.2)}\n", "@media only screen and (max-width: 1024px),only screen and (max-device-width: 1024px){.current-image-previous,.current-image-next{display:none}}@media only screen and (min-device-width: 1025px){.current-image-preview,.current-image-next,.current-image-previous{height:auto;cursor:pointer;opacity:.5;animation:fadein-semi-visible05 .8s;filter:alpha(opacity=50)}.current-image-preview:hover,.current-image-next:hover,.current-image-previous:hover{opacity:1;transition-property:opacity;transition:all .5s ease}.current-image-previous{margin-left:10px;margin-right:5px}.current-image-next{margin-right:10px;margin-left:5px}}@keyframes fadein-semi-visible05{0%{opacity:0}to{opacity:.5}}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.LoadingSpinnerComponent, selector: "ks-loading-spinner", inputs: ["loadingConfig", "accessibilityConfig"] }, { kind: "directive", type: i4.SizeDirective, selector: "[ksSize]", inputs: ["sizeConfig"] }, { kind: "directive", type: i5.KeyboardNavigationDirective, selector: "[ksKeyboardNavigation]", inputs: ["isOpen"], outputs: ["keyboardNavigation"] }, { kind: "directive", type: i6.DescriptionDirective, selector: "[ksDescription]", inputs: ["description"] }, { kind: "directive", type: i7.FallbackImageDirective, selector: "[ksFallbackImage]", inputs: ["fallbackImg"], outputs: ["fallbackApplied"] }, { kind: "directive", type: i8.SwipeDirective, selector: "[ksSwipe]", outputs: ["swipeLeft", "swipeRight", "swipeUp", "swipeDown"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
577
+ }
578
+ export { CurrentImageComponent };
579
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: CurrentImageComponent, decorators: [{
580
+ type: Component,
581
+ args: [{ selector: 'ks-current-image', changeDetection: ChangeDetectionStrategy.OnPush, template: "<main class=\"main-image-container\"\n ksKeyboardNavigation [isOpen]=\"isOpen\" (keyboardNavigation)=\"onKeyPress($event)\"\n [attr.aria-label]=\"accessibilityConfig?.mainContainerAriaLabel\"\n [title]=\"accessibilityConfig?.mainContainerTitle\">\n\n <div class=\"left-sub-container\">\n <a class=\"nav-left {{isFirstImage ? 'no-pointer' : ''}}\"\n [attr.aria-label]=\"accessibilityConfig?.mainPrevImageAriaLabel\"\n [tabIndex]=\"isFirstImage ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event)\" (keyup)=\"onNavigationEvent('left', $event)\">\n <div class=\"inside {{isFirstImage ? 'empty-arrow-image' : 'left-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"isFirstImage ? '' : accessibilityConfig?.mainPrevImageTitle\"></div>\n </a>\n\n <ng-container *ngIf=\"slideConfig?.sidePreviews?.show\">\n <ng-container *ngIf=\"getLeftPreviewImage() as leftPreview\">\n <img *ngIf=\"!isFirstImage; else firstImage\"\n class=\"inside current-image-previous\"\n [src]=\"leftPreview.plain?.img ? leftPreview.plain?.img : leftPreview.modal.img\"\n ksFallbackImage [fallbackImg]=\"leftPreview.plain?.fallbackImg ? leftPreview.plain?.fallbackImg : leftPreview.modal.fallbackImg\"\n [hidden]=\"loading\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"\n [attr.aria-label]=\"leftPreview.modal.ariaLabel\"\n [title]=\"(leftPreview.modal.title || leftPreview.modal.title === '') ? leftPreview.modal.title : getDescriptionToDisplay(leftPreview)\"\n alt=\"{{leftPreview.modal.alt ? leftPreview.modal.alt : getAltDescriptionByImage(leftPreview)}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onNavigationEvent('left', $event, clickAction)\" (keyup)=\"onNavigationEvent('left', $event, keyboardAction)\"/>\n <ng-template #firstImage>\n <div class=\"current-image-previous hidden\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"></div>\n </ng-template>\n </ng-container>\n </ng-container>\n </div>\n\n\n <figure id=\"current-figure\" [style.display]=\"loading ? 'none' : ''\">\n <img id=\"current-image\"\n class=\"inside\"\n [ngClass]=\"currentImageConfig?.navigateOnClick ? '' : 'unclickable'\"\n [src]=\"currentImage.modal.img\"\n ksFallbackImage [fallbackImg]=\"currentImage.modal.fallbackImg\"\n [attr.aria-label]=\"currentImage.modal.ariaLabel\"\n [title]=\"(currentImage.modal.title || currentImage.modal.title === '') ? currentImage.modal.title : getTitleToDisplay()\"\n alt=\"{{currentImage.modal.alt ? currentImage.modal.alt : getAltDescriptionByImage()}}\"\n [tabIndex]=\"0\" role=\"img\"\n (load)=\"onImageLoad($event)\"\n (click)=\"onImageEvent($event, clickAction)\" (keyup)=\"onImageEvent($event, keyboardAction)\"\n ksSwipe\n (swipeLeft)=\"swipe('swipeleft')\"\n (swipeRight)=\"swipe('swiperight')\"/>\n <figcaption *ngIf=\"getDescriptionToDisplay() !== ''\"\n class=\"inside description\"\n ksDescription [description]=\"currentImageConfig?.description\"\n [innerHTML]=\"getDescriptionToDisplay()\">\n </figcaption>\n </figure>\n\n <div class=\"right-sub-container\">\n <ng-container *ngIf=\"slideConfig?.sidePreviews?.show\">\n <ng-container *ngIf=\"getRightPreviewImage() as rightPreview\">\n <img *ngIf=\"!isLastImage; else lastImage\"\n class=\"inside current-image-next\"\n [src]=\"rightPreview.plain?.img ? rightPreview.plain?.img : rightPreview.modal.img\"\n ksFallbackImage [fallbackImg]=\"rightPreview.plain?.fallbackImg ? rightPreview.plain?.fallbackImg : rightPreview.modal.fallbackImg\"\n [hidden]=\"loading\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\"\n [attr.aria-label]=\"rightPreview.modal.ariaLabel\"\n [title]=\"(rightPreview.modal.title || rightPreview.modal.title === '') ? rightPreview.modal.title : getDescriptionToDisplay(rightPreview)\"\n alt=\"{{rightPreview.modal.alt ? rightPreview.modal.alt : getAltDescriptionByImage(rightPreview)}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onNavigationEvent('right', $event, clickAction)\" (keyup)=\"onNavigationEvent('right', $event, keyboardAction)\"/>\n <ng-template #lastImage>\n <div class=\"current-image-next hidden\"\n ksSize [sizeConfig]=\"{width: slideConfig?.sidePreviews?.size.width, height: slideConfig?.sidePreviews?.size.height}\">\n </div>\n </ng-template>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"loading && currentImageConfig?.loadingConfig?.enable\">\n <ks-loading-spinner [loadingConfig]=\"currentImageConfig?.loadingConfig\"\n [accessibilityConfig]=\"accessibilityConfig\"></ks-loading-spinner>\n </ng-container>\n\n <a class=\"nav-right {{isFirstImage ? 'no-pointer' : ''}}\"\n [attr.aria-label]=\"accessibilityConfig?.mainNextImageAriaLabel\"\n [tabIndex]=\"isLastImage ? -1 : 0\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event)\" (keyup)=\"onNavigationEvent('right', $event)\">\n <div class=\"inside {{isLastImage ? 'empty-arrow-image' : 'right-arrow-image'}}\"\n aria-hidden=\"true\"\n [title]=\"isLastImage ? '' : accessibilityConfig?.mainNextImageTitle\"></div>\n </a>\n </div>\n</main>\n", styles: [":host{display:flex;flex-direction:column;justify-content:center}.main-image-container{display:flex;flex-direction:row;align-items:center;justify-content:space-between}.main-image-container .nav,.main-image-container>.right-sub-container>.nav-right,.main-image-container>.left-sub-container>.nav-left{animation:animatezoom 1s;cursor:pointer;transition:all .5s}.main-image-container .nav:hover,.main-image-container>.right-sub-container>.nav-right:hover,.main-image-container>.left-sub-container>.nav-left:hover{transform:scale(1.1)}.main-image-container>.left-sub-container{display:flex;flex-direction:row;justify-content:space-around;align-items:center}.main-image-container>.left-sub-container>.nav-left{margin-right:5px;margin-left:15px}.main-image-container>.left-sub-container>.nav-left.no-pointer{cursor:default!important}.main-image-container>.right-sub-container{display:flex;flex-direction:row;justify-content:space-around;align-items:center}.main-image-container>.right-sub-container>.nav-right{margin-right:15px;margin-left:5px}.main-image-container>.right-sub-container>.nav-right.no-pointer{cursor:default!important}.main-image-container #current-figure{animation:fadein-visible .8s;text-align:center;margin:0;position:relative}.main-image-container #current-figure>#current-image{max-width:100%;height:auto;display:block}.main-image-container #current-figure>#current-image.unclickable{cursor:not-allowed}.main-image-container #current-figure figcaption{padding:10px;position:absolute;bottom:0;left:0;right:0}.main-image-container #current-figure figcaption .description{font-weight:700;text-align:center}#current-image{height:auto;max-width:80vw;max-height:60vh;cursor:pointer}@media screen and (min-width: 70vw){#current-image{max-width:70vw}}@keyframes fadein-visible{0%{opacity:0}to{opacity:1}}@keyframes fadein-semi-visible05{0%{opacity:0}to{opacity:.5}}@keyframes fadein-semi-visible08{0%{opacity:0}to{opacity:.8}}@keyframes fadein-semi-visible09{0%{opacity:0}to{opacity:.9}}\n", ".arrow-image,.right-arrow-image,.left-arrow-image,.empty-arrow-image{width:30px;height:30px;background-size:30px}.empty-arrow-image{background:black;opacity:0}.left-arrow-image{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMTQ1LjE4OCwyMzguNTc1bDIxNS41LTIxNS41YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xcy0xMy44LTUuMy0xOS4xLDBsLTIyNS4xLDIyNS4xYy01LjMsNS4zLTUuMywxMy44LDAsMTkuMWwyMjUuMSwyMjUgICBjMi42LDIuNiw2LjEsNCw5LjUsNHM2LjktMS4zLDkuNS00YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xTDE0NS4xODgsMjM4LjU3NXoiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+);opacity:.8;transition:all .5s}.left-arrow-image:hover{transform:scale(1.2)}.right-arrow-image{background-image:url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMzYwLjczMSwyMjkuMDc1bC0yMjUuMS0yMjUuMWMtNS4zLTUuMy0xMy44LTUuMy0xOS4xLDBzLTUuMywxMy44LDAsMTkuMWwyMTUuNSwyMTUuNWwtMjE1LjUsMjE1LjUgICBjLTUuMyw1LjMtNS4zLDEzLjgsMCwxOS4xYzIuNiwyLjYsNi4xLDQsOS41LDRjMy40LDAsNi45LTEuMyw5LjUtNGwyMjUuMS0yMjUuMUMzNjUuOTMxLDI0Mi44NzUsMzY1LjkzMSwyMzQuMjc1LDM2MC43MzEsMjI5LjA3NXogICAiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+);opacity:.8;transition:all .5s}.right-arrow-image:hover{transform:scale(1.2)}\n", "@media only screen and (max-width: 1024px),only screen and (max-device-width: 1024px){.current-image-previous,.current-image-next{display:none}}@media only screen and (min-device-width: 1025px){.current-image-preview,.current-image-next,.current-image-previous{height:auto;cursor:pointer;opacity:.5;animation:fadein-semi-visible05 .8s;filter:alpha(opacity=50)}.current-image-preview:hover,.current-image-next:hover,.current-image-previous:hover{opacity:1;transition-property:opacity;transition:all .5s ease}.current-image-previous{margin-left:10px;margin-right:5px}.current-image-next{margin-right:10px;margin-left:5px}}@keyframes fadein-semi-visible05{0%{opacity:0}to{opacity:.5}}\n"] }]
582
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
583
+ type: Inject,
584
+ args: [PLATFORM_ID]
585
+ }] }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1.ConfigService }]; }, propDecorators: { id: [{
586
+ type: Input
587
+ }], currentImage: [{
588
+ type: Input
589
+ }], images: [{
590
+ type: Input
591
+ }],
592
+ // @ts-ignore
593
+ isOpen: [{
594
+ type: Input
595
+ }], loadImage: [{
596
+ type: Output
597
+ }], changeImage: [{
598
+ type: Output
599
+ }], closeGallery: [{
600
+ type: Output
601
+ }], onMouseEnter: [{
602
+ type: HostListener,
603
+ args: ['mouseenter']
604
+ }], onMouseLeave: [{
605
+ type: HostListener,
606
+ args: ['mouseleave']
607
+ }] } });
608
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VycmVudC1pbWFnZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rczg5L2FuZ3VsYXItbW9kYWwtZ2FsbGVyeS9zcmMvbGliL2NvbXBvbmVudHMvY3VycmVudC1pbWFnZS9jdXJyZW50LWltYWdlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2tzODkvYW5ndWxhci1tb2RhbC1nYWxsZXJ5L3NyYy9saWIvY29tcG9uZW50cy9jdXJyZW50LWltYWdlL2N1cnJlbnQtaW1hZ2UuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILE9BQU8sRUFFTCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULFlBQVksRUFDWixZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFLTCxNQUFNLEVBQ04sV0FBVyxFQUdaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXBELE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVuRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUU5RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakQsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDeEUsT0FBTyxFQUFTLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRWpFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUdyRCxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxN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RkFBckIscUJBQXFCO2tCQU5qQyxTQUFTOytCQUNFLGtCQUFrQixtQkFHWCx1QkFBdUIsQ0FBQyxNQUFNOzswQkF3R2xDLE1BQU07MkJBQUMsV0FBVzs2SEFoRy9CLEVBQUU7c0JBREQsS0FBSztnQkFNTixZQUFZO3NCQURYLEtBQUs7Z0JBT04sTUFBTTtzQkFETCxLQUFLOztRQU9OLGFBQWE7UUFDYixNQUFNO3NCQUZMLEtBQUs7Z0JBUU4sU0FBUztzQkFEUixNQUFNO2dCQU1QLFdBQVc7c0JBRFYsTUFBTTtnQkFNUCxZQUFZO3NCQURYLE1BQU07Z0JBd0VQLFlBQVk7c0JBRFgsWUFBWTt1QkFBQyxZQUFZO2dCQWdCMUIsWUFBWTtzQkFEWCxZQUFZO3VCQUFDLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxuXG4gQ29weXJpZ2h0IChDKSAyMDE3LTIwMjMgU3RlZmFubyBDYXBwYSAoS3M4OSlcblxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuXG4gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG4gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cblxuIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcbiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OIElORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEVcbiBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBQTEFURk9STV9JRCxcbiAgU2ltcGxlQ2hhbmdlLFxuICBTaW1wbGVDaGFuZ2VzXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5pbXBvcnQgeyBTdWJqZWN0LCB0aW1lciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCBtYXAsIHN3aXRjaE1hcCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBBY2Nlc3NpYmxlQ29tcG9uZW50IH0gZnJvbSAnLi4vYWNjZXNzaWJsZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgQWNjZXNzaWJpbGl0eUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2FjY2Vzc2liaWxpdHkuaW50ZXJmYWNlJztcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gJy4uLy4uL21vZGVsL2FjdGlvbi5lbnVtJztcbmltcG9ydCB7IERlc2NyaXB0aW9uU3RyYXRlZ3kgfSBmcm9tICcuLi8uLi9tb2RlbC9kZXNjcmlwdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgSW1hZ2UsIEltYWdlTW9kYWxFdmVudCB9IGZyb20gJy4uLy4uL21vZGVsL2ltYWdlLmNsYXNzJztcbmltcG9ydCB7IEludGVybmFsTGliSW1hZ2UgfSBmcm9tICcuLi8uLi9tb2RlbC9pbWFnZS1pbnRlcm5hbC5jbGFzcyc7XG5pbXBvcnQgeyBLZXlib2FyZCB9IGZyb20gJy4uLy4uL21vZGVsL2tleWJvYXJkLmVudW0nO1xuaW1wb3J0IHsgS2V5Ym9hcmRDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9rZXlib2FyZC1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IFNsaWRlQ29uZmlnIH0gZnJvbSAnLi4vLi4vbW9kZWwvc2xpZGUtY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBORVhULCBQUkVWIH0gZnJvbSAnLi4vLi4vdXRpbHMvdXNlci1pbnB1dC51dGlsJztcbmltcG9ydCB7IGdldEluZGV4IH0gZnJvbSAnLi4vLi4vdXRpbHMvaW1hZ2UudXRpbCc7XG5pbXBvcnQgeyBDdXJyZW50SW1hZ2VDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9jdXJyZW50LWltYWdlLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ29uZmlnU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IExpYkNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2xpYi1jb25maWcuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBJbnRlcmZhY2UgdG8gZGVzY3JpYmUgdGhlIExvYWQgRXZlbnQsIHVzZWQgdG9cbiAqIGVtaXQgYW4gZXZlbnQgd2hlbiB0aGUgaW1hZ2UgaXMgZmluYWxseSBsb2FkZWQgYW5kIHRoZSBzcGlubmVyIGhhcyBnb25lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEltYWdlTG9hZEV2ZW50IHtcbiAgc3RhdHVzOiBib29sZWFuO1xuICBpbmRleDogbnVtYmVyO1xuICBpZDogbnVtYmVyO1xufVxuXG4vKipcbiAqIENvbXBvbmVudCB3aXRoIHRoZSBjdXJyZW50IGltYWdlIHdpdGggc29tZSBhZGRpdGlvbmFsIGVsZW1lbnRzIGxpa2UgYXJyb3dzIGFuZCBzaWRlIHByZXZpZXdzLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdrcy1jdXJyZW50LWltYWdlJyxcbiAgc3R5bGVVcmxzOiBbJ2N1cnJlbnQtaW1hZ2Uuc2NzcycsICcuLi9pbWFnZS1hcnJvd3Muc2NzcycsICdjdXJyZW50LWltYWdlLXByZXZpZXdzLnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICdjdXJyZW50LWltYWdlLmh0bWwnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBDdXJyZW50SW1hZ2VDb21wb25lbnQgZXh0ZW5kcyBBY2Nlc3NpYmxlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBVbmlxdWUgaWQgKD49MCkgb2YgdGhlIGN1cnJlbnQgaW5zdGFuY2Ugb2YgdGhpcyBsaWJyYXJ5LiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHlvdSBhcmUgdXNpbmdcbiAgICogdGhlIHNlcnZpY2UgdG8gY2FsbCBtb2RhbCBnYWxsZXJ5IHdpdGhvdXQgb3BlbiBpdCBtYW51YWxseS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGlkITogbnVtYmVyO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYEludGVybmFsTGliSW1hZ2VgIHRoYXQgcmVwcmVzZW50IHRoZSB2aXNpYmxlIGltYWdlLlxuICAgKi9cbiAgQElucHV0KClcbiAgY3VycmVudEltYWdlITogSW50ZXJuYWxMaWJJbWFnZTtcbiAgLyoqXG4gICAqIEFycmF5IG9mIGBJbnRlcm5hbExpYkltYWdlYCB0aGF0IHJlcHJlc2VudCB0aGUgbW9kZWwgb2YgdGhpcyBsaWJyYXJ5IHdpdGggYWxsIGltYWdlcyxcbiAgICogdGh1bWJzIGFuZCBzbyBvbi5cbiAgICovXG4gIEBJbnB1dCgpXG4gIGltYWdlcyE6IEludGVybmFsTGliSW1hZ2VbXTtcbiAgLyoqXG4gICAqIEJvb2xlYW4gdGhhdCBpdCBpcyB0cnVlIGlmIHRoZSBtb2RhbCBnYWxsZXJ5IGlzIHZpc2libGUuXG4gICAqIElmIHllcywgYWxzbyB0aGlzIGNvbXBvbmVudCBzaG91bGQgYmUgdmlzaWJsZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIC8vIEB0cy1pZ25vcmVcbiAgaXNPcGVuOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIE91dHB1dCB0byBlbWl0IGFuIGV2ZW50IHdoZW4gaW1hZ2VzIGFyZSBsb2FkZWQuIFRoZSBwYXlsb2FkIGNvbnRhaW5zIGFuIGBJbWFnZUxvYWRFdmVudGAuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgbG9hZEltYWdlOiBFdmVudEVtaXR0ZXI8SW1hZ2VMb2FkRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZUxvYWRFdmVudD4oKTtcbiAgLyoqXG4gICAqIE91dHB1dCB0byBlbWl0IGFueSBjaGFuZ2VzIG9mIHRoZSBjdXJyZW50IGltYWdlLiBUaGUgcGF5bG9hZCBjb250YWlucyBhbiBgSW1hZ2VNb2RhbEV2ZW50YC5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBjaGFuZ2VJbWFnZTogRXZlbnRFbWl0dGVyPEltYWdlTW9kYWxFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEltYWdlTW9kYWxFdmVudD4oKTtcbiAgLyoqXG4gICAqIE91dHB1dCB0byBlbWl0IGFuIGV2ZW50IHdoZW4gdGhlIG1vZGFsIGdhbGxlcnkgaXMgY2xvc2VkLiBUaGUgcGF5bG9hZCBjb250YWlucyBhbiBgSW1hZ2VNb2RhbEV2ZW50YC5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBjbG9zZUdhbGxlcnk6IEV2ZW50RW1pdHRlcjxJbWFnZU1vZGFsRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxJbWFnZU1vZGFsRXZlbnQ+KCk7XG5cbiAgLyoqXG4gICAqIFN1YmplY3QgdG8gcGxheSBtb2RhbC1nYWxsZXJ5LlxuICAgKi9cbiAgcHJpdmF0ZSBzdGFydCQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICAvKipcbiAgICogU3ViamVjdCB0byBzdG9wIG1vZGFsLWdhbGxlcnkuXG4gICAqL1xuICBwcml2YXRlIHN0b3AkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKipcbiAgICogRW51bSBvZiB0eXBlIGBBY3Rpb25gIHRoYXQgcmVwcmVzZW50cyBhIG5vcm1hbCBhY3Rpb24uXG4gICAqIERlY2xhcmVkIGhlcmUgdG8gYmUgdXNlZCBpbnNpZGUgdGhlIHRlbXBsYXRlLlxuICAgKi9cbiAgbm9ybWFsQWN0aW9uOiBBY3Rpb24gPSBBY3Rpb24uTk9STUFMO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYEFjY2Vzc2liaWxpdHlDb25maWdgIHRvIGluaXQgY3VzdG9tIGFjY2Vzc2liaWxpdHkgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgdGl0bGVzLCBhbHQgdGV4dHMsIGFyaWEtbGFiZWxzIGFuZCBzbyBvbi5cbiAgICovXG4gIGFjY2Vzc2liaWxpdHlDb25maWc6IEFjY2Vzc2liaWxpdHlDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgU2xpZGVDb25maWdgIHRvIGdldCBgaW5maW5pdGUgc2xpZGluZ2AuXG4gICAqL1xuICBzbGlkZUNvbmZpZzogU2xpZGVDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3QgdG8gY29uZmlndXJlIGN1cnJlbnQgaW1hZ2UgaW4gbW9kYWwtZ2FsbGVyeS5cbiAgICogRm9yIGluc3RhbmNlIHlvdSBjYW4gZGlzYWJsZSBuYXZpZ2F0aW9uIG9uIGNsaWNrIG9uIGN1cnJlbnQgaW1hZ2UgKGVuYWJsZWQgYnkgZGVmYXVsdCkuXG4gICAqL1xuICBjdXJyZW50SW1hZ2VDb25maWc6IEN1cnJlbnRJbWFnZUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBLZXlib2FyZENvbmZpZ2AgdG8gYXNzaWduIGN1c3RvbSBrZXlzIHRvIGJvdGggRVNDLCBSSUdIVCBhbmQgTEVGVCBrZXlib2FyZCdzIGFjdGlvbnMuXG4gICAqL1xuICBrZXlib2FyZENvbmZpZzogS2V5Ym9hcmRDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIGEgbW91c2UgY2xpY2sgb24gYSBidXR0b24uXG4gICAqIERlY2xhcmVkIGhlcmUgdG8gYmUgdXNlZCBpbnNpZGUgdGhlIHRlbXBsYXRlLlxuICAgKi9cbiAgY2xpY2tBY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5DTElDSztcbiAgLyoqXG4gICAqIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgYSBrZXlib2FyZCBhY3Rpb24uXG4gICAqIERlY2xhcmVkIGhlcmUgdG8gYmUgdXNlZCBpbnNpZGUgdGhlIHRlbXBsYXRlLlxuICAgKi9cbiAga2V5Ym9hcmRBY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5LRVlCT0FSRDtcbiAgLyoqXG4gICAqIEJvb2xlYW4gdGhhdCBpdCdzIHRydWUgd2hlbiB5b3UgYXJlIHdhdGNoaW5nIHRoZSBmaXJzdCBpbWFnZSAoY3VycmVudGx5IHZpc2libGUpLlxuICAgKiBGYWxzZSBieSBkZWZhdWx0XG4gICAqL1xuICBpc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgLyoqXG4gICAqIEJvb2xlYW4gdGhhdCBpdCdzIHRydWUgd2hlbiB5b3UgYXJlIHdhdGNoaW5nIHRoZSBsYXN0IGltYWdlIChjdXJyZW50bHkgdmlzaWJsZSkuXG4gICAqIEZhbHNlIGJ5IGRlZmF1bHRcbiAgICovXG4gIGlzTGFzdEltYWdlID0gZmFsc2U7XG4gIC8qKlxuICAgKiBCb29sZWFuIHRoYXQgaXQncyB0cnVlIGlmIGFuIGltYWdlIG9mIHRoZSBtb2RhbCBnYWxsZXJ5IGlzIHN0aWxsIGxvYWRpbmcuXG4gICAqIFRydWUgYnkgZGVmYXVsdFxuICAgKi9cbiAgbG9hZGluZyA9IHRydWU7XG5cbiAgLy8gdXNlIHB1YmxpYyBDaGFuZ2VEZXRlY3RvclJlZiB0byBiZSBhYmxlIHRvIGNhbGwgaXQgZnJvbSBzcGVjIGZpbGVzIHRvIHRyaWdnZXIgY2hhbmdlIGRldGVjdGlvblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogYW55LCBwcml2YXRlIG5nWm9uZTogTmdab25lLFxuICAgICAgICAgICAgICBwdWJsaWMgcmVmOiBDaGFuZ2VEZXRlY3RvclJlZiwgcHJpdmF0ZSBjb25maWdTZXJ2aWNlOiBDb25maWdTZXJ2aWNlKSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0ZW5lciB0byBzdG9wIHRoZSBnYWxsZXJ5IHdoZW4gdGhlIG1vdXNlIHBvaW50ZXIgaXMgb3ZlciB0aGUgY3VycmVudCBpbWFnZS5cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlZW50ZXInKVxuICBvbk1vdXNlRW50ZXIoKTogdm9pZCB7XG4gICAgLy8gaWYgY2Fyb3VzZWwgZmVhdHVyZSBpcyBkaXNhYmxlLCBkb24ndCBkbyBhbnl0aGluZyBpbiBhbnkgY2FzZVxuICAgIGlmICghdGhpcy5zbGlkZUNvbmZpZyB8fCAhdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnLnBhdXNlT25Ib3Zlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnN0b3BDYXJvdXNlbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3RlbmVyIHRvIHBsYXkgdGhlIGdhbGxlcnkgd2hlbiB0aGUgbW91c2UgcG9pbnRlciBsZWF2ZSB0aGUgY3VycmVudCBpbWFnZS5cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ21vdXNlbGVhdmUnKVxuICBvbk1vdXNlTGVhdmUoKTogdm9pZCB7XG4gICAgLy8gaWYgY2Fyb3VzZWwgZmVhdHVyZSBpcyBkaXNhYmxlLCBkb24ndCBkbyBhbnl0aGluZyBpbiBhbnkgY2FzZVxuICAgIGlmICghdGhpcy5zbGlkZUNvbmZpZyB8fCAhdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnLnBhdXNlT25Ib3ZlciB8fCAhdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnLmF1dG9QbGF5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMucGxheUNhcm91c2VsKCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIMK0bmdPbkluaXTCtCB0byBpbml0IGNvbmZpZ3VyYXRpb24uXG4gICAqIFRoaXMgaXMgYW4gYW5ndWxhciBsaWZlY3ljbGUgaG9vaywgc28gaXRzIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJ5IEFuZ3VsYXIgaXRzZWxmLlxuICAgKiBJbiBwYXJ0aWN1bGFyLCBpdCdzIGNhbGxlZCBvbmx5IG9uZSB0aW1lISEhXG4gICAqL1xuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcgfHwgIWxpYkNvbmZpZy5idXR0b25zQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgYW5kIGJ1dHRvbnNDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIHRoaXMuc2xpZGVDb25maWcgPSBsaWJDb25maWcuc2xpZGVDb25maWc7XG4gICAgdGhpcy5hY2Nlc3NpYmlsaXR5Q29uZmlnID0gbGliQ29uZmlnLmFjY2Vzc2liaWxpdHlDb25maWc7XG4gICAgdGhpcy5jdXJyZW50SW1hZ2VDb25maWcgPSBsaWJDb25maWcuY3VycmVudEltYWdlQ29uZmlnO1xuICAgIHRoaXMua2V5Ym9hcmRDb25maWcgPSBsaWJDb25maWcua2V5Ym9hcmRDb25maWc7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIMK0bmdPbkNoYW5nZXPCtCB0byB1cGRhdGUgYGxvYWRpbmdgIHN0YXR1cyBhbmQgZW1pdCBldmVudHMuXG4gICAqIElmIHRoZSBnYWxsZXJ5IGlzIG9wZW4sIHRoZW4gaXQgd2lsbCBhbHNvIG1hbmFnZSBib3VuZGFyeSBhcnJvd3MgYW5kIHNsaWRpbmcuXG4gICAqIFRoaXMgaXMgYW4gYW5ndWxhciBsaWZlY3ljbGUgaG9vaywgc28gaXRzIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJ5IEFuZ3VsYXIgaXRzZWxmLlxuICAgKiBJbiBwYXJ0aWN1bGFyLCBpdCdzIGNhbGxlZCB3aGVuIGFueSBkYXRhLWJvdW5kIHByb3BlcnR5IG9mIGEgZGlyZWN0aXZlIGNoYW5nZXMhISFcbiAgICovXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCBsaWJDb25maWc6IExpYkNvbmZpZyB8IHVuZGVmaW5lZCA9IHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWcodGhpcy5pZCk7XG4gICAgaWYgKCFsaWJDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGxpYkNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgaW1hZ2VzOiBTaW1wbGVDaGFuZ2UgPSBjaGFuZ2VzLmltYWdlcztcbiAgICBjb25zdCBjdXJyZW50SW1hZ2U6IFNpbXBsZUNoYW5nZSA9IGNoYW5nZXMuY3VycmVudEltYWdlO1xuXG4gICAgaWYgKGN1cnJlbnRJbWFnZSAmJiBjdXJyZW50SW1hZ2UucHJldmlvdXNWYWx1ZSAhPT0gY3VycmVudEltYWdlLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgdGhpcy51cGRhdGVJbmRleGVzKCk7XG4gICAgfSBlbHNlIGlmIChpbWFnZXMgJiYgaW1hZ2VzLnByZXZpb3VzVmFsdWUgIT09IGltYWdlcy5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMudXBkYXRlSW5kZXhlcygpO1xuICAgIH1cblxuICAgIGNvbnN0IHNsaWRlQ29uZmlnOiBTaW1wbGVDaGFuZ2UgPSBjaGFuZ2VzLnNsaWRlQ29uZmlnO1xuICAgIGlmIChzbGlkZUNvbmZpZyAmJiBzbGlkZUNvbmZpZy5wcmV2aW91c1ZhbHVlICE9PSBzbGlkZUNvbmZpZy5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMuc2xpZGVDb25maWcgPSBsaWJDb25maWcuc2xpZGVDb25maWc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgaXMgYW4gYW5ndWxhciBsaWZlY3ljbGUgaG9vaywgc28gaXRzIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJ5IEFuZ3VsYXIgaXRzZWxmLlxuICAgKi9cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIC8vIGludGVydmFsIGRvZXNuJ3QgcGxheSB3ZWxsIHdpdGggU1NSIGFuZCBwcm90cmFjdG9yLFxuICAgIC8vIHNvIHdlIHNob3VsZCBydW4gaXQgaW4gdGhlIGJyb3dzZXIgYW5kIG91dHNpZGUgQW5ndWxhclxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICAgIHRoaXMuc3RhcnQkXG4gICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICBtYXAoKCkgPT4gdGhpcy5zbGlkZUNvbmZpZyAmJiB0aGlzLnNsaWRlQ29uZmlnLnBsYXlDb25maWcgJiYgdGhpcy5zbGlkZUNvbmZpZy5wbGF5Q29uZmlnLmF1dG9QbGF5ICYmIHRoaXMuc2xpZGVDb25maWcucGxheUNvbmZpZy5pbnRlcnZhbCksXG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gICAgICAgICAgICBmaWx0ZXIoKGludGVydmFsOiBhbnkpID0+IGludGVydmFsID4gMCksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoaW50ZXJ2YWwgPT4gdGltZXIoaW50ZXJ2YWwpLnBpcGUodGFrZVVudGlsKHRoaXMuc3RvcCQpKSlcbiAgICAgICAgICApXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PlxuICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzTGFzdEltYWdlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZXh0SW1hZ2UoQWN0aW9uLkFVVE9QTEFZKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB0aGlzLnJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGhhbmRsZSBrZXlwcmVzcyBiYXNlZCBvbiB0aGUgYGtleWJvYXJkQ29uZmlnYCBpbnB1dC4gSXQgZ2V0cyB0aGUgY29kZSBvZlxuICAgKiB0aGUga2V5IHRoYXQgdHJpZ2dlcmVkIHRoZSBrZXlwcmVzcyBldmVudCB0byBuYXZpZ2F0ZSBiZXR3ZWVuIGltYWdlcyBvciB0byBjbG9zZSB0aGUgbW9kYWwgZ2FsbGVyeS5cbiAgICogQHBhcmFtIGNvZGUgc3RyaW5nIG9mIHRoZSBrZXkgdGhhdCB0cmlnZ2VyZWQgdGhlIGtleXByZXNzIGV2ZW50XG4gICAqL1xuICBvbktleVByZXNzKGNvZGU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGVzYzogc3RyaW5nID0gdGhpcy5rZXlib2FyZENvbmZpZyAmJiB0aGlzLmtleWJvYXJkQ29uZmlnLmVzYyA/IHRoaXMua2V5Ym9hcmRDb25maWcuZXNjIDogS2V5Ym9hcmQuRVNDO1xuICAgIGNvbnN0IHJpZ2h0OiBzdHJpbmcgPSB0aGlzLmtleWJvYXJkQ29uZmlnICYmIHRoaXMua2V5Ym9hcmRDb25maWcucmlnaHQgPyB0aGlzLmtleWJvYXJkQ29uZmlnLnJpZ2h0IDogS2V5Ym9hcmQuUklHSFRfQVJST1c7XG4gICAgY29uc3QgbGVmdDogc3RyaW5nID0gdGhpcy5rZXlib2FyZENvbmZpZyAmJiB0aGlzLmtleWJvYXJkQ29uZmlnLmxlZnQgPyB0aGlzLmtleWJvYXJkQ29uZmlnLmxlZnQgOiBLZXlib2FyZC5MRUZUX0FSUk9XO1xuXG4gICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICBjYXNlIGVzYzpcbiAgICAgICAgdGhpcy5jbG9zZUdhbGxlcnkuZW1pdChuZXcgSW1hZ2VNb2RhbEV2ZW50KHRoaXMuaWQsIEFjdGlvbi5LRVlCT0FSRCwgdHJ1ZSkpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgcmlnaHQ6XG4gICAgICAgIHRoaXMubmV4dEltYWdlKEFjdGlvbi5LRVlCT0FSRCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBsZWZ0OlxuICAgICAgICB0aGlzLnByZXZJbWFnZShBY3Rpb24uS0VZQk9BUkQpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdldCB0aGUgaW1hZ2UgZGVzY3JpcHRpb24gYmFzZWQgb24gaW5wdXQgcGFyYW1zLlxuICAgKiBJZiB5b3UgcHJvdmlkZSBhIGZ1bGwgZGVzY3JpcHRpb24gdGhpcyB3aWxsIGJlIHRoZSB2aXNpYmxlIGRlc2NyaXB0aW9uLCBvdGhlcndpc2UsXG4gICAqIGl0IHdpbGwgYmUgYnVpbHQgdXNpbmcgdGhlIGBEZXNjcmlwdGlvbmAgb2JqZWN0LCBjb25jYXRlbmF0aW5nIGl0cyBmaWVsZHMuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgaXRzIGRlc2NyaXB0aW9uLiBJZiBub3QgcHJvdmlkZWQgaXQgd2lsbCBiZSB0aGUgY3VycmVudCBpbWFnZVxuICAgKiBAcmV0dXJucyBTdHJpbmcgZGVzY3JpcHRpb24gb2YgdGhlIGltYWdlIChvciB0aGUgY3VycmVudCBpbWFnZSBpZiBub3QgcHJvdmlkZWQpXG4gICAqIEB0aHJvd3MgYW4gRXJyb3IgaWYgZGVzY3JpcHRpb24gaXNuJ3QgYXZhaWxhYmxlXG4gICAqL1xuICBnZXREZXNjcmlwdGlvblRvRGlzcGxheShpbWFnZTogSW1hZ2UgPSB0aGlzLmN1cnJlbnRJbWFnZSk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRJbWFnZUNvbmZpZyB8fCAhdGhpcy5jdXJyZW50SW1hZ2VDb25maWcuZGVzY3JpcHRpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRGVzY3JpcHRpb24gaW5wdXQgbXVzdCBiZSBhIHZhbGlkIG9iamVjdCBpbXBsZW1lbnRpbmcgdGhlIERlc2NyaXB0aW9uIGludGVyZmFjZScpO1xuICAgIH1cblxuICAgIGNvbnN0IGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuID0gIWltYWdlLm1vZGFsIHx8ICFpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiB8fCBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiA9PT0gJyc7XG5cbiAgICBzd2l0Y2ggKHRoaXMuY3VycmVudEltYWdlQ29uZmlnLmRlc2NyaXB0aW9uLnN0cmF0ZWd5KSB7XG4gICAgICBjYXNlIERlc2NyaXB0aW9uU3RyYXRlZ3kuSElERV9JRl9FTVBUWTpcbiAgICAgICAgcmV0dXJuIGltYWdlV2l0aG91dERlc2NyaXB0aW9uID8gJycgOiBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiArICcnO1xuICAgICAgY2FzZSBEZXNjcmlwdGlvblN0cmF0ZWd5LkFMV0FZU19ISURERU46XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIC8vIC0tLS0tLS0tLS0tIERlc2NyaXB0aW9uU3RyYXRlZ3kuQUxXQVlTX1ZJU0lCTEUgLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRUZXh0RGVzY3JpcHRpb24oaW1hZ2UsIGltYWdlV2l0aG91dERlc2NyaXB0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdldCBgYWx0IGF0dHJpYnV0ZWAuXG4gICAqIGBhbHRgIHNwZWNpZmllcyBhbiBhbHRlcm5hdGUgdGV4dCBmb3IgYW4gaW1hZ2UsIGlmIHRoZSBpbWFnZSBjYW5ub3QgYmUgZGlzcGxheWVkLlxuICAgKiBAcGFyYW0gSW1hZ2UgaW1hZ2UgdG8gZ2V0IGl0cyBhbHQgZGVzY3JpcHRpb24uIElmIG5vdCBwcm92aWRlZCBpdCB3aWxsIGJlIHRoZSBjdXJyZW50IGltYWdlXG4gICAqIEByZXR1cm5zIFN0cmluZyBhbHQgZGVzY3JpcHRpb24gb2YgdGhlIGltYWdlIChvciB0aGUgY3VycmVudCBpbWFnZSBpZiBub3QgcHJvdmlkZWQpXG4gICAqL1xuICBnZXRBbHREZXNjcmlwdGlvbkJ5SW1hZ2UoaW1hZ2U6IEltYWdlID0gdGhpcy5jdXJyZW50SW1hZ2UpOiBzdHJpbmcge1xuICAgIGlmICghaW1hZ2UpIHtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgcmV0dXJuIGltYWdlLm1vZGFsICYmIGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uID8gaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gOiBgSW1hZ2UgJHtnZXRJbmRleChpbWFnZSwgdGhpcy5pbWFnZXMpICsgMX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnZXQgdGhlIHRpdGxlIGF0dHJpYnV0ZXMgYmFzZWQgb24gZGVzY3JpcHRpb25zLlxuICAgKiBUaGlzIGlzIHVzZWZ1bCB0byBwcmV2ZW50IGFjY2Vzc2liaWxpdHkgaXNzdWVzLCBiZWNhdXNlIGlmIERlc2NyaXB0aW9uU3RyYXRlZ3kgaXMgQUxXQVlTX0hJRERFTixcbiAgICogaXQgcHJldmVudHMgYW4gZW1wdHkgc3RyaW5nIGFzIHRpdGxlLlxuICAgKiBAcGFyYW0gSW1hZ2UgaW1hZ2UgdG8gZ2V0IGl0cyBkZXNjcmlwdGlvbi4gSWYgbm90IHByb3ZpZGVkIGl0IHdpbGwgYmUgdGhlIGN1cnJlbnQgaW1hZ2VcbiAgICogQHJldHVybnMgU3RyaW5nIHRpdGxlIG9mIHRoZSBpbWFnZSBiYXNlZCBvbiBkZXNjcmlwdGlvbnNcbiAgICogQHRocm93cyBhbiBFcnJvciBpZiBkZXNjcmlwdGlvbiBpc24ndCBhdmFpbGFibGVcbiAgICovXG4gIGdldFRpdGxlVG9EaXNwbGF5KGltYWdlOiBJbWFnZSA9IHRoaXMuY3VycmVudEltYWdlKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudEltYWdlQ29uZmlnIHx8ICF0aGlzLmN1cnJlbnRJbWFnZUNvbmZpZy5kZXNjcmlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEZXNjcmlwdGlvbiBpbnB1dCBtdXN0IGJlIGEgdmFsaWQgb2JqZWN0IGltcGxlbWVudGluZyB0aGUgRGVzY3JpcHRpb24gaW50ZXJmYWNlJyk7XG4gICAgfVxuICAgIGNvbnN0IGltYWdlV2l0aG91dERlc2NyaXB0aW9uOiBib29sZWFuID0gIWltYWdlLm1vZGFsIHx8ICFpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiB8fCBpbWFnZS5tb2RhbC5kZXNjcmlwdGlvbiA9PT0gJyc7XG4gICAgY29uc3QgZGVzY3JpcHRpb246IHN0cmluZyA9IHRoaXMuYnVpbGRUZXh0RGVzY3JpcHRpb24oaW1hZ2UsIGltYWdlV2l0aG91dERlc2NyaXB0aW9uKTtcbiAgICByZXR1cm4gZGVzY3JpcHRpb247XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdldCB0aGUgbGVmdCBzaWRlIHByZXZpZXcgaW1hZ2UuXG4gICAqIEByZXR1cm5zIEltYWdlIHRoZSBpbWFnZSB0byBzaG93IGFzIHNpemUgcHJldmlldyBvbiB0aGUgbGVmdFxuICAgKi9cbiAgZ2V0TGVmdFByZXZpZXdJbWFnZSgpOiBJbWFnZSB7XG4gICAgaWYgKCF0aGlzLnNsaWRlQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBzbGlkZUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgY3VycmVudEluZGV4OiBudW1iZXIgPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgIGlmIChjdXJyZW50SW5kZXggPT09IDAgJiYgdGhpcy5zbGlkZUNvbmZpZy5pbmZpbml0ZSkge1xuICAgICAgLy8gdGhlIGN1cnJlbnQgaW1hZ2UgaXMgdGhlIGZpcnN0IG9uZSxcbiAgICAgIC8vIHNvIHRoZSBwcmV2aW91cyBvbmUgaXMgdGhlIGxhc3QgaW1hZ2VcbiAgICAgIC8vIGJlY2F1c2UgaW5maW5pdGUgaXMgdHJ1ZVxuICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzW3RoaXMuaW1hZ2VzLmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgICB0aGlzLmhhbmRsZUJvdW5kYXJpZXMoY3VycmVudEluZGV4KTtcbiAgICByZXR1cm4gdGhpcy5pbWFnZXNbTWF0aC5tYXgoY3VycmVudEluZGV4IC0gMSwgMCldO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnZXQgdGhlIHJpZ2h0IHNpZGUgcHJldmlldyBpbWFnZS5cbiAgICogQHJldHVybnMgSW1hZ2UgdGhlIGltYWdlIHRvIHNob3cgYXMgc2l6ZSBwcmV2aWV3IG9uIHRoZSByaWdodFxuICAgKi9cbiAgZ2V0UmlnaHRQcmV2aWV3SW1hZ2UoKTogSW1hZ2Uge1xuICAgIGlmICghdGhpcy5zbGlkZUNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gc2xpZGVDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGN1cnJlbnRJbmRleDogbnVtYmVyID0gZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICBpZiAoY3VycmVudEluZGV4ID09PSB0aGlzLmltYWdlcy5sZW5ndGggLSAxICYmIHRoaXMuc2xpZGVDb25maWcuaW5maW5pdGUpIHtcbiAgICAgIC8vIHRoZSBjdXJyZW50IGltYWdlIGlzIHRoZSBsYXN0IG9uZSxcbiAgICAgIC8vIHNvIHRoZSBuZXh0IG9uZSBpcyB0aGUgZmlyc3QgaW1hZ2VcbiAgICAgIC8vIGJlY2F1c2UgaW5maW5pdGUgaXMgdHJ1ZVxuICAgICAgcmV0dXJuIHRoaXMuaW1hZ2VzWzBdO1xuICAgIH1cbiAgICB0aGlzLmhhbmRsZUJvdW5kYXJpZXMoY3VycmVudEluZGV4KTtcbiAgICByZXR1cm4gdGhpcy5pbWFnZXNbTWF0aC5taW4oY3VycmVudEluZGV4ICsgMSwgdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSldO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgYnkgZXZlbnRzIGZyb20gYm90aCBrZXlib2FyZCBhbmQgbW91c2Ugb24gYW4gaW1hZ2UuXG4gICAqIFRoaXMgd2lsbCBpbnZva2UgdGhlIG5leHRJbWFnZSBtZXRob2QuXG4gICAqIEBwYXJhbSBLZXlib2FyZEV2ZW50IHwgTW91c2VFdmVudCBldmVudCBwYXlsb2FkXG4gICAqIEBwYXJhbSBBY3Rpb24gYWN0aW9uIHRoYXQgdHJpZ2dlcmVkIHRoZSBldmVudCBvciBgQWN0aW9uLk5PUk1BTGAgaWYgbm90IHByb3ZpZGVkXG4gICAqL1xuICBvbkltYWdlRXZlbnQoZXZlbnQ6IEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50LCBhY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5OT1JNQUwpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudEltYWdlQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBjdXJyZW50SW1hZ2VDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIC8vIGNoZWNrIGlmIHRyaWdnZXJlZCBieSBhIG1vdXNlIGNsaWNrXG4gICAgLy8gSWYgeWVzLCBJdCBzaG91bGQgYmxvY2sgbmF2aWdhdGlvbiB3aGVuIG5hdmlnYXRlT25DbGljayBpcyBmYWxzZVxuICAgIGlmIChhY3Rpb24gPT09IEFjdGlvbi5DTElDSyAmJiAhdGhpcy5jdXJyZW50SW1hZ2VDb25maWcubmF2aWdhdGVPbkNsaWNrKSB7XG4gICAgICAvLyBhIHVzZXIgaGFzIHJlcXVlc3RlZCB0byBibG9jayBuYXZpZ2F0aW9uIHZpYSBjb25maWdDdXJyZW50SW1hZ2UubmF2aWdhdGVPbkNsaWNrIHByb3BlcnR5XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcmVzdWx0OiBudW1iZXIgPSBzdXBlci5oYW5kbGVJbWFnZUV2ZW50KGV2ZW50KTtcbiAgICBpZiAocmVzdWx0ID09PSBORVhUKSB7XG4gICAgICB0aGlzLm5leHRJbWFnZShhY3Rpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IGV2ZW50cyBmcm9tIGJvdGgga2V5Ym9hcmQgYW5kIG1vdXNlIG9uIGEgbmF2aWdhdGlvbiBhcnJvdy5cbiAgICogQHBhcmFtIHN0cmluZyBkaXJlY3Rpb24gb2YgdGhlIG5hdmlnYXRpb24gdGhhdCBjYW4gYmUgZWl0aGVyICduZXh0JyBvciAncHJldidcbiAgICogQHBhcmFtIEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICogQHBhcmFtIEFjdGlvbiBhY3Rpb24gdGhhdCB0cmlnZ2VyZWQgdGhlIGV2ZW50IG9yIGBBY3Rpb24uTk9STUFMYCBpZiBub3QgcHJvdmlkZWRcbiAgICogQHBhcmFtIGJvb2xlYW4gZGlzYWJsZSB0byBkaXNhYmxlIG5hdmlnYXRpb25cbiAgICovXG4gIG9uTmF2aWdhdGlvbkV2ZW50KGRpcmVjdGlvbjogc3RyaW5nLCBldmVudDogS2V5Ym9hcmRFdmVudCB8IE1vdXNlRXZlbnQsIGFjdGlvbjogQWN0aW9uID0gQWN0aW9uLk5PUk1BTCwgZGlzYWJsZTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgaWYgKGRpc2FibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcmVzdWx0OiBudW1iZXIgPSBzdXBlci5oYW5kbGVOYXZpZ2F0aW9uRXZlbnQoZGlyZWN0aW9uLCBldmVudCk7XG4gICAgaWYgKHJlc3VsdCA9PT0gTkVYVCkge1xuICAgICAgdGhpcy5uZXh0SW1hZ2UoYWN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gUFJFVikge1xuICAgICAgdGhpcy5wcmV2SW1hZ2UoYWN0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdvIGJhY2sgdG8gdGhlIHByZXZpb3VzIGltYWdlLlxuICAgKiBAcGFyYW0gYWN0aW9uIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgdGhlIHNvdXJjZVxuICAgKiAgYWN0aW9uIHRoYXQgbW92ZWQgYmFjayB0byB0aGUgcHJldmlvdXMgaW1hZ2UuIGBBY3Rpb24uTk9STUFMYCBieSBkZWZhdWx0LlxuICAgKi9cbiAgcHJldkltYWdlKGFjdGlvbjogQWN0aW9uID0gQWN0aW9uLk5PUk1BTCk6IHZvaWQge1xuICAgIC8vIGNoZWNrIGlmIHByZXZJbWFnZSBzaG91bGQgYmUgYmxvY2tlZFxuICAgIGlmICh0aGlzLmlzUHJldmVudFNsaWRpbmcoMCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgcHJldkltYWdlOiBJbnRlcm5hbExpYkltYWdlID0gdGhpcy5nZXRQcmV2SW1hZ2UoKTtcbiAgICB0aGlzLmxvYWRpbmcgPSAhcHJldkltYWdlLnByZXZpb3VzbHlMb2FkZWQ7XG4gICAgdGhpcy5jaGFuZ2VJbWFnZS5lbWl0KG5ldyBJbWFnZU1vZGFsRXZlbnQodGhpcy5pZCwgYWN0aW9uLCBnZXRJbmRleChwcmV2SW1hZ2UsIHRoaXMuaW1hZ2VzKSkpO1xuXG4gICAgdGhpcy5zdGFydCQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBnbyBiYWNrIHRvIHRoZSBwcmV2aW91cyBpbWFnZS5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgYEFjdGlvbmAgdGhhdCByZXByZXNlbnRzIHRoZSBzb3VyY2VcbiAgICogIGFjdGlvbiB0aGF0IG1vdmVkIHRvIHRoZSBuZXh0IGltYWdlLiBgQWN0aW9uLk5PUk1BTGAgYnkgZGVmYXVsdC5cbiAgICovXG4gIG5leHRJbWFnZShhY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5OT1JNQUwpOiB2b2lkIHtcbiAgICAvLyBjaGVjayBpZiBuZXh0SW1hZ2Ugc2hvdWxkIGJlIGJsb2NrZWRcbiAgICBpZiAodGhpcy5pc1ByZXZlbnRTbGlkaW5nKHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IG5leHRJbWFnZTogSW50ZXJuYWxMaWJJbWFnZSA9IHRoaXMuZ2V0TmV4dEltYWdlKCk7XG4gICAgdGhpcy5sb2FkaW5nID0gIW5leHRJbWFnZS5wcmV2aW91c2x5TG9hZGVkO1xuICAgIHRoaXMuY2hhbmdlSW1hZ2UuZW1pdChuZXcgSW1hZ2VNb2RhbEV2ZW50KHRoaXMuaWQsIGFjdGlvbiwgZ2V0SW5kZXgobmV4dEltYWdlLCB0aGlzLmltYWdlcykpKTtcblxuICAgIHRoaXMuc3RhcnQkLm5leHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZW1pdCBhbiBldmVudCBhcyBsb2FkSW1hZ2Ugb3V0cHV0IHRvIHNheSB0aGF0IHRoZSByZXF1ZXN0ZWQgaW1hZ2UgaWYgbG9hZGVkLlxuICAgKiBUaGlzIG1ldGhvZCBpcyBpbnZva2VkIGJ5IHRoZSBqYXZhc2NyaXB0J3MgJ2xvYWQnIGV2ZW50IG9uIGFuIGltZyB0YWcuXG4gICAqIEBwYXJhbSBFdmVudCBldmVudCB0aGF0IHRyaWdnZXJlZCB0aGUgbG9hZFxuICAgKi9cbiAgb25JbWFnZUxvYWQoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgbG9hZEltYWdlRGF0YTogSW1hZ2VMb2FkRXZlbnQgPSB7XG4gICAgICBzdGF0dXM6IHRydWUsXG4gICAgICBpbmRleDogZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKSxcbiAgICAgIGlkOiB0aGlzLmN1cnJlbnRJbWFnZS5pZFxuICAgIH07XG5cbiAgICB0aGlzLmxvYWRJbWFnZS5lbWl0KGxvYWRJbWFnZURhdGEpO1xuXG4gICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHVzZWQgYnkgU3dpcGVEaXJlY3RpdmUgdG8gc3VwcG9ydCB0b3VjaCBnZXN0dXJlcyAoeW91IGNhbiBhbHNvIGludmVydCB0aGUgc3dpcGUgZGlyZWN0aW9uIHdpdGggY29uZmlnQ3VycmVudEltYWdlLmludmVydFN3aXBlKS5cbiAgICogQHBhcmFtIGFjdGlvbiBTdHJpbmcgdGhhdCByZXByZXNlbnQgdGhlIGRpcmVjdGlvbiBvZiB0aGUgc3dpcGUgYWN0aW9uLiAnc3dpcGVyaWdodCcgYnkgZGVmYXVsdC5cbiAgICovXG4gIHN3aXBlKGFjdGlvbiA9ICdzd2lwZXJpZ2h0Jyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2VDb25maWcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW50ZXJuYWwgbGlicmFyeSBlcnJvciAtIGN1cnJlbnRJbWFnZUNvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgIGNhc2UgJ3N3aXBlcmlnaHQnOlxuICAgICAgICBpZiAodGhpcy5jdXJyZW50SW1hZ2VDb25maWcuaW52ZXJ0U3dpcGUpIHtcbiAgICAgICAgICB0aGlzLnByZXZJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubmV4dEltYWdlKEFjdGlvbi5TV0lQRSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzd2lwZWxlZnQnOlxuICAgICAgICBpZiAodGhpcy5jdXJyZW50SW1hZ2VDb25maWcuaW52ZXJ0U3dpcGUpIHtcbiAgICAgICAgICB0aGlzLm5leHRJbWFnZShBY3Rpb24uU1dJUEUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMucHJldkltYWdlKEFjdGlvbi5TV0lQRSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBjYXNlIHRoaXMuU1dJUEVfQUNUSU9OLlVQOlxuICAgICAgLy8gICBicmVhaztcbiAgICAgIC8vIGNhc2UgdGhpcy5TV0lQRV9BQ1RJT04uRE9XTjpcbiAgICAgIC8vICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGluIGBtb2RhbC1nYWxsZXJ5LmNvbXBvbmVudGAgdG8gZ2V0IHRoZSBpbmRleCBvZiBhbiBpbWFnZSB0byBkZWxldGUuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBnZXQgdGhlIGluZGV4LCBvciB0aGUgdmlzaWJsZSBpbWFnZSwgaWYgbm90IHBhc3NlZFxuICAgKiBAcmV0dXJucyBudW1iZXIgdGhlIGluZGV4IG9mIHRoZSBpbWFnZVxuICAgKi9cbiAgZ2V0SW5kZXhUb0RlbGV0ZShpbWFnZTogSW1hZ2UgPSB0aGlzLmN1cnJlbnRJbWFnZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIGdldEluZGV4KGltYWdlLCB0aGlzLmltYWdlcyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIHBsYXkgbW9kYWwgZ2FsbGVyeS5cbiAgICovXG4gIHBsYXlDYXJvdXNlbCgpOiB2b2lkIHtcbiAgICB0aGlzLnN0YXJ0JC5uZXh0KCk7XG4gIH1cblxuICAvKipcbiAgICogU3RvcHMgbW9kYWwgZ2FsbGVyeSBmcm9tIGN5Y2xpbmcgdGhyb3VnaCBpdGVtcy5cbiAgICovXG4gIHN0b3BDYXJvdXNlbCgpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3AkLm5leHQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gY2xlYW51cCByZXNvdXJjZXMuIEluIGZhY3QsIHRoaXMgd2lsbCBzdG9wIHRoZSBtb2RhbCBnYWxsZXJ5LlxuICAgKiBUaGlzIGlzIGFuIGFuZ3VsYXIgbGlmZWN5Y2xlIGhvb2sgdGhhdCBpcyBjYWxsZWQgd2hlbiB0aGlzIGNvbXBvbmVudCBpcyBkZXN0cm95ZWQuXG4gICAqL1xuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3BDYXJvdXNlbCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIHVwZGF0ZSBib3RoIGBpc0ZpcnN0SW1hZ2VgIGFuZCBgaXNMYXN0SW1hZ2VgIGJhc2VkIG9uXG4gICAqIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBpbWFnZS5cbiAgICogQHBhcmFtIG51bWJlciBjdXJyZW50SW5kZXggaXMgdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IGltYWdlXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZUJvdW5kYXJpZXMoY3VycmVudEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pbWFnZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICB0aGlzLmlzTGFzdEltYWdlID0gdHJ1ZTtcbiAgICAgIHRoaXMucmVmLm1hcmtGb3JDaGVjaygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuc2xpZGVDb25maWcgfHwgdGhpcy5zbGlkZUNvbmZpZy5pbmZpbml0ZSA9PT0gdHJ1ZSkge1xuICAgICAgLy8gaW5maW5pdGUgc2xpZGluZyBlbmFibGVkXG4gICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGV4ZWN1dGUgdGhpcyBvbmx5IGlmIGluZmluaXRlIHNsaWRpbmcgaXMgZGlzYWJsZWRcbiAgICAgIHN3aXRjaCAoY3VycmVudEluZGV4KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IHRydWU7XG4gICAgICAgICAgdGhpcy5pc0xhc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMucmVmLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDE6XG4gICAgICAgICAgdGhpcy5pc0ZpcnN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLmlzTGFzdEltYWdlID0gdHJ1ZTtcbiAgICAgICAgICB0aGlzLnJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aGlzLmlzRmlyc3RJbWFnZSA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuaXNMYXN0SW1hZ2UgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gY2hlY2sgaWYgbmV4dC9wcmV2IGFjdGlvbnMgc2hvdWxkIGJlIGJsb2NrZWQuXG4gICAqIEl0IGNoZWNrcyBpZiBzbGlkZUNvbmZpZy5pbmZpbml0ZSA9PT0gZmFsc2UgYW5kIGlmIHRoZSBpbWFnZSBpbmRleCBpcyBlcXVhbHMgdG8gdGhlIGlucHV0IHBhcmFtZXRlci5cbiAgICogSWYgeWVzLCBpdCByZXR1cm5zIHRydWUgdG8gc2F5IHRoYXQgc2xpZGluZyBzaG91bGQgYmUgYmxvY2tlZCwgb3RoZXJ3aXNlIG5vdC5cbiAgICogQHBhcmFtIG51bWJlciBib3VuZGFyeUluZGV4IHRoYXQgY291bGQgYmUgZWl0aGVyIHRoZSBiZWdpbm5pbmcgaW5kZXggKDApIG9yIHRoZSBsYXN0IGluZGV4XG4gICAqICBvZiBpbWFnZXMgKHRoaXMuaW1hZ2VzLmxlbmd0aCAtIDEpLlxuICAgKiBAcmV0dXJucyBib29sZWFuIHRydWUgaWYgc2xpZGVDb25maWcuaW5maW5pdGUgPT09IGZhbHNlIGFuZCB0aGUgY3VycmVudCBpbmRleCBpc1xuICAgKiAgZWl0aGVyIHRoZSBmaXJzdCBvciB0aGUgbGFzdCBvbmUuXG4gICAqL1xuICBwcml2YXRlIGlzUHJldmVudFNsaWRpbmcoYm91bmRhcnlJbmRleDogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5zbGlkZUNvbmZpZyAmJiB0aGlzLnNsaWRlQ29uZmlnLmluZmluaXRlID09PSBmYWxzZSAmJiBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpID09PSBib3VuZGFyeUluZGV4O1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGdldCB0aGUgbmV4dCBpbmRleC5cbiAgICogVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBhdCB0aGUgZW5kLCB3aGVuIHlvdSBjYWxsIG5leHQgYWdhaW4sIHlvdSdsbCBnbyB0byB0aGUgZmlyc3QgaW1hZ2UuXG4gICAqIFRoYXQgaGFwcGVucyBiZWNhdXNlIGFsbCBtb2RhbCBpbWFnZXMgYXJlIHNob3duIGxpa2UgaW4gYSBjaXJjbGUuXG4gICAqL1xuICBwcml2YXRlIGdldE5leHRJbWFnZSgpOiBJbnRlcm5hbExpYkltYWdlIHtcbiAgICBjb25zdCBjdXJyZW50SW5kZXg6IG51bWJlciA9IGdldEluZGV4KHRoaXMuY3VycmVudEltYWdlLCB0aGlzLmltYWdlcyk7XG4gICAgbGV0IG5ld0luZGV4ID0gMDtcbiAgICBpZiAoY3VycmVudEluZGV4ID49IDAgJiYgY3VycmVudEluZGV4IDwgdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgbmV3SW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdJbmRleCA9IDA7IC8vIHN0YXJ0IGZyb20gdGhlIGZpcnN0IGluZGV4XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmltYWdlc1tuZXdJbmRleF07XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gZ2V0IHRoZSBwcmV2aW91cyBpbmRleC5cbiAgICogVGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSBhdCBpbmRleCAwLCB3aGVuIHlvdSBjYWxsIHByZXYgYWdhaW4sIHlvdSdsbCBnbyB0byB0aGUgbGFzdCBpbWFnZS5cbiAgICogVGhhdCBoYXBwZW5zIGJlY2F1c2UgYWxsIG1vZGFsIGltYWdlcyBhcmUgc2hvd24gbGlrZSBpbiBhIGNpcmNsZS5cbiAgICovXG4gIHByaXZhdGUgZ2V0UHJldkltYWdlKCk6IEludGVybmFsTGliSW1hZ2Uge1xuICAgIGNvbnN0IGN1cnJlbnRJbmRleDogbnVtYmVyID0gZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICBsZXQgbmV3SW5kZXggPSAwO1xuICAgIGlmIChjdXJyZW50SW5kZXggPiAwICYmIGN1cnJlbnRJbmRleCA8PSB0aGlzLmltYWdlcy5sZW5ndGggLSAxKSB7XG4gICAgICBuZXdJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld0luZGV4ID0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMTsgLy8gc3RhcnQgZnJvbSB0aGUgbGFzdCBpbmRleFxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbWFnZXNbbmV3SW5kZXhdO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGJ1aWxkIGEgdGV4dCBkZXNjcmlwdGlvbi5cbiAgICogVGhpcyBpcyB1c2VkIGFsc28gdG8gY3JlYXRlIHRpdGxlcy5cbiAgICogQHBhcmFtIEltYWdlIGltYWdlIHRvIGdldCBpdHMgZGVzY3JpcHRpb24uIElmIG5vdCBwcm92aWRlZCBpdCB3aWxsIGJlIHRoZSBjdXJyZW50IGltYWdlLlxuICAgKiBAcGFyYW0gYm9vbGVhbiBpbWFnZVdpdGhvdXREZXNjcmlwdGlvbiBpcyBhIGJvb2xlYW4gdGhhdCBpdCdzIHRydWUgaWYgdGhlIGltYWdlIGhhc24ndCBhICdtb2RhbCcgZGVzY3JpcHRpb24uXG4gICAqIEByZXR1cm5zIFN0cmluZyBkZXNjcmlwdGlvbiBidWlsdCBjb25jYXRlbmF0aW5nIGltYWdlIGZpZWxkcyB3aXRoIGEgc3BlY2lmaWMgbG9naWMuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkVGV4dERlc2NyaXB0aW9uKGltYWdlOiBJbWFnZSwgaW1hZ2VXaXRob3V0RGVzY3JpcHRpb246IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5jdXJyZW50SW1hZ2VDb25maWcgfHwgIXRoaXMuY3VycmVudEltYWdlQ29uZmlnLmRlc2NyaXB0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Rlc2NyaXB0aW9uIGlucHV0IG11c3QgYmUgYSB2YWxpZCBvYmplY3QgaW1wbGVtZW50aW5nIHRoZSBEZXNjcmlwdGlvbiBpbnRlcmZhY2UnKTtcbiAgICB9XG5cbiAgICAvLyBJZiBjdXN0b21GdWxsRGVzY3JpcHRpb24gdXNlIGl0LCBvdGhlcndpc2UgcHJvY2VlZCB0byBidWlsZCBhIGRlc2NyaXB0aW9uXG4gICAgaWYgKHRoaXMuY3VycmVudEltYWdlQ29uZmlnLmRlc2NyaXB0aW9uLmN1c3RvbUZ1bGxEZXNjcmlwdGlvbiAmJiB0aGlzLmN1cnJlbnRJbWFnZUNvbmZpZy5kZXNjcmlwdGlvbi5jdXN0b21GdWxsRGVzY3JpcHRpb24gIT09ICcnKSB7XG4gICAgICByZXR1cm4gdGhpcy5jdXJyZW50SW1hZ2VDb25maWcuZGVzY3JpcHRpb24uY3VzdG9tRnVsbERlc2NyaXB0aW9uO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRJbmRleDogbnVtYmVyID0gZ2V0SW5kZXgoaW1hZ2UsIHRoaXMuaW1hZ2VzKTtcbiAgICAvLyBJZiB0aGUgY3VycmVudCBpbWFnZSBoYXNuJ3QgYSBkZXNjcmlwdGlvbixcbiAgICAvLyBwcmV2ZW50IHRvIHdyaXRlIHRoZSAnIC0gJyAob3IgdGhpcy5kZXNjcmlwdGlvbi5iZWZvcmVUZXh0RGVzY3JpcHRpb24pXG5cbiAgICBjb25zdCBwcmV2RGVzY3JpcHRpb246IHN0cmluZyA9IHRoaXMuY3VycmVudEltYWdlQ29uZmlnLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA/IHRoaXMuY3VycmVudEltYWdlQ29uZmlnLmRlc2NyaXB0aW9uLmltYWdlVGV4dCA6ICcnO1xuICAgIGNvbnN0IG1pZFNlcGFyYXRvcjogc3RyaW5nID0gdGhpcy5jdXJyZW50SW1hZ2VDb25maWcuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yID8gdGhpcy5jdXJyZW50SW1hZ2VDb25maWcuZGVzY3JpcHRpb24ubnVtYmVyU2VwYXJhdG9yIDogJyc7XG4gICAgY29uc3QgbWlkZGxlRGVzY3JpcHRpb246IHN0cmluZyA9IGN1cnJlbnRJbmRleCArIDEgKyBtaWRTZXBhcmF0b3IgKyB0aGlzLmltYWdlcy5sZW5ndGg7XG5cbiAgICBpZiAoaW1hZ2VXaXRob3V0RGVzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJySW1nRGVzY3JpcHRpb246IHN0cmluZyA9IGltYWdlLm1vZGFsICYmIGltYWdlLm1vZGFsLmRlc2NyaXB0aW9uID8gaW1hZ2UubW9kYWwuZGVzY3JpcHRpb24gOiAnJztcbiAgICBjb25zdCBlbmREZXNjcmlwdGlvbjogc3RyaW5nID0gdGhpcy5jdXJyZW50SW1hZ2VDb25maWcuZGVzY3JpcHRpb24uYmVmb3JlVGV4dERlc2NyaXB0aW9uICsgY3VyckltZ0Rlc2NyaXB0aW9uO1xuICAgIHJldHVybiBwcmV2RGVzY3JpcHRpb24gKyBtaWRkbGVEZXNjcmlwdGlvbiArIGVuZERlc2NyaXB0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGNhbGwgaGFuZGxlQm91bmRhcmllcyB3aGVuIG5nT25DaGFuZ2VzIGlzIGNhbGxlZC5cbiAgICovXG4gIHByaXZhdGUgdXBkYXRlSW5kZXhlcygpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICAgIGNvbnN0IGluZGV4OiBudW1iZXIgPSBnZXRJbmRleCh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuICAgICAgICB0aGlzLmhhbmRsZUJvdW5kYXJpZXMoaW5kZXgpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcignQ2Fubm90IGdldCB0aGUgY3VycmVudCBpbWFnZSBpbmRleCBpbiBjdXJyZW50LWltYWdlJyk7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG59XG4iLCI8bWFpbiBjbGFzcz1cIm1haW4taW1hZ2UtY29udGFpbmVyXCJcbiAgICAgIGtzS2V5Ym9hcmROYXZpZ2F0aW9uIFtpc09wZW5dPVwiaXNPcGVuXCIgKGtleWJvYXJkTmF2aWdhdGlvbik9XCJvbktleVByZXNzKCRldmVudClcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhY2Nlc3NpYmlsaXR5Q29uZmlnPy5tYWluQ29udGFpbmVyQXJpYUxhYmVsXCJcbiAgICAgIFt0aXRsZV09XCJhY2Nlc3NpYmlsaXR5Q29uZmlnPy5tYWluQ29udGFpbmVyVGl0bGVcIj5cblxuICA8ZGl2IGNsYXNzPVwibGVmdC1zdWItY29udGFpbmVyXCI+XG4gICAgPGEgY2xhc3M9XCJuYXYtbGVmdCB7e2lzRmlyc3RJbWFnZSA/ICduby1wb2ludGVyJyA6ICcnfX1cIlxuICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYWNjZXNzaWJpbGl0eUNvbmZpZz8ubWFpblByZXZJbWFnZUFyaWFMYWJlbFwiXG4gICAgICAgW3RhYkluZGV4XT1cImlzRmlyc3RJbWFnZSA/IC0xIDogMFwiIHJvbGU9XCJidXR0b25cIlxuICAgICAgIChjbGljayk9XCJvbk5hdmlnYXRpb25FdmVudCgnbGVmdCcsICRldmVudClcIiAoa2V5dXApPVwib25OYXZpZ2F0aW9uRXZlbnQoJ2xlZnQnLCAkZXZlbnQpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW5zaWRlIHt7aXNGaXJzdEltYWdlID8gJ2VtcHR5LWFycm93LWltYWdlJyA6ICdsZWZ0LWFycm93LWltYWdlJ319XCJcbiAgICAgICAgICAgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICAgW3RpdGxlXT1cImlzRmlyc3RJbWFnZSA/ICcnIDogYWNjZXNzaWJpbGl0eUNvbmZpZz8ubWFpblByZXZJbWFnZVRpdGxlXCI+PC9kaXY+XG4gICAgPC9hPlxuXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNob3dcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJnZXRMZWZ0UHJldmlld0ltYWdlKCkgYXMgbGVmdFByZXZpZXdcIj5cbiAgICAgICAgPGltZyAqbmdJZj1cIiFpc0ZpcnN0SW1hZ2U7IGVsc2UgZmlyc3RJbWFnZVwiXG4gICAgICAgICAgICAgY2xhc3M9XCJpbnNpZGUgY3VycmVudC1pbWFnZS1wcmV2aW91c1wiXG4gICAgICAgICAgICAgW3NyY109XCJsZWZ0UHJldmlldy5wbGFpbj8uaW1nID8gbGVmdFByZXZpZXcucGxhaW4/LmltZyA6IGxlZnRQcmV2aWV3Lm1vZGFsLmltZ1wiXG4gICAgICAgICAgICAga3NGYWxsYmFja0ltYWdlIFtmYWxsYmFja0ltZ109XCJsZWZ0UHJldmlldy5wbGFpbj8uZmFsbGJhY2tJbWcgPyBsZWZ0UHJldmlldy5wbGFpbj8uZmFsbGJhY2tJbWcgOiBsZWZ0UHJldmlldy5tb2RhbC5mYWxsYmFja0ltZ1wiXG4gICAgICAgICAgICAgW2hpZGRlbl09XCJsb2FkaW5nXCJcbiAgICAgICAgICAgICBrc1NpemUgW3NpemVDb25maWddPVwie3dpZHRoOiBzbGlkZUNvbmZpZz8uc2lkZVByZXZpZXdzPy5zaXplLndpZHRoLCBoZWlnaHQ6IHNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNpemUuaGVpZ2h0fVwiXG4gICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJsZWZ0UHJldmlldy5tb2RhbC5hcmlhTGFiZWxcIlxuICAgICAgICAgICAgIFt0aXRsZV09XCIobGVmdFByZXZpZXcubW9kYWwudGl0bGUgfHwgbGVmdFByZXZpZXcubW9kYWwudGl0bGUgPT09ICcnKSA/IGxlZnRQcmV2aWV3Lm1vZGFsLnRpdGxlIDogZ2V0RGVzY3JpcHRpb25Ub0Rpc3BsYXkobGVmdFByZXZpZXcpXCJcbiAgICAgICAgICAgICBhbHQ9XCJ7e2xlZnRQcmV2aWV3Lm1vZGFsLmFsdCA/IGxlZnRQcmV2aWV3Lm1vZGFsLmFsdCA6IGdldEFsdERlc2NyaXB0aW9uQnlJbWFnZShsZWZ0UHJldmlldyl9fVwiXG4gICAgICAgICAgICAgW3RhYkluZGV4XT1cIjBcIiByb2xlPVwiaW1nXCJcbiAgICAgICAgICAgICAoY2xpY2spPVwib25OYXZpZ2F0aW9uRXZlbnQoJ2xlZnQnLCAkZXZlbnQsIGNsaWNrQWN0aW9uKVwiIChrZXl1cCk9XCJvbk5hdmlnYXRpb25FdmVudCgnbGVmdCcsICRldmVudCwga2V5Ym9hcmRBY3Rpb24pXCIvPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2ZpcnN0SW1hZ2U+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImN1cnJlbnQtaW1hZ2UtcHJldmlvdXMgaGlkZGVuXCJcbiAgICAgICAgICAgICAgIGtzU2l6ZSBbc2l6ZUNvbmZpZ109XCJ7d2lkdGg6IHNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNpemUud2lkdGgsIGhlaWdodDogc2xpZGVDb25maWc/LnNpZGVQcmV2aWV3cz8uc2l6ZS5oZWlnaHR9XCI+PC9kaXY+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9kaXY+XG5cblxuICA8ZmlndXJlIGlkPVwiY3VycmVudC1maWd1cmVcIiBbc3R5bGUuZGlzcGxheV09XCJsb2FkaW5nID8gJ25vbmUnIDogJydcIj5cbiAgICA8aW1nIGlkPVwiY3VycmVudC1pbWFnZVwiXG4gICAgICAgICBjbGFzcz1cImluc2lkZVwiXG4gICAgICAgICBbbmdDbGFzc109XCJjdXJyZW50SW1hZ2VDb25maWc/Lm5hdmlnYXRlT25DbGljayA/ICcnIDogJ3VuY2xpY2thYmxlJ1wiXG4gICAgICAgICBbc3JjXT1cImN1cnJlbnRJbWFnZS5tb2RhbC5pbWdcIlxuICAgICAgICAga3NGYWxsYmFja0ltYWdlIFtmYWxsYmFja0ltZ109XCJjdXJyZW50SW1hZ2UubW9kYWwuZmFsbGJhY2tJbWdcIlxuICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJjdXJyZW50SW1hZ2UubW9kYWwuYXJpYUxhYmVsXCJcbiAgICAgICAgIFt0aXRsZV09XCIoY3VycmVudEltYWdlLm1vZGFsLnRpdGxlIHx8IGN1cnJlbnRJbWFnZS5tb2RhbC50aXRsZSA9PT0gJycpID8gY3VycmVudEltYWdlLm1vZGFsLnRpdGxlIDogZ2V0VGl0bGVUb0Rpc3BsYXkoKVwiXG4gICAgICAgICBhbHQ9XCJ7e2N1cnJlbnRJbWFnZS5tb2RhbC5hbHQgPyBjdXJyZW50SW1hZ2UubW9kYWwuYWx0IDogZ2V0QWx0RGVzY3JpcHRpb25CeUltYWdlKCl9fVwiXG4gICAgICAgICBbdGFiSW5kZXhdPVwiMFwiIHJvbGU9XCJpbWdcIlxuICAgICAgICAgKGxvYWQpPVwib25JbWFnZUxvYWQoJGV2ZW50KVwiXG4gICAgICAgICAoY2xpY2spPVwib25JbWFnZUV2ZW50KCRldmVudCwgY2xpY2tBY3Rpb24pXCIgKGtleXVwKT1cIm9uSW1hZ2VFdmVudCgkZXZlbnQsIGtleWJvYXJkQWN0aW9uKVwiXG4gICAgICAgICBrc1N3aXBlXG4gICAgICAgICAoc3dpcGVMZWZ0KT1cInN3aXBlKCdzd2lwZWxlZnQnKVwiXG4gICAgICAgICAoc3dpcGVSaWdodCk9XCJzd2lwZSgnc3dpcGVyaWdodCcpXCIvPlxuICAgIDxmaWdjYXB0aW9uICpuZ0lmPVwiZ2V0RGVzY3JpcHRpb25Ub0Rpc3BsYXkoKSAhPT0gJydcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiaW5zaWRlIGRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICBrc0Rlc2NyaXB0aW9uIFtkZXNjcmlwdGlvbl09XCJjdXJyZW50SW1hZ2VDb25maWc/LmRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICBbaW5uZXJIVE1MXT1cImdldERlc2NyaXB0aW9uVG9EaXNwbGF5KClcIj5cbiAgICA8L2ZpZ2NhcHRpb24+XG4gIDwvZmlndXJlPlxuXG4gIDxkaXYgY2xhc3M9XCJyaWdodC1zdWItY29udGFpbmVyXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNob3dcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJnZXRSaWdodFByZXZpZXdJbWFnZSgpIGFzIHJpZ2h0UHJldmlld1wiPlxuICAgICAgICA8aW1nICpuZ0lmPVwiIWlzTGFzdEltYWdlOyBlbHNlIGxhc3RJbWFnZVwiXG4gICAgICAgICAgICAgY2xhc3M9XCJpbnNpZGUgY3VycmVudC1pbWFnZS1uZXh0XCJcbiAgICAgICAgICAgICBbc3JjXT1cInJpZ2h0UHJldmlldy5wbGFpbj8uaW1nID8gcmlnaHRQcmV2aWV3LnBsYWluPy5pbWcgOiByaWdodFByZXZpZXcubW9kYWwuaW1nXCJcbiAgICAgICAgICAgICBrc0ZhbGxiYWNrSW1hZ2UgW2ZhbGxiYWNrSW1nXT1cInJpZ2h0UHJldmlldy5wbGFpbj8uZmFsbGJhY2tJbWcgPyByaWdodFByZXZpZXcucGxhaW4/LmZhbGxiYWNrSW1nIDogcmlnaHRQcmV2aWV3Lm1vZGFsLmZhbGxiYWNrSW1nXCJcbiAgICAgICAgICAgICBbaGlkZGVuXT1cImxvYWRpbmdcIlxuICAgICAgICAgICAgIGtzU2l6ZSBbc2l6ZUNvbmZpZ109XCJ7d2lkdGg6IHNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNpemUud2lkdGgsIGhlaWdodDogc2xpZGVDb25maWc/LnNpZGVQcmV2aWV3cz8uc2l6ZS5oZWlnaHR9XCJcbiAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cInJpZ2h0UHJldmlldy5tb2RhbC5hcmlhTGFiZWxcIlxuICAgICAgICAgICAgIFt0aXRsZV09XCIocmlnaHRQcmV2aWV3Lm1vZGFsLnRpdGxlIHx8IHJpZ2h0UHJldmlldy5tb2RhbC50aXRsZSA9PT0gJycpID8gcmlnaHRQcmV2aWV3Lm1vZGFsLnRpdGxlIDogZ2V0RGVzY3JpcHRpb25Ub0Rpc3BsYXkocmlnaHRQcmV2aWV3KVwiXG4gICAgICAgICAgICAgYWx0PVwie3tyaWdodFByZXZpZXcubW9kYWwuYWx0ID8gcmlnaHRQcmV2aWV3Lm1vZGFsLmFsdCA6IGdldEFsdERlc2NyaXB0aW9uQnlJbWFnZShyaWdodFByZXZpZXcpfX1cIlxuICAgICAgICAgICAgIFt0YWJJbmRleF09XCIwXCIgcm9sZT1cImltZ1wiXG4gICAgICAgICAgICAgKGNsaWNrKT1cIm9uTmF2aWdhdGlvbkV2ZW50KCdyaWdodCcsICRldmVudCwgY2xpY2tBY3Rpb24pXCIgKGtleXVwKT1cIm9uTmF2aWdhdGlvbkV2ZW50KCdyaWdodCcsICRldmVudCwga2V5Ym9hcmRBY3Rpb24pXCIvPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2xhc3RJbWFnZT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3VycmVudC1pbWFnZS1uZXh0IGhpZGRlblwiXG4gICAgICAgICAgICAgICBrc1NpemUgW3NpemVDb25maWddPVwie3dpZHRoOiBzbGlkZUNvbmZpZz8uc2lkZVByZXZpZXdzPy5zaXplLndpZHRoLCBoZWlnaHQ6IHNsaWRlQ29uZmlnPy5zaWRlUHJldmlld3M/LnNpemUuaGVpZ2h0fVwiPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibG9hZGluZyAmJiBjdXJyZW50SW1hZ2VDb25maWc/LmxvYWRpbmdDb25maWc/LmVuYWJsZVwiPlxuICAgICAgPGtzLWxvYWRpbmctc3Bpbm5lciBbbG9hZGluZ0NvbmZpZ109XCJjdXJyZW50SW1hZ2VDb25maWc/LmxvYWRpbmdDb25maWdcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbYWNjZXNzaWJpbGl0eUNvbmZpZ109XCJhY2Nlc3NpYmlsaXR5Q29uZmlnXCI+PC9rcy1sb2FkaW5nLXNwaW5uZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8YSBjbGFzcz1cIm5hdi1yaWdodCB7e2lzRmlyc3RJbWFnZSA/ICduby1wb2ludGVyJyA6ICcnfX1cIlxuICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYWNjZXNzaWJpbGl0eUNvbmZpZz8ubWFpbk5leHRJbWFnZUFyaWFMYWJlbFwiXG4gICAgICAgW3RhYkluZGV4XT1cImlzTGFzdEltYWdlID8gLTEgOiAwXCIgcm9sZT1cImJ1dHRvblwiXG4gICAgICAgKGNsaWNrKT1cIm9uTmF2aWdhdGlvbkV2ZW50KCdyaWdodCcsICRldmVudClcIiAoa2V5dXApPVwib25OYXZpZ2F0aW9uRXZlbnQoJ3JpZ2h0JywgJGV2ZW50KVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImluc2lkZSB7e2lzTGFzdEltYWdlID8gJ2VtcHR5LWFycm93LWltYWdlJyA6ICdyaWdodC1hcnJvdy1pbWFnZSd9fVwiXG4gICAgICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgICAgIFt0aXRsZV09XCJpc0xhc3RJbWFnZSA/ICcnIDogYWNjZXNzaWJpbGl0eUNvbmZpZz8ubWFpbk5leHRJbWFnZVRpdGxlXCI+PC9kaXY+XG4gICAgPC9hPlxuICA8L2Rpdj5cbjwvbWFpbj5cbiJdfQ==